ソースを参照

Feature: Added inspectable field for AABox
- Also fixed custom inspectable field handling

BearishSun 7 年 前
コミット
53b1c03ea9

+ 1 - 0
Source/Scripting/MBansheeEditor/MBansheeEditor.csproj

@@ -49,6 +49,7 @@
     <Compile Include="Inspectors\AudioListenerInspector.cs" />
     <Compile Include="Inspectors\AudioSourceInspector.cs" />
     <Compile Include="Inspectors\BoneInspector.cs" />
+    <Compile Include="Windows\Inspector\InspectableAABox.cs" />
     <Compile Include="Inspectors\LightProbeVolumeInspector.cs" />
     <Compile Include="Inspectors\ReflectionProbeInspector.cs" />
     <Compile Include="Inspectors\RenderSettingsInspector.cs" />

+ 1 - 1
Source/Scripting/MBansheeEditor/Windows/Inspector/CustomInspector.cs

@@ -13,7 +13,7 @@ namespace BansheeEditor
     /// Specifies that a class or a struct uses a custom inspector for GUI display. This attribute can be placed on an 
     /// implementation of <see cref="Inspector"/> in which case the type must reference a <see cref="Component"/> or a
     /// <see cref="Resource"/>. Or it can be placed on an implementation of <see cref="InspectableField"/> in which
-    /// case they type must reference any serializable class/struct, but may also reference an attribute in which case
+    /// case their type must reference any serializable class/struct, but may also reference an attribute in which case
     /// any serializable type with that attribute applied with have a custom inspector.
     /// </summary>
     [AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct)]

+ 105 - 0
Source/Scripting/MBansheeEditor/Windows/Inspector/InspectableAABox.cs

@@ -0,0 +1,105 @@
+//********************************** Banshee Engine (www.banshee3d.com) **************************************************//
+//**************** Copyright (c) 2019 Marko Pintera ([email protected]). All rights reserved. **********************//
+using BansheeEngine;
+
+namespace BansheeEditor
+{
+    /** @addtogroup Inspector
+     *  @{
+     */
+
+    /// <summary>
+    /// Displays GUI for a serializable property containing an AABox.
+    /// </summary>
+    [CustomInspector(typeof(AABox))]
+    public class InspectableAABox : InspectableField
+    {
+        private GUIVector3Field centerField;
+        private GUIVector3Field sizeField;
+        private InspectableState state;
+
+        /// <summary>
+        /// Creates a new inspectable AABox GUI for the specified property.
+        /// </summary>
+        /// <param name="parent">Parent Inspector this field belongs to.</param>
+        /// <param name="title">Name of the property, or some other value to set as the title.</param>
+        /// <param name="path">Full path to this property (includes name of this property and all parent properties).</param>
+        /// <param name="depth">Determines how deep within the inspector nesting hierarchy is this field. Some fields may
+        ///                     contain other fields, in which case you should increase this value by one.</param>
+        /// <param name="layout">Parent layout that all the field elements will be added to.</param>
+        /// <param name="property">Serializable property referencing the field whose contents to display.</param>
+        public InspectableAABox(Inspector parent, string title, string path, int depth, InspectableFieldLayout layout,
+            SerializableProperty property)
+            : base(parent, title, path, SerializableProperty.FieldType.Object, depth, layout, property)
+        { }
+
+        /// <inheritoc/>
+        protected internal override void Initialize(int layoutIndex)
+        {
+            GUILayoutX boundsLayout = new GUILayoutX();
+            centerField = new GUIVector3Field(new LocEdString("Center"), 50);
+            sizeField = new GUIVector3Field(new LocEdString("Size"), 50);
+
+            layout.AddElement(layoutIndex, boundsLayout);
+
+            boundsLayout.AddElement(new GUILabel(new LocEdString(title), GUIOption.FixedWidth(100)));
+
+            GUILayoutY boundsContent = boundsLayout.AddLayoutY();
+            boundsContent.AddElement(centerField);
+            boundsContent.AddElement(sizeField);
+
+            centerField.OnChanged += x =>
+            {
+                AABox bounds = property.GetValue<AABox>();
+                Vector3 min = x - bounds.Size * 0.5f;
+                Vector3 max = x + bounds.Size * 0.5f;
+
+                property.SetValue(new AABox(min, max));
+                state |= InspectableState.ModifyInProgress;
+            };
+            centerField.OnConfirmed += OnFieldValueConfirm;
+            centerField.OnFocusLost += OnFieldValueConfirm;
+
+            sizeField.OnChanged += x =>
+            {
+                AABox bounds = property.GetValue<AABox>();
+                Vector3 min = bounds.Center - x * 0.5f;
+                Vector3 max = bounds.Center + x * 0.5f;
+
+                property.SetValue(new AABox(min, max));
+                state |= InspectableState.ModifyInProgress;
+            };
+            sizeField.OnConfirmed += OnFieldValueConfirm;
+            sizeField.OnFocusLost += OnFieldValueConfirm;
+        }
+
+        /// <inheritdoc/>
+        public override InspectableState Refresh(int layoutIndex)
+        {
+            if ((centerField != null && !centerField.HasInputFocus) &&
+                (sizeField != null && !sizeField.HasInputFocus))
+            {
+                AABox box = property.GetValue<AABox>();
+                centerField.Value = box.Center;
+                sizeField.Value = box.Size;
+            }
+
+            InspectableState oldState = state;
+            if (state.HasFlag(InspectableState.Modified))
+                state = InspectableState.NotModified;
+
+            return oldState;
+        }
+
+        /// <summary>
+        /// Triggered when the user confirms input in either of the 3D vector fields.
+        /// </summary>
+        private void OnFieldValueConfirm()
+        {
+            if (state.HasFlag(InspectableState.ModifyInProgress))
+                state |= InspectableState.Modified;
+        }
+    }
+
+    /** @} */
+}

+ 2 - 1
Source/Scripting/MBansheeEditor/Windows/Inspector/InspectableField.cs

@@ -144,7 +144,8 @@ namespace BansheeEditor
             Type customInspectable = InspectorUtility.GetCustomInspectable(type);
             if (customInspectable != null)
             {
-                field = (InspectableField) Activator.CreateInstance(customInspectable, depth, title, property);
+                field = (InspectableField) Activator.CreateInstance(customInspectable, parent, title, path, depth, layout, 
+                    property);
             }
             else
             {

+ 4 - 4
Source/Scripting/MBansheeEditor/Windows/Inspector/InspectorWindow.cs

@@ -119,7 +119,7 @@ namespace BansheeEditor
 
             currentType = InspectorType.Resource;
 
-            inspectorScrollArea = new GUIScrollArea();
+            inspectorScrollArea = new GUIScrollArea(ScrollBarType.ShowIfDoesntFit, ScrollBarType.NeverShow);
             GUI.AddElement(inspectorScrollArea);
             inspectorLayout = inspectorScrollArea.Layout;
 
@@ -170,7 +170,7 @@ namespace BansheeEditor
             currentType = InspectorType.SceneObject;
             activeSO = so;
 
-            inspectorScrollArea = new GUIScrollArea();
+            inspectorScrollArea = new GUIScrollArea(ScrollBarType.ShowIfDoesntFit, ScrollBarType.NeverShow);
             scrollAreaHighlight = new GUITexture(Builtin.WhiteTexture);
             scrollAreaHighlight.SetTint(HIGHLIGHT_COLOR);
             scrollAreaHighlight.Active = false;
@@ -553,7 +553,7 @@ namespace BansheeEditor
             if (objects.Length == 0 && paths.Length == 0)
             {
                 currentType = InspectorType.None;
-                inspectorScrollArea = new GUIScrollArea();
+                inspectorScrollArea = new GUIScrollArea(ScrollBarType.ShowIfDoesntFit, ScrollBarType.NeverShow);
                 GUI.AddElement(inspectorScrollArea);
                 inspectorLayout = inspectorScrollArea.Layout;
 
@@ -567,7 +567,7 @@ namespace BansheeEditor
             else if ((objects.Length + paths.Length) > 1)
             {
                 currentType = InspectorType.None;
-                inspectorScrollArea = new GUIScrollArea();
+                inspectorScrollArea = new GUIScrollArea(ScrollBarType.ShowIfDoesntFit, ScrollBarType.NeverShow);
                 GUI.AddElement(inspectorScrollArea);
                 inspectorLayout = inspectorScrollArea.Layout;
 

+ 13 - 5
Source/Scripting/SBansheeEditor/Wrappers/BsScriptInspectorUtility.cpp

@@ -51,15 +51,23 @@ namespace bs
 		MonoAssembly* editorAssembly = MonoManager::instance().getAssembly(EDITOR_ASSEMBLY);
 		mCustomInspectorAtribute = editorAssembly->getClass("BansheeEditor", "CustomInspector");
 		if (mCustomInspectorAtribute == nullptr)
-			BS_EXCEPT(InvalidStateException, "Cannot find CustomInspector managed class.");
+			BS_EXCEPT(InternalErrorException, "Cannot find CustomInspector managed class.");
 
 		MonoClass* inspectorClass = editorAssembly->getClass("BansheeEditor", "Inspector");
 		if (inspectorClass == nullptr)
-			BS_EXCEPT(InvalidStateException, "Cannot find Inspector managed class.");
+			BS_EXCEPT(InternalErrorException, "Cannot find Inspector managed class.");
 
 		MonoClass* inspectableFieldClass = editorAssembly->getClass("BansheeEditor", "InspectableField");
 		if (inspectableFieldClass == nullptr)
-			BS_EXCEPT(InvalidStateException, "Cannot find InspectableField managed class.");
+			BS_EXCEPT(InternalErrorException, "Cannot find InspectableField managed class.");
+
+		MonoAssembly* corlib = MonoManager::instance().getAssembly("corlib");
+		if(corlib == nullptr)
+			BS_EXCEPT(InternalErrorException, "corlib assembly is not loaded.");
+
+		MonoClass* systemAttributeClass = corlib->getClass("System", "Attribute");
+		if(systemAttributeClass == nullptr)
+			BS_EXCEPT(InternalErrorException, "Cannot find System.Attribute managed class.");
 
 		mTypeField = mCustomInspectorAtribute->getField("type");
 
@@ -98,9 +106,9 @@ namespace bs
 
 					mInspectorTypes[referencedClass] = curClass;
 				}
-				else if (curClass->isSubClassOf(inspectableFieldClass))
+				else if (curClass->isSubClassOf(inspectableFieldClass) || curClass->isSubClassOf(systemAttributeClass))
 				{
-					mInspectorTypes[referencedClass] = curClass;
+					mInspectableFieldTypes[referencedClass] = curClass;
 				}
 			}
 		}