|
|
@@ -62,6 +62,8 @@ namespace BansheeEngine
|
|
|
mWindowLostFocusConn = RenderWindowManager::instance().onFocusLost.connect(boost::bind(&GUIManager::onWindowFocusLost, this, _1));
|
|
|
mWindowMovedOrResizedConn = RenderWindowManager::instance().onMovedOrResized.connect(boost::bind(&GUIManager::onWindowMovedOrResized, this, _1));
|
|
|
|
|
|
+ mMouseLeftWindowConn = Platform::onMouseLeftWindow.connect(boost::bind(&GUIManager::onMouseLeftWindow, this, _1));
|
|
|
+
|
|
|
mInputCaret = cm_new<GUIInputCaret, PoolAlloc>();
|
|
|
mInputSelection = cm_new<GUIInputSelection, PoolAlloc>();
|
|
|
|
|
|
@@ -94,6 +96,8 @@ namespace BansheeEngine
|
|
|
mWindowLostFocusConn.disconnect();
|
|
|
mWindowMovedOrResizedConn.disconnect();
|
|
|
|
|
|
+ mMouseLeftWindowConn.disconnect();
|
|
|
+
|
|
|
cm_delete<PoolAlloc>(mInputCaret);
|
|
|
cm_delete<PoolAlloc>(mInputSelection);
|
|
|
}
|
|
|
@@ -704,18 +708,6 @@ namespace BansheeEngine
|
|
|
}
|
|
|
#endif
|
|
|
|
|
|
- bool shiftDown = gInput().isButtonDown(BC_LSHIFT) || gInput().isButtonDown(BC_RSHIFT);
|
|
|
- bool ctrlDown = gInput().isButtonDown(BC_LCONTROL) || gInput().isButtonDown(BC_RCONTROL);
|
|
|
- bool altDown = gInput().isButtonDown(BC_LMENU) || gInput().isButtonDown(BC_RMENU);
|
|
|
-
|
|
|
- // TODO - Maybe avoid querying these for every event separately?
|
|
|
- bool buttonStates[(int)GUIMouseButton::Count];
|
|
|
- buttonStates[0] = gInput().isButtonDown(BC_MOUSE_LEFT);
|
|
|
- buttonStates[1] = gInput().isButtonDown(BC_MOUSE_MIDDLE);
|
|
|
- buttonStates[2] = gInput().isButtonDown(BC_MOUSE_RIGHT);
|
|
|
-
|
|
|
- mMouseEvent = GUIMouseEvent(buttonStates, shiftDown, ctrlDown, altDown);
|
|
|
-
|
|
|
GUIWidget* widgetInFocus = nullptr;
|
|
|
GUIElement* topMostElement = nullptr;
|
|
|
Int2 screenPos;
|
|
|
@@ -775,31 +767,84 @@ namespace BansheeEngine
|
|
|
}
|
|
|
}
|
|
|
|
|
|
+ if(handleMouseOver(widgetInFocus, topMostElement, event.screenPos, event.mouseWheelScrollAmount))
|
|
|
+ event.markAsUsed();
|
|
|
+ }
|
|
|
+
|
|
|
+ void GUIManager::onTextInput(const CM::TextInputEvent& event)
|
|
|
+ {
|
|
|
+ if(mKeyboardFocusElement != nullptr)
|
|
|
+ {
|
|
|
+ bool shiftDown = gInput().isButtonDown(BC_LSHIFT) || gInput().isButtonDown(BC_RSHIFT);
|
|
|
+ bool ctrlDown = gInput().isButtonDown(BC_LCONTROL) || gInput().isButtonDown(BC_RCONTROL);
|
|
|
+ bool altDown = gInput().isButtonDown(BC_LMENU) || gInput().isButtonDown(BC_RMENU);
|
|
|
+
|
|
|
+ if(ctrlDown || altDown) // Ignore text input because key characters + alt/ctrl usually correspond to certain commands
|
|
|
+ return;
|
|
|
+
|
|
|
+ mKeyEvent = GUIKeyEvent(shiftDown, ctrlDown, altDown);
|
|
|
+
|
|
|
+ mKeyEvent.setTextInputData(event.textChar);
|
|
|
+ if(sendKeyEvent(mKeyboardFocusWidget, mKeyboardFocusElement, mKeyEvent))
|
|
|
+ event.markAsUsed();
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ bool GUIManager::handleMouseOver(GUIWidget* widget, GUIElement* element, const CM::Int2& screenMousePos, float wheelScrollAmount)
|
|
|
+ {
|
|
|
+ bool eventProcessed = false;
|
|
|
+
|
|
|
+ Int2 localPos;
|
|
|
+ if(widget != nullptr)
|
|
|
+ {
|
|
|
+ const RenderWindow* window = widget->getOwnerWindow();
|
|
|
+
|
|
|
+ Int2 screenPos = window->screenToWindowPos(screenMousePos);
|
|
|
+ Vector4 vecScreenPos((float)screenPos.x, (float)screenPos.y, 0.0f, 1.0f);
|
|
|
+
|
|
|
+ const Matrix4& worldTfrm = widget->SO()->getWorldTfrm();
|
|
|
+
|
|
|
+ Vector4 vecLocalPos = worldTfrm.inverse() * vecScreenPos;
|
|
|
+ localPos = Int2(Math::RoundToInt(vecLocalPos.x), Math::RoundToInt(vecLocalPos.y));
|
|
|
+ }
|
|
|
+
|
|
|
+ bool shiftDown = gInput().isButtonDown(BC_LSHIFT) || gInput().isButtonDown(BC_RSHIFT);
|
|
|
+ bool ctrlDown = gInput().isButtonDown(BC_LCONTROL) || gInput().isButtonDown(BC_RCONTROL);
|
|
|
+ bool altDown = gInput().isButtonDown(BC_LMENU) || gInput().isButtonDown(BC_RMENU);
|
|
|
+
|
|
|
+ // TODO - Maybe avoid querying these for every event separately?
|
|
|
+ bool buttonStates[(int)GUIMouseButton::Count];
|
|
|
+ buttonStates[0] = gInput().isButtonDown(BC_MOUSE_LEFT);
|
|
|
+ buttonStates[1] = gInput().isButtonDown(BC_MOUSE_MIDDLE);
|
|
|
+ buttonStates[2] = gInput().isButtonDown(BC_MOUSE_RIGHT);
|
|
|
+
|
|
|
+ mMouseEvent = GUIMouseEvent(buttonStates, shiftDown, ctrlDown, altDown);
|
|
|
+
|
|
|
// Send MouseOver/MouseOut events to any elements the mouse passes over, except when
|
|
|
// mouse is being held down, in which we only send them to the active element
|
|
|
- if(topMostElement != mMouseOverElement)
|
|
|
+ if(element != mMouseOverElement)
|
|
|
{
|
|
|
if(mMouseOverElement != nullptr)
|
|
|
{
|
|
|
// Send MouseOut event
|
|
|
if(mActiveElement == nullptr || mMouseOverElement == mActiveElement)
|
|
|
{
|
|
|
- Int2 curLocalPos = getWidgetRelativePos(*mMouseOverWidget, event.screenPos);
|
|
|
+ Int2 curLocalPos = getWidgetRelativePos(*mMouseOverWidget, screenMousePos);
|
|
|
|
|
|
- mMouseEvent.setMouseOutData(topMostElement, curLocalPos);
|
|
|
+ mMouseEvent.setMouseOutData(element, curLocalPos);
|
|
|
if(sendMouseEvent(mMouseOverWidget, mMouseOverElement, mMouseEvent))
|
|
|
- event.markAsUsed();
|
|
|
+ eventProcessed = true;
|
|
|
}
|
|
|
}
|
|
|
|
|
|
- if(topMostElement != nullptr)
|
|
|
+ if(element != nullptr)
|
|
|
{
|
|
|
// Send MouseOver event
|
|
|
- if(mActiveElement == nullptr || topMostElement == mActiveElement)
|
|
|
+ if(mActiveElement == nullptr || element == mActiveElement)
|
|
|
{
|
|
|
- mMouseEvent.setMouseOverData(topMostElement, localPos);
|
|
|
- if(sendMouseEvent(widgetInFocus, topMostElement, mMouseEvent))
|
|
|
- event.markAsUsed();
|
|
|
+ mMouseEvent.setMouseOverData(element, localPos);
|
|
|
+ if(sendMouseEvent(widget, element, mMouseEvent))
|
|
|
+ eventProcessed = true;
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
@@ -807,13 +852,13 @@ namespace BansheeEngine
|
|
|
// If mouse is being held down send MouseDrag events
|
|
|
if(mActiveElement != nullptr)
|
|
|
{
|
|
|
- Int2 curLocalPos = getWidgetRelativePos(*mActiveWidget, event.screenPos);
|
|
|
+ Int2 curLocalPos = getWidgetRelativePos(*mActiveWidget, screenMousePos);
|
|
|
|
|
|
if(mLastCursorLocalPos != curLocalPos)
|
|
|
{
|
|
|
- mMouseEvent.setMouseDragData(topMostElement, curLocalPos, curLocalPos - mLastCursorLocalPos);
|
|
|
+ mMouseEvent.setMouseDragData(element, curLocalPos, curLocalPos - mLastCursorLocalPos);
|
|
|
if(sendMouseEvent(mActiveWidget, mActiveElement, mMouseEvent))
|
|
|
- event.markAsUsed();
|
|
|
+ eventProcessed = true;
|
|
|
|
|
|
mLastCursorLocalPos = curLocalPos;
|
|
|
}
|
|
|
@@ -821,58 +866,41 @@ namespace BansheeEngine
|
|
|
// Also if drag is in progress send DragAndDrop events
|
|
|
if(DragAndDropManager::instance().isDragInProgress())
|
|
|
{
|
|
|
- if(topMostElement != nullptr)
|
|
|
+ if(element != nullptr)
|
|
|
{
|
|
|
- mMouseEvent.setDragAndDropDraggedData(topMostElement, localPos, DragAndDropManager::instance().getDragTypeId(), DragAndDropManager::instance().getDragData());
|
|
|
- if(sendMouseEvent(widgetInFocus, topMostElement, mMouseEvent))
|
|
|
- event.markAsUsed();
|
|
|
+ mMouseEvent.setDragAndDropDraggedData(element, localPos, DragAndDropManager::instance().getDragTypeId(), DragAndDropManager::instance().getDragData());
|
|
|
+ if(sendMouseEvent(widget, element, mMouseEvent))
|
|
|
+ eventProcessed = true;
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
else // Otherwise, send MouseMove events if we are hovering over any element
|
|
|
{
|
|
|
- if(topMostElement != nullptr)
|
|
|
+ if(element != nullptr)
|
|
|
{
|
|
|
// Send MouseMove event
|
|
|
if(mLastCursorLocalPos != localPos)
|
|
|
{
|
|
|
- mMouseEvent.setMouseMoveData(topMostElement, localPos);
|
|
|
- if(sendMouseEvent(widgetInFocus, topMostElement, mMouseEvent))
|
|
|
- event.markAsUsed();
|
|
|
+ mMouseEvent.setMouseMoveData(element, localPos);
|
|
|
+ if(sendMouseEvent(widget, element, mMouseEvent))
|
|
|
+ eventProcessed = true;
|
|
|
|
|
|
mLastCursorLocalPos = localPos;
|
|
|
}
|
|
|
|
|
|
- if(Math::Abs(event.mouseWheelScrollAmount) > 0.00001f)
|
|
|
+ if(Math::Abs(wheelScrollAmount) > 0.00001f)
|
|
|
{
|
|
|
- mMouseEvent.setMouseWheelScrollData(topMostElement, event.mouseWheelScrollAmount);
|
|
|
- if(sendMouseEvent(widgetInFocus, topMostElement, mMouseEvent))
|
|
|
- event.markAsUsed();
|
|
|
+ mMouseEvent.setMouseWheelScrollData(element, wheelScrollAmount);
|
|
|
+ if(sendMouseEvent(widget, element, mMouseEvent))
|
|
|
+ eventProcessed = true;
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
|
|
|
- mMouseOverElement = topMostElement;
|
|
|
- mMouseOverWidget = widgetInFocus;
|
|
|
- }
|
|
|
-
|
|
|
- void GUIManager::onTextInput(const CM::TextInputEvent& event)
|
|
|
- {
|
|
|
- if(mKeyboardFocusElement != nullptr)
|
|
|
- {
|
|
|
- bool shiftDown = gInput().isButtonDown(BC_LSHIFT) || gInput().isButtonDown(BC_RSHIFT);
|
|
|
- bool ctrlDown = gInput().isButtonDown(BC_LCONTROL) || gInput().isButtonDown(BC_RCONTROL);
|
|
|
- bool altDown = gInput().isButtonDown(BC_LMENU) || gInput().isButtonDown(BC_RMENU);
|
|
|
-
|
|
|
- if(ctrlDown || altDown) // Ignore text input because key characters + alt/ctrl usually correspond to certain commands
|
|
|
- return;
|
|
|
+ mMouseOverElement = element;
|
|
|
+ mMouseOverWidget = widget;
|
|
|
|
|
|
- mKeyEvent = GUIKeyEvent(shiftDown, ctrlDown, altDown);
|
|
|
-
|
|
|
- mKeyEvent.setTextInputData(event.textChar);
|
|
|
- if(sendKeyEvent(mKeyboardFocusWidget, mKeyboardFocusElement, mKeyEvent))
|
|
|
- event.markAsUsed();
|
|
|
- }
|
|
|
+ return false;
|
|
|
}
|
|
|
|
|
|
void GUIManager::onWindowFocusGained(RenderWindow& win)
|
|
|
@@ -905,6 +933,13 @@ namespace BansheeEngine
|
|
|
}
|
|
|
}
|
|
|
|
|
|
+ // We stop getting mouse move events once it leaves the window, so make sure
|
|
|
+ // nothing stays in hover state
|
|
|
+ void GUIManager::onMouseLeftWindow(CM::RenderWindow* win)
|
|
|
+ {
|
|
|
+ handleMouseOver(nullptr, nullptr, Int2());
|
|
|
+ }
|
|
|
+
|
|
|
void GUIManager::queueForDestroy(GUIElement* element)
|
|
|
{
|
|
|
mScheduledForDestruction.push(element);
|