/// <summary> /// Refreshes the tags so that the APIs have an accurate list of Unity tags. /// The editor has direct access to the internal Unity tags. /// In editor play mode and in players the external TagAccess is used to get Unity tagPaths. /// In the absence of a TagAccess the Unity tags will be constructed from the gameObjects. /// </summary> public void RefreshTags() { #if UNITY_EDITOR IEnumerable <IEnumerable <string> > InternalTagPaths = FormatTagPaths(UnityEditorInternal.InternalEditorUtility.tags.Reverse().ToArray()); AllTagPaths = UnityEditor.EditorApplication.isPlayingOrWillChangePlaymode ? ExternalTagPathsLazy.Value : InternalTagPaths; #else AllTagPaths = ExternalTagPathsLazy.Value; #endif AllTags = AllTagPaths.SelectMany(p => p).Distinct().ToList(); }
/// <summary> /// Get Unity tagPaths by logic and tags starting from initial state. /// </summary> /// <param name="tagLogic">The tag logic.</param> /// <param name="op1TagPaths">The tagPaths used by the logic expression.</param> /// <param name="op2TagPaths">The initial state used by the logic expression.</param> public IEnumerable <IEnumerable <string> > GetTagPathMatches(TagLogic tagLogic, IEnumerable <IEnumerable <string> > op1TagPaths, IEnumerable <IEnumerable <string> > op2TagPaths = null) { IEnumerable <string> allTagPaths = AllTagPaths.Select(p => JoinTags(p)).ToList(); IEnumerable <string> operand1 = op1TagPaths.Select(p => JoinTags(p)).ToList(); IEnumerable <string> operand2 = op2TagPaths != null?op2TagPaths.Select(p => JoinTags(p)) : Enumerable.Empty <string>(); TagLogic tagOperations = op2TagPaths == null ? tagLogic & TagLogic.Invert : tagLogic; foreach (TagLogic tagOperation in tagOperations.GetFlags()) { switch (tagOperation) { case TagLogic.Invert: operand1 = allTagPaths.Except(operand1); break; case TagLogic.And: operand1 = operand1.Intersect(operand2); break; case TagLogic.Or: operand1 = operand1.Union(operand2); break; case TagLogic.Xor: operand1 = operand1.Except(operand1.Intersect(operand2)); break; default: operand1 = Enumerable.Empty <string>(); break; } } Logger.Trace("tagLogic={0} Result={1}{4}Operand1={2}{4}Operand2={3}", tagLogic, string.Join(",", operand1.ToArray()), JoinTagPaths(op2TagPaths), JoinTagPaths(op1TagPaths), Environment.NewLine); return(operand1.Select(p => p.Split('/').AsEnumerable())); }
/// <summary> /// Get Unity tagPaths by logic and tags. /// </summary> /// <param name="tagLogic">The tag logic.</param> /// <param name="tags">The tags.</param> public IEnumerable <IEnumerable <string> > GetTagPathMatches(TagLogic tagLogic, params string[] tags) { IEnumerable <IEnumerable <string> > baseTagPaths = AllTagPaths; IEnumerable <string> splitTags = tags.SelectMany(t => t.Split('/')); IEnumerable <string> regexTagPatterns = splitTags.Where(p => Regex.Match(p, @"[*+?^\\{}\[\]$<>:]").Success); IEnumerable <string> regexTags = regexTagPatterns.SelectMany(p => AllTags.Where(t => Regex.Match(t, p).Success)); IEnumerable <string> findTags = splitTags.Except(regexTagPatterns).Concat(regexTags).Distinct(); IEnumerable <IEnumerable <string> > resultTagPaths = null; // Enumerable.Empty<IEnumerable<string>>(); foreach (IEnumerable <IEnumerable <string> > tagPaths in findTags.Select(t => AllTagPaths.Where(p => ExpandTagGroups(p).Contains(t)))) { resultTagPaths = GetTagPathMatches(tagLogic, tagPaths, resultTagPaths); } return(resultTagPaths ?? Enumerable.Empty <IEnumerable <string> >()); }