Просмотр исходного кода

Added ability to disable controls.
Touch events are now consumed by forms.
Particles are now billboarded.
Fixed drawing of text in CheckBoxes and RadioButtons.
Added missing methods to Slider.
Added an init method to Control for common initialization.

Adam Blake 14 лет назад
Родитель
Сommit
01b6c87a60

+ 25 - 33
gameplay/src/Button.cpp

@@ -17,22 +17,7 @@ namespace gameplay
     Button* Button::create(Theme::Style* style, Properties* properties)
     {
         Button* button = new Button();
-        button->_style = style;
-        properties->getVector2("position", &button->_position);
-        properties->getVector2("size", &button->_size);
-
-        const char* id = properties->getId();
-        if (id)
-        {
-            button->_id = id;
-        }
-
-        const char* text = properties->getString("text");
-        if (text)
-        {
-            button->_text = text;
-        }
-
+        button->init(style, properties);
         __buttons.push_back(button);
 
         return button;
@@ -65,28 +50,35 @@ namespace gameplay
         return NULL;
     }
 
-    void Button::touchEvent(Touch::TouchEvent evt, int x, int y, unsigned int contactIndex)
+    bool Button::touchEvent(Touch::TouchEvent evt, int x, int y, unsigned int contactIndex)
     {
-        if (_state != STATE_DISABLED)
+        if (!isEnabled())
         {
-            switch (evt)
-            {
-            case Touch::TOUCH_PRESS:
-                // TODO: button-down callback.
+            return false;
+        }
 
-                _state = Control::STATE_ACTIVE;
-                break;
-            case Touch::TOUCH_RELEASE:
-                if (_callback &&
-                    x > 0 && x <= _size.x &&
-                    y > 0 && y <= _size.y)
-                {
-                    // Button-clicked callback.
-                    _callback->trigger(this);
-                }
+        switch (evt)
+        {
+        case Touch::TOUCH_PRESS:
+            _state = Control::STATE_ACTIVE;
+            _dirty = true;
+            return _consumeTouchEvents;
+        case Touch::TOUCH_RELEASE:
+            if (_callback &&
+                x > 0 && x <= _size.x &&
+                y > 0 && y <= _size.y)
+            {
+                // Button-clicked callback.
+                _callback->trigger(this);
                 setState(Control::STATE_NORMAL);
-                break;
+                _dirty = true;
+                return _consumeTouchEvents;
             }
+            _dirty = true;
+            setState(Control::STATE_NORMAL);
+            break;
         }
+
+        return _consumeTouchEvents;
     }
 }

+ 11 - 11
gameplay/src/Button.h

@@ -14,19 +14,19 @@ class Button : public Label
     class Callback;
 
 public:
-    Button();
-    virtual ~Button();
-
     static Button* create(Theme::Style* style, Properties* properties);
     static Button* create(const char* id, unsigned int x, unsigned int y, unsigned int width, unsigned int height);
     static Button* getButton(const char* id);
 
     template <class ClassType>
-    void setCallback(ClassType* instance, void (ClassType::*callbackMethod)(Button*));
+    void setCallback(ClassType* instance, void (ClassType::*callbackMethod)(Control*));
 
-    void touchEvent(Touch::TouchEvent evt, int x, int y, unsigned int contactIndex);
+    bool touchEvent(Touch::TouchEvent evt, int x, int y, unsigned int contactIndex);
 
 protected:
+    Button();
+    virtual ~Button();
+
     Callback* _callback;
 
 private:
@@ -36,16 +36,16 @@ private:
     {
     public:
         virtual ~Callback() { }
-        virtual void trigger(Button* button) = 0;
+        virtual void trigger(Control* button) = 0;
     };
 
     template <class ClassType>
     class CallbackImpl : public Callback
     {
-        typedef void (ClassType::*CallbackMethod)(Button*);
+        typedef void (ClassType::*CallbackMethod)(Control*);
     public:
         CallbackImpl(ClassType* instance, CallbackMethod method);
-        void trigger(Button* button);
+        void trigger(Control* control);
     private:
         ClassType* _instance;
         CallbackMethod _method;
@@ -59,15 +59,15 @@ Button::CallbackImpl<ClassType>::CallbackImpl(ClassType* instance, CallbackMetho
 }
 
 template <class ClassType>
-void Button::setCallback(ClassType* instance, void (ClassType::*callbackMethod)(Button*))
+void Button::setCallback(ClassType* instance, void (ClassType::*callbackMethod)(Control*))
 {
     _callback = new CallbackImpl<ClassType>(instance, callbackMethod);
 }
 
 template <class ClassType>
-void Button::CallbackImpl<ClassType>::trigger(Button* button)
+void Button::CallbackImpl<ClassType>::trigger(Control* control)
 {
-    (_instance->*_method)(button);
+    (_instance->*_method)(control);
 }
 
 }

+ 56 - 49
gameplay/src/CheckBox.cpp

@@ -22,27 +22,13 @@ CheckBox::~CheckBox()
 
 CheckBox* CheckBox::create(Theme::Style* style, Properties* properties)
 {
-    CheckBox* checkbox = new CheckBox();
-    checkbox->_style = style;
-    properties->getVector2("position", &checkbox->_position);
-    properties->getVector2("size", &checkbox->_size);
-    checkbox->_checked = properties->getBool("checked");
-
-    const char* id = properties->getId();
-    if (id)
-    {
-        checkbox->_id = id;
-    }
-
-    const char* text = properties->getString("text");
-    if (text)
-    {
-        checkbox->_text = text;
-    }
-
-    __checkBoxes.push_back(checkbox);
+    CheckBox* checkBox = new CheckBox();
+    checkBox->init(style, properties);
+    properties->getVector2("iconSize", &checkBox->_iconSize);
+    checkBox->_checked = properties->getBool("checked");
+    __checkBoxes.push_back(checkBox);
 
-    return checkbox;
+    return checkBox;
 }
 
 CheckBox* CheckBox::getCheckBox(const char* id)
@@ -50,18 +36,28 @@ CheckBox* CheckBox::getCheckBox(const char* id)
     std::vector<CheckBox*>::const_iterator it;
     for (it = __checkBoxes.begin(); it < __checkBoxes.end(); it++)
     {
-        CheckBox* checkbox = *it;
-        if (strcmp(id, checkbox->getID()) == 0)
+        CheckBox* checkBox = *it;
+        if (strcmp(id, checkBox->getID()) == 0)
         {
-            return checkbox;
+            return checkBox;
         }
     }
 
     return NULL;
 }
 
-void CheckBox::touchEvent(Touch::TouchEvent evt, int x, int y, unsigned int contactIndex)
+bool CheckBox::isChecked()
 {
+    return _checked;
+}
+
+bool CheckBox::touchEvent(Touch::TouchEvent evt, int x, int y, unsigned int contactIndex)
+{
+    if (!isEnabled())
+    {
+        return false;
+    }
+
     switch (evt)
     {
     case Touch::TOUCH_RELEASE:
@@ -78,7 +74,35 @@ void CheckBox::touchEvent(Touch::TouchEvent evt, int x, int y, unsigned int cont
         break;
     }
 
-    Button::touchEvent(evt, x, y, contactIndex);
+    return Button::touchEvent(evt, x, y, contactIndex);
+}
+
+void CheckBox::update(const Vector2& position)
+{
+    Theme::Style::Overlay* overlay = _style->getOverlay(getOverlayType());
+    Theme::Icon* icon = overlay->getCheckBoxIcon();
+    Theme::Border border;
+    Theme::ContainerRegion* containerRegion = overlay->getContainerRegion();
+    if (containerRegion)
+    {
+        border = overlay->getContainerRegion()->getBorder();
+    }
+    Theme::Padding padding = _style->getPadding();
+
+    // Set up the text viewport.
+    float iconWidth = 0.0f;
+    if (icon)
+    {
+        iconWidth = icon->getSize().x;
+    }
+
+    Font* font = overlay->getFont();
+    Vector2 pos(position.x + _position.x + border.left + padding.left + iconWidth,
+            position.y + _position.y + border.top + padding.top);
+
+    _viewport.set(pos.x, pos.y,
+        _size.x - border.left - padding.left - border.right - padding.right - iconWidth,
+        _size.y - border.top - padding.top - border.bottom - padding.bottom - overlay->getFontSize());
 }
 
 void CheckBox::drawSprites(SpriteBatch* spriteBatch, const Vector2& position)
@@ -97,7 +121,12 @@ void CheckBox::drawSprites(SpriteBatch* spriteBatch, const Vector2& position)
         }
         const Theme::Padding padding = _style->getPadding();
 
-        const Vector2 size = icon->getSize();
+        Vector2& size = _iconSize;
+        if (_iconSize.isZero())
+        {
+            size = icon->getSize();
+        }
+
         const Vector4 color = icon->getColor();
 
         Vector2 pos(position.x + _position.x + border.left + padding.left,
@@ -120,33 +149,11 @@ void CheckBox::drawText(const Vector2& position)
 {
     // TODO: Batch all labels that use the same font.
     Theme::Style::Overlay* overlay = _style->getOverlay(getOverlayType());
-    Theme::Icon* icon = overlay->getCheckBoxIcon();
-    Theme::Border border;
-    Theme::ContainerRegion* containerRegion = overlay->getContainerRegion();
-    if (containerRegion)
-    {
-        border = overlay->getContainerRegion()->getBorder();
-    }
-    Theme::Padding padding = _style->getPadding();
-
-    // Set up the text viewport.
-    float iconWidth = 0.0f;
-    if (icon)
-    {
-        iconWidth = icon->getSize().x;
-    }
-
     Font* font = overlay->getFont();
-    Vector2 pos(position.x + _position.x + border.left + padding.left + iconWidth,
-            position.y + _position.y + border.top + padding.top);
-
-    Rectangle viewport(pos.x, pos.y,
-        _size.x - border.left - padding.left - border.right - padding.right - iconWidth,
-        _size.y - border.top - padding.top - border.bottom - padding.bottom - font->getSize());
     
     // Draw the text.
     font->begin();
-    font->drawText(_text.c_str(), viewport, overlay->getTextColor(), overlay->getFontSize(), overlay->getTextAlignment(), true, overlay->getTextRightToLeft());
+    font->drawText(_text.c_str(), _viewport, overlay->getTextColor(), overlay->getFontSize(), overlay->getTextAlignment(), true, overlay->getTextRightToLeft());
     font->end();
 
     _dirty = false;

+ 9 - 5
gameplay/src/CheckBox.h

@@ -12,21 +12,25 @@ namespace gameplay
 class CheckBox : public Button
 {
 public:
-    CheckBox();
-    ~CheckBox();
-
     static CheckBox* create(Theme::Style* style, Properties* properties);
     static CheckBox* getCheckBox(const char* id);
 
-    void touchEvent(Touch::TouchEvent evt, int x, int y, unsigned int contactIndex);
+    bool isChecked();
+
+    bool touchEvent(Touch::TouchEvent evt, int x, int y, unsigned int contactIndex);
+
+    void update(const Vector2& position);
 
     void drawSprites(SpriteBatch* spriteBatch, const Vector2& position);
     void drawText(const Vector2& position);
 
-private:
+protected:
+    CheckBox();
     CheckBox(const CheckBox& copy);
+    ~CheckBox();
 
     bool _checked;
+    Vector2 _iconSize;
 };
 
 }

+ 17 - 15
gameplay/src/Container.cpp

@@ -33,7 +33,7 @@ namespace gameplay
         SAFE_RELEASE(_layout);
     }
 
-    Container* Container::create(const char* id, Layout::Type type)
+    Container* Container::create(Layout::Type type)
     {
         Layout* layout = NULL;
         switch(type)
@@ -49,7 +49,6 @@ namespace gameplay
         }
 
         Container* container = new Container();
-        container->_id = id;
         container->_layout = layout;
 
         __containers.push_back(container);
@@ -59,14 +58,9 @@ namespace gameplay
 
     Container* Container::create(Theme::Style* style, Properties* properties, Theme* theme)
     {
-        const char* id = properties->getId();
         const char* layoutString = properties->getString("layout");
-        Container* container = Container::create(id, getLayoutType(layoutString));
-
-        container->_style = style;
-        properties->getVector2("position", &container->_position);
-        properties->getVector2("size", &container->_size);
-
+        Container* container = Container::create(getLayoutType(layoutString));
+        container->init(style, properties);
         container->addControls(theme, properties);
 
         return container;
@@ -226,8 +220,6 @@ namespace gameplay
         {
             _layout->update(this);
         }
-
-        _dirty = false;
     }
 
     void Container::drawSprites(SpriteBatch* spriteBatch, const Vector2& position)
@@ -277,8 +269,10 @@ namespace gameplay
         return false;
     }
 
-    void Container::touchEvent(Touch::TouchEvent evt, int x, int y, unsigned int contactIndex)
+    bool Container::touchEvent(Touch::TouchEvent evt, int x, int y, unsigned int contactIndex)
     {
+        bool eventConsumed = false;
+
         std::vector<Control*>::const_iterator it;
         for (it = _controls.begin(); it < _controls.end(); it++)
         {
@@ -287,25 +281,28 @@ namespace gameplay
             const Vector2& position = control->getPosition();
             
             if (control->getState() != Control::STATE_NORMAL ||
-                (x >= position.x &&
+                (evt == Touch::TOUCH_PRESS &&
+                 x >= position.x &&
                  x <= position.x + size.x &&
                  y >= position.y &&
                  y <= position.y + size.y))
             {
                 // Pass on the event's position relative to the control.
-                control->touchEvent(evt, x - position.x, y - position.y, contactIndex);
+                eventConsumed |= control->touchEvent(evt, x - position.x, y - position.y, contactIndex);
             }
         }
 
         switch (evt)
         {
         case Touch::TOUCH_PRESS:
-            setState(Control::STATE_ACTIVE);
+            setState(Control::STATE_FOCUS);
             break;
         case Touch::TOUCH_RELEASE:
             setState(Control::STATE_NORMAL);
             break;
         }
+
+        return (_consumeTouchEvents | eventConsumed);
     }
 
     void Container::keyEvent(Keyboard::KeyEvent evt, int key)
@@ -320,6 +317,11 @@ namespace gameplay
 
     Layout::Type Container::getLayoutType(const char* layoutString)
     {
+        if (!layoutString)
+        {
+            return Layout::LAYOUT_ABSOLUTE;
+        }
+
         std::string layoutName(layoutString);
         std::transform(layoutName.begin(), layoutName.end(), layoutName.begin(), (int(*)(int))toupper);
         if (layoutName == "LAYOUT_ABSOLUTE")

+ 2 - 2
gameplay/src/Container.h

@@ -13,7 +13,7 @@ public:
     /**
      * A Container's layout type must be specified at creation time.
      */
-    static Container* create(const char* id, Layout::Type type);
+    static Container* create(Layout::Type type);
     static Container* create(Theme::Style* style, Properties* properties, Theme* theme);
     static Container* getContainer(const char* id);
 
@@ -69,7 +69,7 @@ public:
     virtual void drawSprites(SpriteBatch* spriteBatch, const Vector2& position);
     virtual void drawText(const Vector2& position);
 
-    virtual void touchEvent(Touch::TouchEvent evt, int x, int y, unsigned int contactIndex);
+    virtual bool touchEvent(Touch::TouchEvent evt, int x, int y, unsigned int contactIndex);
 
     virtual void keyEvent(Keyboard::KeyEvent evt, int key);
 

+ 59 - 3
gameplay/src/Control.cpp

@@ -5,7 +5,7 @@ namespace gameplay
 {
     Control::Control()
         : _id(""), _state(Control::STATE_NORMAL), _size(Vector2::zero()), _position(Vector2::zero()), _border(Vector2::zero()), _padding(Vector2::zero()),
-          _autoWidth(true), _autoHeight(true), _dirty(true)
+          _autoWidth(true), _autoHeight(true), _dirty(true), _consumeTouchEvents(true)
     {
     }
 
@@ -17,6 +17,22 @@ namespace gameplay
     {
     }
 
+    void Control::init(Theme::Style* style, Properties* properties)
+    {
+        _style = style;
+
+        properties->getVector2("position", &_position);
+        properties->getVector2("size", &_size);
+
+        _state = Control::getStateFromString(properties->getString("state"));
+
+        const char* id = properties->getId();
+        if (id)
+        {
+            _id = id;
+        }
+    }
+
     const char* Control::getID()
     {
         return _id.c_str();
@@ -86,7 +102,7 @@ namespace gameplay
 
     bool Control::isEnabled()
     {
-        return _state == STATE_DISABLED;
+        return _state != STATE_DISABLED;
     }
 
     Theme::Style::OverlayType Control::getOverlayType() const
@@ -99,14 +115,27 @@ namespace gameplay
             return Theme::Style::OVERLAY_FOCUS;
         case Control::STATE_ACTIVE:
             return Theme::Style::OVERLAY_ACTIVE;
+        case Control::STATE_DISABLED:
+            return Theme::Style::OVERLAY_DISABLED;
         default:
             return Theme::Style::OVERLAY_NORMAL;
         }
     }
 
-    void Control::touchEvent(Touch::TouchEvent evt, int x, int y, unsigned int contactIndex)
+    void Control::setConsumeTouchEvents(bool consume)
+    {
+        _consumeTouchEvents = consume;
+    }
+    
+    bool Control::getConsumeTouchEvents()
+    {
+        return _consumeTouchEvents;
+    }
+
+    bool Control::touchEvent(Touch::TouchEvent evt, int x, int y, unsigned int contactIndex)
     {
         // Empty stub to be implemented by Button and its descendents.
+        return _consumeTouchEvents;
     }
 
     void Control::keyEvent(Keyboard::KeyEvent evt, int key)
@@ -192,4 +221,31 @@ namespace gameplay
     {
         return _dirty;
     }
+
+    Control::State Control::getStateFromString(const char* state)
+    {
+        if (!state)
+        {
+            return STATE_NORMAL;
+        }
+
+        if (strcmp(state, "STATE_NORMAL") == 0)
+        {
+            return STATE_NORMAL;
+        }
+        else if (strcmp(state, "STATE_ACTIVE") == 0)
+        {
+            return STATE_ACTIVE;
+        }
+        else if (strcmp(state, "STATE_FOCUS") == 0)
+        {
+            return STATE_FOCUS;
+        }
+        else if (strcmp(state, "STATE_DISABLED") == 0)
+        {
+            return STATE_DISABLED;
+        }
+
+        return STATE_NORMAL;
+    }
 }

+ 9 - 2
gameplay/src/Control.h

@@ -86,10 +86,13 @@ public:
 
     Theme::Style::OverlayType getOverlayType() const;
 
+    void setConsumeTouchEvents(bool consume);
+    bool getConsumeTouchEvents();
+
     /**
      * Defaults to empty stub.
      */
-    virtual void touchEvent(Touch::TouchEvent evt, int x, int y, unsigned int contactIndex);
+    virtual bool touchEvent(Touch::TouchEvent evt, int x, int y, unsigned int contactIndex);
 
     virtual void keyEvent(Keyboard::KeyEvent evt, int key);
 
@@ -111,13 +114,16 @@ public:
     void setStyle(Theme::Style* Style);
     Theme::Style* getStyle() const;
 
-    void themeChanged();
+    static State getStateFromString(const char* state);
 
 protected:
     Control();
     Control(const Control& copy);
     virtual ~Control();
 
+    // Set properties common to all Controls.
+    virtual void init(Theme::Style* style, Properties* properties);
+
     std::string _id;
     State _state;           // Determines overlay used during draw().
     Vector2 _size;
@@ -127,6 +133,7 @@ protected:
     bool _autoWidth;
     bool _autoHeight;
     bool _dirty;
+    bool _consumeTouchEvents;
     Theme::Style* _style;
 };
 

+ 5 - 0
gameplay/src/Font.cpp

@@ -1556,6 +1556,11 @@ SpriteBatch* Font::getSpriteBatch()
 
 Font::Justify Font::getJustifyFromString(const char* justify)
 {
+    if (!justify)
+    {
+        return Font::ALIGN_TOP_LEFT;
+    }
+
     if (strcmp(justify, "ALIGN_LEFT") == 0)
     {
         return Font::ALIGN_LEFT;

+ 37 - 18
gameplay/src/Form.cpp

@@ -59,28 +59,23 @@ namespace gameplay
         }
 
         // Create new form with given ID, theme and layout.
-        const char* id = formProperties->getId();
         const char* themeFile = formProperties->getString("theme");
         const char* layoutString = formProperties->getString("layout");
-        Form* form = Form::create(id, themeFile, getLayoutType(layoutString));
+        Form* form = Form::create(themeFile, getLayoutType(layoutString));
 
-        // Set form's position and dimensions.
-        formProperties->getVector2("position", &form->_position);
-        formProperties->getVector2("size", &form->_size);
-
-        // Set style from theme.
+        Theme* theme = form->getTheme();
         const char* styleName = formProperties->getString("style");
-        form->setStyle(form->getTheme()->getStyle(styleName));
+        form->init(theme->getStyle(styleName), formProperties);
 
         // Add all the controls to the form.
-        form->addControls(form->getTheme(), formProperties);
+        form->addControls(theme, formProperties);
 
         SAFE_DELETE(properties);
 
         return form;
     }
 
-    Form* Form::create(const char* id, const char* themeFile, Layout::Type type)
+    Form* Form::create(const char* themeFile, Layout::Type type)
     {
         Layout* layout;
         switch(type)
@@ -100,9 +95,7 @@ namespace gameplay
         assert(theme);
 
         Form* form = new Form();
-        form->_id = id;
         form->_layout = layout;
-        form->_frameBuffer = FrameBuffer::create(id);
         form->_theme = theme;
 
         __forms.push_back(form);
@@ -271,8 +264,14 @@ namespace gameplay
         // Bind the WorldViewProjection matrix
         material->setParameterAutoBinding("u_worldViewProjectionMatrix", RenderState::WORLD_VIEW_PROJECTION_MATRIX);
 
+        // Create a FrameBuffer if necessary.
+        if (!_frameBuffer)
+        {
+            _frameBuffer = FrameBuffer::create(_id.c_str());
+        }
+
         // Use the FrameBuffer to texture the quad.
-        if (_frameBuffer->getRenderTarget() == NULL)
+        if (!_frameBuffer->getRenderTarget())
         {
             RenderTarget* rt = RenderTarget::create(_id.c_str(), _size.x, _size.y);
             _frameBuffer->setRenderTarget(rt);
@@ -289,7 +288,7 @@ namespace gameplay
         SAFE_RELEASE(sampler);
     }
 
-    void Form::touchEventInternal(Touch::TouchEvent evt, int x, int y, unsigned int contactIndex)
+    bool Form::touchEventInternal(Touch::TouchEvent evt, int x, int y, unsigned int contactIndex)
     {
         // Check for a collision with each Form in __forms.
         // Pass the event on.
@@ -344,7 +343,21 @@ namespace gameplay
                             m.transformPoint(&point);
 
                             // Pass the touch event on.
-                            form->touchEvent(evt, point.x, size.y - point.y, contactIndex);
+                            const Vector2& size = form->getSize();
+                            const Vector2& position = form->getPosition();
+
+                            if (form->getState() == Control::STATE_FOCUS ||
+                                (evt == Touch::TOUCH_PRESS &&
+                                 point.x >= position.x &&
+                                 point.x <= position.x + size.x &&
+                                 point.y >= position.y &&
+                                 point.y <= position.y + size.y))
+                            {
+                               if (form->touchEvent(evt, point.x, size.y - point.y, contactIndex))
+                               {
+                                   return true;
+                               }
+                            }
                         }
                     }
                 }
@@ -354,18 +367,24 @@ namespace gameplay
                     const Vector2& size = form->getSize();
                     const Vector2& position = form->getPosition();
 
-                    if (form->getState() == Control::STATE_ACTIVE ||
-                        (x >= position.x &&
+                    if (form->getState() == Control::STATE_FOCUS ||
+                        (evt == Touch::TOUCH_PRESS &&
+                         x >= position.x &&
                          x <= position.x + size.x &&
                          y >= position.y &&
                          y <= position.y + size.y))
                     {
                         // Pass on the event's position relative to the form.
-                        form->touchEvent(evt, x - position.x, y - position.y, contactIndex);
+                        if (form->touchEvent(evt, x - position.x, y - position.y, contactIndex))
+                        {
+                            return true;
+                        }
                     }
                 }
             }
         }
+
+        return false;
     }
 
     void Form::keyEventInternal(Keyboard::KeyEvent evt, int key)

+ 2 - 2
gameplay/src/Form.h

@@ -23,7 +23,7 @@ public:
      * Create from .form file.
      */
     static Form* create(const char* path);
-    static Form* create(const char* id, const char* textureFile, Layout::Type type);
+    static Form* create(const char* textureFile, Layout::Type type);
     static Form* getForm(const char* id);
 
     void setTheme(Theme* theme);
@@ -53,7 +53,7 @@ private:
     void draw(SpriteBatch* spriteBatch);
     void draw(SpriteBatch* spriteBatch, const Vector2& position);
 
-    static void touchEventInternal(Touch::TouchEvent evt, int x, int y, unsigned int contactIndex);
+    static bool touchEventInternal(Touch::TouchEvent evt, int x, int y, unsigned int contactIndex);
 
     static void keyEventInternal(Keyboard::KeyEvent evt, int key);
 

+ 11 - 0
gameplay/src/Label.cpp

@@ -41,6 +41,17 @@ namespace gameplay
         return label;
     }
 
+    void Label::init(Theme::Style* style, Properties* properties)
+    {
+        Control::init(style, properties);
+
+        const char* text = properties->getString("text");
+        if (text)
+        {
+            _text = text;
+        }
+    }
+
     Label* Label::getLabel(const char* id)
     {
         std::vector<Label*>::const_iterator it;

+ 2 - 0
gameplay/src/Label.h

@@ -26,6 +26,8 @@ protected:
     Label(const Label& copy);
     virtual ~Label();
 
+    virtual void init(Theme::Style* style, Properties* properties);
+
     std::string _text;
     Rectangle _viewport;
 };

+ 14 - 23
gameplay/src/ParticleEmitter.cpp

@@ -2,6 +2,7 @@
 #include "ParticleEmitter.h"
 #include "Game.h"
 #include "Node.h"
+#include "Scene.h"
 #include "Quaternion.h"
 #include "Properties.h"
 
@@ -58,7 +59,7 @@ ParticleEmitter* ParticleEmitter::create(const char* textureFile, TextureBlendin
 
     // Use default SpriteBatch material.
     SpriteBatch* batch =  SpriteBatch::create(texture, NULL, particleCountMax);
-    texture->release(); // batch owns the texture
+    texture->release(); // batch owns the texture.
     assert(batch);
 
     ParticleEmitter* emitter = new ParticleEmitter(batch, particleCountMax);
@@ -890,30 +891,20 @@ void ParticleEmitter::draw()
         // Begin sprite batch drawing
         _spriteBatch->begin();
 
-        // Which draw call we use depends on whether particles are rotating.
-        if (_rotationPerParticleSpeedMin == 0.0f && _rotationPerParticleSpeedMax == 0.0f)
-        {
-            // No rotation.
-            for (unsigned int i = 0; i < _particleCount; i++)
-            {
-                Particle* p = &_particles[i];
-                _spriteBatch->draw(p->_position.x, p->_position.y, p->_position.z, p->_size, p->_size,
-                                   _spriteTextureCoords[p->_frame * 4], _spriteTextureCoords[p->_frame * 4 + 1], _spriteTextureCoords[p->_frame * 4 + 2], _spriteTextureCoords[p->_frame * 4 + 3], p->_color,
-                                   true);
-            }
-        }
-        else
+        // 2D Rotation.
+        Vector2 pivot(0.5f, 0.5f);
+
+        // 3D Rotation so that particles always face the camera.
+        Vector3 right = _node->getScene()->getActiveCamera()->getNode()->getRightVector();
+        Vector3 forward = _node->getScene()->getActiveCamera()->getNode()->getUpVector();
+
+        for (unsigned int i = 0; i < _particleCount; i++)
         {
-            // Rotation.
-            Vector2 pivot(0.5f, 0.5f);
+            Particle* p = &_particles[i];
 
-            for (unsigned int i = 0; i < _particleCount; i++)
-            {
-                Particle* p = &_particles[i];
-                _spriteBatch->draw(p->_position, p->_size, p->_size,
-                                   _spriteTextureCoords[p->_frame * 4], _spriteTextureCoords[p->_frame * 4 + 1], _spriteTextureCoords[p->_frame * 4 + 2], _spriteTextureCoords[p->_frame * 4 + 3], p->_color, pivot, p->_angle,
-                                   true);
-            }
+            _spriteBatch->draw(p->_position, right, forward, p->_size, p->_size,
+                               _spriteTextureCoords[p->_frame * 4], _spriteTextureCoords[p->_frame * 4 + 1], _spriteTextureCoords[p->_frame * 4 + 2], _spriteTextureCoords[p->_frame * 4 + 3],
+                               p->_color, pivot, p->_angle);
         }
 
         // Render.

+ 4 - 2
gameplay/src/PlatformWin32.cpp

@@ -663,8 +663,10 @@ void Platform::displayKeyboard(bool display)
 
 void Platform::touchEventInternal(Touch::TouchEvent evt, int x, int y, unsigned int contactIndex)
 {
-    Game::getInstance()->touchEvent(evt, x, y, contactIndex);
-    Form::touchEventInternal(evt, x, y, contactIndex);
+    if (!Form::touchEventInternal(evt, x, y, contactIndex))
+    {
+        Game::getInstance()->touchEvent(evt, x, y, contactIndex);
+    }
 }
 
 void Platform::keyEventInternal(Keyboard::KeyEvent evt, int key)

+ 40 - 42
gameplay/src/RadioButton.cpp

@@ -23,27 +23,16 @@ RadioButton::~RadioButton()
 RadioButton* RadioButton::create(Theme::Style* style, Properties* properties)
 {
     RadioButton* radioButton = new RadioButton();
-    radioButton->_style = style;
-    properties->getVector2("position", &radioButton->_position);
-    properties->getVector2("size", &radioButton->_size);
+    radioButton->init(style, properties);
+
+    properties->getVector2("iconSize", &radioButton->_iconSize);
+
     if (properties->getBool("selected"))
     {
         RadioButton::clearSelected(radioButton->_groupId);
         radioButton->_selected = true;
     }
 
-    const char* id = properties->getId();
-    if (id)
-    {
-        radioButton->_id = id;
-    }
-
-    const char* text = properties->getString("text");
-    if (text)
-    {
-        radioButton->_text = text;
-    }
-
     const char* groupId = properties->getString("group");
     if (groupId)
     {
@@ -70,36 +59,35 @@ RadioButton* RadioButton::getRadioButton(const char* id)
     return NULL;
 }
 
-void RadioButton::touchEvent(Touch::TouchEvent evt, int x, int y, unsigned int contactIndex)
+bool RadioButton::touchEvent(Touch::TouchEvent evt, int x, int y, unsigned int contactIndex)
 {
-    switch (evt)
+    if (isEnabled())
     {
-    case Touch::TOUCH_PRESS:
-        {
-            _state = Control::STATE_ACTIVE;
-            _dirty = true;
-        }
-        break;
-    case Touch::TOUCH_RELEASE:
+        switch (evt)
         {
-            if (_state == Control::STATE_ACTIVE)
+        case Touch::TOUCH_RELEASE:
             {
-                if (x > 0 && x <= _size.x &&
-                    y > 0 && y <= _size.y)
+                if (_state == Control::STATE_ACTIVE)
                 {
-                    if (_callback)
+                    if (x > 0 && x <= _size.x &&
+                        y > 0 && y <= _size.y)
                     {
-                        _callback->trigger(this);
+                        if (_callback)
+                        {
+                            _callback->trigger(this);
+                        }
+                        RadioButton::clearSelected(_groupId);
+                        _selected = true;
                     }
-                    RadioButton::clearSelected(_groupId);
-                    _selected = true;
                 }
-                setState(Control::STATE_NORMAL);
-
             }
+            break;
         }
-        break;
+
+        return Button::touchEvent(evt, x, y, contactIndex);
     }
+
+    return false;
 }
 
 void RadioButton::clearSelected(const std::string& groupId)
@@ -131,7 +119,11 @@ void RadioButton::drawSprites(SpriteBatch* spriteBatch, const Vector2& position)
         }
         const Theme::Padding padding = _style->getPadding();
 
-        const Vector2 size = icon->getSize();
+        Vector2& size = _iconSize;
+        if (_iconSize.isZero())
+        {
+            size = icon->getSize();
+        }
         const Vector4 color = icon->getColor();
 
         Vector2 pos(position.x + _position.x + border.left + padding.left,
@@ -150,16 +142,15 @@ void RadioButton::drawSprites(SpriteBatch* spriteBatch, const Vector2& position)
     }
 }
 
-void RadioButton::drawText(const Vector2& position)
+void RadioButton::update(const Vector2& position)
 {
-    // TODO: Batch all labels that use the same font.
     Theme::Style::Overlay* overlay = _style->getOverlay(getOverlayType());
-    Theme::Icon* icon = overlay->getRadioButtonIcon();
+    Theme::Icon* icon = overlay->getCheckBoxIcon();
     Theme::Border border;
     Theme::ContainerRegion* containerRegion = overlay->getContainerRegion();
     if (containerRegion)
     {
-        border = containerRegion->getBorder();
+        border = overlay->getContainerRegion()->getBorder();
     }
     Theme::Padding padding = _style->getPadding();
 
@@ -174,13 +165,20 @@ void RadioButton::drawText(const Vector2& position)
     Vector2 pos(position.x + _position.x + border.left + padding.left + iconWidth,
             position.y + _position.y + border.top + padding.top);
 
-    Rectangle viewport(pos.x, pos.y,
+    _viewport.set(pos.x, pos.y,
         _size.x - border.left - padding.left - border.right - padding.right - iconWidth,
-        _size.y - border.top - padding.top - border.bottom - padding.bottom - font->getSize());
+        _size.y - border.top - padding.top - border.bottom - padding.bottom - overlay->getFontSize());
+}
+
+void RadioButton::drawText(const Vector2& position)
+{
+    // TODO: Batch all labels that use the same font.
+    Theme::Style::Overlay* overlay = _style->getOverlay(getOverlayType());
+    Font* font = overlay->getFont();
     
     // Draw the text.
     font->begin();
-    font->drawText(_text.c_str(), viewport, overlay->getTextColor(), overlay->getFontSize(), overlay->getTextAlignment(), true, overlay->getTextRightToLeft());
+    font->drawText(_text.c_str(), _viewport, overlay->getTextColor(), overlay->getFontSize(), overlay->getTextAlignment(), true, overlay->getTextRightToLeft());
     font->end();
 
     _dirty = false;

+ 4 - 1
gameplay/src/RadioButton.h

@@ -17,7 +17,9 @@ public:
     static RadioButton* create(Theme::Style* style, Properties* properties);
     static RadioButton* getRadioButton(const char* id);
 
-    void touchEvent(Touch::TouchEvent evt, int x, int y, unsigned int contactIndex);
+    bool touchEvent(Touch::TouchEvent evt, int x, int y, unsigned int contactIndex);
+
+    void update(const Vector2& position);
 
     void drawSprites(SpriteBatch* spriteBatch, const Vector2& position);
     void drawText(const Vector2& position);
@@ -30,6 +32,7 @@ private:
 
     std::string _groupId;
     bool _selected;
+    Vector2 _iconSize;
 };
 
 }

+ 100 - 48
gameplay/src/Slider.cpp

@@ -16,27 +16,13 @@ Slider::~Slider()
 Slider* Slider::create(Theme::Style* style, Properties* properties)
 {
     Slider* slider = new Slider();
+    slider->init(style, properties);
 
-    slider->_style = style;
-    properties->getVector2("position", &slider->_position);
-    properties->getVector2("size", &slider->_size);
     slider->_min = properties->getFloat("min");
     slider->_max = properties->getFloat("max");
     slider->_value = properties->getFloat("value");
     slider->_step = properties->getFloat("step");
 
-    const char* id = properties->getId();
-    if (id)
-    {
-        slider->_id = id;
-    }
-
-    const char* text = properties->getString("text");
-    if (text)
-    {
-        slider->_text = text;
-    }
-
     __sliders.push_back(slider);
 
     return slider;
@@ -64,49 +50,115 @@ Slider* Slider::getSlider(const char* id)
     return NULL;
 }
 
-void Slider::touchEvent(Touch::TouchEvent evt, int x, int y, unsigned int contactIndex)
+void Slider::setMin(float min)
 {
-    Button::touchEvent(evt, x, y, contactIndex);
+    _min = min;
+}
 
-    if (_state == STATE_ACTIVE &&
-        x > 0 && x <= _size.x &&
-        y > 0 && y <= _size.y)
-    {
-        // Horizontal case.
-        Theme::Border border;
-        Theme::ContainerRegion* containerRegion = _style->getOverlay(getOverlayType())->getContainerRegion();
-        if (containerRegion)
-        {
-            border = containerRegion->getBorder();
-        }
-        Theme::Padding padding = _style->getPadding();
+float Slider::getMin()
+{
+    return _min;
+}
 
-        const Theme::Style::Overlay* overlay = _style->getOverlay(getOverlayType());
-        const Theme::SliderIcon* icon = overlay->getSliderIcon();
+void Slider::setMax(float max)
+{
+    _max = max;
+}
 
-        const Vector2 minCapSize = icon->getMinCapSize();
-        const Vector2 maxCapSize = icon->getMaxCapSize();
+float Slider::getMax()
+{
+    return _max;
+}
 
-        float markerPosition = ((float)x - maxCapSize.x - border.left - padding.left) /
-                               (_size.x - border.left - border.right - padding.left - padding.right - minCapSize.x - maxCapSize.x);
-        if (markerPosition > 1.0f)
-        {
-            markerPosition = 1.0f;
-        }
-        else if (markerPosition < 0.0f)
-        {
-            markerPosition = 0.0f;
-        }
+void Slider::setStep(float step)
+{
+    _step = step;
+}
+
+float Slider::getStep()
+{
+    return _step;
+}
+
+float Slider::getValue()
+{
+    return _value;
+}
 
-        _value = markerPosition * _max;
-        if (_step > 0.0f)
+void Slider::setValue(float value)
+{
+    _value = value;
+}
+
+bool Slider::touchEvent(Touch::TouchEvent evt, int x, int y, unsigned int contactIndex)
+{
+    if (!isEnabled())
+    {
+        return false;
+    }
+
+    bool consumeEvent = false;
+
+    switch (evt)
+    {
+    case Touch::TOUCH_PRESS:
+        _state = Control::STATE_ACTIVE;
+        _dirty = true;
+        // Fall through to calculate new value.
+
+    case Touch::TOUCH_MOVE:
+    case Touch::TOUCH_RELEASE:
+        if (_state == STATE_ACTIVE &&
+            x > 0 && x <= _size.x &&
+            y > 0 && y <= _size.y)
         {
-            float stepDistance = _step / (_max - _min);
+            // Horizontal case.
+            Theme::Border border;
+            Theme::ContainerRegion* containerRegion = _style->getOverlay(getOverlayType())->getContainerRegion();
+            if (containerRegion)
+            {
+                border = containerRegion->getBorder();
+            }
+            Theme::Padding padding = _style->getPadding();
+
+            const Theme::Style::Overlay* overlay = _style->getOverlay(getOverlayType());
+            const Theme::SliderIcon* icon = overlay->getSliderIcon();
+
+            const Vector2 minCapSize = icon->getMinCapSize();
+            const Vector2 maxCapSize = icon->getMaxCapSize();
+
+            float markerPosition = ((float)x - maxCapSize.x - border.left - padding.left) /
+                                    (_size.x - border.left - border.right - padding.left - padding.right - minCapSize.x - maxCapSize.x);
+            if (markerPosition > 1.0f)
+            {
+                markerPosition = 1.0f;
+            }
+            else if (markerPosition < 0.0f)
+            {
+                markerPosition = 0.0f;
+            }
+
+            float oldValue = _value;
+            _value = markerPosition * _max;
+            if (_step > 0.0f)
+            {
+                float stepDistance = _step / (_max - _min);
             
-            int numSteps = round(_value / _step);
-            _value = _step * numSteps;
+                int numSteps = round(_value / _step);
+                _value = _step * numSteps;
+            }
+
+            // Call the callback if our value changed.
+            if (_callback && _value != oldValue)
+            {
+                _callback->trigger(this);
+            }
+
+            _dirty = true;
         }
     }
+
+    return consumeEvent;
 }
 
 void Slider::drawSprites(SpriteBatch* spriteBatch, const Vector2& position)

+ 11 - 2
gameplay/src/Slider.h

@@ -17,13 +17,22 @@ public:
     static Slider* create(const char* id, float min, float max, float defaultPosition = 0.0f, float step = 1.0f);
     static Slider* getSlider(const char* id);
 
-    void touchEvent(Touch::TouchEvent evt, int x, int y, unsigned int contactIndex);
+    void setMin(float min);
+    float getMin();
 
-    void drawSprites(SpriteBatch* spriteBatch, const Vector2& position);
+    void setMax(float max);
+    float getMax();
+
+    void setStep(float step);
+    float getStep();
 
     void setValue(float value);
     float getValue();
 
+    bool touchEvent(Touch::TouchEvent evt, int x, int y, unsigned int contactIndex);
+
+    void drawSprites(SpriteBatch* spriteBatch, const Vector2& position);
+
 protected:
     Slider();
     ~Slider();

+ 48 - 51
gameplay/src/TextBox.cpp

@@ -21,23 +21,9 @@ TextBox::~TextBox()
 TextBox* TextBox::create(Theme::Style* style, Properties* properties)
 {
     TextBox* textBox = new TextBox();
-    textBox->_style = style;
-    properties->getVector2("position", &textBox->_position);
-    properties->getVector2("size", &textBox->_size);
-
-    const char* id = properties->getId();
-    if (id)
-    {
-        textBox->_id = id;
-    }
-
-    const char* text = properties->getString("text");
-    if (text)
-    {
-        textBox->_text = text;
-    }
-
+    textBox->init(style, properties);
     __textBoxes.push_back(textBox);
+
     return textBox;
 }
 
@@ -71,44 +57,55 @@ void TextBox::setCursorLocation(int x, int y)
                        y - border.top - padding.top + _viewport.y);
 }
 
-void TextBox::touchEvent(Touch::TouchEvent evt, int x, int y, unsigned int contactIndex)
+bool TextBox::touchEvent(Touch::TouchEvent evt, int x, int y, unsigned int contactIndex)
 {   
-    if (_state != STATE_DISABLED)
+    if (!isEnabled())
     {
-        switch (evt)
+        return false;
+    }
+
+    switch (evt)
+    {
+    case Touch::TOUCH_PRESS: 
+        if (_state == STATE_NORMAL)
         {
-        case Touch::TOUCH_PRESS: 
-            if (_state == STATE_NORMAL)
-            {
-                _state = STATE_ACTIVE;
-                Game::getInstance()->displayKeyboard(true);
-            }
-            break;
-        case Touch::TOUCH_MOVE:
-            if (_state == STATE_FOCUS &&
-                x > 0 && x <= _size.x &&
-                y > 0 && y <= _size.y)
-            {
-                setCursorLocation(x, y);
-                _dirty = true;
-            }
-            break;
-        case Touch::TOUCH_RELEASE:
-            if (x > 0 && x <= _size.x &&
-                y > 0 && y <= _size.y)
-            {
-                setCursorLocation(x, y);
-                _state = STATE_FOCUS;
-                _dirty = true;
-            }
-            else
-            {
-                _state = STATE_NORMAL;
-                Game::getInstance()->displayKeyboard(false);
-            }
-            break;
+            _state = STATE_ACTIVE;
+            Game::getInstance()->displayKeyboard(true);
+            _dirty = true;
+            return _consumeTouchEvents;
+        }
+        else if (!(x > 0 && x <= _size.x &&
+                    y > 0 && y <= _size.y))
+        {
+            _state = STATE_NORMAL;
+            Game::getInstance()->displayKeyboard(false);
+            _dirty = true;
+            return _consumeTouchEvents;
+        }
+        break;
+    case Touch::TOUCH_MOVE:
+        if (_state == STATE_FOCUS &&
+            x > 0 && x <= _size.x &&
+            y > 0 && y <= _size.y)
+        {
+            setCursorLocation(x, y);
+            _dirty = true;
+            return _consumeTouchEvents;
         }
+        break;
+    case Touch::TOUCH_RELEASE:
+        if (x > 0 && x <= _size.x &&
+            y > 0 && y <= _size.y)
+        {
+            setCursorLocation(x, y);
+            _state = STATE_FOCUS;
+            _dirty = true;
+            return _consumeTouchEvents;
+        }
+        break;
     }
+
+    return _consumeTouchEvents;
 }
 
 void TextBox::keyEvent(Keyboard::KeyEvent evt, int key)
@@ -274,8 +271,6 @@ void TextBox::update(const Vector2& position)
         font->getIndexAtLocation(_text.c_str(), _viewport, overlay->getFontSize(), _cursorLocation, &_cursorLocation,
             overlay->getTextAlignment(), true, overlay->getTextRightToLeft());
     }
-
-    _dirty = false;
 }
 
 void TextBox::drawSprites(SpriteBatch* spriteBatch, const Vector2& position)
@@ -302,6 +297,8 @@ void TextBox::drawSprites(SpriteBatch* spriteBatch, const Vector2& position)
             spriteBatch->draw(_cursorLocation.x - (size.x / 2.0f), _cursorLocation.y, size.x, fontSize, uvs.u1, uvs.v1, uvs.u2, uvs.v2, color);
         }
     }
+
+    _dirty = false;
 }
 
 }

+ 1 - 1
gameplay/src/TextBox.h

@@ -15,7 +15,7 @@ public:
     static TextBox* create(Theme::Style* style, Properties* properties);
     static TextBox* getTextBox(const char* id);
 
-    void touchEvent(Touch::TouchEvent evt, int x, int y, unsigned int contactIndex);
+    bool touchEvent(Touch::TouchEvent evt, int x, int y, unsigned int contactIndex);
 
     void keyEvent(Keyboard::KeyEvent evt, int key);
 

+ 29 - 5
gameplay/src/Theme.cpp

@@ -148,8 +148,8 @@ namespace gameplay
                 Vector4 maxCapRegion;
                 Vector4 trackRegion;
                 Vector4 markerRegion;
-                space->getVector4("leftCapRegion", &minCapRegion);
-                space->getVector4("rightCapRegion", &maxCapRegion);
+                space->getVector4("minCapRegion", &minCapRegion);
+                space->getVector4("maxCapRegion", &maxCapRegion);
                 space->getVector4("trackRegion", &trackRegion);
                 space->getVector4("markerRegion", &markerRegion);
                 
@@ -224,6 +224,7 @@ namespace gameplay
                 Theme::Style::Overlay* normal = NULL;
                 Theme::Style::Overlay* focus = NULL;
                 Theme::Style::Overlay* active = NULL;
+                Theme::Style::Overlay* disabled = NULL;
 
                 // Need to load OVERLAY_NORMAL first so that the other overlays can inherit from it.
                 Properties* innerSpace = space->getNextNamespace();
@@ -398,7 +399,6 @@ namespace gameplay
                             containerRegion = normal->getContainerRegion();
                         }
 
-                        
                         if (strcmp(innerSpacename, "focus") == 0)
                         {
                             focus = Theme::Style::Overlay::create();
@@ -432,6 +432,23 @@ namespace gameplay
                             active->setTextAlignment(alignment);
                             active->setTextRightToLeft(rightToLeft);
 
+                            theme->_fonts.insert(font);
+                        }
+                        else if (strcmp(innerSpacename, "disabled") == 0)
+                        {
+                            disabled = Theme::Style::Overlay::create();
+                            disabled->setContainerRegion(containerRegion);
+                            disabled->setTextCursor(textCursor);
+                            disabled->setMouseCursor(mouseCursor);
+                            disabled->setCheckBoxIcon(checkBoxIcon);
+                            disabled->setRadioButtonIcon(radioButtonIcon);
+                            disabled->setSliderIcon(sliderIcon);
+                            disabled->setTextColor(textColor);
+                            disabled->setFont(font);
+                            disabled->setFontSize(fontSize);
+                            disabled->setTextAlignment(alignment);
+                            disabled->setTextRightToLeft(rightToLeft);
+
                             theme->_fonts.insert(font);
                         }
                     }
@@ -451,7 +468,13 @@ namespace gameplay
                     active->addRef();
                 }
 
-                Theme::Style* s = new Theme::Style(space->getId(), margin, padding, normal, focus, active);
+                if (!disabled)
+                {
+                    disabled = normal;
+                    disabled->addRef();
+                }
+
+                Theme::Style* s = new Theme::Style(space->getId(), margin, padding, normal, focus, active, disabled);
                 theme->_styles.push_back(s);
             }
 
@@ -789,12 +812,13 @@ namespace gameplay
      * Theme::Style *
      ****************/
     Theme::Style::Style(const char* id, const Theme::Margin& margin, const Theme::Padding& padding,
-            Theme::Style::Overlay* normal, Theme::Style::Overlay* focus, Theme::Style::Overlay* active)
+            Theme::Style::Overlay* normal, Theme::Style::Overlay* focus, Theme::Style::Overlay* active, Theme::Style::Overlay* disabled)
         : _id(id), _margin(margin), _padding(padding)
     {
         _overlays[OVERLAY_NORMAL] = normal;
         _overlays[OVERLAY_FOCUS] = focus;
         _overlays[OVERLAY_ACTIVE] = active;
+        _overlays[OVERLAY_DISABLED] = disabled;
     }
 
     Theme::Style::~Style()

+ 4 - 3
gameplay/src/Theme.h

@@ -15,7 +15,7 @@
 namespace gameplay
 {
 
-#define MAX_OVERLAYS 3
+#define MAX_OVERLAYS 4
 #define MAX_OVERLAY_REGIONS 9
 
 /**
@@ -211,11 +211,12 @@ public:
         {
             OVERLAY_NORMAL,
             OVERLAY_FOCUS,
-            OVERLAY_ACTIVE
+            OVERLAY_ACTIVE,
+            OVERLAY_DISABLED
         };
 
         Style(const char* id, const Theme::Margin& margin, const Theme::Padding& padding,
-            Theme::Style::Overlay* normal, Theme::Style::Overlay* focus, Theme::Style::Overlay* active);
+            Theme::Style::Overlay* normal, Theme::Style::Overlay* focus, Theme::Style::Overlay* active, Theme::Style::Overlay* disabled);
 
         ~Style();
 

+ 4 - 0
gameplay/src/gameplay.h

@@ -78,3 +78,7 @@
 #include "AbsoluteLayout.h"
 #include "Label.h"
 #include "Button.h"
+#include "CheckBox.h"
+#include "TextBox.h"
+#include "RadioButton.h"
+#include "Slider.h"