Automatic binding of component references
// MIT License | |
// | |
// Copyright (c) 2018 Sabresaurus | |
// | |
// Permission is hereby granted, free of charge, to any person obtaining a copy | |
// of this software and associated documentation files (the "Software"), to deal | |
// in the Software without restriction, including without limitation the rights | |
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell | |
// copies of the Software, and to permit persons to whom the Software is | |
// furnished to do so, subject to the following conditions: | |
// | |
// The above copyright notice and this permission notice shall be included in all | |
// copies or substantial portions of the Software. | |
// | |
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | |
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | |
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE | |
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | |
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, | |
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE | |
// SOFTWARE. | |
using UnityEngine; | |
using System; | |
using System.Reflection; | |
using System.Collections.Generic; | |
public enum RecursiveDirection { None, Down, Up }; | |
public class AutoComponent : Attribute | |
{ | |
RecursiveDirection direction = RecursiveDirection.None; | |
bool includeInactive = false; | |
public AutoComponent() | |
{} | |
public AutoComponent(RecursiveDirection direction) | |
{ | |
this.direction = direction; | |
} | |
public AutoComponent(RecursiveDirection direction, bool includeInactive) | |
{ | |
this.direction = direction; | |
this.includeInactive = includeInactive; | |
} | |
private static List<FieldInfo> GetFieldsRecursively(Type type) | |
{ | |
List<FieldInfo> fields = new List<FieldInfo>(); | |
fields.AddRange(type.GetFields(BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance)); | |
// NonPublic binding flags only returns fields on the current inheritance level, therefore we must recurse through the superclasses to get them all | |
Type baseType = type.BaseType; | |
while (baseType != null) | |
{ | |
// Add the non-public fields on the superclass | |
fields.AddRange(baseType.GetFields(BindingFlags.NonPublic | BindingFlags.Instance)); | |
// Get the next superclass | |
baseType = baseType.BaseType; | |
} | |
return fields; | |
} | |
public static void Setup(MonoBehaviour behaviour) | |
{ | |
List<FieldInfo> fields = GetFieldsRecursively(behaviour.GetType()); | |
for (int i = 0; i < fields.Count; i++) | |
{ | |
object[] customAttributes = fields[i].GetCustomAttributes(typeof(AutoComponent), false); | |
if(customAttributes.Length > 0) | |
{ | |
RecursiveDirection recursiveDirection = (customAttributes[0] as AutoComponent).direction; | |
// If this is an array or list | |
if (typeof(Array).IsAssignableFrom(fields[i].FieldType)) | |
{ | |
Type elementType = fields[i].FieldType.GetElementType(); | |
Component[] components; | |
if(recursiveDirection == RecursiveDirection.Down) | |
{ | |
components = behaviour.GetComponentsInChildren(elementType, (customAttributes[0] as AutoComponent).includeInactive); | |
} | |
else if(recursiveDirection == RecursiveDirection.Up) | |
{ | |
components = behaviour.GetComponentsInParent(elementType, (customAttributes[0] as AutoComponent).includeInactive); | |
} | |
else | |
{ | |
components = behaviour.GetComponents(elementType); | |
} | |
Array array = Array.CreateInstance(elementType, components.Length); | |
for (int j = 0; j < components.Length; j++) | |
{ | |
array.SetValue(components[j], j); | |
} | |
fields[i].SetValue(behaviour, array); | |
} | |
else | |
{ | |
if(recursiveDirection == RecursiveDirection.Down) | |
{ | |
fields[i].SetValue(behaviour, behaviour.GetComponentInChildren(fields[i].FieldType, (customAttributes[0] as AutoComponent).includeInactive)); | |
} | |
else if(recursiveDirection == RecursiveDirection.Up) | |
{ | |
fields[i].SetValue(behaviour, behaviour.GetComponentInParent(fields[i].FieldType)); | |
} | |
else | |
{ | |
fields[i].SetValue(behaviour, behaviour.GetComponent(fields[i].FieldType)); | |
} | |
} | |
} | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment