瀏覽代碼

Canvas Find Mouse Control

This was a pretty major change which worked on the first try and doesn't seem to have any problems - so naturally I'm a little nervous that I'm missing something. With input events now bubbling up through the controls it was apparent that the old method of always having the old mouse control call leave before the new one calls enter is inadequate. If the mouse enters a child control it first "leaves" the parent despite the fact that clicking on the child might be  responded to by the parent. This change makes it so entering a child control does not leave a parent. As a result, you might call a dozen "enter" events to get to a child control without calling any leave events. As you move the the mouse out of the control stack, each control will then call its leave event correctly. I should also point out that enter and leave events do not bubble, because it really doesn't make sense to do so.
Peter Robinson 3 年之前
父節點
當前提交
a5f1c1c93c
共有 2 個文件被更改,包括 50 次插入5 次删除
  1. 49 5
      engine/source/gui/guiCanvas.cc
  2. 1 0
      engine/source/gui/guiCanvas.h

+ 49 - 5
engine/source/gui/guiCanvas.cc

@@ -647,20 +647,64 @@ void GuiCanvas::findMouseControl(const GuiEvent &event)
       mMouseControl = NULL;
       return;
    }
-   GuiControl *controlHit = findHitControl(event.mousePoint);
-   if(controlHit != static_cast<GuiControl*>(mMouseControl))
+   GuiControl* leavingStack = static_cast<GuiControl*>(mMouseControl);
+   GuiControl* controlHit = findHitControl(event.mousePoint);
+   GuiControl* enteringStack = controlHit;
+   if(leavingStack != enteringStack)
    {
       if (bool(mMouseControl))
       {
-         mMouseControl->onTouchLeave(event);
-         hoverControlStart = Platform::getRealMilliseconds();
-         hoverPositionSet = false;
+          hoverControlStart = Platform::getRealMilliseconds();
+          hoverPositionSet = false;
+
+          //figure out how much of the leaving stack we are leaving.
+          while (!DoesControlStackContainControl(enteringStack, leavingStack))
+          {
+              leavingStack->onTouchLeave(event);
+              leavingStack = leavingStack->getParent();
+              if (!leavingStack)
+                  break;
+          }
       }
+
+      //figure out how much of the entering stack we are entering.
+      if (leavingStack)
+      {
+          while (!DoesControlStackContainControl(leavingStack, enteringStack))
+          {
+              enteringStack->onTouchEnter(event);
+              enteringStack = enteringStack->getParent();
+              if(!enteringStack)
+                  break;
+          }
+      }
+
       mMouseControl = controlHit;
       mMouseControl->onTouchEnter(event);
    }
 }
 
+bool GuiCanvas::DoesControlStackContainControl(GuiControl* stack, const GuiControl* ctrl)
+{
+    GuiControl* pen = stack;
+    do
+    {
+        if (pen)
+        {
+            if (pen == ctrl)
+            {
+                return true;
+            }
+            pen = pen->getParent();
+        }
+        else
+        {
+            return false;
+        }
+    } while (pen);
+    return false;
+}
+
 //Luma: Some fixes from the forums, Dave Calabrese
 //http://www.garagegames.com/community/forums/viewthread/93467/1#comment-669559
 void GuiCanvas::rootScreenTouchDown(const GuiEvent &event)

+ 1 - 0
engine/source/gui/guiCanvas.h

@@ -143,6 +143,7 @@ protected:
    bool						  mHideCursorBecauseOfTouch; ///< Touch event has been detected. Hide the cursor.
 
    virtual void findMouseControl(const GuiEvent &event);
+   bool DoesControlStackContainControl(GuiControl* stack, const GuiControl* ctrl);
    virtual void refreshMouseControl();
    /// @}