Added DragFloat(), DragInt() work in progress #180

This commit is contained in:
ocornut 2015-04-03 14:07:52 +01:00
parent d25578efd8
commit 1247ce251f
2 changed files with 161 additions and 14 deletions

163
imgui.cpp
View File

@ -135,6 +135,7 @@
Occasionally introducing changes that are breaking the API. The breakage are generally minor and easy to fix. 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. 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/04/03 (1.38) - removed ImGuiCol_CheckHovered, ImGuiCol_CheckActive, replaced with the more general ImGuiCol_FrameBgHovered, ImGuiCol_FrameBgActive.
- 2015/03/17 (1.36) - renamed GetItemRectMin()/GetItemRectMax()/IsMouseHoveringBox() to GetItemRectMin()/GetItemRectMax()/IsMouseHoveringRect(). Kept inline redirection function (will obsolete). - 2015/03/17 (1.36) - renamed GetItemRectMin()/GetItemRectMax()/IsMouseHoveringBox() to GetItemRectMin()/GetItemRectMax()/IsMouseHoveringRect(). Kept inline redirection function (will obsolete).
- 2015/03/15 (1.36) - renamed style.TreeNodeSpacing to style.IndentSpacing, ImGuiStyleVar_TreeNodeSpacing to ImGuiStyleVar_IndentSpacing - 2015/03/15 (1.36) - renamed style.TreeNodeSpacing to style.IndentSpacing, ImGuiStyleVar_TreeNodeSpacing to ImGuiStyleVar_IndentSpacing
- 2015/03/13 (1.36) - renamed GetWindowIsFocused() to IsWindowFocused(). Kept inline redirection function (will obsolete). - 2015/03/13 (1.36) - renamed GetWindowIsFocused() to IsWindowFocused(). Kept inline redirection function (will obsolete).
@ -559,6 +560,8 @@ ImGuiStyle::ImGuiStyle()
Colors[ImGuiCol_Border] = ImVec4(0.70f, 0.70f, 0.70f, 1.00f); Colors[ImGuiCol_Border] = ImVec4(0.70f, 0.70f, 0.70f, 1.00f);
Colors[ImGuiCol_BorderShadow] = ImVec4(0.00f, 0.00f, 0.00f, 0.60f); Colors[ImGuiCol_BorderShadow] = ImVec4(0.00f, 0.00f, 0.00f, 0.60f);
Colors[ImGuiCol_FrameBg] = ImVec4(0.80f, 0.80f, 0.80f, 0.30f); // Background of checkbox, radio button, plot, slider, text input Colors[ImGuiCol_FrameBg] = ImVec4(0.80f, 0.80f, 0.80f, 0.30f); // Background of checkbox, radio button, plot, slider, text input
Colors[ImGuiCol_FrameBgHovered] = ImVec4(0.90f, 0.80f, 0.80f, 0.40f);
Colors[ImGuiCol_FrameBgActive] = ImVec4(0.90f, 0.65f, 0.65f, 0.45f);
Colors[ImGuiCol_TitleBg] = ImVec4(0.50f, 0.50f, 1.00f, 0.45f); Colors[ImGuiCol_TitleBg] = ImVec4(0.50f, 0.50f, 1.00f, 0.45f);
Colors[ImGuiCol_TitleBgCollapsed] = ImVec4(0.40f, 0.40f, 0.80f, 0.20f); Colors[ImGuiCol_TitleBgCollapsed] = ImVec4(0.40f, 0.40f, 0.80f, 0.20f);
Colors[ImGuiCol_ScrollbarBg] = ImVec4(0.40f, 0.40f, 0.80f, 0.15f); Colors[ImGuiCol_ScrollbarBg] = ImVec4(0.40f, 0.40f, 0.80f, 0.15f);
@ -566,8 +569,6 @@ ImGuiStyle::ImGuiStyle()
Colors[ImGuiCol_ScrollbarGrabHovered] = ImVec4(0.40f, 0.40f, 0.80f, 0.40f); Colors[ImGuiCol_ScrollbarGrabHovered] = ImVec4(0.40f, 0.40f, 0.80f, 0.40f);
Colors[ImGuiCol_ScrollbarGrabActive] = ImVec4(0.80f, 0.50f, 0.50f, 0.40f); Colors[ImGuiCol_ScrollbarGrabActive] = ImVec4(0.80f, 0.50f, 0.50f, 0.40f);
Colors[ImGuiCol_ComboBg] = ImVec4(0.20f, 0.20f, 0.20f, 0.99f); Colors[ImGuiCol_ComboBg] = ImVec4(0.20f, 0.20f, 0.20f, 0.99f);
Colors[ImGuiCol_CheckHovered] = ImVec4(0.60f, 0.40f, 0.40f, 0.45f);
Colors[ImGuiCol_CheckActive] = ImVec4(0.65f, 0.50f, 0.50f, 0.55f);
Colors[ImGuiCol_CheckMark] = ImVec4(0.90f, 0.90f, 0.90f, 0.50f); Colors[ImGuiCol_CheckMark] = ImVec4(0.90f, 0.90f, 0.90f, 0.50f);
Colors[ImGuiCol_SliderGrab] = ImVec4(1.00f, 1.00f, 1.00f, 0.30f); Colors[ImGuiCol_SliderGrab] = ImVec4(1.00f, 1.00f, 1.00f, 0.30f);
Colors[ImGuiCol_SliderGrabActive] = ImVec4(0.80f, 0.50f, 0.50f, 1.00f); Colors[ImGuiCol_SliderGrabActive] = ImVec4(0.80f, 0.50f, 0.50f, 1.00f);
@ -649,9 +650,11 @@ void ImGuiIO::AddInputCharacter(ImWchar c)
const float PI = 3.14159265358979323846f; const float PI = 3.14159265358979323846f;
#ifdef INT_MAX #ifdef INT_MAX
#define IM_INT_MAX INT_MAX #define IM_INT_MIN INT_MIN
#define IM_INT_MAX INT_MAX
#else #else
#define IM_INT_MAX 2147483647 #define IM_INT_MIN (-2147483647-1)
#define IM_INT_MAX (2147483647)
#endif #endif
// Play it nice with Windows users. Notepad in 2015 still doesn't display text data with Unix-style \n. // Play it nice with Windows users. Notepad in 2015 still doesn't display text data with Unix-style \n.
@ -1138,6 +1141,9 @@ struct ImGuiState
ImGuiID ScalarAsInputTextId; // Temporary text input when CTRL+clicking on a slider, etc. ImGuiID ScalarAsInputTextId; // Temporary text input when CTRL+clicking on a slider, etc.
ImGuiStorage ColorEditModeStorage; // for user selection ImGuiStorage ColorEditModeStorage; // for user selection
ImGuiID ActiveComboID; ImGuiID ActiveComboID;
ImVec2 DragLastMouseDelta;
float DragSpeedScaleSlow;
float DragSpeedScaleFast;
float ScrollbarClickDeltaToGrabCenter; // distance between mouse and center of grab box, normalized in parent space float ScrollbarClickDeltaToGrabCenter; // distance between mouse and center of grab box, normalized in parent space
char Tooltip[1024]; char Tooltip[1024];
char* PrivateClipboard; // if no custom clipboard handler is defined char* PrivateClipboard; // if no custom clipboard handler is defined
@ -1189,6 +1195,9 @@ struct ImGuiState
ScalarAsInputTextId = 0; ScalarAsInputTextId = 0;
ActiveComboID = 0; ActiveComboID = 0;
DragLastMouseDelta = ImVec2(0.0f, 0.0f);
DragSpeedScaleSlow = 0.01f;
DragSpeedScaleFast = 10.0f;
ScrollbarClickDeltaToGrabCenter = 0.0f; ScrollbarClickDeltaToGrabCenter = 0.0f;
memset(Tooltip, 0, sizeof(Tooltip)); memset(Tooltip, 0, sizeof(Tooltip));
PrivateClipboard = NULL; PrivateClipboard = NULL;
@ -3716,6 +3725,8 @@ const char* ImGui::GetStyleColName(ImGuiCol idx)
case ImGuiCol_Border: return "Border"; case ImGuiCol_Border: return "Border";
case ImGuiCol_BorderShadow: return "BorderShadow"; case ImGuiCol_BorderShadow: return "BorderShadow";
case ImGuiCol_FrameBg: return "FrameBg"; case ImGuiCol_FrameBg: return "FrameBg";
case ImGuiCol_FrameBgHovered: return "FrameBgHovered";
case ImGuiCol_FrameBgActive: return "FrameBgActive";
case ImGuiCol_TitleBg: return "TitleBg"; case ImGuiCol_TitleBg: return "TitleBg";
case ImGuiCol_TitleBgCollapsed: return "TitleBgCollapsed"; case ImGuiCol_TitleBgCollapsed: return "TitleBgCollapsed";
case ImGuiCol_ScrollbarBg: return "ScrollbarBg"; case ImGuiCol_ScrollbarBg: return "ScrollbarBg";
@ -3723,8 +3734,6 @@ const char* ImGui::GetStyleColName(ImGuiCol idx)
case ImGuiCol_ScrollbarGrabHovered: return "ScrollbarGrabHovered"; case ImGuiCol_ScrollbarGrabHovered: return "ScrollbarGrabHovered";
case ImGuiCol_ScrollbarGrabActive: return "ScrollbarGrabActive"; case ImGuiCol_ScrollbarGrabActive: return "ScrollbarGrabActive";
case ImGuiCol_ComboBg: return "ComboBg"; case ImGuiCol_ComboBg: return "ComboBg";
case ImGuiCol_CheckHovered: return "CheckHovered";
case ImGuiCol_CheckActive: return "CheckActive";
case ImGuiCol_CheckMark: return "CheckMark"; case ImGuiCol_CheckMark: return "CheckMark";
case ImGuiCol_SliderGrab: return "SliderGrab"; case ImGuiCol_SliderGrab: return "SliderGrab";
case ImGuiCol_SliderGrabActive: return "SliderGrabActive"; case ImGuiCol_SliderGrabActive: return "SliderGrabActive";
@ -5207,11 +5216,11 @@ bool ImGui::SliderFloat(const char* label, float* v, float v_min, float v_max, c
int decimal_precision = 3; int decimal_precision = 3;
ParseFormat(display_format, decimal_precision); ParseFormat(display_format, decimal_precision);
const bool tab_focus_requested = window->FocusItemRegister(g.ActiveId == id);
const bool is_finite = (v_min != -FLT_MAX && v_min != FLT_MAX && v_max != -FLT_MAX && v_max != FLT_MAX); const bool is_finite = (v_min != -FLT_MAX && v_min != FLT_MAX && v_max != -FLT_MAX && v_max != FLT_MAX);
// Tabbing or CTRL-clicking through slider turns into an input box // Tabbing or CTRL-clicking on Slider turns it into an input box
bool start_text_input = false; bool start_text_input = false;
const bool tab_focus_requested = window->FocusItemRegister(g.ActiveId == id);
if (tab_focus_requested || (hovered && g.IO.MouseClicked[0])) if (tab_focus_requested || (hovered && g.IO.MouseClicked[0]))
{ {
SetActiveId(id); SetActiveId(id);
@ -5427,6 +5436,138 @@ bool ImGui::SliderInt4(const char* label, int v[4], int v_min, int v_max, const
return SliderIntN(label, v, 4, v_min, v_max, display_format); return SliderIntN(label, v, 4, v_min, v_max, display_format);
} }
// FIXME-WIP: Work in progress. May change API / behavior.
static bool DragScalarBehavior(const ImRect& frame_bb, ImGuiID id, float* v, float v_step, float v_min, float v_max)
{
ImGuiState& g = *GImGui;
ImGuiWindow* window = GetCurrentWindow();
const ImGuiStyle& style = g.Style;
// Draw frame
const ImU32 frame_col = window->Color(g.ActiveId == id ? ImGuiCol_FrameBgActive : g.HoveredId == id ? ImGuiCol_FrameBgHovered : ImGuiCol_FrameBg);
RenderFrame(frame_bb.Min, frame_bb.Max, frame_col, true, style.FrameRounding);
bool value_changed = false;
// Process clicking on the slider
if (g.ActiveId == id)
{
if (g.IO.MouseDown[0])
{
const ImVec2 mouse_drag_delta = ImGui::GetMouseDragDelta(0);
if (fabsf(mouse_drag_delta.x - g.DragLastMouseDelta.x) > 0.0f)
{
float step = v_step;
if (g.IO.KeyShift && g.DragSpeedScaleFast >= 0.0f)
step = v_step * g.DragSpeedScaleFast;
if (g.IO.KeyAlt && g.DragSpeedScaleSlow >= 0.0f)
step = v_step * g.DragSpeedScaleSlow;
*v += (mouse_drag_delta.x - g.DragLastMouseDelta.x) * step;
*v = ImClamp(*v, v_min, v_max);
g.DragLastMouseDelta.x = mouse_drag_delta.x;
value_changed = true;
}
}
else
{
SetActiveId(0);
}
}
return value_changed;
}
bool ImGui::DragFloat(const char* label, float *v, float v_step, float v_min, float v_max, const char* display_format)
{
ImGuiState& g = *GImGui;
ImGuiWindow* window = GetCurrentWindow();
if (window->SkipItems)
return false;
const ImGuiStyle& style = g.Style;
const ImGuiID id = window->GetID(label);
const float w = ImGui::CalcItemWidth();
const ImVec2 label_size = CalcTextSize(label, NULL, true);
const ImRect frame_bb(window->DC.CursorPos, window->DC.CursorPos + ImVec2(w, label_size.y) + style.FramePadding*2.0f);
const ImRect inner_bb(frame_bb.Min + style.FramePadding, frame_bb.Max - style.FramePadding);
const ImRect total_bb(frame_bb.Min, frame_bb.Max + ImVec2(label_size.x > 0.0f ? style.ItemInnerSpacing.x + label_size.x : 0.0f, 0.0f));
// NB- we don't call ItemSize() yet because we may turn into a text edit box below
if (!ItemAdd(total_bb, &id))
{
ItemSize(total_bb, style.FramePadding.y);
return false;
}
const bool hovered = IsHovered(frame_bb, id);
if (hovered)
g.HoveredId = id;
if (!display_format)
display_format = "%.3f";
int decimal_precision = 3;
ParseFormat(display_format, decimal_precision);
// Tabbing or CTRL-clicking on Drag turns it into an input box
bool start_text_input = false;
const bool tab_focus_requested = window->FocusItemRegister(g.ActiveId == id);
if (tab_focus_requested || (hovered && g.IO.MouseClicked[0]))
{
SetActiveId(id);
FocusWindow(window);
g.DragLastMouseDelta = ImVec2(0.f, 0.f);
const bool is_ctrl_down = g.IO.KeyCtrl;
if (tab_focus_requested || is_ctrl_down)
{
start_text_input = true;
g.ScalarAsInputTextId = 0;
}
}
if (start_text_input || (g.ActiveId == id && g.ScalarAsInputTextId == id))
return SliderFloatAsInputText(label, v, id, decimal_precision);
ItemSize(total_bb, style.FramePadding.y);
// Actual drag behavior
const bool value_changed = DragScalarBehavior(frame_bb, id, v, v_step, v_min, v_max);
// Display value using user-provided display format so user can add prefix/suffix/decorations to the value.
char value_buf[64];
const char* value_buf_end = value_buf + ImFormatString(value_buf, IM_ARRAYSIZE(value_buf), display_format, *v);
const ImVec2 value_text_size = CalcTextSize(value_buf, value_buf_end, true);
RenderTextClipped(ImVec2(ImMax(frame_bb.Min.x + style.FramePadding.x, inner_bb.GetCenter().x - value_text_size.x*0.5f), frame_bb.Min.y + style.FramePadding.y), value_buf, value_buf_end, &value_text_size, frame_bb.Max);
if (label_size.x > 0.0f)
RenderText(ImVec2(frame_bb.Max.x + style.ItemInnerSpacing.x, inner_bb.Min.y), label);
return value_changed;
}
bool ImGui::DragFloat(const char* label, float* v, float v_step, const char* display_format)
{
return ImGui::DragFloat(label, v, v_step, -FLT_MAX, FLT_MAX, display_format);
}
bool ImGui::DragInt(const char* label, int* v, int v_step, int v_min, int v_max, const char* display_format)
{
if (!display_format)
display_format = "%.0f";
float v_f = (float)*v;
bool value_changed = ImGui::DragFloat(label, &v_f, (float)v_step, (float)v_min, (float)v_max, display_format);
*v = (int)v_f;
return value_changed;
}
bool ImGui::DragInt(const char* label, int* v, int v_step, const char* display_format)
{
return ImGui::DragInt(label, v, v_step, IM_INT_MIN, IM_INT_MAX, display_format);
}
enum ImGuiPlotType enum ImGuiPlotType
{ {
ImGuiPlotType_Lines, ImGuiPlotType_Lines,
@ -5598,7 +5739,7 @@ bool ImGui::Checkbox(const char* label, bool* v)
if (pressed) if (pressed)
*v = !(*v); *v = !(*v);
RenderFrame(check_bb.Min, check_bb.Max, window->Color((held && hovered) ? ImGuiCol_CheckActive : hovered ? ImGuiCol_CheckHovered : ImGuiCol_FrameBg), true, style.FrameRounding); RenderFrame(check_bb.Min, check_bb.Max, window->Color((held && hovered) ? ImGuiCol_FrameBgActive : hovered ? ImGuiCol_FrameBgHovered : ImGuiCol_FrameBg), true, style.FrameRounding);
if (*v) if (*v)
{ {
const float check_sz = ImMin(check_bb.GetWidth(), check_bb.GetHeight()); const float check_sz = ImMin(check_bb.GetWidth(), check_bb.GetHeight());
@ -5659,7 +5800,7 @@ bool ImGui::RadioButton(const char* label, bool active)
bool hovered, held; bool hovered, held;
bool pressed = ButtonBehavior(total_bb, id, &hovered, &held, true); bool pressed = ButtonBehavior(total_bb, id, &hovered, &held, true);
window->DrawList->AddCircleFilled(center, radius, window->Color((held && hovered) ? ImGuiCol_CheckActive : hovered ? ImGuiCol_CheckHovered : ImGuiCol_FrameBg), 16); window->DrawList->AddCircleFilled(center, radius, window->Color((held && hovered) ? ImGuiCol_FrameBgActive : hovered ? ImGuiCol_FrameBgHovered : ImGuiCol_FrameBg), 16);
if (active) if (active)
{ {
const float check_sz = ImMin(check_bb.GetWidth(), check_bb.GetHeight()); const float check_sz = ImMin(check_bb.GetWidth(), check_bb.GetHeight());
@ -6866,7 +7007,7 @@ bool ImGui::ColorEdit4(const char* label, float col[4], bool alpha)
ImGui::SameLine(0, (int)style.ItemInnerSpacing.x); ImGui::SameLine(0, (int)style.ItemInnerSpacing.x);
if (n + 1 == components) if (n + 1 == components)
ImGui::PushItemWidth(w_item_last); ImGui::PushItemWidth(w_item_last);
value_changed |= ImGui::SliderInt(ids[n], &i[n], 0, 255, fmt[n]); value_changed |= ImGui::DragInt(ids[n], &i[n], 1, 0, 255, fmt[n]);
} }
ImGui::PopItemWidth(); ImGui::PopItemWidth();
ImGui::PopItemWidth(); ImGui::PopItemWidth();

12
imgui.h
View File

@ -300,6 +300,12 @@ namespace ImGui
IMGUI_API void PlotHistogram(const char* label, const float* values, int values_count, int values_offset = 0, const char* overlay_text = NULL, float scale_min = FLT_MAX, float scale_max = FLT_MAX, ImVec2 graph_size = ImVec2(0,0), size_t stride = sizeof(float)); IMGUI_API void PlotHistogram(const char* label, const float* values, int values_count, int values_offset = 0, const char* overlay_text = NULL, float scale_min = FLT_MAX, float scale_max = FLT_MAX, ImVec2 graph_size = ImVec2(0,0), size_t stride = sizeof(float));
IMGUI_API void PlotHistogram(const char* label, float (*values_getter)(void* data, int idx), void* data, int values_count, int values_offset = 0, const char* overlay_text = NULL, float scale_min = FLT_MAX, float scale_max = FLT_MAX, ImVec2 graph_size = ImVec2(0,0)); IMGUI_API void PlotHistogram(const char* label, float (*values_getter)(void* data, int idx), void* data, int values_count, int values_offset = 0, const char* overlay_text = NULL, float scale_min = FLT_MAX, float scale_max = FLT_MAX, ImVec2 graph_size = ImVec2(0,0));
// Widgets: Drags (tip: ctrl+click on a drag box to input text)
IMGUI_API bool DragFloat(const char* label, float* v, float v_step = 1.0f, float v_min = -FLT_MAX, float v_max = FLT_MAX, const char* display_format = "%.3f");
IMGUI_API bool DragFloat(const char* label, float* v, float v_step, const char* display_format);
IMGUI_API bool DragInt(const char* label, int* v, int v_step = 1, int v_min = -0x7fffffff-1, int v_max = 0x7fffffff, const char* display_format = "%.0f");
IMGUI_API bool DragInt(const char* label, int* v, int v_step, const char* display_format = "%.0f");
// Widgets: Sliders (tip: ctrl+click on a slider to input text) // Widgets: Sliders (tip: ctrl+click on a slider to input text)
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 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); 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);
@ -484,6 +490,8 @@ enum ImGuiCol_
ImGuiCol_Border, ImGuiCol_Border,
ImGuiCol_BorderShadow, ImGuiCol_BorderShadow,
ImGuiCol_FrameBg, // Background of checkbox, radio button, plot, slider, text input ImGuiCol_FrameBg, // Background of checkbox, radio button, plot, slider, text input
ImGuiCol_FrameBgHovered,
ImGuiCol_FrameBgActive,
ImGuiCol_TitleBg, ImGuiCol_TitleBg,
ImGuiCol_TitleBgCollapsed, ImGuiCol_TitleBgCollapsed,
ImGuiCol_ScrollbarBg, ImGuiCol_ScrollbarBg,
@ -491,8 +499,6 @@ enum ImGuiCol_
ImGuiCol_ScrollbarGrabHovered, ImGuiCol_ScrollbarGrabHovered,
ImGuiCol_ScrollbarGrabActive, ImGuiCol_ScrollbarGrabActive,
ImGuiCol_ComboBg, ImGuiCol_ComboBg,
ImGuiCol_CheckHovered,
ImGuiCol_CheckActive,
ImGuiCol_CheckMark, ImGuiCol_CheckMark,
ImGuiCol_SliderGrab, ImGuiCol_SliderGrab,
ImGuiCol_SliderGrabActive, ImGuiCol_SliderGrabActive,
@ -553,7 +559,7 @@ enum ImGuiMouseCursor_
ImGuiMouseCursor_TextInput, ImGuiMouseCursor_TextInput,
ImGuiMouseCursor_Move, // Unused by ImGui ImGuiMouseCursor_Move, // Unused by ImGui
ImGuiMouseCursor_ResizeNS, // Unused by ImGui ImGuiMouseCursor_ResizeNS, // Unused by ImGui
ImGuiMouseCursor_ResizeEW, // Unused by ImGui ImGuiMouseCursor_ResizeEW,
ImGuiMouseCursor_ResizeNESW, // Unused by ImGui ImGuiMouseCursor_ResizeNESW, // Unused by ImGui
ImGuiMouseCursor_ResizeNWSE, ImGuiMouseCursor_ResizeNWSE,
ImGuiMouseCursor_Count_ ImGuiMouseCursor_Count_