IEnumerable <string> OnGUISkillGroup(Character ac, IEnumerable <SkillDef> skills, IEnumerable <string> selectedGroup) { if (delimiter == null) { delimiter = new Regex("//"); } IEnumerable <string> nextSelectedGroup = selectedGroup; int segmentCount = selectedGroup == null ? 0 : selectedGroup.Count(); string segment = (selectedGroup == null || selectedGroup.Count() == 0) ? null : selectedGroup.Last(); if (ac != lastShownCharacter || segmentCount != lastSegmentCount || segment != lastSegment || sorted == null) { //group by skillGroup //anything with selectedGroup as its group is the current level //anything that is one away from selectedGroup is the next level string groupPath = selectedGroup == null ? "" : string.Join("//", selectedGroup.ToArray()); var groups = skills.Where(x => !x.isPassive).OrderBy(x => x.skillName).GroupBy(x => x.skillGroup); List <object> usedEntities = new List <object>(); //top level skills //TODO: can defer sort score calculation until later -- //find each subgroup prefix and do the deepGroupSkills calculation later //since each prefix ought to be unique across a number of groups, we can use //set union semantics. foreach (var group in groups.Where(x => x.Key == groupPath)) { foreach (SkillDef s in group) { usedEntities.Add(s as object); } } foreach (var group in groups.Where(x => x.Key != groupPath && x.Key != null && (groupPath == null || (x.Key.StartsWith(groupPath)))) ) { string[] groupSegments = delimiter.Split(group.Key); //it's a next group string[] groupKeySegments = new string[segmentCount + 1]; // Debug.Log("segs "+groupSegments.Length+" key segs "+groupKeySegments.Length+" scp1 "+(segmentCount+1)); Array.Copy(groupSegments, groupKeySegments, segmentCount + 1); string groupKey = string.Join("//", groupKeySegments); if (!usedEntities.Contains(groupKey)) { usedEntities.Add(groupKey); } } //get it all ordered and sorted and interleaved and displayed nicely sorted = usedEntities.OrderBy(delegate(object x) { if (x is SkillDef) { return((x as SkillDef).skillSorting); } else { string key = x as string; var deepGroupSkills = skills.Where(y => y.skillGroup != null && y.skillGroup.StartsWith(key)); return((int)Mathf.Round((float)deepGroupSkills.Average(y => y.skillSorting))); } }).ToArray().AsEnumerable(); } foreach (object o in sorted) { if (o is SkillDef) { SkillDef skill = o as SkillDef; GUI.enabled = IsSkillEnabled(skill); if (GUILayout.Button(skill.skillName)) { skill.ActivateSkill(); } GUI.enabled = true; } else { string groupKey = o as string; string[] groupSegments = delimiter.Split(groupKey); string groupName = groupSegments[segmentCount]; var deepGroupSkills = skills.Where(x => x.skillGroup != null && x.skillGroup.StartsWith(groupKey)); GUI.enabled = deepGroupSkills.Any(x => IsSkillEnabled(x)); if (GUILayout.Button(groupName)) { if (selectedGroup == null) { nextSelectedGroup = new[] { groupName }; } else { nextSelectedGroup = selectedGroup.Concat(new[] { groupName }); } } GUI.enabled = true; } } if (selectedGroup != null && selectedGroup.Count() > 0) { if (GUILayout.Button("Back") || Input.GetButtonDown("Cancel")) { List <string> nextSel = selectedGroup.ToList(); nextSel.RemoveAt(nextSel.Count - 1); nextSelectedGroup = nextSel; } } lastShownCharacter = ac; lastSegment = segment; lastSegmentCount = segmentCount; return(nextSelectedGroup == null ? null : nextSelectedGroup.ToList().AsEnumerable()); }