Explorar el Código

Fixed crash that occurred when deleting a light from the scene
Fixed a couple of objects that weren't properly checking if a resource was loaded before use

BearishSun hace 10 años
padre
commit
fdb3896efc

+ 138 - 138
BansheeEditor/Source/BsSelectionRenderer.cpp

@@ -1,139 +1,139 @@
-#include "BsSelectionRenderer.h"
-#include "BsMesh.h"
-#include "BsVertexDataDesc.h"
-#include "BsCCamera.h"
-#include "BsCoreThread.h"
-#include "BsBuiltinEditorResources.h"
-#include "BsMaterial.h"
-#include "BsGpuParams.h"
-#include "BsRenderAPI.h"
-#include "BsCoreRenderer.h"
-#include "BsRendererManager.h"
-#include "BsSelection.h"
-#include "BsSceneObject.h"
-#include "BsCRenderable.h"
-#include "BsRenderable.h"
-#include "BsSceneManager.h"
-#include "BsRendererUtility.h"
-
-using namespace std::placeholders;
-
-namespace BansheeEngine
-{
-	SelectionRenderer::SelectionRenderer()
-		:mCore(nullptr)
-	{
-		HMaterial selectionMat = BuiltinEditorResources::instance().createSelectionMat();
-			
-		mCore.store(bs_new<SelectionRendererCore>(SelectionRendererCore::PrivatelyConstuct()), std::memory_order_release);
-
-		gCoreAccessor().queueCommand(std::bind(&SelectionRenderer::initializeCore, this, selectionMat->getCore()));
-	}
-
-	SelectionRenderer::~SelectionRenderer()
-	{
-		gCoreAccessor().queueCommand(std::bind(&SelectionRenderer::destroyCore, this, mCore.load(std::memory_order_relaxed)));
-	}
-
-	void SelectionRenderer::initializeCore(const SPtr<MaterialCore>& initData)
-	{
-		mCore.load(std::memory_order_acquire)->initialize(initData);
-	}
-
-	void SelectionRenderer::destroyCore(SelectionRendererCore* core)
-	{
-		bs_delete(core);
-	}
-
-	void SelectionRenderer::update(const CameraPtr& camera)
-	{
-		Vector<ObjectData> objects;
-
-		const Vector<HSceneObject>& sceneObjects = Selection::instance().getSceneObjects();
-		const Map<Renderable*, SceneRenderableData>& renderables = SceneManager::instance().getAllRenderables();
-
-		for (auto& renderable : renderables)
-		{
-			for (auto& so : sceneObjects)
-			{
-				if (renderable.second.sceneObject != so)
-					continue;
-
-				if (renderable.first->getMesh() != nullptr)
-				{
-					objects.push_back(ObjectData());
-
-					ObjectData& newObjData = objects.back();
-					newObjData.worldTfrm = so->getWorldTfrm();
-					newObjData.mesh = renderable.first->getMesh()->getCore();
-				}
-			}
-		}
-
-		SelectionRendererCore* core = mCore.load(std::memory_order_relaxed);
-		gCoreAccessor().queueCommand(std::bind(&SelectionRendererCore::updateData, core, camera->getCore(), objects));
-	}
-
-	const Color SelectionRendererCore::SELECTION_COLOR = Color(1.0f, 1.0f, 1.0f, 0.3f);
-
-	SelectionRendererCore::SelectionRendererCore(const PrivatelyConstuct& dummy)
-	{
-	}
-
-	SelectionRendererCore::~SelectionRendererCore()
-	{
-		CoreRendererPtr activeRenderer = RendererManager::instance().getActive();
-		if (mCamera != nullptr)
-			activeRenderer->_unregisterRenderCallback(mCamera.get(), 10);
-	}
-
-	void SelectionRendererCore::initialize(const SPtr<MaterialCore>& mat)
-	{
-		THROW_IF_NOT_CORE_THREAD;
-
-		mMaterial = mat;
-
-		SPtr<GpuParamsCore> vertParams = mat->getPassParameters(0)->mVertParams;
-		vertParams->getParam("matWorldViewProj", mMatWorldViewProj);
-
-		SPtr<GpuParamsCore> fragParams = mat->getPassParameters(0)->mFragParams;
-		fragParams->getParam("selColor", mColor);
-	}
-
-	void SelectionRendererCore::updateData(const SPtr<CameraCore>& camera, const Vector<SelectionRenderer::ObjectData>& objects)
-	{
-		if (mCamera != camera)
-		{
-			CoreRendererPtr activeRenderer = RendererManager::instance().getActive();
-			if (mCamera != nullptr)
-				activeRenderer->_unregisterRenderCallback(mCamera.get(), 10);
-
-			if (camera != nullptr)
-				activeRenderer->_registerRenderCallback(camera.get(), 10, std::bind(&SelectionRendererCore::render, this));
-		}
-
-		mCamera = camera;
-		mObjects = objects;
-	}
-
-	void SelectionRendererCore::render()
-	{
-		THROW_IF_NOT_CORE_THREAD;
-
-		if (mCamera == nullptr)
-			return;
-
-		Matrix4 viewProjMat = mCamera->getProjectionMatrixRS() * mCamera->getViewMatrix();
-
-		for (auto& objData : mObjects)
-		{
-			Matrix4 worldViewProjMat = viewProjMat * objData.worldTfrm;
-
-			mMatWorldViewProj.set(worldViewProjMat);
-			mColor.set(SELECTION_COLOR);
-
-			gRendererUtility().setPass(mMaterial, 0);
-			gRendererUtility().draw(objData.mesh, objData.mesh->getProperties().getSubMesh(0));
-		}
-	}
+#include "BsSelectionRenderer.h"
+#include "BsMesh.h"
+#include "BsVertexDataDesc.h"
+#include "BsCCamera.h"
+#include "BsCoreThread.h"
+#include "BsBuiltinEditorResources.h"
+#include "BsMaterial.h"
+#include "BsGpuParams.h"
+#include "BsRenderAPI.h"
+#include "BsCoreRenderer.h"
+#include "BsRendererManager.h"
+#include "BsSelection.h"
+#include "BsSceneObject.h"
+#include "BsCRenderable.h"
+#include "BsRenderable.h"
+#include "BsSceneManager.h"
+#include "BsRendererUtility.h"
+
+using namespace std::placeholders;
+
+namespace BansheeEngine
+{
+	SelectionRenderer::SelectionRenderer()
+		:mCore(nullptr)
+	{
+		HMaterial selectionMat = BuiltinEditorResources::instance().createSelectionMat();
+			
+		mCore.store(bs_new<SelectionRendererCore>(SelectionRendererCore::PrivatelyConstuct()), std::memory_order_release);
+
+		gCoreAccessor().queueCommand(std::bind(&SelectionRenderer::initializeCore, this, selectionMat->getCore()));
+	}
+
+	SelectionRenderer::~SelectionRenderer()
+	{
+		gCoreAccessor().queueCommand(std::bind(&SelectionRenderer::destroyCore, this, mCore.load(std::memory_order_relaxed)));
+	}
+
+	void SelectionRenderer::initializeCore(const SPtr<MaterialCore>& initData)
+	{
+		mCore.load(std::memory_order_acquire)->initialize(initData);
+	}
+
+	void SelectionRenderer::destroyCore(SelectionRendererCore* core)
+	{
+		bs_delete(core);
+	}
+
+	void SelectionRenderer::update(const CameraPtr& camera)
+	{
+		Vector<ObjectData> objects;
+
+		const Vector<HSceneObject>& sceneObjects = Selection::instance().getSceneObjects();
+		const Map<Renderable*, SceneRenderableData>& renderables = SceneManager::instance().getAllRenderables();
+
+		for (auto& renderable : renderables)
+		{
+			for (auto& so : sceneObjects)
+			{
+				if (renderable.second.sceneObject != so)
+					continue;
+
+				if (renderable.first->getMesh().isLoaded())
+				{
+					objects.push_back(ObjectData());
+
+					ObjectData& newObjData = objects.back();
+					newObjData.worldTfrm = so->getWorldTfrm();
+					newObjData.mesh = renderable.first->getMesh()->getCore();
+				}
+			}
+		}
+
+		SelectionRendererCore* core = mCore.load(std::memory_order_relaxed);
+		gCoreAccessor().queueCommand(std::bind(&SelectionRendererCore::updateData, core, camera->getCore(), objects));
+	}
+
+	const Color SelectionRendererCore::SELECTION_COLOR = Color(1.0f, 1.0f, 1.0f, 0.3f);
+
+	SelectionRendererCore::SelectionRendererCore(const PrivatelyConstuct& dummy)
+	{
+	}
+
+	SelectionRendererCore::~SelectionRendererCore()
+	{
+		CoreRendererPtr activeRenderer = RendererManager::instance().getActive();
+		if (mCamera != nullptr)
+			activeRenderer->_unregisterRenderCallback(mCamera.get(), 10);
+	}
+
+	void SelectionRendererCore::initialize(const SPtr<MaterialCore>& mat)
+	{
+		THROW_IF_NOT_CORE_THREAD;
+
+		mMaterial = mat;
+
+		SPtr<GpuParamsCore> vertParams = mat->getPassParameters(0)->mVertParams;
+		vertParams->getParam("matWorldViewProj", mMatWorldViewProj);
+
+		SPtr<GpuParamsCore> fragParams = mat->getPassParameters(0)->mFragParams;
+		fragParams->getParam("selColor", mColor);
+	}
+
+	void SelectionRendererCore::updateData(const SPtr<CameraCore>& camera, const Vector<SelectionRenderer::ObjectData>& objects)
+	{
+		if (mCamera != camera)
+		{
+			CoreRendererPtr activeRenderer = RendererManager::instance().getActive();
+			if (mCamera != nullptr)
+				activeRenderer->_unregisterRenderCallback(mCamera.get(), 10);
+
+			if (camera != nullptr)
+				activeRenderer->_registerRenderCallback(camera.get(), 10, std::bind(&SelectionRendererCore::render, this));
+		}
+
+		mCamera = camera;
+		mObjects = objects;
+	}
+
+	void SelectionRendererCore::render()
+	{
+		THROW_IF_NOT_CORE_THREAD;
+
+		if (mCamera == nullptr)
+			return;
+
+		Matrix4 viewProjMat = mCamera->getProjectionMatrixRS() * mCamera->getViewMatrix();
+
+		for (auto& objData : mObjects)
+		{
+			Matrix4 worldViewProjMat = viewProjMat * objData.worldTfrm;
+
+			mMatWorldViewProj.set(worldViewProjMat);
+			mColor.set(SELECTION_COLOR);
+
+			gRendererUtility().setPass(mMaterial, 0);
+			gRendererUtility().draw(objData.mesh, objData.mesh->getProperties().getSubMesh(0));
+		}
+	}
 }

+ 86 - 86
BansheeUtility/Include/BsCrashHandler.h

@@ -1,87 +1,87 @@
-#pragma once
-
-#define BS_MAX_STACKTRACE_DEPTH 200
-#define BS_MAX_STACKTRACE_NAME_BYTES 1024
-
-namespace BansheeEngine
-{
-	/**
-	 * @brief	Saves crash data and notifies the user when a crash occurs.
-	 */
-	// TODO - Crashes are reported in the same process as the main application. This can be a problem if the crash was caused
-	// by heap. Any further use of the heap by the reporting methods will cause a silent crash, failing to log it. A more appropriate
-	// way of doing it should be to resume another process to actually handle the crash.
-	class BS_UTILITY_EXPORT CrashHandler
-	{
-	public:
-		CrashHandler();
-		~CrashHandler();
-
-		/**
-		 * @brief	Constructs and starts the module.
-		 */
-		static void startUp() { _instance() = bs_new<CrashHandler>(); }
-
-		/**
-		 * @brief	Shuts down this module and frees any resources it is using.
-		 */
-		static void shutDown() { bs_delete(_instance()); }
-
-		/**
-		 * @brief	Returns a reference to the module instance.
-		 */
-		static CrashHandler& instance() { return *_instance(); }
-
-		/**
-		 * @brief	Records a crash with a custom error message.
-		 * 			
-		 * @param	type		Type of the crash that occurred. e.g. "InvalidParameter".
-		 * @param	description	More detailed description of the issue that caused the crash.
-		 * @param	function	Optional name of the function where the error occurred.
-		 * @param	file		Optional name of the source code file in which the code that crashed the program exists.
-		 * @param	line		Optional source code line at which the crash was triggered at.
-		 */
-		void reportCrash(const String& type, const String& description, const String& function = StringUtil::BLANK,
-			const String& file = StringUtil::BLANK, UINT32 line = 0);
-
-#if BS_PLATFORM == BS_PLATFORM_WIN32
-		/**
-		 * @brief	Records a crash resulting from a Windows-specific SEH exception. 
-		 * 			
-		 * @param	exceptionData	Exception data returned from GetExceptionInformation()
-		 * 							
-		 * @returns	Code that signals the __except exception handler on how to proceed.
-		 */
-		int reportCrash(void* exceptionData);
-#endif
-
-		/**
-		 * @brief	Returns a string containing a current stack trace. If function can be found in the symbol
-		 * 			table its readable name will be present in the stack trace, otherwise just its address.
-		 * 						
-		 * @returns	String containing the call stack with each function on its own line.
-		 */
-		String getStackTrace();
-	private:
-		/**
-		 * @brief	Returns path to the folder into which to store the crash reports.
-		 */
-		Path getCrashFolder();
-
-		/**
-		 * @brief	Returns a singleton instance of this module. 
-		 */
-		static CrashHandler*& _instance() { static CrashHandler* inst = nullptr; return inst; }
-
-		static const wchar_t* CrashReportFolder;
-		static const wchar_t* CrashLogName;
-
-		struct Data;
-		Data* m;
-	};
-
-	/**
-	 * @brief	Returns an instance of the CrashHandler.
-	 */
-	BS_UTILITY_EXPORT CrashHandler& gCrashHandler();
+#pragma once
+
+#define BS_MAX_STACKTRACE_DEPTH 200
+#define BS_MAX_STACKTRACE_NAME_BYTES 1024
+
+namespace BansheeEngine
+{
+	/**
+	 * @brief	Saves crash data and notifies the user when a crash occurs.
+	 */
+	// TODO - Crashes are reported in the same process as the main application. This can be a problem if the crash was caused
+	// by heap. Any further use of the heap by the reporting methods will cause a silent crash, failing to log it. A more appropriate
+	// way of doing it should be to resume another process to actually handle the crash.
+	class BS_UTILITY_EXPORT CrashHandler
+	{
+	public:
+		CrashHandler();
+		~CrashHandler();
+
+		/**
+		 * @brief	Constructs and starts the module.
+		 */
+		static void startUp() { _instance() = bs_new<CrashHandler>(); }
+
+		/**
+		 * @brief	Shuts down this module and frees any resources it is using.
+		 */
+		static void shutDown() { bs_delete(_instance()); }
+
+		/**
+		 * @brief	Returns a reference to the module instance.
+		 */
+		static CrashHandler& instance() { return *_instance(); }
+
+		/**
+		 * @brief	Records a crash with a custom error message.
+		 * 			
+		 * @param	type		Type of the crash that occurred. e.g. "InvalidParameter".
+		 * @param	description	More detailed description of the issue that caused the crash.
+		 * @param	function	Optional name of the function where the error occurred.
+		 * @param	file		Optional name of the source code file in which the code that crashed the program exists.
+		 * @param	line		Optional source code line at which the crash was triggered at.
+		 */
+		void reportCrash(const String& type, const String& description, const String& function = StringUtil::BLANK,
+			const String& file = StringUtil::BLANK, UINT32 line = 0) const;
+
+#if BS_PLATFORM == BS_PLATFORM_WIN32
+		/**
+		 * @brief	Records a crash resulting from a Windows-specific SEH exception. 
+		 * 			
+		 * @param	exceptionData	Exception data returned from GetExceptionInformation()
+		 * 							
+		 * @returns	Code that signals the __except exception handler on how to proceed.
+		 */
+		int reportCrash(void* exceptionData) const;
+#endif
+
+		/**
+		 * @brief	Returns a string containing a current stack trace. If function can be found in the symbol
+		 * 			table its readable name will be present in the stack trace, otherwise just its address.
+		 * 						
+		 * @returns	String containing the call stack with each function on its own line.
+		 */
+		static String getStackTrace();
+	private:
+		/**
+		 * @brief	Returns path to the folder into which to store the crash reports.
+		 */
+		Path getCrashFolder() const;
+
+		/**
+		 * @brief	Returns a singleton instance of this module. 
+		 */
+		static CrashHandler*& _instance() { static CrashHandler* inst = nullptr; return inst; }
+
+		static const wchar_t* CrashReportFolder;
+		static const wchar_t* CrashLogName;
+
+		struct Data;
+		Data* m;
+	};
+
+	/**
+	 * @brief	Returns an instance of the CrashHandler.
+	 */
+	BS_UTILITY_EXPORT CrashHandler& gCrashHandler();
 }

+ 3 - 3
BansheeUtility/Source/Win32/BsWin32CrashHandler.cpp

@@ -460,7 +460,7 @@ namespace BansheeEngine
 	}
 
 	void CrashHandler::reportCrash(const String& type, const String& description, const String& function,
-		const String& file, UINT32 line)
+		const String& file, UINT32 line) const
 	{
 		// Win32 debug methods are not thread safe
 		Lock<>(m->mutex);
@@ -492,7 +492,7 @@ namespace BansheeEngine
 		// Note: Potentially also log Windows Error Report and/or send crash data to server
 	}
 
-	int CrashHandler::reportCrash(void* exceptionDataPtr)
+	int CrashHandler::reportCrash(void* exceptionDataPtr) const
 	{
 		EXCEPTION_POINTERS* exceptionData = (EXCEPTION_POINTERS*)exceptionDataPtr;
 
@@ -529,7 +529,7 @@ namespace BansheeEngine
 		return EXCEPTION_EXECUTE_HANDLER;
 	}
 
-	Path CrashHandler::getCrashFolder()
+	Path CrashHandler::getCrashFolder() const
 	{
 		SYSTEMTIME systemTime;
 		GetLocalTime(&systemTime);

+ 139 - 129
MBansheeEngine/NativeLight.cs

@@ -1,129 +1,139 @@
-using System;
-using System.Collections.Generic;
-using System.Linq;
-using System.Runtime.CompilerServices;
-using System.Text;
-
-namespace BansheeEngine
-{
-    /// <summary>
-    /// Light type that determines how is light information parsed by the renderer and other systems.
-    /// </summary>
-    public enum LightType // Note: Must match C++ enum LightType
-    {
-        Directional, Point, Spot
-    }
-
-    /// <summary>
-    /// Wrapper around the native Light class.
-    /// <see cref="Light"/>
-    /// </summary>
-    internal class NativeLight : ScriptObject
-    {
-        internal LightType Type
-        {
-            get { return Internal_GetType(mCachedPtr); }
-            set { Internal_SetType(mCachedPtr, value); }
-        }
-
-        internal Color Color
-        {
-            get { return Internal_GetColor(mCachedPtr); }
-            set { Internal_SetColor(mCachedPtr, value); }
-        }
-
-        internal float Range
-        {
-            get { return Internal_GetRange(mCachedPtr); }
-            set { Internal_SetRange(mCachedPtr, value); }
-        }
-
-        internal float Intensity
-        {
-            get { return Internal_GetIntensity(mCachedPtr); }
-            set { Internal_SetIntensity(mCachedPtr, value); }
-        }
-
-        internal Degree SpotAngle
-        {
-            get { return Internal_GetSpotAngle(mCachedPtr); }
-            set { Internal_SetSpotAngle(mCachedPtr, value.Degrees); }
-        }
-
-        internal Degree SpotFalloffAngle
-        {
-            get { return Internal_GetSpotFalloffAngle(mCachedPtr); }
-            set { Internal_SetSpotFalloffAngle(mCachedPtr, value.Degrees); }
-        }
-
-        internal bool CastsShadow
-        {
-            get { return Internal_GetCastsShadow(mCachedPtr); }
-            set { Internal_SetCastsShadow(mCachedPtr, value); }
-        }
-
-        internal Sphere Bounds
-        {
-            get { return Internal_GetBounds(mCachedPtr); }
-        }
-
-        internal NativeLight(SceneObject sceneObject)
-        {
-            IntPtr sceneObjPtr = IntPtr.Zero;
-            if (sceneObject != null)
-                sceneObjPtr = sceneObject.GetCachedPtr();
-
-            Internal_Create(this, sceneObjPtr);
-        }
-
-        internal void UpdateTransform(SceneObject parentSO)
-        {
-            if (parentSO != null)
-                Internal_UpdateTransform(mCachedPtr, parentSO.GetCachedPtr());
-        }
-
-        internal void OnDestroy()
-        {
-            Internal_OnDestroy(mCachedPtr);
-        }
-
-        [MethodImpl(MethodImplOptions.InternalCall)]
-        private static extern void Internal_Create(NativeLight instance, IntPtr parentSO);
-
-        [MethodImpl(MethodImplOptions.InternalCall)]
-        private static extern LightType Internal_GetType(IntPtr instance);
-        [MethodImpl(MethodImplOptions.InternalCall)]
-        private static extern void Internal_SetType(IntPtr instance, LightType value);
-        [MethodImpl(MethodImplOptions.InternalCall)]
-        private static extern float Internal_GetRange(IntPtr instance);
-        [MethodImpl(MethodImplOptions.InternalCall)]
-        private static extern void Internal_SetRange(IntPtr instance, float value);
-        [MethodImpl(MethodImplOptions.InternalCall)]
-        private static extern float Internal_GetIntensity(IntPtr instance);
-        [MethodImpl(MethodImplOptions.InternalCall)]
-        private static extern void Internal_SetIntensity(IntPtr instance, float value);
-        [MethodImpl(MethodImplOptions.InternalCall)]
-        private static extern Color Internal_GetColor(IntPtr instance);
-        [MethodImpl(MethodImplOptions.InternalCall)]
-        private static extern void Internal_SetColor(IntPtr instance, Color value);
-        [MethodImpl(MethodImplOptions.InternalCall)]
-        private static extern bool Internal_GetCastsShadow(IntPtr instance);
-        [MethodImpl(MethodImplOptions.InternalCall)]
-        private static extern void Internal_SetCastsShadow(IntPtr instance, bool value);
-        [MethodImpl(MethodImplOptions.InternalCall)]
-        private static extern float Internal_GetSpotAngle(IntPtr instance);
-        [MethodImpl(MethodImplOptions.InternalCall)]
-        private static extern void Internal_SetSpotAngle(IntPtr instance, float value);
-        [MethodImpl(MethodImplOptions.InternalCall)]
-        private static extern float Internal_GetSpotFalloffAngle(IntPtr instance);
-        [MethodImpl(MethodImplOptions.InternalCall)]
-        private static extern void Internal_SetSpotFalloffAngle(IntPtr instance, float value);
-        [MethodImpl(MethodImplOptions.InternalCall)]
-        private static extern Sphere Internal_GetBounds(IntPtr instance);
-
-        [MethodImpl(MethodImplOptions.InternalCall)]
-        private static extern void Internal_UpdateTransform(IntPtr instance, IntPtr parentSO);
-        [MethodImpl(MethodImplOptions.InternalCall)]
-        private static extern void Internal_OnDestroy(IntPtr thisPtr);
-    }
-}
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Runtime.CompilerServices;
+using System.Text;
+
+namespace BansheeEngine
+{
+    /// <summary>
+    /// Light type that determines how is light information parsed by the renderer and other systems.
+    /// </summary>
+    public enum LightType // Note: Must match C++ enum LightType
+    {
+        Directional, Point, Spot
+    }
+
+    /// <summary>
+    /// Wrapper around the native Light class.
+    /// <see cref="Light"/>
+    /// </summary>
+    internal class NativeLight : ScriptObject
+    {
+        internal LightType Type
+        {
+            get { return Internal_GetType(mCachedPtr); }
+            set { Internal_SetType(mCachedPtr, value); }
+        }
+
+        internal Color Color
+        {
+            get
+            {
+                Color color;
+                Internal_GetColor(mCachedPtr, out color);
+                return color;
+            }
+            set { Internal_SetColor(mCachedPtr, value); }
+        }
+
+        internal float Range
+        {
+            get { return Internal_GetRange(mCachedPtr); }
+            set { Internal_SetRange(mCachedPtr, value); }
+        }
+
+        internal float Intensity
+        {
+            get { return Internal_GetIntensity(mCachedPtr); }
+            set { Internal_SetIntensity(mCachedPtr, value); }
+        }
+
+        internal Degree SpotAngle
+        {
+            get { return Internal_GetSpotAngle(mCachedPtr); }
+            set { Internal_SetSpotAngle(mCachedPtr, value.Degrees); }
+        }
+
+        internal Degree SpotFalloffAngle
+        {
+            get { return Internal_GetSpotFalloffAngle(mCachedPtr); }
+            set { Internal_SetSpotFalloffAngle(mCachedPtr, value.Degrees); }
+        }
+
+        internal bool CastsShadow
+        {
+            get { return Internal_GetCastsShadow(mCachedPtr); }
+            set { Internal_SetCastsShadow(mCachedPtr, value); }
+        }
+
+        internal Sphere Bounds
+        {
+            get
+            {
+                Sphere bounds;
+                Internal_GetBounds(mCachedPtr, out bounds);
+                return bounds;
+            }
+        }
+
+        internal NativeLight(SceneObject sceneObject)
+        {
+            IntPtr sceneObjPtr = IntPtr.Zero;
+            if (sceneObject != null)
+                sceneObjPtr = sceneObject.GetCachedPtr();
+
+            Internal_Create(this, sceneObjPtr);
+        }
+
+        internal void UpdateTransform(SceneObject parentSO)
+        {
+            if (parentSO != null)
+                Internal_UpdateTransform(mCachedPtr, parentSO.GetCachedPtr());
+        }
+
+        internal void OnDestroy()
+        {
+            Internal_OnDestroy(mCachedPtr);
+        }
+
+        [MethodImpl(MethodImplOptions.InternalCall)]
+        private static extern void Internal_Create(NativeLight instance, IntPtr parentSO);
+
+        [MethodImpl(MethodImplOptions.InternalCall)]
+        private static extern LightType Internal_GetType(IntPtr instance);
+        [MethodImpl(MethodImplOptions.InternalCall)]
+        private static extern void Internal_SetType(IntPtr instance, LightType value);
+        [MethodImpl(MethodImplOptions.InternalCall)]
+        private static extern float Internal_GetRange(IntPtr instance);
+        [MethodImpl(MethodImplOptions.InternalCall)]
+        private static extern void Internal_SetRange(IntPtr instance, float value);
+        [MethodImpl(MethodImplOptions.InternalCall)]
+        private static extern float Internal_GetIntensity(IntPtr instance);
+        [MethodImpl(MethodImplOptions.InternalCall)]
+        private static extern void Internal_SetIntensity(IntPtr instance, float value);
+        [MethodImpl(MethodImplOptions.InternalCall)]
+        private static extern void Internal_GetColor(IntPtr instance, out Color color);
+        [MethodImpl(MethodImplOptions.InternalCall)]
+        private static extern void Internal_SetColor(IntPtr instance, Color value);
+        [MethodImpl(MethodImplOptions.InternalCall)]
+        private static extern bool Internal_GetCastsShadow(IntPtr instance);
+        [MethodImpl(MethodImplOptions.InternalCall)]
+        private static extern void Internal_SetCastsShadow(IntPtr instance, bool value);
+        [MethodImpl(MethodImplOptions.InternalCall)]
+        private static extern float Internal_GetSpotAngle(IntPtr instance);
+        [MethodImpl(MethodImplOptions.InternalCall)]
+        private static extern void Internal_SetSpotAngle(IntPtr instance, float value);
+        [MethodImpl(MethodImplOptions.InternalCall)]
+        private static extern float Internal_GetSpotFalloffAngle(IntPtr instance);
+        [MethodImpl(MethodImplOptions.InternalCall)]
+        private static extern void Internal_SetSpotFalloffAngle(IntPtr instance, float value);
+        [MethodImpl(MethodImplOptions.InternalCall)]
+        private static extern void Internal_GetBounds(IntPtr instance, out Sphere bounds);
+
+        [MethodImpl(MethodImplOptions.InternalCall)]
+        private static extern void Internal_UpdateTransform(IntPtr instance, IntPtr parentSO);
+        [MethodImpl(MethodImplOptions.InternalCall)]
+        private static extern void Internal_OnDestroy(IntPtr thisPtr);
+    }
+}

+ 356 - 356
SBansheeEditor/Source/BsGUIResourceField.cpp

@@ -1,357 +1,357 @@
-#include "BsGUIResourceField.h"
-#include "BsGUILayoutX.h"
-#include "BsGUILabel.h"
-#include "BsGUIDropButton.h"
-#include "BsGUIButton.h"
-#include "BsBuiltinResources.h"
-#include "BsCGUIWidget.h"
-#include "BsGUIMouseEvent.h"
-#include "BsGUIResourceTreeView.h"
-#include "BsCGUIWidget.h"
-#include "BsGameObjectManager.h"
-#include "BsScriptAssemblyManager.h"
-#include "BsMonoClass.h"
-#include "BsMonoManager.h"
-#include "BsResources.h"
-#include "BsProjectLibrary.h"
-#include "BsProjectResourceMeta.h"
-#include "BsManagedResourceMetaData.h"
-#include "BsBuiltinEditorResources.h"
-#include "BsScriptManagedResource.h"
-#include "BsSelection.h"
-
-using namespace std::placeholders;
-
-namespace BansheeEngine
-{
-	const UINT32 GUIResourceField::DEFAULT_LABEL_WIDTH = 100;
-
-	GUIResourceField::GUIResourceField(const PrivatelyConstruct& dummy, const String& typeNamespace, const String& type, const GUIContent& labelContent, UINT32 labelWidth,
-		const String& style, const GUIDimensions& dimensions, bool withLabel)
-		:GUIElementContainer(dimensions, style), mLabel(nullptr), mClearButton(nullptr), mDropButton(nullptr), mType(type), mNamespace(typeNamespace)
-	{
-		mLayout = GUILayoutX::create();
-		_registerChildElement(mLayout);
-
-		if (withLabel)
-		{
-			mLabel = GUILabel::create(labelContent, GUIOptions(GUIOption::fixedWidth(labelWidth)), getSubStyleName(BuiltinEditorResources::ObjectFieldLabelStyleName));
-			mLayout->addElement(mLabel);
-		}
-
-		mDropButton = GUIDropButton::create((UINT32)DragAndDropType::Resources, GUIOptions(GUIOption::flexibleWidth()), getSubStyleName(BuiltinEditorResources::ObjectFieldDropBtnStyleName));
-		mClearButton = GUIButton::create(HString(L""), getSubStyleName(BuiltinEditorResources::ObjectFieldClearBtnStyleName));
-		mClearButton->onClick.connect(std::bind(&GUIResourceField::onClearButtonClicked, this));
-
-		mLayout->addElement(mDropButton);
-		mLayout->addElement(mClearButton);
-
-		mDropButton->onDataDropped.connect(std::bind(&GUIResourceField::dataDropped, this, _1));
-		mDropButton->onClick.connect(std::bind(&GUIResourceField::onDropButtonClicked, this));
-	}
-
-	GUIResourceField::~GUIResourceField()
-	{
-
-	}
-
-	GUIResourceField* GUIResourceField::create(const String& typeNamespace, const String& type, const GUIContent& labelContent, UINT32 labelWidth, const GUIOptions& options,
-		const String& style)
-	{
-		const String* curStyle = &style;
-		if (*curStyle == StringUtil::BLANK)
-			curStyle = &BuiltinEditorResources::ObjectFieldStyleName;
-
-		return bs_new<GUIResourceField>(PrivatelyConstruct(), typeNamespace, type, labelContent, labelWidth, *curStyle,
-			GUIDimensions::create(options), true);
-	}
-
-	GUIResourceField* GUIResourceField::create(const String& typeNamespace, const String& type, const GUIContent& labelContent, const GUIOptions& options,
-		const String& style)
-	{
-		const String* curStyle = &style;
-		if (*curStyle == StringUtil::BLANK)
-			curStyle = &BuiltinEditorResources::ObjectFieldStyleName;
-
-		return bs_new<GUIResourceField>(PrivatelyConstruct(), typeNamespace, type, labelContent, DEFAULT_LABEL_WIDTH, *curStyle,
-			GUIDimensions::create(options), true);
-	}
-
-	GUIResourceField* GUIResourceField::create(const String& typeNamespace, const String& type, const HString& labelText, UINT32 labelWidth, const GUIOptions& options,
-		const String& style)
-	{
-		const String* curStyle = &style;
-		if (*curStyle == StringUtil::BLANK)
-			curStyle = &BuiltinEditorResources::ObjectFieldStyleName;
-
-		return bs_new<GUIResourceField>(PrivatelyConstruct(), typeNamespace, type, GUIContent(labelText), labelWidth, *curStyle,
-			GUIDimensions::create(options), true);
-	}
-
-	GUIResourceField* GUIResourceField::create(const String& typeNamespace, const String& type, const HString& labelText, const GUIOptions& options,
-		const String& style)
-	{
-		const String* curStyle = &style;
-		if (*curStyle == StringUtil::BLANK)
-			curStyle = &BuiltinEditorResources::ObjectFieldStyleName;
-
-		return bs_new<GUIResourceField>(PrivatelyConstruct(), typeNamespace, type, GUIContent(labelText), DEFAULT_LABEL_WIDTH, *curStyle,
-			GUIDimensions::create(options), true);
-	}
-
-	GUIResourceField* GUIResourceField::create(const String& typeNamespace, const String& type, const GUIOptions& options, const String& style)
-	{
-		const String* curStyle = &style;
-		if (*curStyle == StringUtil::BLANK)
-			curStyle = &BuiltinEditorResources::ObjectFieldStyleName;
-
-		return bs_new<GUIResourceField>(PrivatelyConstruct(), typeNamespace, type, GUIContent(), 0, *curStyle,
-			GUIDimensions::create(options), false);
-	}
-
-	GUIResourceField* GUIResourceField::create(const String& typeNamespace, const String& type, const GUIContent& labelContent, UINT32 labelWidth,
-		const String& style)
-	{
-		const String* curStyle = &style;
-		if (*curStyle == StringUtil::BLANK)
-			curStyle = &BuiltinEditorResources::ObjectFieldStyleName;
-
-		return bs_new<GUIResourceField>(PrivatelyConstruct(), typeNamespace, type, labelContent, labelWidth, *curStyle,
-			GUIDimensions::create(), true);
-	}
-
-	GUIResourceField* GUIResourceField::create(const String& typeNamespace, const String& type, const GUIContent& labelContent,
-		const String& style)
-	{
-		const String* curStyle = &style;
-		if (*curStyle == StringUtil::BLANK)
-			curStyle = &BuiltinEditorResources::ObjectFieldStyleName;
-
-		return bs_new<GUIResourceField>(PrivatelyConstruct(), typeNamespace, type, labelContent, DEFAULT_LABEL_WIDTH, *curStyle,
-			GUIDimensions::create(), true);
-	}
-
-	GUIResourceField* GUIResourceField::create(const String& typeNamespace, const String& type, const HString& labelText, UINT32 labelWidth,
-		const String& style)
-	{
-		const String* curStyle = &style;
-		if (*curStyle == StringUtil::BLANK)
-			curStyle = &BuiltinEditorResources::ObjectFieldStyleName;
-
-		return bs_new<GUIResourceField>(PrivatelyConstruct(), typeNamespace, type, GUIContent(labelText), labelWidth, *curStyle,
-			GUIDimensions::create(), true);
-	}
-
-	GUIResourceField* GUIResourceField::create(const String& typeNamespace, const String& type, const HString& labelText,
-		const String& style)
-	{
-		const String* curStyle = &style;
-		if (*curStyle == StringUtil::BLANK)
-			curStyle = &BuiltinEditorResources::ObjectFieldStyleName;
-
-		return bs_new<GUIResourceField>(PrivatelyConstruct(), typeNamespace, type, GUIContent(labelText), DEFAULT_LABEL_WIDTH, *curStyle,
-			GUIDimensions::create(), true);
-	}
-
-	GUIResourceField* GUIResourceField::create(const String& typeNamespace, const String& type, const String& style)
-	{
-		const String* curStyle = &style;
-		if (*curStyle == StringUtil::BLANK)
-			curStyle = &BuiltinEditorResources::ObjectFieldStyleName;
-
-		return bs_new<GUIResourceField>(PrivatelyConstruct(), typeNamespace, type, GUIContent(), 0, *curStyle,
-			GUIDimensions::create(), false);
-	}
-
-	HResource GUIResourceField::getValue() const
-	{
-		if (!mUUID.empty())
-			return gResources().loadFromUUID(mUUID);
-
-		return HResource();
-	}
-
-	void GUIResourceField::setValue(const HResource& value)
-	{
-		if (value)
-		{
-			Path resPath = gProjectLibrary().uuidToPath(value.getUUID());
-			if (!resPath.isEmpty())
-				setUUID(value.getUUID(), false);
-			else // A non-project library resource
-			{
-				if (mUUID == value.getUUID())
-					return;
-
-				mUUID = value.getUUID();
-
-				WString title = value->getName() + L" (" + toWString(mType) + L")";
-				mDropButton->setContent(GUIContent(HEString(title)));
-			}
-		}
-		else
-			setUUID("", false);
-	}
-
-	WeakResourceHandle<Resource> GUIResourceField::getValueWeak() const
-	{
-		if (!mUUID.empty())
-			return Resources::instance()._getResourceHandle(mUUID).getWeak();
-
-		return WeakResourceHandle<Resource>();
-	}
-
-	void GUIResourceField::setValueWeak(const WeakResourceHandle<Resource>& value)
-	{
-		if (value)
-		{
-			Path resPath = gProjectLibrary().uuidToPath(value.getUUID());
-			if (!resPath.isEmpty())
-				setUUID(value.getUUID(), false);
-			else // A non-project library resource
-			{
-				if (mUUID == value.getUUID())
-					return;
-
-				mUUID = value.getUUID();
-
-				WString title = value->getName() + L" (" + toWString(mType) + L")";
-				mDropButton->setContent(GUIContent(HEString(title)));
-			}
-		}
-		else
-			setUUID("", false);
-	}
-
-	void GUIResourceField::setUUID(const String& uuid, bool triggerEvent)
-	{ 
-		if (mUUID == uuid)
-			return;
-
-		mUUID = uuid;
-
-		Path resPath = gProjectLibrary().uuidToPath(mUUID);
-		if (!resPath.isEmpty())
-		{
-			WString title = resPath.getWFilename(false) + L" (" + toWString(mType) + L")";
-			mDropButton->setContent(GUIContent(HEString(title)));
-		}
-		else
-			mDropButton->setContent(GUIContent(HEString(L"None (" + toWString(mType) + L")")));
-
-		if (triggerEvent)
-		{
-			HResource handle = gResources()._getResourceHandle(mUUID);
-			onValueChanged(handle.getWeak());
-		}
-	}
-
-	void GUIResourceField::setTint(const Color& color)
-	{
-		if (mLabel != nullptr)
-			mLabel->setTint(color);
-
-		mDropButton->setTint(color);
-		mClearButton->setTint(color);
-	}
-
-	void GUIResourceField::_updateLayoutInternal(const GUILayoutData& data)
-	{
-		mLayout->_setLayoutData(data);
-		mLayout->_updateLayoutInternal(data);
-	}
-
-	Vector2I GUIResourceField::_getOptimalSize() const
-	{
-		return mLayout->_getOptimalSize();
-	}
-
-	void GUIResourceField::onDropButtonClicked()
-	{
-		if (mUUID == "")
-			return;
-
-		Path resPath = gProjectLibrary().uuidToPath(mUUID);
-		resPath = resPath.getRelative(gProjectLibrary().getResourcesFolder());
-
-		Selection::instance().ping(resPath);
-	}
-
-	void GUIResourceField::dataDropped(void* data)
-	{
-		DraggedResources* draggedResources = reinterpret_cast<DraggedResources*>(data);
-		UINT32 numResources = (UINT32)draggedResources->resourcePaths.size();
-
-		if (numResources <= 0)
-			return;
-
-		MonoClass* acceptedClass = MonoManager::instance().findClass(mNamespace, mType);
-
-		for (UINT32 i = 0; i < numResources; i++)
-		{
-			Path path = draggedResources->resourcePaths[i];
-
-			ProjectLibrary::LibraryEntry* libEntry = gProjectLibrary().findEntry(path);
-			if (libEntry == nullptr || libEntry->type == ProjectLibrary::LibraryEntryType::Directory)
-				continue;
-
-			ProjectLibrary::ResourceEntry* resEntry = static_cast<ProjectLibrary::ResourceEntry*>(libEntry);
-
-			ProjectResourceMetaPtr meta = resEntry->meta;
-			if (meta == nullptr)
-				continue;
-
-			UINT32 typeId = meta->getTypeID();
-			String uuid = meta->getUUID();
-
-			bool found = false;
-			MonoClass* scriptClass = ScriptResource::getClassFromTypeId(typeId);
-			if (scriptClass != nullptr)
-			{
-				if (scriptClass->isSubClassOf(acceptedClass))
-				{
-					setUUID(uuid);
-					found = true;
-				}
-			}
-			else if (typeId == TID_ManagedResource)
-			{
-				ManagedResourceMetaDataPtr managedResMetaData = std::static_pointer_cast<ManagedResourceMetaData>(meta->getResourceMetaData());
-				MonoClass* providedClass = MonoManager::instance().findClass(managedResMetaData->typeNamespace, managedResMetaData->typeName);
-
-				if (providedClass->isSubClassOf(acceptedClass))
-				{
-					setUUID(uuid);
-					found = true;
-				}
-			}
-			else
-			{
-				BS_EXCEPT(NotImplementedException, "Unsupported resource type added to resource field.");
-			}
-
-			if (found)
-				break;
-		}
-	}
-
-	void GUIResourceField::styleUpdated()
-	{
-		if (mLabel != nullptr)
-			mLabel->setStyle(getSubStyleName(BuiltinEditorResources::ObjectFieldLabelStyleName));
-
-		mDropButton->setStyle(getSubStyleName(BuiltinEditorResources::ObjectFieldDropBtnStyleName));
-		mClearButton->setStyle(getSubStyleName(BuiltinEditorResources::ObjectFieldClearBtnStyleName));
-	}
-
-	void GUIResourceField::onClearButtonClicked()
-	{
-		setUUID(StringUtil::BLANK);
-	}
-
-	const String& GUIResourceField::getGUITypeName()
-	{
-		static String typeName = "GUIResourceField";
-		return typeName;
-	}
+#include "BsGUIResourceField.h"
+#include "BsGUILayoutX.h"
+#include "BsGUILabel.h"
+#include "BsGUIDropButton.h"
+#include "BsGUIButton.h"
+#include "BsBuiltinResources.h"
+#include "BsCGUIWidget.h"
+#include "BsGUIMouseEvent.h"
+#include "BsGUIResourceTreeView.h"
+#include "BsCGUIWidget.h"
+#include "BsGameObjectManager.h"
+#include "BsScriptAssemblyManager.h"
+#include "BsMonoClass.h"
+#include "BsMonoManager.h"
+#include "BsResources.h"
+#include "BsProjectLibrary.h"
+#include "BsProjectResourceMeta.h"
+#include "BsManagedResourceMetaData.h"
+#include "BsBuiltinEditorResources.h"
+#include "BsScriptManagedResource.h"
+#include "BsSelection.h"
+
+using namespace std::placeholders;
+
+namespace BansheeEngine
+{
+	const UINT32 GUIResourceField::DEFAULT_LABEL_WIDTH = 100;
+
+	GUIResourceField::GUIResourceField(const PrivatelyConstruct& dummy, const String& typeNamespace, const String& type, const GUIContent& labelContent, UINT32 labelWidth,
+		const String& style, const GUIDimensions& dimensions, bool withLabel)
+		:GUIElementContainer(dimensions, style), mLabel(nullptr), mClearButton(nullptr), mDropButton(nullptr), mType(type), mNamespace(typeNamespace)
+	{
+		mLayout = GUILayoutX::create();
+		_registerChildElement(mLayout);
+
+		if (withLabel)
+		{
+			mLabel = GUILabel::create(labelContent, GUIOptions(GUIOption::fixedWidth(labelWidth)), getSubStyleName(BuiltinEditorResources::ObjectFieldLabelStyleName));
+			mLayout->addElement(mLabel);
+		}
+
+		mDropButton = GUIDropButton::create((UINT32)DragAndDropType::Resources, GUIOptions(GUIOption::flexibleWidth()), getSubStyleName(BuiltinEditorResources::ObjectFieldDropBtnStyleName));
+		mClearButton = GUIButton::create(HString(L""), getSubStyleName(BuiltinEditorResources::ObjectFieldClearBtnStyleName));
+		mClearButton->onClick.connect(std::bind(&GUIResourceField::onClearButtonClicked, this));
+
+		mLayout->addElement(mDropButton);
+		mLayout->addElement(mClearButton);
+
+		mDropButton->onDataDropped.connect(std::bind(&GUIResourceField::dataDropped, this, _1));
+		mDropButton->onClick.connect(std::bind(&GUIResourceField::onDropButtonClicked, this));
+	}
+
+	GUIResourceField::~GUIResourceField()
+	{
+
+	}
+
+	GUIResourceField* GUIResourceField::create(const String& typeNamespace, const String& type, const GUIContent& labelContent, UINT32 labelWidth, const GUIOptions& options,
+		const String& style)
+	{
+		const String* curStyle = &style;
+		if (*curStyle == StringUtil::BLANK)
+			curStyle = &BuiltinEditorResources::ObjectFieldStyleName;
+
+		return bs_new<GUIResourceField>(PrivatelyConstruct(), typeNamespace, type, labelContent, labelWidth, *curStyle,
+			GUIDimensions::create(options), true);
+	}
+
+	GUIResourceField* GUIResourceField::create(const String& typeNamespace, const String& type, const GUIContent& labelContent, const GUIOptions& options,
+		const String& style)
+	{
+		const String* curStyle = &style;
+		if (*curStyle == StringUtil::BLANK)
+			curStyle = &BuiltinEditorResources::ObjectFieldStyleName;
+
+		return bs_new<GUIResourceField>(PrivatelyConstruct(), typeNamespace, type, labelContent, DEFAULT_LABEL_WIDTH, *curStyle,
+			GUIDimensions::create(options), true);
+	}
+
+	GUIResourceField* GUIResourceField::create(const String& typeNamespace, const String& type, const HString& labelText, UINT32 labelWidth, const GUIOptions& options,
+		const String& style)
+	{
+		const String* curStyle = &style;
+		if (*curStyle == StringUtil::BLANK)
+			curStyle = &BuiltinEditorResources::ObjectFieldStyleName;
+
+		return bs_new<GUIResourceField>(PrivatelyConstruct(), typeNamespace, type, GUIContent(labelText), labelWidth, *curStyle,
+			GUIDimensions::create(options), true);
+	}
+
+	GUIResourceField* GUIResourceField::create(const String& typeNamespace, const String& type, const HString& labelText, const GUIOptions& options,
+		const String& style)
+	{
+		const String* curStyle = &style;
+		if (*curStyle == StringUtil::BLANK)
+			curStyle = &BuiltinEditorResources::ObjectFieldStyleName;
+
+		return bs_new<GUIResourceField>(PrivatelyConstruct(), typeNamespace, type, GUIContent(labelText), DEFAULT_LABEL_WIDTH, *curStyle,
+			GUIDimensions::create(options), true);
+	}
+
+	GUIResourceField* GUIResourceField::create(const String& typeNamespace, const String& type, const GUIOptions& options, const String& style)
+	{
+		const String* curStyle = &style;
+		if (*curStyle == StringUtil::BLANK)
+			curStyle = &BuiltinEditorResources::ObjectFieldStyleName;
+
+		return bs_new<GUIResourceField>(PrivatelyConstruct(), typeNamespace, type, GUIContent(), 0, *curStyle,
+			GUIDimensions::create(options), false);
+	}
+
+	GUIResourceField* GUIResourceField::create(const String& typeNamespace, const String& type, const GUIContent& labelContent, UINT32 labelWidth,
+		const String& style)
+	{
+		const String* curStyle = &style;
+		if (*curStyle == StringUtil::BLANK)
+			curStyle = &BuiltinEditorResources::ObjectFieldStyleName;
+
+		return bs_new<GUIResourceField>(PrivatelyConstruct(), typeNamespace, type, labelContent, labelWidth, *curStyle,
+			GUIDimensions::create(), true);
+	}
+
+	GUIResourceField* GUIResourceField::create(const String& typeNamespace, const String& type, const GUIContent& labelContent,
+		const String& style)
+	{
+		const String* curStyle = &style;
+		if (*curStyle == StringUtil::BLANK)
+			curStyle = &BuiltinEditorResources::ObjectFieldStyleName;
+
+		return bs_new<GUIResourceField>(PrivatelyConstruct(), typeNamespace, type, labelContent, DEFAULT_LABEL_WIDTH, *curStyle,
+			GUIDimensions::create(), true);
+	}
+
+	GUIResourceField* GUIResourceField::create(const String& typeNamespace, const String& type, const HString& labelText, UINT32 labelWidth,
+		const String& style)
+	{
+		const String* curStyle = &style;
+		if (*curStyle == StringUtil::BLANK)
+			curStyle = &BuiltinEditorResources::ObjectFieldStyleName;
+
+		return bs_new<GUIResourceField>(PrivatelyConstruct(), typeNamespace, type, GUIContent(labelText), labelWidth, *curStyle,
+			GUIDimensions::create(), true);
+	}
+
+	GUIResourceField* GUIResourceField::create(const String& typeNamespace, const String& type, const HString& labelText,
+		const String& style)
+	{
+		const String* curStyle = &style;
+		if (*curStyle == StringUtil::BLANK)
+			curStyle = &BuiltinEditorResources::ObjectFieldStyleName;
+
+		return bs_new<GUIResourceField>(PrivatelyConstruct(), typeNamespace, type, GUIContent(labelText), DEFAULT_LABEL_WIDTH, *curStyle,
+			GUIDimensions::create(), true);
+	}
+
+	GUIResourceField* GUIResourceField::create(const String& typeNamespace, const String& type, const String& style)
+	{
+		const String* curStyle = &style;
+		if (*curStyle == StringUtil::BLANK)
+			curStyle = &BuiltinEditorResources::ObjectFieldStyleName;
+
+		return bs_new<GUIResourceField>(PrivatelyConstruct(), typeNamespace, type, GUIContent(), 0, *curStyle,
+			GUIDimensions::create(), false);
+	}
+
+	HResource GUIResourceField::getValue() const
+	{
+		if (!mUUID.empty())
+			return gResources().loadFromUUID(mUUID);
+
+		return HResource();
+	}
+
+	void GUIResourceField::setValue(const HResource& value)
+	{
+		if (value)
+		{
+			Path resPath = gProjectLibrary().uuidToPath(value.getUUID());
+			if (!resPath.isEmpty() || !value.isLoaded(false))
+				setUUID(value.getUUID(), false);
+			else // A non-project library resource
+			{
+				if (mUUID == value.getUUID())
+					return;
+
+				mUUID = value.getUUID();
+
+				WString title = value->getName() + L" (" + toWString(mType) + L")";
+				mDropButton->setContent(GUIContent(HEString(title)));
+			}
+		}
+		else
+			setUUID("", false);
+	}
+
+	WeakResourceHandle<Resource> GUIResourceField::getValueWeak() const
+	{
+		if (!mUUID.empty())
+			return Resources::instance()._getResourceHandle(mUUID).getWeak();
+
+		return WeakResourceHandle<Resource>();
+	}
+
+	void GUIResourceField::setValueWeak(const WeakResourceHandle<Resource>& value)
+	{
+		if (value)
+		{
+			Path resPath = gProjectLibrary().uuidToPath(value.getUUID());
+			if (!resPath.isEmpty() || !value.isLoaded(false))
+				setUUID(value.getUUID(), false);
+			else // A non-project library resource
+			{
+				if (mUUID == value.getUUID())
+					return;
+
+				mUUID = value.getUUID();
+
+				WString title = value->getName() + L" (" + toWString(mType) + L")";
+				mDropButton->setContent(GUIContent(HEString(title)));
+			}
+		}
+		else
+			setUUID("", false);
+	}
+
+	void GUIResourceField::setUUID(const String& uuid, bool triggerEvent)
+	{ 
+		if (mUUID == uuid)
+			return;
+
+		mUUID = uuid;
+
+		Path resPath = gProjectLibrary().uuidToPath(mUUID);
+		if (!resPath.isEmpty())
+		{
+			WString title = resPath.getWFilename(false) + L" (" + toWString(mType) + L")";
+			mDropButton->setContent(GUIContent(HEString(title)));
+		}
+		else
+			mDropButton->setContent(GUIContent(HEString(L"None (" + toWString(mType) + L")")));
+
+		if (triggerEvent)
+		{
+			HResource handle = gResources()._getResourceHandle(mUUID);
+			onValueChanged(handle.getWeak());
+		}
+	}
+
+	void GUIResourceField::setTint(const Color& color)
+	{
+		if (mLabel != nullptr)
+			mLabel->setTint(color);
+
+		mDropButton->setTint(color);
+		mClearButton->setTint(color);
+	}
+
+	void GUIResourceField::_updateLayoutInternal(const GUILayoutData& data)
+	{
+		mLayout->_setLayoutData(data);
+		mLayout->_updateLayoutInternal(data);
+	}
+
+	Vector2I GUIResourceField::_getOptimalSize() const
+	{
+		return mLayout->_getOptimalSize();
+	}
+
+	void GUIResourceField::onDropButtonClicked()
+	{
+		if (mUUID == "")
+			return;
+
+		Path resPath = gProjectLibrary().uuidToPath(mUUID);
+		resPath = resPath.getRelative(gProjectLibrary().getResourcesFolder());
+
+		Selection::instance().ping(resPath);
+	}
+
+	void GUIResourceField::dataDropped(void* data)
+	{
+		DraggedResources* draggedResources = reinterpret_cast<DraggedResources*>(data);
+		UINT32 numResources = (UINT32)draggedResources->resourcePaths.size();
+
+		if (numResources <= 0)
+			return;
+
+		MonoClass* acceptedClass = MonoManager::instance().findClass(mNamespace, mType);
+
+		for (UINT32 i = 0; i < numResources; i++)
+		{
+			Path path = draggedResources->resourcePaths[i];
+
+			ProjectLibrary::LibraryEntry* libEntry = gProjectLibrary().findEntry(path);
+			if (libEntry == nullptr || libEntry->type == ProjectLibrary::LibraryEntryType::Directory)
+				continue;
+
+			ProjectLibrary::ResourceEntry* resEntry = static_cast<ProjectLibrary::ResourceEntry*>(libEntry);
+
+			ProjectResourceMetaPtr meta = resEntry->meta;
+			if (meta == nullptr)
+				continue;
+
+			UINT32 typeId = meta->getTypeID();
+			String uuid = meta->getUUID();
+
+			bool found = false;
+			MonoClass* scriptClass = ScriptResource::getClassFromTypeId(typeId);
+			if (scriptClass != nullptr)
+			{
+				if (scriptClass->isSubClassOf(acceptedClass))
+				{
+					setUUID(uuid);
+					found = true;
+				}
+			}
+			else if (typeId == TID_ManagedResource)
+			{
+				ManagedResourceMetaDataPtr managedResMetaData = std::static_pointer_cast<ManagedResourceMetaData>(meta->getResourceMetaData());
+				MonoClass* providedClass = MonoManager::instance().findClass(managedResMetaData->typeNamespace, managedResMetaData->typeName);
+
+				if (providedClass->isSubClassOf(acceptedClass))
+				{
+					setUUID(uuid);
+					found = true;
+				}
+			}
+			else
+			{
+				BS_EXCEPT(NotImplementedException, "Unsupported resource type added to resource field.");
+			}
+
+			if (found)
+				break;
+		}
+	}
+
+	void GUIResourceField::styleUpdated()
+	{
+		if (mLabel != nullptr)
+			mLabel->setStyle(getSubStyleName(BuiltinEditorResources::ObjectFieldLabelStyleName));
+
+		mDropButton->setStyle(getSubStyleName(BuiltinEditorResources::ObjectFieldDropBtnStyleName));
+		mClearButton->setStyle(getSubStyleName(BuiltinEditorResources::ObjectFieldClearBtnStyleName));
+	}
+
+	void GUIResourceField::onClearButtonClicked()
+	{
+		setUUID(StringUtil::BLANK);
+	}
+
+	const String& GUIResourceField::getGUITypeName()
+	{
+		static String typeName = "GUIResourceField";
+		return typeName;
+	}
 }

+ 71 - 73
SBansheeEngine/Include/BsScriptLight.h

@@ -1,74 +1,72 @@
-#pragma once
-
-#include "BsScriptEnginePrerequisites.h"
-#include "BsScriptObject.h"
-#include "BsVector3.h"
-#include "BsQuaternion.h"
-#include "BsDegree.h"
-#include "BsColor.h"
-#include "BsLight.h"
-
-namespace BansheeEngine
-{
-	/**
-	 * @brief	Interop class between C++ & CLR for Light.
-	 */
-	class BS_SCR_BE_EXPORT ScriptLight : public ScriptObject <ScriptLight>
-	{
-	public:
-		SCRIPT_OBJ(ENGINE_ASSEMBLY, "BansheeEngine", "NativeLight")
-
-		/**
-		 * @brief	Gets the wrapped native LightInternal object.
-		 */
-		SPtr<Light> getInternal() const { return mLight; }
-
-	private:
-		ScriptLight(MonoObject* managedInstance, const HSceneObject& parentSO);
-		~ScriptLight();
-
-		/**
-		 * @brief	Destroys the internal light handler object.
-		 */
-		void destroy();
-
-		/**
-		 * @copydoc	ScriptObject::_onManagedInstanceDeleted
-		 */
-		void _onManagedInstanceDeleted() override;
-
-		SPtr<Light> mLight;
-		UINT32 mLastUpdateHash;
-
-		/************************************************************************/
-		/* 								CLR HOOKS						   		*/
-		/************************************************************************/
-		static void internal_create(MonoObject* managedInstance, ScriptSceneObject* parentSO);
-
-		static LightType internal_getType(ScriptLight* thisPtr);
-		static void internal_setType(ScriptLight* thisPtr, LightType type);
-
-		static bool internal_getCastsShadow(ScriptLight* thisPtr);
-		static void internal_setCastsShadow(ScriptLight* thisPtr, bool castsShadow);
-
-		static Color internal_getColor(ScriptLight* thisPtr);
-		static void internal_setColor(ScriptLight* thisPtr, Color color);
-
-		static float internal_getRange(ScriptLight* thisPtr);
-		static void internal_setRange(ScriptLight* thisPtr, float range);
-
-		static float internal_getIntensity(ScriptLight* thisPtr);
-		static void internal_setIntensity(ScriptLight* thisPtr, float intensity);
-
-		static Degree internal_getSpotAngle(ScriptLight* thisPtr);
-		static void internal_setSpotAngle(ScriptLight* thisPtr, Degree spotAngle);
-
-		static Degree internal_getSpotFalloffAngle(ScriptLight* thisPtr);
-		static void internal_setSpotFalloffAngle(ScriptLight* thisPtr, Degree spotFalloffAngle);
-
-		static Sphere internal_getBounds(ScriptLight* thisPtr);
-
-		static void internal_updateTransform(ScriptLight* thisPtr, ScriptSceneObject* parent);
-		static void internal_onDestroy(ScriptLight* instance);
-	};
+#pragma once
+
+#include "BsScriptEnginePrerequisites.h"
+#include "BsScriptObject.h"
+#include "BsDegree.h"
+#include "BsColor.h"
+#include "BsLight.h"
+
+namespace BansheeEngine
+{
+	/**
+	 * @brief	Interop class between C++ & CLR for Light.
+	 */
+	class BS_SCR_BE_EXPORT ScriptLight : public ScriptObject <ScriptLight>
+	{
+	public:
+		SCRIPT_OBJ(ENGINE_ASSEMBLY, "BansheeEngine", "NativeLight")
+
+		/**
+		 * @brief	Gets the wrapped native LightInternal object.
+		 */
+		SPtr<Light> getInternal() const { return mLight; }
+
+	private:
+		ScriptLight(MonoObject* managedInstance, const HSceneObject& parentSO);
+		~ScriptLight();
+
+		/**
+		 * @brief	Destroys the internal light handler object.
+		 */
+		void destroy();
+
+		/**
+		 * @copydoc	ScriptObject::_onManagedInstanceDeleted
+		 */
+		void _onManagedInstanceDeleted() override;
+
+		SPtr<Light> mLight;
+		UINT32 mLastUpdateHash;
+
+		/************************************************************************/
+		/* 								CLR HOOKS						   		*/
+		/************************************************************************/
+		static void internal_create(MonoObject* managedInstance, ScriptSceneObject* parentSO);
+
+		static LightType internal_getType(ScriptLight* thisPtr);
+		static void internal_setType(ScriptLight* thisPtr, LightType type);
+
+		static bool internal_getCastsShadow(ScriptLight* thisPtr);
+		static void internal_setCastsShadow(ScriptLight* thisPtr, bool castsShadow);
+
+		static void internal_getColor(ScriptLight* thisPtr, Color* color);
+		static void internal_setColor(ScriptLight* thisPtr, Color color);
+
+		static float internal_getRange(ScriptLight* thisPtr);
+		static void internal_setRange(ScriptLight* thisPtr, float range);
+
+		static float internal_getIntensity(ScriptLight* thisPtr);
+		static void internal_setIntensity(ScriptLight* thisPtr, float intensity);
+
+		static float internal_getSpotAngle(ScriptLight* thisPtr);
+		static void internal_setSpotAngle(ScriptLight* thisPtr, float spotAngle);
+
+		static float internal_getSpotFalloffAngle(ScriptLight* thisPtr);
+		static void internal_setSpotFalloffAngle(ScriptLight* thisPtr, float spotFalloffAngle);
+
+		static void internal_getBounds(ScriptLight* thisPtr, Sphere* bounds);
+
+		static void internal_updateTransform(ScriptLight* thisPtr, ScriptSceneObject* parent);
+		static void internal_onDestroy(ScriptLight* instance);
+	};
 }

+ 153 - 155
SBansheeEngine/Source/BsScriptLight.cpp

@@ -1,156 +1,154 @@
-#include "BsScriptLight.h"
-#include "BsScriptSceneObject.h"
-#include "BsSceneObject.h"
-#include "BsScriptSceneObject.h"
-#include "BsSceneManager.h"
-
-namespace BansheeEngine
-{
-	ScriptLight::ScriptLight(MonoObject* managedInstance, const HSceneObject& parentSO)
-		:ScriptObject(managedInstance), mLight(nullptr), mLastUpdateHash(0)
-	{
-		mLight = Light::create();
-		gSceneManager()._registerLight(mLight, parentSO);
-	}
-
-	ScriptLight::~ScriptLight()
-	{
-
-	}
-
-	void ScriptLight::initRuntimeData()
-	{
-		metaData.scriptClass->addInternalCall("Internal_Create", &ScriptLight::internal_create);
-
-		metaData.scriptClass->addInternalCall("Internal_GetType", &ScriptLight::internal_getType);
-		metaData.scriptClass->addInternalCall("Internal_SetType", &ScriptLight::internal_setType);
-		metaData.scriptClass->addInternalCall("Internal_GetCastsShadow", &ScriptLight::internal_getCastsShadow);
-		metaData.scriptClass->addInternalCall("Internal_SetCastsShadow", &ScriptLight::internal_setCastsShadow);
-		metaData.scriptClass->addInternalCall("Internal_GetColor", &ScriptLight::internal_getColor);
-		metaData.scriptClass->addInternalCall("Internal_SetColor", &ScriptLight::internal_setColor);
-		metaData.scriptClass->addInternalCall("Internal_GetRange", &ScriptLight::internal_getRange);
-		metaData.scriptClass->addInternalCall("Internal_SetRange", &ScriptLight::internal_setRange);
-		metaData.scriptClass->addInternalCall("Internal_GetIntensity", &ScriptLight::internal_getIntensity);
-		metaData.scriptClass->addInternalCall("Internal_SetIntensity", &ScriptLight::internal_setIntensity);
-		metaData.scriptClass->addInternalCall("Internal_GetSpotAngle", &ScriptLight::internal_getSpotAngle);
-		metaData.scriptClass->addInternalCall("Internal_SetSpotAngle", &ScriptLight::internal_setSpotAngle);
-		metaData.scriptClass->addInternalCall("Internal_GetSpotFalloffAngle", &ScriptLight::internal_getSpotFalloffAngle);
-		metaData.scriptClass->addInternalCall("Internal_SetSpotFalloffAngle", &ScriptLight::internal_setSpotFalloffAngle);
-		metaData.scriptClass->addInternalCall("Internal_GetBounds", &ScriptLight::internal_getBounds);
-		metaData.scriptClass->addInternalCall("Internal_UpdateTransform", &ScriptLight::internal_updateTransform);
-		metaData.scriptClass->addInternalCall("Internal_OnDestroy", &ScriptLight::internal_onDestroy);
-	}
-
-	void ScriptLight::internal_create(MonoObject* managedInstance, ScriptSceneObject* parentSO)
-	{
-		HSceneObject so;
-		if (parentSO != nullptr)
-			so = parentSO->getNativeHandle();
-
-		ScriptLight* nativeInstance = new (bs_alloc<ScriptLight>()) ScriptLight(managedInstance, so);
-	}
-
-	LightType ScriptLight::internal_getType(ScriptLight* thisPtr)
-	{
-		return thisPtr->getInternal()->getType();
-	}
-
-	void ScriptLight::internal_setType(ScriptLight* thisPtr, LightType type)
-	{
-		thisPtr->getInternal()->setType(type);
-	}
-
-	bool ScriptLight::internal_getCastsShadow(ScriptLight* thisPtr)
-	{
-		return thisPtr->getInternal()->getCastsShadow();
-	}
-
-	void ScriptLight::internal_setCastsShadow(ScriptLight* thisPtr, bool castsShadow)
-	{
-		thisPtr->getInternal()->setCastsShadow(castsShadow);
-	}
-
-	Color ScriptLight::internal_getColor(ScriptLight* thisPtr)
-	{
-		return thisPtr->getInternal()->getColor();
-	}
-
-	void ScriptLight::internal_setColor(ScriptLight* thisPtr, Color color)
-	{
-		thisPtr->getInternal()->setColor(color);
-	}
-
-	float ScriptLight::internal_getRange(ScriptLight* thisPtr)
-	{
-		return thisPtr->getInternal()->getRange();
-	}
-
-	void ScriptLight::internal_setRange(ScriptLight* thisPtr, float range)
-	{
-		thisPtr->getInternal()->setRange(range);
-	}
-
-	float ScriptLight::internal_getIntensity(ScriptLight* thisPtr)
-	{
-		return thisPtr->getInternal()->getIntensity();
-	}
-
-	void ScriptLight::internal_setIntensity(ScriptLight* thisPtr, float intensity)
-	{
-		thisPtr->getInternal()->setIntensity(intensity);
-	}
-
-	Degree ScriptLight::internal_getSpotAngle(ScriptLight* thisPtr)
-	{
-		return thisPtr->getInternal()->getSpotAngle();
-	}
-
-	void ScriptLight::internal_setSpotAngle(ScriptLight* thisPtr, Degree spotAngle)
-	{
-		thisPtr->getInternal()->setSpotAngle(spotAngle);
-	}
-
-	Degree ScriptLight::internal_getSpotFalloffAngle(ScriptLight* thisPtr)
-	{
-		return thisPtr->getInternal()->getSpotFalloffAngle();
-	}
-
-	void ScriptLight::internal_setSpotFalloffAngle(ScriptLight* thisPtr, Degree spotFalloffAngle)
-	{
-		thisPtr->getInternal()->setSpotFalloffAngle(spotFalloffAngle);
-	}
-
-	Sphere ScriptLight::internal_getBounds(ScriptLight* thisPtr)
-	{
-		return thisPtr->getInternal()->getBounds();
-	}
-
-	void ScriptLight::internal_updateTransform(ScriptLight* thisPtr, ScriptSceneObject* parent)
-	{
-		HSceneObject parentSO = parent->getNativeSceneObject();
-
-		if (!parentSO.isDestroyed())
-			thisPtr->getInternal()->_updateTransform(parentSO);
-	}
-
-	void ScriptLight::internal_onDestroy(ScriptLight* instance)
-	{
-		instance->destroy();
-	}
-
-	void ScriptLight::destroy()
-	{
-		if (mLight->isDestroyed())
-			return;
-
-		gSceneManager()._unregisterLight(mLight);
-		mLight->destroy();
-	}
-
-	void ScriptLight::_onManagedInstanceDeleted()
-	{
-		destroy();
-
-		ScriptObject::_onManagedInstanceDeleted();
-	}
+#include "BsScriptLight.h"
+#include "BsScriptSceneObject.h"
+#include "BsSceneObject.h"
+#include "BsScriptSceneObject.h"
+#include "BsSceneManager.h"
+
+namespace BansheeEngine
+{
+	ScriptLight::ScriptLight(MonoObject* managedInstance, const HSceneObject& parentSO)
+		:ScriptObject(managedInstance), mLight(nullptr), mLastUpdateHash(0)
+	{
+		mLight = Light::create();
+		gSceneManager()._registerLight(mLight, parentSO);
+	}
+
+	ScriptLight::~ScriptLight()
+	{ }
+
+	void ScriptLight::initRuntimeData()
+	{
+		metaData.scriptClass->addInternalCall("Internal_Create", &ScriptLight::internal_create);
+
+		metaData.scriptClass->addInternalCall("Internal_GetType", &ScriptLight::internal_getType);
+		metaData.scriptClass->addInternalCall("Internal_SetType", &ScriptLight::internal_setType);
+		metaData.scriptClass->addInternalCall("Internal_GetCastsShadow", &ScriptLight::internal_getCastsShadow);
+		metaData.scriptClass->addInternalCall("Internal_SetCastsShadow", &ScriptLight::internal_setCastsShadow);
+		metaData.scriptClass->addInternalCall("Internal_GetColor", &ScriptLight::internal_getColor);
+		metaData.scriptClass->addInternalCall("Internal_SetColor", &ScriptLight::internal_setColor);
+		metaData.scriptClass->addInternalCall("Internal_GetRange", &ScriptLight::internal_getRange);
+		metaData.scriptClass->addInternalCall("Internal_SetRange", &ScriptLight::internal_setRange);
+		metaData.scriptClass->addInternalCall("Internal_GetIntensity", &ScriptLight::internal_getIntensity);
+		metaData.scriptClass->addInternalCall("Internal_SetIntensity", &ScriptLight::internal_setIntensity);
+		metaData.scriptClass->addInternalCall("Internal_GetSpotAngle", &ScriptLight::internal_getSpotAngle);
+		metaData.scriptClass->addInternalCall("Internal_SetSpotAngle", &ScriptLight::internal_setSpotAngle);
+		metaData.scriptClass->addInternalCall("Internal_GetSpotFalloffAngle", &ScriptLight::internal_getSpotFalloffAngle);
+		metaData.scriptClass->addInternalCall("Internal_SetSpotFalloffAngle", &ScriptLight::internal_setSpotFalloffAngle);
+		metaData.scriptClass->addInternalCall("Internal_GetBounds", &ScriptLight::internal_getBounds);
+		metaData.scriptClass->addInternalCall("Internal_UpdateTransform", &ScriptLight::internal_updateTransform);
+		metaData.scriptClass->addInternalCall("Internal_OnDestroy", &ScriptLight::internal_onDestroy);
+	}
+
+	void ScriptLight::internal_create(MonoObject* managedInstance, ScriptSceneObject* parentSO)
+	{
+		HSceneObject so;
+		if (parentSO != nullptr)
+			so = parentSO->getNativeHandle();
+
+		ScriptLight* nativeInstance = new (bs_alloc<ScriptLight>()) ScriptLight(managedInstance, so);
+	}
+
+	LightType ScriptLight::internal_getType(ScriptLight* thisPtr)
+	{
+		return thisPtr->getInternal()->getType();
+	}
+
+	void ScriptLight::internal_setType(ScriptLight* thisPtr, LightType type)
+	{
+		thisPtr->getInternal()->setType(type);
+	}
+
+	bool ScriptLight::internal_getCastsShadow(ScriptLight* thisPtr)
+	{
+		return thisPtr->getInternal()->getCastsShadow();
+	}
+
+	void ScriptLight::internal_setCastsShadow(ScriptLight* thisPtr, bool castsShadow)
+	{
+		thisPtr->getInternal()->setCastsShadow(castsShadow);
+	}
+
+	void ScriptLight::internal_getColor(ScriptLight* thisPtr, Color* color)
+	{
+		*color = thisPtr->getInternal()->getColor();
+	}
+
+	void ScriptLight::internal_setColor(ScriptLight* thisPtr, Color color)
+	{
+		thisPtr->getInternal()->setColor(color);
+	}
+
+	float ScriptLight::internal_getRange(ScriptLight* thisPtr)
+	{
+		return thisPtr->getInternal()->getRange();
+	}
+
+	void ScriptLight::internal_setRange(ScriptLight* thisPtr, float range)
+	{
+		thisPtr->getInternal()->setRange(range);
+	}
+
+	float ScriptLight::internal_getIntensity(ScriptLight* thisPtr)
+	{
+		return thisPtr->getInternal()->getIntensity();
+	}
+
+	void ScriptLight::internal_setIntensity(ScriptLight* thisPtr, float intensity)
+	{
+		thisPtr->getInternal()->setIntensity(intensity);
+	}
+
+	float ScriptLight::internal_getSpotAngle(ScriptLight* thisPtr)
+	{
+		return thisPtr->getInternal()->getSpotAngle().valueDegrees();
+	}
+
+	void ScriptLight::internal_setSpotAngle(ScriptLight* thisPtr, float spotAngle)
+	{
+		thisPtr->getInternal()->setSpotAngle(Degree(spotAngle));
+	}
+
+	float ScriptLight::internal_getSpotFalloffAngle(ScriptLight* thisPtr)
+	{
+		return thisPtr->getInternal()->getSpotFalloffAngle().valueDegrees();
+	}
+
+	void ScriptLight::internal_setSpotFalloffAngle(ScriptLight* thisPtr, float spotFalloffAngle)
+	{
+		thisPtr->getInternal()->setSpotFalloffAngle(Degree(spotFalloffAngle));
+	}
+
+	void ScriptLight::internal_getBounds(ScriptLight* thisPtr, Sphere* bounds)
+	{
+		*bounds = thisPtr->getInternal()->getBounds();
+	}
+
+	void ScriptLight::internal_updateTransform(ScriptLight* thisPtr, ScriptSceneObject* parent)
+	{
+		HSceneObject parentSO = parent->getNativeSceneObject();
+
+		if (!parentSO.isDestroyed())
+			thisPtr->getInternal()->_updateTransform(parentSO);
+	}
+
+	void ScriptLight::internal_onDestroy(ScriptLight* instance)
+	{
+		instance->destroy();
+	}
+
+	void ScriptLight::destroy()
+	{
+		if (mLight->isDestroyed())
+			return;
+
+		gSceneManager()._unregisterLight(mLight);
+		mLight->destroy();
+	}
+
+	void ScriptLight::_onManagedInstanceDeleted()
+	{
+		destroy();
+
+		ScriptObject::_onManagedInstanceDeleted();
+	}
 }

+ 1 - 0
TODO.txt

@@ -101,6 +101,7 @@ Rect3 has child structs (Vector3) which could be the reason. Be aware of other s
 Mono cannot marshal structures? Taken from their documentation:
  Internal calls do not provide support for marshalling structures. This means that any API calls that take a structure 
  (excluding the system types like int32, int64, etc) must be passed as a pointer, in C# this means passing the value as a "ref" or "out" parameter.
+ - This was further confirmed by one of the developers on a forum.
 
 Mono has problems with returning a struct from an internal C++ method. Returned value might end up being corrupted. It works weirdly as
 I am able (for example) return a Rect2 with no problems, but it doesn't work when returning a Degree struct. Returning the value as input