Beispiel #1
0
        private static void DrawUrdfJointData <T>(AGXUnity.IO.URDF.UJoint parent,
                                                  MemberInfo member,
                                                  T jointData)
            where T : struct
        {
            var fieldsAndProperties    = InvokeWrapper.FindFieldsAndProperties(typeof(T));
            var enabledFieldOrProperty = fieldsAndProperties.FirstOrDefault(wrapper => wrapper.Member.Name == "Enabled");

            if (enabledFieldOrProperty == null)
            {
                return;
            }
            var enabled = enabledFieldOrProperty.Get <bool>(jointData);

            using (new GUI.EnabledBlock(enabled)) {
                if (!InspectorGUI.Foldout(GetEditorData(parent, member.Name), InspectorGUI.MakeLabel(member)))
                {
                    return;
                }
                using (InspectorGUI.IndentScope.Single) {
                    foreach (var wrapper in fieldsAndProperties)
                    {
                        if (wrapper == enabledFieldOrProperty)
                        {
                            continue;
                        }

                        var drawer = GetDrawerMethod(wrapper.GetContainingType());
                        drawer.Drawer?.Invoke(null, new object[] { new object[] { jointData }, wrapper });
                    }
                }
            }
        }
Beispiel #2
0
 public static object UrdfJointCalibrationDrawer(object[] objects, InvokeWrapper wrapper)
 {
     DrawUrdfJointData(objects[0] as AGXUnity.IO.URDF.UJoint,
                       wrapper.Member,
                       wrapper.Get <AGXUnity.IO.URDF.UJoint.CalibrationData>(objects[0]));
     return(null);
 }
Beispiel #3
0
 public static object UrdfJointSafetyControllerDrawer(object[] objects, InvokeWrapper wrapper)
 {
     DrawUrdfJointData(objects[0] as AGXUnity.IO.URDF.UJoint,
                       wrapper.Member,
                       wrapper.Get <AGXUnity.IO.URDF.UJoint.SafetyControllerData>(objects[0]));
     return(null);
 }
Beispiel #4
0
        public static object ScriptDrawer(object[] objects, InvokeWrapper wrapper)
        {
            object result           = null;
            var    type             = wrapper.GetContainingType();
            bool   allowSceneObject = type == typeof(GameObject) ||
                                      typeof(ScriptComponent).IsAssignableFrom(type);
            Object valInField       = wrapper.Get <Object>(objects[0]);
            bool   recursiveEditing = wrapper.HasAttribute <AllowRecursiveEditing>();

            if (recursiveEditing)
            {
                result = InspectorGUI.FoldoutObjectField(InspectorGUI.MakeLabel(wrapper.Member),
                                                         valInField,
                                                         type,
                                                         EditorData.Instance.GetData(objects[0] as Object,
                                                                                     wrapper.Member.Name),
                                                         !wrapper.CanWrite());
            }
            else
            {
                result = EditorGUILayout.ObjectField(InspectorGUI.MakeLabel(wrapper.Member),
                                                     valInField,
                                                     type,
                                                     allowSceneObject);
            }

            return(result);
        }
Beispiel #5
0
        /// <summary>
        /// Draw supported member GUI for given targets. This method supports
        /// non-UnityEngine.Object instances, such as pure Serializable classes,
        /// that are part of <paramref name="targets"/>. <paramref name="getChildCallback"/>
        /// is called to access these serializable objects. If <paramref name="getChildCallback"/>
        /// is null, targets will be rendered.
        /// </summary>
        /// <param name="targets">Target UnityEngine.Object instances (used for Undo and SetDirty).</param>
        /// <param name="getChildCallback">Null and targets will be rendered, otherwise the returned
        ///                                instance from this callback.</param>
        public static void DrawMembersGUI(Object[] targets,
                                          Func <Object, object> getChildCallback = null,
                                          SerializedObject fallback = null)
        {
            targets = targets.Where(obj => obj != null).ToArray();

            if (targets.Length == 0)
            {
                return;
            }

            var objects = targets.Select(target => getChildCallback == null ?
                                         target :
                                         getChildCallback(target))
                          .Where(obj => obj != null).ToArray();

            if (objects.Length == 0)
            {
                return;
            }

            Undo.RecordObjects(targets, "Inspector");

            var hasChanges = false;

            InvokeWrapper[] fieldsAndProperties = InvokeWrapper.FindFieldsAndProperties(objects[0].GetType());
            var             group = InspectorGroupHandler.Create();

            foreach (var wrapper in fieldsAndProperties)
            {
                if (!ShouldBeShownInInspector(wrapper.Member))
                {
                    continue;
                }

                group.Update(wrapper, objects[0]);

                if (group.IsHidden)
                {
                    continue;
                }

                var runtimeDisabled = EditorApplication.isPlayingOrWillChangePlaymode &&
                                      wrapper.Member.IsDefined(typeof(DisableInRuntimeInspectorAttribute), true);
                using (new GUI.EnabledBlock(UnityEngine.GUI.enabled && !runtimeDisabled))
                    hasChanges = HandleType(wrapper, objects, fallback) || hasChanges;
            }
            group.Dispose();

            if (hasChanges)
            {
                foreach (var obj in targets)
                {
                    EditorUtility.SetDirty(obj);
                }
            }
        }
Beispiel #6
0
        public static object UrdfInertiaDrawer(object[] objects, InvokeWrapper wrapper)
        {
            var inertia = wrapper.Get <AGXUnity.IO.URDF.Inertia>(objects[0]);

            InspectorGUI.Vector3Field(InspectorGUI.MakeLabel(wrapper.Member), inertia.GetRow(0), "XX,XY,XZ");
            InspectorGUI.Vector3Field(null, inertia.GetRow(1), "YX,YY,YZ");
            InspectorGUI.Vector3Field(null, inertia.GetRow(2), "ZX,ZY,ZZ");
            return(null);
        }
Beispiel #7
0
        public static object EnumDrawer(object obj, InvokeWrapper wrapper, GUISkin skin)
        {
            if (!wrapper.GetContainingType().IsVisible)
            {
                return(null);
            }

            return(EditorGUILayout.EnumPopup(MakeLabel(wrapper.Member), wrapper.Get <Enum>(obj), skin.button));
        }
Beispiel #8
0
            public BeginConstraintRowGUI(ConstraintUtils.ConstraintRow row, InvokeWrapper wrapper)
            {
                m_guiWasEnabled = UnityEngine.GUI.enabled;

                if (row != null)
                {
                    Undo.RecordObject(row.ElementaryConstraint, "RowUpdate");
                }

                UnityEngine.GUI.enabled = m_guiWasEnabled && row != null && row.Valid;
            }
        /// <summary>
        /// Draw supported member GUI for given targets. This method supports
        /// non-UnityEngine.Object instances, such as pure Serializable classes,
        /// that are part of <paramref name="targets"/>. <paramref name="getChildCallback"/>
        /// is called to access these serializable objects. If <paramref name="getChildCallback"/>
        /// is null, targets will be rendered.
        /// </summary>
        /// <param name="targets">Target UnityEngine.Object instances (used for Undo and SetDirty).</param>
        /// <param name="getChildCallback">Null and targets will be rendered, otherwise the returned
        ///                                instance from this callback.</param>
        public static void DrawMembersGUI(Object[] targets,
                                          Func <Object, object> getChildCallback = null,
                                          SerializedObject fallback = null)
        {
            targets = targets.Where(obj => obj != null).ToArray();

            if (targets.Length == 0)
            {
                return;
            }

            var objects = targets.Select(target => getChildCallback == null ?
                                         target :
                                         getChildCallback(target))
                          .Where(obj => obj != null).ToArray();

            if (objects.Length == 0)
            {
                return;
            }

            Undo.RecordObjects(targets, "Inspector");

            var hasChanges = false;

            InvokeWrapper[] fieldsAndProperties = InvokeWrapper.FindFieldsAndProperties(objects[0].GetType());
            var             group = InspectorGroupHandler.Create();

            foreach (var wrapper in fieldsAndProperties)
            {
                if (!ShouldBeShownInInspector(wrapper.Member))
                {
                    continue;
                }

                group.Update(wrapper, objects[0]);

                if (group.IsHidden)
                {
                    continue;
                }

                hasChanges = HandleType(wrapper, objects, fallback) || hasChanges;
            }
            group.Dispose();

            if (hasChanges)
            {
                foreach (var obj in targets)
                {
                    EditorUtility.SetDirty(obj);
                }
            }
        }
Beispiel #10
0
        public static object UrdfElementDrawer(object[] objects, InvokeWrapper wrapper)
        {
            if (objects.Length != 1)
            {
                InspectorGUI.WarningLabel("Multi-select of URDF Elements isn't supported.");
                return(null);
            }

            DrawUrdfElement(wrapper.Get <AGXUnity.IO.URDF.Element>(objects[0]), -1);

            return(null);
        }
Beispiel #11
0
        public void ConstraintRowsGUI(GUISkin skin)
        {
            try {
                ConstraintUtils.ConstraintRowParser constraintRowParser = ConstraintUtils.ConstraintRowParser.Create(Constraint);

                InvokeWrapper[] memberWrappers = InvokeWrapper.FindFieldsAndProperties(null, typeof(ElementaryConstraintRowData));
                if (constraintRowParser.HasTranslationalRows)
                {
                    if (GUI.Foldout(Selected(SelectedFoldout.OrdinaryElementaryTranslational), GUI.MakeLabel("Translational properties </b>(along constraint axis)<b>", true), skin, OnFoldoutStateChange))
                    {
                        using (new GUI.Indent(12))
                            HandleConstraintRowsGUI(constraintRowParser.TranslationalRows, memberWrappers, skin);
                    }
                }

                if (constraintRowParser.HasRotationalRows)
                {
                    GUI.Separator();

                    if (GUI.Foldout(Selected(SelectedFoldout.OrdinaryElementaryRotational), GUI.MakeLabel("Rotational properties </b>(about constraint axis)<b>", true), skin, OnFoldoutStateChange))
                    {
                        using (new GUI.Indent(12))
                            HandleConstraintRowsGUI(constraintRowParser.RotationalRows, memberWrappers, skin);
                    }
                }

                ElementaryConstraintController[] controllers = Constraint.GetElementaryConstraintControllers();
                if (controllers.Length > 0)
                {
                    if (!constraintRowParser.Empty)
                    {
                        GUI.Separator();
                    }

                    if (GUI.Foldout(Selected(SelectedFoldout.Controllers), GUI.MakeLabel("Controllers", true), skin, OnFoldoutStateChange))
                    {
                        using (new GUI.Indent(12)) {
                            GUI.Separator();
                            foreach (var controller in controllers)
                            {
                                HandleConstraintControllerGUI(controller, skin);

                                GUI.Separator();
                            }
                        }
                    }
                }
            }
            catch (AgXUnity.Exception e) {
                GUILayout.Label(GUI.MakeLabel("Unable to parse constraint rows", true), skin.label);
                GUILayout.Label(GUI.MakeLabel("  - " + e.Message, Color.red), skin.label);
            }
        }
Beispiel #12
0
        public static object Vector3Drawer(object obj, InvokeWrapper wrapper, GUISkin skin)
        {
            var valInField = wrapper.Get <Vector3>(obj);

            GUILayout.BeginHorizontal();
            {
                GUILayout.Label(GUI.MakeLabel(wrapper.Member.Name));
                valInField = EditorGUILayout.Vector3Field("", valInField);
            }
            GUILayout.EndHorizontal();

            return(valInField);
        }
Beispiel #13
0
        private static bool CompareMulti <ValueT>(object[] objects,
                                                  InvokeWrapper wrapper,
                                                  Func <DefaultAndUserValue <ValueT>, bool> validator)
            where ValueT : struct
        {
            var identical = true;

            for (int i = 1; i < objects.Length; ++i)
            {
                identical = identical && validator(wrapper.Get <DefaultAndUserValue <ValueT> >(objects[i]));
            }
            return(identical);
        }
Beispiel #14
0
        public static bool HandleType(InvokeWrapper wrapper, object[] objects)
        {
            if (!wrapper.CanRead())
            {
                return(false);
            }

            var drawerInfo = InspectorGUI.GetDrawerMethod(wrapper.GetContainingType());

            if (!drawerInfo.IsValid)
            {
                return(false);
            }

            EditorGUI.showMixedValue = !wrapper.AreValuesEqual(objects);

            var value   = drawerInfo.Drawer.Invoke(null, new object[] { objects[0], wrapper, Skin });
            var changed = UnityEngine.GUI.changed &&
                          (drawerInfo.IsNullable || value != null);

            // Reset changed state so that non-edited values
            // are propagated to other properties.
            UnityEngine.GUI.changed = false;

            EditorGUI.showMixedValue = false;

            if (!changed)
            {
                return(false);
            }

            foreach (var obj in objects)
            {
                object newValue = value;
                if (drawerInfo.CopyOp != null)
                {
                    newValue = wrapper.GetValue(obj);
                    // CopyOp returns the new value for value types.
                    var ret = drawerInfo.CopyOp.Invoke(null, new object[] { value, newValue });
                    if (ret != null)
                    {
                        newValue = ret;
                    }
                }
                wrapper.ConditionalSet(obj, newValue);
            }

            return(true);
        }
Beispiel #15
0
        public static object DecimalDrawer(object obj, InvokeWrapper wrapper, GUISkin skin)
        {
            float value = wrapper.GetContainingType() == typeof(double) ?
                          Convert.ToSingle(wrapper.Get <double>(obj)) :
                          wrapper.Get <float>(obj);
            FloatSliderInInspector slider = wrapper.GetAttribute <FloatSliderInInspector>();

            if (slider != null)
            {
                return(EditorGUILayout.Slider(MakeLabel(wrapper.Member), value, slider.Min, slider.Max));
            }
            else
            {
                return(EditorGUILayout.FloatField(MakeLabel(wrapper.Member), value, skin.textField));
            }
        }
Beispiel #16
0
        public static object DefaultAndUserValueFloatDrawer(object obj, InvokeWrapper wrapper, GUISkin skin)
        {
            var dauvf = wrapper.Get <DefaultAndUserValueFloat>(obj);
            var value = GUI.HandleDefaultAndUserValue(wrapper.Member.Name,
                                                      dauvf,
                                                      skin);

            if (wrapper.IsValid(value))
            {
                if (!dauvf.UseDefault)
                {
                    dauvf.Value = value;
                }
                return(obj);
            }

            return(null);
        }
Beispiel #17
0
        public static object EnumDrawer(object[] objects, InvokeWrapper wrapper)
        {
            if (!wrapper.GetContainingType().IsVisible)
            {
                return(null);
            }

            if (wrapper.GetContainingType().GetCustomAttribute <FlagsAttribute>() != null)
            {
                return(EditorGUILayout.EnumFlagsField(InspectorGUI.MakeLabel(wrapper.Member),
                                                      wrapper.Get <Enum>(objects[0]),
                                                      InspectorEditor.Skin.Popup));
            }
            else
            {
                return(EditorGUILayout.EnumPopup(InspectorGUI.MakeLabel(wrapper.Member),
                                                 wrapper.Get <Enum>(objects[0]),
                                                 InspectorEditor.Skin.Popup));
            }
        }
Beispiel #18
0
        public void Update(InvokeWrapper wrapper, object targetInstance)
        {
            var foldoutBeginAttribute = wrapper.GetAttribute <InspectorGroupBeginAttribute>();

            if (foldoutBeginAttribute != null || wrapper.HasAttribute <InspectorGroupEndAttribute>())
            {
                End();
            }

            if (foldoutBeginAttribute == null)
            {
                return;
            }

            var groupIdentifier = (targetInstance != null ? targetInstance.GetType().FullName : "null") +
                                  "_" + foldoutBeginAttribute.Name;

            Begin(!InspectorGUI.Foldout(EditorData.Instance.GetData(targetInstance as Object,
                                                                    groupIdentifier),
                                        GUI.MakeLabel(foldoutBeginAttribute.Name)));
        }
Beispiel #19
0
        public static object RangeRealDrawer(object obj, InvokeWrapper wrapper, GUISkin skin)
        {
            var      value      = wrapper.Get <RangeReal>(obj);
            GUIStyle labelStyle = skin.label;

            if (value.Min > value.Max)
            {
                if (m_rangeRealInvalidStyle == null)
                {
                    m_rangeRealInvalidStyle = new GUIStyle(skin.label);
                    m_rangeRealInvalidStyle.normal.background = GUI.CreateColoredTexture(4, 4, Color.Lerp(UnityEngine.GUI.color, Color.red, 0.75f));
                }
                labelStyle = m_rangeRealInvalidStyle;
            }

            RangeRealResult result = new RangeRealResult()
            {
                Min        = value.Min,
                MinChanged = false,
                Max        = value.Max,
                MaxChanged = false
            };

            using (new GUILayout.HorizontalScope(labelStyle)) {
                GUILayout.Label(MakeLabel(wrapper.Member), skin.label);
                result.Min              = EditorGUILayout.FloatField("", value.Min, skin.textField, GUILayout.MaxWidth(64));
                result.MinChanged       = UnityEngine.GUI.changed;
                UnityEngine.GUI.changed = false;
                result.Max              = EditorGUILayout.FloatField("", value.Max, skin.textField, GUILayout.MaxWidth(64));
                result.MaxChanged       = UnityEngine.GUI.changed;
                UnityEngine.GUI.changed = result.MinChanged || result.MaxChanged;
            }

            if (labelStyle == m_rangeRealInvalidStyle)
            {
                GUI.WarningLabel("Invalid range, Min > Max: (" + value.Min + " > " + value.Max + ")", skin);
            }

            return(result);
        }
Beispiel #20
0
        private static bool DrawMembersGUI(object obj, T target, GUISkin skin)
        {
            if (obj == null)
            {
                return(false);
            }

            if (obj == target)
            {
                Utils.GUI.PreTargetMembers(target, skin);
            }

            bool changed = false;

            InvokeWrapper[] fieldsAndProperties = InvokeWrapper.FindFieldsAndProperties(obj);
            foreach (InvokeWrapper wrapper in fieldsAndProperties)
            {
                if (ShouldBeShownInInspector(wrapper.Member))
                {
                    changed = HandleType(wrapper, target, skin) || changed;
                }
            }

            var methods = from methodInfo in obj.GetType().GetMethods(BindingFlags.Public | BindingFlags.Instance | BindingFlags.Static)
                          where
                          ShouldBeShownInInspector(methodInfo)
                          select methodInfo;

            methods.ToList().ForEach(methodInfo => changed = HandleMethod(methodInfo, target, skin) || changed);

            if (obj == target)
            {
                Utils.GUI.PostTargetMembers(target, skin);
            }

            return(changed);
        }
Beispiel #21
0
        private void HandleConstraintRowType(ConstraintUtils.ConstraintRow row, int rowIndex, InvokeWrapper wrapper, GUISkin skin)
        {
            RowLabel(rowIndex, skin);

            var    rowData = row != null ? row.RowData : null;
            object value   = null;

            if (wrapper.IsType <float>())
            {
                value = EditorGUILayout.FloatField(wrapper.Get <float>(rowData));
            }
            else if (wrapper.IsType <RangeReal>())
            {
                RangeReal currValue = wrapper.Get <RangeReal>(rowData);
                if (currValue == null)
                {
                    currValue = new RangeReal();
                }

                currValue.Min = EditorGUILayout.FloatField(currValue.Min, GUILayout.MaxWidth(128));
                currValue.Max = EditorGUILayout.FloatField(currValue.Max, GUILayout.MaxWidth(128));

                if (currValue.Min > currValue.Max)
                {
                    currValue.Min = currValue.Max;
                }

                value = currValue;
            }
            else
            {
            }

            if (wrapper.ConditionalSet(rowData, value))
            {
                EditorUtility.SetDirty(Constraint);
            }
        }
Beispiel #22
0
 public static object Vector3Drawer(object[] objects, InvokeWrapper wrapper)
 {
     return(InspectorGUI.Vector3Field(InspectorGUI.MakeLabel(wrapper.Member),
                                      wrapper.Get <Vector3>(objects[0])));
 }
Beispiel #23
0
        public static object GenericListDrawer(object[] objects, InvokeWrapper wrapper)
        {
            var list   = wrapper.Get <System.Collections.IList>(objects[0]);
            var target = objects[0] as Object;

            if (InspectorGUI.Foldout(EditorData.Instance.GetData(target, wrapper.Member.Name),
                                     InspectorGUI.MakeLabel(wrapper.Member)))
            {
                object insertElementBefore = null;
                object insertElementAfter  = null;
                object eraseElement        = null;
                var    skin         = InspectorEditor.Skin;
                var    buttonLayout = new GUILayoutOption[]
                {
                    GUILayout.Width(1.0f * EditorGUIUtility.singleLineHeight),
                    GUILayout.Height(1.0f * EditorGUIUtility.singleLineHeight)
                };
                foreach (var listObject in list)
                {
                    using (InspectorGUI.IndentScope.Single) {
                        GUILayout.BeginHorizontal();
                        {
                            InspectorGUI.Separator(1.0f, EditorGUIUtility.singleLineHeight);

                            if (InspectorGUI.Button(MiscIcon.EntryInsertBefore,
                                                    true,
                                                    "Insert new element before this.",
                                                    buttonLayout))
                            {
                                insertElementBefore = listObject;
                            }
                            if (InspectorGUI.Button(MiscIcon.EntryInsertAfter,
                                                    true,
                                                    "Insert new element after this.",
                                                    buttonLayout))
                            {
                                insertElementAfter = listObject;
                            }
                            if (InspectorGUI.Button(MiscIcon.EntryRemove,
                                                    true,
                                                    "Remove this element.",
                                                    buttonLayout))
                            {
                                eraseElement = listObject;
                            }
                        }
                        GUILayout.EndHorizontal();

                        InspectorEditor.DrawMembersGUI(new Object[] { target }, ignored => listObject);
                    }
                }

                InspectorGUI.Separator(1.0f, 0.5f * EditorGUIUtility.singleLineHeight);

                if (list.Count == 0)
                {
                    GUILayout.Label(GUI.MakeLabel("Empty", true), skin.Label);
                }

                bool addElementToList = false;
                GUILayout.BeginHorizontal();
                {
                    GUILayout.FlexibleSpace();
                    addElementToList = InspectorGUI.Button(MiscIcon.EntryInsertAfter,
                                                           true,
                                                           "Add new element.",
                                                           buttonLayout);
                }
                GUILayout.EndHorizontal();

                object newObject = null;
                if (addElementToList || insertElementBefore != null || insertElementAfter != null)
                {
                    newObject = Activator.CreateInstance(list.GetType().GetGenericArguments()[0], new object[] { });
                }

                if (eraseElement != null)
                {
                    list.Remove(eraseElement);
                }
                else if (newObject != null)
                {
                    if (addElementToList || (list.Count > 0 && insertElementAfter != null && insertElementAfter == list[list.Count - 1]))
                    {
                        list.Add(newObject);
                    }
                    else if (insertElementAfter != null)
                    {
                        list.Insert(list.IndexOf(insertElementAfter) + 1, newObject);
                    }
                    else if (insertElementBefore != null)
                    {
                        list.Insert(list.IndexOf(insertElementBefore), newObject);
                    }
                }

                if (eraseElement != null || newObject != null)
                {
                    EditorUtility.SetDirty(target);
                }
            }

            // A bit of a hack until I figure out how to handle multi-selection
            // of lists, if that should be possible at all. We're handling the
            // list from inside this drawer and by returning null the return
            // value isn't propagated to any targets.
            return(null);
        }
Beispiel #24
0
 public static object BoolDrawer(object obj, InvokeWrapper wrapper, GUISkin skin)
 {
     return(GUI.Toggle(MakeLabel(wrapper.Member), wrapper.Get <bool>(obj), skin.button, skin.label));
 }
Beispiel #25
0
 public static object ColorDrawer(object obj, InvokeWrapper wrapper, GUISkin skin)
 {
     return(EditorGUILayout.ColorField(MakeLabel(wrapper.Member), wrapper.Get <Color>(obj)));
 }
Beispiel #26
0
 public static object IntDrawer(object obj, InvokeWrapper wrapper, GUISkin skin)
 {
     return(EditorGUILayout.IntField(MakeLabel(wrapper.Member).text, wrapper.Get <int>(obj), skin.textField));
 }
Beispiel #27
0
 public static object Vector2Drawer(object obj, InvokeWrapper wrapper, GUISkin skin)
 {
     return(EditorGUILayout.Vector2Field(MakeLabel(wrapper.Member).text, wrapper.Get <Vector2>(obj)));
 }
Beispiel #28
0
 public static object StringDrawer(object obj, InvokeWrapper wrapper, GUISkin skin)
 {
     return(EditorGUILayout.TextField(MakeLabel(wrapper.Member), wrapper.Get <string>(obj), skin.textField));
 }
Beispiel #29
0
        public static object ScriptDrawer(object obj, InvokeWrapper wrapper, GUISkin skin)
        {
            object result           = null;
            var    type             = wrapper.GetContainingType();
            bool   allowSceneObject = type == typeof(GameObject) ||
                                      type.BaseType == typeof(ScriptComponent);
            Object valInField           = wrapper.Get <Object>(obj);
            bool   recursiveEditing     = wrapper.HasAttribute <AllowRecursiveEditing>();
            bool   createNewAssetButton = false;

            if (recursiveEditing)
            {
                var foldoutData = EditorData.Instance.GetData(obj as Object, wrapper.Member.Name);

                GUILayout.BeginHorizontal();
                {
                    var objFieldLabel = MakeLabel(wrapper.Member);
                    var buttonSize    = skin.label.CalcHeight(objFieldLabel, Screen.width);
                    UnityEngine.GUI.enabled = valInField != null;
                    foldoutData.Bool        = GUILayout.Button(GUI.MakeLabel(foldoutData.Bool ? "-" : "+"),
                                                               skin.button,
                                                               new GUILayoutOption[] { GUILayout.Width(20.0f), GUILayout.Height(buttonSize) }) ?
                                              // Button clicked - toggle current value.
                                              !foldoutData.Bool :
                                              // If foldout were enabled but valInField has changed to null - foldout will become disabled.
                                              valInField != null && foldoutData.Bool;
                    UnityEngine.GUI.enabled = true;
                    result = EditorGUILayout.ObjectField(objFieldLabel,
                                                         valInField,
                                                         type,
                                                         allowSceneObject,
                                                         new GUILayoutOption[] { });

                    if (typeof(ScriptAsset).IsAssignableFrom(type))
                    {
                        GUILayout.Space(4);
                        using (new GUI.ColorBlock(Color.Lerp(UnityEngine.GUI.color, Color.green, 0.1f)))
                            createNewAssetButton = GUILayout.Button(GUI.MakeLabel("New", false, "Create new asset"),
                                                                    GUILayout.Width(42),
                                                                    GUILayout.Height(buttonSize));
                    }
                }
                GUILayout.EndHorizontal();

                if (GUILayoutUtility.GetLastRect().Contains(Event.current.mousePosition) &&
                    Event.current.type == EventType.MouseDown &&
                    Event.current.button == 0)
                {
                    Event.current.Use();
                    foldoutData.Bool = !foldoutData.Bool;
                    GUIUtility.ExitGUI();
                }

                if (foldoutData.Bool)
                {
                    using (new GUI.Indent(12)) {
                        GUI.Separator();

                        GUILayout.Space(6);

                        AGXUnity.Utils.GUI.WarningLabel("Changes made to this object will affect all objects referencing this asset.",
                                                        skin);

                        GUILayout.Space(6);

                        Editor editor = Editor.CreateEditor(result as Object);
                        if (editor != null)
                        {
                            editor.OnInspectorGUI();
                        }

                        GUI.Separator();
                    }
                }
            }
            else
            {
                result = EditorGUILayout.ObjectField(MakeLabel(wrapper.Member),
                                                     valInField,
                                                     type,
                                                     allowSceneObject,
                                                     new GUILayoutOption[] { });
            }

            if (createNewAssetButton)
            {
                var assetName = type.Name.SplitCamelCase().ToLower();
                var path      = EditorUtility.SaveFilePanel("Create new " + assetName, "Assets", "new " + assetName + ".asset", "asset");
                if (path != string.Empty)
                {
                    var info         = new System.IO.FileInfo(path);
                    var relativePath = IO.Utils.MakeRelative(path, Application.dataPath);
                    var newInstance  = ScriptAsset.Create(type);
                    newInstance.name = info.Name;
                    AssetDatabase.CreateAsset(newInstance, relativePath + (info.Extension == ".asset" ? "" : ".asset"));
                    AssetDatabase.SaveAssets();
                    AssetDatabase.Refresh();

                    result = newInstance;
                }
            }

            return(result);
        }
Beispiel #30
0
        public static object GenericListDrawer(object obj, InvokeWrapper wrapper, GUISkin skin)
        {
            System.Collections.IList list = wrapper.Get <System.Collections.IList>(obj);
            var target = obj as Object;

            if (GUI.Foldout(EditorData.Instance.GetData(target, wrapper.Member.Name),
                            MakeLabel(wrapper.Member),
                            skin))
            {
                object insertElementBefore = null;
                object insertElementAfter  = null;
                object eraseElement        = null;
                var    buttonLayout        = new GUILayoutOption[] { GUILayout.Width(26), GUILayout.Height(18) };
                using (new GUI.Indent(12)) {
                    foreach (var listObject in list)
                    {
                        GUI.Separator();
                        using (new GUI.Indent(12)) {
                            GUILayout.BeginHorizontal();
                            {
                                GUILayout.BeginVertical();
                                {
                                    // Using target to render listObject since it normally (CollisionGroupEntry) isn't an Object.
                                    InspectorEditor.DrawMembersGUI(new Object[] { target }, ignored => listObject);
                                }
                                GUILayout.EndVertical();

                                using (GUI.NodeListButtonColor) {
                                    if (GUILayout.Button(GUI.MakeLabel(GUI.Symbols.ListInsertElementBefore.ToString(),
                                                                       false,
                                                                       "Insert new element before this"),
                                                         skin.button,
                                                         buttonLayout))
                                    {
                                        insertElementBefore = listObject;
                                    }
                                    if (GUILayout.Button(GUI.MakeLabel(GUI.Symbols.ListInsertElementAfter.ToString(),
                                                                       false,
                                                                       "Insert new element after this"),
                                                         skin.button,
                                                         buttonLayout))
                                    {
                                        insertElementAfter = listObject;
                                    }
                                    if (GUILayout.Button(GUI.MakeLabel(GUI.Symbols.ListEraseElement.ToString(),
                                                                       false,
                                                                       "Erase this element"),
                                                         skin.button,
                                                         buttonLayout))
                                    {
                                        eraseElement = listObject;
                                    }
                                }
                            }
                            GUILayout.EndHorizontal();
                        }
                    }

                    if (list.Count == 0)
                    {
                        GUILayout.Label(GUI.MakeLabel("Empty", true), skin.label);
                    }
                    else
                    {
                        GUI.Separator();
                    }
                }

                bool addElementToList = false;
                GUILayout.BeginHorizontal();
                {
                    GUILayout.FlexibleSpace();
                    using (GUI.NodeListButtonColor)
                        addElementToList = GUILayout.Button(GUI.MakeLabel(GUI.Symbols.ListInsertElementAfter.ToString(),
                                                                          false,
                                                                          "Add new element to list"),
                                                            skin.button,
                                                            buttonLayout);
                }
                GUILayout.EndHorizontal();

                object newObject = null;
                if (addElementToList || insertElementBefore != null || insertElementAfter != null)
                {
                    newObject = Activator.CreateInstance(list.GetType().GetGenericArguments()[0], new object[] { });
                }

                if (eraseElement != null)
                {
                    list.Remove(eraseElement);
                }
                else if (newObject != null)
                {
                    if (addElementToList || (list.Count > 0 && insertElementAfter != null && insertElementAfter == list[list.Count - 1]))
                    {
                        list.Add(newObject);
                    }
                    else if (insertElementAfter != null)
                    {
                        list.Insert(list.IndexOf(insertElementAfter) + 1, newObject);
                    }
                    else if (insertElementBefore != null)
                    {
                        list.Insert(list.IndexOf(insertElementBefore), newObject);
                    }
                }

                if (eraseElement != null || newObject != null)
                {
                    EditorUtility.SetDirty(target);
                }
            }

            // A bit of a hack until I figure out how to handle multi-selection
            // of lists, if that should be possible at all. We're handling the
            // list from inside this drawer and by returning null the return
            // value isn't propagated to any targets.
            return(null);
        }