using System; using System.Collections; using System.Collections.Generic; using System.Reflection; using UnityEngine; using UnityEngine.SceneManagement; public class MonoBehaviourExtended : MonoBehaviour { [AttributeUsage(AttributeTargets.Field, AllowMultiple = true)] protected class DependencyAttribute : PropertyAttribute { public string Of { get; set; } public int Offset { get; set; } public bool Optional { get; set; } public DependencyAttribute() { } public DependencyAttribute(int generationOffset) { Offset = generationOffset; } public override string ToString() { string text = base.ToString(); return text.Remove(0, text.IndexOf('+') + 1); } } protected class ComponentDependencyAttribute : DependencyAttribute { public ComponentDependencyAttribute(int generationOffset = 0) : base(generationOffset) { } } protected class OwnComponentAttribute : ComponentDependencyAttribute { public OwnComponentAttribute(int generationOffset = 0) : base(generationOffset) { } } protected class ComponentAttribute : ComponentDependencyAttribute { public ComponentAttribute(int generationOffset = 0) : base(generationOffset) { } } protected class GlobalComponentAttribute : ComponentDependencyAttribute { } protected class ReferenceComponentAttribute : ComponentDependencyAttribute { public bool DeepSearch { get; set; } public ReferenceComponentAttribute(bool deepSearch = false) { DeepSearch = deepSearch; } } protected class ChildComponentAttribute : ComponentDependencyAttribute { public bool SkipItself { get; set; } public ChildComponentAttribute(int generationOffset = 0) : base(generationOffset) { } } protected class ParentComponentAttribute : ComponentDependencyAttribute { public bool SkipItself { get; set; } public ParentComponentAttribute(int generationOffset = 0) : base(generationOffset) { } } protected class SiblingComponentAttribute : ComponentDependencyAttribute { public bool SkipItself { get; set; } public SiblingComponentAttribute(int generationOffset = 0) : base(generationOffset) { } } protected class FamilyComponentAttribute : ComponentDependencyAttribute { public bool SkipItself { get; set; } public bool FromRoot { get; set; } public int Generations { get; set; } public FamilyComponentAttribute(int generationsBackwards = 1) { Generations = generationsBackwards; } public FamilyComponentAttribute(bool fromRoot, int generationOffset = 0) { Generations = generationOffset; FromRoot = fromRoot; } } protected class ReferencePointAttribute : PropertyAttribute { } protected class GameObjectDependencyAttribute : DependencyAttribute { protected virtual string Named { get; set; } public string GetName() { return Named; } public GameObjectDependencyAttribute(int generationOffset = 0) : base(generationOffset) { } } protected class ChildAttribute : GameObjectDependencyAttribute { public int Index { get; set; } public ChildAttribute(int childIndex = 0) { Index = childIndex; } public ChildAttribute(string name) { Named = name; Index = -1; } } protected class ParentAttribute : GameObjectDependencyAttribute { public ParentAttribute(int parentIndex = 0) : base(parentIndex) { } public ParentAttribute(string name) { Named = name; } } protected class ReferenceAttribute : GameObjectDependencyAttribute { protected override string Named { get { return base.Of; } set { base.Of = value; } } public ReferenceAttribute(string name) { base.Of = name; } } protected class RootAttribute : GameObjectDependencyAttribute { public int FromTop { get; set; } public RootAttribute(int toSkipFromTop = 0) { FromTop = toSkipFromTop; } public RootAttribute(string name) { Named = name; } } protected class SiblingAttribute : GameObjectDependencyAttribute { public int Index { get; set; } public SiblingAttribute(int siblingIndex) { Index = siblingIndex; } public SiblingAttribute(string name) { Named = name; Index = -1; } } private class SceneOrDdols { private Scene? scene; public SceneOrDdols(GameObject go) { try { scene = go.scene; } catch { scene = null; } } public bool IsScene() { return scene.HasValue; } public Scene GetScene() { return scene.Value; } public GameObject[] GetRootGameObjects() { if (IsScene()) { return GetRoots(GetScene()).ToArray(); } return GetDontDestroyOnLoadObjects().ToArray(); } public int GetRootCount() { if (IsScene()) { return GetScene().rootCount; } return GetDontDestroyOnLoadObjects().Count; } public override string ToString() { if (IsScene()) { return scene.Value.name; } return "DDOLs Scene"; } public bool Equals(Scene scene2) { if (scene.HasValue) { return scene.Value == scene2; } return false; } } protected internal class ToSkip : MonoBehaviour { } public static int Verbosity { get; set; } protected static void Log(string msg, bool quietly) { Log(msg, quietly ? 1 : 0); } protected static void Log(string msg, int minVerbosity = 0) { if (Verbosity >= minVerbosity) { Debug.Log(msg); } } protected static void LogWarning(string msg, bool quietly) { LogWarning(msg, quietly ? 1 : (-1)); } protected static void LogWarning(string msg, int minVerbosity = -1) { if (Verbosity >= 2) { Debug.Log("Warning: " + msg); } if (Verbosity >= minVerbosity) { Debug.LogWarning(msg); } } public static List GetDontDestroyOnLoadObjects() { List list = new List(); for (int i = 0; i < SceneManager.sceneCount; i++) { list.AddRange(SceneManager.GetSceneAt(i).GetRootGameObjects()); } List list2 = new List(); Transform[] array = Resources.FindObjectsOfTypeAll(); foreach (Transform transform in array) { if (transform.parent == null && transform.hideFlags == HideFlags.None && !list.Contains(transform.gameObject)) { list2.Add(transform.gameObject); } } list2.Sort((GameObject x, GameObject y) => string.Compare(x.name, y.name)); return list2; } private Transform GetOffsetTransform(Transform t, int offset) { if (t == null) { return null; } if (offset > 0) { for (int i = 0; i < offset; i++) { t = t.parent; if (t == null) { break; } } } else { for (int j = offset; j < 0; j++) { if (t.childCount == 0) { break; } t = t.GetChild(0); } } return t; } private object GetReferenceComponent(List references, MethodInfo method) { if (references.Count == 0) { LogWarning("There are no [ReferencePoint] GameObjects to search in for the [ReferenceComponent] in " + this?.ToString() + ". For automatic search use [Component] instead."); return null; } object obj = null; foreach (GameObject reference in references) { Transform obj2; try { obj2 = reference.transform; } catch { continue; } object[] parameters = new Type[0]; obj = method.Invoke(obj2, parameters); if (obj != null) { break; } } return obj; } private Transform FindGameObjectInChildren(Transform parent, string name) { for (int i = 0; i < parent.childCount; i++) { Transform child = parent.GetChild(i); if (child.gameObject.name.Equals(name)) { return child; } } for (int j = 0; j < parent.childCount; j++) { Transform child2 = parent.GetChild(j); Transform transform = FindGameObjectInChildren(child2, name); if (transform != null) { return transform; } } return null; } private Transform FindGameObjectIn(Transform parent, string name) { if (parent.gameObject.name.Equals(name)) { return parent; } return FindGameObjectInChildren(parent, name); } private List GetScenes(Transform startPoint) { List list = new List(); SceneOrDdols sceneOrDdols = new SceneOrDdols(startPoint?.gameObject); if (sceneOrDdols.IsScene()) { list.Add(sceneOrDdols.GetScene()); } for (int i = 0; i < SceneManager.sceneCount; i++) { Scene sceneAt = SceneManager.GetSceneAt(i); if (!sceneOrDdols.Equals(sceneAt)) { list.Add(sceneAt); } } return list; } private static List GetRoots(Scene scene) { List list = new List(scene.GetRootGameObjects()); list.Sort((GameObject x, GameObject y) => string.Compare(x.name, y.name)); return list; } private GameObject FindGameObject(string name, List delayedScenes) { Transform parent = base.transform; Transform transform = FindGameObjectIn(parent, name); if (transform != null) { return transform.gameObject; } while (parent.parent != null) { Transform transform2 = parent; parent = parent.parent; if (transform2.gameObject.name.Equals(name)) { return transform2.gameObject; } for (int i = 0; i < parent.childCount; i++) { Transform child = parent.GetChild(i); if (child != transform2 && child.gameObject.name.Equals(name)) { return child.gameObject; } } for (int j = 0; j < parent.childCount; j++) { Transform child2 = parent.GetChild(j); if (child2 != transform2) { transform = FindGameObjectInChildren(parent, name); if (transform != null) { return child2.gameObject; } } } } if (parent.name.Equals(name)) { return parent.gameObject; } List scenes = GetScenes(parent); foreach (Scene item in scenes) { foreach (GameObject root in GetRoots(item)) { if (root.name.Equals(name)) { return root; } } if (!item.isLoaded) { delayedScenes.Add(item); } } List dontDestroyOnLoadObjects = GetDontDestroyOnLoadObjects(); foreach (GameObject item2 in dontDestroyOnLoadObjects) { if (item2.name.Equals(name)) { return item2; } } foreach (Scene item3 in scenes) { foreach (GameObject root2 in GetRoots(item3)) { if (root2.transform != parent) { transform = FindGameObjectInChildren(root2.transform, name); if (transform != null) { return transform.gameObject; } } } } foreach (GameObject item4 in dontDestroyOnLoadObjects) { transform = FindGameObjectInChildren(item4.transform, name); if (transform != null) { return transform.gameObject; } } return null; } private GameObject FindGameObject(DependencyAttribute a, FieldInfo f, List references, out bool isDelayed) { isDelayed = false; string of = a.Of; GameObject gameObject = null; List list = new List(); if (references.Count != 0) { FieldInfo field = GetType().GetField(of, BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic); if (field != null && field.GetCustomAttribute(typeof(ReferencePointAttribute)) != null) { object value = field.GetValue(this); try { if (value != null) { if (value is GameObject result) { return result; } if (value is Transform { gameObject: var result2 }) { return result2; } } } catch { Debug.LogError("The " + field?.ToString() + " field in " + this?.ToString() + " is most likely unassigned."); } } else { gameObject = FindGameObjectIn(references, of); if (gameObject == null) { gameObject = FindGameObject(a.Of, list); } } } else { gameObject = FindGameObject(a.Of, list); } if (gameObject == null) { if (list.Count != 0) { isDelayed = true; StartCoroutine(FindGameObjectInScenes(list, a, f, references)); } else { if (!a.Optional) { LogWarning("No GameObject named \"" + a.Of + "\" was found for [" + a?.ToString() + "] " + f?.ToString() + " in " + this?.ToString() + ". Creating one..."); return new GameObject(a.Of); } Log("No GameObject named \"" + a.Of + "\" was found for [" + a?.ToString() + "] " + f?.ToString() + " in " + this?.ToString() + " but it's optional.", quietly: true); } } return gameObject; } private GameObject FindGameObjectIn(IEnumerable list, string name) { foreach (GameObject item in list) { try { if (item.name.Equals(name)) { return item; } } catch { } } return null; } private IEnumerator InitDelayedSingleton(Type singletonType, FieldInfo f) { for (int i = 0; i < SceneManager.sceneCount; i++) { Scene scene = SceneManager.GetSceneAt(i); while (!scene.isLoaded) { yield return null; } } object value = singletonType.GetProperty("Instance").GetValue(null); if (value != null) { f.SetValue(this, value); Log("The [GlobalComponent] " + f?.ToString() + " field in " + this?.ToString() + " has been initialized with a delay. Don't use it in Start() & Awake()!"); } } private IEnumerator WaitForScenesToLoad(IEnumerable scenes) { foreach (Scene scene in scenes) { while (!scene.isLoaded) { yield return null; } } } private GameObject FindGameObjectInScenes(IEnumerable scenes, string name, bool deepSearch = true) { foreach (Scene scene in scenes) { foreach (GameObject root in GetRoots(scene)) { if (root.transform.name.Equals(name)) { return root; } } } if (deepSearch) { foreach (Scene scene2 in scenes) { foreach (GameObject root2 in GetRoots(scene2)) { Transform transform = FindGameObjectInChildren(root2.transform, name); if (transform != null) { return transform.gameObject; } } } } return null; } private IEnumerator FindGameObjectInScenes(IEnumerable scenes, DependencyAttribute a, FieldInfo f, List references = null) { yield return StartCoroutine(WaitForScenesToLoad(scenes)); GameObject gameObject = FindGameObjectInScenes(scenes, a.Of); if (gameObject == null) { if (a.Optional) { Log("No GameObject named \"" + a.Of + "\" was found for [" + a?.ToString() + "] " + f?.ToString() + " in " + this?.ToString() + " but it's optional.", quietly: true); yield break; } LogWarning("No GameObject named \"" + a.Of + "\" was found for [" + a?.ToString() + "] " + f?.ToString() + " in " + this?.ToString() + ". Creating one..."); gameObject = new GameObject(a.Of); } Log("The [" + a?.ToString() + "(Of = \"" + a.Of + "\")] " + f?.ToString() + " field in " + this?.ToString() + " is initialized with a delay. Don't use it in Start() & Awake()!"); Transform offsetTransform = GetOffsetTransform(gameObject.transform, a.Offset); if (a is GameObjectDependencyAttribute a2) { InitObjectField(a2, f, offsetTransform); } else if (a is ComponentDependencyAttribute a3) { InitComponentField(a3, GetType(), f, offsetTransform, references); } } private MethodInfo GetTopMethod(Type type) { return GetType().GetMethod("GetComponent", new Type[0]).MakeGenericMethod(type); } private MethodInfo GetDeepMethod(Type type) { return GetType().GetMethod("GetComponentInChildren", new Type[0]).MakeGenericMethod(type); } private bool HasToSkip(Transform t) { if (t.GetComponent() == null) { return false; } return true; } private object FindComponentInChildren(Transform parent, MethodInfo method) { for (int i = 0; i < parent.childCount; i++) { Transform child = parent.GetChild(i); if (!HasToSkip(child)) { object[] parameters = new Type[0]; object obj = method.Invoke(child, parameters); if (obj != null) { return obj; } } } for (int j = 0; j < parent.childCount; j++) { Transform child2 = parent.GetChild(j); if (!HasToSkip(child2)) { object obj2 = FindComponentInChildren(child2, method); if (obj2 != null) { return obj2; } } } return null; } private object FindComponentIn(Transform parent, MethodInfo method) { if (HasToSkip(parent)) { return null; } object[] parameters = new Type[0]; object obj = method.Invoke(parent, parameters); if (obj != null) { return obj; } return FindComponentInChildren(parent, method); } private IEnumerator FindComponentInScenes(IEnumerable scenes, FieldInfo f, bool deepSearch, bool isOptional, GameObject toSkip = null) { MethodInfo method = (deepSearch ? GetDeepMethod(f.FieldType) : GetTopMethod(f.FieldType)); if (toSkip != null) { toSkip.AddComponent(); } object target = null; foreach (Scene scene in scenes) { while (!scene.isLoaded) { yield return null; } foreach (GameObject root in GetRoots(scene)) { if (toSkip == root) { continue; } if (!deepSearch || toSkip == null) { Transform obj = root.transform; object[] parameters = new Type[0]; target = method.Invoke(obj, parameters); } else { target = FindComponentIn(root.transform, GetTopMethod(f.FieldType)); } if (target == null) { continue; } goto end_IL_008d; } } end_IL_008d: if (toSkip != null) { UnityEngine.Object.DestroyImmediate(toSkip.GetComponent()); } if (target == null && toSkip != null && deepSearch) { target = GetComponentOnlyInChildren(toSkip.transform, method); } if (f.GetValue(this) != null && deepSearch) { yield break; } if (target != null) { f.SetValue(this, target); Log("The " + f?.ToString() + " field in " + this?.ToString() + " has been initialized with a delay. Don't use it in Start() & Awake()!"); } else if (f.GetValue(this) == null) { if (isOptional) { Log("Instance of " + f?.ToString() + " not found for " + this?.ToString() + " but it's optional.", quietly: true); } else { LogWarning("Instance of " + f?.ToString() + " not found for " + this?.ToString() + ". Creating it with a delay... Don't use it in Start() & Awake()!"); CreateComponent(new GlobalComponentAttribute(), f, null, null); } } } private object FindInRoots(FieldInfo f, bool deepSearch, bool isOptional, GameObject startPoint, out bool isDelayed, bool skip = false) { MethodInfo methodInfo = (deepSearch ? GetDeepMethod(f.FieldType) : GetTopMethod(f.FieldType)); Transform parent = null; int siblingIndex = -1; if (skip && startPoint != null) { parent = startPoint.transform.parent; siblingIndex = startPoint.transform.GetSiblingIndex(); startPoint.transform.SetParent(null); } isDelayed = false; List list = new List(); object obj = null; foreach (Scene scene in GetScenes(startPoint?.transform)) { foreach (GameObject root in GetRoots(scene)) { if (!skip || !(startPoint == root)) { Transform obj2 = root.transform; object[] parameters = new Type[0]; obj = methodInfo.Invoke(obj2, parameters); if (obj != null) { goto end_IL_00fb; } } } if (!scene.isLoaded) { list.Add(scene); } continue; end_IL_00fb: break; } if (obj == null) { foreach (GameObject dontDestroyOnLoadObject in GetDontDestroyOnLoadObjects()) { if (!skip || !(startPoint == dontDestroyOnLoadObject)) { Transform obj3 = dontDestroyOnLoadObject.transform; object[] parameters = new Type[0]; obj = methodInfo.Invoke(obj3, parameters); if (obj != null) { break; } } } } if (skip && startPoint != null) { startPoint.transform.SetParent(parent); startPoint.transform.SetSiblingIndex(siblingIndex); } if (obj == null) { if (list.Count != 0) { isDelayed = true; StartCoroutine(FindComponentInScenes(list, f, deepSearch, isOptional, skip ? startPoint : null)); } else if (skip && startPoint != null && deepSearch) { obj = GetComponentOnlyInChildren(startPoint.transform, methodInfo); } } return obj; } private object GetComponentOnlyInChildren(Transform parent, MethodInfo method) { for (int i = 0; i < parent.childCount; i++) { Transform child = parent.GetChild(i); object[] parameters = new Type[0]; object obj = method.Invoke(child, parameters); if (obj != null) { return obj; } } return null; } private object GetSingletonComponent(FieldInfo f, out bool isDelayed) { isDelayed = false; try { Type fieldType = f.FieldType; Type type = typeof(MonoBehaviourSingleton<>).MakeGenericType(fieldType); if (fieldType.IsSubclassOf(type)) { object value = type.GetProperty("Instance").GetValue(null); if (value == null) { StartCoroutine(InitDelayedSingleton(type, f)); isDelayed = true; } return value; } } catch { return null; } return null; } private void InitComponentField(ComponentDependencyAttribute a, Type t, FieldInfo f, Transform startPoint, List references) { object obj = null; if (a is ChildComponentAttribute childComponentAttribute) { if (startPoint != null) { MethodInfo deepMethod = GetDeepMethod(f.FieldType); if (childComponentAttribute.SkipItself) { obj = GetComponentOnlyInChildren(startPoint, deepMethod); } else { Transform obj2 = startPoint; object[] parameters = new Type[0]; obj = deepMethod.Invoke(obj2, parameters); } } else { obj = FindInRoots(f, deepSearch: true, a.Optional, base.transform.gameObject, out var isDelayed); if (isDelayed) { return; } } } else if (a is FamilyComponentAttribute familyComponentAttribute) { Transform transform = startPoint; startPoint = ((!familyComponentAttribute.FromRoot) ? GetOffsetTransform(startPoint, familyComponentAttribute.Generations) : GetRoot(startPoint, familyComponentAttribute.Generations)); if (startPoint != null) { MethodInfo deepMethod2 = GetDeepMethod(f.FieldType); if (familyComponentAttribute.SkipItself) { Transform parent = transform.parent; int siblingIndex = transform.GetSiblingIndex(); transform.SetParent(null); if (startPoint != transform) { Transform obj3 = startPoint; object[] parameters = new Type[0]; obj = deepMethod2.Invoke(obj3, parameters); } if (obj == null && startPoint.root != transform) { obj = GetComponentOnlyInChildren(transform, deepMethod2); } transform.SetParent(parent); transform.SetSiblingIndex(siblingIndex); } else { Transform obj4 = startPoint; object[] parameters = new Type[0]; obj = deepMethod2.Invoke(obj4, parameters); } } else { obj = FindInRoots(f, deepSearch: true, a.Optional, transform?.gameObject, out var isDelayed2, familyComponentAttribute.SkipItself); if (isDelayed2) { return; } } } else if (a is ParentComponentAttribute parentComponentAttribute) { if (parentComponentAttribute.SkipItself) { startPoint = startPoint?.parent; } if (startPoint != null) { MethodInfo methodInfo = t.GetMethod("GetComponentInParent", new Type[0]).MakeGenericMethod(f.FieldType); Transform obj5 = startPoint; object[] parameters = new Type[0]; obj = methodInfo.Invoke(obj5, parameters); } } else if (a is GlobalComponentAttribute) { if (a.Of != null && startPoint != null) { MethodInfo topMethod = GetTopMethod(f.FieldType); Transform obj6 = startPoint; object[] parameters = new Type[0]; obj = topMethod.Invoke(obj6, parameters); } if (obj == null) { if (!a.Optional) { obj = GetSingletonComponent(f, out var isDelayed3); if (isDelayed3) { return; } } if (obj == null) { obj = FindInRoots(f, deepSearch: false, a.Optional, startPoint.gameObject, out var isDelayed4); if (obj == null) { obj = FindInRoots(f, deepSearch: true, a.Optional, startPoint.gameObject, out var isDelayed5); if (obj == null && (isDelayed4 || isDelayed5)) { return; } } } } } else if (a is SiblingComponentAttribute siblingComponentAttribute) { Transform transform2 = startPoint?.parent; if (transform2 != null) { MethodInfo topMethod2 = GetTopMethod(f.FieldType); if (siblingComponentAttribute.SkipItself) { int siblingIndex2 = startPoint.GetSiblingIndex(); startPoint.SetParent(null); obj = GetComponentOnlyInChildren(transform2, topMethod2); startPoint.SetParent(transform2); startPoint.SetSiblingIndex(siblingIndex2); } else { obj = GetComponentOnlyInChildren(transform2, topMethod2); } } else { obj = FindInRoots(f, deepSearch: false, a.Optional, startPoint?.gameObject, out var isDelayed6, siblingComponentAttribute.SkipItself); if (isDelayed6) { return; } } } else if (a is OwnComponentAttribute) { if (startPoint != null) { MethodInfo topMethod3 = GetTopMethod(f.FieldType); Transform obj7 = startPoint; object[] parameters = new Type[0]; obj = topMethod3.Invoke(obj7, parameters); } } else if (a is ReferenceComponentAttribute referenceComponentAttribute) { MethodInfo methodInfo2 = (referenceComponentAttribute.DeepSearch ? GetDeepMethod(f.FieldType) : GetTopMethod(f.FieldType)); if (a.Of != null) { if (startPoint != null) { Transform obj8 = startPoint; object[] parameters = new Type[0]; obj = methodInfo2.Invoke(obj8, parameters); } } else { obj = GetReferenceComponent(references, methodInfo2); } } else if (a is ComponentAttribute) { if (!a.Optional && a.Of == null) { obj = GetSingletonComponent(f, out var isDelayed7); if (isDelayed7) { return; } } MethodInfo topMethod4 = GetTopMethod(f.FieldType); if (obj == null && a.Of == null && references.Count != 0) { obj = GetReferenceComponent(references, topMethod4); } if (obj == null && startPoint != null) { MethodInfo deepMethod3 = GetDeepMethod(f.FieldType); Transform obj9 = startPoint; object[] parameters = new Type[0]; obj = deepMethod3.Invoke(obj9, parameters); while (obj == null) { Transform transform3 = startPoint; Transform parent2 = startPoint.parent; if (parent2 == null) { break; } startPoint = parent2; parameters = new Type[0]; obj = topMethod4.Invoke(transform3, parameters); if (obj == null) { obj = GetComponentOnlyInChildren(startPoint, topMethod4); } if (obj != null) { continue; } for (int i = 0; i < startPoint.childCount; i++) { Transform child = startPoint.GetChild(i); if (child != transform3) { obj = GetComponentOnlyInChildren(child, deepMethod3); } if (obj != null) { break; } } } } if (obj == null) { if (startPoint != null) { Transform obj10 = startPoint; object[] parameters = new Type[0]; obj = topMethod4.Invoke(obj10, parameters); } if (obj == null) { obj = FindInRoots(f, deepSearch: true, a.Optional, startPoint?.gameObject, out var isDelayed8, startPoint != null); if (isDelayed8) { return; } } } } if (obj == null) { if (a.Optional) { Log("Instance of [" + a?.ToString() + "] " + f?.ToString() + " not found for " + this?.ToString() + " but it's optional.", quietly: true); } else { LogWarning("Instance of [" + a?.ToString() + "] " + f?.ToString() + " not found for " + this?.ToString() + ". Creating one..."); CreateComponent(a, f, startPoint, references); } } else { f.SetValue(this, obj); } } private Transform GetChild(Transform parent, int index) { if (index < 0 || index >= parent.childCount) { return null; } return parent.GetChild(index); } private Transform GetRoot(Transform startPoint, int offsetFromTop) { int num = 0; Transform transform = startPoint; while (transform.parent != null) { num++; transform = transform.parent; } if (offsetFromTop != 0) { transform = startPoint; num -= Mathf.Abs(offsetFromTop); transform = GetOffsetTransform(transform, num); } return transform; } private Transform GetTransformByStartPoint(GameObjectDependencyAttribute a, FieldInfo f, Transform startPoint) { if (startPoint == null) { return null; } Transform transform = null; if (a is ParentAttribute) { transform = startPoint.parent; } else if (a is ChildAttribute childAttribute) { transform = GetChild(startPoint, childAttribute.Index); if (transform == null) { string msg = "ChildIndex of [" + a?.ToString() + "(" + childAttribute.Index + ")] " + f?.ToString() + " in " + this?.ToString() + " is out of rage of " + startPoint.name + "'s children."; if (a.Optional) { Log(msg, quietly: true); } else { LogWarning(msg); } } } else if (a is SiblingAttribute siblingAttribute) { Transform parent = startPoint.parent; if (parent != null) { transform = GetChild(parent, siblingAttribute.Index); if (transform == null) { string msg2 = "ChildIndex of [" + a?.ToString() + "(" + siblingAttribute.Index + ")] " + f?.ToString() + " in " + this?.ToString() + " is out of rage of " + parent.name + "'s children."; if (a.Optional) { Log(msg2, quietly: true); } else { LogWarning(msg2); } } } else { SceneOrDdols sceneOrDdols = new SceneOrDdols(startPoint.gameObject); GameObject[] rootGameObjects = sceneOrDdols.GetRootGameObjects(); int index = siblingAttribute.Index; if (index < 0 || index >= rootGameObjects.Length) { string msg3 = "ChildIndex of [" + a?.ToString() + "(" + index + ")] " + f?.ToString() + " in " + this?.ToString() + " is out of rage of " + sceneOrDdols?.ToString() + "'s roots."; if (a.Optional) { Log(msg3, quietly: true); } else { LogWarning(msg3); } } else { transform = rootGameObjects[index].transform; } } } else if (a is ReferenceAttribute) { transform = startPoint; } else if (a is RootAttribute rootAttribute) { transform = GetRoot(startPoint, rootAttribute.FromTop); } return transform; } private IEnumerator FindGameObjectInRoots(GameObjectDependencyAttribute a, IEnumerable scenes, FieldInfo f, bool isOptional, string name, bool deepSearch) { yield return StartCoroutine(WaitForScenesToLoad(scenes)); GameObject gameObject = FindGameObjectInScenes(scenes, name, deepSearch); if (gameObject == null) { if (f.GetValue(this) != null) { yield break; } if (isOptional) { Log("No GameObject named \"" + name + "\" was found for [" + a?.ToString() + "] " + f?.ToString() + " in " + this?.ToString() + " but it's optional.", quietly: true); yield break; } LogWarning("No GameObject named \"" + name + "\" was found for [" + a?.ToString() + "] " + f?.ToString() + " in " + this?.ToString() + ". Creating one..."); gameObject = new GameObject(name); } if (f.FieldType == typeof(GameObject)) { f.SetValue(this, gameObject); } else { f.SetValue(this, gameObject.transform); } Log("The [" + a?.ToString() + "(Named = \"" + name + "\")] " + f?.ToString() + " field in " + this?.ToString() + " has been initialized with a delay. Don't use it in Start() & Awake()!"); } private Transform FindGameObjectInRoots(GameObjectDependencyAttribute a, FieldInfo f, bool isOptional, string name, bool deepSearch, out bool isDelayed) { isDelayed = false; List list = new List(); foreach (Scene scene in GetScenes(base.transform)) { foreach (GameObject root in GetRoots(scene)) { if (deepSearch) { Transform transform = FindGameObjectInChildren(root.transform, name); if (transform != null) { return transform; } } else if (root.transform.name.Equals(name)) { return root.transform; } } if (!scene.isLoaded) { list.Add(scene); } } if (list.Count != 0) { isDelayed = true; StartCoroutine(FindGameObjectInRoots(a, list, f, isOptional, name, deepSearch)); } return null; } private Transform GetTransformByName(GameObjectDependencyAttribute a, FieldInfo f, Transform startPoint, out bool isDelayed) { isDelayed = false; string value = a.GetName(); if (a is ParentAttribute) { if (startPoint != null) { while (startPoint.parent != null) { startPoint = startPoint.parent; if (startPoint.name.Equals(value)) { return startPoint; } } } return null; } if (a is ChildAttribute) { if (startPoint != null) { return FindGameObjectInChildren(startPoint, value); } return FindGameObjectInRoots(a, f, a.Optional, value, deepSearch: true, out isDelayed); } if (a is SiblingAttribute) { startPoint = startPoint?.parent; if (startPoint != null) { for (int i = 0; i < startPoint.childCount; i++) { Transform child = startPoint.GetChild(i); if (child.name.Equals(value)) { return child; } } return null; } return FindGameObjectInRoots(a, f, a.Optional, value, deepSearch: false, out isDelayed); } if (a is ReferenceAttribute) { return startPoint; } if (a is RootAttribute rootAttribute) { if (startPoint != null) { int num = 0; List list = new List(); Transform transform = startPoint; while (transform.parent != null) { num++; transform = transform.parent; } transform = startPoint; num -= Mathf.Abs(rootAttribute.FromTop); if (num < 0) { transform = GetOffsetTransform(startPoint, num); } for (int j = 0; j < Mathf.Abs(num); j++) { list.Add(transform); if (transform.parent == null) { break; } transform = transform.parent; } if (num < 0) { list.Reverse(); transform = GetOffsetTransform(startPoint, num); } if (transform.name.Equals(value)) { return transform; } SiblingAttribute siblingAttribute = new SiblingAttribute(value); siblingAttribute.Optional = rootAttribute.Optional; Transform transformByName = GetTransformByName(siblingAttribute, f, transform, out isDelayed); if (transformByName != null) { return transformByName; } for (int num2 = list.Count - 1; num2 >= 0; num2--) { Transform transform2 = list[num2]; if (transform2.name.Equals(value)) { return transform2; } } } else if (rootAttribute.FromTop == 0) { return FindGameObjectInRoots(a, f, a.Optional, value, deepSearch: false, out isDelayed); } } return null; } private void InitObjectField(GameObjectDependencyAttribute a, FieldInfo f, Transform startPoint) { Transform transform; if (a.GetName() == null) { transform = GetTransformByStartPoint(a, f, startPoint); } else { transform = GetTransformByName(a, f, startPoint, out var isDelayed); if (isDelayed && !(a is RootAttribute)) { return; } } if (transform == null) { if (a.Optional) { Log("Instance of [" + a?.ToString() + "] " + f?.ToString() + " not found for " + this?.ToString() + " but it's optional.", quietly: true); } else { LogWarning("Instance of [" + a?.ToString() + "] " + f?.ToString() + " not found for " + this?.ToString() + "."); CreateGameObject(a, f, startPoint); } } else if (f.FieldType == typeof(GameObject)) { f.SetValue(this, transform.gameObject); } else { f.SetValue(this, transform); } } private void CreateGameObject(GameObjectDependencyAttribute a, FieldInfo f, Transform startPoint) { if (startPoint == null) { return; } string text = a.GetName() ?? f.Name; Transform transform = new GameObject(text).transform; if (a is ParentAttribute) { transform.SetParent(startPoint.parent); startPoint.SetParent(transform); } else if (a is ChildAttribute childAttribute) { for (int i = startPoint.childCount; i < childAttribute.Index; i++) { new GameObject("Child" + (i + 1)).transform.SetParent(startPoint); } transform.SetParent(startPoint); if (childAttribute.Index >= 0) { transform.SetSiblingIndex(childAttribute.Index); } } else if (a is SiblingAttribute siblingAttribute) { Transform parent = startPoint.parent; for (int j = parent?.childCount ?? new SceneOrDdols(startPoint.gameObject).GetRootCount(); j < siblingAttribute.Index; j++) { Transform obj = new GameObject("Sibling" + (j + 1)).transform; obj.SetParent(startPoint); obj.SetParent(parent); } transform.SetParent(startPoint); transform.SetParent(parent); if (siblingAttribute.Index >= 0) { transform.SetSiblingIndex(siblingAttribute.Index); } } else if (a is RootAttribute rootAttribute) { if (rootAttribute.FromTop != 0) { int num = 0; Transform transform2 = startPoint; while (transform2.parent != null) { num++; transform2 = transform2.parent; } transform2 = startPoint; num -= Mathf.Abs(rootAttribute.FromTop); transform2 = GetOffsetTransform(transform2, num); transform.SetParent(transform2.parent); } else { transform.SetParent(startPoint); transform.SetParent(null); } } if (f.FieldType == typeof(GameObject)) { f.SetValue(this, transform.gameObject); } else { f.SetValue(this, transform); } Log("New GameObject called " + text + " has been created.", quietly: true); } private void CreateComponent(ComponentDependencyAttribute a, FieldInfo f, Transform startPoint, List references) { Type fieldType = f.FieldType; Component value = null; if (a is ChildComponentAttribute || a is FamilyComponentAttribute || a is SiblingComponentAttribute) { if (a is SiblingComponentAttribute) { startPoint = startPoint?.parent; } GameObject obj = new GameObject(fieldType.Name, fieldType); value = obj.GetComponent(fieldType); obj.transform.SetParent(startPoint); } else if (a is ParentComponentAttribute || a is GlobalComponentAttribute || a is OwnComponentAttribute || a is ComponentAttribute) { value = ((!(startPoint != null)) ? new GameObject(fieldType.Name, fieldType).GetComponent(fieldType) : startPoint.gameObject.AddComponent(fieldType)); } else if (a is ReferenceComponentAttribute) { if (a.Of != null || references.Count == 0) { if (startPoint != null) { value = startPoint.gameObject.AddComponent(fieldType); } else { GameObject obj2 = new GameObject(fieldType.Name, fieldType); value = obj2.GetComponent(fieldType); obj2.transform.SetParent(base.transform); obj2.transform.SetParent(null); } } else { value = references[Mathf.Min(a.Offset, references.Count - 1)].AddComponent(fieldType); } } f.SetValue(this, value); Log("New component [" + a?.ToString() + "] " + f?.ToString() + " for " + this?.ToString() + " has been created.", quietly: true); } protected void Awake() { Type type = GetType(); FieldInfo[] fields = type.GetFields(BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic); List list = new List(); FieldInfo[] array = fields; foreach (FieldInfo fieldInfo in array) { object[] customAttributes = fieldInfo.GetCustomAttributes(typeof(GameObjectDependencyAttribute), inherit: true); if (customAttributes.Length > 1) { for (int j = 0; j < customAttributes.Length - 1; j++) { ((GameObjectDependencyAttribute)customAttributes[j]).Optional = true; } } object[] array2 = customAttributes; for (int k = 0; k < array2.Length; k++) { GameObjectDependencyAttribute gameObjectDependencyAttribute = (GameObjectDependencyAttribute)array2[k]; if (fieldInfo.IsPublic && !fieldInfo.IsNotSerialized) { LogWarning("You tried to inject a public (serialized) GameObject! (" + fieldInfo?.ToString() + " in " + this?.ToString() + ") It should be private or marked with [NonSerialized], otherwise it may conflict with the Unity serializer and the dependency may not be injected."); } if (fieldInfo.GetValue(this) != null) { break; } if (fieldInfo.FieldType != typeof(GameObject) && fieldInfo.FieldType != typeof(Transform)) { Debug.LogError(gameObjectDependencyAttribute?.ToString() + " cannot be applied to " + fieldInfo?.ToString() + " in " + this?.ToString() + " as it's not of GameObject/Transform type."); } Transform transform = null; if (gameObjectDependencyAttribute.Of != null) { transform = FindGameObject(gameObjectDependencyAttribute, fieldInfo, list, out var _)?.transform; if (transform == null) { continue; } } else { transform = base.transform; } transform = GetOffsetTransform(transform, gameObjectDependencyAttribute.Offset); InitObjectField(gameObjectDependencyAttribute, fieldInfo, transform); } if (fieldInfo.GetCustomAttribute(typeof(ReferencePointAttribute)) != null) { if (fieldInfo.FieldType == typeof(GameObject)) { list.Add((GameObject)fieldInfo.GetValue(this)); continue; } if (fieldInfo.FieldType == typeof(Transform)) { list.Add(((Transform)fieldInfo.GetValue(this)).gameObject); continue; } Debug.LogError("ReferencePointAttribute cannot be applied to " + fieldInfo?.ToString() + " in " + this?.ToString() + " as it's not of GameObject/Transform type."); } } array = fields; foreach (FieldInfo fieldInfo2 in array) { object[] customAttributes2 = fieldInfo2.GetCustomAttributes(typeof(ComponentDependencyAttribute), inherit: true); if (customAttributes2.Length > 1) { for (int l = 0; l < customAttributes2.Length - 1; l++) { ((ComponentDependencyAttribute)customAttributes2[l]).Optional = true; } } object[] array2 = customAttributes2; for (int k = 0; k < array2.Length; k++) { ComponentDependencyAttribute componentDependencyAttribute = (ComponentDependencyAttribute)array2[k]; if (fieldInfo2.GetValue(this) != null) { break; } Transform transform2 = null; if (componentDependencyAttribute.Of != null) { transform2 = FindGameObject(componentDependencyAttribute, fieldInfo2, list, out var _)?.transform; if (transform2 == null) { continue; } } else { transform2 = base.transform; } transform2 = GetOffsetTransform(transform2, componentDependencyAttribute.Offset); InitComponentField(componentDependencyAttribute, type, fieldInfo2, transform2, list); } } } }