Просмотр исходного кода

Added RTTI class hierarchy (Needs further testing)
Moved newObject to RTTIType class

Marko Pintera 13 лет назад
Родитель
Сommit
84e4923d77

+ 5 - 0
CamelotClient/CamelotClient.cpp

@@ -15,6 +15,11 @@ int _tmain(int argc, _TCHAR* argv[])
 	gApplication().startUp("CamelotGLRenderer.dll");
 	gApplication().startUp("CamelotGLRenderer.dll");
 	//gApplication().startUp("CamelotD3D9Renderer.dll");
 	//gApplication().startUp("CamelotD3D9Renderer.dll");
 
 
+	//RTTITypeBase* st = DbgSrlzTest::getRTTIStatic();
+
+//	DbgSrlzTestST::startUp();
+//	TextureST::startUp();
+
 	test();
 	test();
 
 
 	gApplication().runMainLoop();
 	gApplication().runMainLoop();

+ 1 - 25
CamelotRenderer/Include/CmResource.h

@@ -34,31 +34,7 @@ namespace CamelotEngine
 	/************************************************************************/
 	/************************************************************************/
 	public:
 	public:
 		friend class ResourceST;
 		friend class ResourceST;
-
+		static RTTITypeBase* getRTTIStatic();
 		virtual RTTITypeBase* getRTTI() const;
 		virtual RTTITypeBase* getRTTI() const;
-		static Resource* newObject();
-
-	//protected:
-	//	struct RTTIInitOnStart
-	//	{
-	//		RTTIInitOnStart()
-	//		{
-	//			static RTTIMetaType<Resource> myClassMetaType;
-	//			ISerializable::registerRTTIDerivedClass(&myClassMetaType);
-	//		}
-	//	};
-
-	//	static RTTIInitOnStart initOnStart;
-
-	//	static vector<RTTIMetaTypeBase*>::type& getRTTIDerivedClasses()
-	//	{
-	//		static vector<RTTIMetaTypeBase*>::type mRTTIDerivedClasses;
-	//		return mRTTIDerivedClasses;
-	//	}
-
-	//	static void registerRTTIDerivedClass(RTTIMetaTypeBase* derivedClass)
-	//	{
-	//		getRTTIDerivedClasses().push_back(derivedClass);
-	//	}
 	};
 	};
 }
 }

+ 6 - 1
CamelotRenderer/Include/CmResourceST.h

@@ -6,7 +6,7 @@
 
 
 namespace CamelotEngine
 namespace CamelotEngine
 {
 {
-	class CM_EXPORT ResourceST : public RTTIType
+	class CM_EXPORT ResourceST : public RTTIType<Resource, IReflectable, ResourceST>
 	{
 	{
 	private:
 	private:
 		UINT32& getSize(Resource* obj) { return obj->mSize; }
 		UINT32& getSize(Resource* obj) { return obj->mSize; }
@@ -20,5 +20,10 @@ namespace CamelotEngine
 			addPlainField("Size", 0, &ResourceST::getSize, &ResourceST::setSize);
 			addPlainField("Size", 0, &ResourceST::getSize, &ResourceST::setSize);
 			addPlainField("UUID", 1, &ResourceST::getUUID, &ResourceST::setUUID);
 			addPlainField("UUID", 1, &ResourceST::getUUID, &ResourceST::setUUID);
 		}
 		}
+
+		virtual Resource* newRTTIObject()
+		{
+			CM_EXCEPT(InternalErrorException, "Cannot instantiate an abstract class.");
+		}
 	};
 	};
 }
 }

+ 1 - 1
CamelotRenderer/Include/CmTexture.h

@@ -408,8 +408,8 @@ namespace CamelotEngine {
 		/************************************************************************/
 		/************************************************************************/
 	public:
 	public:
 		friend class TextureST;
 		friend class TextureST;
+		static RTTITypeBase* getRTTIStatic();
 		virtual RTTITypeBase* getRTTI() const;
 		virtual RTTITypeBase* getRTTI() const;
-		static Texture* newObject();
     };
     };
 
 
 	/** @} */
 	/** @} */

+ 6 - 26
CamelotRenderer/Include/CmTextureST.h

@@ -8,7 +8,7 @@
 
 
 namespace CamelotEngine
 namespace CamelotEngine
 {
 {
-	class CM_EXPORT TextureST : public RTTIType
+	class CM_EXPORT TextureST : public RTTIType<Texture, Resource, TextureST>
 	{
 	{
 	private:
 	private:
 		CM_SETGET_MEMBER(mSize, UINT32, Texture)
 		CM_SETGET_MEMBER(mSize, UINT32, Texture)
@@ -50,31 +50,6 @@ namespace CamelotEngine
 			// Not allowed to change size this way
 			// Not allowed to change size this way
 		}
 		}
 
 
-		//ManagedDataBlock getFaceData(Texture* obj)
-		//{
-		//	UINT32 totalSize = 0;
-		//	vector<TextureDataPtr>::type faces = obj->getTextureData();
-
-		//	for(auto iter = faces.begin(); iter != faces.end(); ++iter)
-		//	{
-		//		totalSize += (*iter)->getSize();
-		//	}
-
-		//	UINT8* faceData = new UINT8[totalSize]; // TODO - Any way to avoid this reallocation? getTextureData allocates the same amount of memory and then
-		//											// we allocate it again, copy from buffers and throw away getTextureData memory
-		//											//   - TextureData should store everything in one big buffer?
-		//											//   - OR make TextureData ISerializable?!
-
-		//	//ManagedDataBlock dataBlock()
-
-		//	return obj->getTextureData(face).get();
-		//}
-
-		//void setFaceData(Texture* obj, UINT32 face, TextureData* data)
-		//{
-		//	return obj->getTextureData(face).get();
-		//}
-
 	public:
 	public:
 		TextureST()
 		TextureST()
 		{
 		{
@@ -100,5 +75,10 @@ namespace CamelotEngine
 			addReflectablePtrArrayField("mTextureData", 18, &TextureST::getTextureData, &TextureST::getTextureDataArraySize, 
 			addReflectablePtrArrayField("mTextureData", 18, &TextureST::getTextureData, &TextureST::getTextureDataArraySize, 
 				&TextureST::setTextureData, &TextureST::setTextureDataArraySize);
 				&TextureST::setTextureData, &TextureST::setTextureDataArraySize);
 		}
 		}
+
+		virtual Texture* newRTTIObject()
+		{
+			CM_EXCEPT(InternalErrorException, "Cannot instantiate abstract class!");
+		}
 	};
 	};
 }
 }

+ 5 - 7
CamelotRenderer/Source/CmResource.cpp

@@ -46,16 +46,14 @@ namespace CamelotEngine
 	//			load();
 	//			load();
 	//		}
 	//		}
 	//}
 	//}
-	
-	RTTITypeBase* Resource::getRTTI() const
+		
+	RTTITypeBase* Resource::getRTTIStatic()
 	{
 	{
-		static ResourceST rttiType;
-		return &rttiType;
+		return ResourceST::instance();
 	}
 	}
 
 
-
-	Resource* newObject()
+	RTTITypeBase* Resource::getRTTI() const
 	{
 	{
-		CM_EXCEPT(InternalErrorException, "Cannot instantiate an abstract class.");
+		return Resource::getRTTIStatic();
 	}
 	}
 }
 }

+ 4 - 5
CamelotRenderer/Source/CmTexture.cpp

@@ -309,14 +309,13 @@ namespace CamelotEngine {
 	/* 								SERIALIZATION                      		*/
 	/* 								SERIALIZATION                      		*/
 	/************************************************************************/
 	/************************************************************************/
 
 
-	RTTITypeBase* Texture::getRTTI() const
+	RTTITypeBase* Texture::getRTTIStatic()
 	{
 	{
-		static TextureST serializableType;
-		return &serializableType;
+		return TextureST::instance();
 	}
 	}
 
 
-	Texture* Texture::newObject()
+	RTTITypeBase* Texture::getRTTI() const
 	{
 	{
-		CM_EXCEPT(InternalErrorException, "Cannot instantiate abstract class!");
+		return Texture::getRTTIStatic();
 	}
 	}
 }
 }

+ 5 - 0
CamelotUtility/CamelotUtility.vcxproj

@@ -56,6 +56,10 @@
       <ImportLibrary>..\lib\$(Configuration)\$(TargetName).lib</ImportLibrary>
       <ImportLibrary>..\lib\$(Configuration)\$(TargetName).lib</ImportLibrary>
       <AdditionalDependencies>libboost_signals-vc110-mt-gd-1_49.lib;%(AdditionalDependencies)</AdditionalDependencies>
       <AdditionalDependencies>libboost_signals-vc110-mt-gd-1_49.lib;%(AdditionalDependencies)</AdditionalDependencies>
       <AdditionalLibraryDirectories>../Dependencies/lib/Debug</AdditionalLibraryDirectories>
       <AdditionalLibraryDirectories>../Dependencies/lib/Debug</AdditionalLibraryDirectories>
+      <SubSystem>NotSet</SubSystem>
+      <NoEntryPoint>false</NoEntryPoint>
+      <EntryPointSymbol>
+      </EntryPointSymbol>
     </Link>
     </Link>
   </ItemDefinitionGroup>
   </ItemDefinitionGroup>
   <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
   <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
@@ -74,6 +78,7 @@
       <ImportLibrary>..\lib\$(Configuration)\$(TargetName).lib</ImportLibrary>
       <ImportLibrary>..\lib\$(Configuration)\$(TargetName).lib</ImportLibrary>
       <AdditionalDependencies>libboost_signals-vc110-mt-1_49.lib;%(AdditionalDependencies)</AdditionalDependencies>
       <AdditionalDependencies>libboost_signals-vc110-mt-1_49.lib;%(AdditionalDependencies)</AdditionalDependencies>
       <AdditionalLibraryDirectories>../Dependencies/lib/Release</AdditionalLibraryDirectories>
       <AdditionalLibraryDirectories>../Dependencies/lib/Release</AdditionalLibraryDirectories>
+      <NoEntryPoint>false</NoEntryPoint>
     </Link>
     </Link>
   </ItemDefinitionGroup>
   </ItemDefinitionGroup>
   <ItemGroup>
   <ItemGroup>

+ 19 - 7
CamelotUtility/Include/CmIReflectable.h

@@ -6,7 +6,6 @@ namespace CamelotEngine
 {
 {
 	/**
 	/**
 	 * @brief	Interface implemented by classes that provide run time type information.
 	 * @brief	Interface implemented by classes that provide run time type information.
-	 * 			It just provides a method that returns an interface to the class metadata.
 	 */
 	 */
 	class CM_UTILITY_EXPORT IReflectable
 	class CM_UTILITY_EXPORT IReflectable
 	{
 	{
@@ -14,16 +13,29 @@ namespace CamelotEngine
 		/**
 		/**
 		 * @brief	Returns an interface you can use to access class Run Time Type Information.
 		 * @brief	Returns an interface you can use to access class Run Time Type Information.
 		 *
 		 *
-		 * @note	It is suggested you derive your own version of RTTIType, in which you
-		 * 			may encapsulate all reflection specific operations. Although this is optional.
+		 * @note	You must derive your own version of RTTIType, in which you
+		 * 			may encapsulate all reflection specific operations. 
 		 */
 		 */
 		virtual RTTITypeBase* getRTTI() const = 0;
 		virtual RTTITypeBase* getRTTI() const = 0;
 
 
 		/**
 		/**
-		 * @brief	Creates an empty instance of a reflectable object. This is a bit of a hack, 
-		 * 			but EVERY class deriving from IReflectable needs to implement this method. 
-		 * 			You will get a compiler error otherwise.
+		 * @brief	Returns all classes deriving directly from IReflectable.
+		 * 			You can call another version of this method on the returned type class,
+		 * 			to find classes deeper in the hierarchy.
 		 */
 		 */
-		static IReflectable* newObject();
+		static vector<RTTITypeBase*>::type& getDerivedClasses()
+		{
+			static vector<RTTITypeBase*>::type mRTTIDerivedClasses;
+			return mRTTIDerivedClasses;
+		}
+
+		/**
+		 * @brief	INTERNAL USE. Called by each type deriving from IReflectable,
+		 * 			on program load.
+		 */
+		static void registerDerivedClass(RTTITypeBase* derivedClass)
+		{
+			getDerivedClasses().push_back(derivedClass);
+		}
 	};
 	};
 }
 }

+ 1 - 1
CamelotUtility/Include/CmRTTIReflectableField.h

@@ -142,7 +142,7 @@ namespace CamelotEngine
 
 
 		virtual IReflectable* newObject()
 		virtual IReflectable* newObject()
 		{
 		{
-			return DataType::newObject();
+			return DataType::getRTTIStatic()->newRTTIObject();
 		}
 		}
 	};
 	};
 }
 }

+ 1 - 1
CamelotUtility/Include/CmRTTIReflectablePtrField.h

@@ -142,7 +142,7 @@ namespace CamelotEngine
 
 
 		virtual std::shared_ptr<IReflectable> newObject()
 		virtual std::shared_ptr<IReflectable> newObject()
 		{
 		{
-			return std::shared_ptr<IReflectable>(DataType::newObject());
+			return std::shared_ptr<IReflectable>(DataType::getRTTIStatic()->newRTTIObject());
 		}
 		}
 	};
 	};
 }
 }

+ 61 - 6
CamelotUtility/Include/CmRTTIType.h

@@ -44,6 +44,9 @@ namespace CamelotEngine
 		RTTITypeBase();
 		RTTITypeBase();
 		virtual ~RTTITypeBase();
 		virtual ~RTTITypeBase();
 
 
+		virtual void registerDerivedClass(RTTITypeBase* derivedClass) = 0;
+		virtual IReflectable* newRTTIObject() = 0;
+
 		template <class ObjectType, class DataType>
 		template <class ObjectType, class DataType>
 		void setPlainValue(ObjectType* object, const std::string& name, DataType& value)
 		void setPlainValue(ObjectType* object, const std::string& name, DataType& value)
 		{
 		{
@@ -245,18 +248,67 @@ namespace CamelotEngine
 	};
 	};
 
 
 	/**
 	/**
-	 * @brief	Pretty much just an extension of SerializationInterfaceBase. Feel free to derive from this class and return
-	 * 			the derived class from IReflectable::getSerializationInterface. This way you can separate serialization logic from
+	 * @brief	Used for initializing a certain type as soon as the program is loaded.
+	 */
+	template<typename Type, typename BaseType>
+	struct InitRTTIOnStart
+	{
+	public:
+		InitRTTIOnStart()
+		{
+			BaseType::getRTTIStatic()->registerDerivedClass(Type::getRTTIStatic());
+		}
+	};
+
+	/**
+	 * @brief	Specialization for root class of RTTI hierarchy - IReflectable
+	 */
+	template<typename Type>
+	struct InitRTTIOnStart<Type, IReflectable>
+	{
+	public:
+		InitRTTIOnStart()
+		{
+			IReflectable::registerDerivedClass(Type::getRTTIStatic());
+		}
+	};
+
+	/**
+	 * @brief	Pretty much just an extension of RTTITypeBase. Feel free to derive from this class and return
+	 * 			the derived class from IReflectable::getRTTI. This way you can separate serialization logic from
 	 * 			the actual class you're serializing.
 	 * 			the actual class you're serializing.
 	 */
 	 */
-	// TODO - Low priority. This class is separate from SerializationInterfaceBase because of obsolete reasons. It might be okay to merge them in the future, provided there will be
-	// no more changes to serialization.
-	class CM_UTILITY_EXPORT RTTIType : public RTTITypeBase
+	template <typename Type, typename BaseType, typename MyRTTIType>
+	class RTTIType : public RTTITypeBase
 	{
 	{
+	protected:
+		/************************************************************************/
+		/* 						RTTI CLASS META DATA							*/
+		/************************************************************************/
+
+		static vector<RTTITypeBase*>::type& getDerivedClasses()
+		{
+			static vector<RTTITypeBase*>::type mRTTIDerivedClasses;
+			return mRTTIDerivedClasses;
+		}
+
+		static InitRTTIOnStart<Type, BaseType> initOnStart;
+
 	public:
 	public:
 		RTTIType() {}
 		RTTIType() {}
 		virtual ~RTTIType() {}
 		virtual ~RTTIType() {}
 
 
+		static MyRTTIType* instance()
+		{
+			static MyRTTIType inst;
+			return &inst;
+		}
+
+		virtual void registerDerivedClass(RTTITypeBase* derivedClass)
+		{
+			getDerivedClasses().push_back(derivedClass);
+		}
+
 		/************************************************************************/
 		/************************************************************************/
 		/* 			FIELDS OPERATING DIRECTLY ON SERIALIZABLE OBJECT            */
 		/* 			FIELDS OPERATING DIRECTLY ON SERIALIZABLE OBJECT            */
 		/************************************************************************/
 		/************************************************************************/
@@ -338,7 +390,7 @@ namespace CamelotEngine
 			DataType& (InterfaceType::*getter)(ObjectType*), 
 			DataType& (InterfaceType::*getter)(ObjectType*), 
 			void (InterfaceType::*setter)(ObjectType*, DataType&) = nullptr)
 			void (InterfaceType::*setter)(ObjectType*, DataType&) = nullptr)
 		{
 		{
-			BOOST_STATIC_ASSERT_MSG((boost::is_base_of<CamelotEngine::RTTIType, InterfaceType>::value), 
+			BOOST_STATIC_ASSERT_MSG((boost::is_base_of<CamelotEngine::RTTIType<Type, BaseType, MyRTTIType>, InterfaceType>::value), 
 				"Class with the get/set methods must derive from CamelotEngine::SerializationInterface.");
 				"Class with the get/set methods must derive from CamelotEngine::SerializationInterface.");
 
 
 			addPlainField<ObjectType, DataType>(name, uniqueId, 
 			addPlainField<ObjectType, DataType>(name, uniqueId, 
@@ -489,4 +541,7 @@ namespace CamelotEngine
 			addNewField(newField);
 			addNewField(newField);
 		}	
 		}	
 	};
 	};
+
+	template <typename Type, typename BaseType, typename MyRTTIType>
+	InitRTTIOnStart<Type, BaseType> RTTIType<Type, BaseType, MyRTTIType>::initOnStart;
 }
 }

+ 1 - 1
CamelotUtility/Include/CmTextureData.h

@@ -90,8 +90,8 @@ namespace CamelotEngine
 	/************************************************************************/
 	/************************************************************************/
 	public:
 	public:
 		friend class TextureDataST;
 		friend class TextureDataST;
+		static RTTITypeBase* getRTTIStatic();
 		virtual RTTITypeBase* getRTTI() const;
 		virtual RTTITypeBase* getRTTI() const;
-		static TextureData* newObject();
 	private:
 	private:
 		TextureData() {} // Only for serialization
 		TextureData() {} // Only for serialization
 	};
 	};

+ 6 - 1
CamelotUtility/Include/CmTextureDataST.h

@@ -7,7 +7,7 @@
 
 
 namespace CamelotEngine
 namespace CamelotEngine
 {
 {
-	class TextureDataST : public RTTIType
+	class CM_UTILITY_EXPORT TextureDataST : public RTTIType<TextureData, IReflectable, TextureDataST>
 	{
 	{
 		CM_SETGET_MEMBER(mNumMipmaps, UINT32, TextureData)
 		CM_SETGET_MEMBER(mNumMipmaps, UINT32, TextureData)
 		CM_SETGET_MEMBER(mWidth, UINT32, TextureData)
 		CM_SETGET_MEMBER(mWidth, UINT32, TextureData)
@@ -43,5 +43,10 @@ namespace CamelotEngine
 
 
 			addDataBlockField("Data", 8, &TextureDataST::getData, &TextureDataST::setData);
 			addDataBlockField("Data", 8, &TextureDataST::getData, &TextureDataST::setData);
 		}
 		}
+
+		virtual TextureData* newRTTIObject()
+		{
+			return new TextureData();
+		}
 	};
 	};
 }
 }

+ 0 - 8
CamelotUtility/Source/CmIReflectable.cpp

@@ -1,13 +1,5 @@
 #include "CmIReflectable.h"
 #include "CmIReflectable.h"
-#include "CmException.h"
 
 
 namespace CamelotEngine
 namespace CamelotEngine
 {
 {
-	IReflectable* IReflectable::newObject() 
-	{ 
-		CM_EXCEPT(InternalErrorException, 
-			"Cannot create an instance of an abstract class.");
-
-		return nullptr; 
-	} 
 }
 }

+ 5 - 5
CamelotUtility/Source/CmTextureData.cpp

@@ -59,14 +59,14 @@ namespace CamelotEngine
 	/************************************************************************/
 	/************************************************************************/
 	/* 								SERIALIZATION                      		*/
 	/* 								SERIALIZATION                      		*/
 	/************************************************************************/
 	/************************************************************************/
-	RTTITypeBase* TextureData::getRTTI() const
+
+	RTTITypeBase* TextureData::getRTTIStatic()
 	{
 	{
-		static TextureDataST rttiType;
-		return &rttiType;
+		return TextureDataST::instance();
 	}
 	}
 
 
-	TextureData* TextureData::newObject()
+	RTTITypeBase* TextureData::getRTTI() const
 	{
 	{
-		return new TextureData();
+		return TextureData::getRTTIStatic();
 	}
 	}
 }
 }