using System.Collections.Generic; using OpenTK; using SM.Base.Controls; using SM.Base.Scene; using SM.OGL.Mesh; using SM2D.Scene; using SM2D.Types; namespace SM2D.Controls { /// /// Contains special methods for the mouse. /// public class Mouse2D { /// /// Returns the current position of the mouse inside the world. /// public static Vector2 InWorld(Vector2 worldScale) { var res = worldScale; res.Y *= -1; return Mouse.InScreenNormalized * res - res / 2; } /// /// Returns the current position of the mouse inside the world. /// public static Vector2 InWorld(Camera cam) { return InWorld(cam.CalculatedWorldScale) + cam.Position; } /// /// Returns the current position of the mouse inside the world. /// public static Vector2 InWorld(Vector2 worldScale, Vector2 position) { return InWorld(worldScale) + position; } /// /// Checks if the mouse is over an object. /// /// The position in the world. See /// /// public static bool MouseOver(Vector2 mousePos, params TObject[] checkingObjects) where TObject : IModelItem, ITransformItem => MouseOver(mousePos, out _, checkingObjects); /// /// Checks if the mouse is over an object. /// /// The position in the world. See /// /// /// public static bool MouseOver(Vector2 mousePos, ICollection checkingObjects) where TObject : IModelItem, ITransformItem => MouseOver(mousePos, out _, checkingObjects); /// /// Checks if the mouse is over an object and returns the object that was clicked on. /// /// The position in the world. See /// /// /// /// public static bool MouseOver(Vector2 mousePos, out TObject clicked, params TObject[] checkingObjects) where TObject : IModelItem, ITransformItem => MouseOver(mousePos, out clicked, (ICollection)checkingObjects); /// /// Checks if the mouse is over an object and returns the object that was clicked on. /// /// The position in the world. See /// /// /// /// public static bool MouseOver(Vector2 mousePos, out TObject clickedObj, ICollection checkingObjects) where TObject : IModelItem, ITransformItem { clickedObj = default; bool success = false; float distance = -10; foreach (TObject item in checkingObjects) { if (MouseOver(mousePos, item.Mesh.BoundingBox, item.Transform)) { Matrix4 worldPos = item.Transform.InWorldSpace; // if z is greater than distance if (worldPos[3, 2] > distance) { clickedObj = item; distance = worldPos[3, 2]; } success = true; } } return success; } /// /// Checks if the mouse is over an object and returns the object that was clicked on. /// /// The position in the world. See /// /// /// public static bool MouseOver(Vector2 mousePos, BoundingBox boundingBox, Transformation transform) { Matrix4 worldPos = transform.InWorldSpace; boundingBox.GetBounds(worldPos, out Vector3 min, out Vector3 max); if (mousePos.X > min.X && mousePos.X < max.X && mousePos.Y > min.Y && mousePos.Y < max.Y) { return true; } return false; } } }