/// <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> >()); }
/// <summary> /// Determines if gameObject has the tags derived from specified tagLogic and tag(s). /// </summary> /// <param name="gameObject">The gameObject.</param> /// <param name="tagSearch">The tag search.</param> /// <param name="tags">The tags.</param> public static bool HasTags(this GameObject gameObject, TagLogic tagSearch, params string[] tags) { var gameObjectTags = gameObject.Tags(); switch (tagSearch) { case TagLogic.And: return(tags.All(t => gameObjectTags.Contains(t))); case TagLogic.Or: return(tags.Any(t => gameObjectTags.Contains(t))); case TagLogic.Invert: return(tags.All(t => !gameObjectTags.Contains(t))); default: return(false); } }
/// <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> /// Initializes a new instance of the <see cref="TagExpression" /> class. /// </summary> /// <param name="operation">The tag logic operation.</param> /// <param name="operands">The tagPath operands.</param> public TagExpression(TagLogic operation, IEnumerable <IEnumerable <string> > operands) { this.Operation = operation; this.TagPaths = operands; }
public TagService() { tagLogic = new TagLogic(); }
/// <summary> /// Determines if component has the tags derived from specified tagLogic and tag(s). /// </summary> /// <param name="component">The component.</param> /// <param name="tagLogic">The tag search.</param> /// <param name="tags">The tags.</param> public static bool HasTags(this Component component, TagLogic tagLogic, params string[] tags) { return(component.gameObject.HasTags(tagLogic, tags)); }
/// <summary> /// Find gameObjects by taking existing gameObjects tagPath and performing tagLogic operation with the derived tagPattern tagPaths. /// </summary> /// <param name="gameObject">The starting gameObject.</param> /// <param name="tagLogic">The tag logic operation between gameObject tagPath and tagPattern tagPaths.</param> /// <param name="tagPattern">The tag pattern used to generate a set of tagPaths.</param> public static GameObject[] FindGameObjectsWithTags(this GameObject gameObject, TagLogic tagLogic, string tagPattern) { return(TagService.FindGameObjectsWithTags(TagService.GetTagPathMatches(tagLogic, TagService.GetTagPathMatches(tagPattern), TagService.FormatTagPaths(gameObject.tag)))); }
/// <summary> /// Find gameObjects by taking existing gameObjects tagPath and performing tagLogic operation with the derived tagPattern tagPaths. /// </summary> /// <param name="gameObjects">The starting gameObjects.</param> /// <param name="tagLogic">The tag logic operation between gameObjects tagPath and tagPattern tagPaths.</param> /// <param name="tagPattern">The tag pattern used to generate a set of tagPaths.</param> public static GameObject[] FindGameObjectsWithTags(this IEnumerable <GameObject> gameObjects, TagLogic tagLogic, string tagPattern) { return(TagService.FindGameObjectsWithTags(TagService.GetTagPathMatches(tagLogic, gameObjects.Tags(), TagService.GetTagPathMatches(tagPattern)))); }
/// <summary> /// Gets the tagPaths by logic and tag starting from initial tags. /// </summary> /// <param name="tagLogic">The tag logic.</param> /// <param name="startTagPaths">The start tag paths.</param> /// <param name="tag">The tag used by logic.</param> private IEnumerable <IEnumerable <string> > GetTagPathMatches(TagLogic tagLogic, IEnumerable <IEnumerable <string> > startTagPaths, string tag) { return(GetTagPathMatches(tagLogic, GetTagPathMatches(TagLogic.Or, tag), startTagPaths)); }
/// <summary> /// Get Unity tagPaths by tag pattern. /// </summary> /// <param name="findPattern">The find pattern (ie. TagAccess.T1, "T1", "T1 | T2", or "T.*").</param> public IEnumerable <IEnumerable <string> > GetTagPathMatches(string findPattern) { Logger.Debug("Searching tag pattern={0}", findPattern); string pattern = @"(([!&|^]*)([(!]*)([^!&|^()]+)(\)*))+.*$"; Stack <TagExpression> operands = new Stack <TagExpression>(); IEnumerable <IEnumerable <string> > tagPathMatches = Enumerable.Empty <IEnumerable <string> >(); Match match = Regex.Match(findPattern.Replace(" ", String.Empty), pattern); for (int captureIndex = 0; captureIndex < match.Groups[1].Captures.Count; captureIndex++) { string subPatternClause = match.Groups[1].Captures[captureIndex].Value; string logicExpression = match.Groups[2].Captures[captureIndex].Value; string openClause = match.Groups[3].Captures[captureIndex].Value; string tag = match.Groups[4].Captures[captureIndex].Value; string closeClause = match.Groups[5].Captures[captureIndex].Value; TagLogic operation = TagLogic.None; foreach (char op in logicExpression) { switch (op) { case '!': operation |= TagLogic.Invert; break; case '&': operation |= TagLogic.And; break; case '|': operation |= TagLogic.Or; break; case '^': operation |= TagLogic.Xor; break; } } Logger.Trace("Searching tag sub-pattern={0} logicClause={1} openClause={2} tagClause={3} closeClause={4} operation={5}", subPatternClause, logicExpression, openClause, tag, closeClause, operation); for (int i = 0; i < openClause.Length; i++) { if (openClause[i] == '!') { operation ^= TagLogic.Invert; } else if (openClause[i] == '(') { Logger.Trace("Push operation={0} tagPathMatches={1}", operation, JoinTagPaths(tagPathMatches)); operands.Push(new TagExpression(operation, tagPathMatches)); operation = TagLogic.None; } } // Evaluate logic operation tagPathMatches = GetTagPathMatches(operation, tagPathMatches, tag); for (int closeClauseIndex = 0; closeClauseIndex < closeClause.Length; closeClauseIndex++) { TagExpression tagExpression = operands.Pop(); Logger.Trace("Pop operation={0} tagPaths={1}", tagExpression.Operation, JoinTagPaths(tagExpression.TagPaths)); tagPathMatches = GetTagPathMatches(tagExpression.Operation, tagPathMatches, tagExpression.TagPaths); } } return(tagPathMatches); }
/// <summary> /// Find gameObjects by logic and tags. /// </summary> /// <param name="tagSearch">The tag logic expression.</param> /// <param name="tags">The tags to be combined with the logic.</param> public GameObject[] FindGameObjectsWithTags(TagLogic tagSearch, params string[] tags) { IEnumerable <IEnumerable <string> > searchPaths = GetTagPathMatches(tagSearch, tags); return(FindGameObjectsWithTags(searchPaths).ToArray()); }