diff --git a/src/Contexts/EglContext.h b/src/Contexts/EglContext.h index 62e20be7e..29a961856 100644 --- a/src/Contexts/EglContext.h +++ b/src/Contexts/EglContext.h @@ -100,7 +100,54 @@ class EglContext: public AbstractContext { Home = XK_Home, /**< Home */ End = XK_End, /**< End */ PageUp = XK_Page_Up, /**< Page up */ - PageDown = XK_Page_Down /**< Page down */ + PageDown = XK_Page_Down, /**< Page down */ + + Space = XK_space, /**< Space */ + Comma = XK_comma, /**< Comma */ + Period = XK_period, /**< Period */ + Minus = XK_minus, /**< Minus */ + Plus = XK_plus, /**< Plus */ + Slash = XK_slash, /**< Slash */ + Percent = XK_percent, /**< Percent */ + Equal = XK_equal, /**< Equal */ + + Zero = XK_0, /**< Zero */ + One = XK_1, /**< One */ + Two = XK_2, /**< Two */ + Three = XK_3, /**< Three */ + Four = XK_4, /**< Four */ + Five = XK_5, /**< Five */ + Six = XK_6, /**< Six */ + Seven = XK_7, /**< Seven */ + Eight = XK_8, /**< Eight */ + Nine = XK_9, /**< Nine */ + + A = XK_a, /**< Small letter A */ + B = XK_b, /**< Small letter B */ + C = XK_c, /**< Small letter C */ + D = XK_d, /**< Small letter D */ + E = XK_e, /**< Small letter E */ + F = XK_f, /**< Small letter F */ + G = XK_g, /**< Small letter G */ + H = XK_h, /**< Small letter H */ + I = XK_i, /**< Small letter I */ + J = XK_j, /**< Small letter J */ + K = XK_k, /**< Small letter K */ + L = XK_l, /**< Small letter L */ + M = XK_m, /**< Small letter M */ + N = XK_n, /**< Small letter N */ + O = XK_o, /**< Small letter O */ + P = XK_p, /**< Small letter P */ + Q = XK_q, /**< Small letter Q */ + R = XK_r, /**< Small letter R */ + S = XK_s, /**< Small letter S */ + T = XK_t, /**< Small letter T */ + U = XK_u, /**< Small letter U */ + V = XK_v, /**< Small letter V */ + W = XK_w, /**< Small letter W */ + X = XK_x, /**< Small letter X */ + Y = XK_y, /**< Small letter Y */ + Z = XK_z /**< Small letter Z */ }; protected: diff --git a/src/Math/Matrix.h b/src/Math/Matrix.h index 9b63625c5..f89032887 100644 --- a/src/Math/Matrix.h +++ b/src/Math/Matrix.h @@ -26,16 +26,6 @@ namespace Magnum { namespace Math { #ifndef DOXYGEN_GENERATING_OUTPUT namespace Implementation { template class MatrixDeterminant; - - template struct Sequence {}; - - /* E.g. GenerateSequence<3>::Type is Sequence<0, 1, 2> */ - template struct GenerateSequence: - GenerateSequence {}; - - template struct GenerateSequence<0, sequence...> { - typedef Sequence Type; - }; } #endif diff --git a/src/Math/Swizzle.h b/src/Math/Swizzle.h index cfbec9290..e964948a6 100644 --- a/src/Math/Swizzle.h +++ b/src/Math/Swizzle.h @@ -48,6 +48,26 @@ namespace Implementation { template struct TypeForSize<2, T> { typedef Vector2 Type; }; template struct TypeForSize<3, T> { typedef Vector3 Type; }; template struct TypeForSize<4, T> { typedef Vector4 Type; }; + + inline constexpr size_t getPosition(size_t size, size_t position) { + return size > position ? position : throw; + } + + template inline constexpr size_t getComponent(char component) { + return component == 'x' ? getPosition(size, 0) : + component == 'y' ? getPosition(size, 1) : + component == 'z' ? getPosition(size, 2) : + component == 'w' ? getPosition(size, 3) : + component == 'r' ? getPosition(size, 0) : + component == 'g' ? getPosition(size, 1) : + component == 'b' ? getPosition(size, 2) : + component == 'a' ? getPosition(size, 3) : + throw; + } + + template inline constexpr Vector swizzleFrom(Sequence, const Vector& vector, const char(&components)[sizeof...(sequence)+1]) { + return {vector[getComponent(components[sequence])]...}; + } } #endif @@ -66,12 +86,43 @@ elements is unlimited, but must be at least one. If the resulting vector is two, three or four-component, corresponding Vector2, Vector3 or Vector4 specialization is returned. +@attention This function is less convenient to write than +swizzle(const Vector&, const char(&)[newSize]), but the evaluation of +the swizzling operation is guaranteed to be always done at compile time +instead of at runtime. + @see Vector4::xyz(), Vector4::rgb(), Vector4::xy(), Vector3::xy() */ template inline constexpr typename Implementation::TypeForSize::Type swizzle(const Vector& vector) { return {vector[Implementation::GetComponent::value()]...}; } +/** +@brief Swizzle Vector components + +Creates new vector from given components. Example: +@code +Vector4 original(1, 2, 3, 4); + +auto vec = swizzle(original, "abbgrr"); +// vec == { 4, 3, 3, 2, 1, 1 } +@endcode +You can use letters `x`, `y`, `z`, `w` and `r`, `g`, `b`, `a`. Count of +elements is unlimited, but must be at least one. If the resulting vector is +two, three or four-component, corresponding Vector2, Vector3 or Vector4 +specialization is returned. + +@attention This function is more convenient to write than +swizzle(const Vector&), but unless the result is marked with +`constexpr`, the evaluation of the swizzling operation probably won't be +evaluated at compile time, but at runtime. + +@see Vector4::xyz(), Vector4::rgb(), Vector4::xy(), Vector3::xy() +*/ +template inline constexpr typename Implementation::TypeForSize::Type swizzle(const Vector& vector, const char(&components)[newSize]) { + return Implementation::swizzleFrom(typename Implementation::GenerateSequence::Type(), vector, components); +} + }} #endif diff --git a/src/Math/Test/SwizzleTest.cpp b/src/Math/Test/SwizzleTest.cpp index 2560a02ed..298b7dba6 100644 --- a/src/Math/Test/SwizzleTest.cpp +++ b/src/Math/Test/SwizzleTest.cpp @@ -30,31 +30,52 @@ typedef Math::Vector4 Vector4; SwizzleTest::SwizzleTest() { addTests(&SwizzleTest::xyzw, &SwizzleTest::rgba, + &SwizzleTest::fromSmall, &SwizzleTest::type, &SwizzleTest::defaultType); } void SwizzleTest::xyzw() { Vector4 orig(2, 4, 5, 7); - CORRADE_COMPARE((swizzle<'z', 'x', 'w', 'y'>(orig)), Vector4(5, 2, 7, 4)); + Vector4 swizzled(5, 2, 7, 4); + CORRADE_COMPARE(swizzle(orig, "zxwy"), swizzled); + CORRADE_COMPARE((swizzle<'z', 'x', 'w', 'y'>(orig)), swizzled); } void SwizzleTest::rgba() { Vector4 orig(2, 4, 5, 7); - CORRADE_COMPARE((swizzle<'b', 'r', 'a', 'g'>(orig)), Vector4(5, 2, 7, 4)); + Vector4 swizzled(5, 2, 7, 4); + CORRADE_COMPARE(swizzle(orig, "brag"), swizzled); + CORRADE_COMPARE((swizzle<'b', 'r', 'a', 'g'>(orig)), swizzled); +} + +void SwizzleTest::fromSmall() { + /* Force compile-time evaluation for both */ + constexpr Vector2 orig(1, 2); + CORRADE_VERIFY((integral_constant::value)); + CORRADE_COMPARE((swizzle<'g', 'x', 'r'>(orig)), Vector3(2, 1, 1)); } void SwizzleTest::type() { Vector4 orig; CORRADE_VERIFY((is_same(orig)), Vector2>::value)); + CORRADE_VERIFY((is_same::value)); CORRADE_VERIFY((is_same(orig)), Vector3>::value)); + CORRADE_VERIFY((is_same::value)); CORRADE_VERIFY((is_same(orig)), Vector4>::value)); + CORRADE_VERIFY((is_same::value)); } void SwizzleTest::defaultType() { Vector4 orig(1, 2, 3, 4); - CORRADE_COMPARE(swizzle<'b'>(orig), (Vector<1, int>(3))); - CORRADE_COMPARE((swizzle<'b', 'r', 'a', 'g', 'z', 'y', 'x'>(orig)), (Vector<7, int>(3, 1, 4, 2, 3, 2, 1))); + + Vector<1, int> b(3); + CORRADE_COMPARE(swizzle<'b'>(orig), b); + CORRADE_COMPARE(swizzle(orig, "b"), b); + + Vector<7, int> bragzyx(3, 1, 4, 2, 3, 2, 1); + CORRADE_COMPARE((swizzle<'b', 'r', 'a', 'g', 'z', 'y', 'x'>(orig)), bragzyx); + CORRADE_COMPARE(swizzle(orig, "bragzyx"), bragzyx); } }}} diff --git a/src/Math/Test/SwizzleTest.h b/src/Math/Test/SwizzleTest.h index f68a05e45..a08dfdd17 100644 --- a/src/Math/Test/SwizzleTest.h +++ b/src/Math/Test/SwizzleTest.h @@ -25,6 +25,7 @@ class SwizzleTest: public Corrade::TestSuite::Tester { void xyzw(); void rgba(); + void fromSmall(); void type(); void defaultType(); }; diff --git a/src/Math/Vector.h b/src/Math/Vector.h index 0a56fa479..7bd884fbc 100644 --- a/src/Math/Vector.h +++ b/src/Math/Vector.h @@ -26,11 +26,21 @@ namespace Magnum { namespace Math { -/** -@brief %Vector +#ifndef DOXYGEN_GENERATING_OUTPUT +namespace Implementation { + template struct Sequence {}; -@todo Swizzling -*/ + /* E.g. GenerateSequence<3>::Type is Sequence<0, 1, 2> */ + template struct GenerateSequence: + GenerateSequence {}; + + template struct GenerateSequence<0, sequence...> { + typedef Sequence Type; + }; +} +#endif + +/** @brief %Vector */ template class Vector { public: const static size_t Size = size; /**< @brief %Vector size */