void LogObjectChildren(Transform objTransform) { Debug.Log(DbgFormatter.TranformPath(objTransform)); for (var i = 0; i < objTransform.transform.childCount; i++) { LogObjectChildren(objTransform.transform.GetChild(i)); } }
/// <summary>Finds a transform in the hirerachy by the provided path.</summary> /// <remarks> /// Every element of the path may specify an exact transform name or a partial match pattern: /// <list type="bullet"> /// <item> /// <c>*</c> - any name matches. Such patterns can be nested to specify the desired level of /// nesting. E.g. <c>*/*/a</c> will look for name <c>a</c> in the grandchildren. /// </item> /// <item> /// <c>*</c> as a prefix - the name is matched by suffix. E.g. <c>*a</c> matches any name that /// ends with <c>a</c>. /// </item> /// <item> /// <c>*</c> as a suffix - the name is matched by prefix. E.g. <c>a*</c> matches any name that /// starts with <c>a</c>. /// </item> /// <item> /// <c>**</c> - any <i>path</i> matches. What will eventually be found depends on the pattern to /// the right of <c>**</c>. The path match pattern does a "breadth-first" search, i.e. it tries to /// find the shortest path possible. E.g. <c>**/a/b</c> will go through all the nodes starting /// from the parent until path <c>a/b</c> is found. Be careful with this pattern since in case of /// not matching anything it will walk thought the <i>whole</i> hirerachy. /// </item> /// </list> /// <para> /// All patterns except <c>**</c> may have a matching index. It can be used to resolve matches /// when there are multiple objects found with the same name and at the <i>same level</i>. E.g. if /// there are two objects with name "a" at the root level then the first one can be accessed by /// pattern <c>a:0</c>, and the second one by pattern <c>a:1</c>. /// </para> /// <para> /// Path search is <i>slow</i> since it needs walking though the hierarchy nodes. In the worst /// case all the nodes will be visited. Don't use this method in the performance demanding /// methods. /// </para> /// </remarks> /// <param name="parent">The transfrom to start looking from.</param> /// <param name="path">The path elements. All the special symbols must be unescaped.</param> /// <param name="defValue"> /// An object to return if the path is not found. This situation will be treated as a danger, and /// a warning log record will be made. /// </param> /// <returns>Transform or <c>null</c> if nothing found.</returns> /// <example> /// Given the following hierarchy: /// <code lang="c++"><![CDATA[ /// // a /// // + b /// // | + c /// // | | + c1 /// // | | + d /// // | + c /// // | + d /// // | + e /// // | + e1 /// // + abc /// ]]></code> /// <para>The following pattern/output will be possible:</para> /// <code><![CDATA[ /// // a/b/c/d/e/e1 => node "e1" /// // a/b/*/d/e/e1 => node "e1" /// // a/b/*/*/e/e1 => node "e1" /// // a/b/c/c1 => node "с1" /// // a/b/*:0 => branch "a/b/c/c1", node "c" /// // a/b/*:1 => branch "a/b/c/d/e/e1", node "c" /// // a/b/c:1/d => branch "a/b/c/d/e/e1", node "d" /// // **/e1 => node "e1" /// // **/c1 => node "c1" /// // **/c/d => AMBIGUITY! The first found branch will be taken /// // a/**/e1 => node "e1" /// // *bc => node "abc" /// // ab* => node "abc" /// // *b* => node "abc" /// ]]></code> /// </example> /// <seealso cref="UnescapeName"/> /// <include file="Unity3D_HelpIndex.xml" path="//item[@name='T:UnityEngine.Transform']/*"/> public static Transform FindTransformByPath(Transform parent, string[] path, Transform defValue = null) { var obj = FindTransformByPathInternal(parent, path); if (obj == null && defValue != null) { HostedDebugLog.Warning(parent, "Cannot find path: {0}. Using a fallback: {1}", MakePath(path), DbgFormatter.TranformPath(defValue)); return(defValue); } return(obj); }
void WaitAndApplyTweaks() { var roots = UnityEngine.SceneManagement.SceneManager.GetActiveScene().GetRootGameObjects(); foreach (var root in roots) { if (logAllObjects) { LogObjectChildren(root.transform); } foreach (var tweak in modelTweaks) { var names = tweak.modelNamePattern.Split('/'); var reducedNames = names.Skip(1).ToArray(); // Try first name part separately since the scene objects don't have a single root. if (names[0] == "**") { reducedNames = names; // Try all children in the root. } else if (!Hierarchy.PatternMatch(names[0], root.transform.name)) { continue; } var objTransform = Hierarchy.FindTransformByPath(root.transform, reducedNames); if (objTransform != null) { Debug.LogFormat("Tweak '{0}' matched kerbal model: {1}", tweak.tweakName, DbgFormatter.TranformPath(objTransform)); tweak.itemNames.ToList().ForEach(x => { var item = new TweakEquippableItem(x, tweak.matchMeshesBySuffix); item.ApplyTweak(objTransform.gameObject); sceneTweaks.Add(item); }); } } } }