Explorar el Código

Refactored Material serialization so it uses the new MaterialParams object in order to have simpler code
Material parameters are now preserved when shader is changed or updated
Some fixes in binary serialization when deserializing an object that contains missing types

BearishSun hace 10 años
padre
commit
786a0e871f

+ 1 - 0
BansheeCore/BansheeCore.vcxproj

@@ -300,6 +300,7 @@
     <ClInclude Include="Include\BsHString.h" />
     <ClInclude Include="Include\BsIconUtility.h" />
     <ClInclude Include="Include\BsMaterialParams.h" />
+    <ClInclude Include="Include\BsMaterialParamsRTTI.h" />
     <ClInclude Include="Include\BsMeshImportOptions.h" />
     <ClInclude Include="Include\BsMeshImportOptionsRTTI.h" />
     <ClInclude Include="Include\BsMeshUtility.h" />

+ 3 - 0
BansheeCore/BansheeCore.vcxproj.filters

@@ -590,6 +590,9 @@
     <ClInclude Include="Include\BsMaterialParams.h">
       <Filter>Header Files\Material</Filter>
     </ClInclude>
+    <ClInclude Include="Include\BsMaterialParamsRTTI.h">
+      <Filter>Header Files\RTTI</Filter>
+    </ClInclude>
   </ItemGroup>
   <ItemGroup>
     <ClCompile Include="Source\BsCoreApplication.cpp">

+ 4 - 0
BansheeCore/Include/BsCommonTypes.h

@@ -462,4 +462,8 @@ namespace BansheeEngine
 	};
 
 	typedef Map<String, String> NameValuePairList;
+
+	/** @cond SPECIALIZATIONS */
+	BS_ALLOW_MEMCPY_SERIALIZATION(TextureSurface);
+	/** @endcond */
 }

+ 4 - 13
BansheeCore/Include/BsCorePrerequisites.h

@@ -345,28 +345,15 @@ namespace BansheeEngine
 		TID_Technique = 1015,
 		TID_Shader = 1016,
 		TID_Material = 1017,
-		TID_MaterialParams = 1018,
-		TID_FloatParamKVP = 1019,
-		TID_MaterialTexParamKVP = 1020,
 		TID_SamplerState = 1021,
-		TID_SamplerStateParamKVP = 1022,
 		TID_BlendState = 1023,
 		TID_RasterizerState = 1024,
 		TID_DepthStencilState = 1025,
-		TID_MaterialParamFloat = 1026,
-		TID_MaterialParamVec2 = 1027,
-		TID_MaterialParamVec3 = 1028,
-		TID_MaterialParamVec4 = 1029,
-		TID_MaterialParamMat3 = 1030,
-		TID_MaterialParamMat4 = 1031,
-		TID_MaterialParamTexture = 1032,
-		TID_MaterialParamSamplerState = 1033,
 		TID_BLEND_STATE_DESC = 1034,
 		TID_SHADER_DATA_PARAM_DESC = 1035,
 		TID_SHADER_OBJECT_PARAM_DESC = 1036,
 		TID_SHADER_PARAM_BLOCK_DESC = 1047,
 		TID_ImportOptions = 1048,
-		TID_MaterialParamStruct = 1050,
 		TID_Font = 1051,
 		TID_FONT_DESC = 1052,
 		TID_CHAR_DESC = 1053,
@@ -400,6 +387,10 @@ namespace BansheeEngine
 		TID_LocalizedStringData = 1085,
 		TID_MaterialParamColor = 1086,
 		TID_WeakResourceHandle = 1087,
+		TID_TextureParamData = 1088,
+		TID_StructParamData = 1089,
+		TID_MaterialParams = 1090,
+		TID_MaterialRTTIParam = 1091
 	};
 }
 

+ 415 - 402
BansheeCore/Include/BsGpuParams.h

@@ -1,403 +1,416 @@
-#pragma once
-
-#include "BsCorePrerequisites.h"
-#include "BsGpuParam.h"
-#include "BsCoreObject.h"
-#include "BsIResourceListener.h"
-
-namespace BansheeEngine
-{
-	/**
-	 * @brief	Stores information needed for binding a texture to the pipeline.
-	 */
-	struct BoundTextureInfo
-	{
-		BoundTextureInfo()
-			:isLoadStore(false)
-		{ }
-
-		bool isLoadStore;
-		TextureSurface surface;
-	};
-
-	/**
-	 * @brief	Helper structure whose specializations convert an engine data type into a GPU program data parameter type. 
-	 */
-	template<class T> struct TGpuDataParamInfo { };
-	template<> struct TGpuDataParamInfo < float > { enum { TypeId = GPDT_FLOAT1 }; };
-	template<> struct TGpuDataParamInfo < Color > { enum { TypeId = GPDT_FLOAT4 }; };
-	template<> struct TGpuDataParamInfo < Vector2 > { enum { TypeId = GPDT_FLOAT2 }; };
-	template<> struct TGpuDataParamInfo < Vector3 > { enum { TypeId = GPDT_FLOAT3 }; };
-	template<> struct TGpuDataParamInfo < Vector4 > { enum { TypeId = GPDT_FLOAT4 }; };
-	template<> struct TGpuDataParamInfo < Matrix3 > { enum { TypeId = GPDT_MATRIX_3X3 }; };
-	template<> struct TGpuDataParamInfo < Matrix4 > { enum { TypeId = GPDT_MATRIX_4X4 }; };
-
-	/**
-	 * @brief	Contains functionality common for both sim and core thread
-	 *			version of GpuParams.
-	 */
-	class BS_CORE_EXPORT GpuParamsBase
-	{
-	public:
-		/**
-		 * @brief	Creates new GpuParams object using the specified parameter descriptions.
-		 *
-		 * @param	paramDesc			Reference to parameter descriptions that will be used for
-		 *								finding needed parameters.
-		 * @param	transposeMatrices	If true the stored matrices will be transposed before
-		 *								submitted to the GPU (some APIs require different
-		 *								matrix layout).
-		 *
-		 * @note	You normally do not want to call this manually. Instead use GpuProgram::createParameters.
-		 */
-		GpuParamsBase(const GpuParamDescPtr& paramDesc, bool transposeMatrices);
-		virtual ~GpuParamsBase();
-
-		// Note: Disallow copy/assign because it would require some care when copying (copy internal data shared_ptr and
-		// all the internal buffers too). Trivial to implement but not needed at this time. Un-delete and implement if necessary.
-		GpuParamsBase(const GpuParamsBase& other) = delete;
-		GpuParamsBase& operator=(const GpuParamsBase& rhs) = delete;
-
-		/**
-		 * @brief	Returns a description of all stored parameters.
-		 */
-		const GpuParamDesc& getParamDesc() const { return *mParamDesc; }
-
-		/**
-		 * @brief	Returns the size of a data parameter with the specified name, in bytes.
-		 *			Returns 0 if such parameter doesn't exist.
-		 */
-		UINT32 getDataParamSize(const String& name) const;
-
-		/**
-		 * @brief	Checks if parameter with the specified name exists.
-		 */
-		bool hasParam(const String& name) const;
-
-		/**
-		 * @brief	Checks if texture parameter with the specified name exists.
-		 */
-		bool hasTexture(const String& name) const;
-
-		/**
-		 * @brief	Checks if sampler state parameter with the specified name exists.
-		 */
-		bool hasSamplerState(const String& name) const;
-
-		/**
-		 * @brief	Checks if a parameter block with the specified name exists.
-		 */
-		bool hasParamBlock(const String& name) const;
-
-		/**
-		 * @brief	Checks is the texture at the specified slot to be bound as
-		 *			random load/store texture instead of a normal sampled texture.
-		 */
-		bool isLoadStoreTexture(UINT32 slot) const;
-
-		/**
-		 * @brief	Changes the type of the texture at the specified slot.
-		 */
-		void setIsLoadStoreTexture(UINT32 slot, bool isLoadStore);
-
-		/**
-		 * @brief	Returns information that determines which texture surfaces to bind
-		 *			as load/store parameters.
-		 */
-		const TextureSurface& getLoadStoreSurface(UINT32 slot) const;
-
-		/**
-		 * @brief	Sets information that determines which texture surfaces to bind
-		 *			as load/store parameters.
-		 */
-		void setLoadStoreSurface(UINT32 slot, const TextureSurface& surface) const;
-
-		/**
-		 * @brief	Checks whether matrices should be transformed before
-		 *			being written to the parameter buffer.
-		 */
-		bool getTransposeMatrices() const { return mTransposeMatrices; }
-
-		/**
-		 * @copydoc	CoreObject::markCoreDirty
-		 *
-		 * @note	Internal method.
-		 */
-		virtual void _markCoreDirty() { }
-
-		/**
-		 * @copydoc	IResourceListener::markResourcesDirty
-		 *
-		 * @note	Internal method.
-		 */
-		virtual void _markResourcesDirty() { }
-
-	protected:
-		/**
-		 * @brief	Gets a descriptor for a data parameter with the specified name.
-		 */
-		GpuParamDataDesc* getParamDesc(const String& name) const;
-
-		GpuParamDescPtr mParamDesc;
-
-		UINT32 mNumParamBlocks;
-		UINT32 mNumTextures;
-		UINT32 mNumSamplerStates;
-
-		BoundTextureInfo* mTextureInfo;
-
-		bool mTransposeMatrices;
-	};
-
-	/**
-	 * @brief	Templated version of GpuParams that contains functionality for both
-	 *			sim and core thread versions of stored data.
-	 */
-	template <bool Core>
-	class BS_CORE_EXPORT TGpuParams : public GpuParamsBase
-	{
-	public:
-		template<bool Core> struct TTypes { };
-
-		template<> struct TTypes < false > 
-		{ 
-			typedef GpuParams GpuParamsType; 
-			typedef HTexture TextureType;
-			typedef SamplerStatePtr SamplerType;
-			typedef SPtr<GpuParamBlockBuffer> ParamsBufferType;
-		};
-
-		template<> struct TTypes < true > 
-		{ 
-			typedef GpuParamsCore GpuParamsType;
-			typedef SPtr<TextureCore> TextureType;
-			typedef SPtr<SamplerStateCore> SamplerType;
-			typedef SPtr<GpuParamBlockBufferCore> ParamsBufferType;
-		};
-
-		typedef typename TTypes<Core>::GpuParamsType GpuParamsType;
-		typedef typename TTypes<Core>::TextureType TextureType;
-		typedef typename TTypes<Core>::SamplerType SamplerType;
-		typedef typename TTypes<Core>::ParamsBufferType ParamsBufferType;
-
-		/**
-		 * @copydoc	GpuParamsBase::GpuParamsBase(const GpuParamDescPtr&, bool)
-		 */
-		TGpuParams(const GpuParamDescPtr& paramDesc, bool transposeMatrices);
-
-		virtual ~TGpuParams();
-
-		/**
-		 * @brief	Binds a new parameter buffer to the specified slot. Any following parameter reads or
-		 *			writes that are referencing that buffer slot will use the new buffer.
-		 *
-		 * @note	This is useful if you want to share a parameter buffer among multiple GPU programs. 
-		 *			You would only set the values once and then share the buffer among all other GpuParams.
-		 *
-		 *			It is up to the caller to guarantee the provided buffer matches parameter block
-		 *			descriptor for this slot.
-		 */
-		void setParamBlockBuffer(UINT32 slot, const ParamsBufferType& paramBlockBuffer);
-
-		/**
-		 * @brief	Replaces the parameter buffer with the specified name. Any following parameter reads or
-		 *			writes that are referencing that buffer will use the new buffer.
-		 *
-		 * @note	This is useful if you want to share a parameter buffer among multiple GPU programs.
-		 *			You would only set the values once and then share the buffer among all other GpuParams.
-		 *
-		 *			It is up to the caller to guarantee the provided buffer matches parameter block
-		 *			descriptor for this slot.
-		 */
-		void setParamBlockBuffer(const String& name, const ParamsBufferType& paramBlockBuffer);
-
-		/**
-		 * @brief	Returns a handle for the parameter with the specified name.
-		 *			Handle may then be stored and used for quickly setting or retrieving
-		 *			values to/from that parameter.
-		 *
-		 *			Throws exception if parameter with that name and type doesn't exist.
-		*
-		*			Parameter handles will be invalidated when their parent GpuParams object changes.
-		*/
-		template<class T> void getParam(const String& name, TGpuDataParam<T, Core>& output) const;
-
-		/**
-		 * @copydoc	getParam(const String&, TGpuDataParam<T, Core>&)
-		 */
-		void getStructParam(const String& name, TGpuParamStruct<Core>& output) const;
-
-		/**
-		 * @copydoc	getParam(const String&, TGpuDataParam<T, Core>&)
-		 */
-		void getTextureParam(const String& name, TGpuParamTexture<Core>& output) const;
-
-		/**
-		 * @copydoc	getParam(const String&, TGpuDataParam<T, Core>&)
-		 */
-		void getLoadStoreTextureParam(const String& name, TGpuParamLoadStoreTexture<Core>& output) const;
-
-		/**
-		 * @copydoc	getParam(const String&, TGpuDataParam<T, Core>&)
-		 */
-		void getSamplerStateParam(const String& name, TGpuParamSampState<Core>& output) const;
-
-		/**
-		 * @brief	Gets a parameter block buffer from the specified slot.
-		 */
-		ParamsBufferType getParamBlockBuffer(UINT32 slot) const;
-
-		/**
-		 * @brief	Gets a texture bound to the specified slot.
-		 */
-		TextureType getTexture(UINT32 slot);
-
-		/**
-		 * @brief	Gets a sampler state bound to the specified slot.
-		 */
-		SamplerType getSamplerState(UINT32 slot);
-
-		/**
-		 * @brief	Sets a texture at the specified slot.
-		 */
-		void setTexture(UINT32 slot, const TextureType& texture);
-
-		/**
-		 * @brief	Sets a sampler state at the specified slot.
-		 */
-		void setSamplerState(UINT32 slot, const SamplerType& sampler);
-
-	protected:
-		/**
-		 * @copydoc	CoreObject::getThisPtr
-		 */
-		virtual SPtr<GpuParamsType> _getThisPtr() const = 0;
-
-		ParamsBufferType* mParamBlockBuffers;
-		TextureType* mTextures;
-		SamplerType* mSamplerStates;
-	};
-
-	/**
-	 * @brief	Core thread version of GpuParams.
-	 *
-	 * @see		GpuParams
-	 *
-	 * @note	Core thread only.
-	 */
-	class BS_CORE_EXPORT GpuParamsCore : public CoreObjectCore, public TGpuParams<true>
-	{
-	public:
-		~GpuParamsCore() { }
-
-		/**
-		 * @brief	Uploads all CPU stored parameter buffer data to the GPU buffers.
-		 */
-		void updateHardwareBuffers();
-
-		/**
-		 * @copydoc	GpuParamsBase::GpuParamsBase
-		 */
-		static SPtr<GpuParamsCore> create(const GpuParamDescPtr& paramDesc, bool transposeMatrices);
-
-	protected:
-		friend class GpuParams;
-
-		/**
-		 * @copydoc	GpuParamsBase::GpuParamsBase
-		 */
-		GpuParamsCore(const GpuParamDescPtr& paramDesc, bool transposeMatrices);
-
-		/**
-		 * @copydoc	CoreObject::getThisPtr
-		 */
-		SPtr<GpuParamsCore> _getThisPtr() const override;
-
-		/**
-		 * @copydoc	CoreObjectCore::syncToCore
-		 */
-		void syncToCore(const CoreSyncData& data) override;
-	};
-
-	/**
-	 * @brief	Contains descriptions for all parameters in a GPU program and also
-	 *			allows you to write and read those parameters. All parameter values
-	 *			are stored internally on the CPU, and are only submitted to the GPU
-	 *			once the parameters are bound to the pipeline.
-	 *
-	 * @see		CoreThreadAccessor::setConstantBuffers
-	 *
-	 * @note	Sim thread only.
-	 */
-	class BS_CORE_EXPORT GpuParams : public CoreObject, public TGpuParams<false>, public IResourceListener
-	{
-	public:
-		~GpuParams() { }
-
-		/**
-		 * @copydoc	CoreObject::markCoreDirty
-		 *
-		 * @note	Internal method.
-		 */
-		void _markCoreDirty() override;
-
-		/**
-		 * @copydoc	IResourceListener::markResourcesDirty
-		 *
-		 * @note	Internal method.
-		 */
-		void _markResourcesDirty() override;
-
-		/**
-		 * @brief	Retrieves a core implementation of a mesh usable only from the
-		 *			core thread.
-		 */
-		SPtr<GpuParamsCore> getCore() const;
-
-		/**
-		 * @copydoc	GpuParamsBase::GpuParamsBase
-		 */
-		static SPtr<GpuParams> create(const GpuParamDescPtr& paramDesc, bool transposeMatrices);
-
-		/**
-		 * @brief	Contains a lookup table for sizes of all data parameters. Sizes are in bytes.
-		 */
-		const static GpuDataParamInfos PARAM_SIZES;
-
-	protected:
-		/**
-		 * @copydoc	GpuParamsBase::GpuParamsBase
-		 */
-		GpuParams(const GpuParamDescPtr& paramDesc, bool transposeMatrices);
-
-		/**
-		 * @copydoc	CoreObject::getThisPtr
-		 */
-		SPtr<GpuParams> _getThisPtr() const override;
-
-		/**
-		 * @copydoc	CoreObject::createCore
-		 */
-		SPtr<CoreObjectCore> createCore() const override;
-
-		/**
-		 * @copydoc	CoreObject::syncToCore
-		 */
-		CoreSyncData syncToCore(FrameAlloc* allocator) override;
-
-		/**
-		 * @copydoc	IResourceListener::getListenerResources
-		 */
-		void getListenerResources(Vector<HResource>& resources) override;
-
-		/**
-		 * @copydoc IResourceListener::notifyResourceLoaded
-		 */
-		void notifyResourceLoaded(const HResource& resource) override { markCoreDirty(); }
-
-		/**
-		 * @copydoc IResourceListener::notifyResourceChanged
-		 */
-		void notifyResourceChanged(const HResource& resource) override { markCoreDirty(); }
-	};
+#pragma once
+
+#include "BsCorePrerequisites.h"
+#include "BsGpuParam.h"
+#include "BsCoreObject.h"
+#include "BsIResourceListener.h"
+#include "BsVectorNI.h"
+#include "BsMatrixNxM.h"
+
+namespace BansheeEngine
+{
+	/**
+	 * @brief	Stores information needed for binding a texture to the pipeline.
+	 */
+	struct BoundTextureInfo
+	{
+		BoundTextureInfo()
+			:isLoadStore(false)
+		{ }
+
+		bool isLoadStore;
+		TextureSurface surface;
+	};
+
+	/**
+	 * @brief	Helper structure whose specializations convert an engine data type into a GPU program data parameter type. 
+	 */
+	template<class T> struct TGpuDataParamInfo { };
+	template<> struct TGpuDataParamInfo < float > { enum { TypeId = GPDT_FLOAT1 }; };
+	template<> struct TGpuDataParamInfo < Vector2 > { enum { TypeId = GPDT_FLOAT2 }; };
+	template<> struct TGpuDataParamInfo < Vector3 > { enum { TypeId = GPDT_FLOAT3 }; };
+	template<> struct TGpuDataParamInfo < Vector4 > { enum { TypeId = GPDT_FLOAT4 }; };
+	template<> struct TGpuDataParamInfo < int > { enum { TypeId = GPDT_INT1 }; };
+	template<> struct TGpuDataParamInfo < Vector2I > { enum { TypeId = GPDT_INT2 }; };
+	template<> struct TGpuDataParamInfo < Vector3I > { enum { TypeId = GPDT_INT3 }; };
+	template<> struct TGpuDataParamInfo < Vector4I > { enum { TypeId = GPDT_INT4 }; };
+	template<> struct TGpuDataParamInfo < Matrix2 > { enum { TypeId = GPDT_MATRIX_2X2 }; };
+	template<> struct TGpuDataParamInfo < Matrix2x3 > { enum { TypeId = GPDT_MATRIX_2X3 }; };
+	template<> struct TGpuDataParamInfo < Matrix2x4 > { enum { TypeId = GPDT_MATRIX_2X3 }; };
+	template<> struct TGpuDataParamInfo < Matrix3 > { enum { TypeId = GPDT_MATRIX_3X3 }; };
+	template<> struct TGpuDataParamInfo < Matrix3x2 > { enum { TypeId = GPDT_MATRIX_3X2 }; };
+	template<> struct TGpuDataParamInfo < Matrix3x4 > { enum { TypeId = GPDT_MATRIX_3X4 }; };
+	template<> struct TGpuDataParamInfo < Matrix4 > { enum { TypeId = GPDT_MATRIX_4X4 }; };
+	template<> struct TGpuDataParamInfo < Matrix4x2 > { enum { TypeId = GPDT_MATRIX_4X2 }; };
+	template<> struct TGpuDataParamInfo < Matrix4x3 > { enum { TypeId = GPDT_MATRIX_4X3 }; };
+	template<> struct TGpuDataParamInfo < Color > { enum { TypeId = GPDT_COLOR }; };
+
+	/**
+	 * @brief	Contains functionality common for both sim and core thread
+	 *			version of GpuParams.
+	 */
+	class BS_CORE_EXPORT GpuParamsBase
+	{
+	public:
+		/**
+		 * @brief	Creates new GpuParams object using the specified parameter descriptions.
+		 *
+		 * @param	paramDesc			Reference to parameter descriptions that will be used for
+		 *								finding needed parameters.
+		 * @param	transposeMatrices	If true the stored matrices will be transposed before
+		 *								submitted to the GPU (some APIs require different
+		 *								matrix layout).
+		 *
+		 * @note	You normally do not want to call this manually. Instead use GpuProgram::createParameters.
+		 */
+		GpuParamsBase(const GpuParamDescPtr& paramDesc, bool transposeMatrices);
+		virtual ~GpuParamsBase();
+
+		// Note: Disallow copy/assign because it would require some care when copying (copy internal data shared_ptr and
+		// all the internal buffers too). Trivial to implement but not needed at this time. Un-delete and implement if necessary.
+		GpuParamsBase(const GpuParamsBase& other) = delete;
+		GpuParamsBase& operator=(const GpuParamsBase& rhs) = delete;
+
+		/**
+		 * @brief	Returns a description of all stored parameters.
+		 */
+		const GpuParamDesc& getParamDesc() const { return *mParamDesc; }
+
+		/**
+		 * @brief	Returns the size of a data parameter with the specified name, in bytes.
+		 *			Returns 0 if such parameter doesn't exist.
+		 */
+		UINT32 getDataParamSize(const String& name) const;
+
+		/**
+		 * @brief	Checks if parameter with the specified name exists.
+		 */
+		bool hasParam(const String& name) const;
+
+		/**
+		 * @brief	Checks if texture parameter with the specified name exists.
+		 */
+		bool hasTexture(const String& name) const;
+
+		/**
+		 * @brief	Checks if sampler state parameter with the specified name exists.
+		 */
+		bool hasSamplerState(const String& name) const;
+
+		/**
+		 * @brief	Checks if a parameter block with the specified name exists.
+		 */
+		bool hasParamBlock(const String& name) const;
+
+		/**
+		 * @brief	Checks is the texture at the specified slot to be bound as
+		 *			random load/store texture instead of a normal sampled texture.
+		 */
+		bool isLoadStoreTexture(UINT32 slot) const;
+
+		/**
+		 * @brief	Changes the type of the texture at the specified slot.
+		 */
+		void setIsLoadStoreTexture(UINT32 slot, bool isLoadStore);
+
+		/**
+		 * @brief	Returns information that determines which texture surfaces to bind
+		 *			as load/store parameters.
+		 */
+		const TextureSurface& getLoadStoreSurface(UINT32 slot) const;
+
+		/**
+		 * @brief	Sets information that determines which texture surfaces to bind
+		 *			as load/store parameters.
+		 */
+		void setLoadStoreSurface(UINT32 slot, const TextureSurface& surface) const;
+
+		/**
+		 * @brief	Checks whether matrices should be transformed before
+		 *			being written to the parameter buffer.
+		 */
+		bool getTransposeMatrices() const { return mTransposeMatrices; }
+
+		/**
+		 * @copydoc	CoreObject::markCoreDirty
+		 *
+		 * @note	Internal method.
+		 */
+		virtual void _markCoreDirty() { }
+
+		/**
+		 * @copydoc	IResourceListener::markResourcesDirty
+		 *
+		 * @note	Internal method.
+		 */
+		virtual void _markResourcesDirty() { }
+
+	protected:
+		/**
+		 * @brief	Gets a descriptor for a data parameter with the specified name.
+		 */
+		GpuParamDataDesc* getParamDesc(const String& name) const;
+
+		GpuParamDescPtr mParamDesc;
+
+		UINT32 mNumParamBlocks;
+		UINT32 mNumTextures;
+		UINT32 mNumSamplerStates;
+
+		BoundTextureInfo* mTextureInfo;
+
+		bool mTransposeMatrices;
+	};
+
+	/**
+	 * @brief	Templated version of GpuParams that contains functionality for both
+	 *			sim and core thread versions of stored data.
+	 */
+	template <bool Core>
+	class BS_CORE_EXPORT TGpuParams : public GpuParamsBase
+	{
+	public:
+		template<bool Core> struct TTypes { };
+
+		template<> struct TTypes < false > 
+		{ 
+			typedef GpuParams GpuParamsType; 
+			typedef HTexture TextureType;
+			typedef SamplerStatePtr SamplerType;
+			typedef SPtr<GpuParamBlockBuffer> ParamsBufferType;
+		};
+
+		template<> struct TTypes < true > 
+		{ 
+			typedef GpuParamsCore GpuParamsType;
+			typedef SPtr<TextureCore> TextureType;
+			typedef SPtr<SamplerStateCore> SamplerType;
+			typedef SPtr<GpuParamBlockBufferCore> ParamsBufferType;
+		};
+
+		typedef typename TTypes<Core>::GpuParamsType GpuParamsType;
+		typedef typename TTypes<Core>::TextureType TextureType;
+		typedef typename TTypes<Core>::SamplerType SamplerType;
+		typedef typename TTypes<Core>::ParamsBufferType ParamsBufferType;
+
+		/**
+		 * @copydoc	GpuParamsBase::GpuParamsBase(const GpuParamDescPtr&, bool)
+		 */
+		TGpuParams(const GpuParamDescPtr& paramDesc, bool transposeMatrices);
+
+		virtual ~TGpuParams();
+
+		/**
+		 * @brief	Binds a new parameter buffer to the specified slot. Any following parameter reads or
+		 *			writes that are referencing that buffer slot will use the new buffer.
+		 *
+		 * @note	This is useful if you want to share a parameter buffer among multiple GPU programs. 
+		 *			You would only set the values once and then share the buffer among all other GpuParams.
+		 *
+		 *			It is up to the caller to guarantee the provided buffer matches parameter block
+		 *			descriptor for this slot.
+		 */
+		void setParamBlockBuffer(UINT32 slot, const ParamsBufferType& paramBlockBuffer);
+
+		/**
+		 * @brief	Replaces the parameter buffer with the specified name. Any following parameter reads or
+		 *			writes that are referencing that buffer will use the new buffer.
+		 *
+		 * @note	This is useful if you want to share a parameter buffer among multiple GPU programs.
+		 *			You would only set the values once and then share the buffer among all other GpuParams.
+		 *
+		 *			It is up to the caller to guarantee the provided buffer matches parameter block
+		 *			descriptor for this slot.
+		 */
+		void setParamBlockBuffer(const String& name, const ParamsBufferType& paramBlockBuffer);
+
+		/**
+		 * @brief	Returns a handle for the parameter with the specified name.
+		 *			Handle may then be stored and used for quickly setting or retrieving
+		 *			values to/from that parameter.
+		 *
+		 *			Throws exception if parameter with that name and type doesn't exist.
+		*
+		*			Parameter handles will be invalidated when their parent GpuParams object changes.
+		*/
+		template<class T> void getParam(const String& name, TGpuDataParam<T, Core>& output) const;
+
+		/**
+		 * @copydoc	getParam(const String&, TGpuDataParam<T, Core>&)
+		 */
+		void getStructParam(const String& name, TGpuParamStruct<Core>& output) const;
+
+		/**
+		 * @copydoc	getParam(const String&, TGpuDataParam<T, Core>&)
+		 */
+		void getTextureParam(const String& name, TGpuParamTexture<Core>& output) const;
+
+		/**
+		 * @copydoc	getParam(const String&, TGpuDataParam<T, Core>&)
+		 */
+		void getLoadStoreTextureParam(const String& name, TGpuParamLoadStoreTexture<Core>& output) const;
+
+		/**
+		 * @copydoc	getParam(const String&, TGpuDataParam<T, Core>&)
+		 */
+		void getSamplerStateParam(const String& name, TGpuParamSampState<Core>& output) const;
+
+		/**
+		 * @brief	Gets a parameter block buffer from the specified slot.
+		 */
+		ParamsBufferType getParamBlockBuffer(UINT32 slot) const;
+
+		/**
+		 * @brief	Gets a texture bound to the specified slot.
+		 */
+		TextureType getTexture(UINT32 slot);
+
+		/**
+		 * @brief	Gets a sampler state bound to the specified slot.
+		 */
+		SamplerType getSamplerState(UINT32 slot);
+
+		/**
+		 * @brief	Sets a texture at the specified slot.
+		 */
+		void setTexture(UINT32 slot, const TextureType& texture);
+
+		/**
+		 * @brief	Sets a sampler state at the specified slot.
+		 */
+		void setSamplerState(UINT32 slot, const SamplerType& sampler);
+
+	protected:
+		/**
+		 * @copydoc	CoreObject::getThisPtr
+		 */
+		virtual SPtr<GpuParamsType> _getThisPtr() const = 0;
+
+		ParamsBufferType* mParamBlockBuffers;
+		TextureType* mTextures;
+		SamplerType* mSamplerStates;
+	};
+
+	/**
+	 * @brief	Core thread version of GpuParams.
+	 *
+	 * @see		GpuParams
+	 *
+	 * @note	Core thread only.
+	 */
+	class BS_CORE_EXPORT GpuParamsCore : public CoreObjectCore, public TGpuParams<true>
+	{
+	public:
+		~GpuParamsCore() { }
+
+		/**
+		 * @brief	Uploads all CPU stored parameter buffer data to the GPU buffers.
+		 */
+		void updateHardwareBuffers();
+
+		/**
+		 * @copydoc	GpuParamsBase::GpuParamsBase
+		 */
+		static SPtr<GpuParamsCore> create(const GpuParamDescPtr& paramDesc, bool transposeMatrices);
+
+	protected:
+		friend class GpuParams;
+
+		/**
+		 * @copydoc	GpuParamsBase::GpuParamsBase
+		 */
+		GpuParamsCore(const GpuParamDescPtr& paramDesc, bool transposeMatrices);
+
+		/**
+		 * @copydoc	CoreObject::getThisPtr
+		 */
+		SPtr<GpuParamsCore> _getThisPtr() const override;
+
+		/**
+		 * @copydoc	CoreObjectCore::syncToCore
+		 */
+		void syncToCore(const CoreSyncData& data) override;
+	};
+
+	/**
+	 * @brief	Contains descriptions for all parameters in a GPU program and also
+	 *			allows you to write and read those parameters. All parameter values
+	 *			are stored internally on the CPU, and are only submitted to the GPU
+	 *			once the parameters are bound to the pipeline.
+	 *
+	 * @see		CoreThreadAccessor::setConstantBuffers
+	 *
+	 * @note	Sim thread only.
+	 */
+	class BS_CORE_EXPORT GpuParams : public CoreObject, public TGpuParams<false>, public IResourceListener
+	{
+	public:
+		~GpuParams() { }
+
+		/**
+		 * @copydoc	CoreObject::markCoreDirty
+		 *
+		 * @note	Internal method.
+		 */
+		void _markCoreDirty() override;
+
+		/**
+		 * @copydoc	IResourceListener::markResourcesDirty
+		 *
+		 * @note	Internal method.
+		 */
+		void _markResourcesDirty() override;
+
+		/**
+		 * @brief	Retrieves a core implementation of a mesh usable only from the
+		 *			core thread.
+		 */
+		SPtr<GpuParamsCore> getCore() const;
+
+		/**
+		 * @copydoc	GpuParamsBase::GpuParamsBase
+		 */
+		static SPtr<GpuParams> create(const GpuParamDescPtr& paramDesc, bool transposeMatrices);
+
+		/**
+		 * @brief	Contains a lookup table for sizes of all data parameters. Sizes are in bytes.
+		 */
+		const static GpuDataParamInfos PARAM_SIZES;
+
+	protected:
+		/**
+		 * @copydoc	GpuParamsBase::GpuParamsBase
+		 */
+		GpuParams(const GpuParamDescPtr& paramDesc, bool transposeMatrices);
+
+		/**
+		 * @copydoc	CoreObject::getThisPtr
+		 */
+		SPtr<GpuParams> _getThisPtr() const override;
+
+		/**
+		 * @copydoc	CoreObject::createCore
+		 */
+		SPtr<CoreObjectCore> createCore() const override;
+
+		/**
+		 * @copydoc	CoreObject::syncToCore
+		 */
+		CoreSyncData syncToCore(FrameAlloc* allocator) override;
+
+		/**
+		 * @copydoc	IResourceListener::getListenerResources
+		 */
+		void getListenerResources(Vector<HResource>& resources) override;
+
+		/**
+		 * @copydoc IResourceListener::notifyResourceLoaded
+		 */
+		void notifyResourceLoaded(const HResource& resource) override { markCoreDirty(); }
+
+		/**
+		 * @copydoc IResourceListener::notifyResourceChanged
+		 */
+		void notifyResourceChanged(const HResource& resource) override { markCoreDirty(); }
+	};
 }

+ 11 - 5
BansheeCore/Include/BsMaterial.h

@@ -16,7 +16,7 @@ namespace BansheeEngine
 	 *  @{
 	 */
 
-	class __MaterialParams;
+	class MaterialParams;
 
 	/** Helper class containing parameters for all types of GPU programs used in a pass. */
 	template<bool Core>
@@ -510,7 +510,6 @@ namespace BansheeEngine
 		 */
 		void setParamBlockBuffer(const String& name, const ParamBlockPtrType& paramBlock);
 
-	protected:
 		/**
 		 * Allows you to retrieve a handle to a parameter that you can then use for quickly setting and retrieving parameter
 		 * data. This allows you to set/get parameter data without all the cost of extra lookups otherwise required.
@@ -522,6 +521,7 @@ namespace BansheeEngine
 		template <typename T>
 		void getParam(const String& name, TMaterialDataParam<T, Core>& output) const;
 
+	protected:
 		/** 
 		 * Creates a material param out of multiple GPU params. Caller must ensure all GPU params reference the same 
 		 * parameter. 
@@ -640,7 +640,7 @@ namespace BansheeEngine
 		virtual void createCachedParams(const HShader& shader) { }
 
 		/** Returns a list of all values assigned to material parameters. */
-		virtual SPtr<__MaterialParams> getCachedParams() const { return nullptr; }
+		virtual SPtr<MaterialParams> getCachedParams() const { return nullptr; }
 
 		/**
 		 * Initializes the material by using the best technique from the currently set shader. Shader must contain the 
@@ -765,10 +765,16 @@ namespace BansheeEngine
 		void createCachedParams(const HShader& shader) override;
 
 		/** @copydoc Material::getCachedParams */
-		SPtr<__MaterialParams> getCachedParams() const override { return mCachedParams; }
+		SPtr<MaterialParams> getCachedParams() const override { return mCachedParams; }
+
+		/** 
+		 * Uses the provided list of parameters to try to set every parameter in this material. Parameter whose name, type
+		 * or size don't match are ignored and will not be set.
+		 */
+		void setParams(const SPtr<MaterialParams>& params);
 
 		UINT32 mLoadFlags;
-		SPtr<__MaterialParams> mCachedParams;
+		SPtr<MaterialParams> mCachedParams;
 
 		/************************************************************************/
 		/* 								RTTI		                     		*/

+ 11 - 11
BansheeCore/Include/BsMaterialParam.h

@@ -9,7 +9,7 @@ namespace BansheeEngine
 	 *  @{
 	 */
 
-	class __MaterialParams;
+	class MaterialParams;
 
 	/**
 	 * A handle that allows you to set a Material parameter. Internally keeps a reference to the material parameters so that
@@ -36,7 +36,7 @@ namespace BansheeEngine
 	class BS_CORE_EXPORT TMaterialDataParam<T, false>
 	{
 	public:
-		TMaterialDataParam(const String& name, const SPtr<__MaterialParams>& params, 
+		TMaterialDataParam(const String& name, const SPtr<MaterialParams>& params, 
 			const SPtr<Vector<TGpuDataParam<T, false>>>& gpuParams);
 		TMaterialDataParam() { }
 
@@ -49,7 +49,7 @@ namespace BansheeEngine
 	protected:
 		UINT32 mParamIndex;
 		UINT32 mArraySize;
-		SPtr<__MaterialParams> mMaterialParams;
+		SPtr<MaterialParams> mMaterialParams;
 		SPtr<Vector<TGpuDataParam<T, false>>> mGPUParams;
 	};
 
@@ -81,7 +81,7 @@ namespace BansheeEngine
 	class BS_CORE_EXPORT TMaterialParamStruct<false>
 	{
 	public:
-		TMaterialParamStruct(const String& name, const SPtr<__MaterialParams>& params,
+		TMaterialParamStruct(const String& name, const SPtr<MaterialParams>& params,
 			const SPtr<Vector<TGpuParamStruct<false>>>& gpuParams);
 		TMaterialParamStruct() { }
 
@@ -97,7 +97,7 @@ namespace BansheeEngine
 	protected:
 		UINT32 mParamIndex;
 		UINT32 mArraySize;
-		SPtr<__MaterialParams> mMaterialParams;
+		SPtr<MaterialParams> mMaterialParams;
 		SPtr<Vector<TGpuParamStruct<false>>> mGPUParams;
 	};
 
@@ -132,7 +132,7 @@ namespace BansheeEngine
 	class BS_CORE_EXPORT TMaterialParamTexture<false>
 	{
 	public:
-		TMaterialParamTexture(const String& name, const SPtr<__MaterialParams>& params, 
+		TMaterialParamTexture(const String& name, const SPtr<MaterialParams>& params, 
 			const SPtr<Vector<TGpuParamTexture<false>>>& gpuParams);
 		TMaterialParamTexture() { }
 
@@ -144,7 +144,7 @@ namespace BansheeEngine
 
 	protected:
 		UINT32 mParamIndex;
-		SPtr<__MaterialParams> mMaterialParams;
+		SPtr<MaterialParams> mMaterialParams;
 		SPtr<Vector<TGpuParamTexture<false>>> mGPUParams;
 	};
 
@@ -176,7 +176,7 @@ namespace BansheeEngine
 	class BS_CORE_EXPORT TMaterialParamLoadStoreTexture<false>
 	{
 	public:
-		TMaterialParamLoadStoreTexture(const String& name, const SPtr<__MaterialParams>& params,
+		TMaterialParamLoadStoreTexture(const String& name, const SPtr<MaterialParams>& params,
 			const SPtr<Vector<TGpuParamLoadStoreTexture<false>>>& gpuParams);
 		TMaterialParamLoadStoreTexture() { }
 
@@ -188,7 +188,7 @@ namespace BansheeEngine
 
 	protected:
 		UINT32 mParamIndex;
-		SPtr<__MaterialParams> mMaterialParams;
+		SPtr<MaterialParams> mMaterialParams;
 		SPtr<Vector<TGpuParamLoadStoreTexture<false>>> mGPUParams;
 	};
 
@@ -221,7 +221,7 @@ namespace BansheeEngine
 	class BS_CORE_EXPORT TMaterialParamSampState<false>
 	{
 	public:
-		TMaterialParamSampState(const String& name, const SPtr<__MaterialParams>& params, 
+		TMaterialParamSampState(const String& name, const SPtr<MaterialParams>& params, 
 			const SPtr<Vector<TGpuParamSampState<false>>>& gpuParams);
 		TMaterialParamSampState() { }
 
@@ -233,7 +233,7 @@ namespace BansheeEngine
 
 	protected:
 		UINT32 mParamIndex;
-		SPtr<__MaterialParams> mMaterialParams;
+		SPtr<MaterialParams> mMaterialParams;
 		SPtr<Vector<TGpuParamSampState<false>>> mGPUParams;
 	};
 

+ 86 - 54
BansheeCore/Include/BsMaterialParams.h

@@ -1,6 +1,7 @@
 #pragma once
 
 #include "BsCorePrerequisites.h"
+#include "BsIReflectable.h"
 #include "BsStaticAlloc.h"
 #include "BsVector2.h"
 #include "BsVector3.h"
@@ -12,8 +13,6 @@
 #include "BsMatrix4.h"
 #include "BsMatrixNxM.h"
 #include "BsGpuParams.h"
-#include "BsMaterial.h"
-#include "BsShader.h"
 
 namespace BansheeEngine
 {
@@ -37,25 +36,8 @@ namespace BansheeEngine
 	 * optimizes out a variable in a GPU program we should still be able to store it, either for later when the variable
 	 * will be introduced, or for other techniques that might have that variable implemented.
 	 */
-	class BS_CORE_EXPORT __MaterialParams
+	class BS_CORE_EXPORT MaterialParams : public IReflectable
 	{
-		/** Raw data for a single structure parameter. */
-		class BS_CORE_EXPORT StructParamData
-		{
-		public:
-			UINT8* data;
-			UINT32 dataSize;
-		};
-
-		/** Data for a single texture parameter. */
-		class BS_CORE_EXPORT TextureParamData
-		{
-		public:
-			HTexture value;
-			bool isLoadStore;
-			TextureSurface surface;
-		};
-
 	public:
 		/** Type of material parameter. */
 		enum class ParamType
@@ -63,6 +45,15 @@ namespace BansheeEngine
 			Data, Texture, Sampler
 		};
 
+		/** Result codes for getParam method. */
+		enum class GetParamResult
+		{
+			Success,
+			NotFound,
+			InvalidType,
+			IndexOutOfBounds
+		};
+
 		/** Meta-data about a parameter. */
 		struct ParamData
 		{
@@ -72,9 +63,34 @@ namespace BansheeEngine
 			UINT32 arraySize;
 		};
 
+		/** Raw data for a single structure parameter. */
+		class BS_CORE_EXPORT StructParamData : public IReflectable
+		{
+		public:
+			UINT8* data;
+			UINT32 dataSize;
+
+			friend class StructParamDataRTTI;
+			static RTTITypeBase* getRTTIStatic();
+			virtual RTTITypeBase* getRTTI() const override;
+		};
+
+		/** Data for a single texture parameter. */
+		class BS_CORE_EXPORT TextureParamData : public IReflectable
+		{
+		public:
+			HTexture value;
+			bool isLoadStore;
+			TextureSurface surface;
+
+			friend class TextureParamDataRTTI;
+			static RTTITypeBase* getRTTIStatic();
+			virtual RTTITypeBase* getRTTI() const override;
+		};
+
 		/** Creates a new material params object and initializes enough room for parameters from the provided shader. */
-		__MaterialParams(const HShader& shader);
-		~__MaterialParams();
+		MaterialParams(const HShader& shader);
+		~MaterialParams();
 
 		/** 
 		 * Returns the value of a shader data parameter with the specified name at the specified array index. If the
@@ -89,10 +105,11 @@ namespace BansheeEngine
 		template <typename T>
 		void getDataParam(const String& name, UINT32 arrayIdx, T& output) const
 		{
-			GpuParamDataType dataType = getDataType(output);
+			GpuParamDataType dataType = TGpuDataParamInfo<T>::TypeId;
 
-			const ParamData* param = getParamData(name, ParamType::Data, dataType, arrayIdx);
-			if (param == nullptr)
+			const ParamData* param = nullptr;
+			auto result = getParamData(name, ParamType::Data, dataType, arrayIdx, &param);
+			if (result != GetParamResult::Success)
 				return;
 
 			const GpuParamDataTypeInfo& typeInfo = GpuParams::PARAM_SIZES[dataType];
@@ -115,10 +132,11 @@ namespace BansheeEngine
 		template <typename T>
 		void setDataParam(const String& name, UINT32 arrayIdx, const T& input) const
 		{
-			GpuParamDataType dataType = getDataType(output);
+			GpuParamDataType dataType = TGpuDataParamInfo<T>::TypeId;
 
-			const ParamData* param = getParamData(name, ParamType::Data, dataType, arrayIdx);
-			if (param == nullptr)
+			const ParamData* param = nullptr;
+			auto result = getParamData(name, ParamType::Data, dataType, arrayIdx, &param);
+			if (result != GetParamResult::Success)
 				return;
 
 			const GpuParamDataTypeInfo& typeInfo = GpuParams::PARAM_SIZES[dataType];
@@ -213,14 +231,24 @@ namespace BansheeEngine
 		 * @param[in]	type		Type of the parameter retrieve. Error will be logged if actual type of the parameter 
 		 *							doesn't match.
 		 * @param[in]	dataType	Only relevant if the parameter is a data type. Determines exact data type of the parameter
-		 *							to retrieve. Error will be logged if the type of the parameter doesn't match.
-		 * @param[in]	arrayIdx	Array index of the entry to retrieve. Error will be logged if the array index is out
-		 *							side of the valid range.
+		 *							to retrieve. 
+		 * @param[in]	arrayIdx	Array index of the entry to retrieve. 
+		 * @param[out]	output		Object describing the parameter with an index to its data. If the parameter was not found
+		 *							this value is undefined. This value will still be valid if parameter was found but
+		 *							some other error was reported.
 		 *
-		 * @return					If successful, object describing the parameter with an index to its data. Otherwise
-		 *							null.
+		 * @return					Success or error state of the request.
 		 */
-		const ParamData* getParamData(const String& name, ParamType type, GpuParamDataType dataType, UINT32 arrayIdx) const;
+		GetParamResult getParamData(const String& name, ParamType type, GpuParamDataType dataType, UINT32 arrayIdx, 
+			const ParamData** output) const;
+
+		/**
+		 * Logs an error that was reported by getParamData().
+		 *
+		 * @param[in]	name		Name of the shader parameter for which the error occurred.
+		 * @param[in]	arrayIdx	Array index for which the error occurred. 
+		 */
+		void reportGetParamError(GetParamResult errorCode, const String& name, UINT32 arrayIdx) const;
 
 		/** 
 		 * Equivalent to getStructData(const String&, UINT32, T&) except it uses the internal parameter index
@@ -229,7 +257,7 @@ namespace BansheeEngine
 		template <typename T>
 		void getDataParam(UINT32 index, UINT32 arrayIdx, T& output) const
 		{
-			GpuParamDataType dataType = getDataType(output);
+			GpuParamDataType dataType = (GpuParamDataType)TGpuDataParamInfo<T>::TypeId;
 
 			const GpuParamDataTypeInfo& typeInfo = GpuParams::PARAM_SIZES.lookup[dataType];
 			UINT32 paramTypeSize = typeInfo.numColumns * typeInfo.numRows * typeInfo.baseTypeSize;
@@ -245,7 +273,7 @@ namespace BansheeEngine
 		template <typename T>
 		void setDataParam(UINT32 index, UINT32 arrayIdx, const T& input) const
 		{
-			GpuParamDataType dataType = getDataType(input);
+			GpuParamDataType dataType = (GpuParamDataType)TGpuDataParamInfo<T>::TypeId;
 
 			const GpuParamDataTypeInfo& typeInfo = GpuParams::PARAM_SIZES.lookup[dataType];
 			UINT32 paramTypeSize = typeInfo.numColumns * typeInfo.numRows * typeInfo.baseTypeSize;
@@ -296,6 +324,12 @@ namespace BansheeEngine
 		 */
 		void setLoadStoreTexture(UINT32 index, const HTexture& value, const TextureSurface& surface);
 
+		/** 
+		 * Checks is a texture with the specified index a load/store texture or a normal one. Caller must guarantee the 
+		 * index is valid.
+		 */
+		bool getIsTextureLoadStore(UINT32 index) const;
+
 		/** 
 		 * Equivalent to getSamplerState(const String&, SamplerStatePtr&) except it uses the internal parameter index 
 		 * directly, avoiding the name lookup. Caller must guarantee the index is valid.
@@ -308,24 +342,6 @@ namespace BansheeEngine
 		 */
 		void setSamplerState(UINT32 index, const SamplerStatePtr& value);
 
-		static GpuParamDataType getDataType(const float& dummy) { return GPDT_FLOAT1; }
-		static GpuParamDataType getDataType(const Vector2& dummy) { return GPDT_FLOAT2; }
-		static GpuParamDataType getDataType(const Vector3& dummy) { return GPDT_FLOAT3; }
-		static GpuParamDataType getDataType(const Vector4& dummy) { return GPDT_FLOAT4; }
-		static GpuParamDataType getDataType(const int& dummy) { return GPDT_INT1; }
-		static GpuParamDataType getDataType(const Vector2I& dummy) { return GPDT_INT1; }
-		static GpuParamDataType getDataType(const Vector3I& dummy) { return GPDT_INT1; }
-		static GpuParamDataType getDataType(const Vector4I& dummy) { return GPDT_INT1; }
-		static GpuParamDataType getDataType(const Matrix2& dummy) { return GPDT_MATRIX_2X2; }
-		static GpuParamDataType getDataType(const Matrix2x3& dummy) { return GPDT_MATRIX_2X3; }
-		static GpuParamDataType getDataType(const Matrix2x4& dummy) { return GPDT_MATRIX_2X4; }
-		static GpuParamDataType getDataType(const Matrix3& dummy) { return GPDT_MATRIX_3X3; }
-		static GpuParamDataType getDataType(const Matrix3x2& dummy) { return GPDT_MATRIX_3X2; }
-		static GpuParamDataType getDataType(const Matrix3x4& dummy) { return GPDT_MATRIX_3X4; }
-		static GpuParamDataType getDataType(const Matrix4& dummy) { return GPDT_MATRIX_4X4; }
-		static GpuParamDataType getDataType(const Matrix4x2& dummy) { return GPDT_MATRIX_4X2; }
-		static GpuParamDataType getDataType(const Matrix4x3& dummy) { return GPDT_MATRIX_4X3; }
-		static GpuParamDataType getDataType(const Color& dummy) { return GPDT_COLOR; }
 	private:
 		const static UINT32 STATIC_BUFFER_SIZE = 256;
 
@@ -336,13 +352,29 @@ namespace BansheeEngine
 		TextureParamData* mTextureParams = nullptr;
 		SamplerStatePtr* mSamplerStateParams = nullptr;
 
+		UINT32 mDataSize = 0;
 		UINT32 mNumStructParams = 0;
 		UINT32 mNumTextureParams = 0;
 		UINT32 mNumSamplerParams = 0;
 
 		mutable StaticAlloc<STATIC_BUFFER_SIZE, STATIC_BUFFER_SIZE> mAlloc;
+
+		/************************************************************************/
+		/* 								RTTI		                     		*/
+		/************************************************************************/
+
+	public:
+		MaterialParams() { } // Only for serialization
+
+		friend class MaterialParamsRTTI;
+		static RTTITypeBase* getRTTIStatic();
+		virtual RTTITypeBase* getRTTI() const override;
 	};
 
+	/** @cond SPECIALIZATIONS */
+	BS_ALLOW_MEMCPY_SERIALIZATION(MaterialParams::ParamData);
+	/** @endcond */
+
 	/** @} */
 	/** @endcond */
 }

+ 265 - 0
BansheeCore/Include/BsMaterialParamsRTTI.h

@@ -0,0 +1,265 @@
+#pragma once
+
+#include "BsCorePrerequisites.h"
+#include "BsRTTIType.h"
+#include "BsMaterialParams.h"
+#include "BsSamplerState.h"
+
+namespace BansheeEngine
+{
+	class BS_CORE_EXPORT TextureParamDataRTTI : public RTTIType<MaterialParams::TextureParamData, IReflectable, TextureParamDataRTTI>
+	{
+	public:
+		HTexture& getTexture(MaterialParams::TextureParamData* obj) { return obj->value; }
+		void setTexture(MaterialParams::TextureParamData* obj, HTexture& value) { obj->value = value; }
+
+		bool& getIsLoadStore(MaterialParams::TextureParamData* obj) { return obj->isLoadStore; }
+		void setIsLoadStore(MaterialParams::TextureParamData* obj, bool& value) { obj->isLoadStore = value; }
+
+		TextureSurface& getSurface(MaterialParams::TextureParamData* obj) { return obj->surface; }
+		void setSurface(MaterialParams::TextureParamData* obj, TextureSurface& value) { obj->surface = value; }
+
+		TextureParamDataRTTI()
+		{
+			addReflectableField("texture", 0, &TextureParamDataRTTI::getTexture, &TextureParamDataRTTI::setTexture);
+			addPlainField("isLoadStore", 1, &TextureParamDataRTTI::getIsLoadStore, &TextureParamDataRTTI::setIsLoadStore);
+			addPlainField("surface", 2, &TextureParamDataRTTI::getSurface, &TextureParamDataRTTI::setSurface);
+		}
+
+		const String& getRTTIName() override
+		{
+			static String name = "TextureParamData";
+			return name;
+		}
+
+		UINT32 getRTTIId() override
+		{
+			return TID_TextureParamData;
+		}
+
+		std::shared_ptr<IReflectable> newRTTIObject() override
+		{
+			return bs_shared_ptr_new<MaterialParams::TextureParamData>();
+		}
+	};
+
+	class BS_CORE_EXPORT StructParamDataRTTI : public RTTIType<MaterialParams::StructParamData, IReflectable, StructParamDataRTTI>
+	{
+	public:
+		ManagedDataBlock getDataBuffer(MaterialParams::StructParamData* obj)
+		{
+			return ManagedDataBlock(obj->data, obj->dataSize);
+		}
+
+		void setDataBuffer(MaterialParams::StructParamData* obj, ManagedDataBlock value)
+		{
+			// Do nothing as the buffer was already assigned when it was allocated
+		}
+
+		static UINT8* allocateDataBuffer(MaterialParams::StructParamData* obj, UINT32 numBytes)
+		{
+			obj->data = (UINT8*)bs_alloc(numBytes);
+			obj->dataSize = numBytes;
+
+			return obj->data;
+		}
+
+		StructParamDataRTTI()
+		{
+			addDataBlockField("dataBuffer", 0, &StructParamDataRTTI::getDataBuffer,
+				&StructParamDataRTTI::setDataBuffer, 0, &StructParamDataRTTI::allocateDataBuffer);
+		}
+
+		const String& getRTTIName() override
+		{
+			static String name = "StructParamData";
+			return name;
+		}
+
+		UINT32 getRTTIId() override
+		{
+			return TID_StructParamData;
+		}
+
+		std::shared_ptr<IReflectable> newRTTIObject() override
+		{
+			return bs_shared_ptr_new<MaterialParams::StructParamData>();
+		}
+	};
+
+	class BS_CORE_EXPORT MaterialParamsRTTI : public RTTIType<MaterialParams, IReflectable, MaterialParamsRTTI>
+	{
+	public:
+		struct MaterialParam
+		{
+			String name;
+			MaterialParams::ParamData data;
+		};
+
+		MaterialParam& getParamData(MaterialParams* obj, UINT32 idx)
+		{
+			Vector<MaterialParam>& params = any_cast_ref<Vector<MaterialParam>>(obj->mRTTIData);
+			return params[idx];
+		}
+
+		void setParamData(MaterialParams* obj, UINT32 idx, MaterialParam& param)
+		{
+			obj->mParams[param.name] = param.data;
+		}
+
+		UINT32 getParamDataArraySize(MaterialParams* obj)
+		{
+			Vector<MaterialParam>& params = any_cast_ref<Vector<MaterialParam>>(obj->mRTTIData);
+			return (UINT32)params.size();
+		}
+
+		void setParamDataArraySize(MaterialParams* obj, UINT32 size)
+		{
+			// Do nothing
+		}
+
+		ManagedDataBlock getDataBuffer(MaterialParams* obj)
+		{
+			return ManagedDataBlock(obj->mDataParamsBuffer, obj->mDataSize);
+		}
+
+		void setDataBuffer(MaterialParams* obj, ManagedDataBlock value)
+		{
+			// Do nothing as the buffer was already assigned when it was allocated
+		}
+
+		static UINT8* allocateDataBuffer(MaterialParams* obj, UINT32 numBytes)
+		{
+			obj->mDataParamsBuffer = obj->mAlloc.alloc(numBytes);
+			obj->mDataSize = numBytes;
+
+			return obj->mDataParamsBuffer;
+		}
+
+		MaterialParams::StructParamData& getStructParam(MaterialParams* obj, UINT32 idx) { return obj->mStructParams[idx]; }
+		void setStructParam(MaterialParams* obj, UINT32 idx, MaterialParams::StructParamData& param)
+		{
+			MaterialParams::StructParamData& newStructParam = obj->mStructParams[idx];
+			newStructParam.data = (UINT8*)obj->mAlloc.alloc(param.dataSize);
+			memcpy(newStructParam.data, param.data, param.dataSize);
+			newStructParam.dataSize = param.dataSize;
+
+			bs_free(param.data);
+			param.data = nullptr;
+		}
+		UINT32 getStructArraySize(MaterialParams* obj) { return (UINT32)obj->mNumStructParams; }
+		void setStructArraySize(MaterialParams* obj, UINT32 size)
+		{
+			obj->mNumStructParams = size;
+			obj->mStructParams = obj->mAlloc.construct<MaterialParams::StructParamData>(size);
+		}
+
+		MaterialParams::TextureParamData& getTextureParam(MaterialParams* obj, UINT32 idx) { return obj->mTextureParams[idx]; }
+		void setTextureParam(MaterialParams* obj, UINT32 idx, MaterialParams::TextureParamData& param) { obj->mTextureParams[idx] = param; }
+		UINT32 getTextureArraySize(MaterialParams* obj) { return (UINT32)obj->mNumTextureParams; }
+		void setTextureArraySize(MaterialParams* obj, UINT32 size)
+		{
+			obj->mNumTextureParams = size;
+			obj->mTextureParams = obj->mAlloc.construct<MaterialParams::TextureParamData>(size);
+		}
+
+		SamplerStatePtr getSamplerStateParam(MaterialParams* obj, UINT32 idx) { return obj->mSamplerStateParams[idx]; }
+		void setSamplerStateParam(MaterialParams* obj, UINT32 idx, SamplerStatePtr param) { obj->mSamplerStateParams[idx] = param; }
+		UINT32 getSamplerStateArraySize(MaterialParams* obj) { return (UINT32)obj->mNumSamplerParams; }
+		void setSamplerStateArraySize(MaterialParams* obj, UINT32 size)
+		{
+			obj->mNumSamplerParams = size;
+			obj->mSamplerStateParams = obj->mAlloc.construct<SamplerStatePtr>(size);
+		}
+
+		MaterialParamsRTTI()
+		{
+			addPlainArrayField("paramData", 0, &MaterialParamsRTTI::getParamData, &MaterialParamsRTTI::getParamDataArraySize, 
+				&MaterialParamsRTTI::setParamData, &MaterialParamsRTTI::setParamDataArraySize);
+
+			addDataBlockField("dataBuffer", 1, &MaterialParamsRTTI::getDataBuffer,
+				&MaterialParamsRTTI::setDataBuffer, 0, &MaterialParamsRTTI::allocateDataBuffer);
+
+			addReflectableArrayField("structParams", 2, &MaterialParamsRTTI::getStructParam,
+				&MaterialParamsRTTI::getStructArraySize, &MaterialParamsRTTI::setStructParam, &MaterialParamsRTTI::setStructArraySize);
+
+			addReflectableArrayField("textureParams", 3, &MaterialParamsRTTI::getTextureParam,
+				&MaterialParamsRTTI::getTextureArraySize, &MaterialParamsRTTI::setTextureParam, &MaterialParamsRTTI::setTextureArraySize);
+
+			addReflectablePtrArrayField("samplerStateParams", 4, &MaterialParamsRTTI::getSamplerStateParam,
+				&MaterialParamsRTTI::getSamplerStateArraySize, &MaterialParamsRTTI::setSamplerStateParam, &MaterialParamsRTTI::setSamplerStateArraySize);
+		}
+
+		void onSerializationStarted(IReflectable* obj) override
+		{
+			MaterialParams* paramsObj = static_cast<MaterialParams*>(obj);
+			Vector<MaterialParam> params;
+
+			for(auto& entry : paramsObj->mParams)
+				params.push_back({ entry.first, entry.second });
+
+			paramsObj->mRTTIData = params;
+		}
+
+		void onSerializationEnded(IReflectable* obj) override
+		{
+			MaterialParams* paramsObj = static_cast<MaterialParams*>(obj);
+			paramsObj->mRTTIData = nullptr;
+		}
+
+		const String& getRTTIName() override
+		{
+			static String name = "MaterialParams";
+			return name;
+		}
+
+		UINT32 getRTTIId() override 
+		{ 
+			return TID_MaterialParams; 
+		}
+
+		std::shared_ptr<IReflectable> newRTTIObject() override
+		{
+			return bs_shared_ptr_new<MaterialParams>();
+		}
+	};
+
+	template<> struct RTTIPlainType<MaterialParamsRTTI::MaterialParam>
+	{	
+		enum { id = TID_MaterialRTTIParam }; enum { hasDynamicSize = 1 };
+
+		static void toMemory(const MaterialParamsRTTI::MaterialParam& data, char* memory)
+		{ 
+			UINT32 size = getDynamicSize(data);
+
+			memory = rttiWriteElem(size, memory);
+			memory = rttiWriteElem(data.name, memory);
+			memory = rttiWriteElem(data.data, memory);
+		}
+
+		static UINT32 fromMemory(MaterialParamsRTTI::MaterialParam& data, char* memory)
+		{ 
+			UINT32 size = 0;
+			
+			memory = rttiReadElem(size, memory);
+			memory = rttiReadElem(data.name, memory);
+			memory = rttiReadElem(data.data, memory);
+
+			return size;
+		}
+
+		static UINT32 getDynamicSize(const MaterialParamsRTTI::MaterialParam& data)
+		{ 
+			UINT64 dataSize = rttiGetElemSize(data.name) + rttiGetElemSize(data.data) + sizeof(UINT32);
+
+#if BS_DEBUG_MODE
+			if(dataSize > std::numeric_limits<UINT32>::max())
+			{
+				__string_throwDataOverflowException();
+			}
+#endif
+
+			return (UINT32)dataSize;
+		}	
+	}; 
+}

+ 53 - 645
BansheeCore/Include/BsMaterialRTTI.h

@@ -1,646 +1,54 @@
-#pragma once
-
-#include "BsCorePrerequisites.h"
-#include "BsRTTIType.h"
-#include "BsVector2.h"
-#include "BsVector3.h"
-#include "BsVector4.h"
-#include "BsMatrix3.h"
-#include "BsMatrix4.h"
-#include "BsMaterial.h"
-#include "BsGpuParams.h"
-#include "BsShader.h"
-#include "BsSamplerState.h"
-#include "BsDebug.h"
-#include "BsException.h"
-
-namespace BansheeEngine
-{
-	/************************************************************************/
-	/* 					HELPER STRUCTS TO HELP SERIALIZING                  */
-	/************************************************************************/
-
-	class BS_CORE_EXPORT MaterialFloatParam : public IReflectable
-	{
-	public:
-		String name;
-		float value;
-		UINT32 arrayIdx;
-
-		friend class MaterialFloatParamRTTI;
-		static RTTITypeBase* getRTTIStatic();
-		virtual RTTITypeBase* getRTTI() const override;
-	};
-
-	class BS_CORE_EXPORT MaterialVec2Param : public IReflectable
-	{
-	public:
-		String name;
-		Vector2 value;
-		UINT32 arrayIdx;
-
-		friend class MaterialVec2ParamRTTI;
-		static RTTITypeBase* getRTTIStatic();
-		virtual RTTITypeBase* getRTTI() const override;
-	};
-
-	class BS_CORE_EXPORT MaterialVec3Param : public IReflectable
-	{
-	public:
-		String name;
-		Vector3 value;
-		UINT32 arrayIdx;
-
-		friend class MaterialVec3ParamRTTI;
-		static RTTITypeBase* getRTTIStatic();
-		virtual RTTITypeBase* getRTTI() const override;
-	};
-
-	class BS_CORE_EXPORT MaterialVec4Param : public IReflectable
-	{
-	public:
-		String name;
-		Vector4 value;
-		UINT32 arrayIdx;
-
-		friend class MaterialVec4ParamRTTI;
-		static RTTITypeBase* getRTTIStatic();
-		virtual RTTITypeBase* getRTTI() const override;
-	};
-
-	class BS_CORE_EXPORT MaterialColorParam : public IReflectable
-	{
-	public:
-		String name;
-		Color value;
-		UINT32 arrayIdx;
-
-		friend class MaterialColorParamRTTI;
-		static RTTITypeBase* getRTTIStatic();
-		virtual RTTITypeBase* getRTTI() const override;
-	};
-
-
-	class BS_CORE_EXPORT MaterialMat3Param : public IReflectable
-	{
-	public:
-		String name;
-		Matrix3 value;
-		UINT32 arrayIdx;
-
-		friend class MaterialMat3ParamRTTI;
-		static RTTITypeBase* getRTTIStatic();
-		virtual RTTITypeBase* getRTTI() const override;
-	};
-
-	class BS_CORE_EXPORT MaterialMat4Param : public IReflectable
-	{
-	public:
-		String name;
-		Matrix4 value;
-		UINT32 arrayIdx;
-
-		friend class MaterialMat4ParamRTTI;
-		static RTTITypeBase* getRTTIStatic();
-		virtual RTTITypeBase* getRTTI() const override;
-	};
-
-	class BS_CORE_EXPORT MaterialStructParam : public IReflectable
-	{
-	public:
-		String name;
-		Material::StructData value;
-		UINT32 arrayIdx;
-		UINT32 elementSize;
-
-		friend class MaterialStructParamRTTI;
-		static RTTITypeBase* getRTTIStatic();
-		virtual RTTITypeBase* getRTTI() const override;
-	};
-
-	class BS_CORE_EXPORT MaterialTextureParam : public IReflectable
-	{
-	public:
-		String name;
-		HTexture value;
-
-		friend class MaterialTextureParamRTTI;
-		static RTTITypeBase* getRTTIStatic();
-		virtual RTTITypeBase* getRTTI() const override;
-	};
-
-	class BS_CORE_EXPORT MaterialSamplerStateParam : public IReflectable
-	{
-	public:
-		String name;
-		SamplerStatePtr value;
-
-		friend class MaterialSamplerStateParamRTTI;
-		static RTTITypeBase* getRTTIStatic();
-		virtual RTTITypeBase* getRTTI() const override;
-	};
-
-	class BS_CORE_EXPORT MaterialParams : public IReflectable
-	{
-	public:
-		Vector<MaterialFloatParam> floatParams;
-		Vector<MaterialVec2Param> vec2Params;
-		Vector<MaterialVec3Param> vec3Params;
-		Vector<MaterialVec4Param> vec4Params;
-		Vector<MaterialMat3Param> mat3Params;
-		Vector<MaterialMat4Param> mat4Params;
-		Vector<MaterialColorParam> colorParams;
-		Vector<MaterialStructParam> structParams;
-		Vector<MaterialTextureParam> textureParams;
-		Vector<MaterialSamplerStateParam> samplerStateParams;
-
-		friend class MaterialParamsRTTI;
-		static RTTITypeBase* getRTTIStatic();
-		virtual RTTITypeBase* getRTTI() const override;
-	};
-
-	/************************************************************************/
-	/* 				RTTI FOR HELPER STRUCTS TO HELP SERIALIZING             */
-	/************************************************************************/
-
-	class BS_CORE_EXPORT MaterialFloatParamRTTI : public RTTIType<MaterialFloatParam, IReflectable, MaterialFloatParamRTTI>
-	{
-	public:
-		String& getName(MaterialFloatParam* obj) { return obj->name; }
-		void setName(MaterialFloatParam* obj, String& name) { obj->name = name; }
-
-		float& getValue(MaterialFloatParam* obj) { return obj->value; }
-		void setValue(MaterialFloatParam* obj, float& value) { obj->value = value; }
-
-		UINT32& getArrayIdx(MaterialFloatParam* obj) { return obj->arrayIdx; }
-		void setArrayIdx(MaterialFloatParam* obj, UINT32& value) { obj->arrayIdx = value; }
-
-		MaterialFloatParamRTTI()
-		{
-			addPlainField("name", 0, &MaterialFloatParamRTTI::getName, &MaterialFloatParamRTTI::setName);
-			addPlainField("value", 1, &MaterialFloatParamRTTI::getValue, &MaterialFloatParamRTTI::setValue);
-			addPlainField("arrayIdx", 2, &MaterialFloatParamRTTI::getArrayIdx, &MaterialFloatParamRTTI::setArrayIdx);
-		}
-
-		virtual const String& getRTTIName() override
-		{
-			static String name = "MaterialFloatParam";
-			return name;
-		}
-
-		virtual UINT32 getRTTIId() override { return TID_MaterialParamFloat; }
-		virtual std::shared_ptr<IReflectable> newRTTIObject() override
-		{ 
-			return bs_shared_ptr_new<MaterialFloatParam>(); 
-		}
-	};
-
-	class BS_CORE_EXPORT MaterialVec2ParamRTTI : public RTTIType<MaterialVec2Param, IReflectable, MaterialVec2ParamRTTI>
-	{
-	public:
-		String& getName(MaterialVec2Param* obj) { return obj->name; }
-		void setName(MaterialVec2Param* obj, String& name) { obj->name = name; }
-
-		Vector2& getValue(MaterialVec2Param* obj) { return obj->value; }
-		void setValue(MaterialVec2Param* obj, Vector2& value) { obj->value = value; }
-
-		UINT32& getArrayIdx(MaterialVec2Param* obj) { return obj->arrayIdx; }
-		void setArrayIdx(MaterialVec2Param* obj, UINT32& value) { obj->arrayIdx = value; }
-
-		MaterialVec2ParamRTTI()
-		{
-			addPlainField("name", 0, &MaterialVec2ParamRTTI::getName, &MaterialVec2ParamRTTI::setName);
-			addPlainField("value", 1, &MaterialVec2ParamRTTI::getValue, &MaterialVec2ParamRTTI::setValue);
-			addPlainField("arrayIdx", 2, &MaterialVec2ParamRTTI::getArrayIdx, &MaterialVec2ParamRTTI::setArrayIdx);
-		}
-
-		virtual const String& getRTTIName() override
-		{
-			static String name = "MaterialVec2Param";
-			return name;
-		}
-
-		virtual UINT32 getRTTIId() override { return TID_MaterialParamVec2; }
-		virtual std::shared_ptr<IReflectable> newRTTIObject() override
-		{ 
-			return bs_shared_ptr_new<MaterialVec2Param>(); 
-		}
-	};
-
-	class BS_CORE_EXPORT MaterialVec3ParamRTTI : public RTTIType<MaterialVec3Param, IReflectable, MaterialVec3ParamRTTI>
-	{
-	public:
-		String& getName(MaterialVec3Param* obj) { return obj->name; }
-		void setName(MaterialVec3Param* obj, String& name) { obj->name = name; }
-
-		Vector3& getValue(MaterialVec3Param* obj) { return obj->value; }
-		void setValue(MaterialVec3Param* obj, Vector3& value) { obj->value = value; }
-
-		UINT32& getArrayIdx(MaterialVec3Param* obj) { return obj->arrayIdx; }
-		void setArrayIdx(MaterialVec3Param* obj, UINT32& value) { obj->arrayIdx = value; }
-
-		MaterialVec3ParamRTTI()
-		{
-			addPlainField("name", 0, &MaterialVec3ParamRTTI::getName, &MaterialVec3ParamRTTI::setName);
-			addPlainField("value", 1, &MaterialVec3ParamRTTI::getValue, &MaterialVec3ParamRTTI::setValue);
-			addPlainField("arrayIdx", 2, &MaterialVec3ParamRTTI::getArrayIdx, &MaterialVec3ParamRTTI::setArrayIdx);
-		}
-
-		virtual const String& getRTTIName() override
-		{
-			static String name = "MaterialVec3Param";
-			return name;
-		}
-
-		virtual UINT32 getRTTIId() override { return TID_MaterialParamVec3; }
-		virtual std::shared_ptr<IReflectable> newRTTIObject() override
-		{ 
-			return bs_shared_ptr_new<MaterialVec3Param>(); 
-		}
-	};
-
-	class BS_CORE_EXPORT MaterialVec4ParamRTTI : public RTTIType<MaterialVec4Param, IReflectable, MaterialVec4ParamRTTI>
-	{
-	public:
-		String& getName(MaterialVec4Param* obj) { return obj->name; }
-		void setName(MaterialVec4Param* obj, String& name) { obj->name = name; }
-
-		Vector4& getValue(MaterialVec4Param* obj) { return obj->value; }
-		void setValue(MaterialVec4Param* obj, Vector4& value) { obj->value = value; }
-
-		UINT32& getArrayIdx(MaterialVec4Param* obj) { return obj->arrayIdx; }
-		void setArrayIdx(MaterialVec4Param* obj, UINT32& value) { obj->arrayIdx = value; }
-
-		MaterialVec4ParamRTTI()
-		{
-			addPlainField("name", 0, &MaterialVec4ParamRTTI::getName, &MaterialVec4ParamRTTI::setName);
-			addPlainField("value", 1, &MaterialVec4ParamRTTI::getValue, &MaterialVec4ParamRTTI::setValue);
-			addPlainField("arrayIdx", 2, &MaterialVec4ParamRTTI::getArrayIdx, &MaterialVec4ParamRTTI::setArrayIdx);
-		}
-
-		virtual const String& getRTTIName() override
-		{
-			static String name = "MaterialVec4Param";
-			return name;
-		}
-
-		virtual UINT32 getRTTIId() override { return TID_MaterialParamVec4; }
-		virtual std::shared_ptr<IReflectable> newRTTIObject() override
-		{
-			return bs_shared_ptr_new<MaterialVec4Param>();
-		}
-	};
-
-	class BS_CORE_EXPORT MaterialColorParamRTTI : public RTTIType <MaterialColorParam, IReflectable, MaterialColorParamRTTI>
-	{
-	public:
-		String& getName(MaterialColorParam* obj) { return obj->name; }
-		void setName(MaterialColorParam* obj, String& name) { obj->name = name; }
-
-		Color& getValue(MaterialColorParam* obj) { return obj->value; }
-		void setValue(MaterialColorParam* obj, Color& value) { obj->value = value; }
-
-		UINT32& getArrayIdx(MaterialColorParam* obj) { return obj->arrayIdx; }
-		void setArrayIdx(MaterialColorParam* obj, UINT32& value) { obj->arrayIdx = value; }
-
-		MaterialColorParamRTTI()
-		{
-			addPlainField("name", 0, &MaterialColorParamRTTI::getName, &MaterialColorParamRTTI::setName);
-			addPlainField("value", 1, &MaterialColorParamRTTI::getValue, &MaterialColorParamRTTI::setValue);
-			addPlainField("arrayIdx", 2, &MaterialColorParamRTTI::getArrayIdx, &MaterialColorParamRTTI::setArrayIdx);
-		}
-
-		virtual const String& getRTTIName() override
-		{
-			static String name = "MaterialColorParam";
-			return name;
-		}
-
-		virtual UINT32 getRTTIId() override { return TID_MaterialParamColor; }
-		virtual std::shared_ptr<IReflectable> newRTTIObject() override
-		{
-			return bs_shared_ptr_new<MaterialColorParam>();
-		}
-	};
-
-	class BS_CORE_EXPORT MaterialMat3ParamRTTI : public RTTIType<MaterialMat3Param, IReflectable, MaterialMat3ParamRTTI>
-	{
-	public:
-		String& getName(MaterialMat3Param* obj) { return obj->name; }
-		void setName(MaterialMat3Param* obj, String& name) { obj->name = name; }
-
-		Matrix3& getValue(MaterialMat3Param* obj) { return obj->value; }
-		void setValue(MaterialMat3Param* obj, Matrix3& value) { obj->value = value; }
-
-		UINT32& getArrayIdx(MaterialMat3Param* obj) { return obj->arrayIdx; }
-		void setArrayIdx(MaterialMat3Param* obj, UINT32& value) { obj->arrayIdx = value; }
-
-		MaterialMat3ParamRTTI()
-		{
-			addPlainField("name", 0, &MaterialMat3ParamRTTI::getName, &MaterialMat3ParamRTTI::setName);
-			addPlainField("value", 1, &MaterialMat3ParamRTTI::getValue, &MaterialMat3ParamRTTI::setValue);
-			addPlainField("arrayIdx", 2, &MaterialMat3ParamRTTI::getArrayIdx, &MaterialMat3ParamRTTI::setArrayIdx);
-		}
-
-		virtual const String& getRTTIName() override
-		{
-			static String name = "MaterialMat3Param";
-			return name;
-		}
-
-		virtual UINT32 getRTTIId() override { return TID_MaterialParamMat3; }
-		virtual std::shared_ptr<IReflectable> newRTTIObject() override
-		{ 
-			return bs_shared_ptr_new<MaterialMat3Param>();
-		}
-	};
-
-	class BS_CORE_EXPORT MaterialMat4ParamRTTI : public RTTIType<MaterialMat4Param, IReflectable, MaterialMat4ParamRTTI>
-	{
-	public:
-		String& getName(MaterialMat4Param* obj) { return obj->name; }
-		void setName(MaterialMat4Param* obj, String& name) { obj->name = name; }
-
-		Matrix4& getValue(MaterialMat4Param* obj) { return obj->value; }
-		void setValue(MaterialMat4Param* obj, Matrix4& value) { obj->value = value; }
-
-		UINT32& getArrayIdx(MaterialMat4Param* obj) { return obj->arrayIdx; }
-		void setArrayIdx(MaterialMat4Param* obj, UINT32& value) { obj->arrayIdx = value; }
-
-		MaterialMat4ParamRTTI()
-		{
-			addPlainField("name", 0, &MaterialMat4ParamRTTI::getName, &MaterialMat4ParamRTTI::setName);
-			addPlainField("value", 1, &MaterialMat4ParamRTTI::getValue, &MaterialMat4ParamRTTI::setValue);
-			addPlainField("arrayIdx", 2, &MaterialMat4ParamRTTI::getArrayIdx, &MaterialMat4ParamRTTI::setArrayIdx);
-		}
-
-		virtual const String& getRTTIName() override
-		{
-			static String name = "MaterialMat4Param";
-			return name;
-		}
-
-		virtual UINT32 getRTTIId() override { return TID_MaterialParamMat4; }
-		virtual std::shared_ptr<IReflectable> newRTTIObject() override
-		{ 
-			return bs_shared_ptr_new<MaterialMat4Param>();
-		}
-	};
-
-	class BS_CORE_EXPORT MaterialStructParamRTTI : public RTTIType<MaterialStructParam, IReflectable, MaterialStructParamRTTI>
-	{
-	public:
-		String& getName(MaterialStructParam* obj) { return obj->name; }
-		void setName(MaterialStructParam* obj, String& name) { obj->name = name; }
-
-		ManagedDataBlock getValue(MaterialStructParam* obj) 
-		{ 
-			ManagedDataBlock returnValue(obj->value.size);
-
-			UINT8* data = returnValue.getData();
-			memcpy(data, obj->value.data.get(), obj->value.size);
-
-			return returnValue; 
-		}
-
-		void setValue(MaterialStructParam* obj, ManagedDataBlock value) 
-		{ 
-			obj->value = Material::StructData(value.getSize()); 
-			obj->value.write(value.getData());
-			
-		}
-
-		UINT32& getArrayIdx(MaterialStructParam* obj) { return obj->arrayIdx; }
-		void setArrayIdx(MaterialStructParam* obj, UINT32& value) { obj->arrayIdx = value; }
-
-		UINT32& getElementSize(MaterialStructParam* obj) { return obj->elementSize; }
-		void setElementSize(MaterialStructParam* obj, UINT32& value) { obj->elementSize = value; }
-
-		MaterialStructParamRTTI()
-		{
-			addPlainField("name", 0, &MaterialStructParamRTTI::getName, &MaterialStructParamRTTI::setName);
-			addDataBlockField("value", 1, &MaterialStructParamRTTI::getValue, &MaterialStructParamRTTI::setValue);
-			addPlainField("arrayIdx", 2, &MaterialStructParamRTTI::getArrayIdx, &MaterialStructParamRTTI::setArrayIdx);
-			addPlainField("elementSize", 3, &MaterialStructParamRTTI::getElementSize, &MaterialStructParamRTTI::setElementSize);
-		}
-
-		virtual const String& getRTTIName() override
-		{
-			static String name = "MaterialStructParam";
-			return name;
-		}
-
-		virtual UINT32 getRTTIId() override { return TID_MaterialParamStruct; }
-		virtual std::shared_ptr<IReflectable> newRTTIObject() override
-		{ 
-			return bs_shared_ptr_new<MaterialStructParam>();
-		}
-	};
-
-	class BS_CORE_EXPORT MaterialTextureParamRTTI : public RTTIType<MaterialTextureParam, IReflectable, MaterialTextureParamRTTI>
-	{
-	public:
-		String& getName(MaterialTextureParam* obj) { return obj->name; }
-		void setName(MaterialTextureParam* obj, String& name) { obj->name = name; }
-
-		HTexture& getValue(MaterialTextureParam* obj) { return obj->value; }
-		void setValue(MaterialTextureParam* obj, HTexture& value) { obj->value = value; }
-
-		MaterialTextureParamRTTI()
-		{
-			addPlainField("name", 0, &MaterialTextureParamRTTI::getName, &MaterialTextureParamRTTI::setName);
-			addReflectableField("value", 1, &MaterialTextureParamRTTI::getValue, &MaterialTextureParamRTTI::setValue);
-		}
-
-		virtual const String& getRTTIName() override
-		{
-			static String name = "MaterialTextureParam";
-			return name;
-		}
-
-		virtual UINT32 getRTTIId() override { return TID_MaterialParamTexture; }
-		virtual std::shared_ptr<IReflectable> newRTTIObject() override
-		{ 
-			return bs_shared_ptr_new<MaterialTextureParam>();
-		}
-	};
-
-	class BS_CORE_EXPORT MaterialSamplerStateParamRTTI : public RTTIType<MaterialSamplerStateParam, IReflectable, MaterialSamplerStateParamRTTI>
-	{
-	public:
-		String& getName(MaterialSamplerStateParam* obj) { return obj->name; }
-		void setName(MaterialSamplerStateParam* obj, String& name) { obj->name = name; }
-
-		SamplerStatePtr getValue(MaterialSamplerStateParam* obj) { return obj->value; }
-		void setValue(MaterialSamplerStateParam* obj, SamplerStatePtr value) { obj->value = value; }
-
-		MaterialSamplerStateParamRTTI()
-		{
-			addPlainField("name", 0, &MaterialSamplerStateParamRTTI::getName, &MaterialSamplerStateParamRTTI::setName);
-			addReflectablePtrField("value", 1, &MaterialSamplerStateParamRTTI::getValue, &MaterialSamplerStateParamRTTI::setValue);
-		}
-
-		virtual const String& getRTTIName() override
-		{
-			static String name = "MaterialSamplerStateParam";
-			return name;
-		}
-
-		virtual UINT32 getRTTIId() override { return TID_MaterialParamSamplerState; }
-		virtual std::shared_ptr<IReflectable> newRTTIObject() override
-		{ 
-			return bs_shared_ptr_new<MaterialSamplerStateParam>();
-		}
-	};
-
-	class BS_CORE_EXPORT MaterialParamsRTTI : public RTTIType<MaterialParams, IReflectable, MaterialParamsRTTI>
-	{
-	public:
-		MaterialFloatParam& getFloatParam(MaterialParams* obj, UINT32 idx) { return obj->floatParams[idx]; }
-		void setFloatParam(MaterialParams* obj, UINT32 idx, MaterialFloatParam& param) { obj->floatParams[idx] = param; }
-		UINT32 getFloatArraySize(MaterialParams* obj) { return (UINT32)obj->floatParams.size(); }
-		void setFloatArraySize(MaterialParams* obj, UINT32 size) { obj->floatParams.resize(size); }
-
-		MaterialVec2Param& getVec2Param(MaterialParams* obj, UINT32 idx) { return obj->vec2Params[idx]; }
-		void setVec2Param(MaterialParams* obj, UINT32 idx, MaterialVec2Param& param) { obj->vec2Params[idx] = param; }
-		UINT32 getVec2ArraySize(MaterialParams* obj) { return (UINT32)obj->vec2Params.size(); }
-		void setVec2ArraySize(MaterialParams* obj, UINT32 size) { obj->vec2Params.resize(size); }
-
-		MaterialVec3Param& getVec3Param(MaterialParams* obj, UINT32 idx) { return obj->vec3Params[idx]; }
-		void setVec3Param(MaterialParams* obj, UINT32 idx, MaterialVec3Param& param) { obj->vec3Params[idx] = param; }
-		UINT32 getVec3ArraySize(MaterialParams* obj) { return (UINT32)obj->vec3Params.size(); }
-		void setVec3ArraySize(MaterialParams* obj, UINT32 size) { obj->vec3Params.resize(size); }
-
-		MaterialVec4Param& getVec4Param(MaterialParams* obj, UINT32 idx) { return obj->vec4Params[idx]; }
-		void setVec4Param(MaterialParams* obj, UINT32 idx, MaterialVec4Param& param) { obj->vec4Params[idx] = param; }
-		UINT32 getVec4ArraySize(MaterialParams* obj) { return (UINT32)obj->vec4Params.size(); }
-		void setVec4ArraySize(MaterialParams* obj, UINT32 size) { obj->vec4Params.resize(size); }
-
-		MaterialColorParam& getColorParam(MaterialParams* obj, UINT32 idx) { return obj->colorParams[idx]; }
-		void setColorParam(MaterialParams* obj, UINT32 idx, MaterialColorParam& param) { obj->colorParams[idx] = param; }
-		UINT32 getColorArraySize(MaterialParams* obj) { return (UINT32)obj->colorParams.size(); }
-		void setColorArraySize(MaterialParams* obj, UINT32 size) { obj->colorParams.resize(size); }
-
-		MaterialMat3Param& getMat3Param(MaterialParams* obj, UINT32 idx) { return obj->mat3Params[idx]; }
-		void setMat3Param(MaterialParams* obj, UINT32 idx, MaterialMat3Param& param) { obj->mat3Params[idx] = param; }
-		UINT32 getMat3ArraySize(MaterialParams* obj) { return (UINT32)obj->mat3Params.size(); }
-		void setMat3ArraySize(MaterialParams* obj, UINT32 size) { obj->mat3Params.resize(size); }
-
-		MaterialMat4Param& getMat4Param(MaterialParams* obj, UINT32 idx) { return obj->mat4Params[idx]; }
-		void setMat4Param(MaterialParams* obj, UINT32 idx, MaterialMat4Param& param) { obj->mat4Params[idx] = param; }
-		UINT32 getMat4ArraySize(MaterialParams* obj) { return (UINT32)obj->mat4Params.size(); }
-		void setMat4ArraySize(MaterialParams* obj, UINT32 size) { obj->mat4Params.resize(size); }
-
-		MaterialStructParam& getStructParam(MaterialParams* obj, UINT32 idx) { return obj->structParams[idx]; }
-		void setStructParam(MaterialParams* obj, UINT32 idx, MaterialStructParam& param) { obj->structParams[idx] = param; }
-		UINT32 getStructArraySize(MaterialParams* obj) { return (UINT32)obj->structParams.size(); }
-		void setStructArraySize(MaterialParams* obj, UINT32 size) { obj->structParams.resize(size); }
-
-		MaterialTextureParam& getTextureParam(MaterialParams* obj, UINT32 idx) { return obj->textureParams[idx]; }
-		void setTextureParam(MaterialParams* obj, UINT32 idx, MaterialTextureParam& param) { obj->textureParams[idx] = param; }
-		UINT32 getTextureArraySize(MaterialParams* obj) { return (UINT32)obj->textureParams.size(); }
-		void setTextureArraySize(MaterialParams* obj, UINT32 size) { obj->textureParams.resize(size); }
-
-		MaterialSamplerStateParam& getSamplerStateParam(MaterialParams* obj, UINT32 idx) { return obj->samplerStateParams[idx]; }
-		void setSamplerStateParam(MaterialParams* obj, UINT32 idx, MaterialSamplerStateParam& param) { obj->samplerStateParams[idx] = param; }
-		UINT32 getSamplerStateArraySize(MaterialParams* obj) { return (UINT32)obj->samplerStateParams.size(); }
-		void setSamplerStateArraySize(MaterialParams* obj, UINT32 size) { obj->samplerStateParams.resize(size); }
-
-		MaterialParamsRTTI()
-		{
-			addReflectableArrayField("floatParams", 0, &MaterialParamsRTTI::getFloatParam, 
-				&MaterialParamsRTTI::getFloatArraySize, &MaterialParamsRTTI::setFloatParam, &MaterialParamsRTTI::setFloatArraySize);
-
-			addReflectableArrayField("vec2Params", 1, &MaterialParamsRTTI::getVec2Param, 
-				&MaterialParamsRTTI::getVec2ArraySize, &MaterialParamsRTTI::setVec2Param, &MaterialParamsRTTI::setVec2ArraySize);
-
-			addReflectableArrayField("vec3Params", 2, &MaterialParamsRTTI::getVec3Param, 
-				&MaterialParamsRTTI::getVec3ArraySize, &MaterialParamsRTTI::setVec3Param, &MaterialParamsRTTI::setVec3ArraySize);
-
-			addReflectableArrayField("vec4Params", 3, &MaterialParamsRTTI::getVec4Param, 
-				&MaterialParamsRTTI::getVec4ArraySize, &MaterialParamsRTTI::setVec4Param, &MaterialParamsRTTI::setVec4ArraySize);
-
-			addReflectableArrayField("mat3Params", 4, &MaterialParamsRTTI::getMat3Param, 
-				&MaterialParamsRTTI::getMat3ArraySize, &MaterialParamsRTTI::setMat3Param, &MaterialParamsRTTI::setMat3ArraySize);
-
-			addReflectableArrayField("mat4Params", 5, &MaterialParamsRTTI::getMat4Param, 
-				&MaterialParamsRTTI::getMat4ArraySize, &MaterialParamsRTTI::setMat4Param, &MaterialParamsRTTI::setMat4ArraySize);
-
-			addReflectableArrayField("structParams", 6, &MaterialParamsRTTI::getStructParam, 
-				&MaterialParamsRTTI::getStructArraySize, &MaterialParamsRTTI::setStructParam, &MaterialParamsRTTI::setStructArraySize);
-
-			addReflectableArrayField("textureParams", 7, &MaterialParamsRTTI::getTextureParam, 
-				&MaterialParamsRTTI::getTextureArraySize, &MaterialParamsRTTI::setTextureParam, &MaterialParamsRTTI::setTextureArraySize);
-
-			addReflectableArrayField("samplerStateParams", 8, &MaterialParamsRTTI::getSamplerStateParam, 
-				&MaterialParamsRTTI::getSamplerStateArraySize, &MaterialParamsRTTI::setSamplerStateParam, &MaterialParamsRTTI::setSamplerStateArraySize);
-
-			addReflectableArrayField("colorParams", 9, &MaterialParamsRTTI::getColorParam,
-				&MaterialParamsRTTI::getColorArraySize, &MaterialParamsRTTI::setColorParam, &MaterialParamsRTTI::setColorArraySize);
-		}
-
-		virtual const String& getRTTIName()  override
-		{
-			static String name = "MaterialParams";
-			return name;
-		}
-
-		virtual UINT32 getRTTIId() override { return TID_MaterialParams; }
-		virtual std::shared_ptr<IReflectable> newRTTIObject() override
-		{ 
-			return bs_shared_ptr_new<MaterialParams>();
-		}
-	};
-
-	class BS_CORE_EXPORT MaterialRTTI : public RTTIType<Material, Resource, MaterialRTTI>
-	{
-	private:
-		HShader& getShader(Material* obj)
-		{
-			return obj->mShader;
-		}
-
-		void setShader(Material* obj, HShader& val)
-		{
-			obj->mShader = val;
-		}
-
-		std::shared_ptr<MaterialParams> getMaterialParams(Material* obj)
-		{
-			if(obj->mRTTIData.empty())
-				return nullptr;
-
-			return any_cast<std::shared_ptr<MaterialParams>>(obj->mRTTIData);
-		}
-
-		void setMaterialParams(Material* obj, std::shared_ptr<MaterialParams> value)
-		{
-			obj->mRTTIData = value;
-		}
-
-	public:
-		MaterialRTTI()
-		{
-			addReflectableField("mShader", 0, &MaterialRTTI::getShader, &MaterialRTTI::setShader);
-			addReflectablePtrField("mMaterialParams", 1, &MaterialRTTI::getMaterialParams, &MaterialRTTI::setMaterialParams);
-		}
-
-		virtual void onSerializationStarted(IReflectable* obj) override;
-		virtual void onSerializationEnded(IReflectable* obj) override;
-		virtual void onDeserializationStarted(IReflectable* obj) override;
-		virtual void onDeserializationEnded(IReflectable* obj) override;
-
-		virtual const String& getRTTIName() override
-		{
-			static String name = "Material";
-			return name;
-		}
-
-		virtual UINT32 getRTTIId() override
-		{
-			return TID_Material;
-		}
-
-		virtual std::shared_ptr<IReflectable> newRTTIObject() override;
-	};
+#pragma once
+
+#include "BsCorePrerequisites.h"
+#include "BsRTTIType.h"
+#include "BsMaterial.h"
+
+namespace BansheeEngine
+{
+	class BS_CORE_EXPORT MaterialRTTI : public RTTIType<Material, Resource, MaterialRTTI>
+	{
+	private:
+		HShader& getShader(Material* obj)
+		{
+			return obj->mShader;
+		}
+
+		void setShader(Material* obj, HShader& val)
+		{
+			obj->mShader = val;
+		}
+
+		std::shared_ptr<MaterialParams> getMaterialParams(Material* obj)
+		{
+			return obj->mCachedParams;
+		}
+
+		void setMaterialParams(Material* obj, std::shared_ptr<MaterialParams> value)
+		{
+			obj->mRTTIData = value;
+		}
+
+	public:
+		MaterialRTTI()
+		{
+			addReflectableField("mShader", 0, &MaterialRTTI::getShader, &MaterialRTTI::setShader);
+			addReflectablePtrField("mMaterialParams", 2, &MaterialRTTI::getMaterialParams, &MaterialRTTI::setMaterialParams);
+		}
+
+		virtual void onDeserializationEnded(IReflectable* obj) override;
+
+		virtual const String& getRTTIName() override
+		{
+			static String name = "Material";
+			return name;
+		}
+
+		virtual UINT32 getRTTIId() override
+		{
+			return TID_Material;
+		}
+
+		virtual std::shared_ptr<IReflectable> newRTTIObject() override;
+	};
 }

+ 128 - 145
BansheeCore/Source/BsMaterial.cpp

@@ -1076,15 +1076,16 @@ namespace BansheeEngine
 
 	void Material::initialize()
 	{
-		setShader(mShader); // Not calling directly in constructor because it calls virtual methods
+		_markResourcesDirty();
+		initializeIfLoaded();
 
 		Resource::initialize();
 	}
 
 	void Material::setShader(const HShader& shader)
 	{
-		//if (mShader == shader)
-		//	return;
+		if (mShader == shader)
+			return;
 
 		mShader = shader;
 		mBestTechnique = nullptr;
@@ -1236,8 +1237,16 @@ namespace BansheeEngine
 			{
 				mLoadFlags = Load_All;
 
+				// Shader about to change, so save parameters, rebuild material and restore parameters
+				SPtr<MaterialParams> oldParams = mCachedParams;
+
 				initBestTechnique();
 				markCoreDirty();
+
+				if (mBestTechnique == nullptr) // Wasn't initialized
+					return;
+
+				setParams(oldParams);
 			}
 		}
 		else
@@ -1252,7 +1261,7 @@ namespace BansheeEngine
 
 	void Material::createCachedParams(const HShader& shader)
 	{
-		mCachedParams = bs_shared_ptr_new<__MaterialParams>(shader);
+		mCachedParams = bs_shared_ptr_new<MaterialParams>(shader);
 	}
 
 	void Material::notifyResourceLoaded(const HResource& resource)
@@ -1260,179 +1269,153 @@ namespace BansheeEngine
 		initializeIfLoaded();
 	}
 
-	template<class T>
-	void copyParam(SPtr<GpuParams>& from, SPtr<GpuParams>& to, const String& name, UINT32 arraySize)
+	void Material::notifyResourceChanged(const HResource& resource)
+	{
+		mLoadFlags = Load_None;
+		initializeIfLoaded();
+	}
+
+	HMaterial Material::clone()
 	{
-		TGpuDataParam<T, false> newParam;
-		to->getParam(name, newParam);
+		UINT32 bufferSize = 0;
 
-		TGpuDataParam<T, false> oldParam;
-		from->getParam(name, oldParam);
+		MemorySerializer serializer;
+		UINT8* buffer = serializer.encode(this, bufferSize, (void*(*)(UINT32))&bs_alloc);
+
+		std::shared_ptr<Material> cloneObj = std::static_pointer_cast<Material>(serializer.decode(buffer, bufferSize));
+		bs_free(buffer);
+
+		return static_resource_cast<Material>(gResources()._createResourceHandle(cloneObj));
+	}
+
+	template<class T>
+	void copyParam(const SPtr<MaterialParams>& from, Material* to, const String& name, UINT32 index, UINT32 arraySize)
+	{
+		TMaterialDataParam<T, false> param;
+		to->getParam(name, param);
 
+		T paramData;
 		for (UINT32 i = 0; i < arraySize; i++)
-			newParam.set(oldParam.get(i), i);
+		{
+			from->getDataParam(index, i, paramData);
+			param.set(paramData, i);
+		}
 	}
 
-	void Material::notifyResourceChanged(const HResource& resource)
+	void Material::setParams(const SPtr<MaterialParams>& params)
 	{
-		// Shader changed, so save parameters, rebuild material and restore parameters
-		Vector<SPtr<PassParameters>> oldPassParams = mParametersPerPass;
+		if (params == nullptr)
+			return;
 
-		mLoadFlags = Load_None;
-		initializeIfLoaded();
+		std::function<void(const SPtr<MaterialParams>&, Material*, const String&, UINT32, UINT32)> copyParamLookup[GPDT_COUNT];
 
-		for (UINT32 i = 0; i < (UINT32)oldPassParams.size(); i++)
-		{
-			if (i >= (UINT32)mParametersPerPass.size())
-				continue;
+		copyParamLookup[GPDT_FLOAT1] = &copyParam<float>;
+		copyParamLookup[GPDT_FLOAT2] = &copyParam<Vector2>;
+		copyParamLookup[GPDT_FLOAT3] = &copyParam<Vector3>;
+		copyParamLookup[GPDT_FLOAT4] = &copyParam<Vector4>;
 
-			SPtr<PassParameters> oldParams = oldPassParams[i];
-			SPtr<PassParameters> newParams = mParametersPerPass[i];
+		copyParamLookup[GPDT_INT1] = &copyParam<int>;
+		copyParamLookup[GPDT_INT2] = &copyParam<Vector2I>;
+		copyParamLookup[GPDT_INT3] = &copyParam<Vector3I>;
+		copyParamLookup[GPDT_INT4] = &copyParam<Vector4I>;
 
-			for (UINT32 j = 0; j < PassParameters::NUM_PARAMS; j++)
-			{
-				SPtr<GpuParams>& oldGpuParams = oldParams->getParamByIdx(j);
-				SPtr<GpuParams>& newGpuParams = newParams->getParamByIdx(j);
-				if (oldGpuParams == nullptr || newGpuParams == nullptr)
-					continue;
+		copyParamLookup[GPDT_MATRIX_2X2] = &copyParam<Matrix2>;
+		copyParamLookup[GPDT_MATRIX_2X3] = &copyParam<Matrix2x3>;
+		copyParamLookup[GPDT_MATRIX_2X4] = &copyParam<Matrix2x4>;
 
-				const GpuParamDesc& oldDesc = oldGpuParams->getParamDesc();
-				const GpuParamDesc& newDesc = newGpuParams->getParamDesc();
+		copyParamLookup[GPDT_MATRIX_3X3] = &copyParam<Matrix3>;
+		copyParamLookup[GPDT_MATRIX_3X2] = &copyParam<Matrix3x2>;
+		copyParamLookup[GPDT_MATRIX_3X4] = &copyParam<Matrix3x4>;
 
-				for (auto& param : oldDesc.params)
-				{
-					auto iterFind = newDesc.params.find(param.first);
-					if (iterFind == newDesc.params.end())
-						continue;
+		copyParamLookup[GPDT_MATRIX_4X4] = &copyParam<Matrix4>;
+		copyParamLookup[GPDT_MATRIX_4X2] = &copyParam<Matrix4x2>;
+		copyParamLookup[GPDT_MATRIX_4X3] = &copyParam<Matrix4x3>;
 
-					if (param.second.type != iterFind->second.type)
-						continue;
+		copyParamLookup[GPDT_BOOL] = &copyParam<int>;
+		copyParamLookup[GPDT_COLOR] = &copyParam<Color>;
 
-					UINT32 arraySize = std::min(param.second.arraySize, iterFind->second.arraySize);
-					
-					switch (param.second.type)
-					{
-					case GPDT_FLOAT1:
-						copyParam<float>(oldGpuParams, newGpuParams, param.first, arraySize);
-						break;
-					case GPDT_FLOAT2:
-						copyParam<Vector2>(oldGpuParams, newGpuParams, param.first, arraySize);
-						break;
-					case GPDT_FLOAT3:
-						copyParam<Vector3>(oldGpuParams, newGpuParams, param.first, arraySize);
-						break;
-					case GPDT_FLOAT4:
-						copyParam<Vector4>(oldGpuParams, newGpuParams, param.first, arraySize);
-						break;
-					case GPDT_MATRIX_2X2:
-						copyParam<Matrix2>(oldGpuParams, newGpuParams, param.first, arraySize);
-						break;
-					case GPDT_MATRIX_2X3:
-						copyParam<Matrix2x3>(oldGpuParams, newGpuParams, param.first, arraySize);
-						break;
-					case GPDT_MATRIX_2X4:
-						copyParam<Matrix2x4>(oldGpuParams, newGpuParams, param.first, arraySize);
-						break;
-					case GPDT_MATRIX_3X2:
-						copyParam<Matrix3x2>(oldGpuParams, newGpuParams, param.first, arraySize);
-						break;
-					case GPDT_MATRIX_3X3:
-						copyParam<Matrix3>(oldGpuParams, newGpuParams, param.first, arraySize);
-						break;
-					case GPDT_MATRIX_3X4:
-						copyParam<Matrix3x4>(oldGpuParams, newGpuParams, param.first, arraySize);
-						break;
-					case GPDT_MATRIX_4X2:
-						copyParam<Matrix4x2>(oldGpuParams, newGpuParams, param.first, arraySize);
-						break;
-					case GPDT_MATRIX_4X3:
-						copyParam<Matrix4x3>(oldGpuParams, newGpuParams, param.first, arraySize);
-						break;
-					case GPDT_MATRIX_4X4:
-						copyParam<Matrix4>(oldGpuParams, newGpuParams, param.first, arraySize);
-						break;
-					case GPDT_INT1:
-					case GPDT_BOOL:
-						copyParam<int>(oldGpuParams, newGpuParams, param.first, arraySize);
-						break;
-					case GPDT_INT2:
-						copyParam<Vector2I>(oldGpuParams, newGpuParams, param.first, arraySize);
-						break;
-					case GPDT_INT3:
-						copyParam<Vector3I>(oldGpuParams, newGpuParams, param.first, arraySize);
-						break;
-					case GPDT_INT4:
-						copyParam<Vector4I>(oldGpuParams, newGpuParams, param.first, arraySize);
-						break;
-					case GPDT_COLOR:
-						copyParam<Color>(oldGpuParams, newGpuParams, param.first, arraySize);
-						break;
-					case GPDT_STRUCT:
-					{
-						GpuParamStruct newParam;
-						newGpuParams->getStructParam(param.first, newParam);
+		auto& dataParams = mShader->getDataParams();
+		for (auto& param : dataParams)
+		{
+			UINT32 arraySize = param.second.arraySize > 1 ? param.second.arraySize : 1;
 
-						GpuParamStruct oldParam;
-						oldGpuParams->getStructParam(param.first, oldParam);
+			const MaterialParams::ParamData* paramData = nullptr;
+			auto result = params->getParamData(param.first, MaterialParams::ParamType::Data, param.second.type, 0, &paramData);
 
-						if (param.second.elementSize == iterFind->second.elementSize)
-						{
-							for (UINT32 k = 0; k < arraySize; k++)
-							{
-								UINT8* data = (UINT8*)bs_stack_alloc(param.second.elementSize);
-								oldParam.get(data, param.second.elementSize, k);
-								newParam.set(data, param.second.elementSize, k);
-								bs_stack_free(data);
-							}
-						}
-					}
-					break;
-					}
-				}
+			if (result != MaterialParams::GetParamResult::Success)
+				continue;
 
-				for (auto& param : oldDesc.textures)
-				{
-					auto iterFind = newDesc.textures.find(param.first);
-					if (iterFind == newDesc.textures.end())
-						continue;
+			UINT32 elemsToCopy = std::min(arraySize, paramData->arraySize);
 
-					UINT32 oldSlot = param.second.slot;
-					UINT32 newSlot = iterFind->second.slot;
+			auto& copyFunction = copyParamLookup[param.second.type];
+			if (copyFunction != nullptr)
+				copyFunction(params, this, param.first, paramData->index, elemsToCopy);
+			else
+			{
+				if(param.second.type == GPDT_STRUCT)
+				{
+					TMaterialParamStruct<false> curParam = getParamStruct(param.first);
 
-					bool isLoadStore = oldGpuParams->isLoadStoreTexture(oldSlot);
+					UINT32 structSize = params->getStructSize(paramData->index);
+					if (param.second.elementSize != structSize)
+						continue;
 
-					if (!isLoadStore)
-						newGpuParams->setTexture(newSlot, oldGpuParams->getTexture(oldSlot));
-					else
+					UINT8* structData = (UINT8*)bs_stack_alloc(structSize);
+					for (UINT32 i = 0; i < elemsToCopy; i++)
 					{
-						newGpuParams->setIsLoadStoreTexture(newSlot, true);
-						newGpuParams->setLoadStoreSurface(newSlot, oldGpuParams->getLoadStoreSurface(oldSlot));
+						params->getStructData(paramData->index + i, structData, structSize);
+						curParam.set(structData, structSize, i);
 					}
+
+					bs_stack_free(structData);
 				}
+			}
+		}
 
-				for (auto& param : oldDesc.samplers)
-				{
-					auto iterFind = newDesc.samplers.find(param.first);
-					if (iterFind == newDesc.samplers.end())
-						continue;
+		auto& textureParams = mShader->getTextureParams();
+		for (auto& param : textureParams)
+		{
+			const MaterialParams::ParamData* paramData = nullptr;
+			auto result = params->getParamData(param.first, MaterialParams::ParamType::Texture, GPDT_UNKNOWN, 0, &paramData);
 
-					newGpuParams->setSamplerState(iterFind->second.slot, oldGpuParams->getSamplerState(param.second.slot));
-				}
+			if (result != MaterialParams::GetParamResult::Success)
+				continue;
+
+			bool isLoadStore = params->getIsTextureLoadStore(paramData->index);
+			if(!isLoadStore)
+			{
+				TMaterialParamTexture<false> curParam = getParamTexture(param.first);
+
+				HTexture texture;
+				params->getTexture(paramData->index, texture);
+				curParam.set(texture);
+			}
+			else
+			{
+				TMaterialParamLoadStoreTexture<false> curParam = getParamLoadStoreTexture(param.first);
+
+				HTexture texture;
+				TextureSurface surface;
+				params->getLoadStoreTexture(paramData->index, texture, surface);
+				curParam.set(texture, surface);
 			}
 		}
-	}
 
-	HMaterial Material::clone()
-	{
-		UINT32 bufferSize = 0;
+		auto& samplerParams = mShader->getSamplerParams();
+		for (auto& param : samplerParams)
+		{
+			const MaterialParams::ParamData* paramData = nullptr;
+			auto result = params->getParamData(param.first, MaterialParams::ParamType::Sampler, GPDT_UNKNOWN, 0, &paramData);
 
-		MemorySerializer serializer;
-		UINT8* buffer = serializer.encode(this, bufferSize, (void*(*)(UINT32))&bs_alloc);
+			if (result != MaterialParams::GetParamResult::Success)
+				continue;
 
-		std::shared_ptr<Material> cloneObj = std::static_pointer_cast<Material>(serializer.decode(buffer, bufferSize));
-		bs_free(buffer);
+			TMaterialParamSampState<false> curParam = getParamSamplerState(param.first);
 
-		return static_resource_cast<Material>(gResources()._createResourceHandle(cloneObj));
+			SPtr<SamplerState> samplerState;
+			params->getSamplerState(paramData->index, samplerState);
+			curParam.set(samplerState);
+		}
 	}
 
 	HMaterial Material::create()

+ 31 - 20
BansheeCore/Source/BsMaterialParam.cpp

@@ -6,21 +6,24 @@
 namespace BansheeEngine
 {
 	template<class T>
-	TMaterialDataParam<T, false>::TMaterialDataParam(const String& name, const SPtr<__MaterialParams>& params,
+	TMaterialDataParam<T, false>::TMaterialDataParam(const String& name, const SPtr<MaterialParams>& params,
 		const SPtr<Vector<TGpuDataParam<T, false>>>& gpuParams)
 		:mParamIndex(0), mArraySize(0), mMaterialParams(nullptr), mGPUParams(gpuParams)
 	{
 		if(params != nullptr)
 		{
-			const __MaterialParams::ParamData* data = params->getParamData(name, __MaterialParams::ParamType::Data, 
-				__MaterialParams::getDataType(T()), 0);
+			const MaterialParams::ParamData* data = nullptr;
+			auto result = params->getParamData(name, MaterialParams::ParamType::Data, 
+				(GpuParamDataType)TGpuDataParamInfo<T>::TypeId, 0, &data);
 
-			if(data != nullptr)
+			if (result == MaterialParams::GetParamResult::Success)
 			{
 				mMaterialParams = params;
 				mParamIndex = data->index;
 				mArraySize = data->arraySize;
 			}
+			else
+				params->reportGetParamError(result, name, 0);
 		}
 	}
 
@@ -81,21 +84,23 @@ namespace BansheeEngine
 		return (*mParams)[0].get(arrayIdx); // They should all have the same value
 	}
 
-	TMaterialParamStruct<false>::TMaterialParamStruct(const String& name, const SPtr<__MaterialParams>& params, 
+	TMaterialParamStruct<false>::TMaterialParamStruct(const String& name, const SPtr<MaterialParams>& params, 
 		const SPtr<Vector<TGpuParamStruct<false>>>& gpuParams)
 		:mParamIndex(0), mArraySize(0), mMaterialParams(nullptr), mGPUParams(gpuParams)
 	{
 		if (params != nullptr)
 		{
-			const __MaterialParams::ParamData* data = params->getParamData(name, __MaterialParams::ParamType::Data,
-				GPDT_STRUCT, 0);
+			const MaterialParams::ParamData* data = nullptr;
+			auto result = params->getParamData(name, MaterialParams::ParamType::Data, GPDT_STRUCT, 0, &data);
 
-			if (data != nullptr)
+			if (result == MaterialParams::GetParamResult::Success)
 			{
 				mMaterialParams = params;
 				mParamIndex = data->index;
 				mArraySize = data->arraySize;
 			}
+			else
+				params->reportGetParamError(result, name, 0);
 		}
 	}
 
@@ -165,20 +170,22 @@ namespace BansheeEngine
 		return (*mParams)[0].getElementSize();
 	}
 
-	TMaterialParamTexture<false>::TMaterialParamTexture(const String& name, const SPtr<__MaterialParams>& params, 
+	TMaterialParamTexture<false>::TMaterialParamTexture(const String& name, const SPtr<MaterialParams>& params, 
 		const SPtr<Vector<TGpuParamTexture<false>>>& gpuParams)
 		:mParamIndex(0), mMaterialParams(nullptr), mGPUParams(gpuParams)
 	{
 		if (params != nullptr)
 		{
-			const __MaterialParams::ParamData* data = params->getParamData(name, __MaterialParams::ParamType::Texture,
-				GPDT_UNKNOWN, 0);
+			const MaterialParams::ParamData* data = nullptr;
+			auto result = params->getParamData(name, MaterialParams::ParamType::Texture, GPDT_UNKNOWN, 0, &data);
 
-			if (data != nullptr)
+			if (result == MaterialParams::GetParamResult::Success)
 			{
 				mMaterialParams = params;
 				mParamIndex = data->index;
 			}
+			else
+				params->reportGetParamError(result, name, 0);
 		}
 	}
 
@@ -228,20 +235,22 @@ namespace BansheeEngine
 		return (*mParams)[0].get(); // They should all have the same value
 	}
 
-	TMaterialParamLoadStoreTexture<false>::TMaterialParamLoadStoreTexture(const String& name, const SPtr<__MaterialParams>& params, 
+	TMaterialParamLoadStoreTexture<false>::TMaterialParamLoadStoreTexture(const String& name, const SPtr<MaterialParams>& params, 
 		const SPtr<Vector<TGpuParamLoadStoreTexture<false>>>& gpuParams)
 		:mParamIndex(0), mMaterialParams(nullptr), mGPUParams(gpuParams)
 	{
 		if (params != nullptr)
 		{
-			const __MaterialParams::ParamData* data = params->getParamData(name, __MaterialParams::ParamType::Texture,
-				GPDT_UNKNOWN, 0);
+			const MaterialParams::ParamData* data = nullptr;
+			auto result = params->getParamData(name, MaterialParams::ParamType::Texture, GPDT_UNKNOWN, 0, &data);
 
-			if (data != nullptr)
+			if (result == MaterialParams::GetParamResult::Success)
 			{
 				mMaterialParams = params;
 				mParamIndex = data->index;
 			}
+			else
+				params->reportGetParamError(result, name, 0);
 		}
 	}
 
@@ -292,20 +301,22 @@ namespace BansheeEngine
 		return (*mParams)[0].get(); // They should all have the same value
 	}
 
-	TMaterialParamSampState<false>::TMaterialParamSampState(const String& name, const SPtr<__MaterialParams>& params, 
+	TMaterialParamSampState<false>::TMaterialParamSampState(const String& name, const SPtr<MaterialParams>& params, 
 		const SPtr<Vector<TGpuParamSampState<false>>>& gpuParams)
 		:mParamIndex(0), mMaterialParams(nullptr), mGPUParams(gpuParams)
 	{
 		if (params != nullptr)
 		{
-			const __MaterialParams::ParamData* data = params->getParamData(name, __MaterialParams::ParamType::Sampler,
-				GPDT_UNKNOWN, 0);
+			const MaterialParams::ParamData* data = nullptr;
+			auto result = params->getParamData(name, MaterialParams::ParamType::Sampler, GPDT_UNKNOWN, 0, &data);
 
-			if (data != nullptr)
+			if (result == MaterialParams::GetParamResult::Success)
 			{
 				mMaterialParams = params;
 				mParamIndex = data->index;
 			}
+			else
+				params->reportGetParamError(result, name, 0);
 		}
 	}
 

+ 132 - 45
BansheeCore/Source/BsMaterialParams.cpp

@@ -1,13 +1,15 @@
 #include "BsMaterialParams.h"
+#include "BsMaterialParamsRTTI.h"
 #include "BsProfilerCPU.h"
+#include "BsShader.h"
 
 namespace BansheeEngine
 {
-	__MaterialParams::__MaterialParams(const HShader& shader)
+	MaterialParams::MaterialParams(const HShader& shader)
 	{
 		gProfilerCPU().beginSample("Create material params");
 
-		UINT32 bufferSize = 0;
+		mDataSize = 0;
 
 		auto& dataParams = shader->getDataParams();
 		for (auto& param : dataParams)
@@ -16,7 +18,7 @@ namespace BansheeEngine
 			const GpuParamDataTypeInfo& typeInfo = GpuParams::PARAM_SIZES.lookup[(int)param.second.type];
 			UINT32 paramSize = typeInfo.numColumns * typeInfo.numRows * typeInfo.baseTypeSize;
 
-			bufferSize += arraySize * paramSize;
+			mDataSize += arraySize * paramSize;
 
 		}
 
@@ -26,8 +28,8 @@ namespace BansheeEngine
 		mNumTextureParams = (UINT32)textureParams.size();
 		mNumSamplerParams = (UINT32)samplerParams.size();
 
-		mDataParamsBuffer = mAlloc.alloc(bufferSize);
-		memset(mDataParamsBuffer, 0, bufferSize);
+		mDataParamsBuffer = mAlloc.alloc(mDataSize);
+		memset(mDataParamsBuffer, 0, mDataSize);
 
 		mStructParams = mAlloc.construct<StructParamData>(mNumStructParams);
 		mTextureParams = mAlloc.construct<TextureParamData>(mNumTextureParams);
@@ -97,7 +99,7 @@ namespace BansheeEngine
 		gProfilerCPU().endSample("Create material params");
 	}
 
-	__MaterialParams::~__MaterialParams()
+	MaterialParams::~MaterialParams()
 	{
 		if (mStructParams != nullptr)
 		{
@@ -113,106 +115,156 @@ namespace BansheeEngine
 		mAlloc.clear();
 	}
 
-	void __MaterialParams::getStructData(const String& name, void* value, UINT32 size, UINT32 arrayIdx) const
+	void MaterialParams::getStructData(const String& name, void* value, UINT32 size, UINT32 arrayIdx) const
 	{
-		const ParamData* param = getParamData(name, ParamType::Data, GPDT_STRUCT, arrayIdx);
-		if (param == nullptr)
+		const ParamData* param = nullptr;
+		GetParamResult result = getParamData(name, ParamType::Data, GPDT_STRUCT, arrayIdx, &param);
+		if (result != GetParamResult::Success)
+		{
+			reportGetParamError(result, name, arrayIdx);
 			return;
+		}
 
 		getStructData(param->index + arrayIdx, value, size);
 	}
 
-	void __MaterialParams::setStructData(const String& name, const void* value, UINT32 size, UINT32 arrayIdx)
+	void MaterialParams::setStructData(const String& name, const void* value, UINT32 size, UINT32 arrayIdx)
 	{
-		const ParamData* param = getParamData(name, ParamType::Data, GPDT_STRUCT, arrayIdx);
-		if (param == nullptr)
+		const ParamData* param = nullptr;
+		GetParamResult result = getParamData(name, ParamType::Data, GPDT_STRUCT, arrayIdx, &param);
+		if (result != GetParamResult::Success)
+		{
+			reportGetParamError(result, name, arrayIdx);
 			return;
+		}
 
 		setStructData(param->index + arrayIdx, value, size);
 	}
 
-	void __MaterialParams::getTexture(const String& name, HTexture& value) const
+	void MaterialParams::getTexture(const String& name, HTexture& value) const
 	{
-		const ParamData* param = getParamData(name, ParamType::Texture, GPDT_UNKNOWN, 0);
-		if (param == nullptr)
+		const ParamData* param = nullptr;
+		GetParamResult result = getParamData(name, ParamType::Texture, GPDT_UNKNOWN, 0, &param);
+		if (result != GetParamResult::Success)
+		{
+			reportGetParamError(result, name, 0);
 			return;
+		}
 
 		getTexture(param->index, value);
 	}
 
-	void __MaterialParams::setTexture(const String& name, const HTexture& value)
+	void MaterialParams::setTexture(const String& name, const HTexture& value)
 	{
-		const ParamData* param = getParamData(name, ParamType::Texture, GPDT_UNKNOWN, 0);
-		if (param == nullptr)
+		const ParamData* param = nullptr;
+		GetParamResult result = getParamData(name, ParamType::Texture, GPDT_UNKNOWN, 0, &param);
+		if (result != GetParamResult::Success)
+		{
+			reportGetParamError(result, name, 0);
 			return;
+		}
 
 		setTexture(param->index, value);
 	}
 
-	void __MaterialParams::getLoadStoreTexture(const String& name, HTexture& value, TextureSurface& surface) const
+	void MaterialParams::getLoadStoreTexture(const String& name, HTexture& value, TextureSurface& surface) const
 	{
-		const ParamData* param = getParamData(name, ParamType::Texture, GPDT_UNKNOWN, 0);
-		if (param == nullptr)
+		const ParamData* param = nullptr;
+		GetParamResult result = getParamData(name, ParamType::Texture, GPDT_UNKNOWN, 0, &param);
+		if (result != GetParamResult::Success)
+		{
+			reportGetParamError(result, name, 0);
 			return;
+		}
 
 		getLoadStoreTexture(param->index, value, surface);
 	}
 
-	void __MaterialParams::setLoadStoreTexture(const String& name, const HTexture& value, const TextureSurface& surface)
+	void MaterialParams::setLoadStoreTexture(const String& name, const HTexture& value, const TextureSurface& surface)
 	{
-		const ParamData* param = getParamData(name, ParamType::Texture, GPDT_UNKNOWN, 0);
-		if (param == nullptr)
+		const ParamData* param = nullptr;
+		GetParamResult result = getParamData(name, ParamType::Texture, GPDT_UNKNOWN, 0, &param);
+		if (result != GetParamResult::Success)
+		{
+			reportGetParamError(result, name, 0);
 			return;
+		}
 
 		setLoadStoreTexture(param->index, value, surface);
 	}
 
-	void __MaterialParams::getSamplerState(const String& name, SamplerStatePtr& value) const
+	void MaterialParams::getSamplerState(const String& name, SamplerStatePtr& value) const
 	{
-		const ParamData* param = getParamData(name, ParamType::Sampler, GPDT_UNKNOWN, 0);
-		if (param == nullptr)
+		const ParamData* param = nullptr;
+		GetParamResult result = getParamData(name, ParamType::Sampler, GPDT_UNKNOWN, 0, &param);
+		if (result != GetParamResult::Success)
+		{
+			reportGetParamError(result, name, 0);
 			return;
+		}
 
 		getSamplerState(param->index, value);
 	}
 
-	void __MaterialParams::setSamplerState(const String& name, const SamplerStatePtr& value)
+	void MaterialParams::setSamplerState(const String& name, const SamplerStatePtr& value)
 	{
-		const ParamData* param = getParamData(name, ParamType::Sampler, GPDT_UNKNOWN, 0);
-		if (param == nullptr)
+		const ParamData* param = nullptr;
+		GetParamResult result = getParamData(name, ParamType::Sampler, GPDT_UNKNOWN, 0, &param);
+		if(result != GetParamResult::Success)
+		{
+			reportGetParamError(result, name, 0);
 			return;
+		}
 
 		setSamplerState(param->index, value);
 	}
 
-	const __MaterialParams::ParamData* __MaterialParams::getParamData(const String& name, ParamType type, GpuParamDataType dataType,
-		UINT32 arrayIdx) const
+	MaterialParams::GetParamResult MaterialParams::getParamData(const String& name, ParamType type, GpuParamDataType dataType,
+		UINT32 arrayIdx, const ParamData** output) const
 	{
 		auto iterFind = mParams.find(name);
 		if (iterFind == mParams.end())
 		{
 			LOGWRN("Material doesn't have a parameter named " + name + ".");
-			return nullptr;
+			return GetParamResult::NotFound;
 		}
 
 		const ParamData& param = iterFind->second;
+		*output = &param;
+
 		if (param.type != type || (type == ParamType::Data && param.dataType != dataType))
 		{
 			LOGWRN("Parameter \"" + name + "\" is not of the requested type.");
-			return nullptr;
+			return GetParamResult::InvalidType;
 		}
 
 		if (arrayIdx >= param.arraySize)
 		{
 			LOGWRN("Parameter \"" + name + "\" array index " + toString(arrayIdx) + " out of range. Array length is " +
 				toString(param.arraySize) + ".");
-			return nullptr;
+			return GetParamResult::IndexOutOfBounds;
 		}
 
-		return &param;
+		return GetParamResult::Success;
 	}
 
-	void __MaterialParams::getStructData(UINT32 index, void* value, UINT32 size) const
+	void MaterialParams::reportGetParamError(GetParamResult errorCode, const String& name, UINT32 arrayIdx) const
+	{
+		switch(errorCode)
+		{
+		case GetParamResult::NotFound:
+			LOGWRN("Material doesn't have a parameter named " + name + ".");
+			break;
+		case GetParamResult::InvalidType:
+			LOGWRN("Parameter \"" + name + "\" is not of the requested type.");
+			break;
+		case GetParamResult::IndexOutOfBounds:
+			LOGWRN("Parameter \"" + name + "\" array index " + toString(arrayIdx) + " out of range.");
+			break;
+		}
+	}
+
+	void MaterialParams::getStructData(UINT32 index, void* value, UINT32 size) const
 	{
 		const StructParamData& structParam = mStructParams[index];
 		if (structParam.dataSize != size)
@@ -225,7 +277,7 @@ namespace BansheeEngine
 		memcpy(value, structParam.data, structParam.dataSize);
 	}
 
-	void __MaterialParams::setStructData(UINT32 index, const void* value, UINT32 size)
+	void MaterialParams::setStructData(UINT32 index, const void* value, UINT32 size)
 	{
 		const StructParamData& structParam = mStructParams[index];
 		if (structParam.dataSize != size)
@@ -238,33 +290,33 @@ namespace BansheeEngine
 		memcpy(structParam.data, value, structParam.dataSize);
 	}
 
-	UINT32 __MaterialParams::getStructSize(UINT32 index) const
+	UINT32 MaterialParams::getStructSize(UINT32 index) const
 	{
 		const StructParamData& structParam = mStructParams[index];
 		return structParam.dataSize;
 	}
 
-	void __MaterialParams::getTexture(UINT32 index, HTexture& value) const
+	void MaterialParams::getTexture(UINT32 index, HTexture& value) const
 	{
 		TextureParamData& textureParam = mTextureParams[index];
 		value = textureParam.value;
 	}
 
-	void __MaterialParams::setTexture(UINT32 index, const HTexture& value)
+	void MaterialParams::setTexture(UINT32 index, const HTexture& value)
 	{
 		TextureParamData& textureParam = mTextureParams[index];
 		textureParam.value = value;
 		textureParam.isLoadStore = false;
 	}
 
-	void __MaterialParams::getLoadStoreTexture(UINT32 index, HTexture& value, TextureSurface& surface) const
+	void MaterialParams::getLoadStoreTexture(UINT32 index, HTexture& value, TextureSurface& surface) const
 	{
 		TextureParamData& textureParam = mTextureParams[index];
 		value = textureParam.value;
 		surface = textureParam.surface;
 	}
 
-	void __MaterialParams::setLoadStoreTexture(UINT32 index, const HTexture& value, const TextureSurface& surface)
+	void MaterialParams::setLoadStoreTexture(UINT32 index, const HTexture& value, const TextureSurface& surface)
 	{
 		TextureParamData& textureParam = mTextureParams[index];
 		textureParam.value = value;
@@ -272,13 +324,48 @@ namespace BansheeEngine
 		textureParam.surface = surface;
 	}
 
-	void __MaterialParams::getSamplerState(UINT32 index, SamplerStatePtr& value) const
+	bool MaterialParams::getIsTextureLoadStore(UINT32 index) const
+	{
+		return mTextureParams[index].isLoadStore;
+	}
+
+	void MaterialParams::getSamplerState(UINT32 index, SamplerStatePtr& value) const
 	{
 		value = mSamplerStateParams[index];
 	}
 
-	void __MaterialParams::setSamplerState(UINT32 index, const SamplerStatePtr& value)
+	void MaterialParams::setSamplerState(UINT32 index, const SamplerStatePtr& value)
 	{
 		mSamplerStateParams[index] = value;
 	}
+
+	RTTITypeBase* MaterialParams::TextureParamData::getRTTIStatic()
+	{
+		return TextureParamDataRTTI::instance();
+	}
+
+	RTTITypeBase* MaterialParams::TextureParamData::getRTTI() const
+	{
+		return getRTTIStatic();
+	}
+
+	RTTITypeBase* MaterialParams::StructParamData::getRTTIStatic()
+	{
+		return StructParamDataRTTI::instance();
+	}
+
+	RTTITypeBase* MaterialParams::StructParamData::getRTTI() const
+	{
+		return getRTTIStatic();
+	}
+
+	RTTITypeBase* MaterialParams::getRTTIStatic()
+	{
+		return MaterialParamsRTTI::instance();
+	}
+
+	RTTITypeBase* MaterialParams::getRTTI() const
+	{
+		return MaterialParams::getRTTIStatic();
+	}
 }

+ 26 - 358
BansheeCore/Source/BsMaterialRTTI.cpp

@@ -1,359 +1,27 @@
-#include "BsMaterialRTTI.h"
-#include "BsMaterialManager.h"
-#include "BsGpuParamDesc.h"
-
-namespace BansheeEngine
-{
-	RTTITypeBase* MaterialFloatParam::getRTTIStatic() { return MaterialFloatParamRTTI::instance(); }
-	RTTITypeBase* MaterialFloatParam::getRTTI() const { return MaterialFloatParam::getRTTIStatic(); }
-
-	RTTITypeBase* MaterialVec2Param::getRTTIStatic() { return MaterialVec2ParamRTTI::instance(); }
-	RTTITypeBase* MaterialVec2Param::getRTTI() const { return MaterialVec2Param::getRTTIStatic(); }
-
-	RTTITypeBase* MaterialVec3Param::getRTTIStatic() { return MaterialVec3ParamRTTI::instance(); }
-	RTTITypeBase* MaterialVec3Param::getRTTI() const { return MaterialVec3Param::getRTTIStatic(); }
-
-	RTTITypeBase* MaterialVec4Param::getRTTIStatic() { return MaterialVec4ParamRTTI::instance(); }
-	RTTITypeBase* MaterialVec4Param::getRTTI() const { return MaterialVec4Param::getRTTIStatic(); }
-
-	RTTITypeBase* MaterialColorParam::getRTTIStatic() { return MaterialColorParamRTTI::instance(); }
-	RTTITypeBase* MaterialColorParam::getRTTI() const { return MaterialColorParam::getRTTIStatic(); }
-
-	RTTITypeBase* MaterialMat3Param::getRTTIStatic() { return MaterialMat3ParamRTTI::instance(); }
-	RTTITypeBase* MaterialMat3Param::getRTTI() const { return MaterialMat3Param::getRTTIStatic(); }
-
-	RTTITypeBase* MaterialMat4Param::getRTTIStatic() { return MaterialMat4ParamRTTI::instance(); }
-	RTTITypeBase* MaterialMat4Param::getRTTI() const { return MaterialMat4Param::getRTTIStatic(); }
-
-	RTTITypeBase* MaterialStructParam::getRTTIStatic() { return MaterialStructParamRTTI::instance(); }
-	RTTITypeBase* MaterialStructParam::getRTTI() const { return MaterialStructParam::getRTTIStatic(); }
-
-	RTTITypeBase* MaterialTextureParam::getRTTIStatic() { return MaterialTextureParamRTTI::instance(); }
-	RTTITypeBase* MaterialTextureParam::getRTTI() const { return MaterialTextureParam::getRTTIStatic(); }
-
-	RTTITypeBase* MaterialSamplerStateParam::getRTTIStatic() { return MaterialSamplerStateParamRTTI::instance(); }
-	RTTITypeBase* MaterialSamplerStateParam::getRTTI() const { return MaterialSamplerStateParam::getRTTIStatic(); }
-
-	RTTITypeBase* MaterialParams::getRTTIStatic() { return MaterialParamsRTTI::instance(); }
-	RTTITypeBase* MaterialParams::getRTTI() const { return MaterialParams::getRTTIStatic(); }
-
-	void MaterialRTTI::onSerializationStarted(IReflectable* obj)
-	{
-		Material* material = static_cast<Material*>(obj);
-		std::shared_ptr<MaterialParams> params = bs_shared_ptr_new<MaterialParams>();
-
-		HShader shader = material->getShader();
-		if(shader.isLoaded())
-		{
-			const Map<String, String>& validParamNames = material->getValidParamNames();
-
-			for(auto iter = validParamNames.begin(); iter != validParamNames.end(); ++iter)
-			{
-				GpuParamType type = shader->getParamType(iter->first);
-
-				if(type == GPT_DATA)
-				{
-					const SHADER_DATA_PARAM_DESC& paramDesc = shader->getDataParamDesc(iter->first);
-
-					switch(paramDesc.type)
-					{
-					case GPDT_FLOAT1:
-						{
-							for(UINT32 i = 0; i < paramDesc.arraySize; i++)
-							{
-								MaterialFloatParam param;
-								param.name = iter->first;
-								param.value = material->getFloat(iter->first, i);
-								param.arrayIdx = i;
-
-								params->floatParams.push_back(param);
-							}
-						}
-						break;
-					case GPDT_FLOAT2:
-						{
-							for(UINT32 i = 0; i < paramDesc.arraySize; i++)
-							{
-								MaterialVec2Param param;
-								param.name = iter->first;
-								param.value = material->getVec2(iter->first, i);
-								param.arrayIdx = i;
-
-								params->vec2Params.push_back(param);
-							}
-						}
-						break;
-					case GPDT_FLOAT3:
-						{
-							for(UINT32 i = 0; i < paramDesc.arraySize; i++)
-							{
-								MaterialVec3Param param;
-								param.name = iter->first;
-								param.value = material->getVec3(iter->first, i);
-								param.arrayIdx = i;
-
-								params->vec3Params.push_back(param);
-							}
-						}
-						break;
-					case GPDT_FLOAT4:
-						{
-							for(UINT32 i = 0; i < paramDesc.arraySize; i++)
-							{
-								MaterialVec4Param param;
-								param.name = iter->first;
-								param.value = material->getVec4(iter->first, i);
-								param.arrayIdx = i;
-
-								params->vec4Params.push_back(param);
-							}
-						}
-						break;
-					case GPDT_COLOR:
-						{
-							for (UINT32 i = 0; i < paramDesc.arraySize; i++)
-							{
-								MaterialColorParam param;
-								param.name = iter->first;
-								param.value = material->getColor(iter->first, i);
-								param.arrayIdx = i;
-
-								params->colorParams.push_back(param);
-							}
-						}
-						break;
-					case GPDT_MATRIX_3X3:
-						{
-							for(UINT32 i = 0; i < paramDesc.arraySize; i++)
-							{
-								MaterialMat3Param param;
-								param.name = iter->first;
-								param.value = material->getMat3(iter->first, i);
-								param.arrayIdx = i;
-
-								params->mat3Params.push_back(param);
-							}
-						}
-						break;
-					case GPDT_MATRIX_4X4:
-						{
-							for(UINT32 i = 0; i < paramDesc.arraySize; i++)
-							{
-								MaterialMat4Param param;
-								param.name = iter->first;
-								param.value = material->getMat4(iter->first, i);
-								param.arrayIdx = i;
-
-								params->mat4Params.push_back(param);
-							}
-						}
-						break;
-					case GPDT_STRUCT:
-						{
-							for(UINT32 i = 0; i < paramDesc.arraySize; i++)
-							{
-								MaterialStructParam param;
-								param.name = iter->first;
-								param.value = material->getStructData(iter->first, i);
-								param.arrayIdx = i;
-								param.elementSize = paramDesc.elementSize;
-
-								params->structParams.push_back(param);
-							}
-						}
-						break;
-					default:
-						BS_EXCEPT(InternalErrorException, "Cannot serialize this paramater type: " + toString(paramDesc.type));
-					}
-				}
-				else if(type == GPT_TEXTURE)
-				{
-					const SHADER_OBJECT_PARAM_DESC& paramDesc = shader->getTextureParamDesc(iter->first);
-
-					MaterialTextureParam param;
-					param.name = iter->first;
-					param.value = material->getTexture(iter->first);
-
-					params->textureParams.push_back(param);
-				}
-				else if (type == GPT_SAMPLER)
-				{
-					const SHADER_OBJECT_PARAM_DESC& paramDesc = shader->getSamplerParamDesc(iter->first);
-
-					MaterialSamplerStateParam param;
-					param.name = iter->first;
-					param.value = material->getSamplerState(iter->first);
-
-					params->samplerStateParams.push_back(param);
-				}
-				else if (type == GPT_BUFFER)
-				{
-					BS_EXCEPT(NotImplementedException, "Buffers can't be serialized yet.");
-				}
-				else
-					BS_EXCEPT(InternalErrorException, "Invalid parameter type.");
-
-			}
-		}
-
-		material->mRTTIData = params;
-	}
-
-	void MaterialRTTI::onSerializationEnded(IReflectable* obj)
-	{
-		Material* material = static_cast<Material*>(obj);
-
-		material->mRTTIData = nullptr; // This will delete temporary data as it's stored in a unique ptr
-	}
-
-	void MaterialRTTI::onDeserializationStarted(IReflectable* obj)
-	{
-		// Do nothing
-	}
-
-	void MaterialRTTI::onDeserializationEnded(IReflectable* obj)
-	{
-		Material* material = static_cast<Material*>(obj);
-		material->initialize();
-
-		if(material->mRTTIData.empty())
-			return;
-
-		material->initBestTechnique();
-
-		std::shared_ptr<MaterialParams> params = any_cast<std::shared_ptr<MaterialParams>>(material->mRTTIData);
-
-		HShader shader = material->getShader();
-		if(shader.isLoaded(false))
-		{
-			for(auto iter = params->floatParams.begin(); iter != params->floatParams.end(); ++iter)
-			{
-				if(!shader->hasDataParam(iter->name))
-					continue;
-
-				const SHADER_DATA_PARAM_DESC& paramDesc = shader->getDataParamDesc(iter->name);
-
-				if(paramDesc.type != GPDT_FLOAT1 || iter->arrayIdx < 0 || iter->arrayIdx >= paramDesc.arraySize)
-					continue;
-
-				material->setFloat(iter->name, iter->value, iter->arrayIdx);
-			}
-
-			for(auto iter = params->vec2Params.begin(); iter != params->vec2Params.end(); ++iter)
-			{
-				if(!shader->hasDataParam(iter->name))
-					continue;
-
-				const SHADER_DATA_PARAM_DESC& paramDesc = shader->getDataParamDesc(iter->name);
-
-				if(paramDesc.type != GPDT_FLOAT2 || iter->arrayIdx < 0 || iter->arrayIdx >= paramDesc.arraySize)
-					continue;
-
-				material->setVec2(iter->name, iter->value, iter->arrayIdx);
-			}
-
-			for(auto iter = params->vec3Params.begin(); iter != params->vec3Params.end(); ++iter)
-			{
-				if(!shader->hasDataParam(iter->name))
-					continue;
-
-				const SHADER_DATA_PARAM_DESC& paramDesc = shader->getDataParamDesc(iter->name);
-
-				if(paramDesc.type != GPDT_FLOAT3 || iter->arrayIdx < 0 || iter->arrayIdx >= paramDesc.arraySize)
-					continue;
-
-				material->setVec3(iter->name, iter->value, iter->arrayIdx);
-			}
-
-			for(auto iter = params->vec4Params.begin(); iter != params->vec4Params.end(); ++iter)
-			{
-				if(!shader->hasDataParam(iter->name))
-					continue;
-
-				const SHADER_DATA_PARAM_DESC& paramDesc = shader->getDataParamDesc(iter->name);
-
-				if(paramDesc.type != GPDT_FLOAT4 || iter->arrayIdx < 0 || iter->arrayIdx >= paramDesc.arraySize)
-					continue;
-
-				material->setVec4(iter->name, iter->value, iter->arrayIdx);
-			}
-
-			for (auto iter = params->colorParams.begin(); iter != params->colorParams.end(); ++iter)
-			{
-				if (!shader->hasDataParam(iter->name))
-					continue;
-
-				const SHADER_DATA_PARAM_DESC& paramDesc = shader->getDataParamDesc(iter->name);
-
-				if (paramDesc.type != GPDT_COLOR || iter->arrayIdx < 0 || iter->arrayIdx >= paramDesc.arraySize)
-					continue;
-
-				material->setColor(iter->name, iter->value, iter->arrayIdx);
-			}
-
-			for(auto iter = params->mat3Params.begin(); iter != params->mat3Params.end(); ++iter)
-			{
-				if(!shader->hasDataParam(iter->name))
-					continue;
-
-				const SHADER_DATA_PARAM_DESC& paramDesc = shader->getDataParamDesc(iter->name);
-
-				if(paramDesc.type != GPDT_MATRIX_3X3 || iter->arrayIdx < 0 || iter->arrayIdx >= paramDesc.arraySize)
-					continue;
-
-				material->setMat3(iter->name, iter->value, iter->arrayIdx);
-			}
-
-			for(auto iter = params->mat4Params.begin(); iter != params->mat4Params.end(); ++iter)
-			{
-				if(!shader->hasDataParam(iter->name))
-					continue;
-
-				const SHADER_DATA_PARAM_DESC& paramDesc = shader->getDataParamDesc(iter->name);
-
-				if(paramDesc.type != GPDT_MATRIX_4X4 || iter->arrayIdx < 0 || iter->arrayIdx >= paramDesc.arraySize)
-					continue;
-
-				material->setMat4(iter->name, iter->value, iter->arrayIdx);
-			}
-
-			for(auto iter = params->structParams.begin(); iter != params->structParams.end(); ++iter)
-			{
-				if(!shader->hasDataParam(iter->name))
-					continue;
-
-				const SHADER_DATA_PARAM_DESC& paramDesc = shader->getDataParamDesc(iter->name);
-
-				if(paramDesc.type != GPDT_STRUCT || iter->arrayIdx < 0 || iter->arrayIdx >= paramDesc.arraySize || iter->elementSize != paramDesc.elementSize)
-					continue;
-
-				material->setStructData(iter->name, iter->value.data.get(), iter->value.size, iter->arrayIdx);
-			}
-
-			for(auto iter = params->samplerStateParams.begin(); iter != params->samplerStateParams.end(); ++iter)
-			{
-				if(!shader->hasSamplerParam(iter->name))
-					continue;
-
-				const SHADER_OBJECT_PARAM_DESC& paramDesc = shader->getSamplerParamDesc(iter->name);
-				material->setSamplerState(iter->name, iter->value);
-			}
-
-			for(auto iter = params->textureParams.begin(); iter != params->textureParams.end(); ++iter)
-			{
-				if(!shader->hasTextureParam(iter->name))
-					continue;
-
-				const SHADER_OBJECT_PARAM_DESC& paramDesc = shader->getTextureParamDesc(iter->name);
-				material->setTexture(iter->name, iter->value);
-			}
-		}
-
-		material->mRTTIData = nullptr; // This will delete temporary data as it's stored in a unique ptr
-	}
-
-	std::shared_ptr<IReflectable> MaterialRTTI::newRTTIObject()
-	{
-		return MaterialManager::instance().createEmpty();
-	}
+#include "BsMaterialRTTI.h"
+#include "BsMaterialManager.h"
+#include "BsMaterialParams.h"
+
+namespace BansheeEngine
+{
+	void MaterialRTTI::onDeserializationEnded(IReflectable* obj)
+	{
+		Material* material = static_cast<Material*>(obj);
+		material->initialize();
+
+		if(material->mRTTIData.empty())
+			return;
+
+		material->initBestTechnique();
+
+		std::shared_ptr<MaterialParams> params = any_cast<std::shared_ptr<MaterialParams>>(material->mRTTIData);
+		material->setParams(params);
+
+		material->mRTTIData = nullptr; // Delete temporary data
+	}
+
+	std::shared_ptr<IReflectable> MaterialRTTI::newRTTIObject()
+	{
+		return MaterialManager::instance().createEmpty();
+	}
 }

+ 1 - 4
BansheeUtility/Include/BsManagedDataBlock.h

@@ -23,10 +23,8 @@ namespace BansheeEngine
 		 * @param[in] 	data			Array of bytes to store. Direct pointer to the provided array will be stored, 
 		 *								no copying will be done. 
 		 * @param[in]	size			Size of the array, in bytes.
-		 * @param[in]	deallocator		Deallocator that will be used for freeing the data. If null, the default deallocator 
-		 *								will be used.	
 		 */
-		ManagedDataBlock(UINT8* data, UINT32 size, std::function<void(UINT8*)> deallocator = nullptr); 
+		ManagedDataBlock(UINT8* data, UINT32 size); 
 
 		/**
 		 * Constructor that will automatically allocate an internal buffer of the specified size. Copying ManagedDataBlock 
@@ -47,7 +45,6 @@ namespace BansheeEngine
 		UINT8* mData;
 		UINT32 mSize;
 		bool mManaged;
-		std::function<void(UINT8*)> mDeallocator;
 		mutable bool mIsDataOwner;
 	};
 

+ 1 - 1
BansheeUtility/Include/BsSerializedObject.h

@@ -97,7 +97,7 @@ namespace BansheeEngine
 	struct BS_UTILITY_EXPORT SerializedObject : SerializedInstance
 	{
 		/** Returns the RTTI type ID for the most-derived class of this object. */
-		UINT32 getRootTypeId() const { return subObjects[0].typeId; }
+		UINT32 getRootTypeId() const;
 
 		/** @copydoc SerializedInstance::clone */
 		SPtr<SerializedInstance> clone(bool cloneData = true) override;

+ 30 - 36
BansheeUtility/Source/BsManagedDataBlock.cpp

@@ -1,37 +1,31 @@
-#include "BsManagedDataBlock.h"
-#include "BsException.h"
-
-namespace BansheeEngine
-{
-	ManagedDataBlock::ManagedDataBlock(UINT8* data, UINT32 size, std::function<void(UINT8*)> deallocator)
-		:mData(data), mSize(size), mManaged(false), mIsDataOwner(true), mDeallocator(deallocator)
-	{ }
-
-	ManagedDataBlock::ManagedDataBlock(UINT32 size)
-		:mSize(size), mManaged(true), mIsDataOwner(true), mDeallocator(nullptr)
-	{
-		mData = (UINT8*)bs_alloc(size);
-	}
-
-	ManagedDataBlock::ManagedDataBlock(const ManagedDataBlock& source)
-	{
-		mData = source.mData;
-		mSize = source.mSize;
-		mManaged = source.mManaged;
-		mDeallocator = source.mDeallocator;
-
-		mIsDataOwner = true;
-		source.mIsDataOwner = false;
-	}
-
-	ManagedDataBlock::~ManagedDataBlock()
-	{
-		if(mManaged && mIsDataOwner)
-		{
-			if(mDeallocator != nullptr)
-				mDeallocator(mData);
-			else
-				bs_free(mData);
-		}
-	}
+#include "BsManagedDataBlock.h"
+#include "BsException.h"
+
+namespace BansheeEngine
+{
+	ManagedDataBlock::ManagedDataBlock(UINT8* data, UINT32 size)
+		:mData(data), mSize(size), mManaged(false), mIsDataOwner(true)
+	{ }
+
+	ManagedDataBlock::ManagedDataBlock(UINT32 size)
+		:mSize(size), mManaged(true), mIsDataOwner(true)
+	{
+		mData = (UINT8*)bs_alloc(size);
+	}
+
+	ManagedDataBlock::ManagedDataBlock(const ManagedDataBlock& source)
+	{
+		mData = source.mData;
+		mSize = source.mSize;
+		mManaged = source.mManaged;
+
+		mIsDataOwner = true;
+		source.mIsDataOwner = false;
+	}
+
+	ManagedDataBlock::~ManagedDataBlock()
+	{
+		if(mManaged && mIsDataOwner)
+			bs_free(mData);
+	}
 }

+ 144 - 136
BansheeUtility/Source/BsSerializedObject.cpp

@@ -1,137 +1,145 @@
-#include "BsSerializedObject.h"
-#include "BsSerializedObjectRTTI.h"
-
-namespace BansheeEngine
-{
-	SPtr<SerializedInstance> SerializedField::clone(bool cloneData)
-	{
-		SPtr<SerializedField> copy = bs_shared_ptr_new<SerializedField>();
-		copy->size = size;
-
-		if (cloneData)
-		{
-			copy->value = (UINT8*)bs_alloc(size);
-			memcpy(copy->value, value, size);
-			copy->ownsMemory = true;
-		}
-		else
-		{
-			copy->value = value;
-			copy->ownsMemory = false;
-		}
-
-		return copy;
-	}
-
-	SPtr<SerializedInstance> SerializedObject::clone(bool cloneData)
-	{
-		SPtr<SerializedObject> copy = bs_shared_ptr_new<SerializedObject>();
-		copy->subObjects = Vector<SerializedSubObject>(subObjects.size());
-
-		UINT32 i = 0;
-		for (auto& subObject : subObjects)
-		{
-			copy->subObjects[i].typeId = subObject.typeId;
-
-			for (auto& entryPair : subObject.entries)
-			{
-				SerializedEntry entry = entryPair.second;
-
-				if (entry.serialized != nullptr)
-					entry.serialized = entry.serialized->clone(cloneData);
-
-				copy->subObjects[i].entries[entryPair.first] = entry;
-			}
-
-			i++;
-		}
-
-		return copy;
-	}
-
-	SPtr<SerializedInstance> SerializedArray::clone(bool cloneData)
-	{
-		SPtr<SerializedArray> copy = bs_shared_ptr_new<SerializedArray>();
-		copy->numElements = numElements;
-
-		for (auto& entryPair : entries)
-		{
-			SerializedArrayEntry entry = entryPair.second;
-			entry.serialized = entry.serialized->clone(cloneData);
-
-			copy->entries[entryPair.first] = entry;
-		}
-
-		return copy;
-	}
-
-	RTTITypeBase* SerializedInstance::getRTTIStatic()
-	{
-		return SerializedInstanceRTTI::instance();
-	}
-
-	RTTITypeBase* SerializedInstance::getRTTI() const
-	{
-		return SerializedInstance::getRTTIStatic();
-	}
-
-	RTTITypeBase* SerializedField::getRTTIStatic()
-	{
-		return SerializedFieldRTTI::instance();
-	}
-
-	RTTITypeBase* SerializedField::getRTTI() const
-	{
-		return SerializedField::getRTTIStatic();
-	}
-
-	RTTITypeBase* SerializedObject::getRTTIStatic()
-	{
-		return SerializedObjectRTTI::instance();
-	}
-
-	RTTITypeBase* SerializedObject::getRTTI() const
-	{
-		return SerializedObject::getRTTIStatic();
-	}
-
-	RTTITypeBase* SerializedArray::getRTTIStatic()
-	{
-		return SerializedArrayRTTI::instance();
-	}
-
-	RTTITypeBase* SerializedArray::getRTTI() const
-	{
-		return SerializedArray::getRTTIStatic();
-	}
-
-	RTTITypeBase* SerializedSubObject::getRTTIStatic()
-	{
-		return SerializedSubObjectRTTI::instance();
-	}
-
-	RTTITypeBase* SerializedSubObject::getRTTI() const
-	{
-		return SerializedSubObject::getRTTIStatic();
-	}
-
-	RTTITypeBase* SerializedEntry::getRTTIStatic()
-	{
-		return SerializedEntryRTTI::instance();
-	}
-
-	RTTITypeBase* SerializedEntry::getRTTI() const
-	{
-		return SerializedEntry::getRTTIStatic();
-	}
-
-	RTTITypeBase* SerializedArrayEntry::getRTTIStatic()
-	{
-		return SerializedArrayEntryRTTI::instance();
-	}
-
-	RTTITypeBase* SerializedArrayEntry::getRTTI() const
-	{
-		return SerializedArrayEntry::getRTTIStatic();
-	}
+#include "BsSerializedObject.h"
+#include "BsSerializedObjectRTTI.h"
+
+namespace BansheeEngine
+{
+	SPtr<SerializedInstance> SerializedField::clone(bool cloneData)
+	{
+		SPtr<SerializedField> copy = bs_shared_ptr_new<SerializedField>();
+		copy->size = size;
+
+		if (cloneData)
+		{
+			copy->value = (UINT8*)bs_alloc(size);
+			memcpy(copy->value, value, size);
+			copy->ownsMemory = true;
+		}
+		else
+		{
+			copy->value = value;
+			copy->ownsMemory = false;
+		}
+
+		return copy;
+	}
+
+	SPtr<SerializedInstance> SerializedObject::clone(bool cloneData)
+	{
+		SPtr<SerializedObject> copy = bs_shared_ptr_new<SerializedObject>();
+		copy->subObjects = Vector<SerializedSubObject>(subObjects.size());
+
+		UINT32 i = 0;
+		for (auto& subObject : subObjects)
+		{
+			copy->subObjects[i].typeId = subObject.typeId;
+
+			for (auto& entryPair : subObject.entries)
+			{
+				SerializedEntry entry = entryPair.second;
+
+				if (entry.serialized != nullptr)
+					entry.serialized = entry.serialized->clone(cloneData);
+
+				copy->subObjects[i].entries[entryPair.first] = entry;
+			}
+
+			i++;
+		}
+
+		return copy;
+	}
+
+	SPtr<SerializedInstance> SerializedArray::clone(bool cloneData)
+	{
+		SPtr<SerializedArray> copy = bs_shared_ptr_new<SerializedArray>();
+		copy->numElements = numElements;
+
+		for (auto& entryPair : entries)
+		{
+			SerializedArrayEntry entry = entryPair.second;
+			entry.serialized = entry.serialized->clone(cloneData);
+
+			copy->entries[entryPair.first] = entry;
+		}
+
+		return copy;
+	}
+
+	RTTITypeBase* SerializedInstance::getRTTIStatic()
+	{
+		return SerializedInstanceRTTI::instance();
+	}
+
+	RTTITypeBase* SerializedInstance::getRTTI() const
+	{
+		return SerializedInstance::getRTTIStatic();
+	}
+
+	RTTITypeBase* SerializedField::getRTTIStatic()
+	{
+		return SerializedFieldRTTI::instance();
+	}
+
+	RTTITypeBase* SerializedField::getRTTI() const
+	{
+		return SerializedField::getRTTIStatic();
+	}
+
+	UINT32 SerializedObject::getRootTypeId() const
+	{
+		if(subObjects.size() > 0)
+			return subObjects[0].typeId;
+
+		return 0;
+	}
+
+	RTTITypeBase* SerializedObject::getRTTIStatic()
+	{
+		return SerializedObjectRTTI::instance();
+	}
+
+	RTTITypeBase* SerializedObject::getRTTI() const
+	{
+		return SerializedObject::getRTTIStatic();
+	}
+
+	RTTITypeBase* SerializedArray::getRTTIStatic()
+	{
+		return SerializedArrayRTTI::instance();
+	}
+
+	RTTITypeBase* SerializedArray::getRTTI() const
+	{
+		return SerializedArray::getRTTIStatic();
+	}
+
+	RTTITypeBase* SerializedSubObject::getRTTIStatic()
+	{
+		return SerializedSubObjectRTTI::instance();
+	}
+
+	RTTITypeBase* SerializedSubObject::getRTTI() const
+	{
+		return SerializedSubObject::getRTTIStatic();
+	}
+
+	RTTITypeBase* SerializedEntry::getRTTIStatic()
+	{
+		return SerializedEntryRTTI::instance();
+	}
+
+	RTTITypeBase* SerializedEntry::getRTTI() const
+	{
+		return SerializedEntry::getRTTIStatic();
+	}
+
+	RTTITypeBase* SerializedArrayEntry::getRTTIStatic()
+	{
+		return SerializedArrayEntryRTTI::instance();
+	}
+
+	RTTITypeBase* SerializedArrayEntry::getRTTI() const
+	{
+		return SerializedArrayEntry::getRTTIStatic();
+	}
 }