Improve UI inspect-under-mouse

This commit is contained in:
Sinai 2021-03-26 05:43:53 +11:00
parent bf455893e7
commit 418ece55e3
2 changed files with 136 additions and 27 deletions

View File

@ -37,28 +37,40 @@ namespace UnityExplorer.Core.Inspectors
UI = new MouseInspectorUI(); UI = new MouseInspectorUI();
} }
public static void StartInspect() private static readonly List<Graphic> _wasDisabledGraphics = new List<Graphic>();
private static readonly List<CanvasGroup> _wasDisabledCanvasGroups = new List<CanvasGroup>();
private static readonly List<GameObject> _objectsAddedCastersTo = new List<GameObject>();
public static void StartInspect(MouseInspectMode mode)
{ {
Mode = mode;
Enabled = true; Enabled = true;
MainMenu.Instance.MainPanel.SetActive(false); MainMenu.Instance.MainPanel.SetActive(false);
UI.s_UIContent.SetActive(true); UI.s_UIContent.SetActive(true);
// recache Graphic Raycasters each time we start if (mode == MouseInspectMode.UI)
var casters = RuntimeProvider.Instance.FindObjectsOfTypeAll(typeof(GraphicRaycaster));
m_gCasters = new GraphicRaycaster[casters.Length];
for (int i = 0; i < casters.Length; i++)
{ {
m_gCasters[i] = casters[i].Cast(typeof(GraphicRaycaster)) as GraphicRaycaster; SetupUIRaycast();
} }
} }
internal static void ClearHitData()
{
s_lastHit = null;
UI.s_objNameLabel.text = "No hits...";
UI.s_objPathLabel.text = "";
}
public static void StopInspect() public static void StopInspect()
{ {
Enabled = false; Enabled = false;
MainMenu.Instance.MainPanel.SetActive(true); MainMenu.Instance.MainPanel.SetActive(true);
UI.s_UIContent.SetActive(false); UI.s_UIContent.SetActive(false);
if (Mode == MouseInspectMode.UI)
StopUIInspect();
ClearHitData(); ClearHitData();
} }
@ -91,6 +103,18 @@ namespace UnityExplorer.Core.Inspectors
} }
} }
internal static void UpdatePosition(Vector2 mousePos)
{
s_lastMousePos = mousePos;
var inversePos = UIManager.CanvasRoot.transform.InverseTransformPoint(mousePos);
UI.s_mousePosLabel.text = $"<color=grey>Mouse Position:</color> {mousePos.ToString()}";
float yFix = mousePos.y < 120 ? 80 : -80;
UI.s_UIContent.transform.localPosition = new Vector3(inversePos.x, inversePos.y + yFix, 0);
}
internal static void OnHitGameObject(GameObject obj) internal static void OnHitGameObject(GameObject obj)
{ {
if (obj != s_lastHit) if (obj != s_lastHit)
@ -107,6 +131,8 @@ namespace UnityExplorer.Core.Inspectors
} }
} }
// Collider raycasting
internal static void RaycastWorld(Vector2 mousePos) internal static void RaycastWorld(Vector2 mousePos)
{ {
var ray = UnityHelper.MainCamera.ScreenPointToRay(mousePos); var ray = UnityHelper.MainCamera.ScreenPointToRay(mousePos);
@ -124,6 +150,54 @@ namespace UnityExplorer.Core.Inspectors
} }
} }
// UI Graphic raycasting
private static void SetupUIRaycast()
{
foreach (var obj in RuntimeProvider.Instance.FindObjectsOfTypeAll(typeof(Canvas)))
{
var canvas = obj.Cast(typeof(Canvas)) as Canvas;
if (!canvas || !canvas.enabled || !canvas.gameObject.activeInHierarchy)
continue;
if (!canvas.GetComponent<GraphicRaycaster>())
{
canvas.gameObject.AddComponent<GraphicRaycaster>();
//ExplorerCore.Log("Added raycaster to " + canvas.name);
_objectsAddedCastersTo.Add(canvas.gameObject);
}
}
// recache Graphic Raycasters each time we start
var casters = RuntimeProvider.Instance.FindObjectsOfTypeAll(typeof(GraphicRaycaster));
m_gCasters = new GraphicRaycaster[casters.Length];
for (int i = 0; i < casters.Length; i++)
{
m_gCasters[i] = casters[i].Cast(typeof(GraphicRaycaster)) as GraphicRaycaster;
}
// enable raycastTarget on Graphics
foreach (var obj in RuntimeProvider.Instance.FindObjectsOfTypeAll(typeof(Graphic)))
{
var graphic = obj.Cast(typeof(Graphic)) as Graphic;
if (!graphic || !graphic.enabled || graphic.raycastTarget || !graphic.gameObject.activeInHierarchy)
continue;
graphic.raycastTarget = true;
//ExplorerCore.Log("Enabled raycastTarget on " + graphic.name);
_wasDisabledGraphics.Add(graphic);
}
// enable blocksRaycasts on CanvasGroups
foreach (var obj in RuntimeProvider.Instance.FindObjectsOfTypeAll(typeof(CanvasGroup)))
{
var canvas = obj.Cast(typeof(CanvasGroup)) as CanvasGroup;
if (!canvas || !canvas.gameObject.activeInHierarchy || canvas.blocksRaycasts)
continue;
canvas.blocksRaycasts = true;
//ExplorerCore.Log("Enabled raycasts on " + canvas.name);
_wasDisabledCanvasGroups.Add(canvas);
}
}
internal static void RaycastUI(Vector2 mousePos) internal static void RaycastUI(Vector2 mousePos)
{ {
var ped = new PointerEventData(null) var ped = new PointerEventData(null)
@ -136,6 +210,11 @@ namespace UnityExplorer.Core.Inspectors
#else #else
var list = new Il2CppSystem.Collections.Generic.List<RaycastResult>(); var list = new Il2CppSystem.Collections.Generic.List<RaycastResult>();
#endif #endif
//ExplorerCore.Log("~~~~~~~~~ begin raycast ~~~~~~~~");
GameObject hitObject = null;
int highestLayer = int.MinValue;
int highestOrder = int.MinValue;
int highestDepth = int.MinValue;
foreach (var gr in m_gCasters) foreach (var gr in m_gCasters)
{ {
gr.Raycast(ped, list); gr.Raycast(ped, list);
@ -144,14 +223,40 @@ namespace UnityExplorer.Core.Inspectors
{ {
foreach (var hit in list) foreach (var hit in list)
{ {
if (hit.gameObject) if (!hit.gameObject)
continue;
if (hit.gameObject.GetComponent<CanvasGroup>() is CanvasGroup group && group.alpha == 0)
continue;
if (hit.gameObject.GetComponent<Graphic>() is Graphic graphic && graphic.color.a == 0f)
continue;
//ExplorerCore.Log("Hit: " + hit.gameObject.name + ", depth: " + hit.depth + ", layer: " + hit.sortingLayer + ", order: " + hit.sortingOrder);
if (hit.sortingLayer < highestLayer)
continue;
if (hit.sortingLayer > highestLayer)
{ {
var obj = hit.gameObject; highestLayer = hit.sortingLayer;
highestOrder = int.MinValue;
OnHitGameObject(obj);
break;
} }
if (hit.depth < highestDepth)
continue;
if (hit.depth > highestDepth)
{
highestDepth = hit.depth;
highestOrder = int.MinValue;
}
if (hit.sortingOrder <= highestOrder)
continue;
highestOrder = hit.sortingOrder;
hitObject = hit.gameObject;
} }
} }
else else
@ -160,25 +265,30 @@ namespace UnityExplorer.Core.Inspectors
ClearHitData(); ClearHitData();
} }
} }
if (hitObject)
OnHitGameObject(hitObject);
//ExplorerCore.Log("~~~~~~~~~ end raycast ~~~~~~~~");
} }
internal static void UpdatePosition(Vector2 mousePos) private static void StopUIInspect()
{ {
s_lastMousePos = mousePos; foreach (var obj in _objectsAddedCastersTo)
{
if (obj.GetComponent<GraphicRaycaster>() is GraphicRaycaster raycaster)
GameObject.Destroy(raycaster);
}
var inversePos = UIManager.CanvasRoot.transform.InverseTransformPoint(mousePos); foreach (var graphic in _wasDisabledGraphics)
graphic.raycastTarget = false;
UI.s_mousePosLabel.text = $"<color=grey>Mouse Position:</color> {mousePos.ToString()}"; foreach (var canvas in _wasDisabledCanvasGroups)
canvas.blocksRaycasts = false;
float yFix = mousePos.y < 120 ? 80 : -80; _objectsAddedCastersTo.Clear();
UI.s_UIContent.transform.localPosition = new Vector3(inversePos.x, inversePos.y + yFix, 0); _wasDisabledCanvasGroups.Clear();
} _wasDisabledGraphics.Clear();
internal static void ClearHitData()
{
s_lastHit = null;
UI.s_objNameLabel.text = "No hits...";
UI.s_objPathLabel.text = "";
} }
} }
} }

View File

@ -150,8 +150,7 @@ namespace UnityExplorer.UI.Main.Home
void OnInspectMouseClicked() void OnInspectMouseClicked()
{ {
InspectUnderMouse.Mode = mode; InspectUnderMouse.StartInspect(mode);
InspectUnderMouse.StartInspect();
} }
} }