205 lines
5.2 KiB
C#
205 lines
5.2 KiB
C#
using System;
|
|
using System.Collections;
|
|
using System.Collections.Generic;
|
|
using System.Linq;
|
|
using System.Reflection;
|
|
using Newtonsoft.Json;
|
|
#if UNITY_EDITOR
|
|
using UnityEditor.UIElements;
|
|
using Cysharp.Threading.Tasks;
|
|
using UnityEditor;
|
|
#endif
|
|
using UnityEngine;
|
|
using UnityEngine.UIElements;
|
|
using Object = UnityEngine.Object;
|
|
|
|
namespace BITKit.Events
|
|
{
|
|
[Serializable]
|
|
public class UnityEventData
|
|
{
|
|
public Object Target;
|
|
public string MethodName;
|
|
}
|
|
[Serializable]
|
|
public class UnityEvent
|
|
{
|
|
public List<UnityEventData> Targets = new List<UnityEventData>();
|
|
|
|
public void Invoke(params object[] objects)
|
|
{
|
|
foreach (var x in Targets)
|
|
{
|
|
var methodName = x.MethodName;
|
|
var target = x.Target;
|
|
var split = methodName.Split('/');
|
|
if (x.Target is GameObject gameObject&& split.Length is 2 && BITSharp.TryGetTypeFromFullName(split[0],out var type) && gameObject.TryGetComponent(type,out var _target))
|
|
{
|
|
target = _target;
|
|
methodName = split[1];
|
|
}
|
|
|
|
|
|
var method =target.GetType().GetMethod(methodName);
|
|
try
|
|
{
|
|
method?.Invoke(target, objects);
|
|
}
|
|
catch (TargetParameterCountException e)
|
|
{
|
|
BIT4Log.Log<UnityEvent>(string.Join(",",method?.GetParameters().Select(x=>x.Name)));
|
|
throw;
|
|
}
|
|
}
|
|
|
|
}
|
|
}
|
|
#if UNITY_EDITOR
|
|
[CustomPropertyDrawer(typeof(UnityEvent))]
|
|
public class UnityEventDataPropertyDrawer:PropertyDrawer
|
|
{
|
|
private VisualElement root;
|
|
|
|
private UnityEvent agent;
|
|
|
|
private SerializedProperty _property;
|
|
|
|
private static readonly List<string> _unityMethodNames = typeof(MonoBehaviour).GetMethods().Select(x => x.Name).ToList();
|
|
public override VisualElement CreatePropertyGUI(SerializedProperty property)
|
|
{
|
|
_property = property;
|
|
agent = property.Get<UnityEvent>();
|
|
|
|
root = new VisualElement
|
|
{
|
|
style =
|
|
{
|
|
paddingLeft = 10,
|
|
paddingTop = 10,
|
|
paddingRight = 10,
|
|
paddingBottom = 10,
|
|
}
|
|
};
|
|
|
|
root.styleSheets.Add(BITEditorUtils.InspectorStyleSheet);
|
|
|
|
Update();
|
|
|
|
return root;
|
|
}
|
|
|
|
private void Update()
|
|
{
|
|
root.Clear();
|
|
|
|
var targets = _property.FindPropertyRelative(nameof(UnityEvent.Targets));
|
|
|
|
_property.serializedObject.Update();
|
|
|
|
var label = root.Create<Label>();
|
|
|
|
label.text = _property.displayName;
|
|
|
|
var flex = root.Create<VisualElement>();
|
|
|
|
flex.style.flexDirection = FlexDirection.Row;
|
|
|
|
var containers = new[] { flex.Create<VisualElement>(), flex.Create<VisualElement>(),flex.Create<VisualElement>() };
|
|
|
|
containers[1].style.flexGrow = 1;
|
|
|
|
for (var i = 0; i < targets.arraySize; i++)
|
|
{
|
|
var x = agent.Targets[i];
|
|
|
|
var objectField = containers[0].Create<ObjectField>();
|
|
var field = containers[1].Create<DropdownField>();
|
|
var removeButton = containers[2].Create<Button>();
|
|
|
|
|
|
var data = targets.GetArrayElementAtIndex(i);
|
|
var target = data.FindPropertyRelative(nameof(UnityEventData.Target));
|
|
|
|
objectField.BindProperty(target);
|
|
|
|
if (x.Target is not null)
|
|
{
|
|
switch (x.Target)
|
|
{
|
|
case GameObject gameObject:
|
|
var methodNames = new List<string>();
|
|
foreach (var mono in gameObject.GetComponents<MonoBehaviour>())
|
|
{
|
|
foreach (var methodInfo in mono.GetComponents<MonoBehaviour>().Cast<object>().Append(gameObject)
|
|
.SelectMany(_mono => _mono
|
|
.GetType()
|
|
.GetMethods(BindingFlags.Instance | BindingFlags.Public |
|
|
BindingFlags.NonPublic))
|
|
.Where(info =>info.IsSpecialName is false && info.GetCustomAttribute<ObsoleteAttribute>() is null)
|
|
)
|
|
{
|
|
methodNames.Add($"{mono.GetType().FullName}/{methodInfo.Name}");
|
|
}
|
|
}
|
|
|
|
foreach (var VARIABLE in gameObject
|
|
.GetType()
|
|
.GetMethods()
|
|
.Where(info =>info.IsSpecialName is false && info.GetCustomAttribute<ObsoleteAttribute>() is null)
|
|
)
|
|
{
|
|
methodNames.Add(VARIABLE.Name);
|
|
}
|
|
field.choices = methodNames;
|
|
break;
|
|
default:
|
|
field.choices = x.Target
|
|
.GetType()
|
|
.GetMethods(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic)
|
|
.Where(x=>x.IsSpecialName is false)
|
|
.Where(x=>x.GetCustomAttribute<ObsoleteAttribute>() is null)
|
|
.Select(x => $"{x.Name}")
|
|
//.Where(x=>_unityMethodNames.Contains(x) is false)
|
|
.ToList();
|
|
break;
|
|
}
|
|
}
|
|
|
|
|
|
field.RegisterValueChangedCallback(changeEvent =>
|
|
{
|
|
x.MethodName = changeEvent.newValue;
|
|
EditorUtility.SetDirty(_property.serializedObject.targetObject);
|
|
});
|
|
|
|
field.value = x.MethodName;
|
|
|
|
field.style.flexGrow = 1;
|
|
|
|
removeButton.text = "X";
|
|
removeButton.clicked+=()=>{
|
|
agent.Targets.Remove(x);
|
|
Update();
|
|
};
|
|
}
|
|
|
|
var addButton = root.Create<Button>();
|
|
|
|
addButton.text = "Add";
|
|
|
|
addButton.clicked += () =>
|
|
{
|
|
agent.Targets.Add(new());
|
|
Update();
|
|
};
|
|
|
|
var invokeButton = root.Create<Button>();
|
|
invokeButton.text = "Invoke";
|
|
invokeButton.clicked +=()=> agent.Invoke();
|
|
}
|
|
}
|
|
#endif
|
|
}
|
|
|
|
|