modular-avatar/Editor/HarmonyPatches/PickingObjectPatch.cs
bd_ f077d24d48
fix: improved Scale Adjuster implementation (#730)
This new implementation avoids creating any internal objects within the avatar
itself, instead creating them as hidden scene root objects. We also move all update
processing to be driven by camera callbacks as well. These changes help improve
compatibility with tools such as FaceEmo, as well as being less likely to break when
other tools manipulate the avatar's hierarchy directly.
2024-03-05 17:19:54 +09:00

78 lines
2.7 KiB
C#

#region
using System;
using System.Collections;
using System.Collections.Generic;
using System.Reflection;
using HarmonyLib;
using UnityEngine;
using Object = UnityEngine.Object;
#endregion
namespace nadena.dev.modular_avatar.core.editor.HarmonyPatches
{
internal static class PickingObjectPatch
{
private static Type t_PickingObject = AccessTools.TypeByName("UnityEditor.PickingObject");
private static Type l_PickingObject =
typeof(List<>).MakeGenericType(new[] { t_PickingObject });
private static ConstructorInfo ctor_l = AccessTools.Constructor(l_PickingObject);
private static ConstructorInfo ctor_PickingObject =
AccessTools.Constructor(t_PickingObject, new[] { typeof(Object), typeof(int) });
private static PropertyInfo p_materialIndex = AccessTools.Property(t_PickingObject, "materialIndex");
private static MethodInfo m_TryGetGameObject = AccessTools.Method(t_PickingObject, "TryGetGameObject");
internal static void Patch(Harmony h)
{
var t_PickingObject = AccessTools.TypeByName("UnityEditor.PickingObject");
var ctor_PickingObject = AccessTools.Constructor(t_PickingObject, new[] { typeof(Object), typeof(int) });
var t_SceneViewPicking = AccessTools.TypeByName("UnityEditor.SceneViewPicking");
var m_GetAllOverlapping = AccessTools.Method(t_SceneViewPicking, "GetAllOverlapping");
var m_postfix = AccessTools.Method(typeof(PickingObjectPatch), nameof(Postfix_GetAllOverlapping));
h.Patch(original: m_GetAllOverlapping, postfix: new HarmonyMethod(m_postfix));
}
private static void Postfix_GetAllOverlapping(ref object __result)
{
var erased = (IEnumerable)__result;
var list = (IList)ctor_l.Invoke(new object[0]);
foreach (var obj in erased)
{
if (obj == null)
{
list.Add(obj);
continue;
}
var args = new object[] { null };
if ((bool)m_TryGetGameObject.Invoke(obj, args))
{
var go = args[0] as GameObject;
if (go != null && ProxyManager.ProxyToOriginalObject.TryGetValue(go, out var original))
{
list.Add(ctor_PickingObject.Invoke(new[]
{
original,
p_materialIndex.GetValue(obj)
}));
continue;
}
}
list.Add(obj);
}
__result = list;
}
}
}