public void RemoveAspect(GolemAspectEditorData editableAspect) { if (editableAspect == null) { throw new ArgumentNullException("editableAspect"); } var index = EditorAspects.IndexOf(editableAspect); if (index < 0) { throw new ArgumentNullException("editableAspect"); } EditorAspects.RemoveAt(index); var aspect = editableAspect.Aspect; var aspectType = aspect.GetType(); var aspectFieldInGolem = typeof(Golem).GetField(aspectType.Name); if (aspectFieldInGolem == null || !aspectFieldInGolem.FieldType.IsAssignableFrom(aspectType)) { throw new InvalidProgramException(typeof(Golem).Name + " must contain a field for " + aspectType.Name); } var currentFieldValue = aspectFieldInGolem.GetValue(Golem); if (currentFieldValue == null) { throw new InvalidOperationException("Aspect type " + aspectType.GetType() + " doesn't exist in golem"); } if (!object.ReferenceEquals(currentFieldValue, aspect)) { throw new InvalidOperationException("Aspect type " + aspectType.GetType() + " doesn't match the one currently in the golem"); } aspectFieldInGolem.SetValue(Golem, null); for (int i = 0; i < EditorVariables.Count; ++i) { EditorVariables[i].SourceAspects.Remove(aspectType); } removeEditorVariablesWithoutSourceAspects(); }
public void AddAspect(Aspect aspect) { if (aspect == null) { throw new ArgumentNullException("aspect"); } var aspectType = aspect.GetType(); var aspectFieldInGolem = typeof(Golem).GetField(aspectType.Name); if (aspectFieldInGolem == null || !aspectFieldInGolem.FieldType.IsAssignableFrom(aspectType)) { throw new InvalidProgramException(typeof(Golem).Name + " must contain a field for " + aspectType.Name); } bool isNew = false; var currentFieldValue = aspectFieldInGolem.GetValue(Golem); isNew = currentFieldValue == null; if (isNew) { aspectFieldInGolem.SetValue(Golem, aspect); } else if (!object.ReferenceEquals(currentFieldValue, aspect)) { throw new InvalidOperationException(typeof(Golem).Name + " field " + aspectFieldInGolem.Name + " already contains a value for " + aspectType.Name); } var editorAspect = new GolemAspectEditorData(); editorAspect.Field = aspectFieldInGolem; editorAspect.Aspect = aspect; editorAspect.AspectFields = InspectableFieldInfo.GetFields(aspect); editorAspect.AspectVariables = InspectableVariablePropertyInfo.GetVariableProperties(aspect); EditorAspects.Add(editorAspect); // Mark fields for settings that want them if (isNew) { for (int i = 0; i < editorAspect.AspectFields.Length; ++i) { var fieldOfAspect = editorAspect.AspectFields[i]; if (fieldOfAspect.WantsSetting) { editorAspect.FieldsUsingSettings.Add(fieldOfAspect.FieldInfo.Name, null); } } } // Clean up FieldsUsingSettings to only include existing fields { foreach (var key in editorAspect.FieldsUsingSettings.Keys.Where( (fieldName) => !editorAspect.AspectFields.Any((e) => e.FieldInfo.Name == fieldName) ).ToArray()) { editorAspect.FieldsUsingSettings.Remove(key); } } ApplyFieldsUsingSettings(aspect, editorAspect.FieldsUsingSettings, Settings); // Add all of the aspect's declared variables for (int i = 0; i < editorAspect.AspectVariables.Length; ++i) { InspectableVariablePropertyInfo aspectVariable = editorAspect.AspectVariables[i]; string variableName = aspectVariable.VariableAttribute.Name; string variableTooltip = aspectVariable.VariableAttribute.Tooltip; bool notFound = true; for (int j = 0; notFound && j < EditorVariables.Count; ++j) { if (EditorVariables[j].Name == variableName) { EditorVariables[j].SourceAspects.Add(aspectType); if (!string.IsNullOrEmpty(variableTooltip)) { EditorVariables[j].Tooltip = variableTooltip; } notFound = false; } } if (notFound) { Type type = aspectVariable.PropertyInfo.PropertyType; var variableEditorData = new GolemVariableEditorData() { Name = variableName, Tooltip = variableTooltip, SourceAspects = new HashSet <Type>() { aspectType }, InspectableType = aspectVariable.Type, Type = aspectVariable.PropertyInfo.PropertyType, InitialValue = type.IsValueType ? Activator.CreateInstance(type) : null, }; EditorVariables.Add(variableEditorData); } } }
//----------------------------------------------------- // OnInspectorGUI //----------------------------------------------------- public override void OnInspectorGUI() { if (_editable == null) { EditorGUILayout.Space(); EditorGUILayout.LabelField("Golem failed to load"); EditorGUILayout.Space(); return; } //------------------------------------------------- // Graph editor link //------------------------------------------------- EditorGUILayout.Space(); if (GUILayout.Button("Open Editor")) { GolemEditorWindow.Open(_editable); } EditorGUILayout.Space(); EditorGUI.BeginChangeCheck(); //------------------------------------------------- // Aspects //------------------------------------------------- EditorGUILayout.LabelField("Aspects", EditorStyles.boldLabel); // Dropdown for adding an aspect of a new type { var labelRect = EditorGUILayout.GetControlRect(); var dropdownRect = new Rect(labelRect); dropdownRect.xMin += EditorGUIUtility.labelWidth; labelRect.xMax = dropdownRect.xMin; if (EditorGUI.DropdownButton(dropdownRect, new GUIContent("New Aspect..."), FocusType.Passive)) { var menu = new GenericMenu(); var aspectTypes = Assembly.GetAssembly(typeof(Aspect)) .GetTypes() .Where(myType => myType.IsClass && !myType.IsAbstract && myType.IsSubclassOf(typeof(Aspect))) .Where(myType => !_editable.EditorAspects.Any(existing => existing.Aspect.GetType() == myType)) .ToList(); aspectTypes.Sort((a, b) => a.Name.CompareTo(b.Name)); if (aspectTypes.Count == 0) { menu.AddDisabledItem(new GUIContent("No other aspects exist!")); } foreach (var type in aspectTypes) { menu.AddItem( new GUIContent(ObjectNames.NicifyVariableName(type.Name)), false, (object _type) => this.addAspectType((Type)_type), type ); } menu.DropDown(dropdownRect); } } // Each existing aspect { var aspects = _editable.EditorAspects; for (int j = aspects.Count - 1; j >= 0; --j) { GolemAspectEditorData editableAspect = aspects[j]; InspectableFieldInfo[] aspectFields = editableAspect.AspectFields; InspectableVariablePropertyInfo[] aspectVariables = editableAspect.AspectVariables; EditorGUILayout.Space(); Rect foldoutRect = EditorGUILayout.GetControlRect(); Rect rhsToolsRect = foldoutRect; foldoutRect.xMax = foldoutRect.xMax - EditorGUIUtility.singleLineHeight; rhsToolsRect.xMin = foldoutRect.xMax; editableAspect.Foldout = EditorGUI.Foldout(foldoutRect, editableAspect.Foldout, editableAspect.Field.Name); { if (GUI.Button(rhsToolsRect, "X")) { _editable.RemoveAspect(editableAspect); } } if (!editableAspect.Foldout) { continue; } EditorGUI.indentLevel++; // Fields for (int i = 0; i < aspectFields.Length; ++i) { InspectableFieldInfo fieldInfo = aspectFields[i]; GolemEditorUtility.EditorGUILayoutGolemField( fieldInfo.InspectableType, fieldInfo.SpecificType, fieldInfo.FieldInfo, editableAspect.Aspect, editableAspect.FieldsUsingSettings, _editable ); } // Variables, if they exist if (aspectVariables.Length > 0) { EditorGUILayout.Space(); EditorGUILayout.LabelField("Variables", EditorStyles.boldLabel); EditorGUI.BeginDisabledGroup(!EditorApplication.isPlaying); var variables = _editable.Golem.Variables; for (int i = 0; i < aspectVariables.Length; ++i) { var labelRect = EditorGUILayout.GetControlRect(); var position = new Rect(labelRect); position.xMin += EditorGUIUtility.labelWidth; labelRect.xMax = position.xMin; var name = aspectVariables[i].VariableAttribute.Name; EditorGUI.LabelField(labelRect, new GUIContent(aspectVariables[i].PropertyInfo.Name, aspectVariables[i].VariableAttribute.Tooltip)); var variableType = aspectVariables[i].PropertyInfo.PropertyType; variables.InspectorSet(name, variableType, GolemEditorUtility.EditorGUIField(position, aspectVariables[i].Type, variableType, variables.InspectorGet(name, variableType))); } EditorGUI.EndDisabledGroup(); } EditorGUI.indentLevel--; } } //------------------------------------------------- // Variables //------------------------------------------------- if (EditorApplication.isPlaying) { var variables = _editable.Golem.Variables; variables.EditorGUIInspectVariables(); } else { var variables = _editable.EditorVariables; EditorGUILayout.Space(); EditorGUILayout.LabelField(new GUIContent("Variable Initialization", "Derived from Aspects with properties that have the [Variable] attribute"), EditorStyles.boldLabel); for (int i = 0; i < variables.Count; ++i) { var variable = variables[i]; var labelRect = EditorGUILayout.GetControlRect(); var position = new Rect(labelRect); position.xMin += EditorGUIUtility.labelWidth; labelRect.xMax = position.xMin; EditorGUI.LabelField(labelRect, new GUIContent(variable.Name, variable.Tooltip)); variable.InitialValue = GolemEditorUtility.EditorGUIField(position, variable.InspectableType, variable.Type, variable.InitialValue); } } if (EditorGUI.EndChangeCheck()) { _editable.Save(); } //------------------------------------------------- // Settings //------------------------------------------------- EditorGUILayout.Space(); EditorGUILayout.LabelField("Settings", EditorStyles.boldLabel); Settings settings = _editable.Settings; if (settings != null) { EditorGUI.BeginChangeCheck(); settings.DoEditorGUILayout(true); if (EditorGUI.EndChangeCheck()) { _editable.Save(); } EditorGUILayout.Space(); _editable.EditorAsset.InheritSettingsFrom = EditorGUILayout.ObjectField("Inherit From", _editable.EditorAsset.InheritSettingsFrom, typeof(SettingsAsset), false) as SettingsAsset; Settings current = settings.Parent; while (current != null) { EditorGUI.BeginChangeCheck(); current.DoEditorGUILayout(false); if (EditorGUI.EndChangeCheck() && current.SettingsOwner) { EditorUtility.SetDirty(current.SettingsOwner); } current = current.Parent; } } }