|
@@ -1108,10 +1108,11 @@ struct ImGuiState
|
|
|
ImGuiWindow* FocusedWindow; // Will catch keyboard inputs
|
|
|
ImGuiWindow* HoveredWindow; // Will catch mouse inputs
|
|
|
ImGuiWindow* HoveredRootWindow; // Will catch mouse inputs (for focus/move only)
|
|
|
- ImGuiID HoveredId;
|
|
|
- ImGuiID ActiveId;
|
|
|
+ ImGuiID HoveredId; // Hovered widget
|
|
|
+ ImGuiID ActiveId; // Active widget
|
|
|
ImGuiID ActiveIdPreviousFrame;
|
|
|
bool ActiveIdIsAlive;
|
|
|
+ bool ActiveIdIsJustActivated; // Set when
|
|
|
bool ActiveIdIsFocusedOnly; // Set only by active widget. Denote focus but no active interaction.
|
|
|
ImGuiWindow* MovedWindow; // Track the child window we clicked on to move a window. Only valid if ActiveID is the "#MOVE" identifier of a window.
|
|
|
float SettingsDirtyTimer;
|
|
@@ -1144,6 +1145,7 @@ struct ImGuiState
|
|
|
ImGuiID ScalarAsInputTextId; // Temporary text input when CTRL+clicking on a slider, etc.
|
|
|
ImGuiStorage ColorEditModeStorage; // for user selection
|
|
|
ImGuiID ActiveComboID;
|
|
|
+ float DragCurrentValue;
|
|
|
ImVec2 DragLastMouseDelta;
|
|
|
float DragSpeedScaleSlow;
|
|
|
float DragSpeedScaleFast;
|
|
@@ -1182,6 +1184,7 @@ struct ImGuiState
|
|
|
ActiveId = 0;
|
|
|
ActiveIdPreviousFrame = 0;
|
|
|
ActiveIdIsAlive = false;
|
|
|
+ ActiveIdIsJustActivated = false;
|
|
|
ActiveIdIsFocusedOnly = false;
|
|
|
MovedWindow = NULL;
|
|
|
SettingsDirtyTimer = 0.0f;
|
|
@@ -1199,6 +1202,7 @@ struct ImGuiState
|
|
|
|
|
|
ScalarAsInputTextId = 0;
|
|
|
ActiveComboID = 0;
|
|
|
+ DragCurrentValue = 0.0f;
|
|
|
DragLastMouseDelta = ImVec2(0.0f, 0.0f);
|
|
|
DragSpeedScaleSlow = 0.01f;
|
|
|
DragSpeedScaleFast = 10.0f;
|
|
@@ -1314,6 +1318,7 @@ static void SetActiveId(ImGuiID id)
|
|
|
ImGuiState& g = *GImGui;
|
|
|
g.ActiveId = id;
|
|
|
g.ActiveIdIsFocusedOnly = false;
|
|
|
+ g.ActiveIdIsJustActivated = true;
|
|
|
}
|
|
|
|
|
|
static void RegisterAliveId(ImGuiID id)
|
|
@@ -1935,6 +1940,7 @@ void ImGui::NewFrame()
|
|
|
SetActiveId(0);
|
|
|
g.ActiveIdPreviousFrame = g.ActiveId;
|
|
|
g.ActiveIdIsAlive = false;
|
|
|
+ g.ActiveIdIsJustActivated = false;
|
|
|
if (!g.ActiveId)
|
|
|
g.MovedWindow = NULL;
|
|
|
|
|
@@ -5055,7 +5061,7 @@ static bool SliderFloatAsInputText(const char* label, float* v, ImGuiID id, int
|
|
|
}
|
|
|
|
|
|
// Parse display precision back from the display format string
|
|
|
-static void ParseFormat(const char* fmt, int& decimal_precision)
|
|
|
+static inline void ParseFormat(const char* fmt, int& decimal_precision)
|
|
|
{
|
|
|
while ((fmt = strchr(fmt, '%')) != NULL)
|
|
|
{
|
|
@@ -5073,6 +5079,21 @@ static void ParseFormat(const char* fmt, int& decimal_precision)
|
|
|
}
|
|
|
}
|
|
|
|
|
|
+static inline float RoundScalar(float value, int decimal_precision)
|
|
|
+{
|
|
|
+ // Round past decimal precision
|
|
|
+ // 0: 1, 1: 0.1, 2: 0.01, etc.
|
|
|
+ // So when our value is 1.99999 with a precision of 0.001 we'll end up rounding to 2.0
|
|
|
+ // FIXME: Investigate better rounding methods
|
|
|
+ const float min_step = 1.0f / powf(10.0f, (float)decimal_precision);
|
|
|
+ const float remainder = fmodf(value, min_step);
|
|
|
+ if (remainder <= min_step*0.5f)
|
|
|
+ value -= remainder;
|
|
|
+ else
|
|
|
+ value += (min_step - remainder);
|
|
|
+ return value;
|
|
|
+}
|
|
|
+
|
|
|
static bool SliderBehavior(const ImRect& frame_bb, const ImRect& slider_bb, ImGuiID id, float* v, float v_min, float v_max, float power, int decimal_precision, bool horizontal)
|
|
|
{
|
|
|
ImGuiState& g = *GImGui;
|
|
@@ -5151,14 +5172,7 @@ static bool SliderBehavior(const ImRect& frame_bb, const ImRect& slider_bb, ImGu
|
|
|
}
|
|
|
|
|
|
// Round past decimal precision
|
|
|
- // 0->1, 1->0.1, 2->0.01, etc.
|
|
|
- // So when our value is 1.99999 with a precision of 0.001 we'll end up rounding to 2.0
|
|
|
- const float min_step = 1.0f / powf(10.0f, (float)decimal_precision);
|
|
|
- const float remainder = fmodf(new_value, min_step);
|
|
|
- if (remainder <= min_step*0.5f)
|
|
|
- new_value -= remainder;
|
|
|
- else
|
|
|
- new_value += (min_step - remainder);
|
|
|
+ new_value = RoundScalar(new_value, decimal_precision);
|
|
|
|
|
|
if (*v != new_value)
|
|
|
{
|
|
@@ -5464,7 +5478,7 @@ bool ImGui::SliderInt4(const char* label, int v[4], int v_min, int v_max, const
|
|
|
}
|
|
|
|
|
|
// 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)
|
|
|
+static bool DragScalarBehavior(const ImRect& frame_bb, ImGuiID id, float* v, float v_speed, float v_min, float v_max, int decimal_precision)
|
|
|
{
|
|
|
ImGuiState& g = *GImGui;
|
|
|
ImGuiWindow* window = GetCurrentWindow();
|
|
@@ -5481,23 +5495,34 @@ static bool DragScalarBehavior(const ImRect& frame_bb, ImGuiID id, float* v, flo
|
|
|
{
|
|
|
if (g.IO.MouseDown[0])
|
|
|
{
|
|
|
- const ImVec2 mouse_drag_delta = ImGui::GetMouseDragDelta(0);
|
|
|
+ if (g.ActiveIdIsJustActivated)
|
|
|
+ {
|
|
|
+ // Lock current value on click
|
|
|
+ g.DragCurrentValue = *v;
|
|
|
+ g.DragLastMouseDelta = ImVec2(0.f, 0.f);
|
|
|
+ }
|
|
|
|
|
|
+ const ImVec2 mouse_drag_delta = ImGui::GetMouseDragDelta(0, 1.0f);
|
|
|
if (fabsf(mouse_drag_delta.x - g.DragLastMouseDelta.x) > 0.0f)
|
|
|
{
|
|
|
- float step = v_step;
|
|
|
+ float step = v_speed;
|
|
|
if (g.IO.KeyShift && g.DragSpeedScaleFast >= 0.0f)
|
|
|
- step = v_step * g.DragSpeedScaleFast;
|
|
|
+ step = v_speed * g.DragSpeedScaleFast;
|
|
|
if (g.IO.KeyAlt && g.DragSpeedScaleSlow >= 0.0f)
|
|
|
- step = v_step * g.DragSpeedScaleSlow;
|
|
|
+ step = v_speed * g.DragSpeedScaleSlow;
|
|
|
|
|
|
- *v += (mouse_drag_delta.x - g.DragLastMouseDelta.x) * step;
|
|
|
+ g.DragCurrentValue += (mouse_drag_delta.x - g.DragLastMouseDelta.x) * step;
|
|
|
+ g.DragLastMouseDelta.x = mouse_drag_delta.x;
|
|
|
|
|
|
if (v_min < v_max)
|
|
|
- *v = ImClamp(*v, v_min, v_max);
|
|
|
+ g.DragCurrentValue = ImClamp(g.DragCurrentValue, v_min, v_max);
|
|
|
|
|
|
- g.DragLastMouseDelta.x = mouse_drag_delta.x;
|
|
|
- value_changed = true;
|
|
|
+ float new_value = RoundScalar(g.DragCurrentValue, decimal_precision);
|
|
|
+ if (*v != new_value)
|
|
|
+ {
|
|
|
+ *v = new_value;
|
|
|
+ value_changed = true;
|
|
|
+ }
|
|
|
}
|
|
|
}
|
|
|
else
|
|
@@ -5509,7 +5534,7 @@ static bool DragScalarBehavior(const ImRect& frame_bb, ImGuiID id, float* v, flo
|
|
|
return value_changed;
|
|
|
}
|
|
|
|
|
|
-bool ImGui::DragFloat(const char* label, float *v, float v_step, float v_min, float v_max, const char* display_format)
|
|
|
+bool ImGui::DragFloat(const char* label, float *v, float v_speed, float v_min, float v_max, const char* display_format)
|
|
|
{
|
|
|
ImGuiState& g = *GImGui;
|
|
|
ImGuiWindow* window = GetCurrentWindow();
|
|
@@ -5548,7 +5573,6 @@ bool ImGui::DragFloat(const char* label, float *v, float v_step, float v_min, fl
|
|
|
{
|
|
|
SetActiveId(id);
|
|
|
FocusWindow(window);
|
|
|
- g.DragLastMouseDelta = ImVec2(0.f, 0.f);
|
|
|
|
|
|
if (tab_focus_requested || g.IO.KeyCtrl || g.IO.MouseDoubleClicked[0])
|
|
|
{
|
|
@@ -5562,7 +5586,7 @@ bool ImGui::DragFloat(const char* label, float *v, float v_step, float v_min, fl
|
|
|
ItemSize(total_bb, style.FramePadding.y);
|
|
|
|
|
|
// Actual drag behavior
|
|
|
- const bool value_changed = DragScalarBehavior(frame_bb, id, v, v_step, v_min, v_max);
|
|
|
+ const bool value_changed = DragScalarBehavior(frame_bb, id, v, v_speed, v_min, v_max, decimal_precision);
|
|
|
|
|
|
// Display value using user-provided display format so user can add prefix/suffix/decorations to the value.
|
|
|
char value_buf[64];
|
|
@@ -5576,12 +5600,13 @@ bool ImGui::DragFloat(const char* label, float *v, float v_step, float v_min, fl
|
|
|
return value_changed;
|
|
|
}
|
|
|
|
|
|
-bool ImGui::DragInt(const char* label, int* v, int v_step, int v_min, int v_max, const char* display_format)
|
|
|
+// NB: v_speed is float to allow adjusting the drag speed with more precision
|
|
|
+bool ImGui::DragInt(const char* label, int* v, float v_speed, 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);
|
|
|
+ bool value_changed = ImGui::DragFloat(label, &v_f, v_speed, (float)v_min, (float)v_max, display_format);
|
|
|
*v = (int)v_f;
|
|
|
return value_changed;
|
|
|
}
|
|
@@ -7029,7 +7054,7 @@ bool ImGui::ColorEdit4(const char* label, float col[4], bool alpha)
|
|
|
ImGui::SameLine(0, (int)style.ItemInnerSpacing.x);
|
|
|
if (n + 1 == components)
|
|
|
ImGui::PushItemWidth(w_item_last);
|
|
|
- value_changed |= ImGui::DragInt(ids[n], &i[n], 1, 0, 255, fmt[n]);
|
|
|
+ value_changed |= ImGui::DragInt(ids[n], &i[n], 1.0f, 0, 255, fmt[n]);
|
|
|
}
|
|
|
ImGui::PopItemWidth();
|
|
|
ImGui::PopItemWidth();
|