Przeglądaj źródła

Added light data types and components

Marko Pintera 10 lat temu
rodzic
commit
97f46875a9

+ 2 - 0
BansheeCore/Include/BsCorePrerequisites.h

@@ -169,6 +169,8 @@ namespace BansheeEngine
 	class Prefab;
 	class PrefabDiff;
 	class RendererMeshData;
+	class LightInternalCore;
+	class LightInternal;
 	// Asset import
 	class SpecificImporter;
 	class Importer;

+ 16 - 0
BansheeCore/Include/BsCoreRenderer.h

@@ -82,6 +82,22 @@ namespace BansheeEngine
 		 */
 		virtual void _notifyCameraRemoved(const CameraHandlerCore* camera) { }
 
+		/**
+		 * @brief	Called whenever a new light is created.
+		 *
+		 * @note	Core thread.
+		 *			Internal method.
+		 */
+		virtual void _notifyLightAdded(const LightInternalCore* light) { }
+
+		/**
+		 * @brief	Called whenever a light is destroyed.
+		 *
+		 * @note	Core thread.
+		 *			Internal method.
+		 */
+		virtual void _notifyLightRemoved(const LightInternalCore* light) { }
+
 		/**
 		 * @brief	Creates a new empty renderer mesh data.
 		 *

+ 6 - 0
BansheeEngine/BansheeEngine.vcxproj

@@ -245,6 +245,7 @@
     <ClCompile Include="Source\BsGUISlider.cpp" />
     <ClCompile Include="Source\BsGUISpace.cpp" />
     <ClCompile Include="Source\BsInputConfiguration.cpp" />
+    <ClCompile Include="Source\BsLight.cpp" />
     <ClCompile Include="Source\BsPlainText.cpp" />
     <ClCompile Include="Source\BsPlainTextImporter.cpp" />
     <ClCompile Include="Source\BsRenderableController.cpp" />
@@ -257,6 +258,7 @@
     <ClCompile Include="Source\BsShortcutKey.cpp" />
     <ClCompile Include="Source\BsShortcutManager.cpp" />
     <ClCompile Include="Source\BsVirtualInput.cpp" />
+    <ClCompile Include="Source\BsLightInternal.cpp" />
     <ClInclude Include="Include\BsApplication.h" />
     <ClInclude Include="Include\BsCameraHandler.h" />
     <ClInclude Include="Include\BsCameraHandlerRTTI.h" />
@@ -270,6 +272,10 @@
     <ClInclude Include="Include\BsGUIProgressBar.h" />
     <ClInclude Include="Include\BsGUISkinRTTI.h" />
     <ClInclude Include="Include\BsGUISlider.h" />
+    <ClInclude Include="Include\BsLight.h" />
+    <ClInclude Include="Include\BsLightInternal.h" />
+    <ClInclude Include="Include\BsLightInternalRTTI.h" />
+    <ClInclude Include="Include\BsLightRTTI.h" />
     <ClInclude Include="Include\BsPlainText.h" />
     <ClInclude Include="Include\BsPlainTextImporter.h" />
     <ClInclude Include="Include\BsPlainTextRTTI.h" />

+ 18 - 0
BansheeEngine/BansheeEngine.vcxproj.filters

@@ -335,6 +335,18 @@
     <ClInclude Include="Include\BsDropDownAreaPlacement.h">
       <Filter>Header Files\GUI</Filter>
     </ClInclude>
+    <ClInclude Include="Include\BsLightInternal.h">
+      <Filter>Header Files</Filter>
+    </ClInclude>
+    <ClInclude Include="Include\BsLightInternalRTTI.h">
+      <Filter>Header Files\RTTI</Filter>
+    </ClInclude>
+    <ClInclude Include="Include\BsLight.h">
+      <Filter>Header Files\Components</Filter>
+    </ClInclude>
+    <ClInclude Include="Include\BsLightRTTI.h">
+      <Filter>Header Files\RTTI</Filter>
+    </ClInclude>
   </ItemGroup>
   <ItemGroup>
     <ClCompile Include="Source\BsGUIElement.cpp">
@@ -580,5 +592,11 @@
     <ClCompile Include="Source\BsDropDownAreaPlacement.cpp">
       <Filter>Source Files\GUI</Filter>
     </ClCompile>
+    <ClCompile Include="Source\BsLightInternal.cpp">
+      <Filter>Source Files</Filter>
+    </ClCompile>
+    <ClCompile Include="Source\BsLight.cpp">
+      <Filter>Source Files\Components</Filter>
+    </ClCompile>
   </ItemGroup>
 </Project>

+ 73 - 0
BansheeEngine/Include/BsLight.h

@@ -0,0 +1,73 @@
+#pragma once
+
+#include "BsPrerequisites.h"
+#include "BsLightInternal.h"
+#include "BsComponent.h"
+
+namespace BansheeEngine 
+{
+	/**
+	 * @copydoc	LightInternal
+	 */
+    class BS_EXPORT Light : public Component
+    {
+    public:
+		Light(const HSceneObject& parent, LightType type = LightType::Point, Color color = Color::White, 
+			float luminousFlux = 100.0f, float range = 1.0f, bool castsShadows = false, Degree spotAngle = Degree(45));
+
+		virtual ~Light();
+
+		Vector3 getPosition() const { return mInternal->getPosition(); }
+		void setPosition(const Vector3& position) { mInternal->setPosition(position); }
+
+		Quaternion getRotation() const { return mInternal->getRotation(); }
+		void setRotation(const Quaternion& rotation) { mInternal->setRotation(rotation); }
+
+		LightType getType() const { return mInternal->getType(); }
+		void setType(LightType type) { mInternal->setType(type); }
+
+		bool getCastsShadow() const { return mInternal->getCastsShadow(); }
+		void setCastsShadow(bool castsShadow) { mInternal->setCastsShadow(castsShadow); }
+
+		Color getColor() const { return mInternal->getColor(); }
+		void setColor(const Color& color) { mInternal->setColor(color); }
+
+		float getRange() const { return mInternal->getRange(); }
+		void setRange(float range) { mInternal->setRange(range);; }
+
+		float getLuminousFlux() const { return mInternal->getLuminousFlux(); }
+		void setLuminousFlux(float luminousFlux) { mInternal->setLuminousFlux(luminousFlux); }
+
+		Degree getSpotAngle() const { return mInternal->getSpotAngle(); }
+		void setSpotAngle(const Degree& spotAngle) { mInternal->setSpotAngle(spotAngle); }
+
+		SPtr<LightInternal> _getInternal() const { return mInternal; }
+
+    protected:
+		mutable SPtr<LightInternal> mInternal;
+		mutable UINT32 mLastUpdateHash;
+
+		/************************************************************************/
+		/* 						COMPONENT OVERRIDES                      		*/
+		/************************************************************************/
+	protected:
+		friend class SceneObject;
+
+	public:
+		/**
+		 * @copydoc	Component::update
+		 */
+		virtual void update() override { }
+
+		/************************************************************************/
+		/* 								RTTI		                     		*/
+		/************************************************************************/
+	public:
+		friend class LightRTTI;
+		static RTTITypeBase* getRTTIStatic();
+		virtual RTTITypeBase* getRTTI() const;
+
+	protected:
+		Light() {} // Serialization only
+     };
+}

+ 141 - 0
BansheeEngine/Include/BsLightInternal.h

@@ -0,0 +1,141 @@
+#pragma once
+
+#include "BsPrerequisites.h"
+#include "BsIReflectable.h"
+#include "BsVector3.h"
+#include "BsQuaternion.h"
+#include "BsColor.h"
+#include "BsCoreObject.h"
+
+namespace BansheeEngine
+{
+	/**
+	 * @brief	Light types that determine how is light information parsed
+	 *			by the renderer and other systems.
+	 */
+	enum class LightType
+	{
+		Directional, 
+		Point, 
+		Spot
+	};
+
+	class BS_EXPORT LightInternalBase
+	{
+	public:
+		LightInternalBase();
+		LightInternalBase(LightType type, Color color,
+			float luminousFlux, float range, bool castsShadows, Degree spotAngle);
+
+		virtual ~LightInternalBase() { }
+
+		Vector3 getPosition() const { return mPosition; }
+		void setPosition(const Vector3& position) { mPosition = position; _markCoreDirty(); }
+
+		Quaternion getRotation() const { return mRotation; }
+		void setRotation(const Quaternion& rotation) { mRotation = rotation; _markCoreDirty(); }
+
+		LightType getType() const { return mType; }
+		void setType(LightType type) { mType = type; _markCoreDirty(); }
+
+		bool getCastsShadow() const { return mCastsShadows; }
+		void setCastsShadow(bool castsShadow) { mCastsShadows = castsShadow; _markCoreDirty(); }
+
+		Color getColor() const { return mColor; }
+		void setColor(const Color& color) { mColor = color; _markCoreDirty(); }
+
+		float getRange() const { return mRange; }
+		void setRange(float range) { mRange = range; _markCoreDirty(); }
+
+		float getLuminousFlux() const { return mLuminousFlux; }
+		void setLuminousFlux(float luminousFlux) { mLuminousFlux = luminousFlux; _markCoreDirty(); }
+
+		Degree getSpotAngle() const { return mSpotAngle; }
+		void setSpotAngle(const Degree& spotAngle) { mSpotAngle = spotAngle; _markCoreDirty(); }
+
+		/**
+		 * @copydoc	CoreObject::markCoreDirty
+		 */
+		virtual void _markCoreDirty() { }
+
+	protected:
+		Vector3 mPosition; /**< World space position. */
+		Quaternion mRotation; /**< World space rotation. */
+
+		LightType mType; /**< Type of light that determines how are the rest of the parameters interpreted. */
+		bool mCastsShadows; /**< Determines whether the light casts shadows. */
+		Color mColor; /**< Color of the light. */
+		float mRange; /**< Cut off range for the light when rendering. Visibly the light attenuation and intensity determines the range. */
+		float mLuminousFlux; /**< Intensity of the light source. */
+		Degree mSpotAngle; /**< Angle covered by a spot light. */
+	};
+
+	/**
+	 * @copydoc	LightInternalBase
+	 */
+	class BS_EXPORT LightInternalCore : public CoreObjectCore, public LightInternalBase
+	{
+	public:
+		~LightInternalCore();
+
+	protected:
+		friend class LightInternal;
+
+		LightInternalCore(LightType type, Color color,
+			float luminousFlux, float range, bool castsShadows, Degree spotAngle);
+
+		/**
+		 * @copydoc	CoreObjectCore::initialize
+		 */
+		void initialize() override;
+
+		/**
+		 * @copydoc	CoreObject::syncToCore
+		 */
+		void syncToCore(const CoreSyncData& data) override;
+	};
+
+	/**
+	 * @copydoc	CameraHandlerBase
+	 */
+	class BS_EXPORT LightInternal : public IReflectable, public CoreObject, public LightInternalBase
+	{
+	public:
+		SPtr<LightInternalCore> getCore() const;
+
+		static SPtr<LightInternal> create(LightType type = LightType::Point, Color color = Color::White,
+			float luminousFlux = 100.0f, float range = 1.0f, bool castsShadows = false, Degree spotAngle = Degree(45));
+
+	protected:
+		LightInternal(LightType type, Color color,
+			float luminousFlux, float range, bool castsShadows, Degree spotAngle);
+
+		/**
+		 * @copydoc	CoreObject::createCore
+		 */
+		SPtr<CoreObjectCore> createCore() const override;
+
+		/**
+		 * @copydoc	CoreObject::markCoreDirty
+		 */
+		void _markCoreDirty() override;
+
+		/**
+		 * @copydoc	CoreObject::syncToCore
+		 */
+		CoreSyncData syncToCore(FrameAlloc* allocator) override;
+
+		static SPtr<LightInternal> createEmpty();
+
+		/************************************************************************/
+		/* 								RTTI		                     		*/
+		/************************************************************************/
+	public:
+		friend class LightInternalRTTI;
+		static RTTITypeBase* getRTTIStatic();
+		virtual RTTITypeBase* getRTTI() const override;
+
+	protected:
+		LightInternal() {} // Serialization only
+	};
+}

+ 70 - 0
BansheeEngine/Include/BsLightInternalRTTI.h

@@ -0,0 +1,70 @@
+#pragma once
+
+#include "BsPrerequisites.h"
+#include "BsRTTIType.h"
+#include "BsLightInternal.h"
+
+namespace BansheeEngine
+{
+	class BS_EXPORT LightInternalRTTI : public RTTIType <LightInternal, IReflectable, LightInternalRTTI>
+	{
+	private:
+		Vector3& getPosition(LightInternal* obj) { return obj->mPosition; }
+		void setPosition(LightInternal* obj, Vector3& position) { obj->mPosition = position; }
+
+		Quaternion& getRotation(LightInternal* obj) { return obj->mRotation; }
+		void setRotation(LightInternal* obj, Quaternion& rotation) { obj->mRotation = rotation; }
+
+		LightType& getType(LightInternal* obj) { return obj->mType; }
+		void setType(LightInternal* obj, LightType& type) { obj->mType = type; }
+
+		bool& getCastsShadow(LightInternal* obj) { return obj->mCastsShadows; }
+		void setCastsShadow(LightInternal* obj, bool& castsShadow) { obj->mCastsShadows = castsShadow; }
+
+		Color& getColor(LightInternal* obj) { return obj->mColor; }
+		void setColor(LightInternal* obj, Color& color) { obj->mColor = color; }
+
+		float& getRange(LightInternal* obj) { return obj->mRange; }
+		void setRange(LightInternal* obj, float& range) { obj->mRange = range; }
+
+		float& getLuminousFlux(LightInternal* obj) { return obj->mLuminousFlux; }
+		void setLuminousFlux(LightInternal* obj, float& luminousFlux) { obj->mLuminousFlux = luminousFlux; }
+
+		Degree& getSpotAngle(LightInternal* obj) { return obj->mSpotAngle; }
+		void setSpotAngle(LightInternal* obj, Degree& spotAngle) { obj->mSpotAngle = spotAngle; }
+	public:
+		LightInternalRTTI()
+		{
+			addPlainField("mPosition", 0, &LightInternalRTTI::getPosition, &LightInternalRTTI::setPosition);
+			addPlainField("mRotation", 1, &LightInternalRTTI::getRotation, &LightInternalRTTI::setRotation);
+			addPlainField("mType", 2, &LightInternalRTTI::getType, &LightInternalRTTI::setType);
+			addPlainField("mCastsShadow", 3, &LightInternalRTTI::getCastsShadow, &LightInternalRTTI::setCastsShadow);
+			addPlainField("mColor", 4, &LightInternalRTTI::getColor, &LightInternalRTTI::setColor);
+			addPlainField("mRange", 5, &LightInternalRTTI::getRange, &LightInternalRTTI::setRange);
+			addPlainField("mLuminousFlux", 6, &LightInternalRTTI::getLuminousFlux, &LightInternalRTTI::setLuminousFlux);
+			addPlainField("mSpotAngle", 7, &LightInternalRTTI::getSpotAngle, &LightInternalRTTI::setSpotAngle);
+		}
+
+		virtual void onDeserializationEnded(IReflectable* obj) override
+		{
+			LightInternal* lightInternal = static_cast<LightInternal*>(obj);
+			lightInternal->initialize();
+		}
+
+		virtual const String& getRTTIName() override
+		{
+			static String name = "LightInternal";
+			return name;
+		}
+
+		virtual UINT32 getRTTIId() override
+		{
+			return TID_LightInternal;
+		}
+
+		virtual std::shared_ptr<IReflectable> newRTTIObject() override
+		{
+			return LightInternal::createEmpty();
+		}
+	};
+}

+ 38 - 0
BansheeEngine/Include/BsLightRTTI.h

@@ -0,0 +1,38 @@
+#pragma once
+
+#include "BsPrerequisites.h"
+#include "BsRTTIType.h"
+#include "BsLight.h"
+#include "BsGameObjectRTTI.h"
+
+namespace BansheeEngine
+{
+	class BS_EXPORT LightRTTI : public RTTIType <Light, Component, LightRTTI>
+	{
+	private:
+		SPtr<LightInternal> getInternal(Light* obj) { return obj->mInternal; }
+		void setInternal(Light* obj, SPtr<LightInternal> val) { obj->mInternal = val; }
+
+	public:
+		LightRTTI()
+		{
+			addReflectablePtrField("mInternal", 0, &LightRTTI::getInternal, &LightRTTI::setInternal);
+		}
+
+		virtual const String& getRTTIName() override
+		{
+			static String name = "Light";
+			return name;
+		}
+
+		virtual UINT32 getRTTIId() override
+		{
+			return TID_Light;
+		}
+
+		virtual std::shared_ptr<IReflectable> newRTTIObject() override
+		{
+			return GameObjectRTTI::createGameObject<Light>();
+		}
+	};
+}

+ 4 - 1
BansheeEngine/Include/BsPrerequisites.h

@@ -104,6 +104,7 @@ namespace BansheeEngine
 	class Overlay;
 	class Renderable;
 	class Camera;
+	class Light;
 
 	typedef std::shared_ptr<TextSprite> TextSpritePtr;
 	typedef std::shared_ptr<SpriteTexture> SpriteTexturePtr;
@@ -148,6 +149,8 @@ namespace BansheeEngine
 		TID_ScriptCodeImportOptions = 30007,
 		TID_GUIElementStyle = 30008,
 		TID_GUISkin = 30009,
-		TID_GUISkinEntry = 30010
+		TID_GUISkinEntry = 30010,
+		TID_LightInternal = 30011,
+		TID_Light = 30012
 	};
 }

+ 29 - 0
BansheeEngine/Source/BsLight.cpp

@@ -0,0 +1,29 @@
+#include "BsLight.h"
+#include "BsLightRTTI.h"
+
+namespace BansheeEngine
+{
+	Light::Light(const HSceneObject& parent, LightType type, Color color,
+		float luminousFlux, float range, bool castsShadows, Degree spotAngle)
+		: Component(parent), mLastUpdateHash(std::numeric_limits<UINT32>::max())
+	{
+		mInternal = LightInternal::create(type, color, luminousFlux, range, castsShadows, spotAngle);
+
+		setName("Light");
+	}
+
+	Light::~Light()
+	{
+		mInternal->destroy();
+	}
+	
+	RTTITypeBase* Light::getRTTIStatic()
+	{
+		return LightRTTI::instance();
+	}
+
+	RTTITypeBase* Light::getRTTI() const
+	{
+		return Light::getRTTIStatic();
+	}
+}

+ 141 - 0
BansheeEngine/Source/BsLightInternal.cpp

@@ -0,0 +1,141 @@
+#include "BsLightInternal.h"
+#include "BsRendererManager.h"
+#include "BsRenderer.h"
+#include "BsFrameAlloc.h"
+#include "BsLightInternalRTTI.h"
+
+namespace BansheeEngine
+{
+	LightInternalBase::LightInternalBase()
+		:mType(LightType::Point), mCastsShadows(false), mRange(10.0f),
+		mLuminousFlux(100.0f), mSpotAngle(45), mColor(Color::White)
+	{
+		
+	}
+
+	LightInternalBase::LightInternalBase(LightType type, Color color,
+		float luminousFlux, float range, bool castsShadows, Degree spotAngle)
+		:mType(type), mCastsShadows(castsShadows), mRange(range),
+		mLuminousFlux(luminousFlux), mSpotAngle(spotAngle), mColor(color)
+	{
+		
+	}
+
+	LightInternalCore::~LightInternalCore()
+	{
+		RendererManager::instance().getActive()->_notifyLightRemoved(this);
+	}
+
+	LightInternalCore::LightInternalCore(LightType type, Color color,
+		float luminousFlux, float range, bool castsShadows, Degree spotAngle)
+		:LightInternalBase(type, color, luminousFlux, range, castsShadows, spotAngle)
+	{
+
+	}
+
+	void LightInternalCore::initialize()
+	{
+		RendererManager::instance().getActive()->_notifyLightAdded(this);
+
+		CoreObjectCore::initialize();
+	}
+
+	void LightInternalCore::syncToCore(const CoreSyncData& data)
+	{
+		char* dataPtr = (char*)data.getBuffer();
+
+		dataPtr = rttiReadElem(mPosition, dataPtr);
+		dataPtr = rttiReadElem(mRotation, dataPtr);
+		dataPtr = rttiReadElem(mType, dataPtr);
+		dataPtr = rttiReadElem(mCastsShadows, dataPtr);
+		dataPtr = rttiReadElem(mColor, dataPtr);
+		dataPtr = rttiReadElem(mRange, dataPtr);
+		dataPtr = rttiReadElem(mLuminousFlux, dataPtr);
+		dataPtr = rttiReadElem(mSpotAngle, dataPtr);
+	}
+
+	LightInternal::LightInternal(LightType type, Color color,
+		float luminousFlux, float range, bool castsShadows, Degree spotAngle)
+		:LightInternalBase(type, color, luminousFlux, range, castsShadows, spotAngle)
+	{
+
+	}
+
+	SPtr<LightInternalCore> LightInternal::getCore() const
+	{
+		return std::static_pointer_cast<LightInternalCore>(mCoreSpecific);
+	}
+
+	SPtr<LightInternal> LightInternal::create(LightType type, Color color,
+		float luminousFlux, float range, bool castsShadows, Degree spotAngle)
+	{
+		LightInternal* handler = new (bs_alloc<LightInternal>()) 
+			LightInternal(type, color, luminousFlux, range, castsShadows, spotAngle);
+		SPtr<LightInternal> handlerPtr = bs_core_ptr<LightInternal, GenAlloc>(handler);
+		handlerPtr->_setThisPtr(handlerPtr);
+		handlerPtr->initialize();
+
+		return handlerPtr;
+	}
+
+	SPtr<LightInternal> LightInternal::createEmpty()
+	{
+		LightInternal* handler = new (bs_alloc<LightInternal>()) LightInternal();
+		SPtr<LightInternal> handlerPtr = bs_core_ptr<LightInternal, GenAlloc>(handler);
+		handlerPtr->_setThisPtr(handlerPtr);
+
+		return handlerPtr;
+	}
+
+	SPtr<CoreObjectCore> LightInternal::createCore() const
+	{
+		LightInternalCore* handler = new (bs_alloc<LightInternalCore>()) 
+			LightInternalCore(mType, mColor, mLuminousFlux, mRange, mCastsShadows, mSpotAngle);
+		SPtr<LightInternalCore> handlerPtr = bs_shared_ptr<LightInternalCore, GenAlloc>(handler);
+		handlerPtr->_setThisPtr(handlerPtr);
+
+		return handlerPtr;
+	}
+
+	CoreSyncData LightInternal::syncToCore(FrameAlloc* allocator)
+	{
+		UINT32 size = 0;
+		size += rttiGetElemSize(mPosition);
+		size += rttiGetElemSize(mRotation);
+		size += rttiGetElemSize(mType);
+		size += rttiGetElemSize(mCastsShadows);
+		size += rttiGetElemSize(mColor);
+		size += rttiGetElemSize(mRange);
+		size += rttiGetElemSize(mLuminousFlux);
+		size += rttiGetElemSize(mSpotAngle);
+
+		UINT8* buffer = allocator->alloc(size);
+
+		char* dataPtr = (char*)buffer;
+		dataPtr = rttiWriteElem(mPosition, dataPtr);
+		dataPtr = rttiWriteElem(mRotation, dataPtr);
+		dataPtr = rttiWriteElem(mType, dataPtr);
+		dataPtr = rttiWriteElem(mCastsShadows, dataPtr);
+		dataPtr = rttiWriteElem(mColor, dataPtr);
+		dataPtr = rttiWriteElem(mRange, dataPtr);
+		dataPtr = rttiWriteElem(mLuminousFlux, dataPtr);
+		dataPtr = rttiWriteElem(mSpotAngle, dataPtr);
+
+		return CoreSyncData(buffer, size);
+	}
+
+	void LightInternal::_markCoreDirty()
+	{
+		markCoreDirty();
+	}
+
+	RTTITypeBase* LightInternal::getRTTIStatic()
+	{
+		return LightInternalRTTI::instance();
+	}
+
+	RTTITypeBase* LightInternal::getRTTI() const
+	{
+		return LightInternal::getRTTIStatic();
+	}
+}

+ 10 - 0
BansheeRenderer/Include/BsBansheeRenderer.h

@@ -85,6 +85,16 @@ namespace BansheeEngine
 		 */
 		void _notifyCameraRemoved(const CameraHandlerCore* camera) override;
 
+		/**
+		 * @copydoc	Renderer::_notifyLightAdded
+		 */
+		void _notifyLightAdded(const LightInternalCore* light) override;
+
+		/**
+		 * @copydoc	Renderer::_notifyLightRemoved
+		 */
+		void _notifyLightRemoved(const LightInternalCore* light) override;
+
 		/**
 		 * @copydoc	Renderer::_notifyRenderableAdded
 		 */

+ 10 - 0
BansheeRenderer/Source/BsBansheeRenderer.cpp

@@ -148,6 +148,16 @@ namespace BansheeEngine
 		mWorldBounds[renderableId] = renderable->getBounds();
 	}
 
+	void BansheeRenderer::_notifyLightAdded(const LightInternalCore* light)
+	{
+		// TODO
+	}
+
+	void BansheeRenderer::_notifyLightRemoved(const LightInternalCore* light)
+	{
+		// TODO
+	}
+
 	void BansheeRenderer::_notifyCameraAdded(const CameraHandlerCore* camera)
 	{
 		CameraData& camData = mCameraData[camera];

+ 122 - 0
MBansheeEngine/Light.cs

@@ -0,0 +1,122 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Runtime.CompilerServices;
+using System.Text;
+
+namespace BansheeEngine
+{
+    public class Light : Component
+    {
+        private LightInternal internalLight;
+
+        [SerializeField]
+        private SerializableData serializableData = new SerializableData();
+
+        internal LightInternal Internal
+        {
+            get { return internalLight; }
+        }
+
+        internal Vector3 Position
+        {
+            get { return internalLight.Position; }
+            set { internalLight.Position = value; serializableData.position = value; }
+        }
+
+        internal Quaternion Rotation
+        {
+            get { return internalLight.Rotation; }
+            set { internalLight.Rotation = value; serializableData.rotation = value; }
+        }
+
+        internal LightType Type
+        {
+            get { return internalLight.Type; }
+            set { internalLight.Type = value; serializableData.type = value; }
+        }
+
+        internal Color Color
+        {
+            get { return internalLight.Color; }
+            set { internalLight.Color = value; serializableData.color = value; }
+        }
+
+        internal float Range
+        {
+            get { return internalLight.Range; }
+            set { internalLight.Range = value; serializableData.range = value; }
+        }
+
+        internal float LuminousFlux
+        {
+            get { return internalLight.LuminousFlux; }
+            set { internalLight.LuminousFlux = value; serializableData.luminousFlux = value; }
+        }
+
+        internal Degree SpotAngle
+        {
+            get { return internalLight.SpotAngle; }
+            set { internalLight.SpotAngle = value; serializableData.spotAngle = value; }
+        }
+
+        internal bool CastsShadow
+        {
+            get { return internalLight.CastsShadow; }
+            set { internalLight.CastsShadow = value; serializableData.castShadows = value; }
+        }
+
+        private void OnInitialize()
+        {
+            serializableData.position = Vector3.zero;
+            serializableData.rotation = Quaternion.identity;
+            serializableData.color = Color.White;
+            serializableData.spotAngle = new Degree(45);
+            serializableData.range = 10.0f;
+            serializableData.luminousFlux = 100.0f;
+            serializableData.type = LightType.Point;
+            serializableData.castShadows = false;
+        }
+
+        private void OnReset()
+        {
+            if (internalLight != null)
+                internalLight.OnDestroy();
+
+            internalLight = new LightInternal(SceneObject);
+
+            // Restore saved values after reset
+            internalLight.Position = serializableData.position;
+            internalLight.Rotation = serializableData.rotation;
+            internalLight.Color = serializableData.color;
+            internalLight.SpotAngle = serializableData.spotAngle;
+            internalLight.Range = serializableData.range;
+            internalLight.LuminousFlux = serializableData.luminousFlux;
+            internalLight.Type = serializableData.type;
+            internalLight.CastsShadow = serializableData.castShadows;
+        }
+
+        private void Update()
+        {
+            
+        }
+
+        private void OnDestroy()
+        {
+            internalLight.OnDestroy();
+        }
+
+        [SerializeObject]
+        private struct SerializableData
+        {
+            public Vector3 position;
+            public Quaternion rotation;
+            public Color color;
+            public Degree spotAngle;
+            public float range;
+            public float luminousFlux;
+            public LightType type;
+            public bool castShadows;
+        }
+    }
+}

+ 118 - 0
MBansheeEngine/LightInternal.cs

@@ -0,0 +1,118 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Runtime.CompilerServices;
+using System.Text;
+
+namespace BansheeEngine
+{
+    // Don't reorder, used by native code
+    public enum LightType
+    {
+        Directional, Point, Light
+    }
+
+    internal class LightInternal : ScriptObject
+    {
+        internal Vector3 Position
+        {
+            get { return Internal_GetPosition(mCachedPtr); }
+            set { Internal_SetPosition(mCachedPtr, value); }
+        }
+
+        internal Quaternion Rotation
+        {
+            get { return Internal_GetRotation(mCachedPtr); }
+            set { Internal_SetRotation(mCachedPtr, value); }
+        }
+
+        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 LuminousFlux
+        {
+            get { return Internal_GetLuminousFlux(mCachedPtr); }
+            set { Internal_SetLuminousFlux(mCachedPtr, value); }
+        }
+
+        internal Degree SpotAngle
+        {
+            get { return Internal_GetSpotAngle(mCachedPtr); }
+            set { Internal_SetSpotAngle(mCachedPtr, value.Degrees); }
+        }
+
+        internal bool CastsShadow
+        {
+            get { return Internal_GetCastsShadow(mCachedPtr); }
+            set { Internal_SetCastsShadow(mCachedPtr, value); }
+        }
+
+        public LightInternal(SceneObject sceneObject)
+        {
+            IntPtr sceneObjPtr = IntPtr.Zero;
+            if (sceneObject != null)
+                sceneObjPtr = sceneObject.GetCachedPtr();
+
+            Internal_Create(this, sceneObjPtr);
+        }
+
+        internal void OnDestroy()
+        {
+            Internal_OnDestroy(mCachedPtr);
+        }
+
+        [MethodImpl(MethodImplOptions.InternalCall)]
+        private static extern void Internal_Create(LightInternal instance, IntPtr parentSO);
+
+        [MethodImpl(MethodImplOptions.InternalCall)]
+        private static extern Vector3 Internal_GetPosition(IntPtr instance);
+        [MethodImpl(MethodImplOptions.InternalCall)]
+        private static extern void Internal_SetPosition(IntPtr instance, Vector3 value);
+        [MethodImpl(MethodImplOptions.InternalCall)]
+        private static extern Quaternion Internal_GetRotation(IntPtr instance);
+        [MethodImpl(MethodImplOptions.InternalCall)]
+        private static extern void Internal_SetRotation(IntPtr instance, Quaternion value);
+        [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_GetLuminousFlux(IntPtr instance);
+        [MethodImpl(MethodImplOptions.InternalCall)]
+        private static extern void Internal_SetLuminousFlux(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 void Internal_OnDestroy(IntPtr thisPtr);
+    }
+}

+ 2 - 0
MBansheeEngine/MBansheeEngine.csproj

@@ -83,6 +83,8 @@
     <Compile Include="HideInInspector.cs" />
     <Compile Include="Input.cs" />
     <Compile Include="InputConfiguration.cs" />
+    <Compile Include="Light.cs" />
+    <Compile Include="LightInternal.cs" />
     <Compile Include="LocString.cs" />
     <Compile Include="ManagedResource.cs" />
     <Compile Include="Material.cs" />

+ 55 - 0
SBansheeEngine/Include/BsScriptLightInternal.h

@@ -0,0 +1,55 @@
+#pragma once
+
+#include "BsScriptEnginePrerequisites.h"
+#include "BsScriptObject.h"
+#include "BsVector3.h"
+#include "BsQuaternion.h"
+#include "BsDegree.h"
+#include "BsColor.h"
+#include "BsLightInternal.h"
+
+namespace BansheeEngine
+{
+	class BS_SCR_BE_EXPORT ScriptLightInternal : public ScriptObject <ScriptLightInternal>
+	{
+	public:
+		SCRIPT_OBJ(ENGINE_ASSEMBLY, "BansheeEngine", "LightInternal")
+
+		SPtr<LightInternal> getInternal() const { return mLightInternal; }
+
+	private:
+		ScriptLightInternal(MonoObject* managedInstance, const HSceneObject& parentSO);
+		~ScriptLightInternal();
+
+		static void internal_create(MonoObject* managedInstance, ScriptSceneObject* parentSO);
+
+		static Vector3 internal_getPosition(ScriptLightInternal* thisPtr);
+		static void internal_setPosition(ScriptLightInternal* thisPtr, Vector3 position);
+
+		static Quaternion internal_getRotation(ScriptLightInternal* thisPtr);
+		static void internal_setRotation(ScriptLightInternal* thisPtr, Quaternion rotation);
+
+		static LightType internal_getType(ScriptLightInternal* thisPtr);
+		static void internal_setType(ScriptLightInternal* thisPtr, LightType type);
+
+		static bool internal_getCastsShadow(ScriptLightInternal* thisPtr);
+		static void internal_setCastsShadow(ScriptLightInternal* thisPtr, bool castsShadow);
+
+		static Color internal_getColor(ScriptLightInternal* thisPtr);
+		static void internal_setColor(ScriptLightInternal* thisPtr, Color color);
+
+		static float internal_getRange(ScriptLightInternal* thisPtr);
+		static void internal_setRange(ScriptLightInternal* thisPtr, float range);
+
+		static float internal_getLuminousFlux(ScriptLightInternal* thisPtr);
+		static void internal_setLuminousFlux(ScriptLightInternal* thisPtr, float luminousFlux);
+
+		static Degree internal_getSpotAngle(ScriptLightInternal* thisPtr);
+		static void internal_setSpotAngle(ScriptLightInternal* thisPtr, Degree spotAngle);
+
+		static void internal_onDestroy(ScriptLightInternal* instance);
+
+		SPtr<LightInternal> mLightInternal;
+		UINT32 mLastUpdateHash;
+	};
+}

+ 2 - 0
SBansheeEngine/SBansheeEngine.vcxproj

@@ -286,6 +286,7 @@
     <ClInclude Include="Include\BsScriptHString.h" />
     <ClInclude Include="Include\BsScriptInput.h" />
     <ClInclude Include="Include\BsScriptInputConfiguration.h" />
+    <ClInclude Include="Include\BsScriptLightInternal.h" />
     <ClInclude Include="Include\BsScriptMacros.h" />
     <ClInclude Include="Include\BsScriptManagedResource.h" />
     <ClInclude Include="Include\BsScriptMaterial.h" />
@@ -372,6 +373,7 @@
     <ClCompile Include="Source\BsScriptGUIInputBox.cpp" />
     <ClCompile Include="Source\BsScriptInput.cpp" />
     <ClCompile Include="Source\BsScriptInputConfiguration.cpp" />
+    <ClCompile Include="Source\BsScriptLightInternal.cpp" />
     <ClCompile Include="Source\BsScriptManagedResource.cpp" />
     <ClCompile Include="Source\BsScriptMaterial.cpp" />
     <ClCompile Include="Source\BsScriptMesh.cpp" />

+ 6 - 0
SBansheeEngine/SBansheeEngine.vcxproj.filters

@@ -324,6 +324,9 @@
     <ClInclude Include="Include\BsScriptScene.h">
       <Filter>Header Files</Filter>
     </ClInclude>
+    <ClInclude Include="Include\BsScriptLightInternal.h">
+      <Filter>Header Files</Filter>
+    </ClInclude>
   </ItemGroup>
   <ItemGroup>
     <ClCompile Include="Source\BsScriptTexture2D.cpp">
@@ -584,5 +587,8 @@
     <ClCompile Include="Source\BsScriptScene.cpp">
       <Filter>Source Files</Filter>
     </ClCompile>
+    <ClCompile Include="Source\BsScriptLightInternal.cpp">
+      <Filter>Source Files</Filter>
+    </ClCompile>
   </ItemGroup>
 </Project>

+ 134 - 0
SBansheeEngine/Source/BsScriptLightInternal.cpp

@@ -0,0 +1,134 @@
+#include "BsScriptLightInternal.h"
+#include "BsScriptSceneObject.h"
+#include "BsSceneObject.h"
+
+namespace BansheeEngine
+{
+	ScriptLightInternal::ScriptLightInternal(MonoObject* managedInstance, const HSceneObject& parentSO)
+		:ScriptObject(managedInstance), mLightInternal(nullptr), mLastUpdateHash(0)
+	{
+		mLightInternal = LightInternal::create();
+	}
+
+	ScriptLightInternal::~ScriptLightInternal()
+	{
+
+	}
+
+	void ScriptLightInternal::initRuntimeData()
+	{
+		metaData.scriptClass->addInternalCall("Internal_Create", &ScriptLightInternal::internal_create);
+
+		metaData.scriptClass->addInternalCall("Internal_GetPosition", &ScriptLightInternal::internal_getPosition);
+		metaData.scriptClass->addInternalCall("Internal_SetPosition", &ScriptLightInternal::internal_setPosition);
+		metaData.scriptClass->addInternalCall("Internal_GetRotation", &ScriptLightInternal::internal_getRotation);
+		metaData.scriptClass->addInternalCall("Internal_SetRotation", &ScriptLightInternal::internal_setRotation);
+		metaData.scriptClass->addInternalCall("Internal_GetType", &ScriptLightInternal::internal_getType);
+		metaData.scriptClass->addInternalCall("Internal_SetType", &ScriptLightInternal::internal_setType);
+		metaData.scriptClass->addInternalCall("Internal_GetCastsShadow", &ScriptLightInternal::internal_getCastsShadow);
+		metaData.scriptClass->addInternalCall("Internal_SetCastsShadow", &ScriptLightInternal::internal_setCastsShadow);
+		metaData.scriptClass->addInternalCall("Internal_GetColor", &ScriptLightInternal::internal_getColor);
+		metaData.scriptClass->addInternalCall("Internal_SetColor", &ScriptLightInternal::internal_setColor);
+		metaData.scriptClass->addInternalCall("Internal_GetRange", &ScriptLightInternal::internal_getRange);
+		metaData.scriptClass->addInternalCall("Internal_SetRange", &ScriptLightInternal::internal_setRange);
+		metaData.scriptClass->addInternalCall("Internal_GetLuminousFlux", &ScriptLightInternal::internal_getLuminousFlux);
+		metaData.scriptClass->addInternalCall("Internal_SetLuminousFlux", &ScriptLightInternal::internal_setLuminousFlux);
+		metaData.scriptClass->addInternalCall("Internal_GetSpotAngle", &ScriptLightInternal::internal_getSpotAngle);
+		metaData.scriptClass->addInternalCall("Internal_SetSpotAngle", &ScriptLightInternal::internal_setSpotAngle);
+		metaData.scriptClass->addInternalCall("Internal_OnDestroy", &ScriptLightInternal::internal_onDestroy);
+	}
+
+	void ScriptLightInternal::internal_create(MonoObject* managedInstance, ScriptSceneObject* parentSO)
+	{
+		HSceneObject so;
+		if (parentSO != nullptr)
+			so = parentSO->getNativeHandle();
+
+		ScriptLightInternal* nativeInstance = new (bs_alloc<ScriptLightInternal>()) ScriptLightInternal(managedInstance, so);
+	}
+
+	Vector3 ScriptLightInternal::internal_getPosition(ScriptLightInternal* thisPtr)
+	{
+		return thisPtr->getInternal()->getPosition();
+	}
+
+	void ScriptLightInternal::internal_setPosition(ScriptLightInternal* thisPtr, Vector3 position)
+	{
+		thisPtr->getInternal()->setPosition(position);
+	}
+
+	Quaternion ScriptLightInternal::internal_getRotation(ScriptLightInternal* thisPtr)
+	{
+		return thisPtr->getInternal()->getRotation();
+	}
+
+	void ScriptLightInternal::internal_setRotation(ScriptLightInternal* thisPtr, Quaternion rotation)
+	{
+		thisPtr->getInternal()->setRotation(rotation);
+	}
+
+	LightType ScriptLightInternal::internal_getType(ScriptLightInternal* thisPtr)
+	{
+		return thisPtr->getInternal()->getType();
+	}
+
+	void ScriptLightInternal::internal_setType(ScriptLightInternal* thisPtr, LightType type)
+	{
+		thisPtr->getInternal()->setType(type);
+	}
+
+	bool ScriptLightInternal::internal_getCastsShadow(ScriptLightInternal* thisPtr)
+	{
+		return thisPtr->getInternal()->getCastsShadow();
+	}
+
+	void ScriptLightInternal::internal_setCastsShadow(ScriptLightInternal* thisPtr, bool castsShadow)
+	{
+		thisPtr->getInternal()->setCastsShadow(castsShadow);
+	}
+
+	Color ScriptLightInternal::internal_getColor(ScriptLightInternal* thisPtr)
+	{
+		return thisPtr->getInternal()->getColor();
+	}
+
+	void ScriptLightInternal::internal_setColor(ScriptLightInternal* thisPtr, Color color)
+	{
+		thisPtr->getInternal()->setColor(color);
+	}
+
+	float ScriptLightInternal::internal_getRange(ScriptLightInternal* thisPtr)
+	{
+		return thisPtr->getInternal()->getRange();
+	}
+
+	void ScriptLightInternal::internal_setRange(ScriptLightInternal* thisPtr, float range)
+	{
+		thisPtr->getInternal()->setRange(range);
+	}
+
+	float ScriptLightInternal::internal_getLuminousFlux(ScriptLightInternal* thisPtr)
+	{
+		return thisPtr->getInternal()->getLuminousFlux();
+	}
+
+	void ScriptLightInternal::internal_setLuminousFlux(ScriptLightInternal* thisPtr, float luminousFlux)
+	{
+		thisPtr->getInternal()->setLuminousFlux(luminousFlux);
+	}
+
+	Degree ScriptLightInternal::internal_getSpotAngle(ScriptLightInternal* thisPtr)
+	{
+		return thisPtr->getInternal()->getSpotAngle();
+	}
+
+	void ScriptLightInternal::internal_setSpotAngle(ScriptLightInternal* thisPtr, Degree spotAngle)
+	{
+		thisPtr->getInternal()->setSpotAngle(spotAngle);
+	}
+
+	void ScriptLightInternal::internal_onDestroy(ScriptLightInternal* instance)
+	{
+		instance->getInternal()->destroy();
+	}
+}

+ 0 - 1
TODO.txt

@@ -61,7 +61,6 @@ Crash in DefaultHandleManager.PreInput when just flying around the scene while h
 
 After undocking ProjectWindow the auto-scroll seems to be stuck in up position
 When selecting an gizmo icon the selection seems delayed and its gizmos flash for a frame before hiding (Can't reproduce atm but I saw it)
-Main window resize areas don't seem to be set up or work
 Decent looking default layout
 
 Fix handles

+ 4 - 0
TODOExperimentation.txt

@@ -9,6 +9,10 @@ Add basic light type components and their core thread representations
  - Spot - angle, direction, position
  - Point - range (or derive that from flux?), position
 
+Document all Light stutff
+Light bounding box
+Need to update light handler when parent component moves/rotates
+
 Load up and set up a test-bed with Ribek's scene
 
 Create a basic GBuffer - albedo, normal, depth