浏览代码

Base Commit (Float Animation) // TODO : Genericize Animation

/feature-generic-animation-rigs
Thomas ICHÉ 3 年前
当前提交
67c99d51
共有 14 个文件被更改,包括 410 次插入0 次删除
  1. 181
      Editor/PropertyDrawers/ReflectedMemberyPropertyDrawer.cs
  2. 11
      Editor/PropertyDrawers/ReflectedMemberyPropertyDrawer.cs.meta
  3. 8
      Runtime/Ingredients/Rigs/GenericAnimation.meta
  4. 8
      Runtime/ReflectedMember.meta
  5. 31
      Runtime/Ingredients/Rigs/GenericAnimation/GenericAnimationRig.cs
  6. 11
      Runtime/Ingredients/Rigs/GenericAnimation/GenericAnimationRig.cs.meta
  7. 33
      Runtime/Ingredients/Rigs/GenericAnimation/GenericFloatAnimationRig.cs
  8. 11
      Runtime/Ingredients/Rigs/GenericAnimation/GenericFloatAnimationRig.cs.meta
  9. 80
      Runtime/ReflectedMember/ReflectedMember.cs
  10. 11
      Runtime/ReflectedMember/ReflectedMember.cs.meta
  11. 14
      Runtime/ReflectedMember/ReflectedMemberAttribute.cs
  12. 11
      Runtime/ReflectedMember/ReflectedMemberAttribute.cs.meta

181
Editor/PropertyDrawers/ReflectedMemberyPropertyDrawer.cs


using System.Collections.Generic;
using UnityEngine;
using UnityEditor;
using System.Reflection;
using System.Linq;
namespace GameplayIngredients.Editor
{
[CustomPropertyDrawer(typeof(ReflectedMember))]
public class ReflectedMemberyPropertyDrawer : PropertyDrawer
{
Dictionary<(Object, System.Type), string[]> cachedMemberNames;
GenericMenu nullMenu;
void CacheMembersForObject(Object obj, System.Type filterType)
{
if (obj == null)
return;
if (cachedMemberNames == null)
cachedMemberNames = new Dictionary<(Object, System.Type), string[]>();
if (!cachedMemberNames.ContainsKey((obj, filterType)))
{
List<string> names = new List<string>();
foreach (var p in obj.GetType().GetMembers(BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.SetProperty | BindingFlags.SetField))
{
if (p.MemberType == MemberTypes.Field && filterType.IsAssignableFrom((p as FieldInfo).FieldType))
names.Add(p.Name);
else if (p.MemberType == MemberTypes.Property && filterType.IsAssignableFrom((p as PropertyInfo).PropertyType))
names.Add(p.Name);
}
cachedMemberNames.Add((obj, filterType), names.ToArray());
}
}
public override void OnGUI(Rect position, SerializedProperty property, GUIContent label)
{
SerializedProperty obj = property.FindPropertyRelative("m_TargetObject");
SerializedProperty propName = property.FindPropertyRelative("m_MemberName");
float width = EditorGUIUtility.currentViewWidth;
var filterType = typeof(object);
var p = property.serializedObject.targetObject.GetType().GetMember(property.name, BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.GetProperty | BindingFlags.GetField).First();
var attr = p.GetCustomAttribute<ReflectedMemberAttribute>();
if (attr != null) // If using a ReflectedMemberAttribute for filtering type
{
var typeMember = property.serializedObject.targetObject.GetType().GetMember(attr.typeMemberName, BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.GetProperty | BindingFlags.GetField).First();
if (typeMember.DeclaringType is System.Type)
{
if (typeMember is PropertyInfo)
filterType = (typeMember as PropertyInfo).GetValue(property.serializedObject.targetObject) as System.Type;
else if (typeMember is FieldInfo)
filterType = (typeMember as FieldInfo).GetValue(property.serializedObject.targetObject) as System.Type;
}
}
Rect objRect = position;
Rect btnRect = position;
Rect propRect = position;
objRect.xMax = (width / 3) - 4;
btnRect.xMin = (width / 3);
btnRect.xMax = (2 * width / 3);
propRect.xMin = (2 * width / 3);
EditorGUI.ObjectField(objRect, obj, GUIContent.none);
var tgt = obj.objectReferenceValue;
if (tgt == null || !(tgt is GameObject || tgt is Component))
{
if (EditorGUI.DropdownButton(btnRect, GUIContent.none, FocusType.Passive))
{
if (nullMenu == null)
{
nullMenu = new GenericMenu();
nullMenu.AddDisabledItem(new GUIContent("No Game Object or Component Selected"), false);
}
nullMenu.DropDown(btnRect);
}
}
else
{
Component[] comps = null;
int sel = -1;
if (tgt is GameObject)
{
sel = 0;
comps = (tgt as GameObject).GetComponents(typeof(Component));
}
else if (tgt is Component)
{
comps = (tgt as Component).GetComponents(typeof(Component));
}
List<string> names = new List<string>();
names.Add("Game Object");
int i = 1;
foreach (var comp in comps)
{
if (comp is Callable)
names.Add($"{comp.GetType().Name} ({(comp as Callable).Name})");
else
names.Add(comp.GetType().Name);
if (tgt == comp)
sel = i;
i++;
}
EditorGUI.BeginChangeCheck();
int newSel = EditorGUI.Popup(btnRect, sel, names.ToArray());
if (EditorGUI.EndChangeCheck())
{
if (newSel == 0)
{
if (tgt is GameObject)
obj.objectReferenceValue = (tgt as GameObject);
else if (tgt is Component)
obj.objectReferenceValue = (tgt as Component).gameObject;
}
else
obj.objectReferenceValue = comps[newSel - 1];
propName.stringValue = string.Empty;
}
}
if (obj.objectReferenceValue != null)
{
CacheMembersForObject(obj.objectReferenceValue, filterType);
int propIdx = -1;
int i = 0;
if (!string.IsNullOrEmpty(propName.stringValue))
foreach (var name in cachedMemberNames[(obj.objectReferenceValue, filterType)])
{
if (propName.stringValue == name)
propIdx = i;
i++;
}
EditorGUI.BeginChangeCheck();
int newPropIdx = EditorGUI.Popup(propRect, propIdx, cachedMemberNames[(obj.objectReferenceValue, filterType)]);
if (EditorGUI.EndChangeCheck())
{
propName.stringValue = cachedMemberNames[(obj.objectReferenceValue, filterType)][newPropIdx];
}
}
else
{
using (new EditorGUI.DisabledGroupScope(true))
{
EditorGUI.DropdownButton(propRect, new GUIContent("(Please Select an object first)"), FocusType.Passive);
}
}
// Validate data
if (obj.objectReferenceValue != null)
{
if (!(obj.objectReferenceValue is GameObject || obj.objectReferenceValue is Component)) // Invalid Component Type
{
obj.objectReferenceValue = null;
propName.stringValue = string.Empty;
}
}
}
}
}

11
Editor/PropertyDrawers/ReflectedMemberyPropertyDrawer.cs.meta


fileFormatVersion: 2
guid: 101539721cd4dbd4092347cc4f9a1714
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

8
Runtime/Ingredients/Rigs/GenericAnimation.meta


fileFormatVersion: 2
guid: 2cdfdb3fcc6b5f64eb2254610fcc2891
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

8
Runtime/ReflectedMember.meta


fileFormatVersion: 2
guid: 7b4741ea51c1b4646974c0957033625f
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

31
Runtime/Ingredients/Rigs/GenericAnimation/GenericAnimationRig.cs


using System;
using UnityEngine;
namespace GameplayIngredients.Rigs
{
public abstract class GenericAnimationRig : Rig
{
public override UpdateMode defaultUpdateMode => UpdateMode.Update;
public override int defaultPriority => 0;
public override bool canChangeUpdateMode => true;
public abstract Type animatedType { get; }
[Header("Target Property / Field"), ReflectedMember("animatedType")]
public ReflectedMember property;
public override void UpdateRig(float deltaTime)
{
if (property.targetObject != null)
{
property.SetValue(UpdateAndGetValue(deltaTime));
}
}
protected abstract object UpdateAndGetValue(float deltaTime);
}
}

11
Runtime/Ingredients/Rigs/GenericAnimation/GenericAnimationRig.cs.meta


fileFormatVersion: 2
guid: 6f6acdc002a4fea4a85a07db8133241e
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

33
Runtime/Ingredients/Rigs/GenericAnimation/GenericFloatAnimationRig.cs


using NaughtyAttributes;
using System;
using UnityEngine;
namespace GameplayIngredients.Rigs
{
public class GenericFloatAnimationRig : GenericAnimationRig
{
[Header("Base Value")]
[SerializeField]
bool useStoredValueAsBase = true;
[SerializeField, DisableIf("useStoredValueAsBase")]
float baseValue = 1.0f;
[Header("Animation")]
public float frequency = 1.0f;
public float amplitude = 1.0f;
public override Type animatedType => typeof(float);
private void Awake()
{
if (useStoredValueAsBase)
baseValue = (float)property.GetValue();
}
protected override object UpdateAndGetValue(float deltaTime)
{
return Mathf.Sin(Time.time * frequency * Mathf.PI) * amplitude + baseValue;
}
}
}

11
Runtime/Ingredients/Rigs/GenericAnimation/GenericFloatAnimationRig.cs.meta


fileFormatVersion: 2
guid: 3d5a84f07865f0244beebd46a1ae8c1e
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

80
Runtime/ReflectedMember/ReflectedMember.cs


using System;
using System.Linq;
using System.Reflection;
using UnityEngine;
namespace GameplayIngredients
{
[Serializable]
public struct ReflectedMember
{
public UnityEngine.Object targetObject { get => m_TargetObject; }
public MemberInfo member { get { UpdateMember(); return m_Member; } }
[SerializeField]
UnityEngine.Object m_TargetObject;
[SerializeField]
string m_MemberName;
[SerializeField]
MemberInfo m_Member;
public void SetMember(UnityEngine.Object obj, string memberName)
{
m_TargetObject = obj;
m_MemberName = memberName;
UpdateMember();
}
public void SetValue(object value)
{
if (m_TargetObject != null)
{
if (m_Member == null)
UpdateMember();
if (m_Member.MemberType == MemberTypes.Field)
(m_Member as FieldInfo).SetValue(m_TargetObject, value);
else if (m_Member.MemberType == MemberTypes.Property)
(m_Member as PropertyInfo).SetValue(m_TargetObject, value);
else
throw new Exception($"Could not Set value of member {m_Member.Name} which is a {m_Member.MemberType}");
}
else
throw new Exception($"Could not Find member '{m_MemberName}' of target object {m_TargetObject}");
}
public T GetValue<T>()
{
return (T)GetValue();
}
public object GetValue()
{
if (m_TargetObject != null)
{
if (m_Member == null)
UpdateMember();
if (m_Member.MemberType == MemberTypes.Field)
return (m_Member as FieldInfo).GetValue(m_TargetObject);
else if (m_Member.MemberType == MemberTypes.Property)
return (m_Member as PropertyInfo).GetValue(m_TargetObject);
}
return null;
}
public void UpdateMember()
{
if (m_TargetObject == null)
return;
m_Member = m_TargetObject.GetType().GetMember(m_MemberName, BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.SetProperty | BindingFlags.SetField).First();
if (m_Member == null)
Debug.LogWarning($"Could not find member of name {m_MemberName} on type {m_TargetObject.GetType().Name}");
}
}
}

11
Runtime/ReflectedMember/ReflectedMember.cs.meta


fileFormatVersion: 2
guid: c6d25824103303749a64c4f3026ffe33
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

14
Runtime/ReflectedMember/ReflectedMemberAttribute.cs


using UnityEngine;
namespace GameplayIngredients
{
public class ReflectedMemberAttribute : PropertyAttribute
{
public string typeMemberName;
public ReflectedMemberAttribute(string typeMemberName)
{
this.typeMemberName = typeMemberName;
}
}
}

11
Runtime/ReflectedMember/ReflectedMemberAttribute.cs.meta


fileFormatVersion: 2
guid: b835f96fcf72cb8449ff1447a1f36812
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
正在加载...
取消
保存