From 944f414cc6f04da05d780236ac25b83b40828a70 Mon Sep 17 00:00:00 2001 From: omar Date: Fri, 4 May 2018 18:13:27 +0200 Subject: [PATCH] Internals: A few selected math helpers are now using template to handle all supported types. Added ImPow() to wrap float/double in a standard manner without calling pow(double) when not needed in Drag code. --- imgui.cpp | 20 ++++++++++---------- imgui_internal.h | 27 +++++++++++++-------------- 2 files changed, 23 insertions(+), 24 deletions(-) diff --git a/imgui.cpp b/imgui.cpp index 78b8562b6..9ab3b0832 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -8739,7 +8739,7 @@ static float GetMinimumStepAtDecimalPrecision(int decimal_precision) static const float min_steps[10] = { 1.0f, 0.1f, 0.01f, 0.001f, 0.0001f, 0.00001f, 0.000001f, 0.0000001f, 0.00000001f, 0.000000001f }; if (decimal_precision < 0) return FLT_MIN; - return (decimal_precision >= 0 && decimal_precision < 10) ? min_steps[decimal_precision] : powf(10.0f, (float)-decimal_precision); + return (decimal_precision >= 0 && decimal_precision < 10) ? min_steps[decimal_precision] : ImPow(10.0f, (float)-decimal_precision); } static inline float SliderBehaviorCalcRatioFromValue(float v, float v_min, float v_max, float power, float linear_zero_pos) @@ -8754,12 +8754,12 @@ static inline float SliderBehaviorCalcRatioFromValue(float v, float v_min, float if (v_clamped < 0.0f) { const float f = 1.0f - (v_clamped - v_min) / (ImMin(0.0f,v_max) - v_min); - return (1.0f - powf(f, 1.0f/power)) * linear_zero_pos; + return (1.0f - ImPow(f, 1.0f/power)) * linear_zero_pos; } else { const float f = (v_clamped - ImMax(0.0f,v_min)) / (v_max - ImMax(0.0f,v_min)); - return linear_zero_pos + powf(f, 1.0f/power) * (1.0f - linear_zero_pos); + return linear_zero_pos + ImPow(f, 1.0f/power) * (1.0f - linear_zero_pos); } } @@ -8798,8 +8798,8 @@ static bool ImGui::SliderBehavior(const ImRect& bb, ImGuiID id, float* v, float if (v_min * v_max < 0.0f) { // Different sign - const float linear_dist_min_to_0 = powf(v_min >= 0.0f ? v_min : -v_min, 1.0f/power); - const float linear_dist_max_to_0 = powf(v_max >= 0.0f ? v_max : -v_max, 1.0f/power); + const float linear_dist_min_to_0 = ImPow(v_min >= 0.0f ? v_min : -v_min, 1.0f/power); + const float linear_dist_max_to_0 = ImPow(v_max >= 0.0f ? v_max : -v_max, 1.0f/power); linear_zero_pos = linear_dist_min_to_0 / (linear_dist_min_to_0 + linear_dist_max_to_0); } else @@ -8873,7 +8873,7 @@ static bool ImGui::SliderBehavior(const ImRect& bb, ImGuiID id, float* v, float { // Negative: rescale to the negative range before powering float a = 1.0f - (clicked_t / linear_zero_pos); - a = powf(a, power); + a = ImPow(a, power); v_new = ImLerp(ImMin(v_max,0.0f), v_min, a); } else @@ -8884,7 +8884,7 @@ static bool ImGui::SliderBehavior(const ImRect& bb, ImGuiID id, float* v, float a = (clicked_t - linear_zero_pos) / (1.0f - linear_zero_pos); else a = clicked_t; - a = powf(a, power); + a = ImPow(a, power); v_new = ImLerp(ImMax(v_min,0.0f), v_max, a); } } @@ -9195,9 +9195,9 @@ static bool ImGui::DragBehaviorT(ImGuiDataType data_type, TYPE* v, float v_speed if (is_power) { // Offset + round to user desired precision, with a curve on the v_min..v_max range to get more precision on one side of the range - FLOATTYPE v_old_norm_curved = (FLOATTYPE)pow((FLOATTYPE)(v_cur - v_min) / (FLOATTYPE)(v_max - v_min), (FLOATTYPE)1.0f / power); + FLOATTYPE v_old_norm_curved = ImPow((FLOATTYPE)(v_cur - v_min) / (FLOATTYPE)(v_max - v_min), (FLOATTYPE)1.0f / power); FLOATTYPE v_new_norm_curved = v_old_norm_curved + (g.DragCurrentAccum / (v_max - v_min)); - v_cur = v_min + (TYPE)pow(ImSaturate((float)v_new_norm_curved), power) * (v_max - v_min); + v_cur = v_min + (TYPE)ImPow(ImSaturate((float)v_new_norm_curved), power) * (v_max - v_min); v_old_ref_for_accum_remainder = v_old_norm_curved; } else @@ -9217,7 +9217,7 @@ static bool ImGui::DragBehaviorT(ImGuiDataType data_type, TYPE* v, float v_speed g.DragCurrentAccumDirty = false; if (is_power) { - FLOATTYPE v_cur_norm_curved = (FLOATTYPE)pow((FLOATTYPE)(v_cur - v_min) / (FLOATTYPE)(v_max - v_min), (FLOATTYPE)1.0f / power); + FLOATTYPE v_cur_norm_curved = ImPow((FLOATTYPE)(v_cur - v_min) / (FLOATTYPE)(v_max - v_min), (FLOATTYPE)1.0f / power); g.DragCurrentAccum -= (float)(v_cur_norm_curved - v_old_ref_for_accum_remainder); } else diff --git a/imgui_internal.h b/imgui_internal.h index 07cbdb1e4..7f6e8ef06 100644 --- a/imgui_internal.h +++ b/imgui_internal.h @@ -126,8 +126,9 @@ IMGUI_API const char* ImParseFormatFindEnd(const char* format); IMGUI_API const char* ImParseFormatTrimDecorations(const char* format, char* buf, int buf_size); IMGUI_API int ImParseFormatPrecision(const char* format, int default_value); -// Helpers: Math -// We are keeping those not leaking to the user by default, in the case the user has implicit cast operators between ImVec2 and its own types (when IM_VEC2_CLASS_EXTRA is defined) +// Helpers: ImVec2/ImVec4 operators +// We are keeping those disabled by default so they don't leak in user space, to allow user enabling implicit cast operators between ImVec2 and their own types (using IM_VEC2_CLASS_EXTRA etc.) +// We unfortunately don't have a unary- operator for ImVec2 because this would needs to be defined inside the class itself. #ifdef IMGUI_DEFINE_MATH_OPERATORS static inline ImVec2 operator*(const ImVec2& lhs, const float rhs) { return ImVec2(lhs.x*rhs, lhs.y*rhs); } static inline ImVec2 operator/(const ImVec2& lhs, const float rhs) { return ImVec2(lhs.x/rhs, lhs.y/rhs); } @@ -144,23 +145,19 @@ static inline ImVec4 operator-(const ImVec4& lhs, const ImVec4& rhs) static inline ImVec4 operator*(const ImVec4& lhs, const ImVec4& rhs) { return ImVec4(lhs.x*rhs.x, lhs.y*rhs.y, lhs.z*rhs.z, lhs.w*rhs.w); } #endif -static inline int ImMin(int lhs, int rhs) { return lhs < rhs ? lhs : rhs; } -static inline int ImMax(int lhs, int rhs) { return lhs >= rhs ? lhs : rhs; } -static inline float ImMin(float lhs, float rhs) { return lhs < rhs ? lhs : rhs; } -static inline float ImMax(float lhs, float rhs) { return lhs >= rhs ? lhs : rhs; } +// Helpers: Maths +template static inline T ImMin(T lhs, T rhs) { return lhs < rhs ? lhs : rhs; } +template static inline T ImMax(T lhs, T rhs) { return lhs >= rhs ? lhs : rhs; } +template static inline T ImClamp(T v, T mn, T mx) { return (v < mn) ? mn : (v > mx) ? mx : v; } +template static inline T ImLerp(T a, T b, float t) { return (T)(a + (b - a) * t); } +template static inline void ImSwap(T& a, T& b) { T tmp = a; a = b; b = tmp; } static inline ImVec2 ImMin(const ImVec2& lhs, const ImVec2& rhs) { return ImVec2(lhs.x < rhs.x ? lhs.x : rhs.x, lhs.y < rhs.y ? lhs.y : rhs.y); } static inline ImVec2 ImMax(const ImVec2& lhs, const ImVec2& rhs) { return ImVec2(lhs.x >= rhs.x ? lhs.x : rhs.x, lhs.y >= rhs.y ? lhs.y : rhs.y); } -static inline int ImClamp(int v, int mn, int mx) { return (v < mn) ? mn : (v > mx) ? mx : v; } -static inline float ImClamp(float v, float mn, float mx) { return (v < mn) ? mn : (v > mx) ? mx : v; } -static inline ImVec2 ImClamp(const ImVec2& f, const ImVec2& mn, ImVec2 mx) { return ImVec2(ImClamp(f.x,mn.x,mx.x), ImClamp(f.y,mn.y,mx.y)); } -static inline float ImSaturate(float f) { return (f < 0.0f) ? 0.0f : (f > 1.0f) ? 1.0f : f; } -static inline void ImSwap(int& a, int& b) { int tmp = a; a = b; b = tmp; } -static inline void ImSwap(float& a, float& b) { float tmp = a; a = b; b = tmp; } -static inline int ImLerp(int a, int b, float t) { return (int)(a + (b - a) * t); } -static inline float ImLerp(float a, float b, float t) { return a + (b - a) * t; } +static inline ImVec2 ImClamp(const ImVec2& v, const ImVec2& mn, ImVec2 mx) { return ImVec2((v.x < mn.x) ? mn.x : (v.x > mx.x) ? mx.x : v.x, (v.y < mn.y) ? mn.y : (v.y > mx.y) ? mx.y : v.y); } static inline ImVec2 ImLerp(const ImVec2& a, const ImVec2& b, float t) { return ImVec2(a.x + (b.x - a.x) * t, a.y + (b.y - a.y) * t); } static inline ImVec2 ImLerp(const ImVec2& a, const ImVec2& b, const ImVec2& t) { return ImVec2(a.x + (b.x - a.x) * t.x, a.y + (b.y - a.y) * t.y); } static inline ImVec4 ImLerp(const ImVec4& a, const ImVec4& b, float t) { return ImVec4(a.x + (b.x - a.x) * t, a.y + (b.y - a.y) * t, a.z + (b.z - a.z) * t, a.w + (b.w - a.w) * t); } +static inline float ImSaturate(float f) { return (f < 0.0f) ? 0.0f : (f > 1.0f) ? 1.0f : f; } static inline float ImLengthSqr(const ImVec2& lhs) { return lhs.x*lhs.x + lhs.y*lhs.y; } static inline float ImLengthSqr(const ImVec4& lhs) { return lhs.x*lhs.x + lhs.y*lhs.y + lhs.z*lhs.z + lhs.w*lhs.w; } static inline float ImInvLength(const ImVec2& lhs, float fail_value) { float d = lhs.x*lhs.x + lhs.y*lhs.y; if (d > 0.0f) return 1.0f / sqrtf(d); return fail_value; } @@ -170,6 +167,8 @@ static inline float ImDot(const ImVec2& a, const ImVec2& b) static inline ImVec2 ImRotate(const ImVec2& v, float cos_a, float sin_a) { return ImVec2(v.x * cos_a - v.y * sin_a, v.x * sin_a + v.y * cos_a); } static inline float ImLinearSweep(float current, float target, float speed) { if (current < target) return ImMin(current + speed, target); if (current > target) return ImMax(current - speed, target); return current; } static inline ImVec2 ImMul(const ImVec2& lhs, const ImVec2& rhs) { return ImVec2(lhs.x * rhs.x, lhs.y * rhs.y); } +static inline float ImPow(float x, float y) { return powf(x, y); } +static inline double ImPow(double x, double y) { return pow(x, y); } //----------------------------------------------------------------------------- // Types