Created
July 21, 2022 10:00
-
-
Save karljj1/e333a7a3f192a5d264d95bfbaff0fde8 to your computer and use it in GitHub Desktop.
Workaround to UGUI input issues https://issuetracker.unity3d.com/issues/broken-mouse-pointer-input-coordinates-in-graphicraycaster-for-certain-window-sizes-in-build-when-run-in-windowed-mode
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
using UnityEngine.EventSystems; | |
namespace UnityEngine.UI | |
{ | |
internal static class MultipleDisplayUtilities | |
{ | |
/// <summary> | |
/// Converts the current drag position into a relative position for the display. | |
/// </summary> | |
/// <param name="eventData"></param> | |
/// <param name="position"></param> | |
/// <returns>Returns true except when the drag operation is not on the same display as it originated</returns> | |
public static bool GetRelativeMousePositionForDrag(PointerEventData eventData, ref Vector2 position) | |
{ | |
#if UNITY_EDITOR | |
position = eventData.position; | |
#else | |
int pressDisplayIndex = eventData.pointerPressRaycast.displayIndex; | |
var relativePosition = RelativeMouseAtScaled(eventData.position); | |
int currentDisplayIndex = (int)relativePosition.z; | |
// Discard events on a different display. | |
if (currentDisplayIndex != pressDisplayIndex) | |
return false; | |
// If we are not on the main display then we must use the relative position. | |
position = pressDisplayIndex != 0 ? (Vector2)relativePosition : eventData.position; | |
#endif | |
return true; | |
} | |
/// <summary> | |
/// A version of Display.RelativeMouseAt that scales the position when the main display has a different rendering resolution to the system resolution. | |
/// By default, the mouse position is relative to the main render area, we need to adjust this so it is relative to the system resolution | |
/// in order to correctly determine the position on other displays. | |
/// </summary> | |
/// <returns></returns> | |
public static Vector3 RelativeMouseAtScaled(Vector2 position) | |
{ | |
#if !UNITY_EDITOR && !UNITY_WSA | |
// If the main display is now the same resolution as the system then we need to scale the mouse position. (case 1141732) | |
if (Display.main.renderingWidth != Display.main.systemWidth || Display.main.renderingHeight != Display.main.systemHeight) | |
{ | |
// The system will add padding when in full-screen and using a non-native aspect ratio. (case UUM-7893) | |
// For example Rendering 1920x1080 with a systeem resolution of 3440x1440 would create black bars on each side that are 330 pixels wide. | |
// we need to account for this or it will offset our coordinates when we are not on the main display. | |
var systemAspectRatio = Display.main.systemWidth / (float)Display.main.systemHeight; | |
var sizePlusPadding = new Vector2(Display.main.renderingWidth, Display.main.renderingHeight); | |
var padding = Vector2.zero; | |
if (Screen.fullScreen) | |
{ | |
var aspectRatio = Screen.width / (float)Screen.height; | |
if (Display.main.systemHeight * aspectRatio < Display.main.systemWidth) | |
{ | |
// Horizontal padding | |
sizePlusPadding.x = Display.main.renderingHeight * systemAspectRatio; | |
padding.x = (sizePlusPadding.x - Display.main.renderingWidth) * 0.5f; | |
} | |
else | |
{ | |
// Vertical padding | |
sizePlusPadding.y = Display.main.renderingWidth / systemAspectRatio; | |
padding.y = (sizePlusPadding.y - Display.main.renderingHeight) * 0.5f; | |
} | |
} | |
var sizePlusPositivePadding = sizePlusPadding - padding; | |
// If we are not inside of the main display then we must adjust the mouse position so it is scaled by | |
// the main display and adjusted for any padding that may have been added due to different aspect ratios. | |
if (position.y < -padding.y || position.y > sizePlusPositivePadding.y || | |
position.x < -padding.x || position.x > sizePlusPositivePadding.x) | |
{ | |
var adjustedPosition = position; | |
if (!Screen.fullScreen) | |
{ | |
// When in windowed mode, the window will be centered with the 0,0 coordinate at the top left, we need to adjust so it is relative to the screen instead. | |
adjustedPosition.x -= (Display.main.renderingWidth - Display.main.systemWidth) * 0.5f; | |
adjustedPosition.y -= (Display.main.renderingHeight - Display.main.systemHeight) * 0.5f; | |
} | |
else | |
{ | |
// Scale the mouse position to account for the black bars when in a non-native aspect ratio. | |
adjustedPosition += padding; | |
adjustedPosition.x *= Display.main.systemWidth / sizePlusPadding.x; | |
adjustedPosition.y *= Display.main.systemHeight / sizePlusPadding.y; | |
} | |
var relativePos = Display.RelativeMouseAt(adjustedPosition); | |
// If we are not on the main display then return the adjusted position. | |
if (relativePos.z != 0) | |
return relativePos; | |
} | |
// We are using the main display. | |
return new Vector3(position.x, position.y, 0); | |
} | |
#endif | |
return Display.RelativeMouseAt(position); | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment