Parcourir la source

Added isScrolling() to Container. This method is used by controls to determine whether they've been clicked, or merely grabbed as a means to scroll their parent container. This logic has been added to all controls. Slider in particular makes use of it. The form in sample04-particles has been modified to show this.

Adam Blake il y a 13 ans
Parent
commit
7b0be86838

+ 2 - 1
gameplay/src/Button.cpp

@@ -63,7 +63,8 @@ bool Button::touchEvent(Touch::TouchEvent evt, int x, int y, unsigned int contac
         {
             _contactIndex = INVALID_CONTACT_INDEX;
             notifyListeners(Listener::RELEASE);
-            if (x > _clipBounds.x && x <= _clipBounds.x + _clipBounds.width &&
+            if (!_parent->isScrolling() &&
+                x > _clipBounds.x && x <= _clipBounds.x + _clipBounds.width &&
                 y > _clipBounds.y && y <= _clipBounds.y + _clipBounds.height)
             {
                 setState(Control::FOCUS);

+ 1 - 0
gameplay/src/Button.h

@@ -1,6 +1,7 @@
 #ifndef BUTTON_H_
 #define BUTTON_H_
 
+#include "Container.h"
 #include "Label.h"
 #include "Touch.h"
 #include "Theme.h"

+ 2 - 1
gameplay/src/CheckBox.cpp

@@ -86,7 +86,8 @@ bool CheckBox::touchEvent(Touch::TouchEvent evt, int x, int y, unsigned int cont
     case Touch::TOUCH_RELEASE:
         if (_contactIndex == (int) contactIndex && _state == Control::ACTIVE)
         {
-            if (x > _clipBounds.x && x <= _clipBounds.x + _clipBounds.width &&
+            if (!_parent->isScrolling() &&
+                x > _clipBounds.x && x <= _clipBounds.x + _clipBounds.width &&
                 y > _clipBounds.y && y <= _clipBounds.y + _clipBounds.height)
             {
                 _checked = !_checked;

+ 9 - 0
gameplay/src/Container.cpp

@@ -20,6 +20,8 @@ namespace gameplay
 static const long SCROLL_INERTIA_DELAY = 100L;
 // Factor to multiply friction by before applying to velocity.
 static const float SCROLL_FRICTION_FACTOR = 5.0f;
+// Distance that must be scrolled before isScrolling() will return true, used e.g. to cancel button-click events.
+static const float SCROLL_THRESHOLD = 10.0f;
 
 /**
  * Sort function for use with _controls.sort(), based on Z-Order.
@@ -361,6 +363,13 @@ bool Container::isScrollBarsAutoHide() const
     return _scrollBarsAutoHide;
 }
 
+bool Container::isScrolling() const
+{
+    return (_scrolling &&
+            (abs(_scrollingLastX - _scrollingFirstX) > SCROLL_THRESHOLD ||
+             abs(_scrollingLastY - _scrollingFirstY) > SCROLL_THRESHOLD));
+}
+
 Animation* Container::getAnimation(const char* id) const
 {
     std::vector<Control*>::const_iterator itr = _controls.begin();

+ 7 - 0
gameplay/src/Container.h

@@ -175,6 +175,13 @@ public:
      */
     bool isScrollBarsAutoHide() const;
 
+    /**
+     * Whether this container is currently being scrolled.
+     *
+     * @return Whether this container is currently being scrolled.
+     */
+    bool isScrolling() const;
+
     /**
      * @see AnimationTarget::getAnimation
      */

+ 1 - 1
gameplay/src/Control.cpp

@@ -41,7 +41,7 @@ void Control::initialize(Theme::Style* style, Properties* properties)
     _autoWidth = properties->getBool("autoWidth");
     _autoHeight = properties->getBool("autoHeight");
 
-    _consumeInputEvents = properties->getBool("consumeEvents", true);
+    _consumeInputEvents = properties->getBool("consumeInputEvents", true);
 
     if (properties->exists("zIndex"))
     {

+ 2 - 2
gameplay/src/Form.cpp

@@ -40,7 +40,6 @@ static std::vector<Form*> __forms;
 
 Form::Form() : _theme(NULL), _frameBuffer(NULL), _spriteBatch(NULL), _node(NULL), _nodeQuad(NULL), _nodeMaterial(NULL) , _u2(0), _v1(0)
 {
-    _consumeInputEvents = false;
 }
 
 Form::~Form()
@@ -94,6 +93,7 @@ Form* Form::create(const char* id, Theme::Style* style, Layout::Type layoutType)
     form->_style = style;
     form->_layout = layout;
     form->_theme = style->getTheme();
+    form->_theme->addRef();
 
     // Get default projection matrix.
     Game* game = Game::getInstance();
@@ -168,7 +168,7 @@ Form* Form::create(const char* url)
     }
     form->initialize(style, formProperties);
 
-    form->_consumeInputEvents = formProperties->getBool("consumeEvents");
+    form->_consumeInputEvents = formProperties->getBool("consumeInputEvents", true);
 
     // Alignment
     if ((form->_alignment & Control::ALIGN_BOTTOM) == Control::ALIGN_BOTTOM)

+ 0 - 2
gameplay/src/Label.cpp

@@ -60,8 +60,6 @@ void Label::addListener(Control::Listener* listener, int eventFlags)
         GP_ERROR("VALUE_CHANGED event is not applicable to this control.");
     }
 
-    _consumeInputEvents = true;
-
     Control::addListener(listener, eventFlags);
 }
     

+ 2 - 1
gameplay/src/RadioButton.cpp

@@ -102,7 +102,8 @@ bool RadioButton::touchEvent(Touch::TouchEvent evt, int x, int y, unsigned int c
         {
             if (_contactIndex == (int) _contactIndex && _state == Control::ACTIVE)
             {
-                if (x > _clipBounds.x && x <= _clipBounds.x + _clipBounds.width &&
+                if (!_parent->isScrolling() &&
+                    x > _clipBounds.x && x <= _clipBounds.x + _clipBounds.width &&
                     y > _clipBounds.y && y <= _clipBounds.y + _clipBounds.height)
                 {
                     if (!_selected)

+ 36 - 1
gameplay/src/Slider.cpp

@@ -5,6 +5,9 @@ namespace gameplay
 
 // Fraction of slider to scroll when mouse scrollwheel is used.
 static const float SCROLL_FRACTION = 0.1f;
+// Distance that a slider must be moved before it starts consuming input events,
+// e.g. to prevent its parent container from scrolling at the same time.
+static const float SLIDER_THRESHOLD = 5.0f;
 
 Slider::Slider() : _min(0.0f), _max(0.0f), _step(0.0f), _value(0.0f), _minImage(NULL), _maxImage(NULL), _trackImage(NULL), _markerImage(NULL)
 {
@@ -104,6 +107,10 @@ bool Slider::touchEvent(Touch::TouchEvent evt, int x, int y, unsigned int contac
         if (_contactIndex != INVALID_CONTACT_INDEX)
             return false;
         _state = Control::ACTIVE;
+        _originalX = x;
+        _originalValue = _value;
+        _originalConsumeInputEvents = _consumeInputEvents;
+        _moveCancelled = false;
         
         // Fall through to calculate new value.
     case Touch::TOUCH_MOVE:
@@ -111,6 +118,33 @@ bool Slider::touchEvent(Touch::TouchEvent evt, int x, int y, unsigned int contac
         if (evt != Touch::TOUCH_PRESS && _contactIndex != (int)contactIndex)
             return false;
 
+        if (_moveCancelled)
+        {
+            break;
+        }
+        else if (abs(x - _originalX) > SLIDER_THRESHOLD)
+        {
+            // Start consuming input events once we've passed the slider's threshold.
+            _consumeInputEvents = true;
+        }
+        else if (_parent->isScrolling())
+        {
+            // Cancel the change in slider value if we pass the parent container's scrolling threshold.
+            float oldValue = _value;
+            _value = _originalValue;
+            if (_value != oldValue)
+            {
+                notifyListeners(Listener::VALUE_CHANGED);
+            }
+
+            _dirty = true;
+            _moveCancelled = true;
+            _state = NORMAL;
+            _contactIndex = INVALID_CONTACT_INDEX;
+            _consumeInputEvents = _originalConsumeInputEvents;
+            break;
+        }
+
         if (_state == ACTIVE &&
             x > _clipBounds.x && x <= _clipBounds.x + _clipBounds.width &&
             y > _clipBounds.y && y <= _clipBounds.y + _clipBounds.height)
@@ -153,8 +187,9 @@ bool Slider::touchEvent(Touch::TouchEvent evt, int x, int y, unsigned int contac
         }
         break;
     case Touch::TOUCH_RELEASE:
+        _consumeInputEvents = _originalConsumeInputEvents;
 
-        if (_contactIndex != (int) contactIndex)// (evt == Touch::TOUCH_RELEASE)
+        if (_contactIndex != (int) contactIndex)
             return false;
 
         _dirty = true;

+ 20 - 0
gameplay/src/Slider.h

@@ -209,6 +209,26 @@ protected:
      */
     float _value;
 
+    /**
+     * The X coordinate of the first touch event in a sequence.
+     */
+    float _originalX;
+
+    /**
+     * The Slider's original value at the start of a sequence of touch events.
+     */
+    float _originalValue;
+
+    /**
+     * The Slider's original setting of _consumeInputEvents at the start of a sequence of touch events.
+     */
+    bool _originalConsumeInputEvents;
+
+    /**
+     * Whether the Slider's current movement has been cancelled, e.g. because the user is scrolling the parent container.
+     */
+    bool _moveCancelled;
+
     /**
      * The image for the minimum slider value.
      */