diff --git a/ChangeLog.md b/ChangeLog.md index 5c5b1491a..2784bb6b3 100644 --- a/ChangeLog.md +++ b/ChangeLog.md @@ -10,7 +10,7 @@ Nazara Engine: - Fix reflection sometimes being enabled by default for Materials - Fix built-in unserialization of std::string which was corruption memory - Fix Buffer::Destroy() not really destroying buffer - +- ⚠️ Reworked Flags class, replaced EnumAsFlags::value by IsEnumFlag::value, EnumAsFlags no longer need to contains a `value` field. The `max` field can also be of the same type as the enum. Nazara Development Kit: - Added ImageWidget (#139) diff --git a/include/Nazara/Core/Enums.hpp b/include/Nazara/Core/Enums.hpp index 937c01a44..fd171fc86 100644 --- a/include/Nazara/Core/Enums.hpp +++ b/include/Nazara/Core/Enums.hpp @@ -94,8 +94,7 @@ namespace Nz template<> struct EnumAsFlags { - static constexpr bool value = true; - static constexpr int max = OpenMode_Max; + static constexpr OpenMode max = OpenMode_Max; }; using OpenModeFlags = Flags; @@ -198,8 +197,7 @@ namespace Nz template<> struct EnumAsFlags { - static constexpr bool value = true; - static constexpr int max = StreamOption_Max; + static constexpr StreamOption max = StreamOption_Max; }; using StreamOptionFlags = Flags; diff --git a/include/Nazara/Core/Flags.hpp b/include/Nazara/Core/Flags.hpp index b7dff544b..b2f4ca864 100644 --- a/include/Nazara/Core/Flags.hpp +++ b/include/Nazara/Core/Flags.hpp @@ -16,18 +16,34 @@ namespace Nz template struct EnumAsFlags { - static constexpr bool value = false; - static constexpr int max = 0; + }; + + // From: https://stackoverflow.com/questions/11927032/sfinae-check-for-static-member-using-decltype + template + class IsEnumFlag + { + template::max)>::value>::type> + static std::true_type check(int); + + template static std::false_type check(...); + + public: + static constexpr bool value = decltype(check(0))::value; }; template class Flags { static_assert(std::is_enum::value, "Type must be an enumeration"); - static_assert(EnumAsFlags::value, "Enum has not been enabled as flags by an EnumAsFlags specialization"); + static_assert(IsEnumFlag::value, "Enum has not been enabled as flags by an EnumAsFlags specialization"); + + static constexpr std::size_t MaxValue = static_cast(EnumAsFlags::max); + + using BitField16 = typename std::conditional<(MaxValue > 8), UInt16, UInt8>::type; + using BitField32 = typename std::conditional<(MaxValue > 16), UInt32, BitField16>::type; public: - using BitField = typename std::conditional<(EnumAsFlags::max > 32), UInt64, UInt32>::type; + using BitField = typename std::conditional<(MaxValue > 32), UInt64, BitField32>::type; constexpr Flags(BitField value = 0); constexpr Flags(E enumVal); @@ -49,7 +65,7 @@ namespace Nz static constexpr BitField GetFlagValue(E enumValue); - static constexpr BitField ValueMask = ((BitField(1) << (EnumAsFlags::max + 1)) - 1); + static constexpr BitField ValueMask = ((BitField(1) << (MaxValue + 1)) - 1); private: BitField m_value; @@ -58,10 +74,10 @@ namespace Nz // Little hack to have them in both Nz and global scope namespace FlagsOperators { - template constexpr std::enable_if_t::value, Flags> operator~(E lhs); - template constexpr std::enable_if_t::value, Flags> operator|(E lhs, E rhs); - template constexpr std::enable_if_t::value, Flags> operator&(E lhs, E rhs); - template constexpr std::enable_if_t::value, Flags> operator^(E lhs, E rhs); + template constexpr std::enable_if_t::value, Flags> operator~(E lhs); + template constexpr std::enable_if_t::value, Flags> operator|(E lhs, E rhs); + template constexpr std::enable_if_t::value, Flags> operator&(E lhs, E rhs); + template constexpr std::enable_if_t::value, Flags> operator^(E lhs, E rhs); } using namespace FlagsOperators; diff --git a/include/Nazara/Core/Flags.inl b/include/Nazara/Core/Flags.inl index 1899e7576..35fd1d04e 100644 --- a/include/Nazara/Core/Flags.inl +++ b/include/Nazara/Core/Flags.inl @@ -222,7 +222,7 @@ namespace Nz * Returns a Flags object with all state enabled except for the enum one. */ template - constexpr std::enable_if_t::value, Flags> operator~(E lhs) + constexpr std::enable_if_t::value, Flags> operator~(E lhs) { return ~Flags(lhs); } @@ -237,7 +237,7 @@ namespace Nz * Returns a Flags object with combined states from the two enumeration values. */ template - constexpr std::enable_if_t::value, Flags> operator|(E lhs, E rhs) + constexpr std::enable_if_t::value, Flags> operator|(E lhs, E rhs) { return Flags(lhs) | rhs; } @@ -253,7 +253,7 @@ namespace Nz * In this case, only one flag will be enabled if both enumeration values are the same. */ template - constexpr std::enable_if_t::value, Flags> operator&(E lhs, E rhs) + constexpr std::enable_if_t::value, Flags> operator&(E lhs, E rhs) { return Flags(lhs) & rhs; } @@ -269,7 +269,7 @@ namespace Nz * In this case, two flags will be enabled if both the enumeration values are different. */ template - constexpr std::enable_if_t::value, Flags> operator^(E lhs, E rhs) + constexpr std::enable_if_t::value, Flags> operator^(E lhs, E rhs) { return Flags(lhs) ^ rhs; } diff --git a/include/Nazara/Lua/LuaState.inl b/include/Nazara/Lua/LuaState.inl index 12fcdb226..0e95ede6b 100644 --- a/include/Nazara/Lua/LuaState.inl +++ b/include/Nazara/Lua/LuaState.inl @@ -70,21 +70,21 @@ namespace Nz } template - std::enable_if_t::value && !EnumAsFlags::value, unsigned int> LuaImplQueryArg(const LuaState& instance, int index, T* arg, TypeTag) + std::enable_if_t::value && !IsEnumFlag::value, unsigned int> LuaImplQueryArg(const LuaState& instance, int index, T* arg, TypeTag) { using UnderlyingT = std::underlying_type_t; return LuaImplQueryArg(instance, index, reinterpret_cast(arg), TypeTag()); } template - std::enable_if_t::value && !EnumAsFlags::value, unsigned int> LuaImplQueryArg(const LuaState& instance, int index, T* arg, T defValue, TypeTag) + std::enable_if_t::value && !IsEnumFlag::value, unsigned int> LuaImplQueryArg(const LuaState& instance, int index, T* arg, T defValue, TypeTag) { using UnderlyingT = std::underlying_type_t; return LuaImplQueryArg(instance, index, reinterpret_cast(arg), static_cast(defValue), TypeTag()); } template - std::enable_if_t::value && EnumAsFlags::value, unsigned int> LuaImplQueryArg(const LuaState& instance, int index, T* arg, TypeTag) + std::enable_if_t::value && IsEnumFlag::value, unsigned int> LuaImplQueryArg(const LuaState& instance, int index, T* arg, TypeTag) { using UnderlyingT = std::underlying_type_t; @@ -96,7 +96,7 @@ namespace Nz } template - std::enable_if_t::value && EnumAsFlags::value, unsigned int> LuaImplQueryArg(const LuaState& instance, int index, T* arg, T defValue, TypeTag) + std::enable_if_t::value && IsEnumFlag::value, unsigned int> LuaImplQueryArg(const LuaState& instance, int index, T* arg, T defValue, TypeTag) { using UnderlyingT = std::underlying_type_t; @@ -186,14 +186,14 @@ namespace Nz } template - std::enable_if_t::value && !EnumAsFlags::value, int> LuaImplReplyVal(const LuaState& instance, T val, TypeTag) + std::enable_if_t::value && !IsEnumFlag::value, int> LuaImplReplyVal(const LuaState& instance, T val, TypeTag) { using EnumT = typename std::underlying_type::type; return LuaImplReplyVal(instance, static_cast(val), TypeTag()); } template - std::enable_if_t::value && EnumAsFlags::value, int> LuaImplReplyVal(const LuaState& instance, T val, TypeTag) + std::enable_if_t::value && IsEnumFlag::value, int> LuaImplReplyVal(const LuaState& instance, T val, TypeTag) { Flags flags(val); return LuaImplReplyVal(instance, flags, TypeTag()); @@ -202,7 +202,7 @@ namespace Nz template int LuaImplReplyVal(const LuaState& instance, Flags val, TypeTag>) { - instance.PushInteger(UInt32(val)); + instance.PushInteger(Flags::BitField(val)); return 1; } diff --git a/include/Nazara/Network/ENetPacket.hpp b/include/Nazara/Network/ENetPacket.hpp index 54b0c42c6..8d224a0f4 100644 --- a/include/Nazara/Network/ENetPacket.hpp +++ b/include/Nazara/Network/ENetPacket.hpp @@ -22,8 +22,7 @@ namespace Nz template<> struct EnumAsFlags { - static constexpr bool value = true; - static constexpr int max = ENetPacketFlag_UnreliableFragment; + static constexpr ENetPacketFlag max = ENetPacketFlag_UnreliableFragment; }; using ENetPacketFlags = Flags; diff --git a/include/Nazara/Network/Enums.hpp b/include/Nazara/Network/Enums.hpp index 39bce0dd0..42089b6a4 100644 --- a/include/Nazara/Network/Enums.hpp +++ b/include/Nazara/Network/Enums.hpp @@ -102,8 +102,7 @@ namespace Nz template<> struct EnumAsFlags { - static constexpr bool value = true; - static constexpr int max = SocketPollEvent_Max; + static constexpr SocketPollEvent max = SocketPollEvent_Max; }; using SocketPollEventFlags = Flags; diff --git a/include/Nazara/Platform/Enums.hpp b/include/Nazara/Platform/Enums.hpp index 252412904..77b69f65e 100644 --- a/include/Nazara/Platform/Enums.hpp +++ b/include/Nazara/Platform/Enums.hpp @@ -73,8 +73,7 @@ namespace Nz template<> struct EnumAsFlags { - static constexpr bool value = true; - static constexpr int max = WindowStyle_Max; + static constexpr WindowStyle max = WindowStyle_Max; }; using WindowStyleFlags = Flags; diff --git a/include/Nazara/Utility/Enums.hpp b/include/Nazara/Utility/Enums.hpp index 2fda92e70..d6fee2127 100644 --- a/include/Nazara/Utility/Enums.hpp +++ b/include/Nazara/Utility/Enums.hpp @@ -64,8 +64,7 @@ namespace Nz template<> struct EnumAsFlags { - static constexpr bool value = true; - static constexpr int max = BufferUsage_Max; + static constexpr BufferUsage max = BufferUsage_Max; }; using BufferUsageFlags = Flags; diff --git a/include/Nazara/Utility/Formats/MD5AnimParser.hpp b/include/Nazara/Utility/Formats/MD5AnimParser.hpp index f6a75165a..ca61876b3 100644 --- a/include/Nazara/Utility/Formats/MD5AnimParser.hpp +++ b/include/Nazara/Utility/Formats/MD5AnimParser.hpp @@ -69,12 +69,12 @@ namespace Nz std::vector m_frames; std::vector m_joints; Stream& m_stream; + StreamOptionFlags m_streamFlags; String m_currentLine; bool m_keepLastLine; unsigned int m_frameIndex; unsigned int m_frameRate; unsigned int m_lineCount; - unsigned int m_streamFlags; }; } diff --git a/include/Nazara/Utility/Formats/MD5MeshParser.hpp b/include/Nazara/Utility/Formats/MD5MeshParser.hpp index d40b40d4e..880236ac4 100644 --- a/include/Nazara/Utility/Formats/MD5MeshParser.hpp +++ b/include/Nazara/Utility/Formats/MD5MeshParser.hpp @@ -75,11 +75,11 @@ namespace Nz std::vector m_joints; std::vector m_meshes; Stream& m_stream; + StreamOptionFlags m_streamFlags; String m_currentLine; bool m_keepLastLine; unsigned int m_lineCount; unsigned int m_meshIndex; - unsigned int m_streamFlags; }; } diff --git a/src/Nazara/Utility/Formats/MD5AnimParser.cpp b/src/Nazara/Utility/Formats/MD5AnimParser.cpp index 145811afc..2d343f07c 100644 --- a/src/Nazara/Utility/Formats/MD5AnimParser.cpp +++ b/src/Nazara/Utility/Formats/MD5AnimParser.cpp @@ -12,11 +12,11 @@ namespace Nz { MD5AnimParser::MD5AnimParser(Stream& stream) : m_stream(stream), + m_streamFlags(stream.GetStreamOptions()), //< Saves stream flags m_keepLastLine(false), m_frameIndex(0), m_frameRate(0), - m_lineCount(0), - m_streamFlags(stream.GetStreamOptions()) //< Saves stream flags + m_lineCount(0) { m_stream.EnableTextMode(true); } diff --git a/src/Nazara/Utility/Formats/MD5MeshParser.cpp b/src/Nazara/Utility/Formats/MD5MeshParser.cpp index 04816746d..0e719c90f 100644 --- a/src/Nazara/Utility/Formats/MD5MeshParser.cpp +++ b/src/Nazara/Utility/Formats/MD5MeshParser.cpp @@ -13,10 +13,10 @@ namespace Nz { MD5MeshParser::MD5MeshParser(Stream& stream) : m_stream(stream), + m_streamFlags(stream.GetStreamOptions()), //< Saves stream flags m_keepLastLine(false), m_lineCount(0), - m_meshIndex(0), - m_streamFlags(stream.GetStreamOptions()) //< Saves stream flags + m_meshIndex(0) { m_stream.EnableTextMode(true); }