115 lines
4.2 KiB
C#
115 lines
4.2 KiB
C#
using System;
|
|
using RPGCoreCommon.Settings;
|
|
using UnityEngine;
|
|
using UnityEngine.InputSystem;
|
|
using UnityEngine.UIElements;
|
|
using Object = UnityEngine.Object;
|
|
|
|
namespace RPGCoreCommon.Select
|
|
{
|
|
public static class Select
|
|
{
|
|
private static IRuntimePanel _panel;
|
|
|
|
private static IRuntimePanel GetPanel()
|
|
{
|
|
if (_panel != null) return _panel;
|
|
|
|
const string documentUITag = "MainUIDocument";
|
|
UIDocument uiDocument = null;
|
|
|
|
try
|
|
{
|
|
// FIND BY TAG
|
|
var go = GameObject.FindWithTag(documentUITag);
|
|
if (go) uiDocument = go.GetComponent<UIDocument>();
|
|
}
|
|
catch (UnityException)
|
|
{
|
|
Debug.LogError($"Tag {documentUITag} not found! Please add it to the project.");
|
|
}
|
|
|
|
// FIND ANY UI DOCUMENT
|
|
if (!uiDocument)
|
|
{
|
|
Debug.LogWarning($"Found no {nameof(UIDocument)} with tag '{documentUITag}', started looking for any on scene...");
|
|
uiDocument = Object.FindAnyObjectByType<UIDocument>();
|
|
}
|
|
|
|
// PANEL NOT FOUND
|
|
if (!uiDocument)
|
|
{
|
|
Debug.LogError($"Current scene has no {nameof(UIDocument)}! {nameof(Select)} won't work with UI!");
|
|
return null;
|
|
}
|
|
|
|
_panel = uiDocument.runtimePanel;
|
|
return _panel;
|
|
}
|
|
|
|
/// <summary>Get <see cref="GetFromUI"/> and if nothing selected then get <see cref="GetFromScene"/> instead.</summary>
|
|
public static SelectUtilResult Get()
|
|
{
|
|
if (GetFromUI() is { hit: SelectType.UI } fromUI) return fromUI;
|
|
if (GetFromScene() is { hit: SelectType.Scene } fromScene) return fromScene;
|
|
return new SelectUtilResult();
|
|
}
|
|
|
|
/// <summary>Try to select anything from given position on UI that extends <see cref="ISelectableUI"/></summary>
|
|
public static SelectUtilResult GetFromUI()
|
|
{
|
|
var mousePos = Mouse.current.position.ReadValue();
|
|
mousePos.y = Screen.height - mousePos.y;
|
|
var mousePosOnUI = RuntimePanelUtils.ScreenToPanel(GetPanel(), mousePos);
|
|
|
|
return new SelectUtilResult(mousePosOnUI, GetPanel().Pick(mousePosOnUI));
|
|
}
|
|
|
|
/// <summary>
|
|
/// TComponent is <see cref="Rigidbody"/> by default if not provided.<br/>
|
|
/// <inheritdoc cref="GetFromScene{TComponent}"/>
|
|
/// </summary>
|
|
public static SelectUtilResult GetFromScene()
|
|
{
|
|
return GetFromScene<Rigidbody>();
|
|
}
|
|
|
|
/// <summary>
|
|
/// Try to select <see cref="GameObject"/> with component of given type '<typeparamref name="TComponent"/>' in self or in any parent.
|
|
/// If not found then gets <see cref="Collider"/>'s <see cref="GameObject"/>.
|
|
/// </summary>
|
|
/// <typeparam name="TComponent">Type of component to look for</typeparam>
|
|
public static SelectUtilResult GetFromScene<TComponent>() where TComponent : Component
|
|
{
|
|
var hit = SelectHit();
|
|
|
|
// Nothing hit - clicked void?
|
|
if (!hit.collider) return new SelectUtilResult();
|
|
|
|
var component = hit.collider.gameObject.GetComponentInParent<TComponent>();
|
|
|
|
// Wanted component not found - get GameObject from Collider
|
|
if (!component) return new SelectUtilResult(hit.point, hit.collider.gameObject);
|
|
|
|
return new SelectUtilResult(hit.point, component.gameObject, component);
|
|
}
|
|
|
|
/// <summary>Returns Vector3 of clicked position</summary>
|
|
public static Vector3 SelectPosition()
|
|
{
|
|
return SelectHit().point;
|
|
}
|
|
|
|
/// <summary>Returns <see cref="RaycastHit"/> of clicked position</summary>
|
|
public static RaycastHit SelectHit()
|
|
{
|
|
Physics.Raycast(
|
|
Camera.main.ScreenPointToRay(Mouse.current.position.ReadValue()),
|
|
out var hit,
|
|
Mathf.Infinity,
|
|
SettingsManager.Get<SelectSettings>().collisionLayerMask);
|
|
|
|
return hit;
|
|
}
|
|
}
|
|
} |