| | 1 | | // Copyright (c) 2020-2024 dotBunny Inc. |
| | 2 | | // dotBunny licenses this file to you under the BSL-1.0 license. |
| | 3 | | // See the LICENSE file in the project root for more information. |
| | 4 | |
|
| | 5 | | #if !UNITY_DOTSRUNTIME |
| | 6 | |
|
| | 7 | | using System.Diagnostics.CodeAnalysis; |
| | 8 | | using System.Runtime.CompilerServices; |
| | 9 | | using UnityEngine; |
| | 10 | |
|
| | 11 | | namespace GDX |
| | 12 | | { |
| | 13 | | /// <summary> |
| | 14 | | /// <see cref="UnityEngine.GameObject" /> Based Extension Methods |
| | 15 | | /// </summary> |
| | 16 | | /// <exception cref="UnsupportedRuntimeException">Not supported on DOTS Runtime.</exception> |
| | 17 | | [VisualScriptingCompatible(2)] |
| | 18 | | public static class GameObjectExtensions |
| | 19 | | { |
| | 20 | | /// <summary> |
| | 21 | | /// Destroy child <see cref="GameObject" />. |
| | 22 | | /// </summary> |
| | 23 | | /// <param name="targetGameObject">The parent <see cref="GameObject" /> to look at.</param> |
| | 24 | | /// <param name="deactivateBeforeDestroy"> |
| | 25 | | /// Should the <paramref name="targetGameObject" />'s children be deactivated before |
| | 26 | | /// destroying? This can be used to immediately hide an object, that will be destroyed at the end of the fra |
| | 27 | | /// </param> |
| | 28 | | /// <param name="destroyInactive">Should inactive <see cref="GameObject" /> be destroyed as well?</param> |
| | 29 | | [MethodImpl(MethodImplOptions.AggressiveInlining)] |
| | 30 | | [ExcludeFromCodeCoverage] |
| | 31 | | public static void DestroyChildren(this GameObject targetGameObject, bool deactivateBeforeDestroy = true, |
| | 32 | | bool destroyInactive = true) |
| | 33 | | { |
| | 34 | | targetGameObject.transform.DestroyChildren(deactivateBeforeDestroy, destroyInactive); |
| | 35 | | } |
| | 36 | |
|
| | 37 | | /// <summary> |
| | 38 | | /// A slightly more complex version of <see cref="Component.GetComponentInChildren{T}(bool)" /> which allows |
| | 39 | | /// different hinted search options. |
| | 40 | | /// </summary> |
| | 41 | | /// <remarks> |
| | 42 | | /// <para> |
| | 43 | | /// If the <paramref name="maxLevelsOfRecursion" /> is set to 1; this will search the |
| | 44 | | /// <paramref name="targetGameObject" /> and its immediate children only. |
| | 45 | | /// </para> |
| | 46 | | /// <para> |
| | 47 | | /// The internal <see cref="Component.GetComponentInChildren{T}(bool)" /> has optimizations internally i |
| | 48 | | /// code which make it faster in different scenarios. |
| | 49 | | /// </para> |
| | 50 | | /// </remarks> |
| | 51 | | /// <param name="targetGameObject">The target <see cref="GameObject" /> to use as the base for the search.</para |
| | 52 | | /// <param name="lookInChildrenFirst"> |
| | 53 | | /// Should children <see cref="GameObject" /> be searched before the |
| | 54 | | /// <paramref name="targetGameObject" />'s <see cref="GameObject" />. |
| | 55 | | /// </param> |
| | 56 | | /// <param name="includeInactive"> |
| | 57 | | /// Include inactive child <see cref="GameObject" />s when looking for the |
| | 58 | | /// <see cref="Component" />. |
| | 59 | | /// </param> |
| | 60 | | /// <param name="maxLevelsOfRecursion"> |
| | 61 | | /// The maximum levels of recursion when looking for a <see cref="Component" />, -1 for |
| | 62 | | /// infinite recursion. |
| | 63 | | /// </param> |
| | 64 | | /// <typeparam name="T">The target <see cref="UnityEngine.Component" /> type that is being looked for.</typepara |
| | 65 | | /// <returns>The first found <see cref="Component" />.</returns> |
| | 66 | | public static T GetFirstComponentInChildrenComplex<T>(this GameObject targetGameObject, |
| | 67 | | bool includeInactive = false, bool lookInChildrenFirst = false, int maxLevelsOfRecursion = -1) |
| | 68 | | where T : Component |
| 0 | 69 | | { |
| | 70 | | // Make sure we have nothing to return if necessary. |
| | 71 | | T returnComponent; |
| | 72 | |
|
| | 73 | | // Early out looking at the immediate target first. |
| 0 | 74 | | if (!lookInChildrenFirst) |
| 0 | 75 | | { |
| 0 | 76 | | returnComponent = targetGameObject.GetComponent<T>(); |
| 0 | 77 | | if (returnComponent != null) |
| 0 | 78 | | { |
| 0 | 79 | | return returnComponent; |
| | 80 | | } |
| 0 | 81 | | } |
| | 82 | |
|
| 0 | 83 | | returnComponent = |
| | 84 | | targetGameObject.transform.GetFirstComponentInChildrenComplex<T>(includeInactive, 0, |
| | 85 | | maxLevelsOfRecursion); |
| 0 | 86 | | if (returnComponent != null) |
| 0 | 87 | | { |
| 0 | 88 | | return returnComponent; |
| | 89 | | } |
| | 90 | |
|
| 0 | 91 | | return !lookInChildrenFirst ? default : targetGameObject.GetComponent<T>(); |
| 0 | 92 | | } |
| | 93 | |
|
| | 94 | | /// <summary> |
| | 95 | | /// Get a component by type from a <paramref name="targetGameObject" />, if it is not found add and return i |
| | 96 | | /// </summary> |
| | 97 | | /// <remarks>Adding a component at runtime is a performance nightmare. Use with caution!</remarks> |
| | 98 | | /// <param name="targetGameObject">The <see cref="GameObject" /> that we should query for the component.</param> |
| | 99 | | /// <typeparam name="T">The type of component.</typeparam> |
| | 100 | | /// <returns>The component on the <paramref name="targetGameObject" />.</returns> |
| | 101 | | [MethodImpl(MethodImplOptions.AggressiveInlining)] |
| | 102 | | public static T GetOrAddComponent<T>(this GameObject targetGameObject) where T : Component |
| 0 | 103 | | { |
| 0 | 104 | | T instance = targetGameObject.GetComponent<T>(); |
| 0 | 105 | | return instance ? instance : targetGameObject.AddComponent<T>(); |
| 0 | 106 | | } |
| | 107 | |
|
| | 108 | | /// <summary> |
| | 109 | | /// Get an in scene path to the <paramref name="targetGameObject" />. |
| | 110 | | /// </summary> |
| | 111 | | /// <param name="targetGameObject">The <see cref="GameObject" /> which to derive a path from.</param> |
| | 112 | | /// <returns>A created path <see cref="System.String" />.</returns> |
| | 113 | | [MethodImpl(MethodImplOptions.AggressiveInlining)] |
| | 114 | | [ExcludeFromCodeCoverage] |
| | 115 | | public static string GetScenePath(this GameObject targetGameObject) |
| | 116 | | { |
| | 117 | | return targetGameObject.transform.GetScenePath(); |
| | 118 | | } |
| | 119 | | } |
| | 120 | | } |
| | 121 | | #endif // !UNITY_DOTSRUNTIME |