diff --git a/Engine/source/gui/core/guiCanvas.cpp b/Engine/source/gui/core/guiCanvas.cpp index a1d945ecf..d03e81524 100644 --- a/Engine/source/gui/core/guiCanvas.cpp +++ b/Engine/source/gui/core/guiCanvas.cpp @@ -163,7 +163,8 @@ GuiCanvas::GuiCanvas(): GuiControl(), mPlatformWindow(NULL), mDisplayWindow(true), mMenuBarCtrl(nullptr), - mMenuBackground(nullptr) + mMenuBackground(nullptr), + mConstrainMouse(false) { setBounds(0, 0, 640, 480); mAwake = true; @@ -1749,6 +1750,36 @@ void GuiCanvas::setupFences() mNextFenceIdx = 0; } +void GuiCanvas::constrainMouseCoords(Point2I mousePoint) +{ + if (mConstrainMouse == false) return; + Point2I windowPos = getPlatformWindow()->getPosition();//this is the offset + Point2I winSize = getWindowSize();//window size too! + + S32 newDisplay = Con::getIntVariable("pref::Video::deviceId", 0); + SDL_DisplayMode displayM; + if (0 == SDL_GetDesktopDisplayMode(newDisplay, &displayM)) + { + S32 width = displayM.w; + S32 height = displayM.h; + + if (winSize.x < width || winSize.y < height) + { + //we must be windowed + //find the diference and half it + S32 offX = (width - winSize.x) * 0.5f; + S32 offY = (height - winSize.y) * 0.5f; + S32 maxX = winSize.x + offX; + S32 maxY = winSize.y + offY; + + Point2I newPos; //using 8px as a safety margin + newPos.x = mClamp(mousePoint.x, 0, maxX); + newPos.y = mClamp(mousePoint.y, 0, maxY); + setCursorPos(windowPos + newPos); + } + } +} + void GuiCanvas::renderFrame(bool preRenderOnly, bool bufferSwap /* = true */) { AssertISV(mPlatformWindow, "GuiCanvas::renderFrame - no window present!"); @@ -1874,6 +1905,7 @@ void GuiCanvas::renderFrame(bool preRenderOnly, bool bufferSwap /* = true */) addUpdateRegion(pos - Point2I(2, 2), Point2I(cext.x + 4, cext.y + 4)); } + constrainMouseCoords(cursorPos); mLastCursorEnabled = cursorVisible; mLastCursor = mouseCursor; @@ -2956,6 +2988,11 @@ DefineEngineMethod(GuiCanvas, cursorNudge, void, (F32 x, F32 y), , "") object->cursorNudge(x, y); } +DefineEngineMethod(GuiCanvas, constrainMouse, void, (bool constrained), , "constrain Mouse to the window") +{ + object->constrainMouse(constrained); +} + // This function allows resetting of the video-mode from script. It was motivated by // the need to temporarily disable vsync during datablock cache load to avoid a // significant slowdown. diff --git a/Engine/source/gui/core/guiCanvas.h b/Engine/source/gui/core/guiCanvas.h index cc28bd2ca..64493c7dd 100644 --- a/Engine/source/gui/core/guiCanvas.h +++ b/Engine/source/gui/core/guiCanvas.h @@ -84,6 +84,7 @@ /// you need to add your control to the dirty areas of the canvas. /// class guiCanvas; +class Point2I; typedef Signal CanvasSizeChangeSignal; class GuiCanvas : public GuiControl, public IProcessInput { @@ -212,7 +213,7 @@ protected: GuiControl *mMenuBarCtrl; GuiControl* mMenuBackground; - + bool mConstrainMouse; public: DECLARE_CONOBJECT(GuiCanvas); DECLARE_CATEGORY( "Gui Core" ); @@ -233,12 +234,15 @@ public: /// @name Rendering methods /// /// @{ + void constrainMouse(bool constrained) { mConstrainMouse = constrained; }; + void constrainMouseCoords(Point2I mousePoint); /// Repaints the dirty regions of the canvas /// @param preRenderOnly If set to true, only the onPreRender methods of all the GuiControls will be called /// @param bufferSwap If set to true, it will swap buffers at the end. This is to support canvas-subclassing. virtual void renderFrame(bool preRenderOnly, bool bufferSwap = true); + /// Repaints the canvas by calling the platform window display event. virtual void paint();