Browse Source

Add mouse grabbed flag to Input subsystem.
Use it in Editor camera rotation/orbiting operation to prevent Editor's UI element from reacting to mouse in the midst of operation.

Yao Wei Tjong 姚伟忠 11 years ago
parent
commit
153906b8c7

+ 16 - 8
Bin/Data/Scripts/Editor/EditorView.as

@@ -146,7 +146,7 @@ class ViewportContext
 
         cameraPosText = Text();
         statusBar.AddChild(cameraPosText);
-        
+
         cameraPosText.SetFont(font, 11);
         cameraPosText.color = Color(1, 1, 0);
         cameraPosText.textEffect = TE_SHADOW;
@@ -210,7 +210,7 @@ class ViewportContext
     {
         SetOrthographic(!camera.orthographic);
     }
-    
+
     void SetOrthographic(bool orthographic)
     {
         // This doesn't work that great
@@ -249,7 +249,7 @@ class ViewportContext
     void OpenViewportSettingsWindow()
     {
         UpdateSettingsUI();
-        /* settingsWindow.position = */ 
+        /* settingsWindow.position = */
         settingsWindow.visible = true;
     }
 
@@ -394,7 +394,7 @@ void CreateCamera()
 {
     // Set the initial viewport rect
     viewportArea = IntRect(0, 0, graphics.width, graphics.height);
-    
+
     SetViewportMode(viewportMode);
     SetActiveViewport(viewports[0]);
 
@@ -418,7 +418,7 @@ void CreateViewportUI()
         viewportUI = UIElement();
         ui.root.AddChild(viewportUI);
     }
-        
+
     viewportUI.SetFixedSize(viewportArea.width, viewportArea.height);
     viewportUI.position = IntVector2(viewportArea.top, viewportArea.left);
     viewportUI.clipChildren = true;
@@ -618,7 +618,7 @@ void SetViewportMode(uint mode = VIEWPORT_SINGLE)
             viewports[i].cameraNode.rotation = cameraRotations[src];
         }
     }
-    
+
     ReacquireCameraYawPitch();
     UpdateViewParameters();
     UpdateCameraPreview();
@@ -1163,10 +1163,14 @@ void UpdateView(float timeStep)
                 cameraNode.worldPosition = centerPoint - q * Vector3(0.0, 0.0, d.length);
                 orbiting = true;
             }
-            
+
             FadeUI();
+            input.mouseGrabbed = true;
         }
     }
+    else
+        input.mouseGrabbed = false;
+
     if (orbiting && !input.mouseButtonDown[MOUSEB_MIDDLE])
         orbiting = false;
 
@@ -1378,6 +1382,10 @@ void ViewRaycast(bool mouseClick)
     if (ui.HasModalElement())
         return;
 
+    // Ignore if mouse is grabbed by other operation
+    if (input.mouseGrabbed)
+        return;
+
     IntVector2 pos = ui.cursorPosition;
     UIElement@ elementAtPos = ui.GetElementAt(pos, pickMode != PICK_UI_ELEMENTS);
     if(editMode==EDIT_SPAWN)
@@ -1393,7 +1401,7 @@ void ViewRaycast(bool mouseClick)
 
     DebugRenderer@ debug = editorScene.debugRenderer;
 
- 
+
     if (pickMode == PICK_UI_ELEMENTS)
     {
         bool leftClick = mouseClick && input.mouseButtonPress[MOUSEB_LEFT];

+ 6 - 0
Source/Engine/Input/Input.cpp

@@ -76,6 +76,7 @@ Input::Input(Context* context) :
     windowID_(0),
     toggleFullscreen_(true),
     mouseVisible_(false),
+    mouseGrabbed_(false),
     inputFocus_(false),
     minimized_(false),
     focusedThisFrame_(false),
@@ -232,6 +233,11 @@ void Input::SetMouseVisible(bool enable)
     #endif
 }
 
+void Input::SetMouseGrabbed(bool grab)
+{
+    mouseGrabbed_ = grab;
+}
+
 void Input::SetToggleFullscreen(bool enable)
 {
     toggleFullscreen_ = enable;

+ 7 - 1
Source/Engine/Input/Input.h

@@ -78,7 +78,7 @@ struct JoystickState
     float GetAxisPosition(unsigned index) const { return index < axes_.Size() ? axes_[index] : 0.0f; }
     /// Return hat position.
     int GetHatPosition(unsigned index) const { return index < hats_.Size() ? hats_[index] : HAT_CENTER; }
-    
+
     /// SDL joystick.
     SDL_Joystick* joystick_;
     /// SDL joystick instance ID.
@@ -116,6 +116,8 @@ public:
     void SetToggleFullscreen(bool enable);
     /// Set whether the operating system mouse cursor is visible. When not visible (default), is kept centered to prevent leaving the window.
     void SetMouseVisible(bool enable);
+    /// Set whether the mouse is currently being grabbed by an operation.
+    void SetMouseGrabbed(bool grab);
     /// Add screen joystick.
     /** Return the joystick instance ID when successful or negative on error.
      *  If layout file is not given, use the default screen joystick layout.
@@ -203,6 +205,8 @@ public:
     bool IsScreenKeyboardVisible() const;
     /// Return whether the operating system mouse cursor is visible.
     bool IsMouseVisible() const { return mouseVisible_; }
+    /// Return whether the mouse is currently being grabbed by an operation.
+    bool IsMouseGrabbed() const { return mouseGrabbed_; }
     /// Return whether application window has input focus.
     bool HasFocus() { return inputFocus_; }
     /// Return whether application window is minimized.
@@ -272,6 +276,8 @@ private:
     bool toggleFullscreen_;
     /// Operating system mouse cursor visible flag.
     bool mouseVisible_;
+    /// Flag to indicate the mouse is being grabbed by an operation. Subsystems like UI that uses mouse should temporarily ignore the mouse hover or click events.
+    bool mouseGrabbed_;
     /// Input focus flag.
     bool inputFocus_;
     /// Minimized flag.

+ 3 - 0
Source/Engine/LuaScript/pkgs/Input/Input.pkg

@@ -36,6 +36,7 @@ class Input : public Object
 {
     void SetToggleFullscreen(bool enable);
     void SetMouseVisible(bool enable);
+    void SetMouseGrabbed(bool grab);
     int AddScreenJoystick(XMLFile* layoutFile = 0, XMLFile* styleFile = 0);
     bool RemoveScreenJoystick(int id);
     void SetScreenJoystickVisible(int id, bool enable);
@@ -78,6 +79,7 @@ class Input : public Object
     bool IsScreenJoystickVisible(int id) const;
     bool IsScreenKeyboardVisible() const;
     bool IsMouseVisible() const;
+    bool IsMouseGrabbed() const;
     bool HasFocus();
     bool IsMinimized() const;
 
@@ -93,6 +95,7 @@ class Input : public Object
     tolua_readonly tolua_property__get_set bool screenKeyboardSupport;
     tolua_property__is_set bool screenKeyboardVisible;
     tolua_property__is_set bool mouseVisible;
+    tolua_property__is_set bool mouseGrabbed;
     tolua_readonly tolua_property__has_set bool focus;
     tolua_readonly tolua_property__is_set bool minimized;
 };

+ 2 - 0
Source/Engine/Script/InputAPI.cpp

@@ -484,6 +484,8 @@ static void RegisterInput(asIScriptEngine* engine)
     engine->RegisterObjectMethod("Input", "String GetScancodeName(int) const", asMETHOD(Input, GetScancodeName), asCALL_THISCALL);
     engine->RegisterObjectMethod("Input", "void set_mouseVisible(bool)", asMETHOD(Input, SetMouseVisible), asCALL_THISCALL);
     engine->RegisterObjectMethod("Input", "bool get_mouseVisible() const", asMETHOD(Input, IsMouseVisible), asCALL_THISCALL);
+    engine->RegisterObjectMethod("Input", "void set_mouseGrabbed(bool)", asMETHOD(Input, SetMouseGrabbed), asCALL_THISCALL);
+    engine->RegisterObjectMethod("Input", "bool get_mouseGrabbed() const", asMETHOD(Input, IsMouseGrabbed), asCALL_THISCALL);
     engine->RegisterObjectMethod("Input", "void set_screenJoystickVisible(int, bool)", asMETHOD(Input, SetScreenJoystickVisible), asCALL_THISCALL);
     engine->RegisterObjectMethod("Input", "bool get_screenJoystickVisible(int)", asMETHOD(Input, IsScreenJoystickVisible), asCALL_THISCALL);
     engine->RegisterObjectMethod("Input", "void set_screenKeyboardVisible(bool)", asMETHOD(Input, SetScreenKeyboardVisible), asCALL_THISCALL);

+ 26 - 11
Source/Engine/UI/UI.cpp

@@ -296,10 +296,6 @@ void UI::Update(float timeStep)
 
     PROFILE(UpdateUI);
 
-    IntVector2 cursorPos;
-    bool cursorVisible;
-    GetCursorPositionAndVisible(cursorPos, cursorVisible);
-
     // Expire hovers
     for (HashMap<WeakPtr<UIElement>, bool>::Iterator i = hoveredElements_.Begin(); i != hoveredElements_.End(); ++i)
         i->second_ = false;
@@ -322,11 +318,17 @@ void UI::Update(float timeStep)
     }
 
     // Mouse hover
-    if (!usingTouchInput_ && cursorVisible)
-        ProcessHover(cursorPos, mouseButtons_, qualifiers_, cursor_);
+    Input* input = GetSubsystem<Input>();
+    if (!input->IsMouseGrabbed())
+    {
+        IntVector2 cursorPos;
+        bool cursorVisible;
+        GetCursorPositionAndVisible(cursorPos, cursorVisible);
+        if (!usingTouchInput_ && cursorVisible)
+            ProcessHover(cursorPos, mouseButtons_, qualifiers_, cursor_);
+    }
 
     // Touch hover
-    Input* input = GetSubsystem<Input>();
     unsigned numTouches = input->GetNumTouches();
     for (unsigned i = 0; i < numTouches; ++i)
     {
@@ -1169,20 +1171,29 @@ void UI::HandleScreenMode(StringHash eventType, VariantMap& eventData)
 
 void UI::HandleMouseButtonDown(StringHash eventType, VariantMap& eventData)
 {
-    mouseButtons_ = eventData[MouseButtonDown::P_BUTTONS].GetInt();
-    qualifiers_ = eventData[MouseButtonDown::P_QUALIFIERS].GetInt();
+    Input* input = GetSubsystem<Input>();
+    if (input->IsMouseGrabbed())
+        return;
+
+    using namespace MouseButtonDown;
+
+    mouseButtons_ = eventData[P_BUTTONS].GetInt();
+    qualifiers_ = eventData[P_QUALIFIERS].GetInt();
     usingTouchInput_ = false;
 
     IntVector2 cursorPos;
     bool cursorVisible;
     GetCursorPositionAndVisible(cursorPos, cursorVisible);
 
-    ProcessClickBegin(cursorPos, eventData[MouseButtonDown::P_BUTTON].GetInt(), mouseButtons_, qualifiers_, cursor_,
-        cursorVisible);
+    ProcessClickBegin(cursorPos, eventData[P_BUTTON].GetInt(), mouseButtons_, qualifiers_, cursor_, cursorVisible);
 }
 
 void UI::HandleMouseButtonUp(StringHash eventType, VariantMap& eventData)
 {
+    Input* input = GetSubsystem<Input>();
+    if (input->IsMouseGrabbed())
+        return;
+
     using namespace MouseButtonUp;
 
     mouseButtons_ = eventData[P_BUTTONS].GetInt();
@@ -1237,6 +1248,10 @@ void UI::HandleMouseMove(StringHash eventType, VariantMap& eventData)
 
 void UI::HandleMouseWheel(StringHash eventType, VariantMap& eventData)
 {
+    Input* input = GetSubsystem<Input>();
+    if (input->IsMouseGrabbed())
+        return;
+
     using namespace MouseWheel;
 
     mouseButtons_ = eventData[P_BUTTONS].GetInt();