void InitIfNeeded(bool force = false) { if (m_Initialized && !force) { return; } // Check if it already exists (deserialized from window layout file or scriptable object) if (m_TreeViewState == null || force) { m_TreeViewState = new TreeViewState(); } bool firstInit = m_MultiColumnHeaderState == null; var headerState = MultiColumnTreeView.CreateDefaultMultiColumnHeaderState(multiColumnTreeViewRect.width); if (MultiColumnHeaderState.CanOverwriteSerializedFields(m_MultiColumnHeaderState, headerState)) { MultiColumnHeaderState.OverwriteSerializedFields(m_MultiColumnHeaderState, headerState); } m_MultiColumnHeaderState = headerState; var multiColumnHeader = new MyMultiColumnHeader(headerState); if (firstInit || force) { multiColumnHeader.ResizeToFit(); } var treeModel = new TreeModel <SaveEditorTreeElement>(GetData()); m_TreeView = new MultiColumnTreeView(m_TreeViewState, multiColumnHeader, treeModel, treeGenerator); m_SearchField = new SearchField(); m_SearchField.downOrUpArrowKeyPressed += m_TreeView.SetFocusAndEnsureSelectedItem; m_Initialized = true; }
public void AddChildrenRecursive( List <SaveEditorTreeElement> treeElements, SaveEditorTreeElement element, object data, Type typeSrc ) { if (IDCounter > 15000) { //recursive kill safeguard Debug.LogError("Max Tree Size Reached, Aborting"); return; } if (typeSrc.IsPrimitive || typeSrc == typeof(string)) { // Debug.Log("Hit primative " + typeSrc.Name); return; } var interfaces = typeSrc.GetInterfaces(); if (typeSrc.IsArray) { // Debug.Log("Adding Array"); var idx = 0; if (data != null) { foreach (object item in (Array)data) { var child = AddChild(treeElements, element, idx, item, item.GetType(), (old, val, titem) => { ((IList)data)[(int)titem.nameValue] = val; } ); child.removeValueFromParent = (val) => { ((IList)data).Remove(val.value); }; child.needsSiblingRename = true; AddChildrenRecursive(treeElements, child, item, MultiColumnTreeView.GetEnumeratedType(typeSrc)); idx++; } } } else if (interfaces.Any(x => x.Name == "IDictionary")) { // Debug.Log("Adding Dict " + MultiColumnTreeView.GetCSharpRepresentation(typeSrc, true)); if (data != null) { foreach (var item in ((IDictionary)data).Keys) { var value = ((IDictionary)data)[item]; var child = AddChild(treeElements, element, item, value, value.GetType(), (old, val, titem) => { ((IDictionary)data)[titem.nameValue] = val; } ); child.removeValueFromParent = (val) => { ((IDictionary)data).Remove(val.nameValue); }; child.setName = (oldKey, newKey, treeItem) => { if (oldKey == newKey || oldKey.Equals(newKey)) { return; } var cData = (IDictionary)data; cData[newKey] = cData[oldKey]; cData.Remove(oldKey); treeItem.name = newKey.ToString(); }; AddChildrenRecursive(treeElements, child, value, typeSrc.GetGenericArguments()[1]); } } element.addToCollection = (treeItem) => { var arguments = typeSrc.GetGenericArguments(); Type keyType = arguments[0]; Type valueType = arguments[1]; var newKey = Activator.CreateInstance(keyType); var newVal = Activator.CreateInstance(valueType); ((IDictionary)treeItem.value)[newKey] = newVal; return(newVal); }; } else if (interfaces.Any(x => x.Name == "IList")) { // Debug.Log("Adding IList"); if (data != null) { var idx = 0; foreach (object item in (IList)data) { var child = AddChild(treeElements, element, idx, item, item.GetType(), (old, val, titem) => { ((IList)data)[(int)titem.nameValue] = val; } ); child.removeValueFromParent = (val) => { ((IList)data).Remove(val.value); }; child.needsSiblingRename = true; AddChildrenRecursive(treeElements, child, item, MultiColumnTreeView.GetEnumeratedType(typeSrc)); idx++; } } element.addToCollection = (treeItem) => { var val = Activator.CreateInstance(MultiColumnTreeView.GetEnumeratedType(element.valueType)); ((IList)treeItem.value).Add(val); return(val); }; element.needsSiblingRename = true; } else if (typeSrc.IsGenericType && typeSrc.GetGenericTypeDefinition() == typeof(HashSet <>)) { if (data != null) { var hs = (IEnumerable)data; foreach (object item in hs) { var child = AddChild(treeElements, element, item.GetHashCode(), item, item.GetType(), (old, val, titem) => { /*hs.Remove(old); hs.Add(val); */ } ); child.removeValueFromParent = (val) => { MethodInfo methodInfo = typeSrc.GetMethod("Remove"); object[] parametersArray = new object[] { val.value }; methodInfo.Invoke(data, parametersArray); }; // child.needsSiblingRename = true; AddChildrenRecursive(treeElements, child, item, MultiColumnTreeView.GetEnumeratedType(typeSrc)); } } element.addToCollection = (treeItem) => { var val = Activator.CreateInstance(MultiColumnTreeView.GetEnumeratedType(element.valueType)); MethodInfo methodInfo = treeItem.valueType.GetMethod("Add"); object[] parametersArray = new object[] { val }; methodInfo.Invoke(treeItem.value, parametersArray); return(val); }; } else if (data != null && (typeSrc.IsClass || IsCustomValueType(typeSrc))) { // Debug.Log("Adding Class"); foreach (var prop in typeSrc.GetProperties()) { if (!prop.CanRead || !prop.CanWrite) { continue; } if (prop.GetIndexParameters().Length > 0) { continue; } if (prop.PropertyType.IsAbstract) { continue; } var value = prop.GetValue(data); var child = AddChild(treeElements, element, prop.Name, value, prop.PropertyType, (old, val, titem) => { prop.SetValue(data, val); } ); AddChildrenRecursive(treeElements, child, value, prop.PropertyType); } foreach (var field in typeSrc.GetFields()) { if (field.IsLiteral) { continue; } if (IsTypeStatic(field.Attributes)) { continue; } var value = field.GetValue(data); SaveEditorTreeElement child; if (IsCustomValueType(typeSrc)) { //TODO: have to do custom setting of values for structs that works var f = field; child = AddChild(treeElements, element, field.Name, value, field.FieldType, (old, val, titem) => { try{ f.SetValueDirect(__makeref(data), val); }catch (Exception e) { Debug.LogError(e); } } ); } else { child = AddChild(treeElements, element, field.Name, value, field.FieldType, (old, val, titem) => { field.SetValue(data, val); } ); } AddChildrenRecursive(treeElements, child, value, field.FieldType); } } }