Explorar el Código

Added C# Prefab

Marko Pintera hace 10 años
padre
commit
927a721f58

+ 1 - 0
BansheeCore/Source/BsPrefab.cpp

@@ -35,6 +35,7 @@ namespace BansheeEngine
 
 	void Prefab::initialize(const HSceneObject& sceneObject)
 	{
+		sceneObject->breakPrefabLink();
 		PrefabUtility::generatePrefabIds(sceneObject);
 
 		sceneObject->setFlags(SOF_DontInstantiate);

+ 1 - 0
MBansheeEngine/MBansheeEngine.csproj

@@ -104,6 +104,7 @@
     <Compile Include="PixelData.cs" />
     <Compile Include="PixelUtility.cs" />
     <Compile Include="PlainText.cs" />
+    <Compile Include="Prefab.cs" />
     <Compile Include="Program.cs" />
     <Compile Include="Properties\AssemblyInfo.cs" />
     <Compile Include="Math\Quaternion.cs" />

+ 38 - 0
MBansheeEngine/Prefab.cs

@@ -0,0 +1,38 @@
+using System;
+using System.Runtime.CompilerServices;
+using System.Runtime.InteropServices;
+
+namespace BansheeEngine
+{
+    public class Prefab : Resource
+    {
+        // For internal use by the runtime
+        private Prefab()
+        { }
+
+        public Prefab(SceneObject so)
+        {
+            IntPtr soPtr = so.GetCachedPtr();
+            Internal_CreateInstance(this, soPtr);
+        }
+
+        public SceneObject Root
+        {
+            get { return Internal_GetRoot(mCachedPtr); }
+        }
+
+        public SceneObject Instantiate()
+        {
+            return Internal_Instantiate(mCachedPtr);
+        }
+
+        [MethodImpl(MethodImplOptions.InternalCall)]
+        private static extern void Internal_CreateInstance(Prefab instance, IntPtr so);
+
+        [MethodImpl(MethodImplOptions.InternalCall)]
+        private static extern SceneObject Internal_GetRoot(IntPtr thisPtr);
+
+        [MethodImpl(MethodImplOptions.InternalCall)]
+        private static extern SceneObject Internal_Instantiate(IntPtr thisPtr);
+    }
+}

+ 32 - 0
MBansheeEngine/SceneObject.cs

@@ -193,6 +193,26 @@ namespace BansheeEngine
             return Internal_GetChild(mCachedPtr, idx);
         }
 
+        public Prefab GetPrefab()
+        {
+            return Internal_GetPrefab(mCachedPtr);
+        }
+
+        public void BreakPrefab()
+        {
+            Internal_BreakPrefab(mCachedPtr);
+        }
+
+        public void ApplyPrefab()
+        {
+            Internal_ApplyPrefab(mCachedPtr);
+        }
+
+        public void RevertPrefab()
+        {
+            Internal_RevertPrefab(mCachedPtr);
+        }
+
         public void LookAt(Vector3 direction)
         {
             Internal_LookAt(mCachedPtr, direction, Vector3.yAxis);
@@ -253,6 +273,18 @@ namespace BansheeEngine
         [MethodImpl(MethodImplOptions.InternalCall)]
         private static extern SceneObject Internal_GetChild(IntPtr nativeInstance, int idx);
 
+        [MethodImpl(MethodImplOptions.InternalCall)]
+        private static extern Prefab Internal_GetPrefab(IntPtr nativeInstance);
+
+        [MethodImpl(MethodImplOptions.InternalCall)]
+        private static extern void Internal_BreakPrefab(IntPtr nativeInstance);
+
+        [MethodImpl(MethodImplOptions.InternalCall)]
+        private static extern void Internal_ApplyPrefab(IntPtr nativeInstance);
+
+        [MethodImpl(MethodImplOptions.InternalCall)]
+        private static extern void Internal_RevertPrefab(IntPtr nativeInstance);
+
         [MethodImpl(MethodImplOptions.InternalCall)]
         private static extern void Internal_GetPosition(IntPtr nativeInstance, out Vector3 value);
 

+ 1 - 0
SBansheeEngine/Include/BsManagedSerializableObjectInfo.h

@@ -31,6 +31,7 @@ namespace BansheeEngine
 		ShaderRef,
 		MaterialRef,
 		MeshRef,
+		PrefabRef,
 		SceneObjectRef,
 		ComponentRef
 	};

+ 2 - 0
SBansheeEngine/Include/BsScriptAssemblyManager.h

@@ -35,6 +35,7 @@ namespace BansheeEngine
 		MonoClass* getMaterialClass() const { return mMaterialClass; }
 		MonoClass* getMeshClass() const { return mMeshClass; }
 		MonoClass* getFontClass() const { return mFontClass; }
+		MonoClass* getPrefabClass() const { return mPrefabClass;  }
 		MonoClass* getPlainTextClass() const { return mPlainTextClass; }
 		MonoClass* getScriptCodeClass() const { return mScriptCodeClass; }
 
@@ -60,6 +61,7 @@ namespace BansheeEngine
 		MonoClass* mMeshClass;
 		MonoClass* mManagedResourceClass;
 		MonoClass* mFontClass;
+		MonoClass* mPrefabClass;
 		MonoClass* mPlainTextClass;
 		MonoClass* mScriptCodeClass;
 

+ 1 - 0
SBansheeEngine/Include/BsScriptEnginePrerequisites.h

@@ -33,6 +33,7 @@ namespace BansheeEngine
 	class ScriptShader;
 	class ScriptMaterial;
 	class ScriptMesh;
+	class ScriptPrefab;
 	class ScriptGUIElementStyle;
 	class ScriptGUIElementStateStyle;
 	class ScriptGUILayout;

+ 31 - 0
SBansheeEngine/Include/BsScriptPrefab.h

@@ -0,0 +1,31 @@
+#pragma once
+
+#include "BsScriptEnginePrerequisites.h"
+#include "BsScriptResource.h"
+#include "BsPrefab.h"
+
+namespace BansheeEngine
+{
+	class BS_SCR_BE_EXPORT ScriptPrefab : public ScriptObject<ScriptPrefab, ScriptResourceBase>
+	{
+	public:
+		SCRIPT_OBJ(ENGINE_ASSEMBLY, "BansheeEngine", "Prefab")
+
+		HResource getNativeHandle() const override { return mPrefab; }
+		void setNativeHandle(const HResource& resource);
+
+		HPrefab getPrefabHandle() const { return mPrefab; }
+	private:
+		friend class ScriptResourceManager;
+
+		ScriptPrefab(MonoObject* instance, const HPrefab& prefab);
+
+		static void internal_CreateInstance(MonoObject* instance, ScriptSceneObject* so);
+		static MonoObject* internal_GetRoot(ScriptPrefab* instance);
+		static MonoObject* internal_Instantiate(ScriptPrefab* instance);
+
+		void _onManagedInstanceDeleted();
+
+		HPrefab mPrefab;
+	};
+}

+ 17 - 0
SBansheeEngine/Include/BsScriptResourceManager.h

@@ -131,6 +131,18 @@ namespace BansheeEngine
 		 */
 		ScriptFont* createScriptFont(MonoObject* existingInstance, const HFont& resourceHandle);
 
+		/**
+		 * @note Throws an exception if resource for the handle already exists.
+		 * 		 Creates a new managed instance of the object.
+		 */
+		ScriptPrefab* createScriptPrefab(const HPrefab& resourceHandle);
+
+		/**
+		 * @note Throws an exception if resource for the handle already exists.
+		 * 		 Initializes the ScriptResource with an existing managed instance.
+		 */
+		ScriptPrefab* createScriptPrefab(MonoObject* existingInstance, const HPrefab& resourceHandle);
+
 		/**
 		* @note  Throws an exception if resource for the handle already exists.
 		* 		 Initializes the ScriptResource with an existing managed instance.
@@ -187,6 +199,11 @@ namespace BansheeEngine
 		 */
 		ScriptManagedResource* getScriptManagedResource(const HManagedResource& resourceHandle);
 
+		/**
+		 * @note Returns nullptr if script resource doesn't exist.
+		 */
+		ScriptPrefab* getScriptPrefab(const HPrefab& resourceHandle);
+
 		/**
 		 * @note Returns nullptr if script resource doesn't exist.
 		 */

+ 5 - 0
SBansheeEngine/Include/BsScriptSceneObject.h

@@ -28,6 +28,11 @@ namespace BansheeEngine
 		static void internal_getNumChildren(ScriptSceneObject* nativeInstance, UINT32* value);
 		static MonoObject* internal_getChild(ScriptSceneObject* nativeInstance, UINT32 idx);
 
+		static MonoObject* internal_getPrefab(ScriptSceneObject* nativeInstance);
+		static void internal_breakPrefab(ScriptSceneObject* nativeInstance);
+		static void internal_applyPrefab(ScriptSceneObject* nativeInstance);
+		static void internal_revertPrefab(ScriptSceneObject* nativeInstance);
+
 		static void internal_getPosition(ScriptSceneObject* nativeInstance, Vector3* value);
 		static void internal_getLocalPosition(ScriptSceneObject* nativeInstance, Vector3* value);
 		static void internal_getRotation(ScriptSceneObject* nativeInstance, Quaternion* value);

+ 2 - 0
SBansheeEngine/SBansheeEngine.vcxproj

@@ -297,6 +297,7 @@
     <ClInclude Include="Include\BsScriptPixelData.h" />
     <ClInclude Include="Include\BsScriptPixelUtility.h" />
     <ClInclude Include="Include\BsScriptPlainText.h" />
+    <ClInclude Include="Include\BsScriptPrefab.h" />
     <ClInclude Include="Include\BsScriptRenderableHandler.h" />
     <ClInclude Include="Include\BsScriptRenderTarget.h" />
     <ClInclude Include="Include\BsScriptRenderTexture.h" />
@@ -380,6 +381,7 @@
     <ClCompile Include="Source\BsScriptPixelData.cpp" />
     <ClCompile Include="Source\BsScriptPixelUtility.cpp" />
     <ClCompile Include="Source\BsScriptPlainText.cpp" />
+    <ClCompile Include="Source\BsScriptPrefab.cpp" />
     <ClCompile Include="Source\BsScriptRenderableHandler.cpp" />
     <ClCompile Include="Source\BsScriptRenderTarget.cpp" />
     <ClCompile Include="Source\BsScriptRenderTexture.cpp" />

+ 6 - 0
SBansheeEngine/SBansheeEngine.vcxproj.filters

@@ -318,6 +318,9 @@
     <ClInclude Include="Include\BsManagedDiff.h">
       <Filter>Header Files\Serialization</Filter>
     </ClInclude>
+    <ClInclude Include="Include\BsScriptPrefab.h">
+      <Filter>Header Files</Filter>
+    </ClInclude>
   </ItemGroup>
   <ItemGroup>
     <ClCompile Include="Source\BsScriptTexture2D.cpp">
@@ -572,5 +575,8 @@
     <ClCompile Include="Source\BsManagedDiff.cpp">
       <Filter>Source Files\Serialization</Filter>
     </ClCompile>
+    <ClCompile Include="Source\BsScriptPrefab.cpp">
+      <Filter>Source Files</Filter>
+    </ClCompile>
   </ItemGroup>
 </Project>

+ 34 - 6
SBansheeEngine/Source/BsManagedSerializableField.cpp

@@ -15,6 +15,7 @@
 #include "BsScriptShader.h"
 #include "BsScriptMaterial.h"
 #include "BsScriptMesh.h"
+#include "BsScriptPrefab.h"
 #include "BsScriptSceneObject.h"
 #include "BsScriptComponent.h"
 #include "BsManagedSerializableObject.h"
@@ -167,7 +168,7 @@ namespace BansheeEngine
 					if(value != nullptr)
 					{
 						ScriptTexture2D* scriptTexture2D = ScriptTexture2D::toNative(value);
-						fieldData->value = static_resource_cast<ScriptTexture2D>(scriptTexture2D->getNativeHandle());
+						fieldData->value = static_resource_cast<Texture>(scriptTexture2D->getNativeHandle());
 					}
 
 					return fieldData;
@@ -179,7 +180,7 @@ namespace BansheeEngine
 				if (value != nullptr)
 				{
 					ScriptTexture3D* scriptTexture3D = ScriptTexture3D::toNative(value);
-					fieldData->value = static_resource_cast<ScriptTexture3D>(scriptTexture3D->getNativeHandle());
+					fieldData->value = static_resource_cast<Texture>(scriptTexture3D->getNativeHandle());
 				}
 
 				return fieldData;
@@ -191,7 +192,7 @@ namespace BansheeEngine
 				if (value != nullptr)
 				{
 					ScriptTextureCube* scriptTextureCube = ScriptTextureCube::toNative(value);
-					fieldData->value = static_resource_cast<ScriptTextureCube>(scriptTextureCube->getNativeHandle());
+					fieldData->value = static_resource_cast<Texture>(scriptTextureCube->getNativeHandle());
 				}
 
 				return fieldData;
@@ -215,7 +216,7 @@ namespace BansheeEngine
 				if (value != nullptr)
 				{
 					ScriptShader* scriptShader = ScriptShader::toNative(value);
-					fieldData->value = static_resource_cast<ScriptShader>(scriptShader->getNativeHandle());
+					fieldData->value = static_resource_cast<Shader>(scriptShader->getNativeHandle());
 				}
 
 				return fieldData;
@@ -227,7 +228,7 @@ namespace BansheeEngine
 				if (value != nullptr)
 				{
 					ScriptMaterial* scriptMaterial = ScriptMaterial::toNative(value);
-					fieldData->value = static_resource_cast<ScriptMaterial>(scriptMaterial->getNativeHandle());
+					fieldData->value = static_resource_cast<Material>(scriptMaterial->getNativeHandle());
 				}
 
 				return fieldData;
@@ -239,7 +240,19 @@ namespace BansheeEngine
 				if (value != nullptr)
 				{
 					ScriptMesh* scriptMesh = ScriptMesh::toNative(value);
-					fieldData->value = static_resource_cast<ScriptMesh>(scriptMesh->getNativeHandle());
+					fieldData->value = static_resource_cast<Mesh>(scriptMesh->getNativeHandle());
+				}
+
+				return fieldData;
+			}
+			case ScriptPrimitiveType::PrefabRef:
+			{
+				auto fieldData = bs_shared_ptr<ManagedSerializableFieldDataResourceRef>();
+
+				if (value != nullptr)
+				{
+					ScriptPrefab* scriptPrefab = ScriptPrefab::toNative(value);
+					fieldData->value = static_resource_cast<Prefab>(scriptPrefab->getNativeHandle());
 				}
 
 				return fieldData;
@@ -646,6 +659,21 @@ namespace BansheeEngine
 				else
 					return nullptr;
 			}
+			else if (primitiveTypeInfo->mType == ScriptPrimitiveType::PrefabRef)
+			{
+				if (value)
+				{
+					HPrefab prefab = static_resource_cast<Prefab>(value);
+					ScriptPrefab* scriptResource = ScriptResourceManager::instance().getScriptPrefab(prefab);
+					if (scriptResource == nullptr)
+						scriptResource = ScriptResourceManager::instance().createScriptPrefab(prefab);
+
+					if (scriptResource != nullptr)
+						return scriptResource->getManagedInstance();
+				}
+				else
+					return nullptr;
+			}
 			else if (primitiveTypeInfo->mType == ScriptPrimitiveType::ManagedResourceRef)
 			{
 				if (value)

+ 2 - 0
SBansheeEngine/Source/BsManagedSerializableObjectInfo.cpp

@@ -167,6 +167,8 @@ namespace BansheeEngine
 			return ScriptAssemblyManager::instance().getPlainTextClass()->_getInternalClass();
 		case ScriptPrimitiveType::ScriptCodeRef:
 			return ScriptAssemblyManager::instance().getScriptCodeClass()->_getInternalClass();
+		case ScriptPrimitiveType::PrefabRef:
+			return ScriptAssemblyManager::instance().getPrefabClass()->_getInternalClass();
 		case ScriptPrimitiveType::SceneObjectRef:
 			return ScriptAssemblyManager::instance().getSceneObjectClass()->_getInternalClass();
 		case ScriptPrimitiveType::ComponentRef:

+ 12 - 1
SBansheeEngine/Source/BsScriptAssemblyManager.cpp

@@ -19,7 +19,7 @@ namespace BansheeEngine
 		mSerializeFieldAttribute(nullptr), mHideInInspectorAttribute(nullptr), mSystemArrayClass(nullptr), mSystemGenericListClass(nullptr),
 		mSystemGenericDictionaryClass(nullptr), mManagedResourceClass(nullptr), mFontClass(nullptr), mMissingComponentClass(nullptr),
 		mPlainTextClass(nullptr), mScriptCodeClass(nullptr), mShaderClass(nullptr), mMaterialClass(nullptr), mTexture3DClass(nullptr),
-		mTextureCubeClass(nullptr), mMeshClass(nullptr)
+		mTextureCubeClass(nullptr), mMeshClass(nullptr), mPrefabClass(nullptr)
 	{
 
 	}
@@ -319,6 +319,12 @@ namespace BansheeEngine
 				typeInfo->mType = ScriptPrimitiveType::ScriptCodeRef;
 				return typeInfo;
 			}
+			else if (monoClass->isSubClassOf(mPrefabClass))
+			{
+				std::shared_ptr<ManagedSerializableTypeInfoPrimitive> typeInfo = bs_shared_ptr<ManagedSerializableTypeInfoPrimitive>();
+				typeInfo->mType = ScriptPrimitiveType::PrefabRef;
+				return typeInfo;
+			}
 			else if(monoClass->isSubClassOf(mSceneObjectClass))
 			{
 				std::shared_ptr<ManagedSerializableTypeInfoPrimitive> typeInfo = bs_shared_ptr<ManagedSerializableTypeInfoPrimitive>();
@@ -429,6 +435,7 @@ namespace BansheeEngine
 		mShaderClass = nullptr;
 		mMaterialClass = nullptr;
 		mMeshClass = nullptr;
+		mPrefabClass = nullptr;
 		mFontClass = nullptr;
 		mPlainTextClass = nullptr;
 		mScriptCodeClass = nullptr;
@@ -516,6 +523,10 @@ namespace BansheeEngine
 		if (mFontClass == nullptr)
 			BS_EXCEPT(InvalidStateException, "Cannot find Font managed class.");
 
+		mPrefabClass = bansheeEngineAssembly->getClass("BansheeEngine", "Prefab");
+		if (mPrefabClass == nullptr)
+			BS_EXCEPT(InvalidStateException, "Cannot find Prefab managed class.");
+
 		mPlainTextClass = bansheeEngineAssembly->getClass("BansheeEngine", "PlainText");
 		if (mPlainTextClass == nullptr)
 			BS_EXCEPT(InvalidStateException, "Cannot find PlainText managed class.");

+ 65 - 0
SBansheeEngine/Source/BsScriptPrefab.cpp

@@ -0,0 +1,65 @@
+#include "BsScriptPrefab.h"
+#include "BsScriptResourceManager.h"
+#include "BsScriptGameObjectManager.h"
+#include "BsScriptMeta.h"
+#include "BsMonoField.h"
+#include "BsMonoClass.h"
+#include "BsMonoArray.h"
+#include "BsMonoManager.h"
+#include "BsScriptSceneObject.h"
+
+namespace BansheeEngine
+{
+	ScriptPrefab::ScriptPrefab(MonoObject* instance, const HPrefab& prefab)
+		:ScriptObject(instance), mPrefab(prefab)
+	{
+
+	}
+
+	void ScriptPrefab::initRuntimeData()
+	{
+		metaData.scriptClass->addInternalCall("Internal_CreateInstance", &ScriptPrefab::internal_CreateInstance);
+		metaData.scriptClass->addInternalCall("Internal_GetRoot", &ScriptPrefab::internal_GetRoot);
+		metaData.scriptClass->addInternalCall("Internal_Instantiate", &ScriptPrefab::internal_Instantiate);
+	}
+
+	void ScriptPrefab::internal_CreateInstance(MonoObject* instance, ScriptSceneObject* so)
+	{
+		HPrefab prefab = Prefab::create(so->getNativeSceneObject());
+
+		ScriptResourceManager::instance().createScriptPrefab(instance, prefab);
+	}
+
+	MonoObject* ScriptPrefab::internal_GetRoot(ScriptPrefab* thisPtr)
+	{
+		HPrefab prefab = thisPtr->getPrefabHandle();
+
+		HSceneObject instance = prefab->getRoot();
+		ScriptSceneObject* scriptInstance = ScriptGameObjectManager::instance().getOrCreateScriptSceneObject(instance);
+
+		return scriptInstance->getManagedInstance();
+	}
+
+	MonoObject* ScriptPrefab::internal_Instantiate(ScriptPrefab* thisPtr)
+	{
+		HPrefab prefab = thisPtr->getPrefabHandle();
+
+		HSceneObject instance = prefab->instantiate();
+		ScriptSceneObject* scriptInstance = ScriptGameObjectManager::instance().getOrCreateScriptSceneObject(instance);
+
+		return scriptInstance->getManagedInstance();
+	}
+		
+	void ScriptPrefab::_onManagedInstanceDeleted()
+	{
+		mManagedInstance = nullptr;
+
+		if (!mRefreshInProgress)
+			ScriptResourceManager::instance().destroyScriptResource(this);
+	}
+
+	void ScriptPrefab::setNativeHandle(const HResource& resource)
+	{
+		mPrefab = static_resource_cast<Prefab>(resource);
+	}
+}

+ 27 - 0
SBansheeEngine/Source/BsScriptResourceManager.cpp

@@ -12,6 +12,7 @@
 #include "BsScriptMaterial.h"
 #include "BsScriptMesh.h"
 #include "BsScriptFont.h"
+#include "BsScriptPrefab.h"
 #include "BsScriptManagedResource.h"
 #include "BsScriptAssemblyManager.h"
 
@@ -231,6 +232,27 @@ namespace BansheeEngine
 		return scriptResource;
 	}
 
+	ScriptPrefab* ScriptResourceManager::createScriptPrefab(const HPrefab& resourceHandle)
+	{
+		MonoClass* prefabClass = ScriptAssemblyManager::instance().getPrefabClass();
+		MonoObject* monoInstance = prefabClass->createInstance();
+
+		return createScriptPrefab(monoInstance, resourceHandle);
+	}
+
+	ScriptPrefab* ScriptResourceManager::createScriptPrefab(MonoObject* instance, const HPrefab& resourceHandle)
+	{
+		const String& uuid = resourceHandle.getUUID();
+#if BS_DEBUG_MODE
+		throwExceptionIfInvalidOrDuplicate(uuid);
+#endif
+
+		ScriptPrefab* scriptResource = new (bs_alloc<ScriptPrefab>()) ScriptPrefab(instance, resourceHandle);
+		mScriptResources[uuid] = scriptResource;
+
+		return scriptResource;
+	}
+
 	ScriptManagedResource* ScriptResourceManager::createManagedResource(MonoObject* existingInstance, const HManagedResource& resourceHandle)
 	{
 		const String& uuid = resourceHandle.getUUID();
@@ -292,6 +314,11 @@ namespace BansheeEngine
 		return static_cast<ScriptManagedResource*>(getScriptResource(resourceHandle.getUUID()));
 	}
 
+	ScriptPrefab* ScriptResourceManager::getScriptPrefab(const HPrefab& resourceHandle)
+	{
+		return static_cast<ScriptPrefab*>(getScriptResource(resourceHandle.getUUID()));
+	}
+
 	ScriptResourceBase* ScriptResourceManager::getScriptResource(const String& uuid)
 	{
 		if(uuid == "")

+ 53 - 0
SBansheeEngine/Source/BsScriptSceneObject.cpp

@@ -1,11 +1,15 @@
 #include "BsScriptSceneObject.h"
 #include "BsScriptGameObjectManager.h"
+#include "BsScriptResourceManager.h"
 #include "BsScriptMeta.h"
 #include "BsMonoField.h"
 #include "BsMonoClass.h"
 #include "BsMonoManager.h"
 #include "BsSceneObject.h"
 #include "BsMonoUtil.h"
+#include "BsScriptPrefab.h"
+#include "BsPrefab.h"
+#include "BsPrefabUtility.h"
 
 namespace BansheeEngine
 {
@@ -23,6 +27,11 @@ namespace BansheeEngine
 		metaData.scriptClass->addInternalCall("Internal_GetNumChildren", &ScriptSceneObject::internal_getNumChildren);
 		metaData.scriptClass->addInternalCall("Internal_GetChild", &ScriptSceneObject::internal_getChild);
 
+		metaData.scriptClass->addInternalCall("Internal_GetPrefab", &ScriptSceneObject::internal_getPrefab);
+		metaData.scriptClass->addInternalCall("Internal_BreakPrefab", &ScriptSceneObject::internal_breakPrefab);
+		metaData.scriptClass->addInternalCall("Internal_ApplyPrefab", &ScriptSceneObject::internal_applyPrefab);
+		metaData.scriptClass->addInternalCall("Internal_RevertPrefab", &ScriptSceneObject::internal_revertPrefab);
+
 		metaData.scriptClass->addInternalCall("Internal_GetPosition", &ScriptSceneObject::internal_getPosition);
 		metaData.scriptClass->addInternalCall("Internal_GetLocalPosition", &ScriptSceneObject::internal_getLocalPosition);
 		metaData.scriptClass->addInternalCall("Internal_GetRotation", &ScriptSceneObject::internal_getRotation);
@@ -113,6 +122,50 @@ namespace BansheeEngine
 		return childScriptSO->getManagedInstance();
 	}
 
+	MonoObject* ScriptSceneObject::internal_getPrefab(ScriptSceneObject* nativeInstance)
+	{
+		if (checkIfDestroyed(nativeInstance))
+			return nullptr;
+
+		HPrefab prefab = nativeInstance->mSceneObject->getPrefabLink();
+		if (prefab != nullptr)
+		{
+			ScriptPrefab* scriptPrefab = ScriptResourceManager::instance().getScriptPrefab(prefab);
+			if (scriptPrefab == nullptr)
+				scriptPrefab = ScriptResourceManager::instance().createScriptPrefab(prefab);
+
+			return scriptPrefab->getManagedInstance();
+		}
+
+		return nullptr;
+	}
+
+	void ScriptSceneObject::internal_breakPrefab(ScriptSceneObject* nativeInstance)
+	{
+		if (checkIfDestroyed(nativeInstance))
+			return;
+
+		nativeInstance->mSceneObject->breakPrefabLink();
+	}
+
+	void ScriptSceneObject::internal_applyPrefab(ScriptSceneObject* nativeInstance)
+	{
+		if (checkIfDestroyed(nativeInstance))
+			return;
+
+		HPrefab prefab = nativeInstance->mSceneObject->getPrefabLink();
+		if (prefab != nullptr)
+			prefab->update(nativeInstance->mSceneObject);
+	}
+
+	void ScriptSceneObject::internal_revertPrefab(ScriptSceneObject* nativeInstance)
+	{
+		if (checkIfDestroyed(nativeInstance))
+			return;
+
+		PrefabUtility::revertToPrefab(nativeInstance->mSceneObject);
+	}
+
 	void ScriptSceneObject::internal_getPosition(ScriptSceneObject* nativeInstance, Vector3* value)
 	{
 		if (!checkIfDestroyed(nativeInstance))

+ 9 - 5
TODO.txt

@@ -36,11 +36,15 @@ TODO:
 TODO - Whenever I load a SceneObject the entire prefab will be loaded as well. It might be better to store the
  prefab link as a UUID and then load it on demand.
 
-Later: Test game object handle compare, and ID restore systems (likely later once I have more editor functionality working)
-Later: Native+Managed diff is not tested (only the link needs to be tested, I have a separate managed and native tests)
-Later: Modify BinarySerializer so that _encodeIntermediate outputs intermediate format directly without a full on encode
-Later: Consider making ManagedSerializable* array/list/dictionary method/field references static (right now each instance has its own instance
- but they're identical)
+ Test (likely later once I have more editor functionality working):
+  - Game object handle compare
+  - ID restore systems 
+  - Native+Managed diff (only the link between the two)
+
+Code quality improvements:
+ - Modify BinarySerializer so that _encodeIntermediate outputs intermediate format directly without a full on encode
+ - Consider making ManagedSerializable* array/list/dictionary method/field references static (right now each instance has its own instance
+   but they're identical)
 
 ----------------------------------------------------------------------
 Polish stage 1