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 } }