Updated imgui.

This commit is contained in:
Branimir Karadžić 2015-08-29 17:00:23 -07:00
parent bff5f2bafd
commit fdbf146fb5
5 changed files with 179 additions and 59 deletions

View file

@ -620,6 +620,7 @@ ImGuiStyle::ImGuiStyle()
DisplaySafeAreaPadding = ImVec2(4,4); // If you cannot see the edge of your screen (e.g. on a TV) increase the safe area padding. Covers popups/tooltips as well regular windows.
AntiAliasedLines = true; // Enable anti-aliasing on lines/borders. Disable if you are really short on CPU/GPU.
AntiAliasedShapes = true; // Enable anti-aliasing on filled shapes (rounded rectangles, circles, etc.)
CurveTessellationTol = 1.25f; // Tessellation tolerance. Decrease for highly tessellated curves (higher quality, more polygons), increase to reduce quality.
Colors[ImGuiCol_Text] = ImVec4(0.90f, 0.90f, 0.90f, 1.00f);
Colors[ImGuiCol_TextDisabled] = ImVec4(0.60f, 0.60f, 0.60f, 1.00f);
@ -678,6 +679,7 @@ ImGuiIO::ImGuiIO()
LogFilename = "imgui_log.txt";
Fonts = &GImDefaultFontAtlas;
FontGlobalScale = 1.0f;
DisplayFramebufferScale = ImVec2(1.0f, 1.0f);
MousePos = ImVec2(-1,-1);
MousePosPrev = ImVec2(-1,-1);
MouseDoubleClickTime = 0.30f;
@ -882,45 +884,45 @@ int ImTextCharFromUtf8(unsigned int* out_char, const char* in_text, const char*
}
if ((*str & 0xe0) == 0xc0)
{
*out_char = 0;
*out_char = 0xFFFD; // will be invalid but not end of string
if (in_text_end && in_text_end - (const char*)str < 2) return 0;
if (*str < 0xc2) return 0;
if (*str < 0xc2) return 2;
c = (unsigned int)((*str++ & 0x1f) << 6);
if ((*str & 0xc0) != 0x80) return 0;
if ((*str & 0xc0) != 0x80) return 2;
c += (*str++ & 0x3f);
*out_char = c;
return 2;
}
if ((*str & 0xf0) == 0xe0)
{
*out_char = 0;
*out_char = 0xFFFD; // will be invalid but not end of string
if (in_text_end && in_text_end - (const char*)str < 3) return 0;
if (*str == 0xe0 && (str[1] < 0xa0 || str[1] > 0xbf)) return 0;
if (*str == 0xed && str[1] > 0x9f) return 0; // str[1] < 0x80 is checked below
if (*str == 0xe0 && (str[1] < 0xa0 || str[1] > 0xbf)) return 3;
if (*str == 0xed && str[1] > 0x9f) return 3; // str[1] < 0x80 is checked below
c = (unsigned int)((*str++ & 0x0f) << 12);
if ((*str & 0xc0) != 0x80) return 0;
if ((*str & 0xc0) != 0x80) return 3;
c += (unsigned int)((*str++ & 0x3f) << 6);
if ((*str & 0xc0) != 0x80) return 0;
if ((*str & 0xc0) != 0x80) return 3;
c += (*str++ & 0x3f);
*out_char = c;
return 3;
}
if ((*str & 0xf8) == 0xf0)
{
*out_char = 0;
*out_char = 0xFFFD; // will be invalid but not end of string
if (in_text_end && in_text_end - (const char*)str < 4) return 0;
if (*str > 0xf4) return 0;
if (*str == 0xf0 && (str[1] < 0x90 || str[1] > 0xbf)) return 0;
if (*str == 0xf4 && str[1] > 0x8f) return 0; // str[1] < 0x80 is checked below
if (*str > 0xf4) return 4;
if (*str == 0xf0 && (str[1] < 0x90 || str[1] > 0xbf)) return 4;
if (*str == 0xf4 && str[1] > 0x8f) return 4; // str[1] < 0x80 is checked below
c = (unsigned int)((*str++ & 0x07) << 18);
if ((*str & 0xc0) != 0x80) return 0;
if ((*str & 0xc0) != 0x80) return 4;
c += (unsigned int)((*str++ & 0x3f) << 12);
if ((*str & 0xc0) != 0x80) return 0;
if ((*str & 0xc0) != 0x80) return 4;
c += (unsigned int)((*str++ & 0x3f) << 6);
if ((*str & 0xc0) != 0x80) return 0;
if ((*str & 0xc0) != 0x80) return 4;
c += (*str++ & 0x3f);
// utf-8 encodings of values used in surrogate pairs are invalid
if ((c & 0xFFFFF800) == 0xD800) return 0;
if ((c & 0xFFFFF800) == 0xD800) return 4;
*out_char = c;
return 4;
}
@ -1039,6 +1041,12 @@ int ImTextCountUtf8BytesFromStr(const ImWchar* in_text, const ImWchar* in_text_e
return bytes_count;
}
ImVec4 ImGui::ColorConvertU32ToFloat4(ImU32 in)
{
float s = 1.0f/255.0f;
return ImVec4((in & 0xFF) * s, ((in >> 8) & 0xFF) * s, ((in >> 16) & 0xFF) * s, (in >> 24) * s);
}
ImU32 ImGui::ColorConvertFloat4ToU32(const ImVec4& in)
{
ImU32 out = ((ImU32)(ImSaturate(in.x)*255.f));
@ -1783,6 +1791,7 @@ void ImGui::NewFrame()
IM_ASSERT(g.IO.RenderDrawListsFn != NULL); // Must be implemented
IM_ASSERT(g.IO.Fonts->Fonts.Size > 0); // Font Atlas not created. Did you call io.Fonts->GetTexDataAsRGBA32 / GetTexDataAsAlpha8 ?
IM_ASSERT(g.IO.Fonts->Fonts[0]->IsLoaded()); // Font Atlas not created. Did you call io.Fonts->GetTexDataAsRGBA32 / GetTexDataAsAlpha8 ?
IM_ASSERT(g.Style.CurveTessellationTol > 0.0f); // Invalid
if (!g.Initialized)
{
@ -1903,7 +1912,7 @@ void ImGui::NewFrame()
bool mouse_owned_by_application = mouse_earliest_button_down != -1 && !g.IO.MouseDownOwned[mouse_earliest_button_down];
g.IO.WantCaptureMouse = (!mouse_owned_by_application && g.HoveredWindow != NULL) || (!mouse_owned_by_application && mouse_any_down) || (g.ActiveId != 0) || (!g.OpenedPopupStack.empty()) || (g.CaptureMouseNextFrame);
g.IO.WantCaptureKeyboard = (g.ActiveId != 0) || (g.CaptureKeyboardNextFrame);
g.IO.WantInputCharacters = (g.ActiveId != 0 && g.InputTextState.Id == g.ActiveId);
g.IO.WantTextInput = (g.ActiveId != 0 && g.InputTextState.Id == g.ActiveId);
g.MouseCursor = ImGuiMouseCursor_Arrow;
g.CaptureMouseNextFrame = g.CaptureKeyboardNextFrame = false;
@ -5074,13 +5083,14 @@ bool ImGui::SmallButton(const char* label)
// Tip: use ImGui::PushID()/PopID() to push indices or pointers in the ID stack.
// Then you can keep 'str_id' empty or the same for all your buttons (instead of creating a string based on a non-string id)
bool ImGui::InvisibleButton(const char* str_id, const ImVec2& size)
bool ImGui::InvisibleButton(const char* str_id, const ImVec2& size_arg)
{
ImGuiWindow* window = GetCurrentWindow();
if (window->SkipItems)
return false;
const ImGuiID id = window->GetID(str_id);
ImVec2 size = CalcItemSize(size_arg, 0.0f, 0.0f);
const ImRect bb(window->DC.CursorPos, window->DC.CursorPos + size);
ItemSize(bb);
if (!ItemAdd(bb, &id))
@ -5294,24 +5304,13 @@ void ImGui::LogButtons()
LogToClipboard(g.LogAutoExpandMaxDepth);
}
bool ImGui::CollapsingHeader(const char* label, const char* str_id, bool display_frame, bool default_open)
bool ImGui::TreeNodeBehaviorIsOpened(ImGuiID id, ImGuiTreeNodeFlags flags)
{
ImGuiWindow* window = GetCurrentWindow();
if (window->SkipItems)
return false;
ImGuiState& g = *GImGui;
const ImGuiStyle& style = g.Style;
IM_ASSERT(str_id != NULL || label != NULL);
if (str_id == NULL)
str_id = label;
if (label == NULL)
label = str_id;
const ImGuiID id = window->GetID(str_id);
// We only write to the tree storage if the user clicks (or explicitely use SetNextTreeNode*** functions)
ImGuiState& g = *GImGui;
ImGuiWindow* window = g.CurrentWindow;
ImGuiStorage* storage = window->DC.StateStorage;
bool opened;
if (g.SetNextTreeNodeOpenedCond != 0)
{
@ -5338,9 +5337,33 @@ bool ImGui::CollapsingHeader(const char* label, const char* str_id, bool display
}
else
{
opened = storage->GetInt(id, default_open) != 0;
opened = storage->GetInt(id, (flags & ImGuiTreeNodeFlags_DefaultOpen) ? 1 : 0) != 0;
}
// When logging is enabled, we automatically expand tree nodes (but *NOT* collapsing headers.. seems like sensible behavior).
// NB- If we are above max depth we still allow manually opened nodes to be logged.
if (g.LogEnabled && !(flags & ImGuiTreeNodeFlags_NoAutoExpandOnLog) && window->DC.TreeDepth < g.LogAutoExpandMaxDepth)
opened = true;
return opened;
}
bool ImGui::CollapsingHeader(const char* label, const char* str_id, bool display_frame, bool default_open)
{
ImGuiWindow* window = GetCurrentWindow();
if (window->SkipItems)
return false;
ImGuiState& g = *GImGui;
const ImGuiStyle& style = g.Style;
IM_ASSERT(str_id != NULL || label != NULL);
if (str_id == NULL)
str_id = label;
if (label == NULL)
label = str_id;
const ImGuiID id = window->GetID(str_id);
// Framed header expand a little outside the default padding
const ImVec2 window_padding = window->WindowPadding;
const ImVec2 label_size = CalcTextSize(label, NULL, true);
@ -5354,24 +5377,22 @@ bool ImGui::CollapsingHeader(const char* label, const char* str_id, bool display
bb.Max.y += style.FramePadding.y * 2;
}
// FIXME: we don't provide our width so that it doesn't get feed back into AutoFit. Should manage that better so we can still hover without extending ContentsSize
const ImRect text_bb(bb.Min, bb.Min + ImVec2(g.FontSize + style.FramePadding.x*2*2,0) + label_size);
const float collapser_width = g.FontSize + style.FramePadding.x*2;
const ImRect text_bb(bb.Min, bb.Min + ImVec2(collapser_width + style.FramePadding.x*2*0 + (label_size.x > 0.0f ? label_size.x : 0.0f), label_size.y));
ItemSize(ImVec2(text_bb.GetSize().x, bb.GetSize().y), display_frame ? style.FramePadding.y : 0.0f);
// When logging is enabled, if automatically expand tree nodes (but *NOT* collapsing headers.. seems like sensible behavior).
// NB- If we are above max depth we still allow manually opened nodes to be logged.
if (g.LogEnabled && !display_frame && window->DC.TreeDepth < g.LogAutoExpandMaxDepth)
opened = true;
const ImRect interact_bb = display_frame ? bb : ImRect(text_bb.Min, text_bb.Max + ImVec2(style.FramePadding.x*2,0.0f)); // FIXME
bool opened = TreeNodeBehaviorIsOpened(id, (default_open ? ImGuiTreeNodeFlags_DefaultOpen : 0) | (display_frame ? ImGuiTreeNodeFlags_NoAutoExpandOnLog : 0));
if (!ItemAdd(bb, &id))
if (!ItemAdd(interact_bb, &id))
return opened;
bool hovered, held;
bool pressed = ButtonBehavior(display_frame ? bb : text_bb, id, &hovered, &held, false);
bool pressed = ButtonBehavior(interact_bb, id, &hovered, &held, false);
if (pressed)
{
opened = !opened;
storage->SetInt(id, opened);
window->DC.StateStorage->SetInt(id, opened);
}
// Render
@ -5387,7 +5408,7 @@ bool ImGui::CollapsingHeader(const char* label, const char* str_id, bool display
const char log_prefix[] = "\n##";
LogRenderedText(bb.Min + style.FramePadding, log_prefix, log_prefix+3);
}
RenderTextClipped(bb.Min + style.FramePadding + ImVec2(g.FontSize + style.FramePadding.x*2,0), bb.Max, label, NULL, &label_size);
RenderTextClipped(bb.Min + style.FramePadding + ImVec2(collapser_width,0), bb.Max, label, NULL, &label_size);
if (g.LogEnabled)
{
const char log_suffix[] = "##";
@ -5402,7 +5423,7 @@ bool ImGui::CollapsingHeader(const char* label, const char* str_id, bool display
RenderCollapseTriangle(bb.Min + ImVec2(style.FramePadding.x, g.FontSize*0.15f), opened, 0.70f, false);
if (g.LogEnabled)
LogRenderedText(bb.Min, ">");
RenderText(bb.Min + ImVec2(g.FontSize + style.FramePadding.x*2,0), label);
RenderText(bb.Min + ImVec2(collapser_width,0), label);
}
return opened;

View file

@ -114,7 +114,7 @@ namespace ImGui
IMGUI_API void ShowMetricsWindow(bool* opened = NULL); // metrics window for debugging imgui
// Window
IMGUI_API bool Begin(const char* name = "Debug", bool* p_opened = NULL, ImGuiWindowFlags flags = 0); // see .cpp for details. return false when window is collapsed, so you can early out in your code. 'bool* p_opened' creates a widget on the upper-right to close the window (which sets your bool to false).
IMGUI_API bool Begin(const char* name, bool* p_opened = NULL, ImGuiWindowFlags flags = 0); // see .cpp for details. return false when window is collapsed, so you can early out in your code. 'bool* p_opened' creates a widget on the upper-right to close the window (which sets your bool to false).
IMGUI_API bool Begin(const char* name, bool* p_opened, const ImVec2& size_on_first_use, float bg_alpha = -1.0f, ImGuiWindowFlags flags = 0); // this is the older/longer API. call SetNextWindowSize() instead if you want to set a window size. For regular windows, 'size_on_first_use' only applies to the first time EVER the window is created and probably not what you want! maybe obsolete this API eventually.
IMGUI_API void End();
IMGUI_API bool BeginChild(const char* str_id, const ImVec2& size = ImVec2(0,0), bool border = false, ImGuiWindowFlags extra_flags = 0); // begin a scrolling region. size==0.0f: use remaining window size, size<0.0f: use remaining window size minus abs(size). size>0.0f: fixed size. each axis can use a different mode, e.g. ImVec2(0,400).
@ -294,7 +294,7 @@ namespace ImGui
IMGUI_API bool VSliderInt(const char* label, const ImVec2& size, int* v, int v_min, int v_max, const char* display_format = "%.0f");
// Widgets: Trees
IMGUI_API bool TreeNode(const char* str_label_id); // if returning 'true' the node is open and the user is responsible for calling TreePop
IMGUI_API bool TreeNode(const char* str_label_id); // if returning 'true' the node is open and the user is responsible for calling TreePop()
IMGUI_API bool TreeNode(const char* str_id, const char* fmt, ...) IM_PRINTFARGS(2); // "
IMGUI_API bool TreeNode(const void* ptr_id, const char* fmt, ...) IM_PRINTFARGS(2); // "
IMGUI_API bool TreeNodeV(const char* str_id, const char* fmt, va_list args); // "
@ -381,6 +381,7 @@ namespace ImGui
IMGUI_API bool BeginChildFrame(ImGuiID id, const ImVec2& size); // helper to create a child window / scrolling region that looks like a normal widget frame
IMGUI_API void EndChildFrame();
IMGUI_API ImVec4 ColorConvertU32ToFloat4(ImU32 in);
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);
@ -646,6 +647,7 @@ struct ImGuiStyle
ImVec2 DisplaySafeAreaPadding; // If you cannot see the edge of your screen (e.g. on a TV) increase the safe area padding. Covers popups/tooltips as well regular windows.
bool AntiAliasedLines; // Enable anti-aliasing on lines/borders. Disable if you are really tight on CPU/GPU.
bool AntiAliasedShapes; // Enable anti-aliasing on filled shapes (rounded rectangles, circles, etc.)
float CurveTessellationTol; // Tessellation tolerance. Decrease for highly tessellated curves (higher quality, more polygons), increase to reduce quality.
ImVec4 Colors[ImGuiCol_COUNT];
IMGUI_API ImGuiStyle();
@ -675,6 +677,7 @@ 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 DisplayFramebufferScale; // = (1.0f,1.0f) // For retina display or other situations where window coordinates are different from framebuffer coordinates. User storage only, presently not used by ImGui.
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
@ -725,7 +728,7 @@ struct ImGuiIO
bool WantCaptureMouse; // Mouse is hovering a window or widget is active (= ImGui will use your mouse input)
bool WantCaptureKeyboard; // Widget is active (= ImGui will use your keyboard input)
bool WantInputCharacters; // Some text input widget is active, which will read input characters from the InputCharacters array.
bool WantTextInput; // Some text input widget is active, which will read input characters from the InputCharacters array.
float Framerate; // Framerate estimation, in frame per second. Rolling average estimation based on IO.DeltaTime over 120 frames
int MetricsAllocs; // Number of active memory allocations
int MetricsRenderVertices; // Vertices output during last call to Render()
@ -950,7 +953,8 @@ struct ImColor
{
ImVec4 Value;
ImColor(int r, int g, int b, int a = 255) { Value.x = (float)r / 255.0f; Value.y = (float)g / 255.0f; Value.z = (float)b / 255.0f; Value.w = (float)a / 255.0f; }
ImColor(int r, int g, int b, int a = 255) { float sc = 1.0f/255.0f; Value.x = (float)r * sc; Value.y = (float)g * sc; Value.z = (float)b * sc; Value.w = (float)a * sc; }
ImColor(ImU32 rgba) { float sc = 1.0f/255.0f; Value.x = (float)(rgba&0xFF) * sc; Value.y = (float)((rgba>>8)&0xFF) * sc; Value.z = (float)((rgba>>16)&0xFF) * sc; Value.w = (float)(rgba >> 24) * sc; }
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); }
@ -1097,15 +1101,18 @@ struct ImDrawList
IMGUI_API void AddImage(ImTextureID user_texture_id, const ImVec2& a, const ImVec2& b, const ImVec2& uv0, const ImVec2& uv1, ImU32 col = 0xFFFFFFFF);
IMGUI_API void AddPolyline(const ImVec2* points, const int num_points, ImU32 col, bool closed, float thickness, bool anti_aliased);
IMGUI_API void AddConvexPolyFilled(const ImVec2* points, const int num_points, ImU32 col, bool anti_aliased);
IMGUI_API void AddBezierCurve(const ImVec2& pos0, const ImVec2& cp0, const ImVec2& cp1, const ImVec2& pos1, ImU32 col, float thickness, int num_segments = 0);
// Stateful path API, add points then finish with PathFill() or PathStroke()
inline void PathClear() { _Path.resize(0); }
inline void PathLineTo(const ImVec2& p) { _Path.push_back(p); }
IMGUI_API void PathArcTo(const ImVec2& centre, float radius, float a_min, float a_max, int num_segments = 10);
IMGUI_API void PathArcToFast(const ImVec2& centre, float radius, int a_min_of_12, int a_max_of_12);
IMGUI_API void PathRect(const ImVec2& a, const ImVec2& b, float rounding = 0.0f, int rounding_corners = 0x0F);
inline void PathLineTo(const ImVec2& pos) { _Path.push_back(pos); }
inline void PathLineToMergeDuplicate(const ImVec2& pos) { if (_Path.Size == 0 || _Path[_Path.Size-1].x != pos.x || _Path[_Path.Size-1].y != pos.y) _Path.push_back(pos); }
inline void PathFill(ImU32 col) { AddConvexPolyFilled(_Path.Data, _Path.Size, col, true); PathClear(); }
inline void PathStroke(ImU32 col, bool closed, float thickness = 1.0f) { AddPolyline(_Path.Data, _Path.Size, col, closed, thickness, true); PathClear(); }
inline void PathStroke(ImU32 col, bool closed, float thickness = 1.0f) { AddPolyline(_Path.Data, _Path.Size, col, closed, thickness, true); PathClear(); }
IMGUI_API void PathArcTo(const ImVec2& centre, float radius, float a_min, float a_max, int num_segments = 10);
IMGUI_API void PathArcToFast(const ImVec2& centre, float radius, int a_min_of_12, int a_max_of_12); // Use precomputed angles for a 12 steps circle
IMGUI_API void PathBezierCurveTo(const ImVec2& p1, const ImVec2& p2, const ImVec2& p3, int num_segments = 0);
IMGUI_API void PathRect(const ImVec2& rect_min, const ImVec2& rect_max, float rounding = 0.0f, int rounding_corners = 0x0F);
// Channels
// - Use to simulate layers. By switching channels to can render out-of-order (e.g. submit foreground primitives before background primitives)
@ -1140,6 +1147,7 @@ struct ImDrawData
// Functions
void DeIndexAllBuffers(); // For backward compatibility: convert all buffers from indexed to de-indexed, in case you cannot render indexed. Note: this is slow and most likely a waste of resources. Always prefer indexed rendering!
void ScaleClipRects(const ImVec2& sc); // Helper to scale the ClipRect field of each ImDrawCmd. Use if your final output buffer is at a different scale than ImGui expects, or if there is a difference between your window resolution and framebuffer resolution.
};
struct ImFontConfig

View file

@ -827,7 +827,7 @@ void ImGui::ShowTestWindow(bool* opened)
if (ImGui::TreeNode("Groups"))
{
ImGui::TextWrapped("(Using ImGui::BeginGroup()/EndGroup() to layout items)");
ImGui::TextWrapped("(Using ImGui::BeginGroup()/EndGroup() to layout items. BeginGroup() basically locks the horizontal position. EndGroup() bundled the whole group so that you can use functions such as IsItemHovered() on it.)");
ImGui::BeginGroup();
{
ImGui::BeginGroup();
@ -903,7 +903,7 @@ void ImGui::ShowTestWindow(bool* opened)
if (ImGui::TreeNode("Scrolling"))
{
ImGui::TextWrapped("Use SetScrollHere() or SetScrollFromPosY() to scroll to a given position.");
ImGui::TextWrapped("(Use SetScrollHere() or SetScrollFromPosY() to scroll to a given position.)");
static bool track = true;
static int track_line = 50, scroll_to_px = 200;
ImGui::Checkbox("Track", &track);
@ -1343,7 +1343,7 @@ void ImGui::ShowTestWindow(bool* opened)
ImGui::Text("WantCaptureMouse: %s", io.WantCaptureMouse ? "true" : "false");
ImGui::Text("WantCaptureKeyboard: %s", io.WantCaptureKeyboard ? "true" : "false");
ImGui::Text("WantInputCharacters: %s", io.WantInputCharacters ? "true" : "false");
ImGui::Text("WantTextInput: %s", io.WantTextInput ? "true" : "false");
ImGui::Button("Hover me\nto enforce\ninputs capture");
if (ImGui::IsItemHovered())
@ -1392,6 +1392,10 @@ void ImGui::ShowStyleEditor(ImGuiStyle* ref)
{
ImGui::Checkbox("Anti-aliased lines", &style.AntiAliasedLines);
ImGui::Checkbox("Anti-aliased shapes", &style.AntiAliasedShapes);
ImGui::PushItemWidth(100);
ImGui::DragFloat("Curve Tessellation Tolerance", &style.CurveTessellationTol, 0.02f, 0.10f, FLT_MAX, NULL, 2.0f);
if (style.CurveTessellationTol < 0.0f) style.CurveTessellationTol = 0.10f;
ImGui::PopItemWidth();
ImGui::TreePop();
}
@ -1641,6 +1645,9 @@ static void ShowExampleAppCustomRendering(bool* opened)
if (canvas_size.y < 50.0f) canvas_size.y = 50.0f;
draw_list->AddRectFilledMultiColor(canvas_pos, ImVec2(canvas_pos.x + canvas_size.x, canvas_pos.y + canvas_size.y), ImColor(0,0,0), ImColor(255,0,0), ImColor(255,255,0), ImColor(0,255,0));
draw_list->AddRect(canvas_pos, ImVec2(canvas_pos.x + canvas_size.x, canvas_pos.y + canvas_size.y), ImColor(255,255,255));
draw_list->AddBezierCurve(ImVec2(canvas_pos.x+20,canvas_pos.y+20), ImVec2(canvas_pos.x+100,canvas_pos.y+20), ImVec2(canvas_pos.x+canvas_size.x-100,canvas_pos.y+canvas_size.y-20), ImVec2(canvas_pos.x+canvas_size.x-20,canvas_pos.y+canvas_size.y-20), ImColor(255,200,0), 5.0f);
bool adding_preview = false;
ImGui::InvisibleButton("canvas", canvas_size);
if (ImGui::IsItemHovered())
@ -1667,7 +1674,7 @@ static void ShowExampleAppCustomRendering(bool* opened)
}
draw_list->PushClipRect(ImVec4(canvas_pos.x, canvas_pos.y, canvas_pos.x+canvas_size.x, canvas_pos.y+canvas_size.y)); // clip lines within the canvas (if we resize it, etc.)
for (int i = 0; i < points.Size - 1; i += 2)
draw_list->AddLine(ImVec2(canvas_pos.x + points[i].x, canvas_pos.y + points[i].y), ImVec2(canvas_pos.x + points[i+1].x, canvas_pos.y + points[i+1].y), 0xFF00FFFF);
draw_list->AddLine(ImVec2(canvas_pos.x + points[i].x, canvas_pos.y + points[i].y), ImVec2(canvas_pos.x + points[i+1].x, canvas_pos.y + points[i+1].y), 0xFF00FFFF, 2.0f);
draw_list->PopClipRect();
if (adding_preview)
points.pop_back();

View file

@ -639,6 +639,56 @@ void ImDrawList::PathArcTo(const ImVec2& centre, float radius, float amin, float
}
}
static void PathBezierToCasteljau(ImVector<ImVec2>* path, float x1, float y1, float x2, float y2, float x3, float y3, float x4, float y4, float tess_tol, int level)
{
float dx = x4 - x1;
float dy = y4 - y1;
float d2 = ((x2 - x4) * dy - (y2 - y4) * dx);
float d3 = ((x3 - x4) * dy - (y3 - y4) * dx);
d2 = (d2 >= 0) ? d2 : -d2;
d3 = (d3 >= 0) ? d3 : -d3;
if ((d2+d3) * (d2+d3) < tess_tol * (dx*dx + dy*dy))
{
path->push_back(ImVec2(x4, y4));
}
else if (level < 10)
{
float x12 = (x1+x2)*0.5f, y12 = (y1+y2)*0.5f;
float x23 = (x2+x3)*0.5f, y23 = (y2+y3)*0.5f;
float x34 = (x3+x4)*0.5f, y34 = (y3+y4)*0.5f;
float x123 = (x12+x23)*0.5f, y123 = (y12+y23)*0.5f;
float x234 = (x23+x34)*0.5f, y234 = (y23+y34)*0.5f;
float x1234 = (x123+x234)*0.5f, y1234 = (y123+y234)*0.5f;
PathBezierToCasteljau(path, x1,y1, x12,y12, x123,y123, x1234,y1234, tess_tol, level+1);
PathBezierToCasteljau(path, x1234,y1234, x234,y234, x34,y34, x4,y4, tess_tol, level+1);
}
}
void ImDrawList::PathBezierCurveTo(const ImVec2& p2, const ImVec2& p3, const ImVec2& p4, int num_segments)
{
ImVec2 p1 = _Path.back();
if (num_segments == 0)
{
// Auto-tessellated
PathBezierToCasteljau(&_Path, p1.x, p1.y, p2.x, p2.y, p3.x, p3.y, p4.x, p4.y, GImGui->Style.CurveTessellationTol, 0);
}
else
{
float t_step = 1.0f / (float)num_segments;
for (int i_step = 1; i_step <= num_segments; i_step++)
{
float t = t_step * i_step;
float u = 1.0f - t;
float w1 = u*u*u;
float w2 = 3*u*u*t;
float w3 = 3*u*t*t;
float w4 = t*t*t;
_Path.push_back(ImVec2(w1*p1.x + w2*p2.x + w3*p3.x + w4*p4.x, w1*p1.y + w2*p2.y + w3*p3.y + w4*p4.y));
}
}
}
void ImDrawList::PathRect(const ImVec2& a, const ImVec2& b, float rounding, int rounding_corners)
{
float r = rounding;
@ -743,6 +793,16 @@ void ImDrawList::AddCircleFilled(const ImVec2& centre, float radius, ImU32 col,
PathFill(col);
}
void ImDrawList::AddBezierCurve(const ImVec2& pos0, const ImVec2& cp0, const ImVec2& cp1, const ImVec2& pos1, ImU32 col, float thickness, int num_segments)
{
if ((col >> 24) == 0)
return;
PathLineTo(pos0);
PathBezierCurveTo(cp0, cp1, pos1, num_segments);
PathStroke(col, false, thickness);
}
void ImDrawList::AddText(const ImFont* font, float font_size, const ImVec2& pos, ImU32 col, const char* text_begin, const char* text_end, float wrap_width, const ImVec4* cpu_fine_clip_rect)
{
if ((col >> 24) == 0)
@ -833,6 +893,20 @@ void ImDrawData::DeIndexAllBuffers()
}
}
// Helper to scale the ClipRect field of each ImDrawCmd. Use if your final output buffer is at a different scale than ImGui expects, or if there is a difference between your window resolution and framebuffer resolution.
void ImDrawData::ScaleClipRects(const ImVec2& scale)
{
for (int i = 0; i < CmdListsCount; i++)
{
ImDrawList* cmd_list = CmdLists[i];
for (int cmd_i = 0; cmd_i < cmd_list->CmdBuffer.Size; cmd_i++)
{
ImDrawCmd* cmd = &cmd_list->CmdBuffer[cmd_i];
cmd->ClipRect = ImVec4(cmd->ClipRect.x * scale.x, cmd->ClipRect.y * scale.y, cmd->ClipRect.z * scale.x, cmd->ClipRect.w * scale.y);
}
}
}
//-----------------------------------------------------------------------------
// ImFontAtlias
//-----------------------------------------------------------------------------

View file

@ -33,6 +33,7 @@ struct ImGuiWindow;
typedef int ImGuiLayoutType; // enum ImGuiLayoutType_
typedef int ImGuiButtonFlags; // enum ImGuiButtonFlags_
typedef int ImGuiTreeNodeFlags; // enum ImGuiTreeNodeFlags_
//-------------------------------------------------------------------------
// STB libraries
@ -144,6 +145,12 @@ enum ImGuiButtonFlags_
ImGuiButtonFlags_AlignTextBaseLine = 1 << 6
};
enum ImGuiTreeNodeFlags_
{
ImGuiTreeNodeFlags_DefaultOpen = 1 << 0,
ImGuiTreeNodeFlags_NoAutoExpandOnLog = 1 << 1
};
enum ImGuiSelectableFlagsPrivate_
{
// NB: need to be in sync with last value of ImGuiSelectableFlags_
@ -636,6 +643,7 @@ namespace ImGui
IMGUI_API ImVec2 CalcItemSize(ImVec2 size, float default_x, float default_y);
IMGUI_API float CalcWrapWidthForPos(const ImVec2& pos, float wrap_pos_x);
// NB: All position are in absolute pixels coordinates (not window coordinates)
IMGUI_API void RenderText(ImVec2 pos, const char* text, const char* text_end = NULL, bool hide_text_after_hash = true);
IMGUI_API void RenderTextWrapped(ImVec2 pos, const char* text, const char* text_end, float wrap_width);
IMGUI_API void RenderTextClipped(const ImVec2& pos_min, const ImVec2& pos_max, const char* text, const char* text_end, const ImVec2* text_size_if_known, ImGuiAlign align = ImGuiAlign_Default, const ImVec2* clip_min = NULL, const ImVec2* clip_max = NULL);
@ -660,6 +668,8 @@ namespace ImGui
IMGUI_API bool InputScalarEx(const char* label, ImGuiDataType data_type, void* data_ptr, void* step_ptr, void* step_fast_ptr, const char* scalar_format, ImGuiInputTextFlags extra_flags);
IMGUI_API bool InputScalarAsWidgetReplacement(const ImRect& aabb, const char* label, ImGuiDataType data_type, void* data_ptr, ImGuiID id, int decimal_precision);
IMGUI_API bool TreeNodeBehaviorIsOpened(ImGuiID id, ImGuiTreeNodeFlags flags = 0); // Consume previous SetNextTreeNodeOpened() data, if any. May return true when logging
IMGUI_API void PlotEx(ImGuiPlotType plot_type, const char* label, float (*values_getter)(void* data, int idx), void* data, int values_count, int values_offset, const char* overlay_text, float scale_min, float scale_max, ImVec2 graph_size);
IMGUI_API int ParseFormatPrecision(const char* fmt, int default_value);