Forráskód Böngészése

Added Slider UI element.

Lasse Öörni 15 éve
szülő
commit
4f1e1ce9b8

+ 27 - 14
Bin/Data/UI/DefaultStyle.xml

@@ -1,10 +1,4 @@
 <elements>
 <elements>
-    <element type="Cursor">
-        <size value="16 24" />
-        <texture name="Textures/UI.png" />
-        <imagerect value="0 0 16 24" />
-        <hotspot value="0 0" />
-    </element>
     <element type="Button">
     <element type="Button">
         <size value="16 16" />
         <size value="16 16" />
         <texture name="Textures/UI.png" />
         <texture name="Textures/UI.png" />
@@ -14,6 +8,32 @@
         <hoveroffset value="0 16" />
         <hoveroffset value="0 16" />
         <labeloffset value="-1 1" />
         <labeloffset value="-1 1" />
     </element>
     </element>
+    <element type="CheckBox">
+        <size value="16 16" />
+        <texture name="Textures/UI.png" />
+        <uncheckedrect value="64 0 80 16" />
+        <checkedrect value="80 0 96 16" />
+        <border value="4 4 4 4" />
+        <hoveroffset value="0 16" />
+    </element>
+    <element type="Cursor">
+        <size value="16 24" />
+        <texture name="Textures/UI.png" />
+        <imagerect value="0 0 16 24" />
+        <hotspot value="0 0" />
+    </element>
+    <element type="Slider">
+        <size value="16 16" />
+        <texture name="Textures/UI.png" />
+        <imagerect value="48 0 64 16" />
+        <border value="3 3 3 3" />
+        <slider>
+            <texture name="Textures/UI.png" />
+            <imagerect value="16 0 32 16" />
+            <border value="4 4 4 4" />
+            <hoveroffset value="0 16" />
+        </slider>
+    </element>
     <element type="Window">
     <element type="Window">
         <texture name="Textures/UI.png" />
         <texture name="Textures/UI.png" />
         <imagerect value="48 0 64 16" />
         <imagerect value="48 0 64 16" />
@@ -25,12 +45,5 @@
     <element type="Text">
     <element type="Text">
         <font name="Cour.ttf" size="10" />
         <font name="Cour.ttf" size="10" />
     </element>
     </element>
-    <element type="CheckBox">
-        <size value="16 16" />
-        <texture name="Textures/UI.png" />
-        <uncheckedrect value="64 0 80 16" />
-        <checkedrect value="80 0 96 16" />
-        <border value="4 4 4 4" />
-        <hoveroffset value="0 16" />
-    </element>
+
 </elements>
 </elements>

+ 35 - 7
Bin/Data/UI/TestLayout.xml

@@ -1,11 +1,39 @@
 <layout>
 <layout>
-    <element type="Button">
-        <size value="100 40" />
-        <alignment horizontal="center" vertical="center" />
-        <element type="Text">
-            <text value="TEST" />
-            <font name="cour.ttf" size="12" />
-            <alignment horizontal="center" vertical="center" />
+    <element type="Window">
+        <position value="50 50" />
+        <size value="250 250" />
+        <resizable enable="false" />
+        <element type="Button">
+            <position value="10 10" />
+            <size value="100 40" />
+            <element type="Text">
+                <text value="TEST" />
+                <font name="cour.ttf" size="12" />
+                <alignment horizontal="center" vertical="center" />
+            </element>
+        </element>
+        <element type="Slider">
+            <position value="10 200" />
+            <size value="128 16" />
+            <slider range="10" value="5" />
+        </element>
+        <element type="Slider">
+            <position value="200 10" />
+            <size value="16 128 " />
+            <orientation value="vertical" />
+            <slider range="1" value="1" />
+        </element>
+        <element type="CheckBox">
+            <position value="10 100" />
+        </element>
+        <element type="CheckBox">
+            <position value="40 100" />
+        </element>
+        <element type="CheckBox">
+            <position value="10 130" />
+        </element>
+        <element type="CheckBox">
+            <position value="40 130" />
         </element>
         </element>
     </element>
     </element>
 </layout>
 </layout>

+ 1 - 1
Engine/Engine/Engine.cpp

@@ -98,7 +98,7 @@ Engine::Engine(const std::string& logFileName, bool headless) :
         "ControlsUpdate", "ControlsPlayback", "MouseButtonDown", "MouseButtonUp", "MouseMove", "KeyDown", "KeyUp", "Char",
         "ControlsUpdate", "ControlsPlayback", "MouseButtonDown", "MouseButtonUp", "MouseMove", "KeyDown", "KeyUp", "Char",
         "PeerConnected", "NetworkPacket", "PeerDisconnected", "PhysicsPreStep", "PhysicsPostStep", "PhysicsCollision",
         "PeerConnected", "NetworkPacket", "PeerDisconnected", "PhysicsPreStep", "PhysicsPostStep", "PhysicsCollision",
         "EntityCollision", "WindowMessage", "WindowResized", "BeginFrame", "EndFrame", "SceneUpdate", "ScenePostUpdate",
         "EntityCollision", "WindowMessage", "WindowResized", "BeginFrame", "EndFrame", "SceneUpdate", "ScenePostUpdate",
-        "AsyncLoadProgress", "AsyncLoadFinished", "Focused", "Defocused", "Pressed", "Toggled", ""
+        "AsyncLoadProgress", "AsyncLoadFinished", "Focused", "Defocused", "Pressed", "Toggled", "ValueChanged", ""
     };
     };
     
     
     for (unsigned i = 0; inbuiltEvents[i].length(); ++i)
     for (unsigned i = 0; inbuiltEvents[i].length(); ++i)

+ 0 - 1
Engine/Engine/ParticleEmitter.cpp

@@ -28,7 +28,6 @@
 #include "ResourceCache.h"
 #include "ResourceCache.h"
 #include "Scene.h"
 #include "Scene.h"
 #include "SceneEvents.h"
 #include "SceneEvents.h"
-#include "StringUtils.h"
 #include "XMLFile.h"
 #include "XMLFile.h"
 
 
 #include "DebugNew.h"
 #include "DebugNew.h"

+ 20 - 1
Engine/Engine/RegisterUI.cpp

@@ -28,6 +28,7 @@
 #include "Engine.h"
 #include "Engine.h"
 #include "Font.h"
 #include "Font.h"
 #include "RegisterTemplates.h"
 #include "RegisterTemplates.h"
+#include "Slider.h"
 #include "Text.h"
 #include "Text.h"
 #include "UI.h"
 #include "UI.h"
 #include "Window.h"
 #include "Window.h"
@@ -56,6 +57,10 @@ static void registerUIElement(asIScriptEngine* engine)
     engine->RegisterEnumValue("UIElementCorner", "C_BOTTOMLEFT", C_BOTTOMLEFT);
     engine->RegisterEnumValue("UIElementCorner", "C_BOTTOMLEFT", C_BOTTOMLEFT);
     engine->RegisterEnumValue("UIElementCorner", "C_BOTTOMRIGHT", C_BOTTOMRIGHT);
     engine->RegisterEnumValue("UIElementCorner", "C_BOTTOMRIGHT", C_BOTTOMRIGHT);
     
     
+    engine->RegisterEnum("UIElementOrientation");
+    engine->RegisterEnumValue("UIElementOrientation", "O_HORIZONTAL", O_HORIZONTAL);
+    engine->RegisterEnumValue("UIElementOrientation", "O_VERTICAL", O_VERTICAL);
+    
     registerUIElement<UIElement>(engine, "UIElement");
     registerUIElement<UIElement>(engine, "UIElement");
     
     
     // Register static function for getting UI style XML element
     // Register static function for getting UI style XML element
@@ -128,6 +133,19 @@ static void registerCheckBox(asIScriptEngine* engine)
     registerRefCasts<UIElement, CheckBox>(engine, "UIElement", "CheckBox");
     registerRefCasts<UIElement, CheckBox>(engine, "UIElement", "CheckBox");
 }
 }
 
 
+static void registerSlider(asIScriptEngine* engine)
+{
+    registerBorderImage<Slider>(engine, "Slider");
+    engine->RegisterObjectMethod("Slider", "void setOrientation(UIElementOrientation)", asMETHOD(Slider, setOrientation), asCALL_THISCALL);
+    engine->RegisterObjectMethod("Slider", "void setRange(float)", asMETHOD(Slider, setRange), asCALL_THISCALL);
+    engine->RegisterObjectMethod("Slider", "void setValue(float)", asMETHOD(Slider, setValue), asCALL_THISCALL);
+    engine->RegisterObjectMethod("Slider", "UIElementOrientation getOrientation() const", asMETHOD(Slider, getOrientation), asCALL_THISCALL);
+    engine->RegisterObjectMethod("Slider", "float getRange() const", asMETHOD(Slider, getRange), asCALL_THISCALL);
+    engine->RegisterObjectMethod("Slider", "float getValue() const", asMETHOD(Slider, getValue), asCALL_THISCALL);
+    engine->RegisterObjectMethod("Slider", "BorderImage@+ getSlider() const", asMETHOD(Slider, getSlider), asCALL_THISCALL);
+    registerRefCasts<UIElement, Slider>(engine, "UIElement", "Slider");
+}
+
 static void registerWindow(asIScriptEngine* engine)
 static void registerWindow(asIScriptEngine* engine)
 {
 {
     registerBorderImage<Window>(engine, "Window");
     registerBorderImage<Window>(engine, "Window");
@@ -239,11 +257,12 @@ void registerUILibrary(asIScriptEngine* engine)
 {
 {
     registerFont(engine);
     registerFont(engine);
     registerUIElement(engine);
     registerUIElement(engine);
-    registerText(engine);
     registerBorderImage(engine);
     registerBorderImage(engine);
     registerButton(engine);
     registerButton(engine);
     registerCheckBox(engine);
     registerCheckBox(engine);
     registerCursor(engine);
     registerCursor(engine);
+    registerSlider(engine);
+    registerText(engine);
     registerWindow(engine);
     registerWindow(engine);
     registerUI(engine);
     registerUI(engine);
 }
 }

+ 0 - 1
Engine/Renderer/AnimatedModel.cpp

@@ -38,7 +38,6 @@
 #include "ReplicationUtils.h"
 #include "ReplicationUtils.h"
 #include "ResourceCache.h"
 #include "ResourceCache.h"
 #include "Scene.h"
 #include "Scene.h"
-#include "StringUtils.h"
 #include "VertexBuffer.h"
 #include "VertexBuffer.h"
 
 
 #include <algorithm>
 #include <algorithm>

+ 0 - 1
Engine/Renderer/Geometry.cpp

@@ -28,7 +28,6 @@
 #include "Ray.h"
 #include "Ray.h"
 #include "Renderer.h"
 #include "Renderer.h"
 #include "RendererImpl.h"
 #include "RendererImpl.h"
-#include "StringUtils.h"
 #include "VertexBuffer.h"
 #include "VertexBuffer.h"
 
 
 #include "DebugNew.h"
 #include "DebugNew.h"

+ 3 - 0
Engine/UI/BaseUIElementFactory.cpp

@@ -26,6 +26,7 @@
 #include "Button.h"
 #include "Button.h"
 #include "CheckBox.h"
 #include "CheckBox.h"
 #include "Cursor.h"
 #include "Cursor.h"
+#include "Slider.h"
 #include "Text.h"
 #include "Text.h"
 #include "Window.h"
 #include "Window.h"
 
 
@@ -39,6 +40,8 @@ UIElement* BaseUIElementFactory::createElement(ShortStringHash type, const std::
         return new CheckBox(name);
         return new CheckBox(name);
     if (type == Cursor::getTypeStatic())
     if (type == Cursor::getTypeStatic())
         return new Cursor(name);
         return new Cursor(name);
+    if (type == Slider::getTypeStatic())
+        return new Slider(name);
     if (type == Text::getTypeStatic())
     if (type == Text::getTypeStatic())
         return new Text(std::string(), name);
         return new Text(std::string(), name);
     if (type == UIElement::getTypeStatic())
     if (type == UIElement::getTypeStatic())

+ 1 - 0
Engine/UI/CheckBox.h

@@ -26,6 +26,7 @@
 
 
 #include "BorderImage.h"
 #include "BorderImage.h"
 
 
+//! An image that can be toggled between unchecked and checked state
 class CheckBox : public BorderImage
 class CheckBox : public BorderImage
 {
 {
     DEFINE_TYPE(CheckBox);
     DEFINE_TYPE(CheckBox);

+ 0 - 1
Engine/UI/Font.cpp

@@ -27,7 +27,6 @@
 #include "Profiler.h"
 #include "Profiler.h"
 #include "Renderer.h"
 #include "Renderer.h"
 #include "RendererImpl.h"
 #include "RendererImpl.h"
-#include "StringUtils.h"
 #include "Texture2D.h"
 #include "Texture2D.h"
 
 
 #include <stb_truetype.h>
 #include <stb_truetype.h>

+ 178 - 0
Engine/UI/Slider.cpp

@@ -0,0 +1,178 @@
+//
+// Urho3D Engine
+// Copyright (c) 2008-2011 Lasse Öörni
+//
+// 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.
+//
+
+#include "Precompiled.h"
+#include "InputEvents.h"
+#include "Log.h"
+#include "ResourceCache.h"
+#include "Slider.h"
+#include "Texture2D.h"
+#include "UIEvents.h"
+
+#include "DebugNew.h"
+
+Slider::Slider(const std::string& name) :
+    BorderImage(name),
+    mOrientation(O_HORIZONTAL),
+    mRange(1.0f),
+    mValue(0.0f),
+    mDragSlider(false)
+{
+    mEnabled = true;
+    mSlider = new BorderImage();
+    addChild(mSlider);
+    
+    updateSlider();
+}
+
+Slider::~Slider()
+{
+}
+
+void Slider::setStyle(const XMLElement& element, ResourceCache* cache)
+{
+    if (!cache)
+        EXCEPTION("Null resource cache for UI element");
+    
+    BorderImage::setStyle(element, cache);
+    
+    if (element.hasChildElement("orientation"))
+    {
+        std::string orientation = element.getChildElement("orientation").getStringLower("value");
+        if ((orientation == "horizontal") || (orientation == "h"))
+            setOrientation(O_HORIZONTAL);
+        if ((orientation == "vertical") || (orientation == "v"))
+            setOrientation(O_VERTICAL);
+    }
+    
+    XMLElement sliderElem = element.getChildElement("slider");
+    if (sliderElem)
+    {
+        mSlider->setStyle(sliderElem, cache);
+        setRange(sliderElem.getFloat("range"));
+        setValue(sliderElem.getFloat("value"));
+    }
+}
+
+void Slider::update(float timeStep)
+{
+    if (mDragSlider)
+        mHovering = true;
+    
+    // Copy hover effect to the slider button
+    mSlider->setHovering(mHovering);
+}
+
+void Slider::onHover(const IntVector2& position, const IntVector2& screenPosition, unsigned buttons)
+{
+    // Show hover effect if inside the slider button
+    mHovering = mSlider->isInside(screenPosition, true);
+}
+
+void Slider::onDragStart(const IntVector2& position, const IntVector2& screenPosition, unsigned buttons)
+{
+    mOriginalPosition = position;
+    mOriginalSliderPosition = mSlider->getPosition();
+    mDragSlider = mSlider->isInside(screenPosition, true);
+}
+
+void Slider::onDragMove(const IntVector2& position, const IntVector2& screenPosition, unsigned buttons)
+{
+    if (!mDragSlider)
+        return;
+    
+    float newValue = mValue;
+    IntVector2 delta = position - mOriginalPosition;
+    
+    if (mOrientation == O_HORIZONTAL)
+    {
+        int newX = clamp(mOriginalSliderPosition.mX + delta.mX, 0, getWidth() - mSlider->getWidth());
+        mSlider->setPosition(newX, mOriginalSliderPosition.mY);
+        newValue = clamp((float)newX * (mRange + 1.0f) / (float)getWidth(), 0.0f, mRange);
+    }
+    else
+    {
+        int newY = clamp(mOriginalSliderPosition.mY + delta.mY, 0, getHeight() - mSlider->getHeight());
+        mSlider->setPosition(mOriginalSliderPosition.mX, newY);
+        newValue = clamp((float)newY * (mRange + 1.0f) / (float)getHeight(), 0.0f, mRange);
+    }
+    
+    if (newValue != mValue)
+    {
+        mValue = newValue;
+        
+        using namespace ValueChanged;
+        
+        VariantMap eventData;
+        eventData[P_ELEMENT] = (void*)this;
+        eventData[P_VALUE] = mValue;
+        sendEvent(EVENT_VALUECHANGED, eventData);
+    }
+}
+
+void Slider::onDragEnd(const IntVector2& position, const IntVector2& screenPosition)
+{
+    mDragSlider = false;
+}
+
+void Slider::setOrientation(UIElementOrientation orientation)
+{
+    mOrientation = orientation;
+    updateSlider();
+}
+
+void Slider::setRange(float range)
+{
+    mRange = max(range, 0.0f);
+    updateSlider();
+}
+
+void Slider::setValue(float value)
+{
+    mValue = max(value, 0.0f);
+    updateSlider();
+}
+
+void Slider::updateSlider()
+{
+    if (mOrientation == O_HORIZONTAL)
+    {
+        float width = (float)getWidth();
+        if (width < M_EPSILON)
+            return;
+        float sliderLength = width / (mRange + 1.0f);
+        float sliderPos = width * mValue / (mRange + 1.0f);
+        mSlider->setSize((int)sliderLength, getHeight());
+        mSlider->setPosition(clamp((int)(sliderPos + 0.5f), 0, getWidth() - mSlider->getWidth()), 0);
+    }
+    else
+    {
+        float height = (float)getHeight();
+        if (height < M_EPSILON)
+            return;
+        float sliderLength = height / (mRange + 1.0f);
+        float sliderPos = height * mValue / (mRange + 1.0f);
+        mSlider->setSize(getWidth(), (int)sliderLength);
+        mSlider->setPosition(0, clamp((int)(sliderPos + 0.5f), 0, getHeight() - mSlider->getHeight()));
+    }
+}

+ 89 - 0
Engine/UI/Slider.h

@@ -0,0 +1,89 @@
+//
+// Urho3D Engine
+// Copyright (c) 2008-2011 Lasse Öörni
+//
+// 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.
+//
+
+#ifndef UI_SLIDER_H
+#define UI_SLIDER_H
+
+#include "BorderImage.h"
+
+//! An image that contains a slideable child image
+class Slider : public BorderImage
+{
+    DEFINE_TYPE(Slider);
+    
+public:
+    //! Construct with name
+    Slider(const std::string& name = std::string());
+    //! Destruct
+    virtual ~Slider();
+    
+    //! Set UI element style from XML data
+    virtual void setStyle(const XMLElement& element, ResourceCache* cache);
+    //! Perform UI element update
+    virtual void update(float timeStep);
+    //! React to mouse hover
+    virtual void onHover(const IntVector2& position, const IntVector2& screenPosition, unsigned buttons);
+    //! React to mouse drag start
+    virtual void onDragStart(const IntVector2& position, const IntVector2& screenPosition, unsigned buttons);
+    //! React to mouse drag motion
+    virtual void onDragMove(const IntVector2& position, const IntVector2& screenPosition, unsigned buttons);
+    //! React to mouse drag end
+    virtual void onDragEnd(const IntVector2& position, const IntVector2& screenPosition);
+    
+    //! Set orientation
+    void setOrientation(UIElementOrientation orientation);
+    //! Set slider range maximum value (minimum value is always 0)
+    void setRange(float range);
+    //! Set slider current value
+    void setValue(float value);
+    
+    //! Return orientation
+    UIElementOrientation getOrientation() const { return mOrientation; }
+    //! Return slider range
+    float getRange() const { return mRange; }
+    //! Return slider current value
+    float getValue() const { return mValue; }
+    //! Return slider image element
+    BorderImage* getSlider() const { return mSlider; }
+    
+protected:
+    //! Update slider image position & size
+    void updateSlider();
+    
+    //! Slider image
+    SharedPtr<BorderImage> mSlider;
+    //! Orientation
+    UIElementOrientation mOrientation;
+    //! Slider range
+    float mRange;
+    //! Slider current value
+    float mValue;
+    //! Internal flag of whether the slider is being dragged
+    bool mDragSlider;
+    //! Original mouse position at drag start
+    IntVector2 mOriginalPosition;
+    //! Original slider position at drag start
+    IntVector2 mOriginalSliderPosition;
+};
+
+#endif // UI_SLIDER_H

+ 1 - 4
Engine/UI/UI.cpp

@@ -378,10 +378,7 @@ void UI::getElementAt(UIElement*& result, UIElement* current, const IntVector2&
         UIElement* element = *i;
         UIElement* element = *i;
         if ((element != mCursor.getPtr()) && (element->isVisible()))
         if ((element != mCursor.getPtr()) && (element->isVisible()))
         {
         {
-            const IntVector2& screenPosition = element->getScreenPosition();
-            const IntVector2& size = element->getSize();
-            if ((position.mX >= screenPosition.mX) && (position.mX < screenPosition.mX + size.mX) &&
-                (position.mY >= screenPosition.mY) && (position.mY < screenPosition.mY + size.mY))
+            if (element->isInside(position, true))
             {
             {
                 // Store the current result, then recurse into its children. Because children
                 // Store the current result, then recurse into its children. Because children
                 // are sorted from lowest to highest priority, we should be left with the topmost match
                 // are sorted from lowest to highest priority, we should be left with the topmost match

+ 14 - 3
Engine/UI/UIElement.cpp

@@ -24,7 +24,6 @@
 #include "Precompiled.h"
 #include "Precompiled.h"
 #include "Log.h"
 #include "Log.h"
 #include "ResourceCache.h"
 #include "ResourceCache.h"
-#include "StringUtils.h"
 #include "UIElement.h"
 #include "UIElement.h"
 #include "UIEvents.h"
 #include "UIEvents.h"
 
 
@@ -309,7 +308,7 @@ void UIElement::setVerticalAlignment(VerticalAlignment align)
 
 
 void UIElement::setColor(const Color& color)
 void UIElement::setColor(const Color& color)
 {
 {
-    for (unsigned i = 0; i < NUM_UIELEMENT_CORNERS; ++i)
+    for (unsigned i = 0; i < MAX_UIELEMENT_CORNERS; ++i)
         mColor[i] = color;
         mColor[i] = color;
     mHasColorGradient = false;
     mHasColorGradient = false;
 }
 }
@@ -319,7 +318,7 @@ void UIElement::setColor(UIElementCorner corner, const Color& color)
     mColor[corner] = color;
     mColor[corner] = color;
     mHasColorGradient = false;
     mHasColorGradient = false;
     
     
-    for (unsigned i = 0; i < NUM_UIELEMENT_CORNERS; ++i)
+    for (unsigned i = 0; i < MAX_UIELEMENT_CORNERS; ++i)
     {
     {
         if ((i != corner) && (mColor[i] != mColor[corner]))
         if ((i != corner) && (mColor[i] != mColor[corner]))
             mHasColorGradient = true;
             mHasColorGradient = true;
@@ -515,6 +514,18 @@ IntVector2 UIElement::elementToScreen(const IntVector2& position)
     return position + getScreenPosition();
     return position + getScreenPosition();
 }
 }
 
 
+bool UIElement::isInside(IntVector2 position, bool isScreen)
+{
+    if (isScreen)
+        position = screenToElement(position);
+    return (position.mX >= 0) && (position.mY >= 0) && (position.mX < mSize.mX) && (position.mY < mSize.mY);
+}
+
+void UIElement::setHovering(bool enable)
+{
+    mHovering = enable;
+}
+
 void UIElement::adjustScissor(IntRect& currentScissor)
 void UIElement::adjustScissor(IntRect& currentScissor)
 {
 {
     if (mClipChildren)
     if (mClipChildren)

+ 13 - 3
Engine/UI/UIElement.h

@@ -53,10 +53,16 @@ enum UIElementCorner
     C_TOPLEFT = 0,
     C_TOPLEFT = 0,
     C_TOPRIGHT,
     C_TOPRIGHT,
     C_BOTTOMLEFT,
     C_BOTTOMLEFT,
-    C_BOTTOMRIGHT
+    C_BOTTOMRIGHT,
+    MAX_UIELEMENT_CORNERS
 };
 };
 
 
-static const unsigned NUM_UIELEMENT_CORNERS = 4;
+//! UI element orientation
+enum UIElementOrientation
+{
+    O_HORIZONTAL = 0,
+    O_VERTICAL
+};
 
 
 class ResourceCache;
 class ResourceCache;
 
 
@@ -203,7 +209,11 @@ public:
     IntVector2 screenToElement(const IntVector2& screenPosition);
     IntVector2 screenToElement(const IntVector2& screenPosition);
     //! Convert element coordinates to screen coordinates
     //! Convert element coordinates to screen coordinates
     IntVector2 elementToScreen(const IntVector2& position);
     IntVector2 elementToScreen(const IntVector2& position);
+    //! Return whether a point (either in element or screen coordinates) is inside the element
+    bool isInside(IntVector2 position, bool isScreen);
     
     
+    //! Set hovering state
+    void setHovering(bool enable);
     //! Adjust scissor for rendering
     //! Adjust scissor for rendering
     void adjustScissor(IntRect& currentScissor);
     void adjustScissor(IntRect& currentScissor);
     
     
@@ -223,7 +233,7 @@ protected:
     //! Parent element
     //! Parent element
     UIElement* mParent;
     UIElement* mParent;
     //! Colors
     //! Colors
-    Color mColor[NUM_UIELEMENT_CORNERS];
+    Color mColor[MAX_UIELEMENT_CORNERS];
     //! Color modification on hover
     //! Color modification on hover
     Color mHoverColor;
     Color mHoverColor;
     //! Priority
     //! Priority

+ 7 - 0
Engine/UI/UIEvents.h

@@ -51,4 +51,11 @@ DEFINE_EVENT(EVENT_TOGGLED, Toggled)
     EVENT_PARAM(P_STATE, State);                // bool
     EVENT_PARAM(P_STATE, State);                // bool
 }
 }
 
 
+//! UI slider value changed
+DEFINE_EVENT(EVENT_VALUECHANGED, ValueChanged)
+{
+    EVENT_PARAM(P_ELEMENT, Element);            // UIElement pointer
+    EVENT_PARAM(P_VALUE, Value);                // float
+}
+
 #endif // UI_UIEVENTS_H
 #endif // UI_UIEVENTS_H