using UnityEngine;
using UnityEngine.UI;
using System.Collections;
using System;
using System.Collections.Generic;
using System.IO;
using System.Reflection;
#if UNITY_EDITOR
using UnityEditor;
#endif
namespace MoreMountains.Tools
{
///
/// Add this attribute to a class and its Execution Order will be changed to the value specified in parameters
/// Usage : [ExecutionOrder(66)]
///
public class MMExecutionOrderAttribute : Attribute
{
#if UNITY_EDITOR
/// the execution order you want for the class this attribute is applied to
public int ExecutionOrder = 0;
protected static Dictionary _monoScripts;
protected static Type _executionOrderAttributeType;
protected static Assembly _typeAssembly;
protected static Type[] _assemblyTypes;
///
/// Attribute method
///
///
public MMExecutionOrderAttribute(int newExecutionOrder)
{
ExecutionOrder = newExecutionOrder;
}
///
/// When Unity loads, modifies the execution orders of monos with an ExecutionOrder attribute, if needed
///
[InitializeOnLoadMethod]
protected static void ModifyExecutionOrder()
{
Initialization();
FindExecutionOrderAttributes();
if (ExecutionOrderHasChanged())
{
UpdateExecutionOrders();
}
}
///
/// Initialization method
///
protected static void Initialization()
{
_monoScripts = new Dictionary();
_executionOrderAttributeType = typeof(MMExecutionOrderAttribute);
_typeAssembly = _executionOrderAttributeType.Assembly;
_assemblyTypes = _typeAssembly.GetTypes();
}
///
/// Goes through all assembly types and stores execution order attributes when found
///
protected static void FindExecutionOrderAttributes()
{
foreach (Type assemblyType in _assemblyTypes)
{
if (!HasExecutionOrderAttribute(assemblyType))
{
continue;
}
object[] attributes = assemblyType.GetCustomAttributes(_executionOrderAttributeType, false);
MMExecutionOrderAttribute attribute = attributes[0] as MMExecutionOrderAttribute;
string asset = "";
string[] guids = AssetDatabase.FindAssets(assemblyType.Name + " t:script");
if (guids.Length != 0)
{
foreach (string guid in guids)
{
string assetPath = AssetDatabase.GUIDToAssetPath(guid);
string filename = Path.GetFileNameWithoutExtension(assetPath);
if (filename == assemblyType.Name)
{
asset = guid;
break;
}
}
}
else
{
Debug.LogError("MMTools' ExecutionOrderAttribute : Can't change "+ assemblyType.Name + "'s execution order");
return;
}
MonoScript monoScript = AssetDatabase.LoadAssetAtPath(AssetDatabase.GUIDToAssetPath(asset));
_monoScripts.Add(monoScript, attribute);
}
}
///
/// Returns true if the class in parameters has the ExecutionOrder attribute, false otherwise
///
///
///
protected static bool HasExecutionOrderAttribute(Type assemblyType)
{
object[] attributes = assemblyType.GetCustomAttributes(_executionOrderAttributeType, false);
return (attributes.Length == 1);
}
///
/// Returns true if the execution order has changed since last time
///
///
protected static bool ExecutionOrderHasChanged()
{
bool executionOrderHasChanged = false;
foreach (KeyValuePair monoScript in _monoScripts)
{
if (monoScript.Key != null)
{
if (MonoImporter.GetExecutionOrder(monoScript.Key) != monoScript.Value.ExecutionOrder)
{
executionOrderHasChanged = true;
break;
}
}
}
return executionOrderHasChanged;
}
///
/// Updates the execution orders for all pairs found by FindExecutionOrderAttributes()
///
protected static void UpdateExecutionOrders()
{
foreach (KeyValuePair monoScript in _monoScripts)
{
if (monoScript.Key != null)
{
if (MonoImporter.GetExecutionOrder(monoScript.Key) != monoScript.Value.ExecutionOrder)
{
MonoImporter.SetExecutionOrder(monoScript.Key, monoScript.Value.ExecutionOrder);
}
}
}
}
#endif
}
}