Browse Source

Use FlagSet<> for storing masks.

Author of FlagSet.h is Eugene Kozlov (https://github.com/eugeneko/).
Rokas Kupstys 7 years ago
parent
commit
966590d8e7
68 changed files with 1188 additions and 841 deletions
  1. 4 4
      Source/Samples/49_Urho2DIsometricDemo/Character2D.cpp
  2. 3 3
      Source/Samples/50_Urho2DPlatformer/Character2D.cpp
  3. 4 4
      Source/Samples/Sample.inl
  4. 1 1
      Source/Tools/AssetImporter/AssetImporter.cpp
  5. 2 2
      Source/Tools/OgreImporter/OgreImporterUtils.h
  6. 240 0
      Source/Urho3D/Container/FlagSet.h
  7. 27 22
      Source/Urho3D/Core/Attribute.h
  8. 2 2
      Source/Urho3D/Engine/Engine.cpp
  9. 3 3
      Source/Urho3D/Graphics/AnimatedModel.cpp
  10. 1 1
      Source/Urho3D/Graphics/AnimatedModel.h
  11. 1 1
      Source/Urho3D/Graphics/Animation.cpp
  12. 12 9
      Source/Urho3D/Graphics/Animation.h
  13. 1 1
      Source/Urho3D/Graphics/AnimationState.cpp
  14. 1 1
      Source/Urho3D/Graphics/CustomGeometry.cpp
  15. 1 1
      Source/Urho3D/Graphics/CustomGeometry.h
  16. 5 5
      Source/Urho3D/Graphics/DecalSet.cpp
  17. 4 4
      Source/Urho3D/Graphics/Direct3D11/D3D11Graphics.cpp
  18. 1 1
      Source/Urho3D/Graphics/Direct3D11/D3D11Texture2D.cpp
  19. 1 1
      Source/Urho3D/Graphics/Direct3D11/D3D11Texture2DArray.cpp
  20. 1 1
      Source/Urho3D/Graphics/Direct3D11/D3D11Texture3D.cpp
  21. 1 1
      Source/Urho3D/Graphics/Direct3D11/D3D11TextureCube.cpp
  22. 1 1
      Source/Urho3D/Graphics/Direct3D9/D3D9Graphics.cpp
  23. 1 1
      Source/Urho3D/Graphics/Direct3D9/D3D9Texture2D.cpp
  24. 1 1
      Source/Urho3D/Graphics/Direct3D9/D3D9Texture2DArray.cpp
  25. 1 1
      Source/Urho3D/Graphics/Direct3D9/D3D9Texture3D.cpp
  26. 1 1
      Source/Urho3D/Graphics/Direct3D9/D3D9TextureCube.cpp
  27. 1 1
      Source/Urho3D/Graphics/Graphics.h
  28. 34 22
      Source/Urho3D/Graphics/GraphicsDefs.h
  29. 5 5
      Source/Urho3D/Graphics/Material.cpp
  30. 3 3
      Source/Urho3D/Graphics/Material.h
  31. 1 1
      Source/Urho3D/Graphics/Model.cpp
  32. 1 1
      Source/Urho3D/Graphics/Model.h
  33. 13 9
      Source/Urho3D/Graphics/OcclusionBuffer.cpp
  34. 1 1
      Source/Urho3D/Graphics/OpenGL/OGLGraphics.cpp
  35. 1 1
      Source/Urho3D/Graphics/OpenGL/OGLTexture2D.cpp
  36. 1 1
      Source/Urho3D/Graphics/OpenGL/OGLTexture2DArray.cpp
  37. 1 1
      Source/Urho3D/Graphics/OpenGL/OGLTexture3D.cpp
  38. 1 1
      Source/Urho3D/Graphics/OpenGL/OGLTextureCube.cpp
  39. 1 1
      Source/Urho3D/Graphics/RenderPath.h
  40. 2 2
      Source/Urho3D/Graphics/Renderer.cpp
  41. 6 6
      Source/Urho3D/Graphics/Renderer.h
  42. 1 1
      Source/Urho3D/Graphics/Skeleton.cpp
  43. 8 5
      Source/Urho3D/Graphics/Skeleton.h
  44. 2 2
      Source/Urho3D/Graphics/Texture.cpp
  45. 2 2
      Source/Urho3D/Graphics/Texture.h
  46. 2 2
      Source/Urho3D/Graphics/VertexBuffer.cpp
  47. 2 2
      Source/Urho3D/Graphics/VertexBuffer.h
  48. 40 40
      Source/Urho3D/Input/Input.cpp
  49. 17 16
      Source/Urho3D/Input/Input.h
  50. 590 0
      Source/Urho3D/Input/InputConstants.h
  51. 2 531
      Source/Urho3D/Input/InputEvents.h
  52. 2 2
      Source/Urho3D/Scene/LogicComponent.cpp
  53. 19 12
      Source/Urho3D/Scene/LogicComponent.h
  54. 12 8
      Source/Urho3D/Scene/SmoothedTransform.h
  55. 1 1
      Source/Urho3D/UI/Button.cpp
  56. 1 1
      Source/Urho3D/UI/Button.h
  57. 1 1
      Source/Urho3D/UI/CheckBox.cpp
  58. 1 1
      Source/Urho3D/UI/CheckBox.h
  59. 3 3
      Source/Urho3D/UI/LineEdit.cpp
  60. 1 1
      Source/Urho3D/UI/LineEdit.h
  61. 3 3
      Source/Urho3D/UI/ListView.cpp
  62. 3 1
      Source/Urho3D/UI/ListView.h
  63. 2 2
      Source/Urho3D/UI/ScrollView.cpp
  64. 2 2
      Source/Urho3D/UI/ScrollView.h
  65. 46 46
      Source/Urho3D/UI/UI.cpp
  66. 12 12
      Source/Urho3D/UI/UI.h
  67. 2 2
      Source/Urho3D/UI/UIElement.cpp
  68. 18 13
      Source/Urho3D/UI/UIElement.h

+ 4 - 4
Source/Samples/49_Urho2DIsometricDemo/Character2D.cpp

@@ -81,12 +81,12 @@ void Character2D::Update(float timeStep)
     float speedX = Clamp(MOVE_SPEED_X / zoom_, 0.4f, 1.0f);
     float speedY = speedX;
 
-    if (input->GetKeyDown('A') || input->GetKeyDown(KEY_LEFT))
+    if (input->GetKeyDown(KEY_A) || input->GetKeyDown(KEY_LEFT))
     {
         moveDir = moveDir + Vector3::LEFT * speedX;
         animatedSprite->SetFlipX(false); // Flip sprite (reset to default play on the X axis)
     }
-    if (input->GetKeyDown('D') || input->GetKeyDown(KEY_RIGHT))
+    if (input->GetKeyDown(KEY_D) || input->GetKeyDown(KEY_RIGHT))
     {
         moveDir = moveDir + Vector3::RIGHT * speedX;
         animatedSprite->SetFlipX(true); // Flip sprite (flip animation on the X axis)
@@ -95,9 +95,9 @@ void Character2D::Update(float timeStep)
     if (!moveDir.Equals(Vector3::ZERO))
         speedY = speedX * moveSpeedScale_;
 
-    if (input->GetKeyDown('W') || input->GetKeyDown(KEY_UP))
+    if (input->GetKeyDown(KEY_W) || input->GetKeyDown(KEY_UP))
         moveDir = moveDir + Vector3::UP * speedY;
-    if (input->GetKeyDown('S') || input->GetKeyDown(KEY_DOWN))
+    if (input->GetKeyDown(KEY_S) || input->GetKeyDown(KEY_DOWN))
         moveDir = moveDir + Vector3::DOWN * speedY;
 
     // Move

+ 3 - 3
Source/Samples/50_Urho2DPlatformer/Character2D.cpp

@@ -101,19 +101,19 @@ void Character2D::Update(float timeStep)
     // Set direction
     Vector2 moveDir = Vector2::ZERO; // Reset
 
-    if (input->GetKeyDown('A') || input->GetKeyDown(KEY_LEFT))
+    if (input->GetKeyDown(KEY_A) || input->GetKeyDown(KEY_LEFT))
     {
         moveDir = moveDir + Vector2::LEFT;
         animatedSprite->SetFlipX(false); // Flip sprite (reset to default play on the X axis)
     }
-    if (input->GetKeyDown('D') || input->GetKeyDown(KEY_RIGHT))
+    if (input->GetKeyDown(KEY_D) || input->GetKeyDown(KEY_RIGHT))
     {
         moveDir = moveDir + Vector2::RIGHT;
         animatedSprite->SetFlipX(true); // Flip sprite (flip animation on the X axis)
     }
 
     // Jump
-    if ((onGround || aboveClimbable_) && (input->GetKeyPress('W') || input->GetKeyPress(KEY_UP)))
+    if ((onGround || aboveClimbable_) && (input->GetKeyPress(KEY_W) || input->GetKeyPress(KEY_UP)))
         jump = true;
 
     // Climb

+ 4 - 4
Source/Samples/Sample.inl

@@ -280,21 +280,21 @@ void Sample::HandleKeyDown(StringHash /*eventType*/, VariantMap& eventData)
         // Texture quality
         else if (key == '1')
         {
-            int quality = renderer->GetTextureQuality();
+            auto quality = (unsigned)renderer->GetTextureQuality();
             ++quality;
             if (quality > QUALITY_HIGH)
                 quality = QUALITY_LOW;
-            renderer->SetTextureQuality(quality);
+            renderer->SetTextureQuality((Quality)quality);
         }
 
         // Material quality
         else if (key == '2')
         {
-            int quality = renderer->GetMaterialQuality();
+            auto quality = (unsigned)renderer->GetMaterialQuality();
             ++quality;
             if (quality > QUALITY_HIGH)
                 quality = QUALITY_LOW;
-            renderer->SetMaterialQuality(quality);
+            renderer->SetMaterialQuality((Quality)quality);
         }
 
         // Specular lighting

+ 1 - 1
Source/Tools/AssetImporter/AssetImporter.cpp

@@ -1368,7 +1368,7 @@ void BuildAndSaveAnimations(OutModel* model)
             AnimationTrack* track = outAnim->CreateTrack(channelName);
 
             // Check which channels are used
-            track->channelMask_ = 0;
+            track->channelMask_ = CHANNEL_NONE;
             if (channel->mNumPositionKeys > 1 || !posEqual)
                 track->channelMask_ |= CHANNEL_POSITION;
             if (channel->mNumRotationKeys > 1 || !rotEqual)

+ 2 - 2
Source/Tools/OgreImporter/OgreImporterUtils.h

@@ -111,13 +111,13 @@ struct ModelVertex
 
 struct ModelVertexBuffer
 {
-    unsigned elementMask_;
+    FlagSet<VertexMask> elementMask_;
     unsigned morphStart_;
     unsigned morphCount_;
     Vector<ModelVertex> vertices_;
 
     ModelVertexBuffer() :
-        elementMask_(0),
+        elementMask_(MASK_NONE),
         morphStart_(0),
         morphCount_(0)
     {

+ 240 - 0
Source/Urho3D/Container/FlagSet.h

@@ -0,0 +1,240 @@
+//
+// Copyright (c) 2008-2018 the Urho3D project.
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in
+// all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+// THE SOFTWARE.
+//
+
+#pragma once
+
+
+#include <type_traits>
+
+
+namespace Urho3D
+{
+
+/// Bitwise Type trait which enables against Enum value. for consumption by flagset class and it's global operators.
+template<typename T> struct is_flagset
+{
+    constexpr static bool value = false;
+};
+
+/// A set of flags defined by an Enum.
+template <class E, class = typename std::enable_if<is_flagset<E>::value>::type>
+class FlagSet
+{
+public:
+    /// Enum type
+    using Enum = E;
+    /// Integer type
+    using Integer = typename std::underlying_type<Enum>::type;
+public:
+    /// Ctor by integer
+    explicit FlagSet(Integer value)
+        : value_(value)
+    {
+    }
+    /// Empty constructor.
+    FlagSet() = default;
+
+    /// Copy constructor.
+    FlagSet(const FlagSet& another) = default;
+
+    /// Construct from Enum value.
+    FlagSet(const Enum value)
+        : value_((Integer) value)
+    {
+    }
+
+    /// Assignment operator from flagset.
+    FlagSet& operator = (const FlagSet& rhs) = default;
+
+    /// Bitwise AND against Enum value.
+    FlagSet& operator &= (const Enum value)
+    {
+        value_ &= (Integer) value;
+        return *this;
+    }
+
+    /// Bitwise AND against flagset value.
+    FlagSet& operator &= (const FlagSet value)
+    {
+        value_ &= value.value_;
+        return *this;
+    }
+
+    /// Bitwise OR against Enum value.
+    FlagSet& operator |= (const Enum value)
+    {
+        value_ |= (Integer) value;
+        return *this;
+    }
+
+    /// Bitwise OR against flagset value.
+    FlagSet& operator |= (const FlagSet value)
+    {
+        value_ |= value.value_;
+        return *this;
+    }
+
+    /// Bitwise XOR against Enum value.
+    FlagSet& operator ^= (const Enum value)
+    {
+        value_ ^= (Integer) value;
+        return *this;
+    }
+
+    /// Bitwise XOR against flagset value.
+    FlagSet& operator ^= (const FlagSet value)
+    {
+        value_ ^= value.value_;
+        return *this;
+    }
+
+    /// Bitwise AND against Enum value.
+    FlagSet operator & (const Enum value) const
+    {
+        return FlagSet(value_ & (Integer) value);
+    }
+
+    /// Bitwise AND against flagset value.
+    FlagSet operator & (const FlagSet value) const
+    {
+        return FlagSet(value_ & value.value_);
+    }
+
+    /// Bitwise OR against Enum value.
+    FlagSet operator | (const Enum value) const
+    {
+        return FlagSet(value_ | (Integer) value);
+    }
+
+    /// Bitwise OR against flagset value.
+    FlagSet operator | (const FlagSet value) const
+    {
+        return FlagSet(value_ | value.value_);
+    }
+
+    /// Bitwise XOR against Enum value.
+    FlagSet operator ^ (const Enum value) const
+    {
+        return FlagSet(value_ ^ (Integer) value);
+    }
+
+    /// Bitwise XOR against flagset value.
+    FlagSet operator ^ (const FlagSet value) const
+    {
+        return FlagSet(value_ ^ value.value_);
+    }
+
+    /// Bitwise negation.
+    FlagSet operator ~ () const
+    {
+        return FlagSet(~value_);
+    }
+
+    /// Boolean negation.
+    bool operator ! () const
+    {
+        return !value_;
+    }
+
+    /// Returns true if any flag is set.
+    operator bool () const
+    {
+        return value_ != 0;
+    }
+
+    /// Cast to underlying type of enum.
+    operator Integer() const
+    {
+        return value_;
+    }
+
+    /// Cast to enum value.
+    operator Enum() const
+    {
+        return (Enum)value_;
+    }
+
+    /// Equality check against enum value.
+    bool operator ==(Enum rhs)
+    {
+        return value_ == (Integer)rhs;
+    }
+
+    /// Equality check against another flagset.
+    bool operator ==(FlagSet rhs)
+    {
+        return value_ == rhs.value_;
+    }
+
+    /// Non-equality check against enum value.
+    bool operator !=(Enum rhs)
+    {
+        return value_ != (Integer)rhs;
+    }
+
+    /// Non-equality check against another flagset value.
+    bool operator !=(FlagSet rhs)
+    {
+        return value_ != rhs.value_;
+    }
+
+    /// Returns true if specified enum value is set.
+    inline bool is(const Enum value) const
+    {
+        Integer flags = (Integer) value;
+        return (value_ & flags) == flags && (flags != 0 || value_ == flags);
+    }
+
+protected:
+    /// Value
+    Integer value_ = 0;
+};
+
+}
+
+/// Bitwise Operator OR for against Enum value.s
+template <class Enum, class = typename std::enable_if<Urho3D::is_flagset<Enum>::value>::type>
+Urho3D::FlagSet<Enum> operator |(const Enum lhs, const Enum rhs)
+{
+    return Urho3D::FlagSet<Enum>(lhs) | rhs;
+}
+
+/// Bitwise Operator AND for against Enum value.s
+template <class Enum, class = typename std::enable_if<Urho3D::is_flagset<Enum>::value>::type>
+Urho3D::FlagSet<Enum> operator & (const Enum lhs, const Enum rhs)
+{
+    return Urho3D::FlagSet<Enum>(lhs) & rhs;
+}
+
+/// Bitwise Operator XOR for against Enum value.s
+template <class Enum, class = typename std::enable_if<Urho3D::is_flagset<Enum>::value>::type>
+Urho3D::FlagSet<Enum> operator ^ (const Enum lhs, const Enum rhs)
+{
+    return Urho3D::FlagSet<Enum>(lhs) ^ rhs;
+}
+
+/// Bitwise Operator RESET for against Enum value.s
+template <class Enum, class = typename std::enable_if<Urho3D::is_flagset<Enum>::value>::type>
+Urho3D::FlagSet<Enum> operator ~ (const Enum rhs)
+{
+    return (Enum)(~(typename std::underlying_type<Enum>::type)rhs);
+}

+ 27 - 22
Source/Urho3D/Core/Attribute.h

@@ -22,32 +22,37 @@
 
 #pragma once
 
+#include "../Container/FlagSet.h"
 #include "../Container/Ptr.h"
 #include "../Core/Variant.h"
 
 namespace Urho3D
 {
 
-/// Attribute shown only in the editor, but not serialized.
-static const unsigned AM_EDIT = 0x0;
-/// Attribute used for file serialization.
-static const unsigned AM_FILE = 0x1;
-/// Attribute used for network replication.
-static const unsigned AM_NET = 0x2;
-/// Attribute used for both file serialization and network replication (default).
-static const unsigned AM_DEFAULT = 0x3;
-/// Attribute should use latest data grouping instead of delta update in network replication.
-static const unsigned AM_LATESTDATA = 0x4;
-/// Attribute should not be shown in the editor.
-static const unsigned AM_NOEDIT = 0x8;
-/// Attribute is a node ID and may need rewriting.
-static const unsigned AM_NODEID = 0x10;
-/// Attribute is a component ID and may need rewriting.
-static const unsigned AM_COMPONENTID = 0x20;
-/// Attribute is a node ID vector where first element is the amount of nodes.
-static const unsigned AM_NODEIDVECTOR = 0x40;
-/// Attribute is readonly. Can't be used with binary serialized objects.
-static const unsigned AM_FILEREADONLY = 0x81;
+enum AttributeMode
+{
+    /// Attribute shown only in the editor, but not serialized.
+    AM_EDIT = 0x0,
+    /// Attribute used for file serialization.
+    AM_FILE = 0x1,
+    /// Attribute used for network replication.
+    AM_NET = 0x2,
+    /// Attribute used for both file serialization and network replication (default).
+    AM_DEFAULT = 0x3,
+    /// Attribute should use latest data grouping instead of delta update in network replication.
+    AM_LATESTDATA = 0x4,
+    /// Attribute should not be shown in the editor.
+    AM_NOEDIT = 0x8,
+    /// Attribute is a node ID and may need rewriting.
+    AM_NODEID = 0x10,
+    /// Attribute is a component ID and may need rewriting.
+    AM_COMPONENTID = 0x20,
+    /// Attribute is a node ID vector where first element is the amount of nodes.
+    AM_NODEIDVECTOR = 0x40,
+    /// Attribute is readonly. Can't be used with binary serialized objects.
+    AM_FILEREADONLY = 0x81,
+};
+template<> struct is_flagset<AttributeMode> { constexpr static bool value = true; };
 
 class Serializable;
 
@@ -68,7 +73,7 @@ struct AttributeInfo
     AttributeInfo() = default;
 
     /// Construct attribute.
-    AttributeInfo(VariantType type, const char* name, const SharedPtr<AttributeAccessor>& accessor, const char** enumNames, const Variant& defaultValue, unsigned mode) :
+    AttributeInfo(VariantType type, const char* name, const SharedPtr<AttributeAccessor>& accessor, const char** enumNames, const Variant& defaultValue, FlagSet<AttributeMode> mode) :
         type_(type),
         name_(name),
         enumNames_(enumNames),
@@ -102,7 +107,7 @@ struct AttributeInfo
     /// Default value for network replication.
     Variant defaultValue_;
     /// Attribute mode: whether to use for serialization, network replication, or both.
-    unsigned mode_ = AM_DEFAULT;
+    FlagSet<AttributeMode> mode_ = AM_DEFAULT;
     /// Attribute metadata.
     VariantMap metadata_;
     /// Attribute data pointer if elsewhere than in the Serializable.

+ 2 - 2
Source/Urho3D/Engine/Engine.cpp

@@ -270,8 +270,8 @@ bool Engine::Initialize(const VariantMap& parameters)
         renderer->SetDrawShadows(GetParameter(parameters, EP_SHADOWS, true).GetBool());
         if (renderer->GetDrawShadows() && GetParameter(parameters, EP_LOW_QUALITY_SHADOWS, false).GetBool())
             renderer->SetShadowQuality(SHADOWQUALITY_SIMPLE_16BIT);
-        renderer->SetMaterialQuality(GetParameter(parameters, EP_MATERIAL_QUALITY, QUALITY_HIGH).GetInt());
-        renderer->SetTextureQuality(GetParameter(parameters, EP_TEXTURE_QUALITY, QUALITY_HIGH).GetInt());
+        renderer->SetMaterialQuality((Quality)GetParameter(parameters, EP_MATERIAL_QUALITY, QUALITY_HIGH).GetInt());
+        renderer->SetTextureQuality((Quality)GetParameter(parameters, EP_TEXTURE_QUALITY, QUALITY_HIGH).GetInt());
         renderer->SetTextureFilterMode((TextureFilterMode)GetParameter(parameters, EP_TEXTURE_FILTER_MODE, FILTER_TRILINEAR).GetInt());
         renderer->SetTextureAnisotropy(GetParameter(parameters, EP_TEXTURE_ANISOTROPY, 4).GetInt());
 

+ 3 - 3
Source/Urho3D/Graphics/AnimatedModel.cpp

@@ -372,7 +372,7 @@ void AnimatedModel::SetModel(Model* model, bool createBones)
         morphs_.Clear();
         const Vector<ModelMorph>& morphs = model->GetMorphs();
         morphs_.Reserve(morphs.Size());
-        morphElementMask_ = 0;
+        morphElementMask_ = MASK_NONE;
         for (unsigned i = 0; i < morphs.Size(); ++i)
         {
             ModelMorph newMorph;
@@ -432,7 +432,7 @@ void AnimatedModel::SetModel(Model* model, bool createBones)
         geometryBoneMappings_.Clear();
         morphVertexBuffers_.Clear();
         morphs_.Clear();
-        morphElementMask_ = 0;
+        morphElementMask_ = MASK_NONE;
         SetBoundingBox(BoundingBox());
         SetSkeleton(Skeleton(), false);
     }
@@ -1386,7 +1386,7 @@ void AnimatedModel::UpdateMorphs()
 void AnimatedModel::ApplyMorph(VertexBuffer* buffer, void* destVertexData, unsigned morphRangeStart, const VertexBufferMorph& morph,
     float weight)
 {
-    unsigned elementMask = morph.elementMask_ & buffer->GetElementMask();
+    auto elementMask = morph.elementMask_ & buffer->GetElementMask();
     unsigned vertexCount = morph.vertexCount_;
     unsigned normalOffset = buffer->GetElementOffset(SEM_NORMAL);
     unsigned tangentOffset = buffer->GetElementOffset(SEM_TANGENT);

+ 1 - 1
Source/Urho3D/Graphics/AnimatedModel.h

@@ -232,7 +232,7 @@ private:
     /// The frame number animation LOD distance was last calculated on.
     unsigned animationLodFrameNumber_;
     /// Morph vertex element mask.
-    unsigned morphElementMask_;
+    FlagSet<VertexMask> morphElementMask_;
     /// Animation LOD bias.
     float animationLodBias_;
     /// Animation LOD timer.

+ 1 - 1
Source/Urho3D/Graphics/Animation.cpp

@@ -143,7 +143,7 @@ bool Animation::BeginLoad(Deserializer& source)
     for (unsigned i = 0; i < tracks; ++i)
     {
         AnimationTrack* newTrack = CreateTrack(source.ReadString());
-        newTrack->channelMask_ = source.ReadUByte();
+        newTrack->channelMask_ = FlagSet<AnimationChannel>(source.ReadUByte());
 
         unsigned keyFrames = source.ReadUInt();
         newTrack->keyFrames_.Resize(keyFrames);

+ 12 - 9
Source/Urho3D/Graphics/Animation.h

@@ -22,6 +22,7 @@
 
 #pragma once
 
+#include "../Container/FlagSet.h"
 #include "../Container/Ptr.h"
 #include "../Math/Quaternion.h"
 #include "../Math/Vector3.h"
@@ -30,6 +31,15 @@
 namespace Urho3D
 {
 
+enum AnimationChannel : unsigned char
+{
+    CHANNEL_NONE = 0x0,
+    CHANNEL_POSITION = 0x1,
+    CHANNEL_ROTATION = 0x2,
+    CHANNEL_SCALE = 0x4,
+};
+template<> struct is_flagset<AnimationChannel> { constexpr static bool value = true; };
+
 /// Skeletal animation keyframe.
 struct AnimationKeyFrame
 {
@@ -54,10 +64,7 @@ struct AnimationKeyFrame
 struct URHO3D_API AnimationTrack
 {
     /// Construct.
-    AnimationTrack() :
-        channelMask_(0)
-    {
-    }
+    AnimationTrack() = default;
 
     /// Assign keyframe at index.
     void SetKeyFrame(unsigned index, const AnimationKeyFrame& keyFrame);
@@ -82,7 +89,7 @@ struct URHO3D_API AnimationTrack
     /// Name hash.
     StringHash nameHash_;
     /// Bitmask of included data (position, rotation, scale.)
-    unsigned char channelMask_;
+    FlagSet<AnimationChannel> channelMask_{};
     /// Keyframes.
     Vector<AnimationKeyFrame> keyFrames_;
 };
@@ -102,10 +109,6 @@ struct AnimationTriggerPoint
     Variant data_;
 };
 
-static const unsigned char CHANNEL_POSITION = 0x1;
-static const unsigned char CHANNEL_ROTATION = 0x2;
-static const unsigned char CHANNEL_SCALE = 0x4;
-
 /// Skeletal animation resource.
 class URHO3D_API Animation : public ResourceWithMetadata
 {

+ 1 - 1
Source/Urho3D/Graphics/AnimationState.cpp

@@ -500,7 +500,7 @@ void AnimationState::ApplyTrack(AnimationStateTrack& stateTrack, float weight, b
     }
 
     const AnimationKeyFrame* keyFrame = &track->keyFrames_[frame];
-    unsigned char channelMask = track->channelMask_;
+    auto channelMask = track->channelMask_;
 
     Vector3 newPosition;
     Quaternion newRotation;

+ 1 - 1
Source/Urho3D/Graphics/CustomGeometry.cpp

@@ -454,7 +454,7 @@ void CustomGeometry::SetGeometryDataAttr(const PODVector<unsigned char>& value)
     MemoryBuffer buffer(value);
 
     SetNumGeometries(buffer.ReadVLE());
-    elementMask_ = buffer.ReadUInt();
+    elementMask_ = FlagSet<VertexMask>(buffer.ReadUInt());
 
     for (unsigned i = 0; i < geometries_.Size(); ++i)
     {

+ 1 - 1
Source/Urho3D/Graphics/CustomGeometry.h

@@ -136,7 +136,7 @@ private:
     /// Vertex buffer.
     SharedPtr<VertexBuffer> vertexBuffer_;
     /// Element mask used so far.
-    unsigned elementMask_;
+    FlagSet<VertexMask> elementMask_;
     /// Current geometry being updated.
     unsigned geometryIndex_;
     /// Material list attribute.

+ 5 - 5
Source/Urho3D/Graphics/DecalSet.cpp

@@ -56,9 +56,9 @@ static const unsigned MIN_INDICES = 6;
 static const unsigned MAX_VERTICES = 65536;
 static const unsigned DEFAULT_MAX_VERTICES = 512;
 static const unsigned DEFAULT_MAX_INDICES = 1024;
-static const unsigned STATIC_ELEMENT_MASK = MASK_POSITION | MASK_NORMAL | MASK_TEXCOORD1 | MASK_TANGENT;
-static const unsigned SKINNED_ELEMENT_MASK = MASK_POSITION | MASK_NORMAL | MASK_TEXCOORD1 | MASK_TANGENT | MASK_BLENDWEIGHTS |
-                                             MASK_BLENDINDICES;
+static const FlagSet<VertexMask> STATIC_ELEMENT_MASK = MASK_POSITION | MASK_NORMAL | MASK_TEXCOORD1 | MASK_TANGENT;
+static const FlagSet<VertexMask> SKINNED_ELEMENT_MASK = MASK_POSITION | MASK_NORMAL | MASK_TEXCOORD1 | MASK_TANGENT |
+    MASK_BLENDWEIGHTS | MASK_BLENDINDICES;
 
 static DecalVertex ClipEdge(const DecalVertex& v0, const DecalVertex& v1, float d0, float d1, bool skinned)
 {
@@ -577,7 +577,7 @@ void DecalSet::SetDecalsAttr(const PODVector<unsigned char>& value)
             Bone& newBone = bones_[i];
 
             newBone.name_ = buffer.ReadString();
-            newBone.collisionMask_ = buffer.ReadUByte();
+            newBone.collisionMask_ = FlagSet<BoneCollisionShape>(buffer.ReadUByte());
             if (newBone.collisionMask_ & BONECOLLISION_SPHERE)
                 newBone.radius_ = buffer.ReadFloat();
             if (newBone.collisionMask_ & BONECOLLISION_BOX)
@@ -1010,7 +1010,7 @@ void DecalSet::CalculateBoundingBox()
 
 void DecalSet::UpdateBuffers()
 {
-    unsigned newElementMask = skinned_ ? SKINNED_ELEMENT_MASK : STATIC_ELEMENT_MASK;
+    auto newElementMask = skinned_ ? SKINNED_ELEMENT_MASK : STATIC_ELEMENT_MASK;
     unsigned newVBSize = optimizeBufferSize_ ? numVertices_ : maxVertices_;
     unsigned newIBSize = optimizeBufferSize_ ? numIndices_ : maxIndices_;
 

+ 4 - 4
Source/Urho3D/Graphics/Direct3D11/D3D11Graphics.cpp

@@ -590,7 +590,7 @@ void Graphics::EndFrame()
     CleanupScratchBuffers();
 }
 
-void Graphics::Clear(unsigned flags, const Color& color, float depth, unsigned stencil)
+void Graphics::Clear(FlagSet<Urho3D::Clear> flags, const Color& color, float depth, unsigned stencil)
 {
     IntVector2 rtSize = GetRenderTargetDimensions();
 
@@ -631,13 +631,13 @@ void Graphics::Clear(unsigned flags, const Color& color, float depth, unsigned s
         model.m23_ = Clamp(depth, 0.0f, 1.0f);
 
         SetBlendMode(BLEND_REPLACE);
-        SetColorWrite((flags & CLEAR_COLOR) != 0);
+        SetColorWrite(flags & CLEAR_COLOR);
         SetCullMode(CULL_NONE);
         SetDepthTest(CMP_ALWAYS);
-        SetDepthWrite((flags & CLEAR_DEPTH) != 0);
+        SetDepthWrite(flags & CLEAR_DEPTH);
         SetFillMode(FILL_SOLID);
         SetScissorTest(false);
-        SetStencilTest((flags & CLEAR_STENCIL) != 0, CMP_ALWAYS, OP_REF, OP_KEEP, OP_KEEP, stencil);
+        SetStencilTest(flags & CLEAR_STENCIL, CMP_ALWAYS, OP_REF, OP_KEEP, OP_KEEP, stencil);
         SetShaders(GetShader(VS, "ClearFramebuffer"), GetShader(PS, "ClearFramebuffer"));
         SetShaderParameter(VSP_MODEL, model);
         SetShaderParameter(VSP_VIEWPROJ, projection);

+ 1 - 1
Source/Urho3D/Graphics/Direct3D11/D3D11Texture2D.cpp

@@ -168,7 +168,7 @@ bool Texture2D::SetData(Image* image, bool useAlpha)
     // Use a shared ptr for managing the temporary mip images created during this function
     SharedPtr<Image> mipImage;
     unsigned memoryUse = sizeof(Texture2D);
-    int quality = QUALITY_HIGH;
+    auto quality = QUALITY_HIGH;
     Renderer* renderer = GetSubsystem<Renderer>();
     if (renderer)
         quality = renderer->GetTextureQuality();

+ 1 - 1
Source/Urho3D/Graphics/Direct3D11/D3D11Texture2DArray.cpp

@@ -198,7 +198,7 @@ bool Texture2DArray::SetData(unsigned layer, Image* image, bool useAlpha)
     // Use a shared ptr for managing the temporary mip images created during this function
     SharedPtr<Image> mipImage;
     unsigned memoryUse = 0;
-    int quality = QUALITY_HIGH;
+    auto quality = QUALITY_HIGH;
     Renderer* renderer = GetSubsystem<Renderer>();
     if (renderer)
         quality = renderer->GetTextureQuality();

+ 1 - 1
Source/Urho3D/Graphics/Direct3D11/D3D11Texture3D.cpp

@@ -176,7 +176,7 @@ bool Texture3D::SetData(Image* image, bool useAlpha)
     // Use a shared ptr for managing the temporary mip images created during this function
     SharedPtr<Image> mipImage;
     unsigned memoryUse = sizeof(Texture3D);
-    int quality = QUALITY_HIGH;
+    auto quality = QUALITY_HIGH;
     Renderer* renderer = GetSubsystem<Renderer>();
     if (renderer)
         quality = renderer->GetTextureQuality();

+ 1 - 1
Source/Urho3D/Graphics/Direct3D11/D3D11TextureCube.cpp

@@ -184,7 +184,7 @@ bool TextureCube::SetData(CubeMapFace face, Image* image, bool useAlpha)
     // Use a shared ptr for managing the temporary mip images created during this function
     SharedPtr<Image> mipImage;
     unsigned memoryUse = 0;
-    int quality = QUALITY_HIGH;
+    auto quality = QUALITY_HIGH;
     Renderer* renderer = GetSubsystem<Renderer>();
     if (renderer)
         quality = renderer->GetTextureQuality();

+ 1 - 1
Source/Urho3D/Graphics/Direct3D9/D3D9Graphics.cpp

@@ -771,7 +771,7 @@ void Graphics::EndFrame()
     CleanupScratchBuffers();
 }
 
-void Graphics::Clear(unsigned flags, const Color& color, float depth, unsigned stencil)
+void Graphics::Clear(FlagSet<Urho3D::Clear> flags, const Color& color, float depth, unsigned stencil)
 {
     DWORD d3dFlags = 0;
     if (flags & CLEAR_COLOR)

+ 1 - 1
Source/Urho3D/Graphics/Direct3D9/D3D9Texture2D.cpp

@@ -216,7 +216,7 @@ bool Texture2D::SetData(Image* image, bool useAlpha)
     // Use a shared ptr for managing the temporary mip images created during this function
     SharedPtr<Image> mipImage;
     unsigned memoryUse = sizeof(Texture2D);
-    int quality = QUALITY_HIGH;
+    auto quality = QUALITY_HIGH;
     Renderer* renderer = GetSubsystem<Renderer>();
     if (renderer)
         quality = renderer->GetTextureQuality();

+ 1 - 1
Source/Urho3D/Graphics/Direct3D9/D3D9Texture2DArray.cpp

@@ -121,7 +121,7 @@ bool Texture2DArray::SetData(unsigned layer, Image* image, bool useAlpha)
     // Use a shared ptr for managing the temporary mip images created during this function
     SharedPtr<Image> mipImage;
     unsigned memoryUse = 0;
-    int quality = QUALITY_HIGH;
+    auto quality = QUALITY_HIGH;
     Renderer* renderer = GetSubsystem<Renderer>();
     if (renderer)
         quality = renderer->GetTextureQuality();

+ 1 - 1
Source/Urho3D/Graphics/Direct3D9/D3D9Texture3D.cpp

@@ -227,7 +227,7 @@ bool Texture3D::SetData(Image* image, bool useAlpha)
     // Use a shared ptr for managing the temporary mip images created during this function
     SharedPtr<Image> mipImage;
     unsigned memoryUse = sizeof(Texture3D);
-    int quality = QUALITY_HIGH;
+    auto quality = QUALITY_HIGH;
     Renderer* renderer = GetSubsystem<Renderer>();
     if (renderer)
         quality = renderer->GetTextureQuality();

+ 1 - 1
Source/Urho3D/Graphics/Direct3D9/D3D9TextureCube.cpp

@@ -233,7 +233,7 @@ bool TextureCube::SetData(CubeMapFace face, Image* image, bool useAlpha)
     // Use a shared ptr for managing the temporary mip images created during this function
     SharedPtr<Image> mipImage;
     unsigned memoryUse = 0;
-    int quality = QUALITY_HIGH;
+    auto quality = QUALITY_HIGH;
     Renderer* renderer = GetSubsystem<Renderer>();
     if (renderer)
         quality = renderer->GetTextureQuality();

+ 1 - 1
Source/Urho3D/Graphics/Graphics.h

@@ -125,7 +125,7 @@ public:
     /// End frame rendering and swap buffers.
     void EndFrame();
     /// Clear any or all of rendertarget, depth buffer and stencil buffer.
-    void Clear(unsigned flags, const Color& color = Color(0.0f, 0.0f, 0.0f, 0.0f), float depth = 1.0f, unsigned stencil = 0);
+    void Clear(FlagSet<Urho3D::Clear> flags, const Color& color = Color(0.0f, 0.0f, 0.0f, 0.0f), float depth = 1.0f, unsigned stencil = 0);
     /// Resolve multisampled backbuffer to a texture rendertarget. The texture's size should match the viewport size.
     bool ResolveToTexture(Texture2D* destination, const IntRect& viewport);
     /// Resolve a multisampled texture on itself.

+ 34 - 22
Source/Urho3D/Graphics/GraphicsDefs.h

@@ -22,6 +22,7 @@
 
 #pragma once
 
+#include "../Container/FlagSet.h"
 #include "../Container/HashBase.h"
 #include "../Math/StringHash.h"
 
@@ -430,31 +431,42 @@ extern URHO3D_API const StringHash PSP_ZONEMAX;
 // Scale calculation from bounding box diagonal.
 extern URHO3D_API const Vector3 DOT_SCALE;
 
-static const int QUALITY_LOW = 0;
-static const int QUALITY_MEDIUM = 1;
-static const int QUALITY_HIGH = 2;
-static const int QUALITY_MAX = 15;
+enum Quality : unsigned
+{
+    QUALITY_LOW = 0,
+    QUALITY_MEDIUM = 1,
+    QUALITY_HIGH = 2,
+    QUALITY_MAX = 15,
+};
 
-static const unsigned CLEAR_COLOR = 0x1;
-static const unsigned CLEAR_DEPTH = 0x2;
-static const unsigned CLEAR_STENCIL = 0x4;
+enum Clear : unsigned
+{
+    CLEAR_COLOR = 0x1,
+    CLEAR_DEPTH = 0x2,
+    CLEAR_STENCIL = 0x4,
+};
+template<> struct is_flagset<Clear> { constexpr static bool value = true; };
 
 // Legacy vertex element bitmasks.
-static const unsigned MASK_NONE = 0x0;
-static const unsigned MASK_POSITION = 0x1;
-static const unsigned MASK_NORMAL = 0x2;
-static const unsigned MASK_COLOR = 0x4;
-static const unsigned MASK_TEXCOORD1 = 0x8;
-static const unsigned MASK_TEXCOORD2 = 0x10;
-static const unsigned MASK_CUBETEXCOORD1 = 0x20;
-static const unsigned MASK_CUBETEXCOORD2 = 0x40;
-static const unsigned MASK_TANGENT = 0x80;
-static const unsigned MASK_BLENDWEIGHTS = 0x100;
-static const unsigned MASK_BLENDINDICES = 0x200;
-static const unsigned MASK_INSTANCEMATRIX1 = 0x400;
-static const unsigned MASK_INSTANCEMATRIX2 = 0x800;
-static const unsigned MASK_INSTANCEMATRIX3 = 0x1000;
-static const unsigned MASK_OBJECTINDEX = 0x2000;
+enum VertexMask : unsigned
+{
+    MASK_NONE = 0x0,
+    MASK_POSITION = 0x1,
+    MASK_NORMAL = 0x2,
+    MASK_COLOR = 0x4,
+    MASK_TEXCOORD1 = 0x8,
+    MASK_TEXCOORD2 = 0x10,
+    MASK_CUBETEXCOORD1 = 0x20,
+    MASK_CUBETEXCOORD2 = 0x40,
+    MASK_TANGENT = 0x80,
+    MASK_BLENDWEIGHTS = 0x100,
+    MASK_BLENDINDICES = 0x200,
+    MASK_INSTANCEMATRIX1 = 0x400,
+    MASK_INSTANCEMATRIX2 = 0x800,
+    MASK_INSTANCEMATRIX3 = 0x1000,
+    MASK_OBJECTINDEX = 0x2000,
+};
+template<> struct is_flagset<VertexMask> { constexpr static bool value = true; };
 
 static const int MAX_RENDERTARGETS = 4;
 static const int MAX_VERTEX_STREAMS = 4;

+ 5 - 5
Source/Urho3D/Graphics/Material.cpp

@@ -166,12 +166,12 @@ bool CompareTechniqueEntries(const TechniqueEntry& lhs, const TechniqueEntry& rh
 }
 
 TechniqueEntry::TechniqueEntry() noexcept :
-    qualityLevel_(0),
+    qualityLevel_(QUALITY_LOW),
     lodDistance_(0.0f)
 {
 }
 
-TechniqueEntry::TechniqueEntry(Technique* tech, unsigned qualityLevel, float lodDistance) noexcept :
+TechniqueEntry::TechniqueEntry(Technique* tech, Quality qualityLevel, float lodDistance) noexcept :
     technique_(tech),
     original_(tech),
     qualityLevel_(qualityLevel),
@@ -424,7 +424,7 @@ bool Material::Load(const XMLElement& source)
             TechniqueEntry newTechnique;
             newTechnique.technique_ = newTechnique.original_ = tech;
             if (techniqueElem.HasAttribute("quality"))
-                newTechnique.qualityLevel_ = techniqueElem.GetInt("quality");
+                newTechnique.qualityLevel_ = (Quality)techniqueElem.GetInt("quality");
             if (techniqueElem.HasAttribute("loddistance"))
                 newTechnique.lodDistance_ = techniqueElem.GetFloat("loddistance");
             techniques_.Push(newTechnique);
@@ -579,7 +579,7 @@ bool Material::Load(const JSONValue& source)
             newTechnique.technique_ = newTechnique.original_ = tech;
             JSONValue qualityVal = techVal.Get("quality");
             if (!qualityVal.IsNull())
-                newTechnique.qualityLevel_ = qualityVal.GetInt();
+                newTechnique.qualityLevel_ = (Quality)qualityVal.GetInt();
             JSONValue lodDistanceVal = techVal.Get("loddistance");
             if (!lodDistanceVal.IsNull())
                 newTechnique.lodDistance_ = lodDistanceVal.GetFloat();
@@ -923,7 +923,7 @@ void Material::SetNumTechniques(unsigned num)
     RefreshMemoryUse();
 }
 
-void Material::SetTechnique(unsigned index, Technique* tech, unsigned qualityLevel, float lodDistance)
+void Material::SetTechnique(unsigned index, Technique* tech, Quality qualityLevel, float lodDistance)
 {
     if (index >= techniques_.Size())
         return;

+ 3 - 3
Source/Urho3D/Graphics/Material.h

@@ -58,7 +58,7 @@ struct TechniqueEntry
     /// Construct with defaults.
     TechniqueEntry() noexcept;
     /// Construct with parameters.
-    TechniqueEntry(Technique* tech, unsigned qualityLevel, float lodDistance) noexcept;
+    TechniqueEntry(Technique* tech, Quality qualityLevel, float lodDistance) noexcept;
     /// Destruct.
     ~TechniqueEntry() noexcept = default;
 
@@ -67,7 +67,7 @@ struct TechniqueEntry
     /// Original technique, in case the material adds shader compilation defines. The modified clones are requested from it.
     SharedPtr<Technique> original_;
     /// Quality level.
-    int qualityLevel_;
+    Quality qualityLevel_;
     /// LOD distance.
     float lodDistance_;
 };
@@ -135,7 +135,7 @@ public:
     /// Set number of techniques.
     void SetNumTechniques(unsigned num);
     /// Set technique.
-    void SetTechnique(unsigned index, Technique* tech, unsigned qualityLevel = 0, float lodDistance = 0.0f);
+    void SetTechnique(unsigned index, Technique* tech, Quality qualityLevel = QUALITY_LOW, float lodDistance = 0.0f);
     /// Set additional vertex shader defines. Separate multiple defines with spaces. Setting defines at the material level causes technique(s) to be cloned as necessary.
     void SetVertexShaderDefines(const String& defines);
     /// Set additional pixel shader defines. Separate multiple defines with spaces. Setting defines at the material level causes technique(s) to be cloned as necessary.

+ 1 - 1
Source/Urho3D/Graphics/Model.cpp

@@ -268,7 +268,7 @@ bool Model::BeginLoad(Deserializer& source)
             VertexBufferMorph newBuffer;
             unsigned bufferIndex = source.ReadUInt();
 
-            newBuffer.elementMask_ = source.ReadUInt();
+            newBuffer.elementMask_ = FlagSet<VertexMask>(source.ReadUInt());
             newBuffer.vertexCount_ = source.ReadUInt();
 
             // Base size: size of each vertex index

+ 1 - 1
Source/Urho3D/Graphics/Model.h

@@ -41,7 +41,7 @@ class VertexBuffer;
 struct VertexBufferMorph
 {
     /// Vertex elements.
-    unsigned elementMask_;
+    FlagSet<VertexMask> elementMask_;
     /// Number of vertices.
     unsigned vertexCount_;
     /// Morphed vertices data size as bytes.

+ 13 - 9
Source/Urho3D/Graphics/OcclusionBuffer.cpp

@@ -33,12 +33,16 @@
 namespace Urho3D
 {
 
-static const unsigned CLIPMASK_X_POS = 0x1;
-static const unsigned CLIPMASK_X_NEG = 0x2;
-static const unsigned CLIPMASK_Y_POS = 0x4;
-static const unsigned CLIPMASK_Y_NEG = 0x8;
-static const unsigned CLIPMASK_Z_POS = 0x10;
-static const unsigned CLIPMASK_Z_NEG = 0x20;
+enum ClipMask : unsigned
+{
+    CLIPMASK_X_POS = 0x1,
+    CLIPMASK_X_NEG = 0x2,
+    CLIPMASK_Y_POS = 0x4,
+    CLIPMASK_Y_NEG = 0x8,
+    CLIPMASK_Z_POS = 0x10,
+    CLIPMASK_Z_NEG = 0x20,
+};
+template<> struct is_flagset<ClipMask> { constexpr static bool value = true; };
 
 void DrawOcclusionBatchWork(const WorkItem* item, unsigned threadIndex)
 {
@@ -584,15 +588,15 @@ void OcclusionBuffer::CalculateViewport()
 
 void OcclusionBuffer::DrawTriangle(Vector4* vertices, unsigned threadIndex)
 {
-    unsigned clipMask = 0;
-    unsigned andClipMask = 0;
+    FlagSet<ClipMask> clipMask{};
+    FlagSet<ClipMask> andClipMask{};
     bool drawOk = false;
     Vector3 projected[3];
 
     // Build the clip plane mask for the triangle
     for (unsigned i = 0; i < 3; ++i)
     {
-        unsigned vertexClipMask = 0;
+        FlagSet<ClipMask> vertexClipMask{};
 
         if (vertices[i].x_ > vertices[i].w_)
             vertexClipMask |= CLIPMASK_X_POS;

+ 1 - 1
Source/Urho3D/Graphics/OpenGL/OGLGraphics.cpp

@@ -659,7 +659,7 @@ void Graphics::EndFrame()
     CleanupScratchBuffers();
 }
 
-void Graphics::Clear(unsigned flags, const Color& color, float depth, unsigned stencil)
+void Graphics::Clear(FlagSet<Urho3D::Clear> flags, const Color& color, float depth, unsigned stencil)
 {
     PrepareDraw();
 

+ 1 - 1
Source/Urho3D/Graphics/OpenGL/OGLTexture2D.cpp

@@ -177,7 +177,7 @@ bool Texture2D::SetData(Image* image, bool useAlpha)
     // Use a shared ptr for managing the temporary mip images created during this function
     SharedPtr<Image> mipImage;
     unsigned memoryUse = sizeof(Texture2D);
-    int quality = QUALITY_HIGH;
+    auto quality = QUALITY_HIGH;
     auto* renderer = GetSubsystem<Renderer>();
     if (renderer)
         quality = renderer->GetTextureQuality();

+ 1 - 1
Source/Urho3D/Graphics/OpenGL/OGLTexture2DArray.cpp

@@ -204,7 +204,7 @@ bool Texture2DArray::SetData(unsigned layer, Image* image, bool useAlpha)
     // Use a shared ptr for managing the temporary mip images created during this function
     SharedPtr<Image> mipImage;
     unsigned memoryUse = 0;
-    int quality = QUALITY_HIGH;
+    auto quality = QUALITY_HIGH;
     auto* renderer = GetSubsystem<Renderer>();
     if (renderer)
         quality = renderer->GetTextureQuality();

+ 1 - 1
Source/Urho3D/Graphics/OpenGL/OGLTexture3D.cpp

@@ -164,7 +164,7 @@ bool Texture3D::SetData(Image* image, bool useAlpha)
     // Use a shared ptr for managing the temporary mip images created during this function
     SharedPtr<Image> mipImage;
     unsigned memoryUse = sizeof(Texture3D);
-    int quality = QUALITY_HIGH;
+    auto quality = QUALITY_HIGH;
     auto* renderer = GetSubsystem<Renderer>();
     if (renderer)
         quality = renderer->GetTextureQuality();

+ 1 - 1
Source/Urho3D/Graphics/OpenGL/OGLTextureCube.cpp

@@ -195,7 +195,7 @@ bool TextureCube::SetData(CubeMapFace face, Image* image, bool useAlpha)
     // Use a shared ptr for managing the temporary mip images created during this function
     SharedPtr<Image> mipImage;
     unsigned memoryUse = 0;
-    int quality = QUALITY_HIGH;
+    auto quality = QUALITY_HIGH;
     auto* renderer = GetSubsystem<Renderer>();
     if (renderer)
         quality = renderer->GetTextureQuality();

+ 1 - 1
Source/Urho3D/Graphics/RenderPath.h

@@ -161,7 +161,7 @@ struct URHO3D_API RenderPathCommand
     /// Depth-stencil output name.
     String depthStencilName_;
     /// Clear flags. Affects clear command only.
-    unsigned clearFlags_{};
+    FlagSet<Clear> clearFlags_{};
     /// Clear color. Affects clear command only.
     Color clearColor_;
     /// Clear depth. Affects clear command only.

+ 2 - 2
Source/Urho3D/Graphics/Renderer.cpp

@@ -328,7 +328,7 @@ void Renderer::SetTextureFilterMode(TextureFilterMode mode)
     textureFilterMode_ = mode;
 }
 
-void Renderer::SetTextureQuality(int quality)
+void Renderer::SetTextureQuality(Quality quality)
 {
     quality = Clamp(quality, QUALITY_LOW, QUALITY_HIGH);
 
@@ -339,7 +339,7 @@ void Renderer::SetTextureQuality(int quality)
     }
 }
 
-void Renderer::SetMaterialQuality(int quality)
+void Renderer::SetMaterialQuality(Quality quality)
 {
     quality = Clamp(quality, QUALITY_LOW, QUALITY_MAX);
 

+ 6 - 6
Source/Urho3D/Graphics/Renderer.h

@@ -201,9 +201,9 @@ public:
     /// Set default texture filtering.
     void SetTextureFilterMode(TextureFilterMode mode);
     /// Set texture quality level. See the QUALITY constants in GraphicsDefs.h.
-    void SetTextureQuality(int quality);
+    void SetTextureQuality(Quality quality);
     /// Set material quality level. See the QUALITY constants in GraphicsDefs.h.
-    void SetMaterialQuality(int quality);
+    void SetMaterialQuality(Quality quality);
     /// Set shadows on/off.
     void SetDrawShadows(bool enable);
     /// Set shadow map resolution.
@@ -278,10 +278,10 @@ public:
     TextureFilterMode GetTextureFilterMode() const { return textureFilterMode_; }
 
     /// Return texture quality level.
-    int GetTextureQuality() const { return textureQuality_; }
+    Quality GetTextureQuality() const { return textureQuality_; }
 
     /// Return material quality level.
-    int GetMaterialQuality() const { return materialQuality_; }
+    Quality GetMaterialQuality() const { return materialQuality_; }
 
     /// Return shadow map resolution.
     int GetShadowMapSize() const { return shadowMapSize_; }
@@ -537,9 +537,9 @@ private:
     /// Texture filtering mode.
     TextureFilterMode textureFilterMode_{FILTER_TRILINEAR};
     /// Texture quality level.
-    int textureQuality_{QUALITY_HIGH};
+    Quality textureQuality_{QUALITY_HIGH};
     /// Material quality level.
-    int materialQuality_{QUALITY_HIGH};
+    Quality materialQuality_{QUALITY_HIGH};
     /// Shadow map resolution.
     int shadowMapSize_{1024};
     /// Shadow quality.

+ 1 - 1
Source/Urho3D/Graphics/Skeleton.cpp

@@ -59,7 +59,7 @@ bool Skeleton::Load(Deserializer& source)
         source.Read(&newBone.offsetMatrix_.m00_, sizeof(Matrix3x4));
 
         // Read bone collision data
-        newBone.collisionMask_ = source.ReadUByte();
+        newBone.collisionMask_ = FlagSet<BoneCollisionShape>(source.ReadUByte());
         if (newBone.collisionMask_ & BONECOLLISION_SPHERE)
             newBone.radius_ = source.ReadFloat();
         if (newBone.collisionMask_ & BONECOLLISION_BOX)

+ 8 - 5
Source/Urho3D/Graphics/Skeleton.h

@@ -28,9 +28,13 @@
 namespace Urho3D
 {
 
-static const unsigned BONECOLLISION_NONE = 0x0;
-static const unsigned BONECOLLISION_SPHERE = 0x1;
-static const unsigned BONECOLLISION_BOX = 0x2;
+enum BoneCollisionShape : unsigned char
+{
+    BONECOLLISION_NONE = 0x0,
+    BONECOLLISION_SPHERE = 0x1,
+    BONECOLLISION_BOX = 0x2,
+};
+template<> struct is_flagset<BoneCollisionShape> { constexpr static bool value = true; };
 
 class Deserializer;
 class ResourceCache;
@@ -46,7 +50,6 @@ struct Bone
         initialRotation_(Quaternion::IDENTITY),
         initialScale_(Vector3::ONE),
         animated_(true),
-        collisionMask_(0),
         radius_(0.0f)
     {
     }
@@ -68,7 +71,7 @@ struct Bone
     /// Animation enable flag.
     bool animated_;
     /// Supported collision types.
-    unsigned char collisionMask_;
+    FlagSet<BoneCollisionShape> collisionMask_ = BONECOLLISION_NONE;
     /// Radius.
     float radius_;
     /// Local-space bounding box.

+ 2 - 2
Source/Urho3D/Graphics/Texture.cpp

@@ -106,7 +106,7 @@ void Texture::SetBackupTexture(Texture* texture)
     backupTexture_ = texture;
 }
 
-void Texture::SetMipsToSkip(int quality, int toSkip)
+void Texture::SetMipsToSkip(Quality quality, int toSkip)
 {
     if (quality >= QUALITY_LOW && quality < MAX_TEXTURE_QUALITY_LEVELS)
     {
@@ -121,7 +121,7 @@ void Texture::SetMipsToSkip(int quality, int toSkip)
     }
 }
 
-int Texture::GetMipsToSkip(int quality) const
+int Texture::GetMipsToSkip(Quality quality) const
 {
     return (quality >= QUALITY_LOW && quality < MAX_TEXTURE_QUALITY_LEVELS) ? mipsToSkip_[quality] : 0;
 }

+ 2 - 2
Source/Urho3D/Graphics/Texture.h

@@ -67,7 +67,7 @@ public:
     /// Set backup texture to use when rendering to this texture.
     void SetBackupTexture(Texture* texture);
     /// Set mip levels to skip on a quality setting when loading. Ensures higher quality levels do not skip more.
-    void SetMipsToSkip(int quality, int toSkip);
+    void SetMipsToSkip(Quality quality, int toSkip);
 
     /// Return API-specific texture format.
     unsigned GetFormat() const { return format_; }
@@ -121,7 +121,7 @@ public:
     Texture* GetBackupTexture() const { return backupTexture_; }
 
     /// Return mip levels to skip on a quality setting when loading.
-    int GetMipsToSkip(int quality) const;
+    int GetMipsToSkip(Quality quality) const;
     /// Return mip level width, or 0 if level does not exist.
     int GetLevelWidth(unsigned level) const;
     /// Return mip level width, or 0 if level does not exist.

+ 2 - 2
Source/Urho3D/Graphics/VertexBuffer.cpp

@@ -93,7 +93,7 @@ void VertexBuffer::UpdateOffsets()
 {
     unsigned elementOffset = 0;
     elementHash_ = 0;
-    elementMask_ = 0;
+    elementMask_ = MASK_NONE;
 
     for (PODVector<VertexElement>::Iterator i = elements_.Begin(); i != elements_.End(); ++i)
     {
@@ -106,7 +106,7 @@ void VertexBuffer::UpdateOffsets()
         {
             const VertexElement& legacy = LEGACY_VERTEXELEMENTS[j];
             if (i->type_ == legacy.type_ && i->semantic_ == legacy.semantic_ && i->index_ == legacy.index_)
-                elementMask_ |= (1u << j);
+                elementMask_ |= FlagSet<VertexMask>(1u << j);
         }
     }
 

+ 2 - 2
Source/Urho3D/Graphics/VertexBuffer.h

@@ -100,7 +100,7 @@ public:
     unsigned GetElementOffset(VertexElementType type, VertexElementSemantic semantic, unsigned char index = 0) const { const VertexElement* element = GetElement(type, semantic, index); return element ? element->offset_ : M_MAX_UNSIGNED; }
 
     /// Return legacy vertex element mask. Note that both semantic and type must match the legacy element for a mask bit to be set.
-    unsigned GetElementMask() const { return elementMask_; }
+    FlagSet<VertexMask> GetElementMask() const { return elementMask_; }
 
     /// Return CPU memory shadow data.
     unsigned char* GetShadowData() const { return shadowData_.Get(); }
@@ -155,7 +155,7 @@ private:
     /// Vertex element hash.
     unsigned long long elementHash_{};
     /// Vertex element legacy bitmask.
-    unsigned elementMask_{};
+    FlagSet<VertexMask> elementMask_{};
     /// Buffer locking state.
     LockState lockState_{LOCK_NONE};
     /// Lock start vertex.

+ 40 - 40
Source/Urho3D/Input/Input.cpp

@@ -70,12 +70,12 @@ const StringHash VAR_SCREEN_JOYSTICK_ID("VAR_SCREEN_JOYSTICK_ID");
 const unsigned TOUCHID_MAX = 32;
 
 /// Convert SDL keycode if necessary.
-int ConvertSDLKeyCode(int keySym, int scanCode)
+Key ConvertSDLKeyCode(int keySym, int scanCode)
 {
     if (scanCode == SCANCODE_AC_BACK)
         return KEY_ESCAPE;
     else
-        return SDL_tolower(keySym);
+        return (Key)SDL_tolower(keySym);
 }
 
 UIElement* TouchState::GetTouchedElement()
@@ -536,8 +536,8 @@ void Input::Update()
                 eventData[P_Y] = mousePosition.y_;
                 eventData[P_DX] = mouseMove_.x_;
                 eventData[P_DY] = mouseMove_.y_;
-                eventData[P_BUTTONS] = mouseButtonDown_;
-                eventData[P_QUALIFIERS] = GetQualifiers();
+                eventData[P_BUTTONS] = (unsigned)mouseButtonDown_;
+                eventData[P_QUALIFIERS] = (unsigned)GetQualifiers();
                 SendEvent(E_MOUSEMOVE, eventData);
             }
         }
@@ -1299,67 +1299,67 @@ SDL_JoystickID Input::OpenJoystick(unsigned index)
     return joystickID;
 }
 
-int Input::GetKeyFromName(const String& name) const
+Key Input::GetKeyFromName(const String& name) const
 {
-    return SDL_GetKeyFromName(name.CString());
+    return (Key)SDL_GetKeyFromName(name.CString());
 }
 
-int Input::GetKeyFromScancode(int scancode) const
+Key Input::GetKeyFromScancode(Scancode scancode) const
 {
-    return SDL_GetKeyFromScancode((SDL_Scancode)scancode);
+    return (Key)SDL_GetKeyFromScancode((SDL_Scancode)scancode);
 }
 
-String Input::GetKeyName(int key) const
+String Input::GetKeyName(Key key) const
 {
     return String(SDL_GetKeyName(key));
 }
 
-int Input::GetScancodeFromKey(int key) const
+Scancode Input::GetScancodeFromKey(Key key) const
 {
-    return SDL_GetScancodeFromKey(key);
+    return (Scancode)SDL_GetScancodeFromKey(key);
 }
 
-int Input::GetScancodeFromName(const String& name) const
+Scancode Input::GetScancodeFromName(const String& name) const
 {
-    return SDL_GetScancodeFromName(name.CString());
+    return (Scancode)SDL_GetScancodeFromName(name.CString());
 }
 
-String Input::GetScancodeName(int scancode) const
+String Input::GetScancodeName(Scancode scancode) const
 {
     return SDL_GetScancodeName((SDL_Scancode)scancode);
 }
 
-bool Input::GetKeyDown(int key) const
+bool Input::GetKeyDown(Key key) const
 {
     return keyDown_.Contains(SDL_tolower(key));
 }
 
-bool Input::GetKeyPress(int key) const
+bool Input::GetKeyPress(Key key) const
 {
     return keyPress_.Contains(SDL_tolower(key));
 }
 
-bool Input::GetScancodeDown(int scancode) const
+bool Input::GetScancodeDown(Scancode scancode) const
 {
     return scancodeDown_.Contains(scancode);
 }
 
-bool Input::GetScancodePress(int scancode) const
+bool Input::GetScancodePress(Scancode scancode) const
 {
     return scancodePress_.Contains(scancode);
 }
 
-bool Input::GetMouseButtonDown(int button) const
+bool Input::GetMouseButtonDown(MouseButton button) const
 {
     return (mouseButtonDown_ & button) != 0;
 }
 
-bool Input::GetMouseButtonPress(int button) const
+bool Input::GetMouseButtonPress(MouseButton button) const
 {
     return (mouseButtonPress_ & button) != 0;
 }
 
-bool Input::GetQualifierDown(int qualifier) const
+bool Input::GetQualifierDown(Qualifier qualifier) const
 {
     if (qualifier == QUAL_SHIFT)
         return GetKeyDown(KEY_LSHIFT) || GetKeyDown(KEY_RSHIFT);
@@ -1371,7 +1371,7 @@ bool Input::GetQualifierDown(int qualifier) const
     return false;
 }
 
-bool Input::GetQualifierPress(int qualifier) const
+bool Input::GetQualifierPress(Qualifier qualifier) const
 {
     if (qualifier == QUAL_SHIFT)
         return GetKeyPress(KEY_LSHIFT) || GetKeyPress(KEY_RSHIFT);
@@ -1383,9 +1383,9 @@ bool Input::GetQualifierPress(int qualifier) const
     return false;
 }
 
-int Input::GetQualifiers() const
+FlagSet<Qualifier> Input::GetQualifiers() const
 {
-    int ret = 0;
+    FlagSet<Qualifier> ret;
     if (GetQualifierDown(QUAL_SHIFT))
         ret |= QUAL_SHIFT;
     if (GetQualifierDown(QUAL_CTRL))
@@ -1568,7 +1568,7 @@ void Input::ResetInputAccumulation()
     // Reset input accumulation for this frame
     keyPress_.Clear();
     scancodePress_.Clear();
-    mouseButtonPress_ = 0;
+    mouseButtonPress_ = MOUSEB_NONE;
     mouseMove_ = IntVector2::ZERO;
     mouseMoveWheel_ = 0;
     for (HashMap<SDL_JoystickID, JoystickState>::Iterator i = joysticks_.Begin(); i != joysticks_.End(); ++i)
@@ -1650,7 +1650,7 @@ void Input::ResetState()
 
     mouseMove_ = IntVector2::ZERO;
     mouseMoveWheel_ = 0;
-    mouseButtonPress_ = 0;
+    mouseButtonPress_ = MOUSEB_NONE;
 }
 
 void Input::ResetTouches()
@@ -1742,7 +1742,7 @@ void Input::SendInputFocusEvent()
     SendEvent(E_INPUTFOCUS, eventData);
 }
 
-void Input::SetMouseButton(int button, bool newState)
+void Input::SetMouseButton(MouseButton button, bool newState)
 {
     if (newState)
     {
@@ -1763,12 +1763,12 @@ void Input::SetMouseButton(int button, bool newState)
 
     VariantMap& eventData = GetEventDataMap();
     eventData[P_BUTTON] = button;
-    eventData[P_BUTTONS] = mouseButtonDown_;
-    eventData[P_QUALIFIERS] = GetQualifiers();
+    eventData[P_BUTTONS] = (unsigned)mouseButtonDown_;
+    eventData[P_QUALIFIERS] = (unsigned)GetQualifiers();
     SendEvent(newState ? E_MOUSEBUTTONDOWN : E_MOUSEBUTTONUP, eventData);
 }
 
-void Input::SetKey(int key, int scancode, bool newState)
+void Input::SetKey(Key key, Scancode scancode, bool newState)
 {
     bool repeat = false;
 
@@ -1798,8 +1798,8 @@ void Input::SetKey(int key, int scancode, bool newState)
     VariantMap& eventData = GetEventDataMap();
     eventData[P_KEY] = key;
     eventData[P_SCANCODE] = scancode;
-    eventData[P_BUTTONS] = mouseButtonDown_;
-    eventData[P_QUALIFIERS] = GetQualifiers();
+    eventData[P_BUTTONS] = (unsigned)mouseButtonDown_;
+    eventData[P_QUALIFIERS] = (unsigned)GetQualifiers();
     if (newState)
         eventData[P_REPEAT] = repeat;
     SendEvent(newState ? E_KEYDOWN : E_KEYUP, eventData);
@@ -1819,8 +1819,8 @@ void Input::SetMouseWheel(int delta)
 
         VariantMap& eventData = GetEventDataMap();
         eventData[P_WHEEL] = delta;
-        eventData[P_BUTTONS] = mouseButtonDown_;
-        eventData[P_QUALIFIERS] = GetQualifiers();
+        eventData[P_BUTTONS] = (unsigned)mouseButtonDown_;
+        eventData[P_QUALIFIERS] = (unsigned)GetQualifiers();
         SendEvent(E_MOUSEWHEEL, eventData);
     }
 }
@@ -1899,11 +1899,11 @@ void Input::HandleSDLEvent(void* sdlEvent)
     switch (evt.type)
     {
     case SDL_KEYDOWN:
-        SetKey(ConvertSDLKeyCode(evt.key.keysym.sym, evt.key.keysym.scancode), evt.key.keysym.scancode, true);
+        SetKey(ConvertSDLKeyCode(evt.key.keysym.sym, evt.key.keysym.scancode), (Scancode)evt.key.keysym.scancode, true);
         break;
 
     case SDL_KEYUP:
-        SetKey(ConvertSDLKeyCode(evt.key.keysym.sym, evt.key.keysym.scancode), evt.key.keysym.scancode, false);
+        SetKey(ConvertSDLKeyCode(evt.key.keysym.sym, evt.key.keysym.scancode), (Scancode)evt.key.keysym.scancode, false);
         break;
 
     case SDL_TEXTINPUT:
@@ -1930,7 +1930,7 @@ void Input::HandleSDLEvent(void* sdlEvent)
 
     case SDL_MOUSEBUTTONDOWN:
         if (!touchEmulation_)
-            SetMouseButton(1u << (evt.button.button - 1), true);
+            SetMouseButton(static_cast<MouseButton>(1u << (evt.button.button - 1)), true);
         else
         {
             int x, y;
@@ -1953,7 +1953,7 @@ void Input::HandleSDLEvent(void* sdlEvent)
 
     case SDL_MOUSEBUTTONUP:
         if (!touchEmulation_)
-            SetMouseButton(1u << (evt.button.button - 1), false);
+            SetMouseButton(static_cast<MouseButton>(1u << (evt.button.button - 1)), false);
         else
         {
             int x, y;
@@ -2004,8 +2004,8 @@ void Input::HandleSDLEvent(void* sdlEvent)
                 // The "on-the-fly" motion data needs to be scaled now, though this may reduce accuracy
                 eventData[P_DX] = (int)(evt.motion.xrel * inputScale_.x_);
                 eventData[P_DY] = (int)(evt.motion.yrel * inputScale_.y_);
-                eventData[P_BUTTONS] = mouseButtonDown_;
-                eventData[P_QUALIFIERS] = GetQualifiers();
+                eventData[P_BUTTONS] = (unsigned)mouseButtonDown_;
+                eventData[P_QUALIFIERS] = (unsigned)GetQualifiers();
                 SendEvent(E_MOUSEMOVE, eventData);
             }
         }

+ 17 - 16
Source/Urho3D/Input/Input.h

@@ -22,6 +22,7 @@
 
 #pragma once
 
+#include "../Container/FlagSet.h"
 #include "../Container/HashSet.h"
 #include "../Core/Mutex.h"
 #include "../Core/Object.h"
@@ -212,33 +213,33 @@ public:
     void CenterMousePosition();
 
     /// Return keycode from key name.
-    int GetKeyFromName(const String& name) const;
+    Key GetKeyFromName(const String& name) const;
     /// Return keycode from scancode.
-    int GetKeyFromScancode(int scancode) const;
+    Key GetKeyFromScancode(Scancode scancode) const;
     /// Return name of key from keycode.
-    String GetKeyName(int key) const;
+    String GetKeyName(Key key) const;
     /// Return scancode from keycode.
-    int GetScancodeFromKey(int key) const;
+    Scancode GetScancodeFromKey(Key key) const;
     /// Return scancode from key name.
-    int GetScancodeFromName(const String& name) const;
+    Scancode GetScancodeFromName(const String& name) const;
     /// Return name of key from scancode.
-    String GetScancodeName(int scancode) const;
+    String GetScancodeName(Scancode scancode) const;
     /// Check if a key is held down.
-    bool GetKeyDown(int key) const;
+    bool GetKeyDown(Key key) const;
     /// Check if a key has been pressed on this frame.
-    bool GetKeyPress(int key) const;
+    bool GetKeyPress(Key key) const;
     /// Check if a key is held down by scancode.
-    bool GetScancodeDown(int scancode) const;
+    bool GetScancodeDown(Scancode scancode) const;
     /// Check if a key has been pressed on this frame by scancode.
-    bool GetScancodePress(int scancode) const;
+    bool GetScancodePress(Scancode scancode) const;
     /// Check if a mouse button is held down.
-    bool GetMouseButtonDown(int button) const;
+    bool GetMouseButtonDown(MouseButton button) const;
     /// Check if a mouse button has been pressed on this frame.
-    bool GetMouseButtonPress(int button) const;
+    bool GetMouseButtonPress(MouseButton button) const;
     /// Check if a qualifier key is held down.
-    bool GetQualifierDown(int qualifier) const;
+    bool GetQualifierDown(Qualifier qualifier) const;
     /// Check if a qualifier key has been pressed on this frame.
-    bool GetQualifierPress(int qualifier) const;
+    bool GetQualifierPress(Qualifier qualifier) const;
     /// Return the currently held down qualifiers.
     int GetQualifiers() const;
     /// Return mouse position within window. Should only be used with a visible mouse cursor. Uses the backbuffer (Graphics width/height) coordinates.
@@ -323,9 +324,9 @@ private:
     /// Send an input focus or window minimization change event.
     void SendInputFocusEvent();
     /// Handle a mouse button change.
-    void SetMouseButton(int button, bool newState);
+    void SetMouseButton(MouseButton button, bool newState);
     /// Handle a key change.
-    void SetKey(int key, int scancode, bool newState);
+    void SetKey(Key key, Scancode scancode, bool newState);
     /// Handle mouse wheel change.
     void SetMouseWheel(int delta);
     /// Suppress next mouse movement.

+ 590 - 0
Source/Urho3D/Input/InputConstants.h

@@ -0,0 +1,590 @@
+//
+// Copyright (c) 2008-2018 the Urho3D project.
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in
+// all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+// THE SOFTWARE.
+//
+
+#pragma once
+
+#include "../Container/FlagSet.h"
+#include "../Math/MathDefs.h"
+
+#include <SDL/SDL_joystick.h>
+#include <SDL/SDL_gamecontroller.h>
+#include <SDL/SDL_keycode.h>
+#include <SDL/SDL_mouse.h>
+
+
+namespace Urho3D
+{
+
+enum MouseButton : unsigned
+{
+    MOUSEB_NONE,
+    MOUSEB_LEFT = SDL_BUTTON_LMASK,
+    MOUSEB_MIDDLE = SDL_BUTTON_MMASK,
+    MOUSEB_RIGHT = SDL_BUTTON_RMASK,
+    MOUSEB_X1 = SDL_BUTTON_X1MASK,
+    MOUSEB_X2 = SDL_BUTTON_X2MASK,
+    MOUSEB_ANY = M_MAX_UNSIGNED
+};
+template<> struct is_flagset<MouseButton> { constexpr static bool value = true; };
+
+enum Qualifier : unsigned
+{
+    QUAL_NONE = 0,
+    QUAL_SHIFT = 1,
+    QUAL_CTRL = 2,
+    QUAL_ALT = 4,
+    QUAL_ANY = 8
+};
+template<> struct is_flagset<Qualifier> { constexpr static bool value = true; };
+
+
+enum Key : unsigned
+{
+    KEY_UNKNOWN = SDLK_UNKNOWN,
+    KEY_A = SDLK_a,
+    KEY_B = SDLK_b,
+    KEY_C = SDLK_c,
+    KEY_D = SDLK_d,
+    KEY_E = SDLK_e,
+    KEY_F = SDLK_f,
+    KEY_G = SDLK_g,
+    KEY_H = SDLK_h,
+    KEY_I = SDLK_i,
+    KEY_J = SDLK_j,
+    KEY_K = SDLK_k,
+    KEY_L = SDLK_l,
+    KEY_M = SDLK_m,
+    KEY_N = SDLK_n,
+    KEY_O = SDLK_o,
+    KEY_P = SDLK_p,
+    KEY_Q = SDLK_q,
+    KEY_R = SDLK_r,
+    KEY_S = SDLK_s,
+    KEY_T = SDLK_t,
+    KEY_U = SDLK_u,
+    KEY_V = SDLK_v,
+    KEY_W = SDLK_w,
+    KEY_X = SDLK_x,
+    KEY_Y = SDLK_y,
+    KEY_Z = SDLK_z,
+    KEY_0 = SDLK_0,
+    KEY_1 = SDLK_1,
+    KEY_2 = SDLK_2,
+    KEY_3 = SDLK_3,
+    KEY_4 = SDLK_4,
+    KEY_5 = SDLK_5,
+    KEY_6 = SDLK_6,
+    KEY_7 = SDLK_7,
+    KEY_8 = SDLK_8,
+    KEY_9 = SDLK_9,
+    KEY_BACKSPACE = SDLK_BACKSPACE,
+    KEY_TAB = SDLK_TAB,
+    KEY_RETURN = SDLK_RETURN,
+    KEY_RETURN2 = SDLK_RETURN2,
+    KEY_KP_ENTER = SDLK_KP_ENTER,
+    KEY_SHIFT = SDLK_LSHIFT,
+    KEY_CTRL = SDLK_LCTRL,
+    KEY_ALT = SDLK_LALT,
+    KEY_GUI = SDLK_LGUI,
+    KEY_PAUSE = SDLK_PAUSE,
+    KEY_CAPSLOCK = SDLK_CAPSLOCK,
+    KEY_ESCAPE = SDLK_ESCAPE,
+    KEY_SPACE = SDLK_SPACE,
+    KEY_PAGEUP = SDLK_PAGEUP,
+    KEY_PAGEDOWN = SDLK_PAGEDOWN,
+    KEY_END = SDLK_END,
+    KEY_HOME = SDLK_HOME,
+    KEY_LEFT = SDLK_LEFT,
+    KEY_UP = SDLK_UP,
+    KEY_RIGHT = SDLK_RIGHT,
+    KEY_DOWN = SDLK_DOWN,
+    KEY_SELECT = SDLK_SELECT,
+    KEY_PRINTSCREEN = SDLK_PRINTSCREEN,
+    KEY_INSERT = SDLK_INSERT,
+    KEY_DELETE = SDLK_DELETE,
+    KEY_LGUI = SDLK_LGUI,
+    KEY_RGUI = SDLK_RGUI,
+    KEY_APPLICATION = SDLK_APPLICATION,
+    KEY_KP_0 = SDLK_KP_0,
+    KEY_KP_1 = SDLK_KP_1,
+    KEY_KP_2 = SDLK_KP_2,
+    KEY_KP_3 = SDLK_KP_3,
+    KEY_KP_4 = SDLK_KP_4,
+    KEY_KP_5 = SDLK_KP_5,
+    KEY_KP_6 = SDLK_KP_6,
+    KEY_KP_7 = SDLK_KP_7,
+    KEY_KP_8 = SDLK_KP_8,
+    KEY_KP_9 = SDLK_KP_9,
+    KEY_KP_MULTIPLY = SDLK_KP_MULTIPLY,
+    KEY_KP_PLUS = SDLK_KP_PLUS,
+    KEY_KP_MINUS = SDLK_KP_MINUS,
+    KEY_KP_PERIOD = SDLK_KP_PERIOD,
+    KEY_KP_DIVIDE = SDLK_KP_DIVIDE,
+    KEY_F1 = SDLK_F1,
+    KEY_F2 = SDLK_F2,
+    KEY_F3 = SDLK_F3,
+    KEY_F4 = SDLK_F4,
+    KEY_F5 = SDLK_F5,
+    KEY_F6 = SDLK_F6,
+    KEY_F7 = SDLK_F7,
+    KEY_F8 = SDLK_F8,
+    KEY_F9 = SDLK_F9,
+    KEY_F10 = SDLK_F10,
+    KEY_F11 = SDLK_F11,
+    KEY_F12 = SDLK_F12,
+    KEY_F13 = SDLK_F13,
+    KEY_F14 = SDLK_F14,
+    KEY_F15 = SDLK_F15,
+    KEY_F16 = SDLK_F16,
+    KEY_F17 = SDLK_F17,
+    KEY_F18 = SDLK_F18,
+    KEY_F19 = SDLK_F19,
+    KEY_F20 = SDLK_F20,
+    KEY_F21 = SDLK_F21,
+    KEY_F22 = SDLK_F22,
+    KEY_F23 = SDLK_F23,
+    KEY_F24 = SDLK_F24,
+    KEY_NUMLOCKCLEAR = SDLK_NUMLOCKCLEAR,
+    KEY_SCROLLLOCK = SDLK_SCROLLLOCK,
+    KEY_LSHIFT = SDLK_LSHIFT,
+    KEY_RSHIFT = SDLK_RSHIFT,
+    KEY_LCTRL = SDLK_LCTRL,
+    KEY_RCTRL = SDLK_RCTRL,
+    KEY_LALT = SDLK_LALT,
+    KEY_RALT = SDLK_RALT,
+    KEY_AC_BACK = SDLK_AC_BACK,
+    KEY_AC_BOOKMARKS = SDLK_AC_BOOKMARKS,
+    KEY_AC_FORWARD = SDLK_AC_FORWARD,
+    KEY_AC_HOME = SDLK_AC_HOME,
+    KEY_AC_REFRESH = SDLK_AC_REFRESH,
+    KEY_AC_SEARCH = SDLK_AC_SEARCH,
+    KEY_AC_STOP = SDLK_AC_STOP,
+    KEY_AGAIN = SDLK_AGAIN,
+    KEY_ALTERASE = SDLK_ALTERASE,
+    KEY_AMPERSAND = SDLK_AMPERSAND,
+    KEY_ASTERISK = SDLK_ASTERISK,
+    KEY_AT = SDLK_AT,
+    KEY_AUDIOMUTE = SDLK_AUDIOMUTE,
+    KEY_AUDIONEXT = SDLK_AUDIONEXT,
+    KEY_AUDIOPLAY = SDLK_AUDIOPLAY,
+    KEY_AUDIOPREV = SDLK_AUDIOPREV,
+    KEY_AUDIOSTOP = SDLK_AUDIOSTOP,
+    KEY_BACKQUOTE = SDLK_BACKQUOTE,
+    KEY_BACKSLASH = SDLK_BACKSLASH,
+    KEY_BRIGHTNESSDOWN = SDLK_BRIGHTNESSDOWN,
+    KEY_BRIGHTNESSUP = SDLK_BRIGHTNESSUP,
+    KEY_CALCULATOR = SDLK_CALCULATOR,
+    KEY_CANCEL = SDLK_CANCEL,
+    KEY_CARET = SDLK_CARET,
+    KEY_CLEAR = SDLK_CLEAR,
+    KEY_CLEARAGAIN = SDLK_CLEARAGAIN,
+    KEY_COLON = SDLK_COLON,
+    KEY_COMMA = SDLK_COMMA,
+    KEY_COMPUTER = SDLK_COMPUTER,
+    KEY_COPY = SDLK_COPY,
+    KEY_CRSEL = SDLK_CRSEL,
+    KEY_CURRENCYSUBUNIT = SDLK_CURRENCYSUBUNIT,
+    KEY_CURRENCYUNIT = SDLK_CURRENCYUNIT,
+    KEY_CUT = SDLK_CUT,
+    KEY_DECIMALSEPARATOR = SDLK_DECIMALSEPARATOR,
+    KEY_DISPLAYSWITCH = SDLK_DISPLAYSWITCH,
+    KEY_DOLLAR = SDLK_DOLLAR,
+    KEY_EJECT = SDLK_EJECT,
+    KEY_EQUALS = SDLK_EQUALS,
+    KEY_EXCLAIM = SDLK_EXCLAIM,
+    KEY_EXSEL = SDLK_EXSEL,
+    KEY_FIND = SDLK_FIND,
+    KEY_GREATER = SDLK_GREATER,
+    KEY_HASH = SDLK_HASH,
+    KEY_HELP = SDLK_HELP,
+    KEY_KBDILLUMDOWN = SDLK_KBDILLUMDOWN,
+    KEY_KBDILLUMTOGGLE = SDLK_KBDILLUMTOGGLE,
+    KEY_KBDILLUMUP = SDLK_KBDILLUMUP,
+    KEY_KP_00 = SDLK_KP_00,
+    KEY_KP_000 = SDLK_KP_000,
+    KEY_KP_A = SDLK_KP_A,
+    KEY_KP_AMPERSAND = SDLK_KP_AMPERSAND,
+    KEY_KP_AT = SDLK_KP_AT,
+    KEY_KP_B = SDLK_KP_B,
+    KEY_KP_BACKSPACE = SDLK_KP_BACKSPACE,
+    KEY_KP_BINARY = SDLK_KP_BINARY,
+    KEY_KP_C = SDLK_KP_C,
+    KEY_KP_CLEAR = SDLK_KP_CLEAR,
+    KEY_KP_CLEARENTRY = SDLK_KP_CLEARENTRY,
+    KEY_KP_COLON = SDLK_KP_COLON,
+    KEY_KP_COMMA = SDLK_KP_COMMA,
+    KEY_KP_D = SDLK_KP_D,
+    KEY_KP_DBLAMPERSAND = SDLK_KP_DBLAMPERSAND,
+    KEY_KP_DBLVERTICALBAR = SDLK_KP_DBLVERTICALBAR,
+    KEY_KP_DECIMAL = SDLK_KP_DECIMAL,
+    KEY_KP_E = SDLK_KP_E,
+    KEY_KP_EQUALS = SDLK_KP_EQUALS,
+    KEY_KP_EQUALSAS400 = SDLK_KP_EQUALSAS400,
+    KEY_KP_EXCLAM = SDLK_KP_EXCLAM,
+    KEY_KP_F = SDLK_KP_F,
+    KEY_KP_GREATER = SDLK_KP_GREATER,
+    KEY_KP_HASH = SDLK_KP_HASH,
+    KEY_KP_HEXADECIMAL = SDLK_KP_HEXADECIMAL,
+    KEY_KP_LEFTBRACE = SDLK_KP_LEFTBRACE,
+    KEY_KP_LEFTPAREN = SDLK_KP_LEFTPAREN,
+    KEY_KP_LESS = SDLK_KP_LESS,
+    KEY_KP_MEMADD = SDLK_KP_MEMADD,
+    KEY_KP_MEMCLEAR = SDLK_KP_MEMCLEAR,
+    KEY_KP_MEMDIVIDE = SDLK_KP_MEMDIVIDE,
+    KEY_KP_MEMMULTIPLY = SDLK_KP_MEMMULTIPLY,
+    KEY_KP_MEMRECALL = SDLK_KP_MEMRECALL,
+    KEY_KP_MEMSTORE = SDLK_KP_MEMSTORE,
+    KEY_KP_MEMSUBTRACT = SDLK_KP_MEMSUBTRACT,
+    KEY_KP_OCTAL = SDLK_KP_OCTAL,
+    KEY_KP_PERCENT = SDLK_KP_PERCENT,
+    KEY_KP_PLUSMINUS = SDLK_KP_PLUSMINUS,
+    KEY_KP_POWER = SDLK_KP_POWER,
+    KEY_KP_RIGHTBRACE = SDLK_KP_RIGHTBRACE,
+    KEY_KP_RIGHTPAREN = SDLK_KP_RIGHTPAREN,
+    KEY_KP_SPACE = SDLK_KP_SPACE,
+    KEY_KP_TAB = SDLK_KP_TAB,
+    KEY_KP_VERTICALBAR = SDLK_KP_VERTICALBAR,
+    KEY_KP_XOR = SDLK_KP_XOR,
+    KEY_LEFTBRACKET = SDLK_LEFTBRACKET,
+    KEY_LEFTPAREN = SDLK_LEFTPAREN,
+    KEY_LESS = SDLK_LESS,
+    KEY_MAIL = SDLK_MAIL,
+    KEY_MEDIASELECT = SDLK_MEDIASELECT,
+    KEY_MENU = SDLK_MENU,
+    KEY_MINUS = SDLK_MINUS,
+    KEY_MODE = SDLK_MODE,
+    KEY_MUTE = SDLK_MUTE,
+    KEY_OPER = SDLK_OPER,
+    KEY_OUT = SDLK_OUT,
+    KEY_PASTE = SDLK_PASTE,
+    KEY_PERCENT = SDLK_PERCENT,
+    KEY_PERIOD = SDLK_PERIOD,
+    KEY_PLUS = SDLK_PLUS,
+    KEY_POWER = SDLK_POWER,
+    KEY_PRIOR = SDLK_PRIOR,
+    KEY_QUESTION = SDLK_QUESTION,
+    KEY_QUOTE = SDLK_QUOTE,
+    KEY_QUOTEDBL = SDLK_QUOTEDBL,
+    KEY_RIGHTBRACKET = SDLK_RIGHTBRACKET,
+    KEY_RIGHTPAREN = SDLK_RIGHTPAREN,
+    KEY_SEMICOLON = SDLK_SEMICOLON,
+    KEY_SEPARATOR = SDLK_SEPARATOR,
+    KEY_SLASH = SDLK_SLASH,
+    KEY_SLEEP = SDLK_SLEEP,
+    KEY_STOP = SDLK_STOP,
+    KEY_SYSREQ = SDLK_SYSREQ,
+    KEY_THOUSANDSSEPARATOR = SDLK_THOUSANDSSEPARATOR,
+    KEY_UNDERSCORE = SDLK_UNDERSCORE,
+    KEY_UNDO = SDLK_UNDO,
+    KEY_VOLUMEDOWN = SDLK_VOLUMEDOWN,
+    KEY_VOLUMEUP = SDLK_VOLUMEUP,
+    KEY_WWW = SDLK_WWW,
+};
+
+enum Scancode : unsigned
+{
+    SCANCODE_UNKNOWN = SDL_SCANCODE_UNKNOWN,
+    SCANCODE_CTRL = SDL_SCANCODE_LCTRL,
+    SCANCODE_SHIFT = SDL_SCANCODE_LSHIFT,
+    SCANCODE_ALT = SDL_SCANCODE_LALT,
+    SCANCODE_GUI = SDL_SCANCODE_LGUI,
+    SCANCODE_A = SDL_SCANCODE_A,
+    SCANCODE_B = SDL_SCANCODE_B,
+    SCANCODE_C = SDL_SCANCODE_C,
+    SCANCODE_D = SDL_SCANCODE_D,
+    SCANCODE_E = SDL_SCANCODE_E,
+    SCANCODE_F = SDL_SCANCODE_F,
+    SCANCODE_G = SDL_SCANCODE_G,
+    SCANCODE_H = SDL_SCANCODE_H,
+    SCANCODE_I = SDL_SCANCODE_I,
+    SCANCODE_J = SDL_SCANCODE_J,
+    SCANCODE_K = SDL_SCANCODE_K,
+    SCANCODE_L = SDL_SCANCODE_L,
+    SCANCODE_M = SDL_SCANCODE_M,
+    SCANCODE_N = SDL_SCANCODE_N,
+    SCANCODE_O = SDL_SCANCODE_O,
+    SCANCODE_P = SDL_SCANCODE_P,
+    SCANCODE_Q = SDL_SCANCODE_Q,
+    SCANCODE_R = SDL_SCANCODE_R,
+    SCANCODE_S = SDL_SCANCODE_S,
+    SCANCODE_T = SDL_SCANCODE_T,
+    SCANCODE_U = SDL_SCANCODE_U,
+    SCANCODE_V = SDL_SCANCODE_V,
+    SCANCODE_W = SDL_SCANCODE_W,
+    SCANCODE_X = SDL_SCANCODE_X,
+    SCANCODE_Y = SDL_SCANCODE_Y,
+    SCANCODE_Z = SDL_SCANCODE_Z,
+    SCANCODE_1 = SDL_SCANCODE_1,
+    SCANCODE_2 = SDL_SCANCODE_2,
+    SCANCODE_3 = SDL_SCANCODE_3,
+    SCANCODE_4 = SDL_SCANCODE_4,
+    SCANCODE_5 = SDL_SCANCODE_5,
+    SCANCODE_6 = SDL_SCANCODE_6,
+    SCANCODE_7 = SDL_SCANCODE_7,
+    SCANCODE_8 = SDL_SCANCODE_8,
+    SCANCODE_9 = SDL_SCANCODE_9,
+    SCANCODE_0 = SDL_SCANCODE_0,
+    SCANCODE_RETURN = SDL_SCANCODE_RETURN,
+    SCANCODE_ESCAPE = SDL_SCANCODE_ESCAPE,
+    SCANCODE_BACKSPACE = SDL_SCANCODE_BACKSPACE,
+    SCANCODE_TAB = SDL_SCANCODE_TAB,
+    SCANCODE_SPACE = SDL_SCANCODE_SPACE,
+    SCANCODE_MINUS = SDL_SCANCODE_MINUS,
+    SCANCODE_EQUALS = SDL_SCANCODE_EQUALS,
+    SCANCODE_LEFTBRACKET = SDL_SCANCODE_LEFTBRACKET,
+    SCANCODE_RIGHTBRACKET = SDL_SCANCODE_RIGHTBRACKET,
+    SCANCODE_BACKSLASH = SDL_SCANCODE_BACKSLASH,
+    SCANCODE_NONUSHASH = SDL_SCANCODE_NONUSHASH,
+    SCANCODE_SEMICOLON = SDL_SCANCODE_SEMICOLON,
+    SCANCODE_APOSTROPHE = SDL_SCANCODE_APOSTROPHE,
+    SCANCODE_GRAVE = SDL_SCANCODE_GRAVE,
+    SCANCODE_COMMA = SDL_SCANCODE_COMMA,
+    SCANCODE_PERIOD = SDL_SCANCODE_PERIOD,
+    SCANCODE_SLASH = SDL_SCANCODE_SLASH,
+    SCANCODE_CAPSLOCK = SDL_SCANCODE_CAPSLOCK,
+    SCANCODE_F1 = SDL_SCANCODE_F1,
+    SCANCODE_F2 = SDL_SCANCODE_F2,
+    SCANCODE_F3 = SDL_SCANCODE_F3,
+    SCANCODE_F4 = SDL_SCANCODE_F4,
+    SCANCODE_F5 = SDL_SCANCODE_F5,
+    SCANCODE_F6 = SDL_SCANCODE_F6,
+    SCANCODE_F7 = SDL_SCANCODE_F7,
+    SCANCODE_F8 = SDL_SCANCODE_F8,
+    SCANCODE_F9 = SDL_SCANCODE_F9,
+    SCANCODE_F10 = SDL_SCANCODE_F10,
+    SCANCODE_F11 = SDL_SCANCODE_F11,
+    SCANCODE_F12 = SDL_SCANCODE_F12,
+    SCANCODE_PRINTSCREEN = SDL_SCANCODE_PRINTSCREEN,
+    SCANCODE_SCROLLLOCK = SDL_SCANCODE_SCROLLLOCK,
+    SCANCODE_PAUSE = SDL_SCANCODE_PAUSE,
+    SCANCODE_INSERT = SDL_SCANCODE_INSERT,
+    SCANCODE_HOME = SDL_SCANCODE_HOME,
+    SCANCODE_PAGEUP = SDL_SCANCODE_PAGEUP,
+    SCANCODE_DELETE = SDL_SCANCODE_DELETE,
+    SCANCODE_END = SDL_SCANCODE_END,
+    SCANCODE_PAGEDOWN = SDL_SCANCODE_PAGEDOWN,
+    SCANCODE_RIGHT = SDL_SCANCODE_RIGHT,
+    SCANCODE_LEFT = SDL_SCANCODE_LEFT,
+    SCANCODE_DOWN = SDL_SCANCODE_DOWN,
+    SCANCODE_UP = SDL_SCANCODE_UP,
+    SCANCODE_NUMLOCKCLEAR = SDL_SCANCODE_NUMLOCKCLEAR,
+    SCANCODE_KP_DIVIDE = SDL_SCANCODE_KP_DIVIDE,
+    SCANCODE_KP_MULTIPLY = SDL_SCANCODE_KP_MULTIPLY,
+    SCANCODE_KP_MINUS = SDL_SCANCODE_KP_MINUS,
+    SCANCODE_KP_PLUS = SDL_SCANCODE_KP_PLUS,
+    SCANCODE_KP_ENTER = SDL_SCANCODE_KP_ENTER,
+    SCANCODE_KP_1 = SDL_SCANCODE_KP_1,
+    SCANCODE_KP_2 = SDL_SCANCODE_KP_2,
+    SCANCODE_KP_3 = SDL_SCANCODE_KP_3,
+    SCANCODE_KP_4 = SDL_SCANCODE_KP_4,
+    SCANCODE_KP_5 = SDL_SCANCODE_KP_5,
+    SCANCODE_KP_6 = SDL_SCANCODE_KP_6,
+    SCANCODE_KP_7 = SDL_SCANCODE_KP_7,
+    SCANCODE_KP_8 = SDL_SCANCODE_KP_8,
+    SCANCODE_KP_9 = SDL_SCANCODE_KP_9,
+    SCANCODE_KP_0 = SDL_SCANCODE_KP_0,
+    SCANCODE_KP_PERIOD = SDL_SCANCODE_KP_PERIOD,
+    SCANCODE_NONUSBACKSLASH = SDL_SCANCODE_NONUSBACKSLASH,
+    SCANCODE_APPLICATION = SDL_SCANCODE_APPLICATION,
+    SCANCODE_POWER = SDL_SCANCODE_POWER,
+    SCANCODE_KP_EQUALS = SDL_SCANCODE_KP_EQUALS,
+    SCANCODE_F13 = SDL_SCANCODE_F13,
+    SCANCODE_F14 = SDL_SCANCODE_F14,
+    SCANCODE_F15 = SDL_SCANCODE_F15,
+    SCANCODE_F16 = SDL_SCANCODE_F16,
+    SCANCODE_F17 = SDL_SCANCODE_F17,
+    SCANCODE_F18 = SDL_SCANCODE_F18,
+    SCANCODE_F19 = SDL_SCANCODE_F19,
+    SCANCODE_F20 = SDL_SCANCODE_F20,
+    SCANCODE_F21 = SDL_SCANCODE_F21,
+    SCANCODE_F22 = SDL_SCANCODE_F22,
+    SCANCODE_F23 = SDL_SCANCODE_F23,
+    SCANCODE_F24 = SDL_SCANCODE_F24,
+    SCANCODE_EXECUTE = SDL_SCANCODE_EXECUTE,
+    SCANCODE_HELP = SDL_SCANCODE_HELP,
+    SCANCODE_MENU = SDL_SCANCODE_MENU,
+    SCANCODE_SELECT = SDL_SCANCODE_SELECT,
+    SCANCODE_STOP = SDL_SCANCODE_STOP,
+    SCANCODE_AGAIN = SDL_SCANCODE_AGAIN,
+    SCANCODE_UNDO = SDL_SCANCODE_UNDO,
+    SCANCODE_CUT = SDL_SCANCODE_CUT,
+    SCANCODE_COPY = SDL_SCANCODE_COPY,
+    SCANCODE_PASTE = SDL_SCANCODE_PASTE,
+    SCANCODE_FIND = SDL_SCANCODE_FIND,
+    SCANCODE_MUTE = SDL_SCANCODE_MUTE,
+    SCANCODE_VOLUMEUP = SDL_SCANCODE_VOLUMEUP,
+    SCANCODE_VOLUMEDOWN = SDL_SCANCODE_VOLUMEDOWN,
+    SCANCODE_KP_COMMA = SDL_SCANCODE_KP_COMMA,
+    SCANCODE_KP_EQUALSAS400 = SDL_SCANCODE_KP_EQUALSAS400,
+    SCANCODE_INTERNATIONAL1 = SDL_SCANCODE_INTERNATIONAL1,
+    SCANCODE_INTERNATIONAL2 = SDL_SCANCODE_INTERNATIONAL2,
+    SCANCODE_INTERNATIONAL3 = SDL_SCANCODE_INTERNATIONAL3,
+    SCANCODE_INTERNATIONAL4 = SDL_SCANCODE_INTERNATIONAL4,
+    SCANCODE_INTERNATIONAL5 = SDL_SCANCODE_INTERNATIONAL5,
+    SCANCODE_INTERNATIONAL6 = SDL_SCANCODE_INTERNATIONAL6,
+    SCANCODE_INTERNATIONAL7 = SDL_SCANCODE_INTERNATIONAL7,
+    SCANCODE_INTERNATIONAL8 = SDL_SCANCODE_INTERNATIONAL8,
+    SCANCODE_INTERNATIONAL9 = SDL_SCANCODE_INTERNATIONAL9,
+    SCANCODE_LANG1 = SDL_SCANCODE_LANG1,
+    SCANCODE_LANG2 = SDL_SCANCODE_LANG2,
+    SCANCODE_LANG3 = SDL_SCANCODE_LANG3,
+    SCANCODE_LANG4 = SDL_SCANCODE_LANG4,
+    SCANCODE_LANG5 = SDL_SCANCODE_LANG5,
+    SCANCODE_LANG6 = SDL_SCANCODE_LANG6,
+    SCANCODE_LANG7 = SDL_SCANCODE_LANG7,
+    SCANCODE_LANG8 = SDL_SCANCODE_LANG8,
+    SCANCODE_LANG9 = SDL_SCANCODE_LANG9,
+    SCANCODE_ALTERASE = SDL_SCANCODE_ALTERASE,
+    SCANCODE_SYSREQ = SDL_SCANCODE_SYSREQ,
+    SCANCODE_CANCEL = SDL_SCANCODE_CANCEL,
+    SCANCODE_CLEAR = SDL_SCANCODE_CLEAR,
+    SCANCODE_PRIOR = SDL_SCANCODE_PRIOR,
+    SCANCODE_RETURN2 = SDL_SCANCODE_RETURN2,
+    SCANCODE_SEPARATOR = SDL_SCANCODE_SEPARATOR,
+    SCANCODE_OUT = SDL_SCANCODE_OUT,
+    SCANCODE_OPER = SDL_SCANCODE_OPER,
+    SCANCODE_CLEARAGAIN = SDL_SCANCODE_CLEARAGAIN,
+    SCANCODE_CRSEL = SDL_SCANCODE_CRSEL,
+    SCANCODE_EXSEL = SDL_SCANCODE_EXSEL,
+    SCANCODE_KP_00 = SDL_SCANCODE_KP_00,
+    SCANCODE_KP_000 = SDL_SCANCODE_KP_000,
+    SCANCODE_THOUSANDSSEPARATOR = SDL_SCANCODE_THOUSANDSSEPARATOR,
+    SCANCODE_DECIMALSEPARATOR = SDL_SCANCODE_DECIMALSEPARATOR,
+    SCANCODE_CURRENCYUNIT = SDL_SCANCODE_CURRENCYUNIT,
+    SCANCODE_CURRENCYSUBUNIT = SDL_SCANCODE_CURRENCYSUBUNIT,
+    SCANCODE_KP_LEFTPAREN = SDL_SCANCODE_KP_LEFTPAREN,
+    SCANCODE_KP_RIGHTPAREN = SDL_SCANCODE_KP_RIGHTPAREN,
+    SCANCODE_KP_LEFTBRACE = SDL_SCANCODE_KP_LEFTBRACE,
+    SCANCODE_KP_RIGHTBRACE = SDL_SCANCODE_KP_RIGHTBRACE,
+    SCANCODE_KP_TAB = SDL_SCANCODE_KP_TAB,
+    SCANCODE_KP_BACKSPACE = SDL_SCANCODE_KP_BACKSPACE,
+    SCANCODE_KP_A = SDL_SCANCODE_KP_A,
+    SCANCODE_KP_B = SDL_SCANCODE_KP_B,
+    SCANCODE_KP_C = SDL_SCANCODE_KP_C,
+    SCANCODE_KP_D = SDL_SCANCODE_KP_D,
+    SCANCODE_KP_E = SDL_SCANCODE_KP_E,
+    SCANCODE_KP_F = SDL_SCANCODE_KP_F,
+    SCANCODE_KP_XOR = SDL_SCANCODE_KP_XOR,
+    SCANCODE_KP_POWER = SDL_SCANCODE_KP_POWER,
+    SCANCODE_KP_PERCENT = SDL_SCANCODE_KP_PERCENT,
+    SCANCODE_KP_LESS = SDL_SCANCODE_KP_LESS,
+    SCANCODE_KP_GREATER = SDL_SCANCODE_KP_GREATER,
+    SCANCODE_KP_AMPERSAND = SDL_SCANCODE_KP_AMPERSAND,
+    SCANCODE_KP_DBLAMPERSAND = SDL_SCANCODE_KP_DBLAMPERSAND,
+    SCANCODE_KP_VERTICALBAR = SDL_SCANCODE_KP_VERTICALBAR,
+    SCANCODE_KP_DBLVERTICALBAR = SDL_SCANCODE_KP_DBLVERTICALBAR,
+    SCANCODE_KP_COLON = SDL_SCANCODE_KP_COLON,
+    SCANCODE_KP_HASH = SDL_SCANCODE_KP_HASH,
+    SCANCODE_KP_SPACE = SDL_SCANCODE_KP_SPACE,
+    SCANCODE_KP_AT = SDL_SCANCODE_KP_AT,
+    SCANCODE_KP_EXCLAM = SDL_SCANCODE_KP_EXCLAM,
+    SCANCODE_KP_MEMSTORE = SDL_SCANCODE_KP_MEMSTORE,
+    SCANCODE_KP_MEMRECALL = SDL_SCANCODE_KP_MEMRECALL,
+    SCANCODE_KP_MEMCLEAR = SDL_SCANCODE_KP_MEMCLEAR,
+    SCANCODE_KP_MEMADD = SDL_SCANCODE_KP_MEMADD,
+    SCANCODE_KP_MEMSUBTRACT = SDL_SCANCODE_KP_MEMSUBTRACT,
+    SCANCODE_KP_MEMMULTIPLY = SDL_SCANCODE_KP_MEMMULTIPLY,
+    SCANCODE_KP_MEMDIVIDE = SDL_SCANCODE_KP_MEMDIVIDE,
+    SCANCODE_KP_PLUSMINUS = SDL_SCANCODE_KP_PLUSMINUS,
+    SCANCODE_KP_CLEAR = SDL_SCANCODE_KP_CLEAR,
+    SCANCODE_KP_CLEARENTRY = SDL_SCANCODE_KP_CLEARENTRY,
+    SCANCODE_KP_BINARY = SDL_SCANCODE_KP_BINARY,
+    SCANCODE_KP_OCTAL = SDL_SCANCODE_KP_OCTAL,
+    SCANCODE_KP_DECIMAL = SDL_SCANCODE_KP_DECIMAL,
+    SCANCODE_KP_HEXADECIMAL = SDL_SCANCODE_KP_HEXADECIMAL,
+    SCANCODE_LCTRL = SDL_SCANCODE_LCTRL,
+    SCANCODE_LSHIFT = SDL_SCANCODE_LSHIFT,
+    SCANCODE_LALT = SDL_SCANCODE_LALT,
+    SCANCODE_LGUI = SDL_SCANCODE_LGUI,
+    SCANCODE_RCTRL = SDL_SCANCODE_RCTRL,
+    SCANCODE_RSHIFT = SDL_SCANCODE_RSHIFT,
+    SCANCODE_RALT = SDL_SCANCODE_RALT,
+    SCANCODE_RGUI = SDL_SCANCODE_RGUI,
+    SCANCODE_MODE = SDL_SCANCODE_MODE,
+    SCANCODE_AUDIONEXT = SDL_SCANCODE_AUDIONEXT,
+    SCANCODE_AUDIOPREV = SDL_SCANCODE_AUDIOPREV,
+    SCANCODE_AUDIOSTOP = SDL_SCANCODE_AUDIOSTOP,
+    SCANCODE_AUDIOPLAY = SDL_SCANCODE_AUDIOPLAY,
+    SCANCODE_AUDIOMUTE = SDL_SCANCODE_AUDIOMUTE,
+    SCANCODE_MEDIASELECT = SDL_SCANCODE_MEDIASELECT,
+    SCANCODE_WWW = SDL_SCANCODE_WWW,
+    SCANCODE_MAIL = SDL_SCANCODE_MAIL,
+    SCANCODE_CALCULATOR = SDL_SCANCODE_CALCULATOR,
+    SCANCODE_COMPUTER = SDL_SCANCODE_COMPUTER,
+    SCANCODE_AC_SEARCH = SDL_SCANCODE_AC_SEARCH,
+    SCANCODE_AC_HOME = SDL_SCANCODE_AC_HOME,
+    SCANCODE_AC_BACK = SDL_SCANCODE_AC_BACK,
+    SCANCODE_AC_FORWARD = SDL_SCANCODE_AC_FORWARD,
+    SCANCODE_AC_STOP = SDL_SCANCODE_AC_STOP,
+    SCANCODE_AC_REFRESH = SDL_SCANCODE_AC_REFRESH,
+    SCANCODE_AC_BOOKMARKS = SDL_SCANCODE_AC_BOOKMARKS,
+    SCANCODE_BRIGHTNESSDOWN = SDL_SCANCODE_BRIGHTNESSDOWN,
+    SCANCODE_BRIGHTNESSUP = SDL_SCANCODE_BRIGHTNESSUP,
+    SCANCODE_DISPLAYSWITCH = SDL_SCANCODE_DISPLAYSWITCH,
+    SCANCODE_KBDILLUMTOGGLE = SDL_SCANCODE_KBDILLUMTOGGLE,
+    SCANCODE_KBDILLUMDOWN = SDL_SCANCODE_KBDILLUMDOWN,
+    SCANCODE_KBDILLUMUP = SDL_SCANCODE_KBDILLUMUP,
+    SCANCODE_EJECT = SDL_SCANCODE_EJECT,
+    SCANCODE_SLEEP = SDL_SCANCODE_SLEEP,
+    SCANCODE_APP1 = SDL_SCANCODE_APP1,
+    SCANCODE_APP2 = SDL_SCANCODE_APP2,
+};
+
+enum HatPosition : unsigned
+{
+    HAT_CENTER = SDL_HAT_CENTERED,
+    HAT_UP = SDL_HAT_UP,
+    HAT_RIGHT = SDL_HAT_RIGHT,
+    HAT_DOWN = SDL_HAT_DOWN,
+    HAT_LEFT = SDL_HAT_LEFT,
+};
+
+enum ControllerButton : unsigned
+{
+    CONTROLLER_BUTTON_A = SDL_CONTROLLER_BUTTON_A,
+    CONTROLLER_BUTTON_B = SDL_CONTROLLER_BUTTON_B,
+    CONTROLLER_BUTTON_X = SDL_CONTROLLER_BUTTON_X,
+    CONTROLLER_BUTTON_Y = SDL_CONTROLLER_BUTTON_Y,
+    CONTROLLER_BUTTON_BACK = SDL_CONTROLLER_BUTTON_BACK,
+    CONTROLLER_BUTTON_GUIDE = SDL_CONTROLLER_BUTTON_GUIDE,
+    CONTROLLER_BUTTON_START = SDL_CONTROLLER_BUTTON_START,
+    CONTROLLER_BUTTON_LEFTSTICK = SDL_CONTROLLER_BUTTON_LEFTSTICK,
+    CONTROLLER_BUTTON_RIGHTSTICK = SDL_CONTROLLER_BUTTON_RIGHTSTICK,
+    CONTROLLER_BUTTON_LEFTSHOULDER = SDL_CONTROLLER_BUTTON_LEFTSHOULDER,
+    CONTROLLER_BUTTON_RIGHTSHOULDER = SDL_CONTROLLER_BUTTON_RIGHTSHOULDER,
+    CONTROLLER_BUTTON_DPAD_UP = SDL_CONTROLLER_BUTTON_DPAD_UP,
+    CONTROLLER_BUTTON_DPAD_DOWN = SDL_CONTROLLER_BUTTON_DPAD_DOWN,
+    CONTROLLER_BUTTON_DPAD_LEFT = SDL_CONTROLLER_BUTTON_DPAD_LEFT,
+    CONTROLLER_BUTTON_DPAD_RIGHT = SDL_CONTROLLER_BUTTON_DPAD_RIGHT,
+};
+
+enum ControllerAxis : unsigned
+{
+    CONTROLLER_AXIS_LEFTX = SDL_CONTROLLER_AXIS_LEFTX,
+    CONTROLLER_AXIS_LEFTY = SDL_CONTROLLER_AXIS_LEFTY,
+    CONTROLLER_AXIS_RIGHTX = SDL_CONTROLLER_AXIS_RIGHTX,
+    CONTROLLER_AXIS_RIGHTY = SDL_CONTROLLER_AXIS_RIGHTY,
+    CONTROLLER_AXIS_TRIGGERLEFT = SDL_CONTROLLER_AXIS_TRIGGERLEFT,
+    CONTROLLER_AXIS_TRIGGERRIGHT = SDL_CONTROLLER_AXIS_TRIGGERRIGHT,
+};
+
+}

+ 2 - 531
Source/Urho3D/Input/InputEvents.h

@@ -23,11 +23,8 @@
 #pragma once
 
 #include "../Core/Object.h"
+#include "../Input/InputConstants.h"
 
-#include <SDL/SDL_joystick.h>
-#include <SDL/SDL_gamecontroller.h>
-#include <SDL/SDL_keycode.h>
-#include <SDL/SDL_mouse.h>
 
 namespace Urho3D
 {
@@ -231,7 +228,7 @@ URHO3D_EVENT(E_EXITREQUESTED, ExitRequested)
 URHO3D_EVENT(E_SDLRAWINPUT, SDLRawInput)
 {
     URHO3D_PARAM(P_SDLEVENT, SDLEvent);           // SDL_Event*
-    URHO3D_PARAM(P_CONSUMED, Consumed);            // bool
+    URHO3D_PARAM(P_CONSUMED, Consumed);           // bool
 }
 
 /// Input handling begins.
@@ -244,530 +241,4 @@ URHO3D_EVENT(E_INPUTEND, InputEnd)
 {
 }
 
-static const int MOUSEB_LEFT = SDL_BUTTON_LMASK;
-static const int MOUSEB_MIDDLE = SDL_BUTTON_MMASK;
-static const int MOUSEB_RIGHT = SDL_BUTTON_RMASK;
-static const int MOUSEB_X1 = SDL_BUTTON_X1MASK;
-static const int MOUSEB_X2 = SDL_BUTTON_X2MASK;
-
-static const int QUAL_SHIFT = 1;
-static const int QUAL_CTRL = 2;
-static const int QUAL_ALT = 4;
-static const int QUAL_ANY = 8;
-
-static const int KEY_UNKNOWN = SDLK_UNKNOWN;
-static const int KEY_A = SDLK_a;
-static const int KEY_B = SDLK_b;
-static const int KEY_C = SDLK_c;
-static const int KEY_D = SDLK_d;
-static const int KEY_E = SDLK_e;
-static const int KEY_F = SDLK_f;
-static const int KEY_G = SDLK_g;
-static const int KEY_H = SDLK_h;
-static const int KEY_I = SDLK_i;
-static const int KEY_J = SDLK_j;
-static const int KEY_K = SDLK_k;
-static const int KEY_L = SDLK_l;
-static const int KEY_M = SDLK_m;
-static const int KEY_N = SDLK_n;
-static const int KEY_O = SDLK_o;
-static const int KEY_P = SDLK_p;
-static const int KEY_Q = SDLK_q;
-static const int KEY_R = SDLK_r;
-static const int KEY_S = SDLK_s;
-static const int KEY_T = SDLK_t;
-static const int KEY_U = SDLK_u;
-static const int KEY_V = SDLK_v;
-static const int KEY_W = SDLK_w;
-static const int KEY_X = SDLK_x;
-static const int KEY_Y = SDLK_y;
-static const int KEY_Z = SDLK_z;
-static const int KEY_0 = SDLK_0;
-static const int KEY_1 = SDLK_1;
-static const int KEY_2 = SDLK_2;
-static const int KEY_3 = SDLK_3;
-static const int KEY_4 = SDLK_4;
-static const int KEY_5 = SDLK_5;
-static const int KEY_6 = SDLK_6;
-static const int KEY_7 = SDLK_7;
-static const int KEY_8 = SDLK_8;
-static const int KEY_9 = SDLK_9;
-static const int KEY_BACKSPACE = SDLK_BACKSPACE;
-static const int KEY_TAB = SDLK_TAB;
-static const int KEY_RETURN = SDLK_RETURN;
-static const int KEY_RETURN2 = SDLK_RETURN2;
-static const int KEY_KP_ENTER = SDLK_KP_ENTER;
-static const int KEY_SHIFT = SDLK_LSHIFT;
-static const int KEY_CTRL = SDLK_LCTRL;
-static const int KEY_ALT = SDLK_LALT;
-static const int KEY_GUI = SDLK_LGUI;
-static const int KEY_PAUSE = SDLK_PAUSE;
-static const int KEY_CAPSLOCK = SDLK_CAPSLOCK;
-static const int KEY_ESCAPE = SDLK_ESCAPE;
-static const int KEY_SPACE = SDLK_SPACE;
-static const int KEY_PAGEUP = SDLK_PAGEUP;
-static const int KEY_PAGEDOWN = SDLK_PAGEDOWN;
-static const int KEY_END = SDLK_END;
-static const int KEY_HOME = SDLK_HOME;
-static const int KEY_LEFT = SDLK_LEFT;
-static const int KEY_UP = SDLK_UP;
-static const int KEY_RIGHT = SDLK_RIGHT;
-static const int KEY_DOWN = SDLK_DOWN;
-static const int KEY_SELECT = SDLK_SELECT;
-static const int KEY_PRINTSCREEN = SDLK_PRINTSCREEN;
-static const int KEY_INSERT = SDLK_INSERT;
-static const int KEY_DELETE = SDLK_DELETE;
-static const int KEY_LGUI = SDLK_LGUI;
-static const int KEY_RGUI = SDLK_RGUI;
-static const int KEY_APPLICATION = SDLK_APPLICATION;
-static const int KEY_KP_0 = SDLK_KP_0;
-static const int KEY_KP_1 = SDLK_KP_1;
-static const int KEY_KP_2 = SDLK_KP_2;
-static const int KEY_KP_3 = SDLK_KP_3;
-static const int KEY_KP_4 = SDLK_KP_4;
-static const int KEY_KP_5 = SDLK_KP_5;
-static const int KEY_KP_6 = SDLK_KP_6;
-static const int KEY_KP_7 = SDLK_KP_7;
-static const int KEY_KP_8 = SDLK_KP_8;
-static const int KEY_KP_9 = SDLK_KP_9;
-static const int KEY_KP_MULTIPLY = SDLK_KP_MULTIPLY;
-static const int KEY_KP_PLUS = SDLK_KP_PLUS;
-static const int KEY_KP_MINUS = SDLK_KP_MINUS;
-static const int KEY_KP_PERIOD = SDLK_KP_PERIOD;
-static const int KEY_KP_DIVIDE = SDLK_KP_DIVIDE;
-static const int KEY_F1 = SDLK_F1;
-static const int KEY_F2 = SDLK_F2;
-static const int KEY_F3 = SDLK_F3;
-static const int KEY_F4 = SDLK_F4;
-static const int KEY_F5 = SDLK_F5;
-static const int KEY_F6 = SDLK_F6;
-static const int KEY_F7 = SDLK_F7;
-static const int KEY_F8 = SDLK_F8;
-static const int KEY_F9 = SDLK_F9;
-static const int KEY_F10 = SDLK_F10;
-static const int KEY_F11 = SDLK_F11;
-static const int KEY_F12 = SDLK_F12;
-static const int KEY_F13 = SDLK_F13;
-static const int KEY_F14 = SDLK_F14;
-static const int KEY_F15 = SDLK_F15;
-static const int KEY_F16 = SDLK_F16;
-static const int KEY_F17 = SDLK_F17;
-static const int KEY_F18 = SDLK_F18;
-static const int KEY_F19 = SDLK_F19;
-static const int KEY_F20 = SDLK_F20;
-static const int KEY_F21 = SDLK_F21;
-static const int KEY_F22 = SDLK_F22;
-static const int KEY_F23 = SDLK_F23;
-static const int KEY_F24 = SDLK_F24;
-static const int KEY_NUMLOCKCLEAR = SDLK_NUMLOCKCLEAR;
-static const int KEY_SCROLLLOCK = SDLK_SCROLLLOCK;
-static const int KEY_LSHIFT = SDLK_LSHIFT;
-static const int KEY_RSHIFT = SDLK_RSHIFT;
-static const int KEY_LCTRL = SDLK_LCTRL;
-static const int KEY_RCTRL = SDLK_RCTRL;
-static const int KEY_LALT = SDLK_LALT;
-static const int KEY_RALT = SDLK_RALT;
-static const int KEY_AC_BACK = SDLK_AC_BACK;
-static const int KEY_AC_BOOKMARKS = SDLK_AC_BOOKMARKS;
-static const int KEY_AC_FORWARD = SDLK_AC_FORWARD;
-static const int KEY_AC_HOME = SDLK_AC_HOME;
-static const int KEY_AC_REFRESH = SDLK_AC_REFRESH;
-static const int KEY_AC_SEARCH = SDLK_AC_SEARCH;
-static const int KEY_AC_STOP = SDLK_AC_STOP;
-static const int KEY_AGAIN = SDLK_AGAIN;
-static const int KEY_ALTERASE = SDLK_ALTERASE;
-static const int KEY_AMPERSAND = SDLK_AMPERSAND;
-static const int KEY_ASTERISK = SDLK_ASTERISK;
-static const int KEY_AT = SDLK_AT;
-static const int KEY_AUDIOMUTE = SDLK_AUDIOMUTE;
-static const int KEY_AUDIONEXT = SDLK_AUDIONEXT;
-static const int KEY_AUDIOPLAY = SDLK_AUDIOPLAY;
-static const int KEY_AUDIOPREV = SDLK_AUDIOPREV;
-static const int KEY_AUDIOSTOP = SDLK_AUDIOSTOP;
-static const int KEY_BACKQUOTE = SDLK_BACKQUOTE;
-static const int KEY_BACKSLASH = SDLK_BACKSLASH;
-static const int KEY_BRIGHTNESSDOWN = SDLK_BRIGHTNESSDOWN;
-static const int KEY_BRIGHTNESSUP = SDLK_BRIGHTNESSUP;
-static const int KEY_CALCULATOR = SDLK_CALCULATOR;
-static const int KEY_CANCEL = SDLK_CANCEL;
-static const int KEY_CARET = SDLK_CARET;
-static const int KEY_CLEAR = SDLK_CLEAR;
-static const int KEY_CLEARAGAIN = SDLK_CLEARAGAIN;
-static const int KEY_COLON = SDLK_COLON;
-static const int KEY_COMMA = SDLK_COMMA;
-static const int KEY_COMPUTER = SDLK_COMPUTER;
-static const int KEY_COPY = SDLK_COPY;
-static const int KEY_CRSEL = SDLK_CRSEL;
-static const int KEY_CURRENCYSUBUNIT = SDLK_CURRENCYSUBUNIT;
-static const int KEY_CURRENCYUNIT = SDLK_CURRENCYUNIT;
-static const int KEY_CUT = SDLK_CUT;
-static const int KEY_DECIMALSEPARATOR = SDLK_DECIMALSEPARATOR;
-static const int KEY_DISPLAYSWITCH = SDLK_DISPLAYSWITCH;
-static const int KEY_DOLLAR = SDLK_DOLLAR;
-static const int KEY_EJECT = SDLK_EJECT;
-static const int KEY_EQUALS = SDLK_EQUALS;
-static const int KEY_EXCLAIM = SDLK_EXCLAIM;
-static const int KEY_EXSEL = SDLK_EXSEL;
-static const int KEY_FIND = SDLK_FIND;
-static const int KEY_GREATER = SDLK_GREATER;
-static const int KEY_HASH = SDLK_HASH;
-static const int KEY_HELP = SDLK_HELP;
-static const int KEY_KBDILLUMDOWN = SDLK_KBDILLUMDOWN;
-static const int KEY_KBDILLUMTOGGLE = SDLK_KBDILLUMTOGGLE;
-static const int KEY_KBDILLUMUP = SDLK_KBDILLUMUP;
-static const int KEY_KP_00 = SDLK_KP_00;
-static const int KEY_KP_000 = SDLK_KP_000;
-static const int KEY_KP_A = SDLK_KP_A;
-static const int KEY_KP_AMPERSAND = SDLK_KP_AMPERSAND;
-static const int KEY_KP_AT = SDLK_KP_AT;
-static const int KEY_KP_B = SDLK_KP_B;
-static const int KEY_KP_BACKSPACE = SDLK_KP_BACKSPACE;
-static const int KEY_KP_BINARY = SDLK_KP_BINARY;
-static const int KEY_KP_C = SDLK_KP_C;
-static const int KEY_KP_CLEAR = SDLK_KP_CLEAR;
-static const int KEY_KP_CLEARENTRY = SDLK_KP_CLEARENTRY;
-static const int KEY_KP_COLON = SDLK_KP_COLON;
-static const int KEY_KP_COMMA = SDLK_KP_COMMA;
-static const int KEY_KP_D = SDLK_KP_D;
-static const int KEY_KP_DBLAMPERSAND = SDLK_KP_DBLAMPERSAND;
-static const int KEY_KP_DBLVERTICALBAR = SDLK_KP_DBLVERTICALBAR;
-static const int KEY_KP_DECIMAL = SDLK_KP_DECIMAL;
-static const int KEY_KP_E = SDLK_KP_E;
-static const int KEY_KP_EQUALS = SDLK_KP_EQUALS;
-static const int KEY_KP_EQUALSAS400 = SDLK_KP_EQUALSAS400;
-static const int KEY_KP_EXCLAM = SDLK_KP_EXCLAM;
-static const int KEY_KP_F = SDLK_KP_F;
-static const int KEY_KP_GREATER = SDLK_KP_GREATER;
-static const int KEY_KP_HASH = SDLK_KP_HASH;
-static const int KEY_KP_HEXADECIMAL = SDLK_KP_HEXADECIMAL;
-static const int KEY_KP_LEFTBRACE = SDLK_KP_LEFTBRACE;
-static const int KEY_KP_LEFTPAREN = SDLK_KP_LEFTPAREN;
-static const int KEY_KP_LESS = SDLK_KP_LESS;
-static const int KEY_KP_MEMADD = SDLK_KP_MEMADD;
-static const int KEY_KP_MEMCLEAR = SDLK_KP_MEMCLEAR;
-static const int KEY_KP_MEMDIVIDE = SDLK_KP_MEMDIVIDE;
-static const int KEY_KP_MEMMULTIPLY = SDLK_KP_MEMMULTIPLY;
-static const int KEY_KP_MEMRECALL = SDLK_KP_MEMRECALL;
-static const int KEY_KP_MEMSTORE = SDLK_KP_MEMSTORE;
-static const int KEY_KP_MEMSUBTRACT = SDLK_KP_MEMSUBTRACT;
-static const int KEY_KP_OCTAL = SDLK_KP_OCTAL;
-static const int KEY_KP_PERCENT = SDLK_KP_PERCENT;
-static const int KEY_KP_PLUSMINUS = SDLK_KP_PLUSMINUS;
-static const int KEY_KP_POWER = SDLK_KP_POWER;
-static const int KEY_KP_RIGHTBRACE = SDLK_KP_RIGHTBRACE;
-static const int KEY_KP_RIGHTPAREN = SDLK_KP_RIGHTPAREN;
-static const int KEY_KP_SPACE = SDLK_KP_SPACE;
-static const int KEY_KP_TAB = SDLK_KP_TAB;
-static const int KEY_KP_VERTICALBAR = SDLK_KP_VERTICALBAR;
-static const int KEY_KP_XOR = SDLK_KP_XOR;
-static const int KEY_LEFTBRACKET = SDLK_LEFTBRACKET;
-static const int KEY_LEFTPAREN = SDLK_LEFTPAREN;
-static const int KEY_LESS = SDLK_LESS;
-static const int KEY_MAIL = SDLK_MAIL;
-static const int KEY_MEDIASELECT = SDLK_MEDIASELECT;
-static const int KEY_MENU = SDLK_MENU;
-static const int KEY_MINUS = SDLK_MINUS;
-static const int KEY_MODE = SDLK_MODE;
-static const int KEY_MUTE = SDLK_MUTE;
-static const int KEY_OPER = SDLK_OPER;
-static const int KEY_OUT = SDLK_OUT;
-static const int KEY_PASTE = SDLK_PASTE;
-static const int KEY_PERCENT = SDLK_PERCENT;
-static const int KEY_PERIOD = SDLK_PERIOD;
-static const int KEY_PLUS = SDLK_PLUS;
-static const int KEY_POWER = SDLK_POWER;
-static const int KEY_PRIOR = SDLK_PRIOR;
-static const int KEY_QUESTION = SDLK_QUESTION;
-static const int KEY_QUOTE = SDLK_QUOTE;
-static const int KEY_QUOTEDBL = SDLK_QUOTEDBL;
-static const int KEY_RIGHTBRACKET = SDLK_RIGHTBRACKET;
-static const int KEY_RIGHTPAREN = SDLK_RIGHTPAREN;
-static const int KEY_SEMICOLON = SDLK_SEMICOLON;
-static const int KEY_SEPARATOR = SDLK_SEPARATOR;
-static const int KEY_SLASH = SDLK_SLASH;
-static const int KEY_SLEEP = SDLK_SLEEP;
-static const int KEY_STOP = SDLK_STOP;
-static const int KEY_SYSREQ = SDLK_SYSREQ;
-static const int KEY_THOUSANDSSEPARATOR = SDLK_THOUSANDSSEPARATOR;
-static const int KEY_UNDERSCORE = SDLK_UNDERSCORE;
-static const int KEY_UNDO = SDLK_UNDO;
-static const int KEY_VOLUMEDOWN = SDLK_VOLUMEDOWN;
-static const int KEY_VOLUMEUP = SDLK_VOLUMEUP;
-static const int KEY_WWW = SDLK_WWW;
-
-static const int SCANCODE_UNKNOWN = SDL_SCANCODE_UNKNOWN;
-static const int SCANCODE_CTRL = SDL_SCANCODE_LCTRL;
-static const int SCANCODE_SHIFT = SDL_SCANCODE_LSHIFT;
-static const int SCANCODE_ALT = SDL_SCANCODE_LALT;
-static const int SCANCODE_GUI = SDL_SCANCODE_LGUI;
-static const int SCANCODE_A = SDL_SCANCODE_A;
-static const int SCANCODE_B = SDL_SCANCODE_B;
-static const int SCANCODE_C = SDL_SCANCODE_C;
-static const int SCANCODE_D = SDL_SCANCODE_D;
-static const int SCANCODE_E = SDL_SCANCODE_E;
-static const int SCANCODE_F = SDL_SCANCODE_F;
-static const int SCANCODE_G = SDL_SCANCODE_G;
-static const int SCANCODE_H = SDL_SCANCODE_H;
-static const int SCANCODE_I = SDL_SCANCODE_I;
-static const int SCANCODE_J = SDL_SCANCODE_J;
-static const int SCANCODE_K = SDL_SCANCODE_K;
-static const int SCANCODE_L = SDL_SCANCODE_L;
-static const int SCANCODE_M = SDL_SCANCODE_M;
-static const int SCANCODE_N = SDL_SCANCODE_N;
-static const int SCANCODE_O = SDL_SCANCODE_O;
-static const int SCANCODE_P = SDL_SCANCODE_P;
-static const int SCANCODE_Q = SDL_SCANCODE_Q;
-static const int SCANCODE_R = SDL_SCANCODE_R;
-static const int SCANCODE_S = SDL_SCANCODE_S;
-static const int SCANCODE_T = SDL_SCANCODE_T;
-static const int SCANCODE_U = SDL_SCANCODE_U;
-static const int SCANCODE_V = SDL_SCANCODE_V;
-static const int SCANCODE_W = SDL_SCANCODE_W;
-static const int SCANCODE_X = SDL_SCANCODE_X;
-static const int SCANCODE_Y = SDL_SCANCODE_Y;
-static const int SCANCODE_Z = SDL_SCANCODE_Z;
-static const int SCANCODE_1 = SDL_SCANCODE_1;
-static const int SCANCODE_2 = SDL_SCANCODE_2;
-static const int SCANCODE_3 = SDL_SCANCODE_3;
-static const int SCANCODE_4 = SDL_SCANCODE_4;
-static const int SCANCODE_5 = SDL_SCANCODE_5;
-static const int SCANCODE_6 = SDL_SCANCODE_6;
-static const int SCANCODE_7 = SDL_SCANCODE_7;
-static const int SCANCODE_8 = SDL_SCANCODE_8;
-static const int SCANCODE_9 = SDL_SCANCODE_9;
-static const int SCANCODE_0 = SDL_SCANCODE_0;
-static const int SCANCODE_RETURN = SDL_SCANCODE_RETURN;
-static const int SCANCODE_ESCAPE = SDL_SCANCODE_ESCAPE;
-static const int SCANCODE_BACKSPACE = SDL_SCANCODE_BACKSPACE;
-static const int SCANCODE_TAB = SDL_SCANCODE_TAB;
-static const int SCANCODE_SPACE = SDL_SCANCODE_SPACE;
-static const int SCANCODE_MINUS = SDL_SCANCODE_MINUS;
-static const int SCANCODE_EQUALS = SDL_SCANCODE_EQUALS;
-static const int SCANCODE_LEFTBRACKET = SDL_SCANCODE_LEFTBRACKET;
-static const int SCANCODE_RIGHTBRACKET = SDL_SCANCODE_RIGHTBRACKET;
-static const int SCANCODE_BACKSLASH = SDL_SCANCODE_BACKSLASH;
-static const int SCANCODE_NONUSHASH = SDL_SCANCODE_NONUSHASH;
-static const int SCANCODE_SEMICOLON = SDL_SCANCODE_SEMICOLON;
-static const int SCANCODE_APOSTROPHE = SDL_SCANCODE_APOSTROPHE;
-static const int SCANCODE_GRAVE = SDL_SCANCODE_GRAVE;
-static const int SCANCODE_COMMA = SDL_SCANCODE_COMMA;
-static const int SCANCODE_PERIOD = SDL_SCANCODE_PERIOD;
-static const int SCANCODE_SLASH = SDL_SCANCODE_SLASH;
-static const int SCANCODE_CAPSLOCK = SDL_SCANCODE_CAPSLOCK;
-static const int SCANCODE_F1 = SDL_SCANCODE_F1;
-static const int SCANCODE_F2 = SDL_SCANCODE_F2;
-static const int SCANCODE_F3 = SDL_SCANCODE_F3;
-static const int SCANCODE_F4 = SDL_SCANCODE_F4;
-static const int SCANCODE_F5 = SDL_SCANCODE_F5;
-static const int SCANCODE_F6 = SDL_SCANCODE_F6;
-static const int SCANCODE_F7 = SDL_SCANCODE_F7;
-static const int SCANCODE_F8 = SDL_SCANCODE_F8;
-static const int SCANCODE_F9 = SDL_SCANCODE_F9;
-static const int SCANCODE_F10 = SDL_SCANCODE_F10;
-static const int SCANCODE_F11 = SDL_SCANCODE_F11;
-static const int SCANCODE_F12 = SDL_SCANCODE_F12;
-static const int SCANCODE_PRINTSCREEN = SDL_SCANCODE_PRINTSCREEN;
-static const int SCANCODE_SCROLLLOCK = SDL_SCANCODE_SCROLLLOCK;
-static const int SCANCODE_PAUSE = SDL_SCANCODE_PAUSE;
-static const int SCANCODE_INSERT = SDL_SCANCODE_INSERT;
-static const int SCANCODE_HOME = SDL_SCANCODE_HOME;
-static const int SCANCODE_PAGEUP = SDL_SCANCODE_PAGEUP;
-static const int SCANCODE_DELETE = SDL_SCANCODE_DELETE;
-static const int SCANCODE_END = SDL_SCANCODE_END;
-static const int SCANCODE_PAGEDOWN = SDL_SCANCODE_PAGEDOWN;
-static const int SCANCODE_RIGHT = SDL_SCANCODE_RIGHT;
-static const int SCANCODE_LEFT = SDL_SCANCODE_LEFT;
-static const int SCANCODE_DOWN = SDL_SCANCODE_DOWN;
-static const int SCANCODE_UP = SDL_SCANCODE_UP;
-static const int SCANCODE_NUMLOCKCLEAR = SDL_SCANCODE_NUMLOCKCLEAR;
-static const int SCANCODE_KP_DIVIDE = SDL_SCANCODE_KP_DIVIDE;
-static const int SCANCODE_KP_MULTIPLY = SDL_SCANCODE_KP_MULTIPLY;
-static const int SCANCODE_KP_MINUS = SDL_SCANCODE_KP_MINUS;
-static const int SCANCODE_KP_PLUS = SDL_SCANCODE_KP_PLUS;
-static const int SCANCODE_KP_ENTER = SDL_SCANCODE_KP_ENTER;
-static const int SCANCODE_KP_1 = SDL_SCANCODE_KP_1;
-static const int SCANCODE_KP_2 = SDL_SCANCODE_KP_2;
-static const int SCANCODE_KP_3 = SDL_SCANCODE_KP_3;
-static const int SCANCODE_KP_4 = SDL_SCANCODE_KP_4;
-static const int SCANCODE_KP_5 = SDL_SCANCODE_KP_5;
-static const int SCANCODE_KP_6 = SDL_SCANCODE_KP_6;
-static const int SCANCODE_KP_7 = SDL_SCANCODE_KP_7;
-static const int SCANCODE_KP_8 = SDL_SCANCODE_KP_8;
-static const int SCANCODE_KP_9 = SDL_SCANCODE_KP_9;
-static const int SCANCODE_KP_0 = SDL_SCANCODE_KP_0;
-static const int SCANCODE_KP_PERIOD = SDL_SCANCODE_KP_PERIOD;
-static const int SCANCODE_NONUSBACKSLASH = SDL_SCANCODE_NONUSBACKSLASH;
-static const int SCANCODE_APPLICATION = SDL_SCANCODE_APPLICATION;
-static const int SCANCODE_POWER = SDL_SCANCODE_POWER;
-static const int SCANCODE_KP_EQUALS = SDL_SCANCODE_KP_EQUALS;
-static const int SCANCODE_F13 = SDL_SCANCODE_F13;
-static const int SCANCODE_F14 = SDL_SCANCODE_F14;
-static const int SCANCODE_F15 = SDL_SCANCODE_F15;
-static const int SCANCODE_F16 = SDL_SCANCODE_F16;
-static const int SCANCODE_F17 = SDL_SCANCODE_F17;
-static const int SCANCODE_F18 = SDL_SCANCODE_F18;
-static const int SCANCODE_F19 = SDL_SCANCODE_F19;
-static const int SCANCODE_F20 = SDL_SCANCODE_F20;
-static const int SCANCODE_F21 = SDL_SCANCODE_F21;
-static const int SCANCODE_F22 = SDL_SCANCODE_F22;
-static const int SCANCODE_F23 = SDL_SCANCODE_F23;
-static const int SCANCODE_F24 = SDL_SCANCODE_F24;
-static const int SCANCODE_EXECUTE = SDL_SCANCODE_EXECUTE;
-static const int SCANCODE_HELP = SDL_SCANCODE_HELP;
-static const int SCANCODE_MENU = SDL_SCANCODE_MENU;
-static const int SCANCODE_SELECT = SDL_SCANCODE_SELECT;
-static const int SCANCODE_STOP = SDL_SCANCODE_STOP;
-static const int SCANCODE_AGAIN = SDL_SCANCODE_AGAIN;
-static const int SCANCODE_UNDO = SDL_SCANCODE_UNDO;
-static const int SCANCODE_CUT = SDL_SCANCODE_CUT;
-static const int SCANCODE_COPY = SDL_SCANCODE_COPY;
-static const int SCANCODE_PASTE = SDL_SCANCODE_PASTE;
-static const int SCANCODE_FIND = SDL_SCANCODE_FIND;
-static const int SCANCODE_MUTE = SDL_SCANCODE_MUTE;
-static const int SCANCODE_VOLUMEUP = SDL_SCANCODE_VOLUMEUP;
-static const int SCANCODE_VOLUMEDOWN = SDL_SCANCODE_VOLUMEDOWN;
-static const int SCANCODE_KP_COMMA = SDL_SCANCODE_KP_COMMA;
-static const int SCANCODE_KP_EQUALSAS400 = SDL_SCANCODE_KP_EQUALSAS400;
-static const int SCANCODE_INTERNATIONAL1 = SDL_SCANCODE_INTERNATIONAL1;
-static const int SCANCODE_INTERNATIONAL2 = SDL_SCANCODE_INTERNATIONAL2;
-static const int SCANCODE_INTERNATIONAL3 = SDL_SCANCODE_INTERNATIONAL3;
-static const int SCANCODE_INTERNATIONAL4 = SDL_SCANCODE_INTERNATIONAL4;
-static const int SCANCODE_INTERNATIONAL5 = SDL_SCANCODE_INTERNATIONAL5;
-static const int SCANCODE_INTERNATIONAL6 = SDL_SCANCODE_INTERNATIONAL6;
-static const int SCANCODE_INTERNATIONAL7 = SDL_SCANCODE_INTERNATIONAL7;
-static const int SCANCODE_INTERNATIONAL8 = SDL_SCANCODE_INTERNATIONAL8;
-static const int SCANCODE_INTERNATIONAL9 = SDL_SCANCODE_INTERNATIONAL9;
-static const int SCANCODE_LANG1 = SDL_SCANCODE_LANG1;
-static const int SCANCODE_LANG2 = SDL_SCANCODE_LANG2;
-static const int SCANCODE_LANG3 = SDL_SCANCODE_LANG3;
-static const int SCANCODE_LANG4 = SDL_SCANCODE_LANG4;
-static const int SCANCODE_LANG5 = SDL_SCANCODE_LANG5;
-static const int SCANCODE_LANG6 = SDL_SCANCODE_LANG6;
-static const int SCANCODE_LANG7 = SDL_SCANCODE_LANG7;
-static const int SCANCODE_LANG8 = SDL_SCANCODE_LANG8;
-static const int SCANCODE_LANG9 = SDL_SCANCODE_LANG9;
-static const int SCANCODE_ALTERASE = SDL_SCANCODE_ALTERASE;
-static const int SCANCODE_SYSREQ = SDL_SCANCODE_SYSREQ;
-static const int SCANCODE_CANCEL = SDL_SCANCODE_CANCEL;
-static const int SCANCODE_CLEAR = SDL_SCANCODE_CLEAR;
-static const int SCANCODE_PRIOR = SDL_SCANCODE_PRIOR;
-static const int SCANCODE_RETURN2 = SDL_SCANCODE_RETURN2;
-static const int SCANCODE_SEPARATOR = SDL_SCANCODE_SEPARATOR;
-static const int SCANCODE_OUT = SDL_SCANCODE_OUT;
-static const int SCANCODE_OPER = SDL_SCANCODE_OPER;
-static const int SCANCODE_CLEARAGAIN = SDL_SCANCODE_CLEARAGAIN;
-static const int SCANCODE_CRSEL = SDL_SCANCODE_CRSEL;
-static const int SCANCODE_EXSEL = SDL_SCANCODE_EXSEL;
-static const int SCANCODE_KP_00 = SDL_SCANCODE_KP_00;
-static const int SCANCODE_KP_000 = SDL_SCANCODE_KP_000;
-static const int SCANCODE_THOUSANDSSEPARATOR = SDL_SCANCODE_THOUSANDSSEPARATOR;
-static const int SCANCODE_DECIMALSEPARATOR = SDL_SCANCODE_DECIMALSEPARATOR;
-static const int SCANCODE_CURRENCYUNIT = SDL_SCANCODE_CURRENCYUNIT;
-static const int SCANCODE_CURRENCYSUBUNIT = SDL_SCANCODE_CURRENCYSUBUNIT;
-static const int SCANCODE_KP_LEFTPAREN = SDL_SCANCODE_KP_LEFTPAREN;
-static const int SCANCODE_KP_RIGHTPAREN = SDL_SCANCODE_KP_RIGHTPAREN;
-static const int SCANCODE_KP_LEFTBRACE = SDL_SCANCODE_KP_LEFTBRACE;
-static const int SCANCODE_KP_RIGHTBRACE = SDL_SCANCODE_KP_RIGHTBRACE;
-static const int SCANCODE_KP_TAB = SDL_SCANCODE_KP_TAB;
-static const int SCANCODE_KP_BACKSPACE = SDL_SCANCODE_KP_BACKSPACE;
-static const int SCANCODE_KP_A = SDL_SCANCODE_KP_A;
-static const int SCANCODE_KP_B = SDL_SCANCODE_KP_B;
-static const int SCANCODE_KP_C = SDL_SCANCODE_KP_C;
-static const int SCANCODE_KP_D = SDL_SCANCODE_KP_D;
-static const int SCANCODE_KP_E = SDL_SCANCODE_KP_E;
-static const int SCANCODE_KP_F = SDL_SCANCODE_KP_F;
-static const int SCANCODE_KP_XOR = SDL_SCANCODE_KP_XOR;
-static const int SCANCODE_KP_POWER = SDL_SCANCODE_KP_POWER;
-static const int SCANCODE_KP_PERCENT = SDL_SCANCODE_KP_PERCENT;
-static const int SCANCODE_KP_LESS = SDL_SCANCODE_KP_LESS;
-static const int SCANCODE_KP_GREATER = SDL_SCANCODE_KP_GREATER;
-static const int SCANCODE_KP_AMPERSAND = SDL_SCANCODE_KP_AMPERSAND;
-static const int SCANCODE_KP_DBLAMPERSAND = SDL_SCANCODE_KP_DBLAMPERSAND;
-static const int SCANCODE_KP_VERTICALBAR = SDL_SCANCODE_KP_VERTICALBAR;
-static const int SCANCODE_KP_DBLVERTICALBAR = SDL_SCANCODE_KP_DBLVERTICALBAR;
-static const int SCANCODE_KP_COLON = SDL_SCANCODE_KP_COLON;
-static const int SCANCODE_KP_HASH = SDL_SCANCODE_KP_HASH;
-static const int SCANCODE_KP_SPACE = SDL_SCANCODE_KP_SPACE;
-static const int SCANCODE_KP_AT = SDL_SCANCODE_KP_AT;
-static const int SCANCODE_KP_EXCLAM = SDL_SCANCODE_KP_EXCLAM;
-static const int SCANCODE_KP_MEMSTORE = SDL_SCANCODE_KP_MEMSTORE;
-static const int SCANCODE_KP_MEMRECALL = SDL_SCANCODE_KP_MEMRECALL;
-static const int SCANCODE_KP_MEMCLEAR = SDL_SCANCODE_KP_MEMCLEAR;
-static const int SCANCODE_KP_MEMADD = SDL_SCANCODE_KP_MEMADD;
-static const int SCANCODE_KP_MEMSUBTRACT = SDL_SCANCODE_KP_MEMSUBTRACT;
-static const int SCANCODE_KP_MEMMULTIPLY = SDL_SCANCODE_KP_MEMMULTIPLY;
-static const int SCANCODE_KP_MEMDIVIDE = SDL_SCANCODE_KP_MEMDIVIDE;
-static const int SCANCODE_KP_PLUSMINUS = SDL_SCANCODE_KP_PLUSMINUS;
-static const int SCANCODE_KP_CLEAR = SDL_SCANCODE_KP_CLEAR;
-static const int SCANCODE_KP_CLEARENTRY = SDL_SCANCODE_KP_CLEARENTRY;
-static const int SCANCODE_KP_BINARY = SDL_SCANCODE_KP_BINARY;
-static const int SCANCODE_KP_OCTAL = SDL_SCANCODE_KP_OCTAL;
-static const int SCANCODE_KP_DECIMAL = SDL_SCANCODE_KP_DECIMAL;
-static const int SCANCODE_KP_HEXADECIMAL = SDL_SCANCODE_KP_HEXADECIMAL;
-static const int SCANCODE_LCTRL = SDL_SCANCODE_LCTRL;
-static const int SCANCODE_LSHIFT = SDL_SCANCODE_LSHIFT;
-static const int SCANCODE_LALT = SDL_SCANCODE_LALT;
-static const int SCANCODE_LGUI = SDL_SCANCODE_LGUI;
-static const int SCANCODE_RCTRL = SDL_SCANCODE_RCTRL;
-static const int SCANCODE_RSHIFT = SDL_SCANCODE_RSHIFT;
-static const int SCANCODE_RALT = SDL_SCANCODE_RALT;
-static const int SCANCODE_RGUI = SDL_SCANCODE_RGUI;
-static const int SCANCODE_MODE = SDL_SCANCODE_MODE;
-static const int SCANCODE_AUDIONEXT = SDL_SCANCODE_AUDIONEXT;
-static const int SCANCODE_AUDIOPREV = SDL_SCANCODE_AUDIOPREV;
-static const int SCANCODE_AUDIOSTOP = SDL_SCANCODE_AUDIOSTOP;
-static const int SCANCODE_AUDIOPLAY = SDL_SCANCODE_AUDIOPLAY;
-static const int SCANCODE_AUDIOMUTE = SDL_SCANCODE_AUDIOMUTE;
-static const int SCANCODE_MEDIASELECT = SDL_SCANCODE_MEDIASELECT;
-static const int SCANCODE_WWW = SDL_SCANCODE_WWW;
-static const int SCANCODE_MAIL = SDL_SCANCODE_MAIL;
-static const int SCANCODE_CALCULATOR = SDL_SCANCODE_CALCULATOR;
-static const int SCANCODE_COMPUTER = SDL_SCANCODE_COMPUTER;
-static const int SCANCODE_AC_SEARCH = SDL_SCANCODE_AC_SEARCH;
-static const int SCANCODE_AC_HOME = SDL_SCANCODE_AC_HOME;
-static const int SCANCODE_AC_BACK = SDL_SCANCODE_AC_BACK;
-static const int SCANCODE_AC_FORWARD = SDL_SCANCODE_AC_FORWARD;
-static const int SCANCODE_AC_STOP = SDL_SCANCODE_AC_STOP;
-static const int SCANCODE_AC_REFRESH = SDL_SCANCODE_AC_REFRESH;
-static const int SCANCODE_AC_BOOKMARKS = SDL_SCANCODE_AC_BOOKMARKS;
-static const int SCANCODE_BRIGHTNESSDOWN = SDL_SCANCODE_BRIGHTNESSDOWN;
-static const int SCANCODE_BRIGHTNESSUP = SDL_SCANCODE_BRIGHTNESSUP;
-static const int SCANCODE_DISPLAYSWITCH = SDL_SCANCODE_DISPLAYSWITCH;
-static const int SCANCODE_KBDILLUMTOGGLE = SDL_SCANCODE_KBDILLUMTOGGLE;
-static const int SCANCODE_KBDILLUMDOWN = SDL_SCANCODE_KBDILLUMDOWN;
-static const int SCANCODE_KBDILLUMUP = SDL_SCANCODE_KBDILLUMUP;
-static const int SCANCODE_EJECT = SDL_SCANCODE_EJECT;
-static const int SCANCODE_SLEEP = SDL_SCANCODE_SLEEP;
-static const int SCANCODE_APP1 = SDL_SCANCODE_APP1;
-static const int SCANCODE_APP2 = SDL_SCANCODE_APP2;
-
-static const int HAT_CENTER = SDL_HAT_CENTERED;
-static const int HAT_UP = SDL_HAT_UP;
-static const int HAT_RIGHT = SDL_HAT_RIGHT;
-static const int HAT_DOWN = SDL_HAT_DOWN;
-static const int HAT_LEFT = SDL_HAT_LEFT;
-
-static const int CONTROLLER_BUTTON_A = SDL_CONTROLLER_BUTTON_A;
-static const int CONTROLLER_BUTTON_B = SDL_CONTROLLER_BUTTON_B;
-static const int CONTROLLER_BUTTON_X = SDL_CONTROLLER_BUTTON_X;
-static const int CONTROLLER_BUTTON_Y = SDL_CONTROLLER_BUTTON_Y;
-static const int CONTROLLER_BUTTON_BACK = SDL_CONTROLLER_BUTTON_BACK;
-static const int CONTROLLER_BUTTON_GUIDE = SDL_CONTROLLER_BUTTON_GUIDE;
-static const int CONTROLLER_BUTTON_START = SDL_CONTROLLER_BUTTON_START;
-static const int CONTROLLER_BUTTON_LEFTSTICK = SDL_CONTROLLER_BUTTON_LEFTSTICK;
-static const int CONTROLLER_BUTTON_RIGHTSTICK = SDL_CONTROLLER_BUTTON_RIGHTSTICK;
-static const int CONTROLLER_BUTTON_LEFTSHOULDER = SDL_CONTROLLER_BUTTON_LEFTSHOULDER;
-static const int CONTROLLER_BUTTON_RIGHTSHOULDER = SDL_CONTROLLER_BUTTON_RIGHTSHOULDER;
-static const int CONTROLLER_BUTTON_DPAD_UP = SDL_CONTROLLER_BUTTON_DPAD_UP;
-static const int CONTROLLER_BUTTON_DPAD_DOWN = SDL_CONTROLLER_BUTTON_DPAD_DOWN;
-static const int CONTROLLER_BUTTON_DPAD_LEFT = SDL_CONTROLLER_BUTTON_DPAD_LEFT;
-static const int CONTROLLER_BUTTON_DPAD_RIGHT = SDL_CONTROLLER_BUTTON_DPAD_RIGHT;
-
-static const int CONTROLLER_AXIS_LEFTX = SDL_CONTROLLER_AXIS_LEFTX;
-static const int CONTROLLER_AXIS_LEFTY = SDL_CONTROLLER_AXIS_LEFTY;
-static const int CONTROLLER_AXIS_RIGHTX = SDL_CONTROLLER_AXIS_RIGHTX;
-static const int CONTROLLER_AXIS_RIGHTY = SDL_CONTROLLER_AXIS_RIGHTY;
-static const int CONTROLLER_AXIS_TRIGGERLEFT = SDL_CONTROLLER_AXIS_TRIGGERLEFT;
-static const int CONTROLLER_AXIS_TRIGGERRIGHT = SDL_CONTROLLER_AXIS_TRIGGERRIGHT;
-
 }

+ 2 - 2
Source/Urho3D/Scene/LogicComponent.cpp

@@ -64,7 +64,7 @@ void LogicComponent::FixedPostUpdate(float timeStep)
 {
 }
 
-void LogicComponent::SetUpdateEventMask(unsigned char mask)
+void LogicComponent::SetUpdateEventMask(FlagSet<UseEvent> mask)
 {
     if (updateEventMask_ != mask)
     {
@@ -99,7 +99,7 @@ void LogicComponent::OnSceneSet(Scene* scene)
         UnsubscribeFromEvent(E_PHYSICSPRESTEP);
         UnsubscribeFromEvent(E_PHYSICSPOSTSTEP);
 #endif
-        currentEventMask_ = 0;
+        currentEventMask_ = USE_NONE;
     }
 }
 

+ 19 - 12
Source/Urho3D/Scene/LogicComponent.h

@@ -22,19 +22,26 @@
 
 #pragma once
 
+#include "../Container/FlagSet.h"
 #include "../Scene/Component.h"
 
 namespace Urho3D
 {
 
-/// Bitmask for using the scene update event.
-static const unsigned char USE_UPDATE = 0x1;
-/// Bitmask for using the scene post-update event.
-static const unsigned char USE_POSTUPDATE = 0x2;
-/// Bitmask for using the physics update event.
-static const unsigned char USE_FIXEDUPDATE = 0x4;
-/// Bitmask for using the physics post-update event.
-static const unsigned char USE_FIXEDPOSTUPDATE = 0x8;
+enum UseEvent : unsigned
+{
+    /// Bitmask for not using any events.
+    USE_NONE = 0x0,
+    /// Bitmask for using the scene update event.
+    USE_UPDATE = 0x1,
+    /// Bitmask for using the scene post-update event.
+    USE_POSTUPDATE = 0x2,
+    /// Bitmask for using the physics update event.
+    USE_FIXEDUPDATE = 0x4,
+    /// Bitmask for using the physics post-update event.
+    USE_FIXEDPOSTUPDATE = 0x8,
+};
+template<> struct is_flagset<UseEvent> { constexpr static bool value = true; };
 
 /// Helper base class for user-defined game logic components that hooks up to update events and forwards them to virtual functions similar to ScriptInstance class.
 class URHO3D_API LogicComponent : public Component
@@ -68,10 +75,10 @@ class URHO3D_API LogicComponent : public Component
     virtual void FixedPostUpdate(float timeStep);
 
     /// Set what update events should be subscribed to. Use this for optimization: by default all are in use. Note that this is not an attribute and is not saved or network-serialized, therefore it should always be called eg. in the subclass constructor.
-    void SetUpdateEventMask(unsigned char mask);
+    void SetUpdateEventMask(FlagSet<UseEvent> mask);
 
     /// Return what update events are subscribed to.
-    unsigned char GetUpdateEventMask() const { return updateEventMask_; }
+    FlagSet<UseEvent> GetUpdateEventMask() const { return updateEventMask_; }
 
     /// Return whether the DelayedStart() function has been called.
     bool IsDelayedStartCalled() const { return delayedStartCalled_; }
@@ -96,9 +103,9 @@ private:
     void HandlePhysicsPostStep(StringHash eventType, VariantMap& eventData);
 #endif
     /// Requested event subscription mask.
-    unsigned char updateEventMask_;
+    FlagSet<UseEvent> updateEventMask_;
     /// Current event subscription mask.
-    unsigned char currentEventMask_;
+    FlagSet<UseEvent> currentEventMask_;
     /// Flag for delayed start.
     bool delayedStartCalled_;
 };

+ 12 - 8
Source/Urho3D/Scene/SmoothedTransform.h

@@ -27,12 +27,16 @@
 namespace Urho3D
 {
 
-/// No ongoing smoothing.
-static const unsigned SMOOTH_NONE = 0;
-/// Ongoing position smoothing.
-static const unsigned SMOOTH_POSITION = 1;
-/// Ongoing rotation smoothing.
-static const unsigned SMOOTH_ROTATION = 2;
+enum SmoothingType : unsigned
+{
+    /// No ongoing smoothing.
+    SMOOTH_NONE = 0,
+    /// Ongoing position smoothing.
+    SMOOTH_POSITION = 1,
+    /// Ongoing rotation smoothing.
+    SMOOTH_ROTATION = 2,
+};
+template<> struct is_flagset<SmoothingType> { constexpr static bool value = true; };
 
 /// Transform smoothing component for network updates.
 class URHO3D_API SmoothedTransform : public Component
@@ -70,7 +74,7 @@ public:
     Quaternion GetTargetWorldRotation() const;
 
     /// Return whether smoothing is in progress.
-    bool IsInProgress() const { return smoothingMask_ != 0; }
+    bool IsInProgress() const { return smoothingMask_ != SMOOTH_NONE; }
 
 protected:
     /// Handle scene node being assigned at creation.
@@ -85,7 +89,7 @@ private:
     /// Target rotation.
     Quaternion targetRotation_;
     /// Active smoothing operations bitmask.
-    unsigned char smoothingMask_;
+    FlagSet<SmoothingType> smoothingMask_;
     /// Subscribed to smoothing update event flag.
     bool subscribed_;
 };

+ 1 - 1
Source/Urho3D/UI/Button.cpp

@@ -146,7 +146,7 @@ void Button::OnDragMove(const IntVector2& position, const IntVector2& screenPosi
     SetPressed(true);
 }
 
-void Button::OnKey(int key, int buttons, int qualifiers)
+void Button::OnKey(Key key, FlagSet<MouseButton> buttons, FlagSet<Qualifier> qualifiers)
 {
     if (HasFocus() && (key == KEY_RETURN || key == KEY_RETURN2 || key == KEY_KP_ENTER || key == KEY_SPACE))
     {

+ 1 - 1
Source/Urho3D/UI/Button.h

@@ -56,7 +56,7 @@ public:
         (const IntVector2& position, const IntVector2& screenPosition, const IntVector2& deltaPos, int buttons, int qualifiers,
             Cursor* cursor) override;
     /// React to a key press.
-    void OnKey(int key, int buttons, int qualifiers) override;
+    void OnKey(Key key, FlagSet<MouseButton> buttons, FlagSet<Qualifier> qualifiers) override;
 
     /// Set offset to image rectangle used when pressed.
     void SetPressedOffset(const IntVector2& offset);

+ 1 - 1
Source/Urho3D/UI/CheckBox.cpp

@@ -74,7 +74,7 @@ void CheckBox::OnClickBegin(const IntVector2& position, const IntVector2& screen
         SetChecked(!checked_);
 }
 
-void CheckBox::OnKey(int key, int buttons, int qualifiers)
+void CheckBox::OnKey(Key key, FlagSet<MouseButton> buttons, FlagSet<Qualifier> qualifiers)
 {
     if (HasFocus() && key == KEY_SPACE)
     {

+ 1 - 1
Source/Urho3D/UI/CheckBox.h

@@ -46,7 +46,7 @@ public:
     void OnClickBegin
         (const IntVector2& position, const IntVector2& screenPosition, int button, int buttons, int qualifiers, Cursor* cursor) override;
     /// React to a key press.
-    void OnKey(int key, int buttons, int qualifiers) override;
+    void OnKey(Key key, FlagSet<MouseButton> buttons, FlagSet<Qualifier> qualifiers) override;
 
     /// Set checked state.
     void SetChecked(bool enable);

+ 3 - 3
Source/Urho3D/UI/LineEdit.cpp

@@ -204,7 +204,7 @@ bool LineEdit::OnDragDropFinish(UIElement* source)
     return false;
 }
 
-void LineEdit::OnKey(int key, int buttons, int qualifiers)
+void LineEdit::OnKey(Key key, FlagSet<MouseButton> buttons, FlagSet<Qualifier> qualifiers)
 {
     bool changed = false;
     bool cursorMoved = false;
@@ -363,8 +363,8 @@ void LineEdit::OnKey(int key, int buttons, int qualifiers)
             VariantMap& eventData = GetEventDataMap();
             eventData[P_ELEMENT] = this;
             eventData[P_KEY] = key;
-            eventData[P_BUTTONS] = buttons;
-            eventData[P_QUALIFIERS] = qualifiers;
+            eventData[P_BUTTONS] = (unsigned)buttons;
+            eventData[P_QUALIFIERS] = (unsigned)qualifiers;
             SendEvent(E_UNHANDLEDKEY, eventData);
         }
         return;

+ 1 - 1
Source/Urho3D/UI/LineEdit.h

@@ -65,7 +65,7 @@ public:
     /// React to drag and drop finish. Return true to signal that the drop was accepted.
     bool OnDragDropFinish(UIElement* source) override;
     /// React to a key press.
-    void OnKey(int key, int buttons, int qualifiers) override;
+    void OnKey(Key key, FlagSet<MouseButton> buttons, FlagSet<Qualifier> qualifiers) override;
     /// React to text input event.
     void OnTextInput(const String& text) override;
 

+ 3 - 3
Source/Urho3D/UI/ListView.cpp

@@ -203,7 +203,7 @@ void ListView::RegisterObject(Context* context)
     URHO3D_ACCESSOR_ATTRIBUTE("Select On Click End", GetSelectOnClickEnd, SetSelectOnClickEnd, bool, false, AM_FILE);
 }
 
-void ListView::OnKey(int key, int buttons, int qualifiers)
+void ListView::OnKey(Key key, FlagSet<MouseButton> buttons, FlagSet<Qualifier> qualifiers)
 {
     // If no selection, can not move with keys
     unsigned numItems = GetNumItems();
@@ -307,8 +307,8 @@ void ListView::OnKey(int key, int buttons, int qualifiers)
     VariantMap& eventData = GetEventDataMap();
     eventData[P_ELEMENT] = this;
     eventData[P_KEY] = key;
-    eventData[P_BUTTONS] = buttons;
-    eventData[P_QUALIFIERS] = qualifiers;
+    eventData[P_BUTTONS] = (unsigned)buttons;
+    eventData[P_QUALIFIERS] = (unsigned)qualifiers;
     SendEvent(E_UNHANDLEDKEY, eventData);
 }
 

+ 3 - 1
Source/Urho3D/UI/ListView.h

@@ -22,6 +22,8 @@
 
 #pragma once
 
+
+#include "../Input/InputConstants.h"
 #include "../UI/ScrollView.h"
 
 namespace Urho3D
@@ -52,7 +54,7 @@ public:
     static void RegisterObject(Context* context);
 
     /// React to a key press.
-    void OnKey(int key, int buttons, int qualifiers) override;
+    void OnKey(Key key, FlagSet<MouseButton> buttons, FlagSet<Qualifier> qualifiers) override;
     /// React to resize.
     void OnResize(const IntVector2& newSize, const IntVector2& delta) override;
 

+ 2 - 2
Source/Urho3D/UI/ScrollView.cpp

@@ -186,7 +186,7 @@ void ScrollView::ApplyAttributes()
     SetViewPosition(viewPositionAttr_);
 }
 
-void ScrollView::OnWheel(int delta, int buttons, int qualifiers)
+void ScrollView::OnWheel(int delta, FlagSet<MouseButton> buttons, FlagSet<Qualifier> qualifiers)
 {
     if (delta > 0)
         verticalScrollBar_->StepBack();
@@ -194,7 +194,7 @@ void ScrollView::OnWheel(int delta, int buttons, int qualifiers)
         verticalScrollBar_->StepForward();
 }
 
-void ScrollView::OnKey(int key, int buttons, int qualifiers)
+void ScrollView::OnKey(Key key, FlagSet<MouseButton> buttons, FlagSet<Qualifier> qualifiers)
 {
     switch (key)
     {

+ 2 - 2
Source/Urho3D/UI/ScrollView.h

@@ -48,9 +48,9 @@ public:
     /// Apply attribute changes that can not be applied immediately.
     void ApplyAttributes() override;
     /// React to mouse wheel.
-    void OnWheel(int delta, int buttons, int qualifiers) override;
+    void OnWheel(int delta, FlagSet<MouseButton> buttons, FlagSet<Qualifier> qualifiers) override;
     /// React to a key press.
-    void OnKey(int key, int buttons, int qualifiers) override;
+    void OnKey(Key key, FlagSet<MouseButton> buttons, FlagSet<Qualifier> qualifiers) override;
     /// React to resize.
     void OnResize(const IntVector2& newSize, const IntVector2& delta) override;
 

+ 46 - 46
Source/Urho3D/UI/UI.cpp

@@ -67,7 +67,7 @@
 
 #include "../DebugNew.h"
 
-#define TOUCHID_MASK(id) (1u << (unsigned)(id))
+#define TOUCHID_MASK(id) FlagSet<MouseButton>(1u << (unsigned)(id))
 
 namespace Urho3D
 {
@@ -377,7 +377,7 @@ void UI::Update(float timeStep)
         IntVector2 touchPos = touch->position_;
         touchPos.x_ = (int)(touchPos.x_ / uiScale_);
         touchPos.y_ = (int)(touchPos.y_ / uiScale_);
-        ProcessHover(touchPos, TOUCHID_MASK(touch->touchID_), 0, nullptr);
+        ProcessHover(touchPos, TOUCHID_MASK(touch->touchID_), QUAL_NONE, nullptr);
     }
 
     // End hovers that expired without refreshing
@@ -1268,7 +1268,7 @@ void UI::ReleaseFontFaces()
         fonts[i]->ReleaseFaces();
 }
 
-void UI::ProcessHover(const IntVector2& windowCursorPos, int buttons, int qualifiers, Cursor* cursor)
+void UI::ProcessHover(const IntVector2& windowCursorPos, FlagSet<MouseButton> buttons, FlagSet<Qualifier> qualifiers, Cursor* cursor)
 {
     IntVector2 cursorPos;
     WeakPtr<UIElement> element(GetElementAt(windowCursorPos, true, &cursorPos));
@@ -1284,8 +1284,8 @@ void UI::ProcessHover(const IntVector2& windowCursorPos, int buttons, int qualif
             continue;
         }
 
-        bool dragSource = dragElement && (dragElement->GetDragDropMode() & DD_SOURCE) != 0;
-        bool dragTarget = element && (element->GetDragDropMode() & DD_TARGET) != 0;
+        bool dragSource = dragElement && (dragElement->GetDragDropMode() & DD_SOURCE);
+        bool dragTarget = element && (element->GetDragDropMode() & DD_TARGET);
         bool dragDropTest = dragSource && dragTarget && element != dragElement;
         // If drag start event has not been posted yet, do not do drag handling here
         if (dragData->dragBeginPending)
@@ -1357,7 +1357,7 @@ void UI::ProcessHover(const IntVector2& windowCursorPos, int buttons, int qualif
     }
 }
 
-void UI::ProcessClickBegin(const IntVector2& windowCursorPos, int button, int buttons, int qualifiers, Cursor* cursor, bool cursorVisible)
+void UI::ProcessClickBegin(const IntVector2& windowCursorPos, MouseButton button, FlagSet<MouseButton> buttons, FlagSet<Qualifier> qualifiers, Cursor* cursor, bool cursorVisible)
 {
     if (cursorVisible)
     {
@@ -1366,7 +1366,7 @@ void UI::ProcessClickBegin(const IntVector2& windowCursorPos, int button, int bu
 
         bool newButton;
         if (usingTouchInput_)
-            newButton = (button & buttons) == 0;
+            newButton = (buttons & button) == MOUSEB_NONE;
         else
             newButton = true;
         buttons |= button;
@@ -1439,7 +1439,7 @@ void UI::ProcessClickBegin(const IntVector2& windowCursorPos, int button, int bu
     }
 }
 
-void UI::ProcessClickEnd(const IntVector2& windowCursorPos, int button, int buttons, int qualifiers, Cursor* cursor, bool cursorVisible)
+void UI::ProcessClickEnd(const IntVector2& windowCursorPos, MouseButton button, FlagSet<MouseButton> buttons, FlagSet<Qualifier> qualifiers, Cursor* cursor, bool cursorVisible)
 {
     WeakPtr<UIElement> element;
     IntVector2 cursorPos = windowCursorPos;
@@ -1473,10 +1473,10 @@ void UI::ProcessClickEnd(const IntVector2& windowCursorPos, int button, int butt
                     cursor);
                 SendDragOrHoverEvent(E_DRAGEND, dragElement, cursorPos, IntVector2::ZERO, dragData);
 
-                bool dragSource = dragElement && (dragElement->GetDragDropMode() & DD_SOURCE) != 0;
+                bool dragSource = dragElement && (dragElement->GetDragDropMode() & DD_SOURCE);
                 if (dragSource)
                 {
-                    bool dragTarget = element && (element->GetDragDropMode() & DD_TARGET) != 0;
+                    bool dragTarget = element && (element->GetDragDropMode() & DD_TARGET);
                     bool dragDropFinish = dragSource && dragTarget && element != dragElement;
 
                     if (dragDropFinish)
@@ -1505,7 +1505,7 @@ void UI::ProcessClickEnd(const IntVector2& windowCursorPos, int button, int butt
     }
 }
 
-void UI::ProcessMove(const IntVector2& windowCursorPos, const IntVector2& cursorDeltaPos, int buttons, int qualifiers, Cursor* cursor,
+void UI::ProcessMove(const IntVector2& windowCursorPos, const IntVector2& cursorDeltaPos, FlagSet<MouseButton> buttons, FlagSet<Qualifier> qualifiers, Cursor* cursor,
     bool cursorVisible)
 {
     if (cursorVisible && dragElementsCount_ > 0 && buttons)
@@ -1611,23 +1611,23 @@ void UI::SendDragOrHoverEvent(StringHash eventType, UIElement* element, const In
 
     if (dragData)
     {
-        eventData[P_BUTTONS] = dragData->dragButtons;
+        eventData[P_BUTTONS] = (unsigned)dragData->dragButtons;
         eventData[P_NUMBUTTONS] = dragData->numDragButtons;
     }
 
     element->SendEvent(eventType, eventData);
 }
 
-void UI::SendClickEvent(StringHash eventType, UIElement* beginElement, UIElement* endElement, const IntVector2& pos, int button,
-    int buttons, int qualifiers)
+void UI::SendClickEvent(StringHash eventType, UIElement* beginElement, UIElement* endElement, const IntVector2& pos, MouseButton button,
+    FlagSet<MouseButton> buttons, FlagSet<Qualifier> qualifiers)
 {
     VariantMap& eventData = GetEventDataMap();
     eventData[UIMouseClick::P_ELEMENT] = endElement;
     eventData[UIMouseClick::P_X] = pos.x_;
     eventData[UIMouseClick::P_Y] = pos.y_;
     eventData[UIMouseClick::P_BUTTON] = button;
-    eventData[UIMouseClick::P_BUTTONS] = buttons;
-    eventData[UIMouseClick::P_QUALIFIERS] = qualifiers;
+    eventData[UIMouseClick::P_BUTTONS] = (unsigned)buttons;
+    eventData[UIMouseClick::P_QUALIFIERS] = (unsigned)qualifiers;
 
     // For click end events, send also the element the click began on
     if (eventType == E_UIMOUSECLICKEND)
@@ -1646,8 +1646,8 @@ void UI::SendClickEvent(StringHash eventType, UIElement* beginElement, UIElement
     SendEvent(eventType, eventData);
 }
 
-void UI::SendDoubleClickEvent(UIElement* beginElement, UIElement* endElement, const IntVector2& firstPos, const IntVector2& secondPos, int button,
-    int buttons, int qualifiers)
+void UI::SendDoubleClickEvent(UIElement* beginElement, UIElement* endElement, const IntVector2& firstPos, const IntVector2& secondPos, MouseButton button,
+    FlagSet<MouseButton> buttons, FlagSet<Qualifier> qualifiers)
 {
     VariantMap& eventData = GetEventDataMap();
     eventData[UIMouseDoubleClick::P_ELEMENT] = endElement;
@@ -1656,8 +1656,8 @@ void UI::SendDoubleClickEvent(UIElement* beginElement, UIElement* endElement, co
     eventData[UIMouseDoubleClick::P_XBEGIN] = firstPos.x_;
     eventData[UIMouseDoubleClick::P_YBEGIN] = firstPos.y_;
     eventData[UIMouseDoubleClick::P_BUTTON] = button;
-    eventData[UIMouseDoubleClick::P_BUTTONS] = buttons;
-    eventData[UIMouseDoubleClick::P_QUALIFIERS] = qualifiers;
+    eventData[UIMouseDoubleClick::P_BUTTONS] = (unsigned)buttons;
+    eventData[UIMouseDoubleClick::P_QUALIFIERS] = (unsigned)qualifiers;
 
 
     if (endElement)
@@ -1685,8 +1685,8 @@ void UI::HandleMouseButtonDown(StringHash eventType, VariantMap& eventData)
 {
     using namespace MouseButtonDown;
 
-    mouseButtons_ = eventData[P_BUTTONS].GetInt();
-    qualifiers_ = eventData[P_QUALIFIERS].GetInt();
+    mouseButtons_ = FlagSet<MouseButton>(eventData[P_BUTTONS].GetUInt());
+    qualifiers_ = FlagSet<Qualifier>(eventData[P_QUALIFIERS].GetUInt());
     usingTouchInput_ = false;
 
     IntVector2 cursorPos;
@@ -1699,29 +1699,29 @@ void UI::HandleMouseButtonDown(StringHash eventType, VariantMap& eventData)
     auto* input = GetSubsystem<Input>();
 
     if (!input->IsMouseGrabbed())
-        ProcessClickBegin(cursorPos, eventData[P_BUTTON].GetInt(), mouseButtons_, qualifiers_, cursor_, cursorVisible);
+        ProcessClickBegin(cursorPos, FlagSet<MouseButton>(eventData[P_BUTTON].GetUInt()), mouseButtons_, qualifiers_, cursor_, cursorVisible);
 }
 
 void UI::HandleMouseButtonUp(StringHash eventType, VariantMap& eventData)
 {
     using namespace MouseButtonUp;
 
-    mouseButtons_ = eventData[P_BUTTONS].GetInt();
-    qualifiers_ = eventData[P_QUALIFIERS].GetInt();
+    mouseButtons_ = FlagSet<MouseButton>(eventData[P_BUTTONS].GetUInt());
+    qualifiers_ = FlagSet<Qualifier>(eventData[P_QUALIFIERS].GetUInt());
 
     IntVector2 cursorPos;
     bool cursorVisible;
     GetCursorPositionAndVisible(cursorPos, cursorVisible);
 
-    ProcessClickEnd(cursorPos, eventData[P_BUTTON].GetInt(), mouseButtons_, qualifiers_, cursor_, cursorVisible);
+    ProcessClickEnd(cursorPos, (MouseButton)eventData[P_BUTTON].GetUInt(), mouseButtons_, qualifiers_, cursor_, cursorVisible);
 }
 
 void UI::HandleMouseMove(StringHash eventType, VariantMap& eventData)
 {
     using namespace MouseMove;
 
-    mouseButtons_ = eventData[P_BUTTONS].GetInt();
-    qualifiers_ = eventData[P_QUALIFIERS].GetInt();
+    mouseButtons_ = FlagSet<MouseButton>(eventData[P_BUTTONS].GetUInt());
+    qualifiers_ = FlagSet<Qualifier>(eventData[P_QUALIFIERS].GetUInt());
     usingTouchInput_ = false;
 
     auto* input = GetSubsystem<Input>();
@@ -1769,8 +1769,8 @@ void UI::HandleMouseWheel(StringHash eventType, VariantMap& eventData)
 
     using namespace MouseWheel;
 
-    mouseButtons_ = eventData[P_BUTTONS].GetInt();
-    qualifiers_ = eventData[P_QUALIFIERS].GetInt();
+    mouseButtons_ = FlagSet<MouseButton>(eventData[P_BUTTONS].GetInt());
+    qualifiers_ = FlagSet<Qualifier>(eventData[P_QUALIFIERS].GetInt());
     int delta = eventData[P_WHEEL].GetInt();
     usingTouchInput_ = false;
 
@@ -1818,16 +1818,16 @@ void UI::HandleTouchBegin(StringHash eventType, VariantMap& eventData)
     pos.y_ = int(pos.y_ / uiScale_);
     usingTouchInput_ = true;
 
-    int touchId = TOUCHID_MASK(eventData[P_TOUCHID].GetInt());
+    auto touchId = TOUCHID_MASK(eventData[P_TOUCHID].GetInt());
     WeakPtr<UIElement> element(GetElementAt(pos));
 
     if (element)
     {
-        ProcessClickBegin(pos, touchId, touchDragElements_[element], 0, nullptr, true);
+        ProcessClickBegin(pos, touchId, touchDragElements_[element], QUAL_NONE, nullptr, true);
         touchDragElements_[element] |= touchId;
     }
     else
-        ProcessClickBegin(pos, touchId, touchId, 0, nullptr, true);
+        ProcessClickBegin(pos, touchId, touchId, QUAL_NONE, nullptr, true);
 }
 
 void UI::HandleTouchEnd(StringHash eventType, VariantMap& eventData)
@@ -1839,16 +1839,16 @@ void UI::HandleTouchEnd(StringHash eventType, VariantMap& eventData)
     pos.y_ = int(pos.y_ / uiScale_);
 
     // Get the touch index
-    int touchId = TOUCHID_MASK(eventData[P_TOUCHID].GetInt());
+    auto touchId = TOUCHID_MASK(eventData[P_TOUCHID].GetInt());
 
     // Transmit hover end to the position where the finger was lifted
     WeakPtr<UIElement> element(GetElementAt(pos));
 
     // Clear any drag events that were using the touch id
-    for (HashMap<WeakPtr<UIElement>, int>::Iterator i = touchDragElements_.Begin(); i != touchDragElements_.End();)
+    for (auto i = touchDragElements_.Begin(); i != touchDragElements_.End();)
     {
-        int touches = i->second_;
-        if (touches & touchId)
+        auto touches = i->second_;
+        if (touchId & touches)
             i = touchDragElements_.Erase(i);
         else
             ++i;
@@ -1857,7 +1857,7 @@ void UI::HandleTouchEnd(StringHash eventType, VariantMap& eventData)
     if (element && element->IsEnabled())
         element->OnHover(element->ScreenToElement(pos), pos, 0, 0, nullptr);
 
-    ProcessClickEnd(pos, touchId, 0, 0, nullptr, true);
+    ProcessClickEnd(pos, touchId, MOUSEB_NONE, QUAL_NONE, nullptr, true);
 }
 
 void UI::HandleTouchMove(StringHash eventType, VariantMap& eventData)
@@ -1872,18 +1872,18 @@ void UI::HandleTouchMove(StringHash eventType, VariantMap& eventData)
     deltaPos.y_ = int(deltaPos.y_ / uiScale_);
     usingTouchInput_ = true;
 
-    int touchId = TOUCHID_MASK(eventData[P_TOUCHID].GetInt());
+    auto touchId = TOUCHID_MASK(eventData[P_TOUCHID].GetInt());
 
-    ProcessMove(pos, deltaPos, touchId, 0, nullptr, true);
+    ProcessMove(pos, deltaPos, touchId, QUAL_NONE, nullptr, true);
 }
 
 void UI::HandleKeyDown(StringHash eventType, VariantMap& eventData)
 {
     using namespace KeyDown;
 
-    mouseButtons_ = eventData[P_BUTTONS].GetInt();
-    qualifiers_ = eventData[P_QUALIFIERS].GetInt();
-    int key = eventData[P_KEY].GetInt();
+    mouseButtons_ = FlagSet<MouseButton>(eventData[P_BUTTONS].GetUInt());
+    qualifiers_ = FlagSet<Qualifier>(eventData[P_QUALIFIERS].GetUInt());
+    auto key = (Key)eventData[P_KEY].GetUInt();
 
     // Cancel UI dragging
     if (key == KEY_ESCAPE && dragElementsCount_ > 0)
@@ -2064,12 +2064,12 @@ IntVector2 UI::SumTouchPositions(UI::DragData* dragData, const IntVector2& oldSe
     IntVector2 sendPos = oldSendPos;
     if (usingTouchInput_)
     {
-        int buttons = dragData->dragButtons;
+        FlagSet<MouseButton> buttons = dragData->dragButtons;
         dragData->sumPos = IntVector2::ZERO;
         auto* input = GetSubsystem<Input>();
-        for (unsigned i = 0; (1u << i) <= buttons; i++)
+        for (unsigned i = 0; (1u << i) <= (unsigned)buttons; i++)
         {
-            if ((1u << i) & buttons)
+            if (FlagSet<MouseButton>(1u << i) & buttons)
             {
                 TouchState* ts = input->GetTouch((unsigned)i);
                 if (!ts)

+ 12 - 12
Source/Urho3D/UI/UI.h

@@ -224,7 +224,7 @@ public:
     struct DragData
     {
         /// Which button combo initiated the drag.
-        int dragButtons;
+        FlagSet<MouseButton> dragButtons;
         /// How many buttons initiated the drag.
         int numDragButtons;
         /// Sum of all touch locations
@@ -282,25 +282,25 @@ private:
     /// Force release of font faces when global font properties change.
     void ReleaseFontFaces();
     /// Handle button or touch hover.
-    void ProcessHover(const IntVector2& windowCursorPos, int buttons, int qualifiers, Cursor* cursor);
+    void ProcessHover(const IntVector2& windowCursorPos, FlagSet<MouseButton> buttons, FlagSet<Qualifier> qualifiers, Cursor* cursor);
     /// Handle button or touch begin.
     void
-        ProcessClickBegin(const IntVector2& windowCursorPos, int button, int buttons, int qualifiers, Cursor* cursor, bool cursorVisible);
+        ProcessClickBegin(const IntVector2& windowCursorPos, MouseButton button, FlagSet<MouseButton> buttons, FlagSet<Qualifier> qualifiers, Cursor* cursor, bool cursorVisible);
     /// Handle button or touch end.
-    void ProcessClickEnd(const IntVector2& windowCursorPos, int button, int buttons, int qualifiers, Cursor* cursor, bool cursorVisible);
+    void ProcessClickEnd(const IntVector2& windowCursorPos, MouseButton button, FlagSet<MouseButton> buttons, FlagSet<Qualifier> qualifiers, Cursor* cursor, bool cursorVisible);
     /// Handle mouse or touch move.
-    void ProcessMove(const IntVector2& windowCursorPos, const IntVector2& cursorDeltaPos, int buttons, int qualifiers, Cursor* cursor,
+    void ProcessMove(const IntVector2& windowCursorPos, const IntVector2& cursorDeltaPos, FlagSet<MouseButton> buttons, FlagSet<Qualifier> qualifiers, Cursor* cursor,
         bool cursorVisible);
     /// Send a UI element drag or hover begin event.
     void SendDragOrHoverEvent
         (StringHash eventType, UIElement* element, const IntVector2& screenPos, const IntVector2& deltaPos, UI::DragData* dragData);
     /// Send a UI click event.
     void SendClickEvent
-        (StringHash eventType, UIElement* beginElement, UIElement* endElement, const IntVector2& pos, int button, int buttons,
-            int qualifiers);
+        (StringHash eventType, UIElement* beginElement, UIElement* endElement, const IntVector2& pos, MouseButton button, FlagSet<MouseButton> buttons,
+            FlagSet<Qualifier> qualifiers);
 
     /// Send a UI double click event
-    void SendDoubleClickEvent(UIElement* beginElement, UIElement* endElement, const IntVector2& firstPos, const IntVector2& secondPos, int button, int buttons, int qualifiers);
+    void SendDoubleClickEvent(UIElement* beginElement, UIElement* endElement, const IntVector2& firstPos, const IntVector2& secondPos, MouseButton button, FlagSet<MouseButton> buttons, FlagSet<Qualifier> qualifiers);
     
     /// Handle screen mode event.
     void HandleScreenMode(StringHash eventType, VariantMap& eventData);
@@ -376,11 +376,11 @@ private:
     /// Drag begin event distance threshold in pixels.
     int dragBeginDistance_;
     /// Mouse buttons held down.
-    int mouseButtons_;
+    FlagSet<MouseButton> mouseButtons_;
     /// Last mouse button pressed.
-    int lastMouseButtons_;
+    FlagSet<MouseButton> lastMouseButtons_;
     /// Qualifier keys held down.
-    int qualifiers_;
+    FlagSet<Qualifier> qualifiers_;
     /// Font texture maximum size.
     int maxFontTextureSize_;
     /// Initialized flag.
@@ -424,7 +424,7 @@ private:
     /// Number of elements in dragElements_ with dragPending = false.
     int dragConfirmedCount_;
     /// UI elements that are being touched with touch input.
-    HashMap<WeakPtr<UIElement>, int> touchDragElements_;
+    HashMap<WeakPtr<UIElement>, FlagSet<MouseButton>> touchDragElements_;
     /// Confirmed drag elements cache.
     Vector<UIElement*> dragElementsConfirmed_;
     /// Current scale of UI.

+ 2 - 2
Source/Urho3D/UI/UIElement.cpp

@@ -145,7 +145,7 @@ void UIElement::RegisterObject(Context* context)
     URHO3D_ACCESSOR_ATTRIBUTE("Clip Children", GetClipChildren, SetClipChildren, bool, false, AM_FILE);
     URHO3D_ACCESSOR_ATTRIBUTE("Use Derived Opacity", GetUseDerivedOpacity, SetUseDerivedOpacity, bool, true, AM_FILE);
     URHO3D_ENUM_ACCESSOR_ATTRIBUTE("Focus Mode", GetFocusMode, SetFocusMode, FocusMode, focusModes, FM_NOTFOCUSABLE, AM_FILE);
-    URHO3D_ENUM_ACCESSOR_ATTRIBUTE("Drag And Drop Mode", GetDragDropMode, SetDragDropMode, unsigned, dragDropModes, DD_DISABLED, AM_FILE);
+    URHO3D_ENUM_ACCESSOR_ATTRIBUTE("Drag And Drop Mode", GetDragDropMode, SetDragDropMode, FlagSet<DragAndDropMode>, dragDropModes, DD_DISABLED, AM_FILE);
     URHO3D_ENUM_ACCESSOR_ATTRIBUTE("Layout Mode", GetLayoutMode, SetLayoutMode, LayoutMode, layoutModes, LM_FREE, AM_FILE);
     URHO3D_ACCESSOR_ATTRIBUTE("Layout Spacing", GetLayoutSpacing, SetLayoutSpacing, int, 0, AM_FILE);
     URHO3D_ACCESSOR_ATTRIBUTE("Layout Border", GetLayoutBorder, SetLayoutBorder, IntRect, IntRect::ZERO, AM_FILE);
@@ -986,7 +986,7 @@ void UIElement::SetVisible(bool enable)
     }
 }
 
-void UIElement::SetDragDropMode(unsigned mode)
+void UIElement::SetDragDropMode(FlagSet<DragAndDropMode> mode)
 {
     dragDropMode_ = mode;
 }

+ 18 - 13
Source/Urho3D/UI/UIElement.h

@@ -23,6 +23,7 @@
 #pragma once
 
 #include "../Math/Vector2.h"
+#include "../Input/InputConstants.h"
 #include "../Resource/XMLFile.h"
 #include "../Scene/Animatable.h"
 #include "../UI/UIBatch.h"
@@ -98,14 +99,18 @@ enum TraversalMode
     TM_DEPTH_FIRST
 };
 
-/// Drag and drop disabled.
-static const unsigned DD_DISABLED = 0x0;
-/// Drag and drop source flag.
-static const unsigned DD_SOURCE = 0x1;
-/// Drag and drop target flag.
-static const unsigned DD_TARGET = 0x2;
-/// Drag and drop source and target.
-static const unsigned DD_SOURCE_AND_TARGET = 0x3;
+enum DragAndDropMode : unsigned
+{
+    /// Drag and drop disabled.
+    DD_DISABLED = 0x0,
+    /// Drag and drop source flag.
+    DD_SOURCE = 0x1,
+    /// Drag and drop target flag.
+    DD_TARGET = 0x2,
+    /// Drag and drop source and target.
+    DD_SOURCE_AND_TARGET = 0x3,
+};
+template<> struct is_flagset<DragAndDropMode> { constexpr static bool value = true; };
 
 class Cursor;
 class ResourceCache;
@@ -175,9 +180,9 @@ public:
     /// React to drag and drop finish. Return true to signal that the drop was accepted.
     virtual bool OnDragDropFinish(UIElement* source);
     /// React to mouse wheel.
-    virtual void OnWheel(int delta, int buttons, int qualifiers) { }
+    virtual void OnWheel(int delta, FlagSet<MouseButton> buttons, FlagSet<Qualifier> qualifiers) { }
     /// React to a key press.
-    virtual void OnKey(int key, int buttons, int qualifiers) { }
+    virtual void OnKey(Key key, FlagSet<MouseButton> buttons, FlagSet<Qualifier> qualifiers) { }
     /// React to text input event.
     virtual void OnTextInput(const String& text) { }
 
@@ -309,7 +314,7 @@ public:
     /// Set focus mode.
     void SetFocusMode(FocusMode mode);
     /// Set drag and drop flags.
-    void SetDragDropMode(unsigned mode);
+    void SetDragDropMode(FlagSet<DragAndDropMode> mode);
     /// Set style from an XML file. Find the style element by name. If the style file is not explicitly provided, use the default style from parental chain. Return true if the style is applied successfully.
     bool SetStyle(const String& styleName, XMLFile* file = nullptr);
     /// Set style from an XML element. Return true if the style is applied successfully.
@@ -531,7 +536,7 @@ public:
     FocusMode GetFocusMode() const { return focusMode_; }
 
     /// Return drag and drop flags.
-    unsigned GetDragDropMode() const { return dragDropMode_; }
+    FlagSet<DragAndDropMode> GetDragDropMode() const { return dragDropMode_; }
 
     /// Return applied style name. Return an empty string when the applied style is an 'auto' style (i.e. style derived from instance's type).
     const String& GetAppliedStyle() const;
@@ -705,7 +710,7 @@ protected:
     /// Focus mode.
     FocusMode focusMode_{FM_NOTFOCUSABLE};
     /// Drag and drop flags.
-    unsigned dragDropMode_{DD_DISABLED};
+    FlagSet<DragAndDropMode> dragDropMode_{DD_DISABLED};
     /// Layout mode.
     LayoutMode layoutMode_{LM_FREE};
     /// Layout spacing.