using System; using System.Text; using NitroxClient.MonoBehaviours; using NitroxModel.DataStructures; using NitroxModel.Helper; using UnityEngine; using Object = UnityEngine.Object; namespace NitroxClient.Unity.Helper { public static class GameObjectHelper { public static bool TryGetComponentInChildren(this GameObject go, out T component, bool includeInactive = false) where T : Component { component = go.GetComponentInChildren(includeInactive); return component; } public static bool TryGetComponentInParent(this GameObject go, out T component, bool includeInactive = false) where T : Component { component = go.GetComponentInParent(includeInactive); return component; } public static bool TryGetComponentInChildren(this Component co, out T component, bool includeInactive = false) where T : Component => TryGetComponentInChildren(co.gameObject, out component, includeInactive); public static bool TryGetComponentInParent(this Component co, out T component, bool includeInactive = false) where T : Component => TryGetComponentInParent(co.gameObject, out component, includeInactive); public static T RequireComponent(this GameObject o) where T : Component { T component = o.GetComponent(); Validate.IsTrue(component, $"{o.name} did not have a component of type {typeof(T)}"); return component; } public static T RequireComponentInChildren(this GameObject o, bool includeInactive = false) where T : Component { T component = o.GetComponentInChildren(includeInactive); Validate.IsTrue(component, $"{o.name} did not have a component of type {typeof(T)} in its children"); return component; } public static T RequireComponentInParent(this GameObject o) where T : Component { T component = o.GetComponentInParent(); Validate.IsTrue(component, $"{o.name} did not have a component of type {typeof(T)} in its parent"); return component; } public static T RequireComponent(this Component co) where T : Component => RequireComponent(co.gameObject); public static T RequireComponentInChildren(this Component co, bool includeInactive = false) where T : Component => RequireComponentInChildren(co.gameObject, includeInactive); public static T RequireComponentInParent(this Component co) where T : Component => RequireComponentInParent(co.gameObject); public static Transform RequireTransform(this Transform tf, string name) { Transform child = tf.Find(name); if (!child) { throw new ArgumentNullException($@"{tf} does not contain ""{name}"""); } return child; } public static Transform RequireTransform(this GameObject go, string name) => go.transform.RequireTransform(name); public static Transform RequireTransform(this MonoBehaviour mb, string name) => mb.transform.RequireTransform(name); public static GameObject RequireGameObject(this Transform tf, string name) => tf.RequireTransform(name).gameObject; public static GameObject RequireGameObject(this GameObject go, string name) => go.transform.RequireGameObject(name); public static GameObject RequireGameObject(this MonoBehaviour mb, string name) => mb.transform.RequireGameObject(name); public static GameObject RequireGameObject(string name) { GameObject go = GameObject.Find(name); Validate.IsTrue(go, $"No global GameObject found with {name}!"); return go; } public static string GetFullHierarchyPath(this Component component) { return component ? $"{component.gameObject.GetFullHierarchyPath()} -> {component.GetType().Name}.cs" : ""; } public static string GetHierarchyPath(this GameObject go, GameObject end) { if (!go || go == end) { return ""; } if (!go.transform.parent) { return go.name; } StringBuilder sb = new(go.name); for (GameObject gameObject = go.transform.parent.gameObject; gameObject && gameObject != end; gameObject = gameObject.transform.parent ? gameObject.transform.parent.gameObject : null) { sb.Insert(0, $"{gameObject.name}/"); } return sb.ToString(); } public static Transform GetRootParent(this Component co) => co.transform.GetRootParent(); public static Transform GetRootParent(this GameObject go) => go.transform.GetRootParent(); public static Transform GetRootParent(this Transform root) { while (root.parent) { root = root.parent; } return root; } public static bool TryGetComponentInAscendance(this Transform transform, int degree, out T component) { while (degree > 0) { if (!transform.parent) { component = default; return false; } transform = transform.parent; degree--; } return transform.TryGetComponent(out component); } /// /// Custom wrapper for prefab spawning which ensures a NitroxEntity is present /// on the newly created object before its components are enabled (Awake is not fired). /// public static GameObject InstantiateInactiveWithId(GameObject original, NitroxId nitroxId, Vector3 position = default, Quaternion rotation = default) { GameObject copy = Object.Instantiate(original, position, rotation, false); NitroxEntity.SetNewId(copy, nitroxId); return copy; } /// /// /// Sets the GameObject to active after spawning it with a NitroxEntity. /// public static GameObject InstantiateWithId(GameObject original, NitroxId nitroxId, Vector3 position = default, Quaternion rotation = default) { GameObject copy = InstantiateInactiveWithId(original, nitroxId, position, rotation); copy.SetActive(true); return copy; } /// /// Override for using our own wrapper /// public static GameObject CreateGenericLoot(TechType techType, NitroxId nitroxId) { GameObject gameObject = SpawnFromPrefab(Utils.genericLootPrefab, nitroxId); gameObject.GetComponent().SetTechTypeOverride(techType, lootCube: true); return gameObject; } /// /// Override for using our own wrapper /// public static GameObject SpawnFromPrefab(GameObject prefab, NitroxId nitroxId, Transform parent = null) { GameObject gameObject = InstantiateWithId(prefab, nitroxId); gameObject.transform.parent = parent; return gameObject; } } }