MeshLib
 
Loading...
Searching...
No Matches
MRImGuiVectorOperators.h
Go to the documentation of this file.
1#pragma once
2
3#include <concepts>
4#include <type_traits>
5
6#include <imgui.h>
7
8// Utilities.
9namespace MR::ImGuiMath
10{
11 namespace detail
12 {
13 template <typename T>
14 concept Scalar = std::is_arithmetic_v<T>;
15
16 template <typename T>
17 concept Vector = std::same_as<T, ImVec2> || std::same_as<T, ImVec4>;
18
19 template <typename T>
21
22 template <typename T>
24
25 template <typename T> struct VecSize : std::integral_constant<int, 1> {};
26 template <> struct VecSize<ImVec2> : std::integral_constant<int, 2> {};
27 template <> struct VecSize<ImVec4> : std::integral_constant<int, 4> {};
28
29 template <int N> struct VecFromSize {};
30 template <> struct VecFromSize<2> { using type = ImVec2; };
31 template <> struct VecFromSize<4> { using type = ImVec4; };
32
33 // Returns the common vector size between `P...` (cvref-qualifiers are ignored).
34 // If there are no vectors in the list, returns `1`.
35 // If there are some vectors, returns their size. If the vectors have different sizes, returns -1 to indicate failure.
36 template <typename ...P>
37 struct CommonVecSize : std::integral_constant<int, 1> {};
38 template <typename T, typename ...P>
39 struct CommonVecSize<T, P...>
40 {
41 static constexpr int cur = VecSize<std::remove_cvref_t<T>>::value;
42 static constexpr int next = CommonVecSize<P...>::value;
43 static constexpr int value =
44 cur == 1 || cur == next ? next :
45 next == 1 ? cur :
46 -1;
47 };
48
49 // Whether `P...` are valid operands for a custom operator.
50 // All of them must be vectors and scalars (maybe cvref-qualified), and the common vector size must be defined and greater than 1.
51 template <typename ...P>
52 concept ValidOperands = ( VectorOrScalarMaybeCvref<P> && ... ) && ( CommonVecSize<P...>::value > 1 );
53 }
54
55 template <detail::VectorOrScalarMaybeCvref T>
56 [[nodiscard]] constexpr auto&& getElem( int i, T&& value )
57 {
59 {
60 return value;
61 }
62 else
63 {
64 // Technically UB, but helps with optimizations on MSVC for some reason, compared to an if-else chain.
65 // GCC and Clang optimize both in the same manner.
66 return ( &value.x )[i];
67 }
68 }
69
70 // Returns a vector, where each element is computed by appling `func()` to individual elements of the `params...`.
71 // Scalar parameters are accepted too.
72 template <typename F, typename ...P> requires detail::ValidOperands<P...>
73 [[nodiscard]] constexpr auto applyElementwise( F&& func, P&&... params ) -> typename detail::VecFromSize<detail::CommonVecSize<P...>::value>::type
74 {
75 constexpr int n = detail::CommonVecSize<P...>::value;
77 for (int i = 0; i < n; i++)
78 getElem( i, ret ) = func( getElem( i, params )... );
79 return ret;
80 }
81
82 // Reduces a vector over a binary `func`.
83 template <typename F, detail::VectorOrScalarMaybeCvref T>
84 [[nodiscard]] constexpr auto reduce( F&& func, T&& value )
85 {
86 if constexpr ( std::is_same_v<std::remove_cvref_t<T>, ImVec2> )
87 return func( value.x, value.y );
88 else if constexpr ( std::is_same_v<std::remove_cvref_t<T>, ImVec2> )
89 return func( func( value.x, value.y ), func( value.x, value.w ) );
90 else
91 return value;
92 }
93}
94
95// Operators.
96
97template <MR::ImGuiMath::detail::Vector A> [[nodiscard]] constexpr A operator+( A a ) { return a; }
98template <MR::ImGuiMath::detail::Vector A> [[nodiscard]] constexpr A operator-( A a ) { return MR::ImGuiMath::applyElementwise( std::negate{}, a ); }
99
100template <typename A, typename B> requires MR::ImGuiMath::detail::ValidOperands<A, B>
101[[nodiscard]] constexpr auto operator+( A a, B b ) { return MR::ImGuiMath::applyElementwise( std::plus{}, a, b ); }
102
103template <typename A, typename B> requires MR::ImGuiMath::detail::ValidOperands<A, B>
104[[nodiscard]] constexpr auto operator-( A a, B b ) { return MR::ImGuiMath::applyElementwise( std::minus{}, a, b ); }
105
106template <typename A, typename B> requires MR::ImGuiMath::detail::ValidOperands<A, B>
107[[nodiscard]] constexpr auto operator*( A a, B b ) { return MR::ImGuiMath::applyElementwise( std::multiplies{}, a, b ); }
108
109template <typename A, typename B> requires MR::ImGuiMath::detail::ValidOperands<A, B>
110[[nodiscard]] constexpr auto operator/( A a, B b ) { return MR::ImGuiMath::applyElementwise( std::divides{}, a, b ); }
111
112template <MR::ImGuiMath::detail::Vector A, MR::ImGuiMath::detail::VectorOrScalar B> constexpr A& operator+=( A& a, B b ) { return a = a + b; }
113template <MR::ImGuiMath::detail::Vector A, MR::ImGuiMath::detail::VectorOrScalar B> constexpr A& operator-=( A& a, B b ) { return a = a - b; }
114template <MR::ImGuiMath::detail::Vector A, MR::ImGuiMath::detail::VectorOrScalar B> constexpr A& operator*=( A& a, B b ) { return a = a * b; }
115template <MR::ImGuiMath::detail::Vector A, MR::ImGuiMath::detail::VectorOrScalar B> constexpr A& operator/=( A& a, B b ) { return a = a / b; }
116
117[[nodiscard]] constexpr bool operator==( ImVec2 a, ImVec2 b ) { return a.x == b.x && a.y == b.y; }
118[[nodiscard]] constexpr bool operator==( ImVec4 a, ImVec4 b ) { return a.x == b.x && a.y == b.y && a.z == b.z && a.w == b.w; }
119// C++20 generates `!=` from `==`.
120
121namespace MR::ImGuiMath
122{
123 // Misc functions.
124
125 template <detail::Vector A> [[nodiscard]] constexpr A round( A a ) { return (applyElementwise)( []( auto x ){ return std::round( x ); }, a ); }
126 template <detail::Vector A> [[nodiscard]] constexpr A floor( A a ) { return (applyElementwise)( []( auto x ){ return std::floor( x ); }, a ); }
127 template <detail::Vector A> [[nodiscard]] constexpr A ceil( A a ) { return (applyElementwise)( []( auto x ){ return std::ceil( x ); }, a ); }
128
129 template <detail::Vector A> [[nodiscard]] constexpr auto dot( A a, A b ) { return reduce( std::plus{}, a * b ); }
130
131 template <detail::Vector A> [[nodiscard]] constexpr auto lengthSq( A a ) { return (dot)( a, a ); }
132 template <detail::Vector A> [[nodiscard]] constexpr auto length( A a ) { return std::sqrt( lengthSq( a ) ); }
133
134 template <detail::Vector A> [[nodiscard]] constexpr A normalize( A a ) { auto l = length( a ); return l ? a / l : a; }
135
136 [[nodiscard]] constexpr ImVec2 rot90( ImVec2 a ) { return ImVec2( -a.y, a.x ); }
137
138 template <detail::Vector A, detail::Scalar B> [[nodiscard]] constexpr A mix( B t, A a, A b ) { return a * ( 1 - t ) + b * t; }
139
140 template <typename A, typename B> requires detail::ValidOperands<A, B>
141 [[nodiscard]] constexpr auto min( A a, B b ) { return (applyElementwise)( []( auto x, auto y ){ return x < y ? x : y; }, a, b ); }
142 template <typename A, typename B> requires detail::ValidOperands<A, B>
143 [[nodiscard]] constexpr auto max( A a, B b ) { return (applyElementwise)( []( auto x, auto y ){ return x > y ? x : y; }, a, b ); }
144
145 template <detail::Vector T, typename A, typename B> requires detail::ValidOperands<T, A, B>
146 [[nodiscard]] constexpr T clamp( T value, A a, B b ) { return (max)( (min)( value, b ), a ); }
147
148 // Comparison helpers.
149
150 // Usage: `Compare{Any,All}( vector ) @ vector_or_scalar`.
151 // For example: `CompareAll( vector ) >= 42`.
152
153 template <typename Derived, detail::VectorOrScalar A, bool All>
155 {
157
159
160 template <typename F, detail::ValidOperands<A> B>
161 [[nodiscard]] constexpr bool compare( F&& func, B other ) const
162 {
163 for ( int i = 0; i < detail::VecSize<A>::value; i++ )
164 {
165 if ( func( getElem( i, value ), getElem( i, other ) ) != All )
166 return !All;
167 }
168 return All;
169 }
170
171 template <detail::ValidOperands<A> B> [[nodiscard]] constexpr bool operator==( B other ) const { return compare( std::equal_to{}, other ); }
172 template <detail::ValidOperands<A> B> [[nodiscard]] constexpr bool operator!=( B other ) const { return compare( std::not_equal_to{}, other ); }
173 template <detail::ValidOperands<A> B> [[nodiscard]] constexpr bool operator< ( B other ) const { return compare( std::less{}, other ); }
174 template <detail::ValidOperands<A> B> [[nodiscard]] constexpr bool operator> ( B other ) const { return compare( std::greater{}, other ); }
175 template <detail::ValidOperands<A> B> [[nodiscard]] constexpr bool operator<=( B other ) const { return compare( std::less_equal{}, other ); }
176 template <detail::ValidOperands<A> B> [[nodiscard]] constexpr bool operator>=( B other ) const { return compare( std::greater_equal{}, other ); }
177 };
178
179 template <detail::VectorOrScalar A>
180 struct CompareAll : BasicVectorCompareHelper<CompareAll<A>, A, true>
181 {
183 };
184 template <detail::VectorOrScalar A>
186
187 template <detail::VectorOrScalar A>
188 struct CompareAny : BasicVectorCompareHelper<CompareAll<A>, A, false>
189 {
191 };
192 template <detail::VectorOrScalar A>
194}
constexpr A & operator*=(A &a, B b)
Definition MRImGuiVectorOperators.h:114
constexpr bool operator==(ImVec2 a, ImVec2 b)
Definition MRImGuiVectorOperators.h:117
constexpr A operator-(A a)
Definition MRImGuiVectorOperators.h:98
constexpr A operator+(A a)
Definition MRImGuiVectorOperators.h:97
constexpr auto operator*(A a, B b)
Definition MRImGuiVectorOperators.h:107
constexpr A & operator-=(A &a, B b)
Definition MRImGuiVectorOperators.h:113
constexpr A & operator/=(A &a, B b)
Definition MRImGuiVectorOperators.h:115
constexpr A & operator+=(A &a, B b)
Definition MRImGuiVectorOperators.h:112
constexpr auto operator/(A a, B b)
Definition MRImGuiVectorOperators.h:110
length
Definition MRObjectDimensionsEnum.h:14
Definition MRImGuiVectorOperators.h:14
Definition MRImGuiVectorOperators.h:52
Definition MRImGuiVectorOperators.h:23
Definition MRImGuiVectorOperators.h:20
Definition MRImGuiVectorOperators.h:17
Definition MRImGuiVectorOperators.h:10
constexpr auto max(A a, B b)
Definition MRImGuiVectorOperators.h:143
constexpr A mix(B t, A a, A b)
Definition MRImGuiVectorOperators.h:138
constexpr A round(A a)
Definition MRImGuiVectorOperators.h:125
constexpr A normalize(A a)
Definition MRImGuiVectorOperators.h:134
constexpr A ceil(A a)
Definition MRImGuiVectorOperators.h:127
CompareAny(A) -> CompareAny< A >
constexpr ImVec2 rot90(ImVec2 a)
Definition MRImGuiVectorOperators.h:136
constexpr T clamp(T value, A a, B b)
Definition MRImGuiVectorOperators.h:146
constexpr auto && getElem(int i, T &&value)
Definition MRImGuiVectorOperators.h:56
CompareAll(A) -> CompareAll< A >
constexpr auto applyElementwise(F &&func, P &&... params) -> typename detail::VecFromSize< detail::CommonVecSize< P... >::value >::type
Definition MRImGuiVectorOperators.h:73
constexpr auto lengthSq(A a)
Definition MRImGuiVectorOperators.h:131
constexpr auto dot(A a, A b)
Definition MRImGuiVectorOperators.h:129
constexpr auto min(A a, B b)
Definition MRImGuiVectorOperators.h:141
constexpr auto reduce(F &&func, T &&value)
Definition MRImGuiVectorOperators.h:84
constexpr A floor(A a)
Definition MRImGuiVectorOperators.h:126
Definition MRImGuiVectorOperators.h:155
constexpr bool operator>=(B other) const
Definition MRImGuiVectorOperators.h:176
constexpr bool compare(F &&func, B other) const
Definition MRImGuiVectorOperators.h:161
constexpr bool operator!=(B other) const
Definition MRImGuiVectorOperators.h:172
constexpr bool operator>(B other) const
Definition MRImGuiVectorOperators.h:174
A value
Definition MRImGuiVectorOperators.h:156
constexpr BasicVectorCompareHelper(A value)
Definition MRImGuiVectorOperators.h:158
constexpr bool operator==(B other) const
Definition MRImGuiVectorOperators.h:171
constexpr bool operator<(B other) const
Definition MRImGuiVectorOperators.h:173
constexpr bool operator<=(B other) const
Definition MRImGuiVectorOperators.h:175
Definition MRImGuiVectorOperators.h:181
Definition MRImGuiVectorOperators.h:189
Definition MRImGuiVectorOperators.h:37
ImVec2 type
Definition MRImGuiVectorOperators.h:30
ImVec4 type
Definition MRImGuiVectorOperators.h:31
Definition MRImGuiVectorOperators.h:29
Definition MRImGuiVectorOperators.h:25