Forráskód Böngészése

Modifying struct members in inspector now properly persists the changes

Marko Pintera 10 éve
szülő
commit
9776b4efa4

+ 23 - 2
MBansheeEngine/SerializableField.cs

@@ -56,8 +56,29 @@ namespace BansheeEngine
 
 
         public SerializableProperty GetProperty()
         public SerializableProperty GetProperty()
         {
         {
-            SerializableProperty.Getter getter = () => Internal_GetValue(mCachedPtr, parent.referencedObject);
-            SerializableProperty.Setter setter = (object value) => Internal_SetValue(mCachedPtr, parent.referencedObject, value);
+            SerializableProperty.Getter getter = () =>
+            {
+                object parentObject = parent.GetReferencedObject();
+                
+                if (parentObject != null)
+                    return Internal_GetValue(mCachedPtr, parentObject);
+                else
+                    return null;
+            };
+
+            SerializableProperty.Setter setter = (object value) =>
+            {
+                object parentObject = parent.GetReferencedObject();
+
+                if (parentObject != null)
+                {
+                    Internal_SetValue(mCachedPtr, parentObject, value);
+
+                    // If value type we cannot just modify the parent object because it's just a copy
+                    if (parentObject.GetType().IsValueType && parent.parentProperty != null)
+                        parent.parentProperty.SetValue(parentObject);
+                }
+            };
 
 
             SerializableProperty newProperty = Internal_CreateProperty(mCachedPtr);
             SerializableProperty newProperty = Internal_CreateProperty(mCachedPtr);
             newProperty.Construct(type, internalType, getter, setter);
             newProperty.Construct(type, internalType, getter, setter);

+ 21 - 8
MBansheeEngine/SerializableObject.cs

@@ -10,20 +10,25 @@ namespace BansheeEngine
     #pragma warning disable 649
     #pragma warning disable 649
     public sealed class SerializableObject : ScriptObject
     public sealed class SerializableObject : ScriptObject
     {
     {
-        internal object referencedObject;
+        internal SerializableProperty parentProperty;
+        internal object parentObject;
         private SerializableField[] _fields;
         private SerializableField[] _fields;
 
 
-        public SerializableObject(Type objectType, object instance)
+        // Note: Also called from native code
+        public SerializableObject(Type objectType, SerializableProperty parentProperty)
         {
         {
-            Internal_CreateInstance(this, objectType, instance);
+            Internal_CreateInstance(this, objectType);
 
 
-            referencedObject = instance;
+            this.parentProperty = parentProperty;
+            this.parentObject = null;
         }
         }
 
 
-        // Constructed from native code
-        private SerializableObject(object instance)
+        public SerializableObject(Type objectType, object parentObject)
         {
         {
-            referencedObject = instance;
+            Internal_CreateInstance(this, objectType);
+
+            this.parentProperty = null;
+            this.parentObject = parentObject;
         }
         }
 
 
         public SerializableField[] fields
         public SerializableField[] fields
@@ -31,7 +36,15 @@ namespace BansheeEngine
             get { return _fields; }
             get { return _fields; }
         }
         }
 
 
+        public object GetReferencedObject()
+        {
+            if (parentProperty != null)
+                return parentProperty.GetValue<object>();
+            else
+                return parentObject;
+        }
+
         [MethodImpl(MethodImplOptions.InternalCall)]
         [MethodImpl(MethodImplOptions.InternalCall)]
-        private static extern void Internal_CreateInstance(SerializableObject instance, Type objectType, object objInstance);
+        private static extern void Internal_CreateInstance(SerializableObject instance, Type objectType);
     }
     }
 }
 }

+ 1 - 0
SBansheeEngine/Include/BsScriptEnginePrerequisites.h

@@ -68,6 +68,7 @@ namespace BansheeEngine
 	class ManagedSerializableDiff;
 	class ManagedSerializableDiff;
 	class ManagedResource;
 	class ManagedResource;
 	class ManagedResourceMetaData;
 	class ManagedResourceMetaData;
+	class ScriptSerializableProperty;
 	class ScriptAssemblyManager;
 	class ScriptAssemblyManager;
 	class ScriptHString;
 	class ScriptHString;
 	class ScriptContextMenu;
 	class ScriptContextMenu;

+ 2 - 2
SBansheeEngine/Include/BsScriptSerializableObject.h

@@ -10,10 +10,10 @@ namespace BansheeEngine
 	public:
 	public:
 		SCRIPT_OBJ(ENGINE_ASSEMBLY, "BansheeEngine", "SerializableObject")
 		SCRIPT_OBJ(ENGINE_ASSEMBLY, "BansheeEngine", "SerializableObject")
 
 
-		static ScriptSerializableObject* create(const ManagedSerializableTypeInfoPtr& typeInfo, MonoObject* object);
+		static ScriptSerializableObject* create(ScriptSerializableProperty* parentProperty, MonoObject* object);
 
 
 	private:
 	private:
-		static void internal_createInstance(MonoObject* instance, MonoReflectionType* type, MonoObject* object);
+		static void internal_createInstance(MonoObject* instance, MonoReflectionType* type);
 
 
 		static ScriptSerializableObject* createInternal(MonoObject* instance, const ManagedSerializableObjectInfoPtr& objInfo);
 		static ScriptSerializableObject* createInternal(MonoObject* instance, const ManagedSerializableObjectInfoPtr& objInfo);
 
 

+ 2 - 0
SBansheeEngine/Include/BsScriptSerializableProperty.h

@@ -12,6 +12,8 @@ namespace BansheeEngine
 
 
 		static ScriptSerializableProperty* create(const ManagedSerializableTypeInfoPtr& typeInfo);
 		static ScriptSerializableProperty* create(const ManagedSerializableTypeInfoPtr& typeInfo);
 
 
+		ManagedSerializableTypeInfoPtr getTypeInfo() const { return mTypeInfo; }
+
 		~ScriptSerializableProperty() {}
 		~ScriptSerializableProperty() {}
 
 
 	private:
 	private:

+ 5 - 4
SBansheeEngine/Source/BsScriptSerializableObject.cpp

@@ -1,5 +1,6 @@
 #include "BsScriptSerializableObject.h"
 #include "BsScriptSerializableObject.h"
 #include "BsScriptSerializableField.h"
 #include "BsScriptSerializableField.h"
+#include "BsScriptSerializableProperty.h"
 #include "BsScriptAssemblyManager.h"
 #include "BsScriptAssemblyManager.h"
 #include "BsScriptMeta.h"
 #include "BsScriptMeta.h"
 #include "BsMonoField.h"
 #include "BsMonoField.h"
@@ -24,12 +25,12 @@ namespace BansheeEngine
 		FieldsField = metaData.scriptClass->getField("_fields");
 		FieldsField = metaData.scriptClass->getField("_fields");
 	}
 	}
 
 
-	ScriptSerializableObject* ScriptSerializableObject::create(const ManagedSerializableTypeInfoPtr& typeInfo, MonoObject* object)
+	ScriptSerializableObject* ScriptSerializableObject::create(ScriptSerializableProperty* property, MonoObject* object)
 	{
 	{
-		MonoType* monoInternalElementType = mono_class_get_type(typeInfo->getMonoClass());
+		MonoType* monoInternalElementType = mono_class_get_type(property->getTypeInfo()->getMonoClass());
 		MonoReflectionType* internalElementType = mono_type_get_object(MonoManager::instance().getDomain(), monoInternalElementType);
 		MonoReflectionType* internalElementType = mono_type_get_object(MonoManager::instance().getDomain(), monoInternalElementType);
 
 
-		void* params[2] = { internalElementType, object };
+		void* params[2] = { internalElementType, property->getManagedInstance() };
 		MonoObject* managedInstance = metaData.scriptClass->createInstance(params, 2);
 		MonoObject* managedInstance = metaData.scriptClass->createInstance(params, 2);
 
 
 		// Managed constructor will call back to native which will create ScriptSerializableObject instance,
 		// Managed constructor will call back to native which will create ScriptSerializableObject instance,
@@ -37,7 +38,7 @@ namespace BansheeEngine
 		return ScriptSerializableObject::toNative(managedInstance);
 		return ScriptSerializableObject::toNative(managedInstance);
 	}
 	}
 
 
-	void ScriptSerializableObject::internal_createInstance(MonoObject* instance, MonoReflectionType* type, MonoObject* object)
+	void ScriptSerializableObject::internal_createInstance(MonoObject* instance, MonoReflectionType* type)
 	{
 	{
 		MonoType* internalType = mono_reflection_type_get_type(type);
 		MonoType* internalType = mono_reflection_type_get_type(type);
 		::MonoClass* monoClass = mono_type_get_class(internalType);
 		::MonoClass* monoClass = mono_type_get_class(internalType);

+ 1 - 1
SBansheeEngine/Source/BsScriptSerializableProperty.cpp

@@ -48,7 +48,7 @@ namespace BansheeEngine
 
 
 	MonoObject* ScriptSerializableProperty::internal_createObject(ScriptSerializableProperty* nativeInstance, MonoObject* object)
 	MonoObject* ScriptSerializableProperty::internal_createObject(ScriptSerializableProperty* nativeInstance, MonoObject* object)
 	{
 	{
-		ScriptSerializableObject* newObject = ScriptSerializableObject::create(nativeInstance->mTypeInfo, object);
+		ScriptSerializableObject* newObject = ScriptSerializableObject::create(nativeInstance, object);
 
 
 		return newObject->getManagedInstance();
 		return newObject->getManagedInstance();
 	}
 	}

+ 3 - 4
TODO.txt

@@ -56,7 +56,7 @@ Polish
 
 
 TODO:
 TODO:
  - Thoroughly test inspector
  - Thoroughly test inspector
- - Modifying structs doesn't persist changes
+ - Writing on a child struct field unfocused input because the inspector gets rebuilt - delay rebuild until user unfocuses from the input box?
 
 
 Ribek use:
 Ribek use:
  - Camera, Renderable, Material, Texture inspector
  - Camera, Renderable, Material, Texture inspector
@@ -107,14 +107,13 @@ Other polish:
  - Ortographic camera views (+ gizmo in scene view corner that shows camera orientation)
  - Ortographic camera views (+ gizmo in scene view corner that shows camera orientation)
  - Drag to select in scene view
  - Drag to select in scene view
  - Update GUISlider so it works with the new style (and to have min/max limits, plus step size)
  - Update GUISlider so it works with the new style (and to have min/max limits, plus step size)
- - Replace "minimize" button in tabbed title bar with maximize and make sure it works
+ - Replace "minimize" button in tabbed title bar with maximize and make sure it works (in both docked and floating mode)
  - When I expand inspector elements and them come back to that object it should remember the previous state
  - When I expand inspector elements and them come back to that object it should remember the previous state
    - Add a chaching mechanism to inspector (likely based on instance ID & property names)
    - Add a chaching mechanism to inspector (likely based on instance ID & property names)
    - This has to work not only when I come back to the object, but whenever inspector rebuilds (e.g. after removing element from array)
    - This has to work not only when I come back to the object, but whenever inspector rebuilds (e.g. after removing element from array)
    - Consider saving this information with the serialized object
    - Consider saving this information with the serialized object
  - Make sure to persist EditorSettings
  - Make sure to persist EditorSettings
  - Import option inspectors for Texture, Mesh, Font
  - Import option inspectors for Texture, Mesh, Font
- - DOck manager maximize doesn't work'
 
 
 Stage 2 polish:
 Stage 2 polish:
  - Inject an icon into an .exe (Win32 specific)
  - Inject an icon into an .exe (Win32 specific)
@@ -130,13 +129,13 @@ Stage 2 polish:
 
 
 Finalizing:
 Finalizing:
  - Add copyright notices in all files & change license to GPL
  - Add copyright notices in all files & change license to GPL
+ - UseCustomInspector isn't implemented
  - I could record undo/redo per-property using the new diff system
  - I could record undo/redo per-property using the new diff system
  - When building game make sure to go over texture resources and ensure they are saved in the valid format
  - When building game make sure to go over texture resources and ensure they are saved in the valid format
    as we don't want to do format conversion at runtime (Not cruical, but it should be done eventually)
    as we don't want to do format conversion at runtime (Not cruical, but it should be done eventually)
    - This should something similar to Unity where when changing the platform all resources get reimported
    - This should something similar to Unity where when changing the platform all resources get reimported
  - When building level for release make sure to clear all prefab diffs (possibly store them elsewhere in the first place)
  - When building level for release make sure to clear all prefab diffs (possibly store them elsewhere in the first place)
    - And all prefab instances should have updateFromPrefab called on them.
    - And all prefab instances should have updateFromPrefab called on them.
- - Save the default editor layout somewhere and make sure its used on initial startup when no layout exists
  - Undo/Redo when breaking or reverting a scene object (and in general test & finalize undo/redo system)
  - Undo/Redo when breaking or reverting a scene object (and in general test & finalize undo/redo system)
  - Move all the code files into subfolders so their hierarchy is similar to VS filters
  - Move all the code files into subfolders so their hierarchy is similar to VS filters
  - Get rid of PoolAlloc and other unused allocators (plus fix bs_new and others which have weird overloads)
  - Get rid of PoolAlloc and other unused allocators (plus fix bs_new and others which have weird overloads)