Updated ImGui.

This commit is contained in:
Branimir Karadžić 2015-10-19 18:12:08 -07:00
parent b6ae6fda61
commit 64d3c7884d
5 changed files with 118 additions and 86 deletions

View file

@ -1,4 +1,4 @@
// ImGui library v1.46 WIP
// ImGui library v1.47 WIP
// Main code & documentation
// See ImGui::ShowTestWindow() in imgui_demo.cpp for demo code.
@ -665,7 +665,7 @@ ImGuiStyle::ImGuiStyle()
Colors[ImGuiCol_TitleBgCollapsed] = ImVec4(0.40f, 0.40f, 0.80f, 0.20f);
Colors[ImGuiCol_TitleBgActive] = ImVec4(0.50f, 0.50f, 1.00f, 0.55f);
Colors[ImGuiCol_MenuBarBg] = ImVec4(0.40f, 0.40f, 0.55f, 0.80f);
Colors[ImGuiCol_ScrollbarBg] = ImVec4(0.40f, 0.40f, 0.80f, 0.15f);
Colors[ImGuiCol_ScrollbarBg] = ImVec4(0.20f, 0.25f, 0.30f, 0.60f);
Colors[ImGuiCol_ScrollbarGrab] = ImVec4(0.40f, 0.40f, 0.80f, 0.30f);
Colors[ImGuiCol_ScrollbarGrabHovered] = ImVec4(0.40f, 0.40f, 0.80f, 0.40f);
Colors[ImGuiCol_ScrollbarGrabActive] = ImVec4(0.80f, 0.50f, 0.50f, 0.40f);
@ -761,6 +761,8 @@ void ImGuiIO::AddInputCharactersUTF8(const char* utf8_chars)
// HELPERS
//-----------------------------------------------------------------------------
#define IM_F32_TO_INT8(_VAL) ((int)((_VAL) * 255.0f + 0.5f))
#define IM_INT_MIN (-2147483647-1)
#define IM_INT_MAX (2147483647)
@ -1083,10 +1085,11 @@ ImVec4 ImGui::ColorConvertU32ToFloat4(ImU32 in)
ImU32 ImGui::ColorConvertFloat4ToU32(const ImVec4& in)
{
ImU32 out = ((ImU32)(ImSaturate(in.x)*255.f));
out |= ((ImU32)(ImSaturate(in.y)*255.f) << 8);
out |= ((ImU32)(ImSaturate(in.z)*255.f) << 16);
out |= ((ImU32)(ImSaturate(in.w)*255.f) << 24);
ImU32 out;
out = ((ImU32)IM_F32_TO_INT8(ImSaturate(in.x)));
out |= ((ImU32)IM_F32_TO_INT8(ImSaturate(in.y))) << 8;
out |= ((ImU32)IM_F32_TO_INT8(ImSaturate(in.z))) << 16;
out |= ((ImU32)IM_F32_TO_INT8(ImSaturate(in.w))) << 24;
return out;
}
@ -1524,7 +1527,7 @@ ImGuiWindow::ImGuiWindow(const char* name)
SetWindowPosAllowFlags = SetWindowSizeAllowFlags = SetWindowCollapsedAllowFlags = ImGuiSetCond_Always | ImGuiSetCond_Once | ImGuiSetCond_FirstUseEver | ImGuiSetCond_Appearing;
SetWindowPosCenterWanted = false;
LastFrameDrawn = -1;
LastFrameActive = -1;
ItemWidthDefault = 0.0f;
FontWindowScale = 1.0f;
@ -3495,7 +3498,7 @@ bool ImGui::Begin(const char* name, bool* p_opened, const ImVec2& size_on_first_
}
const int current_frame = ImGui::GetFrameCount();
const bool first_begin_of_the_frame = (window->LastFrameDrawn != current_frame);
const bool first_begin_of_the_frame = (window->LastFrameActive != current_frame);
if (first_begin_of_the_frame)
window->Flags = (ImGuiWindowFlags)flags;
else
@ -3508,23 +3511,25 @@ bool ImGui::Begin(const char* name, bool* p_opened, const ImVec2& size_on_first_
CheckStacksSize(window, true);
IM_ASSERT(parent_window != NULL || !(flags & ImGuiWindowFlags_ChildWindow));
bool window_was_visible = (window->LastFrameDrawn == current_frame - 1); // Not using !WasActive because the implicit "Debug" window would always toggle off->on
bool window_was_active = (window->LastFrameActive == current_frame - 1); // Not using !WasActive because the implicit "Debug" window would always toggle off->on
if (flags & ImGuiWindowFlags_Popup)
{
ImGuiPopupRef& popup_ref = g.OpenedPopupStack[g.CurrentPopupStack.Size];
window_was_visible &= (window->PopupID == popup_ref.PopupID);
window_was_visible &= (window == popup_ref.Window);
window_was_active &= (window->PopupID == popup_ref.PopupID);
window_was_active &= (window == popup_ref.Window);
popup_ref.Window = window;
g.CurrentPopupStack.push_back(popup_ref);
window->PopupID = popup_ref.PopupID;
}
const bool window_appearing_after_being_hidden = (window->HiddenFrames == 1);
// Process SetNextWindow***() calls
bool window_pos_set_by_api = false, window_size_set_by_api = false;
if (g.SetNextWindowPosCond)
{
const ImVec2 backup_cursor_pos = window->DC.CursorPos; // FIXME: not sure of the exact reason of this anymore :( need to look into that.
if (!window_was_visible) window->SetWindowPosAllowFlags |= ImGuiSetCond_Appearing;
if (!window_was_active || window_appearing_after_being_hidden) window->SetWindowPosAllowFlags |= ImGuiSetCond_Appearing;
window_pos_set_by_api = (window->SetWindowPosAllowFlags & g.SetNextWindowPosCond) != 0;
if (window_pos_set_by_api && ImLengthSqr(g.SetNextWindowPosVal - ImVec2(-FLT_MAX,-FLT_MAX)) < 0.001f)
{
@ -3533,16 +3538,16 @@ bool ImGui::Begin(const char* name, bool* p_opened, const ImVec2& size_on_first_
}
else
{
ImGui::SetWindowPos(g.SetNextWindowPosVal, g.SetNextWindowPosCond);
SetWindowPos(window, g.SetNextWindowPosVal, g.SetNextWindowPosCond);
}
window->DC.CursorPos = backup_cursor_pos;
g.SetNextWindowPosCond = 0;
}
if (g.SetNextWindowSizeCond)
{
if (!window_was_visible) window->SetWindowSizeAllowFlags |= ImGuiSetCond_Appearing;
if (!window_was_active || window_appearing_after_being_hidden) window->SetWindowSizeAllowFlags |= ImGuiSetCond_Appearing;
window_size_set_by_api = (window->SetWindowSizeAllowFlags & g.SetNextWindowSizeCond) != 0;
ImGui::SetWindowSize(g.SetNextWindowSizeVal, g.SetNextWindowSizeCond);
SetWindowSize(window, g.SetNextWindowSizeVal, g.SetNextWindowSizeCond);
g.SetNextWindowSizeCond = 0;
}
if (g.SetNextWindowContentSizeCond)
@ -3556,8 +3561,8 @@ bool ImGui::Begin(const char* name, bool* p_opened, const ImVec2& size_on_first_
}
if (g.SetNextWindowCollapsedCond)
{
if (!window_was_visible) window->SetWindowCollapsedAllowFlags |= ImGuiSetCond_Appearing;
ImGui::SetWindowCollapsed(g.SetNextWindowCollapsedVal, g.SetNextWindowCollapsedCond);
if (!window_was_active || window_appearing_after_being_hidden) window->SetWindowCollapsedAllowFlags |= ImGuiSetCond_Appearing;
SetWindowCollapsed(window, g.SetNextWindowCollapsedVal, g.SetNextWindowCollapsedCond);
g.SetNextWindowCollapsedCond = 0;
}
if (g.SetNextWindowFocus)
@ -3588,7 +3593,7 @@ bool ImGui::Begin(const char* name, bool* p_opened, const ImVec2& size_on_first_
window->BeginCount = 0;
window->DrawList->Clear();
window->ClipRect = ImVec4(-FLT_MAX,-FLT_MAX,+FLT_MAX,+FLT_MAX);
window->LastFrameDrawn = current_frame;
window->LastFrameActive = current_frame;
window->IDStack.resize(1);
// Setup texture, outer clipping rectangle
@ -3599,7 +3604,7 @@ bool ImGui::Begin(const char* name, bool* p_opened, const ImVec2& size_on_first_
PushClipRect(GetVisibleRect());
// New windows appears in front
if (!window_was_visible)
if (!window_was_active)
{
window->AutoPosLastDirection = -1;
@ -3630,10 +3635,6 @@ bool ImGui::Begin(const char* name, bool* p_opened, const ImVec2& size_on_first_
window->Collapsed = false;
}
const bool window_appearing_after_being_hidden = (window->HiddenFrames == 1);
if (window->HiddenFrames > 0)
window->HiddenFrames--;
// SIZE
// Save contents size from last frame for auto-fitting (unless explicitly specified)
@ -3641,7 +3642,9 @@ bool ImGui::Begin(const char* name, bool* p_opened, const ImVec2& size_on_first_
window->SizeContents.y = (window->SizeContentsExplicit.y != 0.0f) ? window->SizeContentsExplicit.y : ((window_is_new ? 0.0f : window->DC.CursorMaxPos.y - window->Pos.y) + window->Scroll.y);
// Hide popup/tooltip window when first appearing while we measure size (because we recycle them)
if ((flags & (ImGuiWindowFlags_Popup | ImGuiWindowFlags_Tooltip)) != 0 && !window_was_visible)
if (window->HiddenFrames > 0)
window->HiddenFrames--;
if ((flags & (ImGuiWindowFlags_Popup | ImGuiWindowFlags_Tooltip)) != 0 && !window_was_active)
{
window->HiddenFrames = 1;
if (flags & ImGuiWindowFlags_AlwaysAutoResize)
@ -3961,7 +3964,7 @@ bool ImGui::Begin(const char* name, bool* p_opened, const ImVec2& size_on_first_
window->DC.TreeDepth = 0;
window->DC.StateStorage = &window->StateStorage;
window->DC.GroupStack.resize(0);
window->MenuColumns.Update(3, style.ItemSpacing.x, !window_was_visible);
window->MenuColumns.Update(3, style.ItemSpacing.x, !window_was_active);
if (window->AutoFitFramesX > 0)
window->AutoFitFramesX--;
@ -4081,7 +4084,9 @@ static void Scrollbar(ImGuiWindow* window, bool horizontal)
const float border_offset = (window->Flags & ImGuiWindowFlags_ShowBorders) ? 1.0f : 0.0f;
ImRect bb = horizontal
? ImRect(window->Pos.x + border_offset, window_rect.Max.y - style.ScrollbarSize, window_rect.Max.x - other_scrollbar_size_w, window_rect.Max.y)
: ImRect(window_rect.Max.x - style.ScrollbarSize, window->Pos.y + window->TitleBarHeight() + border_offset, window_rect.Max.x, window_rect.Max.y - other_scrollbar_size_w);
: ImRect(window_rect.Max.x - style.ScrollbarSize, window->Pos.y + border_offset, window_rect.Max.x, window_rect.Max.y - other_scrollbar_size_w);
if (!horizontal)
bb.Min.y += window->TitleBarHeight() + ((window->Flags & ImGuiWindowFlags_MenuBar) ? window->MenuBarHeight() - border_offset : 0.0f);
float window_rounding = (window->Flags & ImGuiWindowFlags_ChildWindow) ? style.ChildWindowRounding : style.WindowRounding;
int window_rounding_corners;
@ -7087,6 +7092,7 @@ static bool InputTextFilterCharacter(unsigned int* p_char, ImGuiInputTextFlags f
}
// Edit a string of text
// FIXME: This is rather complex partly because we are doing UTF8 > u16 > UTF8 conversions on the go to more easily handle stb_textedit calls. Ideally we should stay in UTF-8 all the time.
bool ImGui::InputTextEx(const char* label, char* buf, int buf_size, const ImVec2& size_arg, ImGuiInputTextFlags flags, ImGuiTextEditCallback callback, void* user_data)
{
ImGuiWindow* window = GetCurrentWindow();
@ -7174,9 +7180,7 @@ bool ImGui::InputTextEx(const char* label, char* buf, int buf_size, const ImVec2
{
// Recycle existing cursor/selection/undo stack but clamp position
// Note a single mouse click will override the cursor/position immediately by calling stb_textedit_click handler.
edit_state.StbState.cursor = ImMin(edit_state.StbState.cursor, edit_state.CurLenW);
edit_state.StbState.select_start = ImMin(edit_state.StbState.select_start, edit_state.CurLenW);
edit_state.StbState.select_end = ImMin(edit_state.StbState.select_end, edit_state.CurLenW);
edit_state.CursorClamp();
}
else
{
@ -7207,6 +7211,16 @@ bool ImGui::InputTextEx(const char* label, char* buf, int buf_size, const ImVec2
if (g.ActiveId == id)
{
if (!is_editable && !g.ActiveIdIsJustActivated)
{
// When read-only we always use the live data passed to the function
edit_state.Text.resize(buf_size+1);
const char* buf_end = NULL;
edit_state.CurLenW = ImTextStrFromUtf8(edit_state.Text.Data, edit_state.Text.Size, buf, NULL, &buf_end);
edit_state.CurLenA = (int)(buf_end - buf);
edit_state.CursorClamp();
}
edit_state.BufSizeA = buf_size;
// Although we are active we don't prevent mouse from hovering other elements unless we are interacting right now with the widget.
@ -7256,6 +7270,7 @@ bool ImGui::InputTextEx(const char* label, char* buf, int buf_size, const ImVec2
memset(g.IO.InputCharacters, 0, sizeof(g.IO.InputCharacters));
}
// Handle various key-presses
const int k_mask = (is_shift_down ? STB_TEXTEDIT_K_SHIFT : 0);
const bool is_ctrl_only = is_ctrl_down && !is_alt_down && !is_shift_down;
if (IsKeyPressedMap(ImGuiKey_LeftArrow)) { edit_state.OnKeyPressed(is_ctrl_down ? STB_TEXTEDIT_K_WORDLEFT | k_mask : STB_TEXTEDIT_K_LEFT | k_mask); }
@ -7264,8 +7279,8 @@ bool ImGui::InputTextEx(const char* label, char* buf, int buf_size, const ImVec2
else if (is_multiline && IsKeyPressedMap(ImGuiKey_DownArrow)) { if (is_ctrl_down) SetWindowScrollY(draw_window, draw_window->Scroll.y + g.FontSize); else edit_state.OnKeyPressed(STB_TEXTEDIT_K_DOWN| k_mask); }
else if (IsKeyPressedMap(ImGuiKey_Home)) { edit_state.OnKeyPressed(is_ctrl_down ? STB_TEXTEDIT_K_TEXTSTART | k_mask : STB_TEXTEDIT_K_LINESTART | k_mask); }
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) && is_editable) { edit_state.OnKeyPressed(STB_TEXTEDIT_K_DELETE | k_mask); }
else if (IsKeyPressedMap(ImGuiKey_Backspace) && is_editable) { edit_state.OnKeyPressed(STB_TEXTEDIT_K_BACKSPACE | k_mask); }
else if (IsKeyPressedMap(ImGuiKey_Delete) && is_editable) { edit_state.OnKeyPressed(STB_TEXTEDIT_K_DELETE | k_mask); }
else if (IsKeyPressedMap(ImGuiKey_Backspace) && is_editable) { edit_state.OnKeyPressed(STB_TEXTEDIT_K_BACKSPACE | k_mask); }
else if (IsKeyPressedMap(ImGuiKey_Enter))
{
bool ctrl_enter_for_new_line = (flags & ImGuiInputTextFlags_CtrlEnterForNewLine) != 0;
@ -7274,16 +7289,16 @@ bool ImGui::InputTextEx(const char* label, char* buf, int buf_size, const ImVec2
SetActiveID(0);
enter_pressed = true;
}
else if (is_editable) // New line
else if (is_editable)
{
unsigned int c = '\n';
unsigned int c = '\n'; // Insert new line
if (InputTextFilterCharacter(&c, flags, callback, user_data))
edit_state.OnKeyPressed((int)c);
}
}
else if ((flags & ImGuiInputTextFlags_AllowTabInput) && IsKeyPressedMap(ImGuiKey_Tab) && !is_ctrl_down && !is_shift_down && !is_alt_down && is_editable)
{
unsigned int c = '\t';
unsigned int c = '\t'; // Insert TAB
if (InputTextFilterCharacter(&c, flags, callback, user_data))
edit_state.OnKeyPressed((int)c);
}
@ -7358,7 +7373,7 @@ bool ImGui::InputTextEx(const char* label, char* buf, int buf_size, const ImVec2
{
// Apply new value immediately - copy modified buffer back
// Note that as soon as we can focus into the input box, the in-widget value gets priority over any underlying modification of the input buffer
// FIXME: We actually always render 'buf' in RenderTextScrolledClipped
// FIXME: We actually always render 'buf' when calling DrawList->AddText
// FIXME-OPT: CPU waste to do this every time the widget is active, should mark dirty state from the stb_textedit callbacks
if (is_editable)
{
@ -7428,6 +7443,7 @@ bool ImGui::InputTextEx(const char* label, char* buf, int buf_size, const ImVec2
}
}
// Copy back to user buffer
if (is_editable && strcmp(edit_state.TempTextBuffer.Data, buf) != 0)
{
ImFormatString(buf, buf_size, "%s", edit_state.TempTextBuffer.Data);
@ -7439,9 +7455,9 @@ bool ImGui::InputTextEx(const char* label, char* buf, int buf_size, const ImVec2
if (!is_multiline)
RenderFrame(frame_bb.Min, frame_bb.Max, window->Color(ImGuiCol_FrameBg), true, style.FrameRounding);
// Render
const ImVec4 clip_rect(frame_bb.Min.x, frame_bb.Min.y, frame_bb.Min.x + size.x + style.FramePadding.x*2.0f, frame_bb.Min.y + size.y + style.FramePadding.y*2.0f);
ImVec2 render_pos = is_multiline ? draw_window->DC.CursorPos : frame_bb.Min + style.FramePadding;
ImVec4 clip_rect(frame_bb.Min.x, frame_bb.Min.y, frame_bb.Min.x + size.x + style.FramePadding.x*2.0f, frame_bb.Min.y + size.y + style.FramePadding.y*2.0f);
ImVec2 text_size(0.f, 0.f);
if (g.ActiveId == id || (edit_state.Id == id && is_multiline && g.ActiveId == draw_window->GetID("#SCROLLY")))
{
@ -7453,40 +7469,44 @@ bool ImGui::InputTextEx(const char* label, char* buf, int buf_size, const ImVec2
// - Measure text height (for scrollbar)
// We are attempting to do most of that in **one main pass** to minimize the computation cost (non-negligible for large amount of text) + 2nd pass for selection rendering (we could merge them by an extra refactoring effort)
const ImWchar* text_begin = edit_state.Text.Data;
const ImWchar* text_end = text_begin + edit_state.CurLenW;
ImVec2 cursor_offset, select_start_offset;
{
// Count lines + find lines numbers of cursor and select_start
int matches_remaining = 0;
int matches_line_no[2] = { -1, -999 };
const ImWchar* matches_ptr[2] = { NULL, NULL };
matches_ptr[0] = text_begin + edit_state.StbState.cursor; matches_remaining++;
// Count lines + find lines numbers straddling 'cursor' and 'select_start' position.
const ImWchar* searches_input_ptr[2];
searches_input_ptr[0] = text_begin + edit_state.StbState.cursor;
searches_input_ptr[1] = NULL;
int searches_remaining = 1;
int searches_result_line_number[2] = { -1, -999 };
if (edit_state.StbState.select_start != edit_state.StbState.select_end)
{
matches_ptr[1] = text_begin + ImMin(edit_state.StbState.select_start, edit_state.StbState.select_end);
matches_line_no[1] = -1;
matches_remaining++;
searches_input_ptr[1] = text_begin + ImMin(edit_state.StbState.select_start, edit_state.StbState.select_end);
searches_result_line_number[1] = -1;
searches_remaining++;
}
matches_remaining += is_multiline ? 1 : 0; // So that we never exit the loop until all lines are counted.
// Iterate all lines to find our line numbers
// In multi-line mode, we never exit the loop until all lines are counted, so add one extra to the searches_remaining counter.
searches_remaining += is_multiline ? 1 : 0;
int line_count = 0;
for (const ImWchar* s = text_begin; s < text_end+1; s++)
if ((*s) == '\n' || s == text_end)
for (const ImWchar* s = text_begin; *s != 0; s++)
if (*s == '\n')
{
line_count++;
if (matches_line_no[0] == -1 && s >= matches_ptr[0]) { matches_line_no[0] = line_count; if (--matches_remaining <= 0) break; }
if (matches_line_no[1] == -1 && s >= matches_ptr[1]) { matches_line_no[1] = line_count; if (--matches_remaining <= 0) break; }
if (searches_result_line_number[0] == -1 && s >= searches_input_ptr[0]) { searches_result_line_number[0] = line_count; if (--searches_remaining <= 0) break; }
if (searches_result_line_number[1] == -1 && s >= searches_input_ptr[1]) { searches_result_line_number[1] = line_count; if (--searches_remaining <= 0) break; }
}
line_count++;
if (searches_result_line_number[0] == -1) searches_result_line_number[0] = line_count;
if (searches_result_line_number[1] == -1) searches_result_line_number[1] = line_count;
// Calculate 2d position
IM_ASSERT(matches_line_no[0] != -1);
cursor_offset.x = InputTextCalcTextSizeW(ImStrbolW(matches_ptr[0], text_begin), matches_ptr[0]).x;
cursor_offset.y = matches_line_no[0] * g.FontSize;
if (matches_line_no[1] >= 0)
// Calculate 2d position by finding the beginning of the line and measuring distance
cursor_offset.x = InputTextCalcTextSizeW(ImStrbolW(searches_input_ptr[0], text_begin), searches_input_ptr[0]).x;
cursor_offset.y = searches_result_line_number[0] * g.FontSize;
if (searches_result_line_number[1] >= 0)
{
select_start_offset.x = InputTextCalcTextSizeW(ImStrbolW(matches_ptr[1], text_begin), matches_ptr[1]).x;
select_start_offset.y = matches_line_no[1] * g.FontSize;
select_start_offset.x = InputTextCalcTextSizeW(ImStrbolW(searches_input_ptr[1], text_begin), searches_input_ptr[1]).x;
select_start_offset.y = searches_result_line_number[1] * g.FontSize;
}
// Calculate text height
@ -7525,7 +7545,7 @@ bool ImGui::InputTextEx(const char* label, char* buf, int buf_size, const ImVec2
}
}
edit_state.CursorFollow = false;
ImVec2 render_scroll = ImVec2(edit_state.ScrollX, 0.0f);
const ImVec2 render_scroll = ImVec2(edit_state.ScrollX, 0.0f);
// Draw selection
if (edit_state.StbState.select_start != edit_state.StbState.select_end)
@ -8322,6 +8342,7 @@ void ImGui::EndMenu()
}
// A little colored square. Return true when clicked.
// FIXME: May want to display/ignore the alpha component in the color display? Yet show it in the tooltip.
bool ImGui::ColorButton(const ImVec4& col, bool small_height, bool outline_border)
{
ImGuiWindow* window = GetCurrentWindow();
@ -8342,13 +8363,7 @@ bool ImGui::ColorButton(const ImVec4& col, bool small_height, bool outline_borde
RenderFrame(bb.Min, bb.Max, window->Color(col), outline_border, style.FrameRounding);
if (hovered)
{
int ix = (int)(col.x * 255.0f + 0.5f);
int iy = (int)(col.y * 255.0f + 0.5f);
int iz = (int)(col.z * 255.0f + 0.5f);
int iw = (int)(col.w * 255.0f + 0.5f);
ImGui::SetTooltip("Color:\n(%.2f,%.2f,%.2f,%.2f)\n#%02X%02X%02X%02X", col.x, col.y, col.z, col.w, ix, iy, iz, iw);
}
ImGui::SetTooltip("Color:\n(%.2f,%.2f,%.2f,%.2f)\n#%02X%02X%02X%02X", col.x, col.y, col.z, col.w, IM_F32_TO_INT8(col.x), IM_F32_TO_INT8(col.y), IM_F32_TO_INT8(col.z), IM_F32_TO_INT8(col.z));
return pressed;
}
@ -8390,7 +8405,7 @@ bool ImGui::ColorEdit4(const char* label, float col[4], bool alpha)
if (edit_mode == ImGuiColorEditMode_HSV)
ImGui::ColorConvertRGBtoHSV(f[0], f[1], f[2], f[0], f[1], f[2]);
int i[4] = { (int)(f[0] * 255.0f + 0.5f), (int)(f[1] * 255.0f + 0.5f), (int)(f[2] * 255.0f + 0.5f), (int)(f[3] * 255.0f + 0.5f) };
int i[4] = { IM_F32_TO_INT8(f[0]), IM_F32_TO_INT8(f[1]), IM_F32_TO_INT8(f[2]), IM_F32_TO_INT8(f[3]) };
int components = alpha ? 4 : 3;
bool value_changed = false;
@ -8463,6 +8478,10 @@ bool ImGui::ColorEdit4(const char* label, float col[4], bool alpha)
const ImVec4 col_display(col[0], col[1], col[2], 1.0f);
if (ImGui::ColorButton(col_display))
g.ColorEditModeStorage.SetInt(id, (edit_mode + 1) % 3); // Don't set local copy of 'edit_mode' right away!
// Recreate our own tooltip over's ColorButton() one because we want to display correct alpha here
if (ImGui::IsItemHovered())
ImGui::SetTooltip("Color:\n(%.2f,%.2f,%.2f,%.2f)\n#%02X%02X%02X%02X", col[0], col[1], col[2], col[3], IM_F32_TO_INT8(col[0]), IM_F32_TO_INT8(col[1]), IM_F32_TO_INT8(col[2]), IM_F32_TO_INT8(col[3]));
if (window->DC.ColorEditMode == ImGuiColorEditMode_UserSelectShowButton)
{
@ -8932,6 +8951,7 @@ void ImGui::Value(const char* prefix, float v, const char* float_format)
}
}
// FIXME: May want to remove those helpers?
void ImGui::Color(const char* prefix, const ImVec4& v)
{
ImGui::Text("%s: (%.2f,%.2f,%.2f,%.2f)", prefix, v.x, v.y, v.z, v.w);

View file

@ -1,4 +1,4 @@
// ImGui library v1.46 WIP
// ImGui library v1.47 WIP
// Headers
// See imgui.cpp file for documentation.
@ -17,7 +17,7 @@
#include <stdlib.h> // NULL, malloc, free, qsort, atoi
#include <string.h> // memset, memmove, memcpy, strlen, strchr, strcpy, strcmp
#define IMGUI_VERSION "1.46 WIP"
#define IMGUI_VERSION "1.47 WIP"
// Define assertion handler.
#ifndef IM_ASSERT
@ -953,7 +953,7 @@ struct ImGuiTextEditCallbackData
ImGuiKey EventKey; // Key pressed (Up/Down/TAB) // Read-only
char* Buf; // Current text // Read-write (pointed data only)
int BufSize; // // Read-only
bool BufDirty; // Set if you modify Buf directly // Write
bool BufDirty; // Must set if you modify Buf directly // Write
int CursorPos; // // Read-write
int SelectionStart; // // Read-write (== to SelectionEnd when no selection)
int SelectionEnd; // // Read-write

View file

@ -1,4 +1,4 @@
// ImGui library v1.46 WIP
// ImGui library v1.47 WIP
// Demo code
// Don't remove this file from your project! It is useful reference code that you can execute.
@ -423,7 +423,18 @@ void ImGui::ShowTestWindow(bool* opened)
if (ImGui::TreeNode("Multi-line Text Input"))
{
static bool read_only = false;
static char text[1024*16] = "// F00F bug\nlabel:\n\tlock cmpxchg8b eax\n";
static char text[1024*16] =
"/*\n"
" The Pentium F00F bug, shorthand for F0 0F C7 C8,\n"
" the hexadecimal encoding of one offending instruction,\n"
" more formally, the invalid operand with locked CMPXCHG8B\n"
" instruction bug, is a design flaw in the majority of\n"
" Intel Pentium, Pentium MMX, and Pentium OverDrive\n"
" processors (all in the P5 microarchitecture).\n"
"*/\n\n"
"label:\n"
"\tlock cmpxchg8b eax\n";
ImGui::PushStyleVar(ImGuiStyleVar_FramePadding, ImVec2(0,0));
ImGui::Checkbox("Read-only", &read_only);
ImGui::PopStyleVar();

View file

@ -1,4 +1,4 @@
// ImGui library v1.46 WIP
// ImGui library v1.47 WIP
// Drawing and font code
// Contains implementation for

View file

@ -1,4 +1,4 @@
// ImGui library v1.46 WIP
// ImGui library v1.47 WIP
// Internals
// You may use this file to debug, understand or extend ImGui features but we don't provide any guarantee of forward compatibility!
@ -270,24 +270,25 @@ struct IMGUI_API ImGuiSimpleColumns
// Internal state of the currently focused/edited text input box
struct IMGUI_API ImGuiTextEditState
{
ImGuiID Id; // widget id owning the text state
ImVector<ImWchar> Text; // edit buffer, we need to persist but can't guarantee the persistence of the user-provided buffer. so we copy into own buffer.
ImVector<char> InitialText; // backup of end-user buffer at the time of focus (in UTF-8, unaltered)
ImGuiID Id; // widget id owning the text state
ImVector<ImWchar> Text; // edit buffer, we need to persist but can't guarantee the persistence of the user-provided buffer. so we copy into own buffer.
ImVector<char> InitialText; // backup of end-user buffer at the time of focus (in UTF-8, unaltered)
ImVector<char> TempTextBuffer;
int CurLenA, CurLenW; // we need to maintain our buffer length in both UTF-8 and wchar format.
int BufSizeA; // end-user buffer size
int CurLenA, CurLenW; // we need to maintain our buffer length in both UTF-8 and wchar format.
int BufSizeA; // end-user buffer size
float ScrollX;
ImGuiStb::STB_TexteditState StbState;
float CursorAnim;
bool CursorFollow;
ImVec2 InputCursorScreenPos; // Cursor position in screen space to be used by IME callback.
ImVec2 InputCursorScreenPos; // Cursor position in screen space to be used by IME callback.
bool SelectedAllMouseLock;
ImGuiTextEditState() { memset(this, 0, sizeof(*this)); }
void CursorAnimReset() { CursorAnim = -0.30f; } // After a user-input the cursor stays on for a while without blinking
bool HasSelection() const { return StbState.select_start != StbState.select_end; }
void ClearSelection() { StbState.select_start = StbState.select_end = StbState.cursor; }
void SelectAll() { StbState.select_start = 0; StbState.select_end = CurLenW; StbState.cursor = StbState.select_end; StbState.has_preferred_x = false; }
ImGuiTextEditState() { memset(this, 0, sizeof(*this)); }
void CursorAnimReset() { CursorAnim = -0.30f; } // After a user-input the cursor stays on for a while without blinking
void CursorClamp() { StbState.cursor = ImMin(StbState.cursor, CurLenW); StbState.select_start = ImMin(StbState.select_start, CurLenW); StbState.select_end = ImMin(StbState.select_end, CurLenW); }
bool HasSelection() const { return StbState.select_start != StbState.select_end; }
void ClearSelection() { StbState.select_start = StbState.select_end = StbState.cursor; }
void SelectAll() { StbState.select_start = 0; StbState.select_end = CurLenW; StbState.cursor = StbState.select_end; StbState.has_preferred_x = false; }
void OnKeyPressed(int key);
};
@ -598,7 +599,7 @@ struct IMGUI_API ImGuiWindow
ImVector<ImGuiID> IDStack; // ID stack. ID are hashes seeded with the value at the top of the stack
ImRect ClipRect; // = DrawList->clip_rect_stack.back(). Scissoring / clipping rectangle. x1, y1, x2, y2.
ImRect ClippedWindowRect; // = ClipRect just after setup in Begin()
int LastFrameDrawn;
int LastFrameActive;
float ItemWidthDefault;
ImGuiSimpleColumns MenuColumns; // Simplified columns storage for menu items
ImGuiStorage StateStorage;