|
|
@@ -12,8 +12,8 @@
|
|
|
- PROGRAMMER GUIDE (read me!)
|
|
|
- API BREAKING CHANGES (read me when you update!)
|
|
|
- FREQUENTLY ASKED QUESTIONS (FAQ), TIPS
|
|
|
- - Can I have multiple widgets with the same label? (Yes)
|
|
|
- How do I update to a newer version of ImGui?
|
|
|
+ - Can I have multiple widgets with the same label? (Yes)
|
|
|
- Why is my text output blurry?
|
|
|
- How can I load a different font than the default?
|
|
|
- How can I load multiple fonts?
|
|
|
@@ -186,6 +186,16 @@
|
|
|
FREQUENTLY ASKED QUESTIONS (FAQ), TIPS
|
|
|
======================================
|
|
|
|
|
|
+ Q: How do I update to a newer version of ImGui?
|
|
|
+ A: Overwrite the following files:
|
|
|
+ imgui.cpp
|
|
|
+ imgui.h
|
|
|
+ stb_rect_pack.h
|
|
|
+ stb_textedit.h
|
|
|
+ stb_truetype.h
|
|
|
+ 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!
|
|
|
+
|
|
|
Q: Can I have multiple widgets with the same label?
|
|
|
A: Yes. A primer on the use of labels/IDs in ImGui..
|
|
|
|
|
|
@@ -270,15 +280,6 @@
|
|
|
e.g. when displaying a single object that may change over time (1-1 relationship), using a static string as ID will preserve your node open/closed state when the targeted object change.
|
|
|
e.g. when displaying a list of objects, using indices or pointers as ID will preserve the node open/closed state differently. experiment and see what makes more sense!
|
|
|
|
|
|
- Q: How do I update to a newer version of ImGui?
|
|
|
- A: Overwrite the following files:
|
|
|
- imgui.cpp
|
|
|
- imgui.h
|
|
|
- stb_rect_pack.h
|
|
|
- stb_textedit.h
|
|
|
- stb_truetype.h
|
|
|
- Check the "API BREAKING CHANGES" sections for a list of occasional API breaking changes.
|
|
|
-
|
|
|
Q: Why is my text output blurry?
|
|
|
A: In your Render function, try translating your projection matrix by (0.5f,0.5f) or (0.375f,0.375f)
|
|
|
|
|
|
@@ -329,6 +330,7 @@
|
|
|
- main: considering adding EndFrame()/Init(). some constructs are awkward in the implementation because of the lack of them.
|
|
|
- main: IsItemHovered() make it more consistent for various type of widgets, widgets with multiple components, etc. also effectively IsHovered() region sometimes differs from hot region, e.g tree nodes
|
|
|
- main: IsItemHovered() info stored in a stack? so that 'if TreeNode() { Text; TreePop; } if IsHovered' return the hover state of the TreeNode?
|
|
|
+ - input text: add ImGuiInputTextFlags_EnterToApply? (off github issue #218)
|
|
|
!- input number: large int not reliably supported because of int<>float conversions.
|
|
|
- input number: optional range min/max for Input*() functions
|
|
|
- input number: holding [-]/[+] buttons could increase the step speed non-linearly (or user-controlled)
|
|
|
@@ -343,6 +345,7 @@
|
|
|
- columns: columns header to act as button (~sort op) and allow resize/reorder (github issue #125)
|
|
|
- columns: user specify columns size (github issue #125)
|
|
|
- popup: border options. richer api like BeginChild() perhaps? (github issue #197)
|
|
|
+ - combo: sparse combo boxes (via function call?)
|
|
|
- combo: turn child handling code into pop up helper
|
|
|
- combo: contents should extends to fit label if combo widget is small
|
|
|
- combo/listbox: keyboard control. need inputtext like non-active focus + key handling. considering keybord for custom listbox (see github pr #203)
|
|
|
@@ -494,13 +497,14 @@ struct ImGuiTextEditState;
|
|
|
struct ImGuiIniData;
|
|
|
struct ImGuiState;
|
|
|
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 RenderText(ImVec2 pos, const char* text, const char* text_end = NULL, bool hide_text_after_hash = true);
|
|
|
static void RenderTextWrapped(ImVec2 pos, const char* text, const char* text_end, float wrap_width);
|
|
|
-static void RenderTextClipped(ImVec2 pos, const char* text, const char* text_end, const ImVec2* text_size_if_known, const ImVec2& clip_max);
|
|
|
+static void RenderTextClipped(ImVec2 pos, const char* text, const char* text_end, const ImVec2* text_size_if_known, const ImVec2& pos_max, const ImVec2* clip_max = NULL, ImGuiAlign align = ImGuiAlign_Default);
|
|
|
static void RenderFrame(ImVec2 p_min, ImVec2 p_max, ImU32 fill_col, bool border = true, float rounding = 0.0f);
|
|
|
static void RenderCollapseTriangle(ImVec2 p_min, bool opened, float scale = 1.0f, bool shadow = false);
|
|
|
static void RenderCheckMark(ImVec2 pos, ImU32 col);
|
|
|
@@ -561,6 +565,7 @@ ImGuiStyle::ImGuiStyle()
|
|
|
WindowPadding = ImVec2(8,8); // Padding within a window
|
|
|
WindowMinSize = ImVec2(32,32); // Minimum window size
|
|
|
WindowRounding = 9.0f; // Radius of window corners rounding. Set to 0.0f to have rectangular windows
|
|
|
+ WindowTitleAlign = ImGuiAlign_Left; // Alignment for title bar text
|
|
|
ChildWindowRounding = 0.0f; // Radius of child window corners rounding. Set to 0.0f to have rectangular windows
|
|
|
FramePadding = ImVec2(4,3); // Padding within a framed rectangle (used by most widgets)
|
|
|
FrameRounding = 0.0f; // Radius of frame corners rounding. Set to 0.0f to have rectangular frames (used by most widgets).
|
|
|
@@ -930,6 +935,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
|
|
|
{
|
|
|
ImGuiCol Col;
|
|
|
@@ -2255,6 +2267,7 @@ void ImGui::Render()
|
|
|
|
|
|
// Gather windows to render
|
|
|
g.IO.MetricsRenderVertices = 0;
|
|
|
+ g.IO.MetricsActiveWindows = 0;
|
|
|
for (size_t i = 0; i < IM_ARRAYSIZE(g.RenderDrawLists); i++)
|
|
|
g.RenderDrawLists[i].resize(0);
|
|
|
for (size_t i = 0; i != g.Windows.size(); i++)
|
|
|
@@ -2263,6 +2276,7 @@ void ImGui::Render()
|
|
|
if (window->Active && window->HiddenFrames <= 0 && (window->Flags & (ImGuiWindowFlags_ChildWindow)) == 0)
|
|
|
{
|
|
|
// FIXME: Generalize this with a proper layering system so we can stack.
|
|
|
+ g.IO.MetricsActiveWindows++;
|
|
|
if (window->Flags & ImGuiWindowFlags_Popup)
|
|
|
AddWindowToRenderList(g.RenderDrawLists[1], window);
|
|
|
else if (window->Flags & ImGuiWindowFlags_Tooltip)
|
|
|
@@ -2460,37 +2474,36 @@ static void RenderTextWrapped(ImVec2 pos, const char* text, const char* text_end
|
|
|
const int text_len = (int)(text_end - text);
|
|
|
if (text_len > 0)
|
|
|
{
|
|
|
- // Render
|
|
|
window->DrawList->AddText(g.Font, g.FontSize, pos, window->Color(ImGuiCol_Text), text, text_end, wrap_width);
|
|
|
-
|
|
|
- // Log as text
|
|
|
if (g.LogEnabled)
|
|
|
LogText(pos, text, text_end);
|
|
|
}
|
|
|
}
|
|
|
|
|
|
-static void RenderTextClipped(ImVec2 pos, const char* text, const char* text_end, const ImVec2* text_size_if_known, const ImVec2& clip_max)
|
|
|
+static void RenderTextClipped(ImVec2 pos, const char* text, const char* text_end, const ImVec2* text_size_if_known, const ImVec2& pos_max, const ImVec2* clip_max, ImGuiAlign align)
|
|
|
{
|
|
|
- ImGuiState& g = *GImGui;
|
|
|
- ImGuiWindow* window = GetCurrentWindow();
|
|
|
-
|
|
|
// Hide anything after a '##' string
|
|
|
const char* text_display_end = FindTextDisplayEnd(text, text_end);
|
|
|
const int text_len = (int)(text_display_end - text);
|
|
|
- if (text_len > 0)
|
|
|
- {
|
|
|
- const ImVec2 text_size = text_size_if_known ? *text_size_if_known : ImGui::CalcTextSize(text, text_display_end, false, 0.0f);
|
|
|
+ if (text_len == 0)
|
|
|
+ return;
|
|
|
+
|
|
|
+ ImGuiState& g = *GImGui;
|
|
|
+ ImGuiWindow* window = GetCurrentWindow();
|
|
|
|
|
|
- // Perform CPU side clipping for single clipped element to avoid using scissor state
|
|
|
- const bool need_clipping = (pos.x + text_size.x >= clip_max.x) || (pos.y + text_size.y >= clip_max.y);
|
|
|
+ // Perform CPU side clipping for single clipped element to avoid using scissor state
|
|
|
+ const ImVec2 text_size = text_size_if_known ? *text_size_if_known : ImGui::CalcTextSize(text, text_display_end, false, 0.0f);
|
|
|
+ if (!clip_max) clip_max = &pos_max;
|
|
|
+ const bool need_clipping = (pos.x + text_size.x >= clip_max->x) || (pos.y + text_size.y >= clip_max->y);
|
|
|
|
|
|
- // Render
|
|
|
- window->DrawList->AddText(g.Font, g.FontSize, pos, window->Color(ImGuiCol_Text), text, text_display_end, 0.0f, need_clipping ? &clip_max : NULL);
|
|
|
+ // Align
|
|
|
+ if (align & ImGuiAlign_Center) pos.x = ImMax(pos.x, (pos.x + pos_max.x - text_size.x) * 0.5f);
|
|
|
+ else if (align & ImGuiAlign_Right) pos.x = ImMax(pos.x, pos_max.x - text_size.x);
|
|
|
|
|
|
- // Log as text
|
|
|
- if (g.LogEnabled)
|
|
|
- LogText(pos, text, text_display_end);
|
|
|
- }
|
|
|
+ // Render
|
|
|
+ window->DrawList->AddText(g.Font, g.FontSize, pos, window->Color(ImGuiCol_Text), text, text_display_end, 0.0f, need_clipping ? clip_max : NULL);
|
|
|
+ if (g.LogEnabled)
|
|
|
+ LogText(pos, text, text_display_end);
|
|
|
}
|
|
|
|
|
|
// Render a rectangle shaped with optional rounding and borders
|
|
|
@@ -3428,7 +3441,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 ImGuiID resize_id = window->GetID("#RESIZE");
|
|
|
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);
|
|
|
|
|
|
if (hovered || held)
|
|
|
@@ -3541,16 +3554,19 @@ bool ImGui::Begin(const char* name, bool* p_opened, const ImVec2& size_on_first_
|
|
|
if (p_opened != NULL)
|
|
|
CloseWindowButton(p_opened);
|
|
|
|
|
|
- ImVec2 text_min = window->Pos + style.FramePadding;
|
|
|
+ const ImVec2 text_size = CalcTextSize(name, NULL, true);
|
|
|
if (!(flags & ImGuiWindowFlags_NoCollapse))
|
|
|
- {
|
|
|
RenderCollapseTriangle(window->Pos + style.FramePadding, !window->Collapsed, 1.0f, true);
|
|
|
- text_min.x += g.FontSize + style.ItemInnerSpacing.x;
|
|
|
- }
|
|
|
-
|
|
|
- const ImVec2 text_size = CalcTextSize(name, NULL, true);
|
|
|
- const ImVec2 text_max = window->Pos + ImVec2(window->Size.x - (p_opened ? (title_bar_rect.GetHeight()-3) : style.FramePadding.x), style.FramePadding.y*2 + text_size.y);
|
|
|
- RenderTextClipped(text_min, name, NULL, &text_size, text_max);
|
|
|
+
|
|
|
+ ImVec2 text_min = window->Pos + style.FramePadding;
|
|
|
+ ImVec2 text_max = window->Pos + ImVec2(window->Size.x - style.FramePadding.x, style.FramePadding.y*2 + text_size.y);
|
|
|
+ ImVec2 clip_max = ImVec2(window->Pos.x + window->Size.x - (p_opened ? title_bar_rect.GetHeight() - 3 : style.FramePadding.x), text_max.y); // Match the size of CloseWindowButton()
|
|
|
+ bool pad_left = (flags & ImGuiWindowFlags_NoCollapse) == 0;
|
|
|
+ bool pad_right = (p_opened != NULL);
|
|
|
+ if (style.WindowTitleAlign & ImGuiAlign_Center) pad_right = pad_left;
|
|
|
+ if (pad_left) text_min.x += g.FontSize + style.ItemInnerSpacing.x;
|
|
|
+ if (pad_right) text_max.x -= g.FontSize + style.ItemInnerSpacing.x;
|
|
|
+ RenderTextClipped(text_min, name, NULL, &text_size, text_max, &clip_max, style.WindowTitleAlign);
|
|
|
}
|
|
|
if (flags & ImGuiWindowFlags_Popup)
|
|
|
{
|
|
|
@@ -3739,6 +3755,19 @@ void ImGui::PushItemWidth(float item_width)
|
|
|
window->DC.ItemWidth.push_back(item_width == 0.0f ? window->ItemWidthDefault : item_width);
|
|
|
}
|
|
|
|
|
|
+static void PushMultiItemsWidths(int components, float w_full = 0.0f)
|
|
|
+{
|
|
|
+ ImGuiWindow* window = GetCurrentWindow();
|
|
|
+ const ImGuiStyle& style = GImGui->Style;
|
|
|
+ if (w_full <= 0.0f)
|
|
|
+ w_full = ImGui::CalcItemWidth();
|
|
|
+ const float w_item_one = ImMax(1.0f, (float)(int)((w_full - (style.FramePadding.x*2.0f + style.ItemInnerSpacing.x) * (components-1)) / (float)components));
|
|
|
+ const float w_item_last = ImMax(1.0f, (float)(int)(w_full - (w_item_one + style.FramePadding.x*2.0f + style.ItemInnerSpacing.x) * (components-1)));
|
|
|
+ window->DC.ItemWidth.push_back(w_item_last);
|
|
|
+ for (int i = 0; i < components-1; i++)
|
|
|
+ window->DC.ItemWidth.push_back(w_item_one);
|
|
|
+}
|
|
|
+
|
|
|
void ImGui::PopItemWidth()
|
|
|
{
|
|
|
ImGuiWindow* window = GetCurrentWindow();
|
|
|
@@ -3753,9 +3782,8 @@ float ImGui::CalcItemWidth()
|
|
|
{
|
|
|
// Align to a right-side limit. We include 1 frame padding in the calculation because this is how the width is always used (we add 2 frame padding to it), but we could move that responsibility to the widget as well.
|
|
|
ImGuiState& g = *GImGui;
|
|
|
- w = -w;
|
|
|
float width_to_right_edge = window->Pos.x + ImGui::GetContentRegionMax().x - window->DC.CursorPos.x;
|
|
|
- w = ImMax(1.0f, width_to_right_edge - w - g.Style.FramePadding.x * 2.0f);
|
|
|
+ w = ImMax(1.0f, width_to_right_edge + w - g.Style.FramePadding.x * 2.0f);
|
|
|
}
|
|
|
w = (float)(int)w;
|
|
|
return w;
|
|
|
@@ -4514,13 +4542,13 @@ static inline bool IsWindowContentHoverable(ImGuiWindow* window)
|
|
|
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;
|
|
|
if (g.HoveredId == 0)
|
|
|
{
|
|
|
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 (IsWindowContentHoverable(g.HoveredRootWindow))
|
|
|
return true;
|
|
|
@@ -4528,13 +4556,13 @@ static bool IsHovered(const ImRect& bb, ImGuiID id)
|
|
|
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;
|
|
|
ImGuiWindow* window = GetCurrentWindow();
|
|
|
|
|
|
- const bool hovered = IsHovered(bb, id);
|
|
|
bool pressed = false;
|
|
|
+ const bool hovered = IsHovered(bb, id, (flags & ImGuiButtonFlags_FlattenChilds) != 0);
|
|
|
if (hovered)
|
|
|
{
|
|
|
g.HoveredId = id;
|
|
|
@@ -4542,7 +4570,7 @@ static bool ButtonBehavior(const ImRect& bb, ImGuiID id, bool* out_hovered, bool
|
|
|
{
|
|
|
if (g.IO.MouseClicked[0])
|
|
|
{
|
|
|
- if (pressed_on_click)
|
|
|
+ if (flags & ImGuiButtonFlags_PressedOnClick)
|
|
|
{
|
|
|
pressed = true;
|
|
|
SetActiveId(0);
|
|
|
@@ -4553,7 +4581,7 @@ static bool ButtonBehavior(const ImRect& bb, ImGuiID id, bool* out_hovered, bool
|
|
|
}
|
|
|
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;
|
|
|
}
|
|
|
@@ -4599,7 +4627,7 @@ bool ImGui::Button(const char* label, const ImVec2& size_arg, bool repeat_when_h
|
|
|
return false;
|
|
|
|
|
|
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
|
|
|
const ImU32 col = window->Color((hovered && held) ? ImGuiCol_ButtonActive : hovered ? ImGuiCol_ButtonHovered : ImGuiCol_Button);
|
|
|
@@ -5558,28 +5586,18 @@ static bool SliderFloatN(const char* label, float* v, int components, float v_mi
|
|
|
if (window->SkipItems)
|
|
|
return false;
|
|
|
|
|
|
- const ImGuiStyle& style = g.Style;
|
|
|
- const float w_full = ImGui::CalcItemWidth();
|
|
|
- const float w_item_one = ImMax(1.0f, (float)(int)((w_full - (style.FramePadding.x*2.0f + style.ItemInnerSpacing.x)*(components-1)) / (float)components));
|
|
|
- const float w_item_last = ImMax(1.0f, (float)(int)(w_full - (w_item_one + style.FramePadding.x*2.0f + style.ItemInnerSpacing.x)*(components-1)));
|
|
|
-
|
|
|
bool value_changed = false;
|
|
|
ImGui::BeginGroup();
|
|
|
ImGui::PushID(label);
|
|
|
- ImGui::PushItemWidth(w_item_one);
|
|
|
+ PushMultiItemsWidths(components);
|
|
|
for (int i = 0; i < components; i++)
|
|
|
{
|
|
|
ImGui::PushID(i);
|
|
|
- if (i + 1 == components)
|
|
|
- {
|
|
|
- ImGui::PopItemWidth();
|
|
|
- ImGui::PushItemWidth(w_item_last);
|
|
|
- }
|
|
|
value_changed |= ImGui::SliderFloat("##v", &v[i], v_min, v_max, display_format, power);
|
|
|
- ImGui::SameLine(0, (int)style.ItemInnerSpacing.x);
|
|
|
+ ImGui::SameLine(0, (int)g.Style.ItemInnerSpacing.x);
|
|
|
ImGui::PopID();
|
|
|
+ ImGui::PopItemWidth();
|
|
|
}
|
|
|
- ImGui::PopItemWidth();
|
|
|
ImGui::PopID();
|
|
|
|
|
|
ImGui::TextUnformatted(label, FindTextDisplayEnd(label));
|
|
|
@@ -5610,28 +5628,18 @@ static bool SliderIntN(const char* label, int* v, int components, int v_min, int
|
|
|
if (window->SkipItems)
|
|
|
return false;
|
|
|
|
|
|
- const ImGuiStyle& style = g.Style;
|
|
|
- const float w_full = ImGui::CalcItemWidth();
|
|
|
- const float w_item_one = ImMax(1.0f, (float)(int)((w_full - (style.FramePadding.x*2.0f + style.ItemInnerSpacing.x)*(components-1)) / (float)components));
|
|
|
- const float w_item_last = ImMax(1.0f, (float)(int)(w_full - (w_item_one + style.FramePadding.x*2.0f + style.ItemInnerSpacing.x)*(components-1)));
|
|
|
-
|
|
|
bool value_changed = false;
|
|
|
ImGui::BeginGroup();
|
|
|
ImGui::PushID(label);
|
|
|
- ImGui::PushItemWidth(w_item_one);
|
|
|
+ PushMultiItemsWidths(components);
|
|
|
for (int i = 0; i < components; i++)
|
|
|
{
|
|
|
ImGui::PushID(i);
|
|
|
- if (i + 1 == components)
|
|
|
- {
|
|
|
- ImGui::PopItemWidth();
|
|
|
- ImGui::PushItemWidth(w_item_last);
|
|
|
- }
|
|
|
value_changed |= ImGui::SliderInt("##v", &v[i], v_min, v_max, display_format);
|
|
|
- ImGui::SameLine(0, (int)style.ItemInnerSpacing.x);
|
|
|
+ ImGui::SameLine(0, (int)g.Style.ItemInnerSpacing.x);
|
|
|
ImGui::PopID();
|
|
|
+ ImGui::PopItemWidth();
|
|
|
}
|
|
|
- ImGui::PopItemWidth();
|
|
|
ImGui::PopID();
|
|
|
|
|
|
ImGui::TextUnformatted(label, FindTextDisplayEnd(label));
|
|
|
@@ -5805,28 +5813,18 @@ static bool DragFloatN(const char* label, float* v, int components, float v_spee
|
|
|
if (window->SkipItems)
|
|
|
return false;
|
|
|
|
|
|
- const ImGuiStyle& style = g.Style;
|
|
|
- const float w_full = ImGui::CalcItemWidth();
|
|
|
- const float w_item_one = ImMax(1.0f, (float)(int)((w_full - (style.FramePadding.x*2.0f + style.ItemInnerSpacing.x)*(components-1)) / (float)components));
|
|
|
- const float w_item_last = ImMax(1.0f, (float)(int)(w_full - (w_item_one + style.FramePadding.x*2.0f + style.ItemInnerSpacing.x)*(components-1)));
|
|
|
-
|
|
|
bool value_changed = false;
|
|
|
ImGui::BeginGroup();
|
|
|
ImGui::PushID(label);
|
|
|
- ImGui::PushItemWidth(w_item_one);
|
|
|
+ PushMultiItemsWidths(components);
|
|
|
for (int i = 0; i < components; i++)
|
|
|
{
|
|
|
ImGui::PushID(i);
|
|
|
- if (i + 1 == components)
|
|
|
- {
|
|
|
- ImGui::PopItemWidth();
|
|
|
- ImGui::PushItemWidth(w_item_last);
|
|
|
- }
|
|
|
value_changed |= ImGui::DragFloat("##v", &v[i], v_speed, v_min, v_max, display_format, power);
|
|
|
- ImGui::SameLine(0, (int)style.ItemInnerSpacing.x);
|
|
|
+ ImGui::SameLine(0, (int)g.Style.ItemInnerSpacing.x);
|
|
|
ImGui::PopID();
|
|
|
+ ImGui::PopItemWidth();
|
|
|
}
|
|
|
- ImGui::PopItemWidth();
|
|
|
ImGui::PopID();
|
|
|
|
|
|
ImGui::TextUnformatted(label, FindTextDisplayEnd(label));
|
|
|
@@ -5868,28 +5866,18 @@ static bool DragIntN(const char* label, int* v, int components, float v_speed, i
|
|
|
if (window->SkipItems)
|
|
|
return false;
|
|
|
|
|
|
- const ImGuiStyle& style = g.Style;
|
|
|
- const float w_full = ImGui::CalcItemWidth();
|
|
|
- const float w_item_one = ImMax(1.0f, (float)(int)((w_full - (style.FramePadding.x*2.0f + style.ItemInnerSpacing.x)*(components-1)) / (float)components));
|
|
|
- const float w_item_last = ImMax(1.0f, (float)(int)(w_full - (w_item_one + style.FramePadding.x*2.0f + style.ItemInnerSpacing.x)*(components-1)));
|
|
|
-
|
|
|
bool value_changed = false;
|
|
|
ImGui::BeginGroup();
|
|
|
ImGui::PushID(label);
|
|
|
- ImGui::PushItemWidth(w_item_one);
|
|
|
+ PushMultiItemsWidths(components);
|
|
|
for (int i = 0; i < components; i++)
|
|
|
{
|
|
|
ImGui::PushID(i);
|
|
|
- if (i + 1 == components)
|
|
|
- {
|
|
|
- ImGui::PopItemWidth();
|
|
|
- ImGui::PushItemWidth(w_item_last);
|
|
|
- }
|
|
|
value_changed |= ImGui::DragInt("##v", &v[i], v_speed, v_min, v_max, display_format);
|
|
|
- ImGui::SameLine(0, (int)style.ItemInnerSpacing.x);
|
|
|
+ ImGui::SameLine(0, (int)g.Style.ItemInnerSpacing.x);
|
|
|
ImGui::PopID();
|
|
|
+ ImGui::PopItemWidth();
|
|
|
}
|
|
|
- ImGui::PopItemWidth();
|
|
|
ImGui::PopID();
|
|
|
|
|
|
ImGui::TextUnformatted(label, FindTextDisplayEnd(label));
|
|
|
@@ -6848,31 +6836,21 @@ static bool InputFloatN(const char* label, float* v, int components, int decimal
|
|
|
if (window->SkipItems)
|
|
|
return false;
|
|
|
|
|
|
- const ImGuiStyle& style = g.Style;
|
|
|
- const float w_full = ImGui::CalcItemWidth();
|
|
|
- const float w_item_one = ImMax(1.0f, (float)(int)((w_full - (style.FramePadding.x*2.0f + style.ItemInnerSpacing.x) * (components-1)) / (float)components));
|
|
|
- const float w_item_last = ImMax(1.0f, (float)(int)(w_full - (w_item_one + style.FramePadding.x*2.0f + style.ItemInnerSpacing.x) * (components-1)));
|
|
|
-
|
|
|
bool value_changed = false;
|
|
|
ImGui::BeginGroup();
|
|
|
ImGui::PushID(label);
|
|
|
- ImGui::PushItemWidth(w_item_one);
|
|
|
+ PushMultiItemsWidths(components);
|
|
|
for (int i = 0; i < components; i++)
|
|
|
{
|
|
|
ImGui::PushID(i);
|
|
|
- if (i + 1 == components)
|
|
|
- {
|
|
|
- ImGui::PopItemWidth();
|
|
|
- ImGui::PushItemWidth(w_item_last);
|
|
|
- }
|
|
|
value_changed |= ImGui::InputFloat("##v", &v[i], 0, 0, decimal_precision, extra_flags);
|
|
|
- ImGui::SameLine(0, (int)style.ItemInnerSpacing.x);
|
|
|
+ ImGui::SameLine(0, (int)g.Style.ItemInnerSpacing.x);
|
|
|
ImGui::PopID();
|
|
|
+ ImGui::PopItemWidth();
|
|
|
}
|
|
|
- ImGui::PopItemWidth();
|
|
|
ImGui::PopID();
|
|
|
|
|
|
- window->DC.CurrentLineTextBaseOffset = ImMax(window->DC.CurrentLineTextBaseOffset, style.FramePadding.y);
|
|
|
+ window->DC.CurrentLineTextBaseOffset = ImMax(window->DC.CurrentLineTextBaseOffset, g.Style.FramePadding.y);
|
|
|
ImGui::TextUnformatted(label, FindTextDisplayEnd(label));
|
|
|
ImGui::EndGroup();
|
|
|
|
|
|
@@ -6901,31 +6879,21 @@ static bool InputIntN(const char* label, int* v, int components, ImGuiInputTextF
|
|
|
if (window->SkipItems)
|
|
|
return false;
|
|
|
|
|
|
- const ImGuiStyle& style = g.Style;
|
|
|
- const float w_full = ImGui::CalcItemWidth();
|
|
|
- const float w_item_one = ImMax(1.0f, (float)(int)((w_full - (style.FramePadding.x*2.0f + style.ItemInnerSpacing.x) * (components-1)) / (float)components));
|
|
|
- const float w_item_last = ImMax(1.0f, (float)(int)(w_full - (w_item_one + style.FramePadding.x*2.0f + style.ItemInnerSpacing.x) * (components-1)));
|
|
|
-
|
|
|
bool value_changed = false;
|
|
|
ImGui::BeginGroup();
|
|
|
ImGui::PushID(label);
|
|
|
- ImGui::PushItemWidth(w_item_one);
|
|
|
+ PushMultiItemsWidths(components);
|
|
|
for (int i = 0; i < components; i++)
|
|
|
{
|
|
|
ImGui::PushID(i);
|
|
|
- if (i + 1 == components)
|
|
|
- {
|
|
|
- ImGui::PopItemWidth();
|
|
|
- ImGui::PushItemWidth(w_item_last);
|
|
|
- }
|
|
|
value_changed |= ImGui::InputInt("##v", &v[i], 0, 0, extra_flags);
|
|
|
- ImGui::SameLine(0, (int)style.ItemInnerSpacing.x);
|
|
|
+ ImGui::SameLine(0, (int)g.Style.ItemInnerSpacing.x);
|
|
|
ImGui::PopID();
|
|
|
+ ImGui::PopItemWidth();
|
|
|
}
|
|
|
- ImGui::PopItemWidth();
|
|
|
ImGui::PopID();
|
|
|
|
|
|
- window->DC.CurrentLineTextBaseOffset = ImMax(window->DC.CurrentLineTextBaseOffset, style.FramePadding.y);
|
|
|
+ window->DC.CurrentLineTextBaseOffset = ImMax(window->DC.CurrentLineTextBaseOffset, g.Style.FramePadding.y);
|
|
|
ImGui::TextUnformatted(label, FindTextDisplayEnd(label));
|
|
|
ImGui::EndGroup();
|
|
|
|
|
|
@@ -7135,7 +7103,7 @@ bool ImGui::Selectable(const char* label, bool selected, const ImVec2& size_arg)
|
|
|
return false;
|
|
|
|
|
|
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
|
|
|
if (hovered || selected)
|
|
|
@@ -8431,10 +8399,8 @@ void ImFontAtlas::ClearTexData()
|
|
|
TexPixelsRGBA32 = NULL;
|
|
|
}
|
|
|
|
|
|
-void ImFontAtlas::Clear()
|
|
|
+void ImFontAtlas::ClearFonts()
|
|
|
{
|
|
|
- ClearInputData();
|
|
|
- ClearTexData();
|
|
|
for (size_t i = 0; i < Fonts.size(); i++)
|
|
|
{
|
|
|
Fonts[i]->~ImFont();
|
|
|
@@ -8443,6 +8409,13 @@ void ImFontAtlas::Clear()
|
|
|
Fonts.clear();
|
|
|
}
|
|
|
|
|
|
+void ImFontAtlas::Clear()
|
|
|
+{
|
|
|
+ ClearInputData();
|
|
|
+ ClearTexData();
|
|
|
+ ClearFonts();
|
|
|
+}
|
|
|
+
|
|
|
void ImGui::GetDefaultFontData(const void** fnt_data, unsigned int* fnt_size, const void** png_data, unsigned int* png_size)
|
|
|
{
|
|
|
printf("GetDefaultFontData() is obsoleted in ImGui 1.30.\n");
|
|
|
@@ -8520,8 +8493,8 @@ ImFont* ImFontAtlas::AddFontFromFileTTF(const char* filename, float size_pixels,
|
|
|
return font;
|
|
|
}
|
|
|
|
|
|
-// NB: ownership of 'data' is given to ImFontAtlas which will clear it.
|
|
|
-ImFont* ImFontAtlas::AddFontFromMemoryTTF(void* in_ttf_data, unsigned int in_ttf_data_size, float size_pixels, const ImWchar* glyph_ranges, int font_no)
|
|
|
+// Transfer ownership of 'ttf_data' to ImFontAtlas, will be deleted after Build()
|
|
|
+ImFont* ImFontAtlas::AddFontFromMemoryTTF(void* ttf_data, int ttf_size, float size_pixels, const ImWchar* glyph_ranges, int font_no)
|
|
|
{
|
|
|
// Create new font
|
|
|
ImFont* font = (ImFont*)ImGui::MemAlloc(sizeof(ImFont));
|
|
|
@@ -8532,8 +8505,8 @@ ImFont* ImFontAtlas::AddFontFromMemoryTTF(void* in_ttf_data, unsigned int in_ttf
|
|
|
ImFontAtlasData* data = (ImFontAtlasData*)ImGui::MemAlloc(sizeof(ImFontAtlasData));
|
|
|
memset(data, 0, sizeof(ImFontAtlasData));
|
|
|
data->OutFont = font;
|
|
|
- data->TTFData = in_ttf_data;
|
|
|
- data->TTFDataSize = in_ttf_data_size;
|
|
|
+ data->TTFData = ttf_data;
|
|
|
+ data->TTFDataSize = (size_t)ttf_size;
|
|
|
data->SizePixels = size_pixels;
|
|
|
data->GlyphRanges = glyph_ranges;
|
|
|
data->FontNo = font_no;
|
|
|
@@ -8545,15 +8518,15 @@ ImFont* ImFontAtlas::AddFontFromMemoryTTF(void* in_ttf_data, unsigned int in_ttf
|
|
|
return font;
|
|
|
}
|
|
|
|
|
|
-ImFont* ImFontAtlas::AddFontFromMemoryCompressedTTF(const void* in_compressed_ttf_data, unsigned int in_compressed_ttf_data_size, float size_pixels, const ImWchar* glyph_ranges, int font_no)
|
|
|
+ImFont* ImFontAtlas::AddFontFromMemoryCompressedTTF(const void* compressed_ttf_data, int compressed_ttf_size, float size_pixels, const ImWchar* glyph_ranges, int font_no)
|
|
|
{
|
|
|
// Decompress
|
|
|
- const size_t buf_decompressed_size = stb_decompress_length((unsigned char*)in_compressed_ttf_data);
|
|
|
- unsigned char* buf_decompressed = (unsigned char *)ImGui::MemAlloc(buf_decompressed_size);
|
|
|
- stb_decompress(buf_decompressed, (unsigned char*)in_compressed_ttf_data, in_compressed_ttf_data_size);
|
|
|
+ const size_t buf_decompressed_size = stb_decompress_length((unsigned char*)compressed_ttf_data);
|
|
|
+ unsigned char* buf_decompressed_data = (unsigned char *)ImGui::MemAlloc(buf_decompressed_size);
|
|
|
+ stb_decompress(buf_decompressed_data, (unsigned char*)compressed_ttf_data, (unsigned int)compressed_ttf_size);
|
|
|
|
|
|
// Add
|
|
|
- ImFont* font = AddFontFromMemoryTTF(buf_decompressed, (unsigned int)buf_decompressed_size, size_pixels, glyph_ranges, font_no);
|
|
|
+ ImFont* font = AddFontFromMemoryTTF(buf_decompressed_data, (int)buf_decompressed_size, size_pixels, glyph_ranges, font_no);
|
|
|
return font;
|
|
|
}
|
|
|
|
|
|
@@ -8572,7 +8545,7 @@ bool ImFontAtlas::Build()
|
|
|
for (size_t input_i = 0; input_i < InputData.size(); input_i++)
|
|
|
{
|
|
|
ImFontAtlasData& data = *InputData[input_i];
|
|
|
- IM_ASSERT(data.OutFont && !data.OutFont->IsLoaded());
|
|
|
+ IM_ASSERT(data.OutFont && (!data.OutFont->IsLoaded() || data.OutFont->ContainerAtlas == this));
|
|
|
const int font_offset = stbtt_GetFontOffsetForIndex((unsigned char*)data.TTFData, data.FontNo);
|
|
|
IM_ASSERT(font_offset >= 0);
|
|
|
if (!stbtt_InitFont(&data.FontInfo, (unsigned char*)data.TTFData, font_offset))
|
|
|
@@ -8686,6 +8659,7 @@ bool ImFontAtlas::Build()
|
|
|
int font_ascent, font_descent, font_line_gap;
|
|
|
stbtt_GetFontVMetrics(&data.FontInfo, &font_ascent, &font_descent, &font_line_gap);
|
|
|
data.OutFont->BaseLine = (font_ascent * font_scale);
|
|
|
+ data.OutFont->Glyphs.resize(0);
|
|
|
|
|
|
const float uv_scale_x = 1.0f / TexWidth;
|
|
|
const float uv_scale_y = 1.0f / TexHeight;
|
|
|
@@ -8723,7 +8697,6 @@ bool ImFontAtlas::Build()
|
|
|
ImGui::MemFree(buf_ranges);
|
|
|
buf_packedchars = NULL;
|
|
|
buf_ranges = NULL;
|
|
|
- ClearInputData();
|
|
|
|
|
|
// Render into our custom data block
|
|
|
RenderCustomTexData(1, &extra_rects);
|
|
|
@@ -9871,7 +9844,7 @@ void ImGui::ShowTestWindow(bool* opened)
|
|
|
ImGui::TreePop();
|
|
|
}
|
|
|
|
|
|
- if (ImGui::TreeNode("Fonts"))
|
|
|
+ if (ImGui::TreeNode("Fonts", "Fonts (%d)", (int)ImGui::GetIO().Fonts->Fonts.size()))
|
|
|
{
|
|
|
ImGui::TextWrapped("Tip: Load fonts with GetIO().Fonts->AddFontFromFileTTF().");
|
|
|
for (size_t i = 0; i < ImGui::GetIO().Fonts->Fonts.size(); i++)
|