public static bool DrawRecursive(ref object target, BaseGUI gui, int id, UnityObject unityTarget, params string[] memberNames) { List <MemberInfo> members; var targetType = target.GetType(); if (memberNames.IsNullOrEmpty()) { members = VFWVisibilityLogic.CachedGetVisibleMembers(targetType); } else { members = new List <MemberInfo>(); for (int i = 0; i < memberNames.Length; i++) { var name = memberNames[i]; var member = ReflectionHelper.CachedGetMember(targetType, name); if (member == null) { LogFormat("RecursiveDrawer: Couldn't find member {0} in {1}", name, targetType.Name); continue; } if (VFWVisibilityLogic.IsVisibleMember(member)) { members.Add(member); } } } if (members.Count == 0) { gui.HelpBox("Object doesn't have any visible members"); return(false); } bool changed = false; using (gui.Indent()) { for (int i = 0; i < members.Count; i++) { MemberInfo member = members[i]; EditorMember em; changed |= gui.Member(member, target, unityTarget, id, false, out em); target = em.RawTarget; } } return(changed); }
/// <summary> /// Fetches visible members in the inspected target object and assigns them to their corresponding categories /// </summary> private void Initialize() { OnBeforeInitialized(); // fetch visible members _visibleMembers = VFWVisibilityLogic.CachedGetVisibleMembers(targetType).ToList(); // allocate categories _categories = new List <MembersCategory>(); var multiple = targetType.GetCustomAttribute <DefineCategoriesAttribute>(true); var definitions = targetType.GetCustomAttributes <DefineCategoryAttribute>(true); if (multiple != null) { definitions = definitions.Concat(multiple.names.Select(n => new DefineCategoryAttribute(n, 1000))); } Func <string, string[]> ParseCategoryPath = fullPath => { int nPaths = fullPath.Split('/').Length; string[] result = new string[nPaths]; for (int i = 0, index = -1; i < nPaths - 1; i++) { index = fullPath.IndexOf('/', index + 1); result[i] = fullPath.Substring(0, index); } result[nPaths - 1] = fullPath; return(result); }; // Order by exclusivity var defs = from d in definitions let paths = ParseCategoryPath(d.FullPath) orderby !d.Exclusive select new { def = d, paths }; // Parse paths and resolve definitions var resolver = new CategoryDefinitionResolver(); var lookup = new Dictionary <string, MembersCategory>(); foreach (var x in defs) { var paths = x.paths; var d = x.def; MembersCategory parent = null; for (int i = 0; i < paths.Length; i++) { var path = paths[i]; var current = (parent == null ? _categories : parent.NestedCategories).FirstOrDefault(c => c.FullPath == path); if (current == null) { current = new MembersCategory(path, d.DisplayOrder, id); if (i == 0) { _categories.Add(current); } if (parent != null) { parent.NestedCategories.Add(current); } } lookup[path] = current; parent = current; } var last = lookup[paths.Last()]; last.ForceExpand = d.ForceExpand; last.AlwaysHideHeader = d.AlwaysHideHeader; resolver.Resolve(_visibleMembers, d).Foreach(last.Members.Add); lookup.Clear(); parent.Members = parent.Members.OrderBy <MemberInfo, float>(VFWVisibilityLogic.GetMemberDisplayOrder).ToList(); } // filter out empty categories _categories = _categories.Where(x => x.NestedCategories.Count > 0 || x.Members.Count > 0) .OrderBy(x => x.DisplayOrder) .ToList(); for (int i = 0; i < _categories.Count; i++) { var c = _categories[i]; c.RemoveEmptyNestedCategories(); } var displayKey = RuntimeHelper.CombineHashCodes(id, "display"); var displayValue = prefs.Ints.ValueOrDefault(displayKey, -1); var vfwSettings = VFWSettings.GetInstance(); _display = displayValue == -1 ? vfwSettings.DefaultDisplay : (CategoryDisplay)displayValue; prefs.Ints[displayKey] = (int)_display; var spacingKey = RuntimeHelper.CombineHashCodes(id, "spacing"); _spacing = prefs.Ints.ValueOrDefault(spacingKey, vfwSettings.DefaultSpacing); prefs.Ints[spacingKey] = _spacing; var field = targetType.GetAllMembers(typeof(MonoBehaviour), Flags.InstancePrivate) .FirstOrDefault(m => m.Name == "_serializationData"); if (field == null) { throw new vMemberNotFound(targetType, "_serializationData"); } _serializationData = EditorMember.WrapMember(field, target, target, id); field = targetType.GetField("dbg", Flags.InstanceAnyVisibility); if (field == null) { throw new vMemberNotFound(targetType, "dbg"); } _debug = EditorMember.WrapMember(field, target, target, id); OnAfterInitialized(); }