Merge branch 'dev'

This commit is contained in:
Branimir Karadžić 2015-01-31 19:10:48 -08:00
commit ac7f301c0c
6 changed files with 731 additions and 489 deletions

View file

@ -1,4 +1,4 @@
// ImGui library v1.30 wip
// ImGui library v1.30
// See ImGui::ShowTestWindow() for sample code.
// Read 'Programmer guide' below for notes on how to setup ImGui in your codebase.
// Get latest version at https://github.com/ocornut/imgui
@ -95,7 +95,7 @@
// TODO: store your texture pointer/identifier in 'io.Fonts->TexID'
// Application main loop
while (true)
for (;;)
{
// 1) get low-level input
// e.g. on Win32, GetKeyboardState(), or poll your events, etc.
@ -128,6 +128,7 @@
Occasionally introducing changes that are breaking the API. The breakage are generally minor and easy to fix.
Here is a change-log of API breaking changes, if you are using one of the functions listed, expect to have to fix some code.
- 2015/01/19 (1.30) - renamed ImGuiStorage::GetIntPtr()/GetFloatPtr() to GetIntRef()/GetIntRef() because Ptr was conflicting with actual pointer storage functions.
- 2015/01/11 (1.30) - big font/image API change! now loads TTF file. allow for multiple fonts. no need for a PNG loader.
(1.30) - removed GetDefaultFontData(). uses io.Fonts->GetTextureData*() API to retrieve uncompressed pixels.
this sequence:
@ -233,6 +234,7 @@
==================
- misc: merge or clarify ImVec4 / ImGuiAabb, they are essentially duplicate containers
!- i/o: avoid requesting mouse capture if button held and initial click was out of reach for imgui
- window: add horizontal scroll
- window: fix resize grip rendering scaling along with Rounding style setting
- window: autofit feedback loop when user relies on any dynamic layout (window width multiplier, column). maybe just clearly drop manual autofit?
@ -362,7 +364,7 @@ namespace IMGUI_STB_NAMESPACE
#define STBRP_STATIC
#define STB_RECT_PACK_IMPLEMENTATION
#endif
#include <stb/stb_rect_pack.h>
#include "stb_rect_pack.h"
#define STBTT_malloc(x,u) ((void)(u), ImGui::MemAlloc(x))
#define STBTT_free(x,u) ((void)(u), ImGui::MemFree(x))
@ -371,11 +373,11 @@ namespace IMGUI_STB_NAMESPACE
#define STBTT_STATIC
#define STB_TRUETYPE_IMPLEMENTATION
#endif
#include <stb/stb_truetype.h>
#include "stb_truetype.h"
#define STB_TEXTEDIT_STRING ImGuiTextEditState
#define STB_TEXTEDIT_CHARTYPE ImWchar
#include <stb/stb_textedit.h>
#include "stb_textedit.h"
#ifdef __clang__
#pragma clang diagnostic pop
@ -425,11 +427,6 @@ static ImU32 ImCrc32(const void* data, size_t data_size, ImU32 seed);
static bool ImLoadFileToMemory(const char* filename, const char* file_open_mode, void** out_file_data, size_t* out_file_size, size_t padding_bytes = 0);
static int ImUpperPowerOfTwo(int v) { v--; v |= v >> 1; v |= v >> 2; v |= v >> 4; v |= v >> 8; v |= v >> 16; v++; return v; }
// Helpers: Color Conversion
static ImU32 ImConvertColorFloat4ToU32(const ImVec4& in);
static void ImConvertColorRGBtoHSV(float r, float g, float b, float& out_h, float& out_s, float& out_v);
static void ImConvertColorHSVtoRGB(float h, float s, float v, float& out_r, float& out_g, float& out_b);
// Helpers: UTF-8 <> wchar
static int ImTextCharToUtf8(char* buf, size_t buf_size, unsigned int in_char); // return output UTF-8 bytes count
static ptrdiff_t ImTextStrToUtf8(char* buf, size_t buf_size, const ImWchar* in_text, const ImWchar* in_text_end); // return output UTF-8 bytes count
@ -445,6 +442,17 @@ static int ImTextCountUtf8BytesFromWchar(const ImWchar* in_text, const
static const char* GetClipboardTextFn_DefaultImpl();
static void SetClipboardTextFn_DefaultImpl(const char* text);
//-----------------------------------------------------------------------------
// Texture Atlas data
//-----------------------------------------------------------------------------
// Technically we should use the rect pack API for that, but it's just simpler to hard-core the positions for now.
// As we start using more of the texture atlas (for rounded corners) we can change that.
static const ImVec2 TEX_ATLAS_SIZE(32, 32);
static const ImVec2 TEX_ATLAS_POS_MOUSE_CURSOR_BLACK(1, 3);
static const ImVec2 TEX_ATLAS_POS_MOUSE_CURSOR_WHITE(14, 3);
static const ImVec2 TEX_ATLAS_SIZE_MOUSE_CURSOR(12, 19);
//-----------------------------------------------------------------------------
// User facing structures
//-----------------------------------------------------------------------------
@ -512,7 +520,9 @@ static ImFontAtlas GDefaultFontAtlas;
ImGuiIO::ImGuiIO()
{
// Most fields are initialized with zero
memset(this, 0, sizeof(*this));
DisplaySize = ImVec2(-1.0f, -1.0f);
DeltaTime = 1.0f/60.0f;
IniSavingRate = 5.0f;
@ -520,7 +530,6 @@ ImGuiIO::ImGuiIO()
LogFilename = "imgui_log.txt";
Fonts = &GDefaultFontAtlas;
FontGlobalScale = 1.0f;
FontAllowUserScaling = false;
MousePos = ImVec2(-1,-1);
MousePosPrev = ImVec2(-1,-1);
MouseDoubleClickTime = 0.30f;
@ -700,7 +709,7 @@ static size_t ImFormatStringV(char* buf, size_t buf_size, const char* fmt, va_li
return (w == -1) ? buf_size : (size_t)w;
}
static ImU32 ImConvertColorFloat4ToU32(const ImVec4& in)
ImU32 ImGui::ColorConvertFloat4ToU32(const ImVec4& in)
{
ImU32 out = ((ImU32)(ImSaturate(in.x)*255.f));
out |= ((ImU32)(ImSaturate(in.y)*255.f) << 8);
@ -711,7 +720,7 @@ static ImU32 ImConvertColorFloat4ToU32(const ImVec4& in)
// Convert rgb floats ([0-1],[0-1],[0-1]) to hsv floats ([0-1],[0-1],[0-1]), from Foley & van Dam p592
// Optimized http://lolengine.net/blog/2013/01/13/fast-rgb-to-hsv
static void ImConvertColorRGBtoHSV(float r, float g, float b, float& out_h, float& out_s, float& out_v)
void ImGui::ColorConvertRGBtoHSV(float r, float g, float b, float& out_h, float& out_s, float& out_v)
{
float K = 0.f;
if (g < b)
@ -733,7 +742,7 @@ static void ImConvertColorRGBtoHSV(float r, float g, float b, float& out_h, floa
// Convert hsv floats ([0-1],[0-1],[0-1]) to rgb floats ([0-1],[0-1],[0-1]), from Foley & van Dam p593
// also http://en.wikipedia.org/wiki/HSL_and_HSV
static void ImConvertColorHSVtoRGB(float h, float s, float v, float& out_r, float& out_g, float& out_b)
void ImGui::ColorConvertHSVtoRGB(float h, float s, float v, float& out_r, float& out_g, float& out_b)
{
if (s == 0.0f)
{
@ -1084,8 +1093,8 @@ public:
float TitleBarHeight() const { return (Flags & ImGuiWindowFlags_NoTitleBar) ? 0 : FontSize() + GImGui.Style.FramePadding.y * 2.0f; }
ImGuiAabb TitleBarAabb() const { return ImGuiAabb(Pos, Pos + ImVec2(SizeFull.x, TitleBarHeight())); }
ImVec2 WindowPadding() const { return ((Flags & ImGuiWindowFlags_ChildWindow) && !(Flags & ImGuiWindowFlags_ShowBorders)) ? ImVec2(1,1) : GImGui.Style.WindowPadding; }
ImU32 Color(ImGuiCol idx, float a=1.f) const { ImVec4 c = GImGui.Style.Colors[idx]; c.w *= GImGui.Style.Alpha * a; return ImConvertColorFloat4ToU32(c); }
ImU32 Color(const ImVec4& col) const { ImVec4 c = col; c.w *= GImGui.Style.Alpha; return ImConvertColorFloat4ToU32(c); }
ImU32 Color(ImGuiCol idx, float a=1.f) const { ImVec4 c = GImGui.Style.Colors[idx]; c.w *= GImGui.Style.Alpha * a; return ImGui::ColorConvertFloat4ToU32(c); }
ImU32 Color(const ImVec4& col) const { ImVec4 c = col; c.w *= GImGui.Style.Alpha; return ImGui::ColorConvertFloat4ToU32(c); }
};
static ImGuiWindow* GetCurrentWindow()
@ -1095,6 +1104,11 @@ static ImGuiWindow* GetCurrentWindow()
return GImGui.CurrentWindow;
}
static void SetActiveId(ImGuiID id)
{
GImGui.ActiveId = id;
}
static void RegisterAliveId(const ImGuiID& id)
{
if (GImGui.ActiveId == id)
@ -1148,7 +1162,16 @@ float ImGuiStorage::GetFloat(ImU32 key, float default_val) const
return it->val_f;
}
int* ImGuiStorage::GetIntPtr(ImGuiID key, int default_val)
void* ImGuiStorage::GetVoidPtr(ImGuiID key) const
{
ImVector<Pair>::iterator it = LowerBound(const_cast<ImVector<ImGuiStorage::Pair>&>(Data), key);
if (it == Data.end() || it->key != key)
return NULL;
return it->val_p;
}
// References are only valid until a new value is added to the storage. Calling a Set***() function or a Get***Ref() function invalidates the pointer.
int* ImGuiStorage::GetIntRef(ImGuiID key, int default_val)
{
ImVector<Pair>::iterator it = LowerBound(Data, key);
if (it == Data.end() || it->key != key)
@ -1156,7 +1179,7 @@ int* ImGuiStorage::GetIntPtr(ImGuiID key, int default_val)
return &it->val_i;
}
float* ImGuiStorage::GetFloatPtr(ImGuiID key, float default_val)
float* ImGuiStorage::GetFloatRef(ImGuiID key, float default_val)
{
ImVector<Pair>::iterator it = LowerBound(Data, key);
if (it == Data.end() || it->key != key)
@ -1188,6 +1211,17 @@ void ImGuiStorage::SetFloat(ImU32 key, float val)
it->val_f = val;
}
void ImGuiStorage::SetVoidPtr(ImU32 key, void* val)
{
ImVector<Pair>::iterator it = LowerBound(Data, key);
if (it == Data.end() || it->key != key)
{
Data.insert(it, Pair(key, val));
return;
}
it->val_p = val;
}
void ImGuiStorage::SetAllInt(int v)
{
for (size_t i = 0; i < Data.size(); i++)
@ -1649,7 +1683,7 @@ void ImGui::NewFrame()
// Clear reference to active widget if the widget isn't alive anymore
g.HoveredId = 0;
if (!g.ActiveIdIsAlive && g.ActiveIdPreviousFrame == g.ActiveId && g.ActiveId != 0)
g.ActiveId = 0;
SetActiveId(0);
g.ActiveIdPreviousFrame = g.ActiveId;
g.ActiveIdIsAlive = false;
@ -1835,7 +1869,7 @@ void ImGui::Render()
// Select window for move/focus when we're done with all our widgets (we only consider non-childs windows here)
if (g.ActiveId == 0 && g.HoveredId == 0 && g.HoveredRootWindow != NULL && g.IO.MouseClicked[0])
g.ActiveId = g.HoveredRootWindow->GetID("#MOVE");
SetActiveId(g.HoveredRootWindow->GetID("#MOVE"));
// Sort the window list so that all child windows are after their parent
// We cannot do that on FocusWindow() because childs may not exist yet
@ -1885,6 +1919,21 @@ void ImGui::Render()
window->AddToRenderList();
}
if (g.IO.MouseDrawCursor)
{
const ImVec2 pos = g.IO.MousePos;
const ImVec2 size = TEX_ATLAS_SIZE_MOUSE_CURSOR;
const ImTextureID tex_id = g.IO.Fonts->TexID;
const ImVec2 tex_uv_scale(1.0f/g.IO.Fonts->TexWidth, 1.0f/g.IO.Fonts->TexHeight);
static ImDrawList draw_list;
draw_list.Clear();
draw_list.AddImage(tex_id, pos+ImVec2(1,0), pos+ImVec2(1,0) + size, TEX_ATLAS_POS_MOUSE_CURSOR_BLACK * tex_uv_scale, (TEX_ATLAS_POS_MOUSE_CURSOR_BLACK + size) * tex_uv_scale, 0x30000000); // Shadow
draw_list.AddImage(tex_id, pos+ImVec2(2,0), pos+ImVec2(2,0) + size, TEX_ATLAS_POS_MOUSE_CURSOR_BLACK * tex_uv_scale, (TEX_ATLAS_POS_MOUSE_CURSOR_BLACK + size) * tex_uv_scale, 0x30000000); // Shadow
draw_list.AddImage(tex_id, pos, pos + size, TEX_ATLAS_POS_MOUSE_CURSOR_BLACK * tex_uv_scale, (TEX_ATLAS_POS_MOUSE_CURSOR_BLACK + size) * tex_uv_scale, 0xFF000000); // Black border
draw_list.AddImage(tex_id, pos, pos + size, TEX_ATLAS_POS_MOUSE_CURSOR_WHITE * tex_uv_scale, (TEX_ATLAS_POS_MOUSE_CURSOR_WHITE + size) * tex_uv_scale, 0xFFFFFFFF); // White fill
g.RenderDrawLists.push_back(&draw_list);
}
// Render
if (!g.RenderDrawLists.empty())
g.IO.RenderDrawListsFn(&g.RenderDrawLists[0], (int)g.RenderDrawLists.size());
@ -2431,6 +2480,9 @@ bool ImGui::Begin(const char* name, bool* p_opened, ImVec2 size, float fill_alph
g.SetNextWindowCollapsedCond = 0;
}
// Find parent
ImGuiWindow* parent_window = (flags & ImGuiWindowFlags_ChildWindow) != 0 ? g.CurrentWindowStack[g.CurrentWindowStack.size()-2] : NULL;
// Find root (if we are a child window)
size_t root_idx = g.CurrentWindowStack.size() - 1;
while (root_idx > 0)
@ -2451,7 +2503,6 @@ bool ImGui::Begin(const char* name, bool* p_opened, ImVec2 size, float fill_alph
if (first_begin_of_the_frame)
{
window->DrawList->Clear();
window->DrawList->PushTextureID(g.Font->ContainerAtlas->TexID);
window->Visible = true;
// New windows appears in front
@ -2463,18 +2514,26 @@ bool ImGui::Begin(const char* name, bool* p_opened, ImVec2 size, float fill_alph
if (flags & ImGuiWindowFlags_ChildWindow)
{
ImGuiWindow* parent_window = g.CurrentWindowStack[g.CurrentWindowStack.size()-2];
parent_window->DC.ChildWindows.push_back(window);
window->Pos = window->PosFloat = parent_window->DC.CursorPos;
window->SizeFull = size;
}
}
// Outer clipping rectangle
if ((flags & ImGuiWindowFlags_ChildWindow) && !(flags & ImGuiWindowFlags_ComboBox))
PushClipRect(g.CurrentWindowStack[g.CurrentWindowStack.size()-2]->ClipRectStack.back());
else
PushClipRect(ImVec4(0.0f, 0.0f, g.IO.DisplaySize.x, g.IO.DisplaySize.y));
// Setup texture
window->DrawList->PushTextureID(g.Font->ContainerAtlas->TexID);
// Setup outer clipping rectangle
if ((flags & ImGuiWindowFlags_ChildWindow) && !(flags & ImGuiWindowFlags_ComboBox))
PushClipRect(parent_window->ClipRectStack.back());
else if (g.IO.DisplayVisibleMin.x != g.IO.DisplayVisibleMax.x && g.IO.DisplayVisibleMin.y != g.IO.DisplayVisibleMax.y)
PushClipRect(ImVec4(g.IO.DisplayVisibleMin.x, g.IO.DisplayVisibleMin.y, g.IO.DisplayVisibleMax.x, g.IO.DisplayVisibleMax.y));
else
PushClipRect(ImVec4(0.0f, 0.0f, g.IO.DisplaySize.x, g.IO.DisplaySize.y));
// Setup and draw window
if (first_begin_of_the_frame)
{
// Seed ID stack with our window pointer
window->IDStack.resize(0);
ImGui::PushID(window);
@ -2496,7 +2555,7 @@ bool ImGui::Begin(const char* name, bool* p_opened, ImVec2 size, float fill_alph
}
else
{
g.ActiveId = 0;
SetActiveId(0);
}
}
@ -2509,11 +2568,14 @@ bool ImGui::Begin(const char* name, bool* p_opened, ImVec2 size, float fill_alph
// Clamp into view
if (!(window->Flags & ImGuiWindowFlags_ChildWindow) && !(window->Flags & ImGuiWindowFlags_Tooltip))
{
// FIXME: Parameterize padding.
const ImVec2 pad = ImVec2(window->FontSize()*2.0f, window->FontSize()*2.0f); // FIXME: Parametrize of clarify this behavior.
if (g.IO.DisplaySize.x > 0.0f && g.IO.DisplaySize.y > 0.0f) // Ignore zero-sized display explicitly to avoid losing positions if a window manager reports zero-sized window when initializing or minimizing.
{
window->PosFloat = ImMax(window->PosFloat + window->Size, pad) - window->Size;
window->PosFloat = ImMin(window->PosFloat, ImVec2(g.IO.DisplaySize.x, g.IO.DisplaySize.y) - pad);
ImVec2 clip_min = pad;
ImVec2 clip_max = g.IO.DisplaySize - pad;
window->PosFloat = ImMax(window->PosFloat + window->Size, clip_min) - window->Size;
window->PosFloat = ImMin(window->PosFloat, clip_max);
}
window->SizeFull = ImMax(window->SizeFull, style.WindowMinSize);
}
@ -2761,22 +2823,6 @@ bool ImGui::Begin(const char* name, bool* p_opened, ImVec2 size, float fill_alph
PopClipRect();
}
}
else
{
// Short path when we do multiple Begin in the same frame.
window->DrawList->PushTextureID(g.Font->ContainerAtlas->TexID);
// Outer clipping rectangle
if ((flags & ImGuiWindowFlags_ChildWindow) && !(flags & ImGuiWindowFlags_ComboBox))
{
ImGuiWindow* parent_window = g.CurrentWindowStack[g.CurrentWindowStack.size()-2];
PushClipRect(parent_window->ClipRectStack.back());
}
else
{
PushClipRect(ImVec4(0.0f, 0.0f, g.IO.DisplaySize.x, g.IO.DisplaySize.y));
}
}
// Inner clipping rectangle
// We set this up after processing the resize grip so that our clip rectangle doesn't lag by a frame
@ -3522,7 +3568,7 @@ static bool ButtonBehaviour(const ImGuiAabb& bb, const ImGuiID& id, bool* out_ho
{
if (g.IO.MouseClicked[0])
{
g.ActiveId = id;
SetActiveId(id);
FocusWindow(window);
}
else if (repeat && g.ActiveId && ImGui::IsMouseClicked(0, true))
@ -3543,7 +3589,7 @@ static bool ButtonBehaviour(const ImGuiAabb& bb, const ImGuiID& id, bool* out_ho
{
if (hovered)
pressed = true;
g.ActiveId = 0;
SetActiveId(0);
}
}
@ -3630,7 +3676,7 @@ bool ImGui::InvisibleButton(const char* str_id, const ImVec2& size)
if (!ItemAdd(bb, &id))
return false;
bool hovered, held;
bool hovered, held;
bool pressed = ButtonBehaviour(bb, id, &hovered, &held, true);
return pressed;
@ -3666,30 +3712,70 @@ static bool CloseWindowButton(bool* p_opened)
return pressed;
}
void ImGui::Image(ImTextureID user_texture_id, const ImVec2& size, const ImVec2& uv0, const ImVec2& uv1, ImU32 tint_col, ImU32 border_col)
void ImGui::Image(ImTextureID user_texture_id, const ImVec2& size, const ImVec2& uv0, const ImVec2& uv1, const ImVec4& tint_col, const ImVec4& border_col)
{
ImGuiWindow* window = GetCurrentWindow();
if (window->SkipItems)
return;
ImGuiAabb bb(window->DC.CursorPos, window->DC.CursorPos + size);
if (border_col != 0)
if (border_col.w > 0.0f)
bb.Max += ImVec2(2,2);
ItemSize(bb.GetSize(), &bb.Min);
ItemSize(bb);
if (!ItemAdd(bb, NULL))
return;
if (border_col != 0)
if (border_col.w > 0.0f)
{
window->DrawList->AddRect(bb.Min, bb.Max, border_col, 0.0f);
window->DrawList->AddImage(user_texture_id, bb.Min+ImVec2(1,1), bb.Max-ImVec2(1,1), uv0, uv1, tint_col);
window->DrawList->AddRect(bb.Min, bb.Max, window->Color(border_col), 0.0f);
window->DrawList->AddImage(user_texture_id, bb.Min+ImVec2(1,1), bb.Max-ImVec2(1,1), uv0, uv1, window->Color(tint_col));
}
else
{
window->DrawList->AddImage(user_texture_id, bb.Min, bb.Max, uv0, uv1, tint_col);
window->DrawList->AddImage(user_texture_id, bb.Min, bb.Max, uv0, uv1, window->Color(tint_col));
}
}
// frame_padding < 0: uses FramePadding from style (default)
// frame_padding = 0: no framing
// frame_padding > 0: set framing size
// The color used are the button colors.
bool ImGui::ImageButton(ImTextureID user_texture_id, const ImVec2& size, const ImVec2& uv0, const ImVec2& uv1, int frame_padding, const ImVec4& bg_col)
{
ImGuiState& g = GImGui;
ImGuiWindow* window = GetCurrentWindow();
if (window->SkipItems)
return false;
const ImGuiStyle& style = g.Style;
// Default to using texture ID as ID. User can still push string/integer prefixes.
// We could hash the size/uv to create a unique ID but that would prevent the user from animating buttons.
ImGui::PushID((void *)user_texture_id);
const ImGuiID id = window->GetID("#image");
ImGui::PopID();
const ImVec2 padding = (frame_padding >= 0) ? ImVec2((float)frame_padding, (float)frame_padding) : style.FramePadding;
const ImGuiAabb bb(window->DC.CursorPos, window->DC.CursorPos + size + padding*2);
const ImGuiAabb image_bb(window->DC.CursorPos + padding, window->DC.CursorPos + padding + size);
ItemSize(bb);
if (!ItemAdd(bb, &id))
return false;
bool hovered, held;
bool pressed = ButtonBehaviour(bb, id, &hovered, &held, true);
// Render
const ImU32 col = window->Color((hovered && held) ? ImGuiCol_ButtonActive : hovered ? ImGuiCol_ButtonHovered : ImGuiCol_Button);
if (padding.x > 0.0f || padding.y > 0.0f)
RenderFrame(bb.Min, bb.Max, col);
if (bg_col.w > 0.0f)
window->DrawList->AddRectFilled(image_bb.Min, image_bb.Max, window->Color(bg_col));
window->DrawList->AddImage(user_texture_id, image_bb.Min, image_bb.Max, uv0, uv1);
return pressed;
}
// Start logging ImGui output to TTY
void ImGui::LogToTTY(int max_depth)
{
@ -4159,7 +4245,7 @@ bool ImGui::SliderFloat(const char* label, float* v, float v_min, float v_max, c
bool start_text_input = false;
if (tab_focus_requested || (hovered && g.IO.MouseClicked[0]))
{
g.ActiveId = id;
SetActiveId(id);
FocusWindow(window);
const bool is_ctrl_down = g.IO.KeyCtrl;
@ -4177,7 +4263,7 @@ bool ImGui::SliderFloat(const char* label, float* v, float v_min, float v_max, c
char text_buf[64];
ImFormatString(text_buf, IM_ARRAYSIZE(text_buf), "%.*f", decimal_precision, *v);
g.ActiveId = g.SliderAsInputTextId;
SetActiveId(g.SliderAsInputTextId);
g.HoveredId = 0;
window->FocusItemUnregister(); // Our replacement slider will override the focus ID (registered previously to allow for a TAB focus to happen)
value_changed = ImGui::InputText(label, text_buf, IM_ARRAYSIZE(text_buf), ImGuiInputTextFlags_CharsDecimal | ImGuiInputTextFlags_AutoSelectAll);
@ -4186,15 +4272,18 @@ bool ImGui::SliderFloat(const char* label, float* v, float v_min, float v_max, c
// First frame
IM_ASSERT(g.ActiveId == id); // InputText ID should match the Slider ID (else we'd need to store them both which is also possible)
g.SliderAsInputTextId = g.ActiveId;
g.ActiveId = id;
SetActiveId(id);
g.HoveredId = id;
}
else
{
if (g.ActiveId == g.SliderAsInputTextId)
g.ActiveId = id;
SetActiveId(id);
else
g.ActiveId = g.SliderAsInputTextId = 0;
{
SetActiveId(0);
g.SliderAsInputTextId = 0;
}
}
if (value_changed)
{
@ -4258,7 +4347,7 @@ bool ImGui::SliderFloat(const char* label, float* v, float v_min, float v_max, c
}
else
{
g.ActiveId = 0;
SetActiveId(0);
}
}
@ -4740,7 +4829,7 @@ namespace IMGUI_STB_NAMESPACE
{
#endif
#define STB_TEXTEDIT_IMPLEMENTATION
#include <stb/stb_textedit.h>
#include "stb_textedit.h"
#ifdef IMGUI_STB_NAMESPACE
}
#endif
@ -4999,7 +5088,7 @@ bool ImGui::InputText(const char* label, char* buf, size_t buf_size, ImGuiInputT
if (tab_focus_requested || is_ctrl_down)
select_all = true;
}
g.ActiveId = id;
SetActiveId(id);
FocusWindow(window);
}
else if (io.MouseClicked[0])
@ -5007,7 +5096,7 @@ bool ImGui::InputText(const char* label, char* buf, size_t buf_size, ImGuiInputT
// Release focus when we click outside
if (g.ActiveId == id)
{
g.ActiveId = 0;
SetActiveId(0);
}
}
@ -5045,6 +5134,25 @@ bool ImGui::InputText(const char* label, char* buf, size_t buf_size, ImGuiInputT
if (edit_state.SelectedAllMouseLock && !io.MouseDown[0])
edit_state.SelectedAllMouseLock = false;
if (g.IO.InputCharacters[0])
{
// Process text input (before we check for Return because using some IME will effectively send a Return?)
for (int n = 0; n < IM_ARRAYSIZE(g.IO.InputCharacters) && g.IO.InputCharacters[n]; n++)
{
const ImWchar c = g.IO.InputCharacters[n];
if (c)
{
// Insert character if they pass filtering
if (InputTextFilterCharacter(c, flags))
continue;
edit_state.OnKeyPressed(c);
}
}
// Consume characters
memset(g.IO.InputCharacters, 0, sizeof(g.IO.InputCharacters));
}
const int k_mask = (is_shift_down ? STB_TEXTEDIT_K_SHIFT : 0);
if (IsKeyPressedMap(ImGuiKey_LeftArrow)) { edit_state.OnKeyPressed(is_ctrl_down ? STB_TEXTEDIT_K_WORDLEFT | k_mask : STB_TEXTEDIT_K_LEFT | k_mask); }
else if (IsKeyPressedMap(ImGuiKey_RightArrow)) { edit_state.OnKeyPressed(is_ctrl_down ? STB_TEXTEDIT_K_WORDRIGHT | k_mask : STB_TEXTEDIT_K_RIGHT | k_mask); }
@ -5052,8 +5160,8 @@ bool ImGui::InputText(const char* label, char* buf, size_t buf_size, ImGuiInputT
else if (IsKeyPressedMap(ImGuiKey_End)) { edit_state.OnKeyPressed(is_ctrl_down ? STB_TEXTEDIT_K_TEXTEND | k_mask : STB_TEXTEDIT_K_LINEEND | k_mask); }
else if (IsKeyPressedMap(ImGuiKey_Delete)) { edit_state.OnKeyPressed(STB_TEXTEDIT_K_DELETE | k_mask); }
else if (IsKeyPressedMap(ImGuiKey_Backspace)) { edit_state.OnKeyPressed(STB_TEXTEDIT_K_BACKSPACE | k_mask); }
else if (IsKeyPressedMap(ImGuiKey_Enter)) { g.ActiveId = 0; enter_pressed = true; }
else if (IsKeyPressedMap(ImGuiKey_Escape)) { g.ActiveId = 0; cancel_edit = true; }
else if (IsKeyPressedMap(ImGuiKey_Enter)) { SetActiveId(0); enter_pressed = true; }
else if (IsKeyPressedMap(ImGuiKey_Escape)) { SetActiveId(0); cancel_edit = true; }
else if (is_ctrl_down && IsKeyPressedMap(ImGuiKey_Z)) { edit_state.OnKeyPressed(STB_TEXTEDIT_K_UNDO); }
else if (is_ctrl_down && IsKeyPressedMap(ImGuiKey_Y)) { edit_state.OnKeyPressed(STB_TEXTEDIT_K_REDO); }
else if (is_ctrl_down && IsKeyPressedMap(ImGuiKey_A)) { edit_state.SelectAll(); }
@ -5106,24 +5214,6 @@ bool ImGui::InputText(const char* label, char* buf, size_t buf_size, ImGuiInputT
}
}
}
else if (g.IO.InputCharacters[0])
{
// Text input
for (int n = 0; n < IM_ARRAYSIZE(g.IO.InputCharacters) && g.IO.InputCharacters[n]; n++)
{
const ImWchar c = g.IO.InputCharacters[n];
if (c)
{
// Insert character if they pass filtering
if (InputTextFilterCharacter(c, flags))
continue;
edit_state.OnKeyPressed(c);
}
}
// Consume characters
memset(g.IO.InputCharacters, 0, sizeof(g.IO.InputCharacters));
}
edit_state.CursorAnim += g.IO.DeltaTime;
edit_state.UpdateScrollOffset();
@ -5442,7 +5532,7 @@ bool ImGui::Combo(const char* label, int* current_item, bool (*items_getter)(voi
}
if (item_pressed)
{
g.ActiveId = 0;
SetActiveId(0);
g.ActiveComboID = 0;
value_changed = true;
*current_item = item_idx;
@ -5533,7 +5623,7 @@ bool ImGui::ColorEdit4(const char* label, float col[4], bool alpha)
const ImVec4 col_display(fx, fy, fz, 1.0f);
if (edit_mode == ImGuiColorEditMode_HSV)
ImConvertColorRGBtoHSV(fx, fy, fz, fx, fy, fz);
ImGui::ColorConvertRGBtoHSV(fx, fy, fz, fx, fy, fz);
int ix = (int)(fx * 255.0f + 0.5f);
int iy = (int)(fy * 255.0f + 0.5f);
@ -5635,7 +5725,7 @@ bool ImGui::ColorEdit4(const char* label, float col[4], bool alpha)
fz = iz / 255.0f;
fw = iw / 255.0f;
if (edit_mode == 1)
ImConvertColorHSVtoRGB(fx, fy, fz, fx, fy, fz);
ImGui::ColorConvertHSVtoRGB(fx, fy, fz, fx, fy, fz);
if (value_changed)
{
@ -5693,7 +5783,7 @@ void ImGui::Spacing()
}
// Advance cursor given item size.
static void ItemSize(ImVec2 size, ImVec2* adjust_start_offset)
static void ItemSize(ImVec2 size, ImVec2* adjust_vertical_offset)
{
ImGuiState& g = GImGui;
ImGuiWindow* window = GetCurrentWindow();
@ -5701,8 +5791,8 @@ static void ItemSize(ImVec2 size, ImVec2* adjust_start_offset)
return;
const float line_height = ImMax(window->DC.CurrentLineHeight, size.y);
if (adjust_start_offset)
adjust_start_offset->y = adjust_start_offset->y + (line_height - size.y) * 0.5f;
if (adjust_vertical_offset)
adjust_vertical_offset->y = adjust_vertical_offset->y + (line_height - size.y) * 0.5f;
// Always align ourselves on pixel boundaries
window->DC.CursorPosPrevLine = ImVec2(window->DC.CursorPos.x + size.x, window->DC.CursorPos.y);
@ -6021,68 +6111,84 @@ void ImDrawList::Clear()
texture_id_stack.resize(0);
}
void ImDrawList::SetClipRect(const ImVec4& clip_rect)
void ImDrawList::AddDrawCmd()
{
ImDrawCmd draw_cmd;
draw_cmd.vtx_count = 0;
draw_cmd.clip_rect = clip_rect_stack.empty() ? GNullClipRect : clip_rect_stack.back();
draw_cmd.texture_id = texture_id_stack.empty() ? NULL : texture_id_stack.back();
draw_cmd.user_callback = NULL;
draw_cmd.user_callback_data = NULL;
commands.push_back(draw_cmd);
}
void ImDrawList::AddCallback(ImDrawCallback callback, void* callback_data)
{
ImDrawCmd* current_cmd = commands.empty() ? NULL : &commands.back();
if (current_cmd && current_cmd->vtx_count == 0)
if (!current_cmd || current_cmd->vtx_count != 0 || current_cmd->user_callback != NULL)
{
// Reuse existing command (high-level clipping may have discarded vertices submitted earlier)
// FIXME-OPT: Possibly even reuse previous command.
current_cmd->clip_rect = clip_rect;
AddDrawCmd();
current_cmd = &commands.back();
}
current_cmd->user_callback = callback;
current_cmd->user_callback_data = callback_data;
// Force a new command after us
// We function this way so that the most common calls (AddLine, AddRect..) always have a command to add to without doing any check.
AddDrawCmd();
}
void ImDrawList::UpdateClipRect()
{
ImDrawCmd* current_cmd = commands.empty() ? NULL : &commands.back();
if (!current_cmd || (current_cmd->vtx_count != 0) || current_cmd->user_callback != NULL)
{
AddDrawCmd();
}
else
{
ImDrawCmd draw_cmd;
draw_cmd.vtx_count = 0;
draw_cmd.clip_rect = clip_rect;
draw_cmd.texture_id = texture_id_stack.back();
commands.push_back(draw_cmd);
current_cmd->clip_rect = clip_rect_stack.empty() ? GNullClipRect : clip_rect_stack.back();
}
}
void ImDrawList::PushClipRect(const ImVec4& clip_rect)
{
SetClipRect(clip_rect);
clip_rect_stack.push_back(clip_rect);
UpdateClipRect();
}
void ImDrawList::PopClipRect()
{
IM_ASSERT(clip_rect_stack.size() > 0);
clip_rect_stack.pop_back();
const ImVec4 clip_rect = clip_rect_stack.empty() ? GNullClipRect : clip_rect_stack.back();
SetClipRect(clip_rect);
UpdateClipRect();
}
void ImDrawList::SetTextureID(const ImTextureID& texture_id)
void ImDrawList::UpdateTextureID()
{
ImDrawCmd* current_cmd = commands.empty() ? NULL : &commands.back();
if (current_cmd && (current_cmd->vtx_count == 0 || current_cmd->texture_id == texture_id))
const ImTextureID texture_id = texture_id_stack.empty() ? NULL : texture_id_stack.back();
if (!current_cmd || (current_cmd->vtx_count != 0 && current_cmd->texture_id != texture_id) || current_cmd->user_callback != NULL)
{
// Reuse existing command
// FIXME-OPT: Possibly even reuse previous command.
current_cmd->texture_id = texture_id;
AddDrawCmd();
}
else
{
ImDrawCmd draw_cmd;
draw_cmd.vtx_count = 0;
draw_cmd.clip_rect = clip_rect_stack.empty() ? GNullClipRect: clip_rect_stack.back();
draw_cmd.texture_id = texture_id;
commands.push_back(draw_cmd);
current_cmd->texture_id = texture_id;
}
}
void ImDrawList::PushTextureID(const ImTextureID& texture_id)
{
SetTextureID(texture_id);
texture_id_stack.push_back(texture_id);
UpdateTextureID();
}
void ImDrawList::PopTextureID()
{
IM_ASSERT(texture_id_stack.size() > 0);
texture_id_stack.pop_back();
const ImTextureID texture_id = texture_id_stack.empty() ? NULL : texture_id_stack.back();
SetTextureID(texture_id);
UpdateTextureID();
}
void ImDrawList::ReserveVertices(unsigned int vtx_count)
@ -6112,6 +6218,7 @@ void ImDrawList::AddVtxUV(const ImVec2& pos, ImU32 col, const ImVec2& uv)
vtx_write++;
}
// NB: memory should be reserved for 6 vertices by the caller.
void ImDrawList::AddVtxLine(const ImVec2& a, const ImVec2& b, ImU32 col)
{
const float length = sqrtf(ImLengthSqr(b - a));
@ -6335,7 +6442,7 @@ void ImDrawList::AddImage(ImTextureID user_texture_id, const ImVec2& a, const Im
if ((col >> 24) == 0)
return;
const bool push_texture_id = user_texture_id != texture_id_stack.back();
const bool push_texture_id = texture_id_stack.empty() || user_texture_id != texture_id_stack.back();
if (push_texture_id)
PushTextureID(user_texture_id);
@ -6571,8 +6678,8 @@ bool ImFontAtlas::Build()
// Pack our extra data rectangle first, so it will be on the upper-left corner of our texture (UV will have small values).
stbrp_rect extra_rect;
extra_rect.w = 16;
extra_rect.h = 16;
extra_rect.w = (int)TEX_ATLAS_SIZE.x;
extra_rect.h = (int)TEX_ATLAS_SIZE.y;
stbrp_pack_rects((stbrp_context*)spc.pack_info, &extra_rect, 1);
TexExtraDataPos = ImVec2(extra_rect.x, extra_rect.y);
@ -6582,6 +6689,7 @@ bool ImFontAtlas::Build()
stbrp_rect* buf_rects = (stbrp_rect*)ImGui::MemAlloc(total_glyph_count * sizeof(stbrp_rect));
stbtt_pack_range* buf_ranges = (stbtt_pack_range*)ImGui::MemAlloc(total_glyph_range_count * sizeof(stbtt_pack_range));
memset(buf_packedchars, 0, total_glyph_count * sizeof(stbtt_packedchar));
memset(buf_rects, 0, total_glyph_count * sizeof(stbrp_rect)); // Unnessary but let's clear this for the sake of sanity.
memset(buf_ranges, 0, total_glyph_range_count * sizeof(stbtt_pack_range));
// First pass: pack all glyphs (no rendering at this point, we are working with glyph sizes only)
@ -6696,11 +6804,51 @@ bool ImFontAtlas::Build()
buf_ranges = NULL;
ClearInputData();
// Render into our custom data block
RenderCustomTexData();
return true;
}
void ImFontAtlas::RenderCustomTexData()
{
IM_ASSERT(TexExtraDataPos.x == 0.0f && TexExtraDataPos.y == 0.0f);
// Draw white pixel into texture and make UV points to it
TexPixelsAlpha8[0] = TexPixelsAlpha8[1] = TexPixelsAlpha8[TexWidth+0] = TexPixelsAlpha8[TexWidth+1] = 0xFF;
TexUvWhitePixel = ImVec2((TexExtraDataPos.x + 0.5f) / TexWidth, (TexExtraDataPos.y + 0.5f) / TexHeight);
return true;
// Draw a mouse cursor into texture
// Because our font uses an alpha texture, we have to spread the cursor in 2 parts (black/white) which will be rendered separately.
const char cursor_pixels[] =
{
"X "
"XX "
"X.X "
"X..X "
"X...X "
"X....X "
"X.....X "
"X......X "
"X.......X "
"X........X "
"X.........X "
"X..........X"
"X......XXXXX"
"X...X..X "
"X..X X..X "
"X.X X..X "
"XX X..X "
" X..X "
" XX "
};
IM_ASSERT(sizeof(cursor_pixels)-1 == (int)TEX_ATLAS_SIZE_MOUSE_CURSOR.x * (int)TEX_ATLAS_SIZE_MOUSE_CURSOR.y);
for (int y = 0, n = 0; y < 19; y++)
for (int x = 0; x < 12; x++, n++)
{
TexPixelsAlpha8[((int)TEX_ATLAS_POS_MOUSE_CURSOR_BLACK.x + x) + ((int)TEX_ATLAS_POS_MOUSE_CURSOR_BLACK.y + y) * TexWidth] = (cursor_pixels[n] == 'X') ? 0xFF : 0x00;
TexPixelsAlpha8[((int)TEX_ATLAS_POS_MOUSE_CURSOR_WHITE.x + x) + ((int)TEX_ATLAS_POS_MOUSE_CURSOR_WHITE.y + y) * TexWidth] = (cursor_pixels[n] == '.') ? 0xFF : 0x00;
}
}
//-----------------------------------------------------------------------------
@ -7542,7 +7690,12 @@ void ImGui::ShowTestWindow(bool* opened)
static float fill_alpha = 0.65f;
const ImGuiWindowFlags layout_flags = (no_titlebar ? ImGuiWindowFlags_NoTitleBar : 0) | (no_border ? 0 : ImGuiWindowFlags_ShowBorders) | (no_resize ? ImGuiWindowFlags_NoResize : 0) | (no_move ? ImGuiWindowFlags_NoMove : 0) | (no_scrollbar ? ImGuiWindowFlags_NoScrollbar : 0);
ImGui::Begin("ImGui Test", opened, ImVec2(550,680), fill_alpha, layout_flags);
if (!ImGui::Begin("ImGui Test", opened, ImVec2(550,680), fill_alpha, layout_flags))
{
// Early out if the window is collapsed, as an optimization.
ImGui::End();
return;
}
ImGui::PushItemWidth(ImGui::GetWindowWidth() * 0.65f);
ImGui::Text("ImGui says hello.");
@ -7679,7 +7832,8 @@ void ImGui::ShowTestWindow(bool* opened)
// Most compiler appears to support UTF-8 in source code (with Visual Studio you need to save your file as 'UTF-8 without signature')
// However for the sake for maximum portability here we are *not* including raw UTF-8 character in this source file, instead we encode the string with hexadecimal constants.
// In your own application be reasonable and use UTF-8 in source or retrieve the data from file system!
ImGui::TextWrapped("CJK text will only appears if the font was loaded with the appropriate CJK character ranges. Call io.Font->LoadFromFileTTF() manually to specify extra character ranges. Note that characters values are preserved even if the font cannot be displayed, so you can safely copy & paste garbled characters into another application.");
// Note that characters values are preserved even if the font cannot be displayed, so you can safely copy & paste garbled characters into another application.
ImGui::TextWrapped("CJK text will only appears if the font was loaded with the appropriate CJK character ranges. Call io.Font->LoadFromFileTTF() manually to load extra character ranges.");
ImGui::Text("Hiragana: \xe3\x81\x8b\xe3\x81\x8d\xe3\x81\x8f\xe3\x81\x91\xe3\x81\x93 (kakikukeko)");
ImGui::Text("Kanjis: \xe6\x97\xa5\xe6\x9c\xac\xe8\xaa\x9e (nihongo)");
static char buf[32] = "\xe6\x97\xa5\xe6\x9c\xac\xe8\xaa\x9e";
@ -7694,7 +7848,7 @@ void ImGui::ShowTestWindow(bool* opened)
float tex_w = (float)ImGui::GetIO().Fonts->TexWidth;
float tex_h = (float)ImGui::GetIO().Fonts->TexHeight;
ImTextureID tex_id = ImGui::GetIO().Fonts->TexID;
ImGui::Image(tex_id, ImVec2(tex_w, tex_h), ImVec2(0,0), ImVec2(1,1), 0xFFFFFFFF, 0x999999FF);
ImGui::Image(tex_id, ImVec2(tex_w, tex_h), ImVec2(0,0), ImVec2(1,1), ImColor(255,255,255,255), ImColor(255,255,255,128));
if (ImGui::IsItemHovered())
{
ImGui::BeginTooltip();
@ -7705,9 +7859,22 @@ void ImGui::ShowTestWindow(bool* opened)
ImGui::Text("Max: (%.2f, %.2f)", focus_x + focus_sz, focus_y + focus_sz);
ImVec2 uv0 = ImVec2((focus_x) / tex_w, (focus_y) / tex_h);
ImVec2 uv1 = ImVec2((focus_x + focus_sz) / tex_w, (focus_y + focus_sz) / tex_h);
ImGui::Image(tex_id, ImVec2(128,128), uv0, uv1, 0xFFFFFFFF, 0x999999FF);
ImGui::Image(tex_id, ImVec2(128,128), uv0, uv1, ImColor(255,255,255,255), ImColor(255,255,255,128));
ImGui::EndTooltip();
}
ImGui::TextWrapped("And now some textured buttons..");
static int pressed_count = 0;
for (int i = 0; i < 8; i++)
{
if (i > 0)
ImGui::SameLine();
ImGui::PushID(i);
int frame_padding = -1 + i; // -1 padding uses default padding
if (ImGui::ImageButton(tex_id, ImVec2(32,32), ImVec2(0,0), ImVec2(32.0f/tex_w,32/tex_h), frame_padding))
pressed_count += 1;
ImGui::PopID();
}
ImGui::Text("Pressed %d times.", pressed_count);
ImGui::TreePop();
}
@ -7719,7 +7886,20 @@ void ImGui::ShowTestWindow(bool* opened)
ImGui::RadioButton("radio b", &e, 1); ImGui::SameLine();
ImGui::RadioButton("radio c", &e, 2);
ImGui::Text("Hover me");
// Color buttons, demonstrate using PushID() to add unique identifier in the ID stack, and changing style.
for (int i = 0; i < 7; i++)
{
if (i > 0) ImGui::SameLine();
ImGui::PushID(i);
ImGui::PushStyleColor(ImGuiCol_Button, ImColor::HSV(i/7.0f, 0.6f, 0.6f));
ImGui::PushStyleColor(ImGuiCol_ButtonHovered, ImColor::HSV(i/7.0f, 0.7f, 0.7f));
ImGui::PushStyleColor(ImGuiCol_ButtonActive, ImColor::HSV(i/7.0f, 0.8f, 0.8f));
ImGui::Button("Click");
ImGui::PopStyleColor(3);
ImGui::PopID();
}
ImGui::Text("Hover over me");
if (ImGui::IsItemHovered())
ImGui::SetTooltip("I am a tooltip");
@ -7891,10 +8071,11 @@ void ImGui::ShowTestWindow(bool* opened)
ImGui::Columns(2);
for (int i = 0; i < 100; i++)
{
if (i == 50)
ImGui::NextColumn();
char buf[32];
ImFormatString(buf, IM_ARRAYSIZE(buf), "%08x", i*5731);
ImGui::Button(buf);
ImGui::NextColumn();
}
ImGui::EndChild();
}
@ -8154,7 +8335,7 @@ static void ShowExampleAppCustomRendering(bool* opened)
// However you can draw directly and poll mouse/keyboard by yourself. You can manipulate the cursor using GetCursorPos() and SetCursorPos().
// If you only use the ImDrawList API, you can notify the owner window of its extends by using SetCursorPos(max) followed by an empty Text("") statement.
ImVec2 canvas_pos = ImGui::GetCursorScreenPos(); // ImDrawList API uses screen coordinates!
ImVec2 canvas_size = ImVec2(ImMin(50.0f,ImGui::GetWindowContentRegionMax().x-ImGui::GetCursorPos().x), ImMin(50.0f,ImGui::GetWindowContentRegionMax().y-ImGui::GetCursorPos().y)); // Resize canvas what's available
ImVec2 canvas_size = ImVec2(ImMax(50.0f,ImGui::GetWindowContentRegionMax().x-ImGui::GetCursorPos().x), ImMax(50.0f,ImGui::GetWindowContentRegionMax().y-ImGui::GetCursorPos().y)); // Resize canvas what's available
draw_list->AddRect(canvas_pos, ImVec2(canvas_pos.x + canvas_size.x, canvas_pos.y + canvas_size.y), 0xFFFFFFFF);
bool adding_preview = false;
ImGui::InvisibleButton("canvas", canvas_size);
@ -8583,7 +8764,7 @@ static unsigned int stb_decompress(unsigned char *output, unsigned char *i, unsi
i += 16;
stb__dout = output;
for (;;) {
while (1) {
unsigned char *old_i = i;
i = stb_decompress_token(i);
if (i == old_i) {

View file

@ -1,4 +1,4 @@
// ImGui library v1.30 wip
// ImGui library v1.30
// See .cpp file for commentary.
// See ImGui::ShowTestWindow() for sample code.
// Read 'Programmer guide' in .cpp for notes on how to setup ImGui in your codebase.
@ -6,6 +6,7 @@
#pragma once
struct ImDrawCmd;
struct ImDrawList;
struct ImFont;
struct ImFontAtlas;
@ -244,7 +245,8 @@ namespace ImGui
IMGUI_API bool Button(const char* label, const ImVec2& size = ImVec2(0,0), bool repeat_when_held = false);
IMGUI_API bool SmallButton(const char* label);
IMGUI_API bool InvisibleButton(const char* str_id, const ImVec2& size);
IMGUI_API void Image(ImTextureID user_texture_id, const ImVec2& size, const ImVec2& uv0 = ImVec2(0,0), const ImVec2& uv1 = ImVec2(1,1), ImU32 tint_col = 0xFFFFFFFF, ImU32 border_col = 0x00000000);
IMGUI_API void Image(ImTextureID user_texture_id, const ImVec2& size, const ImVec2& uv0 = ImVec2(0,0), const ImVec2& uv1 = ImVec2(1,1), const ImVec4& tint_col = ImVec4(1,1,1,1), const ImVec4& border_col = ImVec4(0,0,0,0));
IMGUI_API bool ImageButton(ImTextureID user_texture_id, const ImVec2& size, const ImVec2& uv0 = ImVec2(0,0), const ImVec2& uv1 = ImVec2(1,1), int frame_padding = -1, const ImVec4& bg_col = ImVec4(0,0,0,1)); // <0 frame_padding uses default frame padding settings. 0 for no paddnig.
IMGUI_API bool CollapsingHeader(const char* label, const char* str_id = NULL, const bool display_frame = true, const bool default_open = false);
IMGUI_API bool SliderFloat(const char* label, float* v, float v_min, float v_max, const char* display_format = "%.3f", float power = 1.0f); // adjust display_format to decorate the value with a prefix or a suffix. Use power!=1.0 for logarithmic sliders.
IMGUI_API bool SliderFloat2(const char* label, float v[2], float v_min, float v_max, const char* display_format = "%.3f", float power = 1.0f);
@ -321,6 +323,10 @@ namespace ImGui
IMGUI_API const char* GetStyleColName(ImGuiCol idx);
IMGUI_API ImVec2 CalcTextSize(const char* text, const char* text_end = NULL, bool hide_text_after_double_hash = false, float wrap_width = -1.0f);
IMGUI_API ImU32 ColorConvertFloat4ToU32(const ImVec4& in);
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);
// Obsolete (will be removed)
IMGUI_API void GetDefaultFontData(const void** fnt_data, unsigned int* fnt_size, const void** png_data, unsigned int* png_size);
@ -501,6 +507,8 @@ struct ImGuiIO
ImFontAtlas* Fonts; // <auto> // Load and assemble one or more fonts into a single tightly packed texture. Output to Fonts array.
float FontGlobalScale; // = 1.0f // Global scale all fonts
bool FontAllowUserScaling; // = false // Allow user scaling text of individual window with CTRL+Wheel.
ImVec2 DisplayVisibleMin; // <unset> (0.0f,0.0f) // If you use DisplaySize as a virtual space larger than your screen, set DisplayVisibleMin/Max to the visible area.
ImVec2 DisplayVisibleMax; // <unset> (0.0f,0.0f) // If the values are the same, we defaults to Min=(0.0f) and Max=DisplaySize
//------------------------------------------------------------------
// User Functions
@ -530,6 +538,7 @@ struct ImGuiIO
ImVec2 MousePos; // Mouse position, in pixels (set to -1,-1 if no mouse / on another screen, etc.)
bool MouseDown[5]; // Mouse buttons. ImGui itself only uses button 0 (left button) but you can use others as storage for convenience.
float MouseWheel; // Mouse wheel: 1 unit scrolls about 5 lines text.
bool MouseDrawCursor; // Request ImGui to draw a mouse cursor for you (if you are on a platform without a mouse cursor).
bool KeyCtrl; // Keyboard modifier pressed: Control
bool KeyShift; // Keyboard modifier pressed: Shift
bool KeysDown[512]; // Keyboard keys that are pressed (in whatever order user naturally has access to keyboard data)
@ -641,26 +650,34 @@ struct ImGuiStorage
struct Pair
{
ImGuiID key;
union { int val_i; float val_f; };
union { int val_i; float val_f; void* val_p; };
Pair(ImGuiID _key, int _val_i) { key = _key; val_i = _val_i; }
Pair(ImGuiID _key, float _val_f) { key = _key; val_f = _val_f; }
Pair(ImGuiID _key, void* _val_p) { key = _key; val_p = _val_p; }
};
ImVector<Pair> Data;
// - Get***() functions find pair, never add/allocate. Pairs are sorted so a query is O(log N)
// - Set***() functions find pair, insertion on demand if missing.
// - Get***Ptr() functions find pair, insertion on demand if missing, return pointer. Useful if you intend to do Get+Set.
// A typical use case where this is very convenient:
// float* pvar = ImGui::GetIntPtr(key); ImGui::SliderInt("var", pvar, 0, 100); some_var += *pvar;
// - Sorted insertion is costly but should amortize. A typical frame shouldn't need to insert any new pair.
IMGUI_API void Clear();
IMGUI_API int GetInt(ImGuiID key, int default_val = 0) const;
IMGUI_API void SetInt(ImGuiID key, int val);
IMGUI_API int* GetIntPtr(ImGuiID key, int default_val = 0);
IMGUI_API float GetFloat(ImGuiID key, float default_val = 0.0f) const;
IMGUI_API void SetFloat(ImGuiID key, float val);
IMGUI_API float* GetFloatPtr(ImGuiID key, float default_val = 0);
IMGUI_API void SetAllInt(int val); // Use on your own storage if you know only integer are being stored.
IMGUI_API void* GetVoidPtr(ImGuiID key) const; // default_val is NULL
IMGUI_API void SetVoidPtr(ImGuiID key, void* val);
// - Get***Ref() functions finds pair, insert on demand if missing, return pointer. Useful if you intend to do Get+Set.
// - References are only valid until a new value is added to the storage. Calling a Set***() function or a Get***Ref() function invalidates the pointer.
// - A typical use case where this is convenient:
// float* pvar = ImGui::GetFloatRef(key); ImGui::SliderFloat("var", pvar, 0, 100.0f); some_var += *pvar;
// - You can also use this to quickly create temporary editable values during a session of using Edit&Continue, without restarting your application.
IMGUI_API int* GetIntRef(ImGuiID key, int default_val = 0);
IMGUI_API float* GetFloatRef(ImGuiID key, float default_val = 0);
// Use on your own storage if you know only integer are being stored (open/close all tree nodes)
IMGUI_API void SetAllInt(int val);
};
// Shared state of InputText(), passed to callback when a ImGuiInputTextFlags_Callback* flag is used.
@ -681,20 +698,50 @@ struct ImGuiTextEditCallbackData
void InsertChars(int pos, const char* text, const char* text_end = NULL);
};
//-----------------------------------------------------------------------------
// Draw List
// Hold a series of drawing commands. The user provides a renderer for ImDrawList
//-----------------------------------------------------------------------------
struct ImDrawCmd
// ImColor() is just a helper that implicity converts to either ImU32 (packed 4x1 byte) or ImVec4 (4x1 float)
// None of the ImGui API are using ImColor directly but you can use it as a convenience to pass colors in either formats.
struct ImColor
{
unsigned int vtx_count;
ImVec4 clip_rect;
ImTextureID texture_id; // Copy of user-provided 'TexID' from ImFont or passed to Image*() functions. Ignore if not using images or multiple fonts.
ImVec4 Value;
ImColor(int r, int g, int b, int a = 255) { Value.x = r / 255.0f; Value.y = g / 255.0f; Value.z = b / 255.0f; Value.w = a / 255.0f; }
ImColor(float r, float g, float b, float a = 1.0f) { Value.x = r; Value.y = g; Value.z = b; Value.w = a; }
ImColor(const ImVec4& col) { Value = col; }
operator ImU32() const { return ImGui::ColorConvertFloat4ToU32(Value); }
operator ImVec4() const { return Value; }
static ImColor HSV(float h, float s, float v, float a = 1.0f) { float r,g,b; ImGui::ColorConvertHSVtoRGB(h, s, v, r, g, b); return ImColor(r,g,b,a); }
};
//-----------------------------------------------------------------------------
// Draw List
// Hold a series of drawing commands. The user provides a renderer for ImDrawList.
//-----------------------------------------------------------------------------
// Draw callbacks for advanced uses.
// NB- You most likely DO NOT need to care about draw callbacks just to create your own widget or customized UI rendering (you can poke into the draw list for that)
// Draw callback are useful for example if you want to render a complex 3D scene inside a UI element.
// The expected behavior from your rendering loop is:
// if (cmd.user_callback != NULL)
// cmd.user_callback(parent_list, cmd);
// else
// RenderTriangles()
// It is up to you to decide if your rendering loop or the callback should be responsible for backup/restoring rendering state.
typedef void (*ImDrawCallback)(const ImDrawList* parent_list, const ImDrawCmd* cmd);
// Typically, 1 command = 1 gpu draw call
struct ImDrawCmd
{
unsigned int vtx_count; // Number of vertices (multiple of 3) to be drawn as triangles. The vertices are stored in the callee ImDrawList's vtx_buffer[] array.
ImVec4 clip_rect; // Clipping rectangle (x1, y1, x2, y2)
ImTextureID texture_id; // User-provided texture ID. Set by user in ImfontAtlas::SetTexID() for fonts or passed to Image*() functions. Ignore if never using images or multiple fonts atlas.
ImDrawCallback user_callback; // If != NULL, call the function instead of rendering the vertices. vtx_count will be 0. clip_rect and texture_id will be set normally.
void* user_callback_data; // The draw callback code can access this.
};
// Vertex layout
#ifndef IMGUI_OVERRIDE_DRAWVERT_STRUCT_LAYOUT
// Default vertex layout
struct ImDrawVert
{
ImVec2 pos;
@ -709,35 +756,28 @@ IMGUI_OVERRIDE_DRAWVERT_STRUCT_LAYOUT;
#endif
// Draw command list
// This is the low-level list of polygon that ImGui:: functions are creating. At the end of the frame, all command lists are passed to your ImGuiIO::RenderDrawListFn function for rendering.
// At the moment, each ImGui window contains its own ImDrawList but they could potentially be merged.
// This is the low-level list of polygons that ImGui functions are filling. At the end of the frame, all command lists are passed to your ImGuiIO::RenderDrawListFn function for rendering.
// At the moment, each ImGui window contains its own ImDrawList but they could potentially be merged in the future.
// If you want to add custom rendering within a window, you can use ImGui::GetWindowDrawList() to access the current draw list and add your own primitives.
// You can interleave normal ImGui:: calls and adding primitives to the current draw list.
// Note that this only gives you access to rendering polygons. If your intent is to create custom widgets and the publicly exposed functions/data aren't sufficient, you can add code in imgui_user.inl
struct ImDrawList
{
// This is what you have to render
ImVector<ImDrawCmd> commands; // commands
ImVector<ImDrawVert> vtx_buffer; // each command consume ImDrawCmd::vtx_count of those
ImVector<ImDrawCmd> commands; // Commands. Typically 1 command = 1 gpu draw call.
ImVector<ImDrawVert> vtx_buffer; // Vertex buffer. Each command consume ImDrawCmd::vtx_count of those
// [Internal to ImGui]
ImVector<ImVec4> clip_rect_stack; // [internal]
ImVector<ImTextureID> texture_id_stack; // [internal]
ImDrawVert* vtx_write; // [internal] point within vtx_buffer after each add command (to avoid using the ImVector<> operators too much)
ImVector<ImVec4> clip_rect_stack; // [Internal]
ImVector<ImTextureID> texture_id_stack; // [Internal]
ImDrawVert* vtx_write; // [Internal] point within vtx_buffer after each add command (to avoid using the ImVector<> operators too much)
ImDrawList() { Clear(); }
IMGUI_API void Clear();
IMGUI_API void SetClipRect(const ImVec4& clip_rect);
IMGUI_API void PushClipRect(const ImVec4& clip_rect);
IMGUI_API void PopClipRect();
IMGUI_API void SetTextureID(const ImTextureID& texture_id);
IMGUI_API void PushTextureID(const ImTextureID& texture_id);
IMGUI_API void PopTextureID();
IMGUI_API void ReserveVertices(unsigned int vtx_count);
IMGUI_API void AddVtx(const ImVec2& pos, ImU32 col);
IMGUI_API void AddVtxUV(const ImVec2& pos, ImU32 col, const ImVec2& uv);
IMGUI_API void AddVtxLine(const ImVec2& a, const ImVec2& b, ImU32 col);
// Primitives
IMGUI_API void AddLine(const ImVec2& a, const ImVec2& b, ImU32 col);
@ -748,7 +788,19 @@ struct ImDrawList
IMGUI_API void AddCircleFilled(const ImVec2& centre, float radius, ImU32 col, int num_segments = 12);
IMGUI_API void AddArc(const ImVec2& center, float rad, ImU32 col, int a_min, int a_max, bool tris = false, const ImVec2& third_point_offset = ImVec2(0,0));
IMGUI_API void AddText(ImFont* font, float font_size, const ImVec2& pos, ImU32 col, const char* text_begin, const char* text_end = NULL, float wrap_width = 0.0f);
IMGUI_API void AddImage(ImTextureID user_texture_id, const ImVec2& a, const ImVec2& b, const ImVec2& uv0, const ImVec2& uv1, ImU32 col);
IMGUI_API void AddImage(ImTextureID user_texture_id, const ImVec2& a, const ImVec2& b, const ImVec2& uv0, const ImVec2& uv1, ImU32 col = 0xFFFFFFFF);
// Advanced
IMGUI_API void AddCallback(ImDrawCallback callback, void* callback_data); // Your rendering function must check for 'user_callback' in ImDrawCmd and call the function instead of rendering triangles.
IMGUI_API void AddDrawCmd(); // This is useful if you need to forcefully create a new draw call (to allow for dependent rendering / blending). Otherwise primitives are merged into the same draw-call as much as possible
// Internal helpers
IMGUI_API void ReserveVertices(unsigned int vtx_count);
IMGUI_API void AddVtx(const ImVec2& pos, ImU32 col);
IMGUI_API void AddVtxUV(const ImVec2& pos, ImU32 col, const ImVec2& uv);
IMGUI_API void AddVtxLine(const ImVec2& a, const ImVec2& b, ImU32 col);
IMGUI_API void UpdateClipRect();
IMGUI_API void UpdateTextureID();
};
// Load and rasterize multiple TTF fonts into a same texture.
@ -800,6 +852,7 @@ struct ImFontAtlas
ImVector<ImFontAtlasData*> InputData; // Internal data
IMGUI_API bool Build(); // Build pixels data. This is automatically for you by the GetTexData*** functions.
IMGUI_API void ClearInputData(); // Clear the input TTF data.
IMGUI_API void RenderCustomTexData();
};
// TTF font loading and rendering

View file

@ -0,0 +1 @@
#include <stb/stb_rect_pack.h>

1
3rdparty/ocornut-imgui/stb_textedit.h vendored Normal file
View file

@ -0,0 +1 @@
#include <stb/stb_textedit.h>

1
3rdparty/ocornut-imgui/stb_truetype.h vendored Normal file
View file

@ -0,0 +1 @@
#include <stb/stb_truetype.h>

View file

@ -139,6 +139,9 @@ struct OcornutImguiContext
, bgfx::copy(data, width*height*4)
);
ImGuiStyle& style = ImGui::GetStyle();
style.FrameRounding = 4.0f;
io.RenderDrawListsFn = imguiRender;
}
@ -160,6 +163,8 @@ struct OcornutImguiContext
io.MouseDown[0] = 0 != (_button & IMGUI_MBUT_LEFT);
ImGui::NewFrame();
ImGui::ShowTestWindow();
}
void endFrame()