Example #1
0
        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);
                }
            }
        }
Example #2
0
        //-----------------------------------------------------
        // 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;
                }
            }
        }