BearishSun 8 лет назад
Родитель
Сommit
6d96214a3e

+ 288 - 0
Documentation/Manuals/Native/User/advancedRtti.md

@@ -0,0 +1,288 @@
+Advanced RTTI				{#advancedRtti}
+===============
+
+This manual is a continuation of the @ref serializingObjects manual, focusing on some more advanced features of the RTTI system.
+
+# Manually defining fields
+Previously we have shown how to define RTTI member fields by using the BS_RTTI_MEMBER_* macros. While this method is in most cases preferable, it might not be useful if more advanced functionality is required. The macro approach is only able to reference class fields directly, but sometimes we might wish to access data returned by a method, or we might want to process the data in some way (e.g. compressing it).
+
+We can do this by manually defining fields. In order to manually register fields the systems supports a several sets of `add*Field` methods, each expecting a unique name/id, and a pair of getter/setter methods. The getter/setter methods can then be used for any more advanced processing.
+
+## Plain fields
+You register plain fields by calling @ref bs::RTTIType<Type, BaseType, MyRTTIType>::addPlainField "RTTIType::addPlainField()". The getter/setter methods must return/accept a reference to the value of the field.
+
+~~~~~~~~~~~~~{.cpp}
+class MyComponent : public Component
+{
+public:
+	// ...
+
+	UINT32 myInt;
+
+	// ...
+};
+
+class MyComponentRTTI : public RTTIType<MyComponent, Component, MyComponentRTTI>
+{
+public:
+	UINT32& getMyInt(MyComponent* obj) { return obj->myInt; }
+	void setMyInt(MyComponent* obj, UINT32& value) { obj->myInt = value; }
+
+	MyComponentRTTI ()
+	{
+		// Register the getter/setter methods above. You must specify a name and field id (both must be unique within the type).
+		addPlainField("myInt", 0, &MyComponentRTTI::getMyInt, &MyComponentRTTI::setMyInt);
+	}
+	
+	// ... 
+};
+~~~~~~~~~~~~~
+
+## Reflectable fields
+The reflectable field getter/setter signature is similar to the plain field one, only the @ref bs::RTTIType<Type, BaseType, MyRTTIType>::addReflectableField "RTTIType::addReflectableField()" method is used for registration instead. 
+
+~~~~~~~~~~~~~{.cpp}
+class MyComponent : public Component
+{
+public:
+	// ...
+
+	HMesh mesh;
+
+	// ...
+};
+
+class MyComponentRTTI : public RTTIType<MyComponent, Component, MyComponentRTTI>
+{
+public:
+	HMesh& getMesh(MyComponent* obj) { return obj->mesh; }
+	void setMesh(MyComponent* obj, HMesh& value) { obj->mesh = value; }
+
+	MyComponentRTTI ()
+	{
+		addReflectableField("mesh", 0, &MyComponentRTTI::getMesh, &MyComponentRTTI::setMesh);
+	}
+	
+	// ... 
+};
+~~~~~~~~~~~~~
+
+## Reflectable pointer fields
+Reflectable pointer getter/setter methods must return shared pointers to the instance, and they're registered with @ref bs::RTTIType<Type, BaseType, MyRTTIType>::addReflectablePtrField "RTTIType::addReflectablePtrField()".
+~~~~~~~~~~~~~{.cpp}
+class MyClass : public IReflectable
+{
+	// ...
+}
+
+class MyComponent : public Component
+{
+public:
+	// ...
+
+	SPtr<MyClass> myClass;
+
+	// ...
+};
+
+class MyComponentRTTI : public RTTIType<MyComponent, Component, MyComponentRTTI>
+{
+public:
+	SPtr<MyClass> getMyClass(MyComponent* obj) { return obj->myClass; }
+	void setMyClass(MyComponent* obj, SPtr<MyClass> value) { obj->myClass = value; }
+
+	MyComponentRTTI ()
+	{
+		addReflectablePtrField("myClass", 0, &MyComponentRTTI::getMyClass, &MyComponentRTTI::setMyClass);
+	}
+	
+	// ... 
+};
+~~~~~~~~~~~~~
+
+## Array fields
+Each of the valid field types (plain/reflectable/reflectable pointer), also come in array form. The array form requires two additional getter/setter methods that get/set array size, and normal getter/setter methods require an additional index parameter. 
+
+Methods for registering array fields are:
+ - @ref bs::RTTIType<Type, BaseType, MyRTTIType>::addPlainArrayField "RTTIType::addPlainArrayField()"
+ - @ref bs::RTTIType<Type, BaseType, MyRTTIType>::addReflectableArrayField "RTTIType::addReflectableArrayField()"
+ - @ref bs::RTTIType<Type, BaseType, MyRTTIType>::addReflectablePtrArrayField "RTTIType::addReflectablePtrArrayField()"
+ 
+~~~~~~~~~~~~~{.cpp}
+class MyComponent : public Component
+{
+public:
+	// ...
+
+	Vector<HMesh> meshes;
+
+	// ...
+};
+
+class MyComponentRTTI : public RTTIType<MyComponent, Component, MyComponentRTTI>
+{
+public:
+	HMesh& getMesh(MyComponent* obj, UINT32 idx) { return obj->meshes[idx]; }
+	void setMesh(MyComponent* obj, HMesh& value, UINT32 idx) { obj->meshes[idx] = value; }
+
+	UINT32 getNumMeshes(MyComponent* obj) { return obj->meshes.size(); }
+	void setNumMeshes(MyComponent* obj, UINT32 size) { obj->meshes.resize(size); }
+	
+	MyComponentRTTI ()
+	{
+		addReflectablePtrArrayField("meshes", 0, &MyComponentRTTI::getMesh, &MyComponentRTTI::getNumMeshes, 
+			&MyComponentRTTI::setMesh, &MyComponentRTTI::setNumMeshes);
+		
+		// And similarly for other field types
+	}
+	
+	// ... 
+};
+~~~~~~~~~~~~~
+
+> By using this form of field definitions you are also no longer limited to arrays only contained with the **Vector** container.
+
+# Advanced plain fields
+Although plain fields are primarily intended for simple built-in types, sometimes they also need to be used on complex types. For example a **std::string** is often used as a field type, but it is not a simple built-in type, nor can we make it derive from **IReflectable**. For these purposes you can use @ref bs::RTTIPlainType<T> "RTTIPlainType<T>". This is a templated class you can specialize for your specific type. 
+
+Once you specialize the class for your type, implementing all the required methods, you will then be able to use your type on plain fields in the RTTI class. Without this specialization the system will refuse to compile the RTTI type.
+
+The specialization involves implementing methods for serializing/deserializing and retrieving object size. It has no advanced functionality like versioning (so if the structure of the type changes, it will break any previously serialized data), or keeping references to other objects.
+
+For example if we wanted to serialize a string:
+~~~~~~~~~~~~~{.cpp}
+template<> struct RTTIPlainType<std::string>
+{	
+	enum { id = 20 }; enum { hasDynamicSize = 1 }; // Provide unique ID, and a flag whether the size of the structure is dynamic.
+
+	static void toMemory(const std::string& data, char* memory)
+	{ 
+		UINT32 size = getDynamicSize(data);
+
+		memcpy(memory, &size, sizeof(UINT32));
+		memory += sizeof(UINT32);
+		size -= sizeof(UINT32);
+		memcpy(memory, data.data(), size); 
+	}
+
+	static UINT32 fromMemory(std::string& data, char* memory)
+	{ 
+		UINT32 size;
+		memcpy(&size, memory, sizeof(UINT32)); 
+		memory += sizeof(UINT32);
+
+		UINT32 stringSize = size - sizeof(UINT32);
+		data = std::string(memory, stringSize);
+
+		return size;
+	}
+
+	static UINT32 getDynamicSize(const std::string& data)	
+	{ 
+		UINT64 dataSize = data.size() * sizeof(std::string::value_type) + sizeof(UINT32);
+		return (UINT32)dataSize;
+	}	
+}; 
+~~~~~~~~~~~~~
+
+> Note: Banshee already provides many of such specializations, including ones for strings, vectors and maps.
+
+Each specialization must implement all three **toMemory()**, **fromMemory()** and **getDynamicSize()** methods. It must also provide a flag **hasDynamicSize** which determines whether or not it has dynamic size. Any structure whose size varies with each instance (like a string) must set this flag to true. You must also set it to true if the size is static but larger than 255 bytes.
+
+After the specialization is implemented you will be able to use the type in getters/setters for plain fields as you would *int* or *float*. 
+
+For very simple classes you can also use the @ref BS_ALLOW_MEMCPY_SERIALIZATION macro instead. It will create a basic **RTTIPlainType<T>** specialization which uses *memcpy()* and *sizeof()* to implement the necessary methods.
+
+~~~~~~~~~~~~~{.cpp}
+// Simple plain old data type
+struct SimpleData
+{
+	int some;
+	float data;
+	float here;
+};
+
+BS_ALLOW_MEMCPY_SERIALIZATION(SimpleData)
+~~~~~~~~~~~~~
+
+**RTTIPlainType** specializations can also be used as a more traditional form of serialization in case you find the RTTI system an overkill. For example if you needed to transfer data over a network and don't require advanced versioning features. The system provides helper methods that allow you to easily work with plain types in such a case:
+ - @ref bs::rttiReadElem "rttiReadElem()" - Deserializes an object from the provided buffer and returns offset into the buffer after the read data
+ - @ref bs::rttiWriteElem "rttiWriteElem()" - Serializes an object into the provided buffer and returns offset into the buffer after the written data
+ - @ref bs::rttiGetElemSize "rttiGetElemSize()" - Returns a size an object
+ 
+~~~~~~~~~~~~~{.cpp}
+// Assuming Vector has a RTTIPlainType<T> specialization (which it has, Banshee provides it by default)
+
+Vector<SimpleData> myData;
+// fill out myData
+
+// Simply serialize the entire vector and all of its contents
+UINT32 size = rttiGetElemSize(myData);
+UINT8* data = (UINT8*)bs_alloc(size);
+rttiWriteElem(myData, data);
+
+// Simply deserialize the data
+Vector<SimpleData> myDataCopy;
+rttiReadElem(myDataCopy, data);
+
+bs_free(data);
+~~~~~~~~~~~~~
+
+# Querying RTTI
+Aside from using RTTI for serialization, you can also use it to manually query various information about objects. 
+
+Global queries:
+ - @ref bs::rtti_is_of_type "rtti_is_of_type<T>()" - Checks is a specific object of type *T*
+ - @ref bs::rtti_is_subclass "rtti_is_subclass<T>()" - Checks is a specific object derived from type *T*
+ - @ref bs::rtti_create "rtti_create()" - Creates a new object from its type ID
+ 
+**IReflectable** queries:
+ - @ref bs::IReflectable::getTypeName "IReflectable::getTypeName()" - Gets the name of the object's type
+ - @ref bs::IReflectable::getTypeId "IReflectable::getTypeId()" - Gets the type ID of the object's type
+ 
+**RTTIType** queries:
+ - @ref bs::RTTITypeBase::getBaseClass "RTTITypeBase::getBaseClass()" - Returns the **RTTIType** object of the base class
+ - @ref bs::RTTITypeBase::getDerivedClasses "RTTITypeBase::getDerivedClasses()" - Returns a list of **RTTIType**%s for all derived classes
+ - @ref bs::RTTITypeBase::getNumFields "RTTITypeBase::getNumFields()" - Returns the number of member fields
+ - @ref bs::RTTITypeBase::getField "RTTITypeBase::getField()" - Returns information about a field from its sequential index, in the form of @ref bs::RTTIField "RTTIField"
+ - @ref bs::RTTITypeBase::findField "RTTITypeBase::findField()" - Searches for a field with a specific name and returns information about it in form of **RTTIField**
+ 
+**RTTIField** queries:
+ - @ref bs::RTTIField::isPlainType "RTTIField::isPlainType()" - Checks if field contains a plain data type. **RTTIField** can then be cast to @ref bs::RTTIPlainFieldBase "RTTIPlainFieldBase" for more operations.
+ - @ref bs::RTTIField::isReflectableType "RTTIField::isReflectableType()" - Checks if field contains an **IReflectable** data type. **RTTIField** can then be cast to @ref bs::RTTIReflectableFieldBase "RTTIReflectableFieldBase" for more operations.
+ - @ref bs::RTTIField::isReflectablePtrType "RTTIField::isReflectablePtrType()" - Checks if field contains an **IReflectable** pointer data type. **RTTIField** can then be cast to @ref bs::RTTIReflectablePtrFieldBase "RTTIReflectablePtrFieldBase" for more operations.
+ - @ref bs::RTTIField::isArray "RTTIField::isArray()" - Checks if the field contains an array or a single value
+ 
+~~~~~~~~~~~~~{.cpp}
+IReflectable* myObject = ...;
+
+rtti_is_of_type<Texture>(myObject);
+rtti_is_subclass<Texture>(myObject);
+rtti_create(TID_Texture);
+
+myObject->getTypeName();
+myObject->getTypeId();
+
+RTTITypeBase* rttiType = myObject->getRTTI();
+rttiType->getBaseClass();
+rttiType->getDerivedClasses();
+rttiType->getNumFields();
+rttiType->getField(index);
+
+RTTIField* rttiField = rttiType->findField(name);
+rttiField->isPlainType();
+rttiField->isReflectableType();
+rttiField->isReflectablePtrType();
+rttiField->isArray();
+~~~~~~~~~~~~~
+
+Once you have an instance of a **RTTIField** object, you can also use it to directly read and write values on object instances for that particular field.
+
+# Advanced serialization 
+When implementing **RTTIType<Type, BaseType, MyRTTIType>** can optionally override any of these methods, for additional functionality:
+ - @ref bs::RTTIType<Type, BaseType, MyRTTIType>::onSerializationStarted "RTTIType::onSerializationStarted"
+ - @ref bs::RTTIType<Type, BaseType, MyRTTIType>::onSerializationEnded "RTTIType::onSerializationEnded"
+ - @ref bs::RTTIType<Type, BaseType, MyRTTIType>::onDeserializationStarted "RTTIType::onDeserializationStarted"
+ - @ref bs::RTTIType<Type, BaseType, MyRTTIType>::onDeserializationEnded "RTTIType::onDeserializationEnded"
+ 
+As their names imply they will get called during serialization/deserialization and allow you to do any pre- or post-processing of the data. Each of those methods accepts an **IReflectable** pointer to the object currently being processed. Each type that implements **IReflectable** also comes with a *mRTTIData* field which is of **Any** type, and can be used for storing temporary data during serialization/deserialization (primarily when using the methods above).

+ 273 - 0
Documentation/Manuals/Native/User/serializingObjects.md

@@ -0,0 +1,273 @@
+Serializing objects				{#serializingObjects}
+===============
+
+Serializing an objects involves encoding the contents of an object, and (usually) saving it to a storage device so it can be decoded later. This process is used by the resources system to save/load all types of resources, and it is also used by the scene system for saving/loading the contents of all components in the scene.
+
+In order to make an object serializable you need to set up a special interface that allows the system to query information about the object, retrieve and set its data. This interface is known as Run Time Type Information (RTTI).
+
+In Banshee any object that is serializable, and therefore has RTTI, must implement the @ref bs::IReflectable "IReflectable" interface. If you are creating custom components or resources, **Component** and **Resource** base classes already derive from this interface so you don't need to specify it manually. The interface is simple, requiring you to implement two methods:
+ - RTTITypeBase* getRTTI() const;
+ - static RTTITypeBase* getRTTIStatic();
+ 
+Implementations of these methods will return an object containing all RTTI for a specific class. In the rest of this manual we'll focus on explaning how to create a RTTI class implementation returned by these methods.
+
+~~~~~~~~~~~~~{.cpp}
+// IReflectable implementation for a normal class
+class MyClass : public IReflectable
+{
+	// ...class members...
+
+	static RTTITypeBase* getRTTIStatic()
+	{ return MyClassRTTI::instance(); }
+
+	RTTITypeBase* getRTTI() const override
+	{ return MyClass::getRTTIStatic(); }
+};
+
+// IReflectable implementation for a component
+class MyComponent : public Component
+{
+public:
+	MyComponent(const HSceneObject& parent)
+		:Component(parent)
+	{}
+
+	// ...class members...
+
+	static RTTITypeBase* getRTTIStatic()
+	{ return MyComponentRTTI::instance(); }
+
+	RTTITypeBase* getRTTI() const override
+	{ return MyComponent::getRTTIStatic(); }
+};
+~~~~~~~~~~~~~
+
+# Creating the RTTI object
+All RTTI objects must implement the @ref bs::RTTIType<Type, BaseType, MyRTTIType> "RTTIType<Type, BaseType, MyRTTIType>" interface. The interface accepts three template parameters:
+ - *Type* - Class of the object we're creating RTTI for (e.g. *MyClass* or *MyComponent* from example above)
+ - *BaseType* - Base type of the object we're creating RTTI for (e.g. *IReflectable* or *Component* from example above)
+ - *MyRTTIType* - Name of the RTTI class itself
+ 
+~~~~~~~~~~~~~{.cpp}
+class MyClassRTTI : public RTTIType<MyClass, IReflectable, MyClassRTTI>
+{
+	// ...
+};
+
+class MyComponentRTTI : public RTTIType<MyComponent, Component, MyComponentRTTI>
+{
+	// ...
+};
+~~~~~~~~~~~~~
+
+The RTTI object must at least implement the following methods:
+ - @ref bs::RTTITypeBase::getRTTIName() "RTTITypeBase::getRTTIName()" - Returns the name of the class the RTTI describes
+ - @ref bs::RTTITypeBase::getRTTIId() "RTTITypeBase::getRTTIId()" - Returns an identifier that uniquely identifies the class
+ - @ref bs::RTTITypeBase::newRTTIObject() "RTTITypeBase::newRTTIObject()" - Creates a new empty instance of the class the RTTI describes
+ 
+~~~~~~~~~~~~~{.cpp}
+enum TypeIds
+{
+	// These numbers must be unique or the system will complain. Use numbers higher than 200000 to avoid conflicts with built-in types
+	TID_MyClass = 200000,
+	TID_MyComponent = 200001
+}
+
+class MyClassRTTI : public RTTIType<MyClass, IReflectable, MyClassRTTI>
+{
+public:
+	const String& getRTTIName() override
+	{
+		static String name = "MyClass";
+		return name;
+	}
+
+	UINT32 getRTTIId() override
+	{
+		return TID_MyClass;
+	}
+
+	SPtr<IReflectable> newRTTIObject() override
+	{
+		return bs_shared_ptr_new<MyClass>();
+	}
+};
+
+class MyComponentRTTI : public RTTIType<MyComponent, Component, MyComponentRTTI>
+{
+public:
+	const String& getRTTIName() override
+	{
+		static String name = "MyComponent";
+		return name;
+	}
+
+	UINT32 getRTTIId() override
+	{
+		return TID_MyComponent;
+	}
+
+	SPtr<IReflectable> newRTTIObject() override
+	{
+		return GameObjectRTTI::createGameObject<MyComponent>();
+	}
+};
+~~~~~~~~~~~~~
+
+> Note that when creating new instances of components within RTTI class, you must use **GameObjectRTTI::createGameObject<T>()** method, instead of just creating the object normally.
+
+This is the minimal amount of work you need to do in order to implement RTTI. The RTTI types above now describe the class type, but not any of its members. In order to actually have class data serialized, you also need to define member fields.
+
+# Member fields
+Member fields give the RTTI type a way to access (retrieve and assign) data from various members in the class the RTTI type describes. Let's imagine our *MyComponent* class had a few data members:
+~~~~~~~~~~~~~{.cpp}
+class MyComponent : public Component
+{
+public:
+	// ...
+
+	UINT32 myInt;
+	float myFloat;
+	String myString;
+
+	// ...
+};
+~~~~~~~~~~~~~
+
+Its field definition within the RTTI type would look like so:
+~~~~~~~~~~~~~{.cpp}
+class MyComponentRTTI : public RTTIType<MyComponent, Component, MyComponentRTTI>
+{
+public:
+	BS_BEGIN_RTTI_MEMBERS
+		BS_RTTI_MEMBER_PLAIN(myInt, 0)
+		BS_RTTI_MEMBER_PLAIN(myFloat, 1)
+		BS_RTTI_MEMBER_PLAIN(myString, 2)
+	BS_END_RTTI_MEMBERS
+
+	MyComponentRTTI()
+		:mInitMembers(this)
+	{ }
+	
+	// ... 
+};
+~~~~~~~~~~~~~
+
+Field definition portion of the RTTI type always begins with the @ref bs::BS_BEGIN_RTTI_MEMBERS "BS_BEGIN_RTTI_MEMBERS" macro, and ends with the @ref bs::BS_END_RTTI_MEMBERS "BS_END_RTTI_MEMBERS". If field definition is provided you must also provide a constructor that initializes the *mInitMembers* with the *this* pointer.
+
+The field members themselves are defined by calling macros starting with BS_RTTI_MEMBER_*. The macro expects the name of the field it describes, as well as a unique ID of the field. The suffix of the BS_RTTI_MEMBER_* macro depends on the type of the field being added. There are three different types:
+ - @ref bs::BS_RTTI_MEMBER_PLAIN "BS_RTTI_MEMBER_PLAIN" - Field containing basic data types like ints, floats, strings or other types that can be just trivially copied during serialization/deserialization.
+ - @ref bs::BS_RTTI_MEMBER_REFL "BS_RTTI_MEMBER_REFL" - Field containing objects deriving from **IReflectable** (i.e. classes that have RTTI). The main advantage of using **IReflectable** types over plain ones is that you are allowed to add or remove fields from **IReflectable**%s RTTI type, and it wont break any data that was previously serialized. This is very important as you make changes to your components or resources, so you can still load previously saved data (e.g. imagine saving a level, changing a component, and then being unable to load the level). Plain types on the other hand must always keep the same structure, otherwise the serialized data will be broken.
+ - @ref bs::BS_RTTI_MEMBER_REFLPTR "BS_RTTI_MEMBER_REFLPTR" - Fields containing pointers to objects deriving from **IReflectable**. Same as **BS_RTTI_MEMBER_REFL**, except that multiple fields can point to the same object. This ensures the object won't be serialized multiple times, wasting space and performance, and also ensures that the system can properly restore all references to the object when it's deserialized.
+ 
+~~~~~~~~~~~~~{.cpp}
+// Component definition with more complex field types
+class MyComponent : public Component
+{
+public:
+	// ...
+
+	UINT32 myInt;
+	float myFloat;
+	String myString;
+	SPtr<MyClass> myPtrClass;
+	MyClass myClass;
+	HRenderable renderable; // Component handle
+	HMesh mesh; // Resource handle
+
+	// ...
+};
+
+class MyComponentRTTI : public RTTIType<MyComponent, Component, MyComponentRTTI>
+{
+public:
+	BS_BEGIN_RTTI_MEMBERS
+		BS_RTTI_MEMBER_PLAIN(myInt, 0)
+		BS_RTTI_MEMBER_PLAIN(myFloat, 1)
+		BS_RTTI_MEMBER_PLAIN(myString, 2)
+		BS_RTTI_MEMBER_REFLPTR(myPtrClass, 3)
+		BS_RTTI_MEMBER_REFL(myClass, 4)
+		BS_RTTI_MEMBER_REFL(renderable, 5)
+		BS_RTTI_MEMBER_REFL(mesh, 6)
+	BS_END_RTTI_MEMBERS
+
+	MyComponentRTTI()
+		:mInitMembers(this)
+	{ }
+	
+	// ... 
+};
+~~~~~~~~~~~~~
+
+> Note that component and resource handles are considered **IReflectable**, and are therefore serialized by using **BS_RTTI_MEMBER_REFL**.
+
+Each field must have an ID unique within the RTTI type. If you remove members from the RTTI type, you should not re-use their IDs for other members. Additionally, if the type of a specific field changes, you should assign it a new ID. The IDs allow the system to map previously serialized data to the current structure of the object.
+
+## Arrays
+Array field types are also supported:
+ - @ref bs::BS_RTTI_MEMBER_PLAIN_ARRAY "BS_RTTI_MEMBER_PLAIN_ARRAY"
+ - @ref bs::BS_RTTI_MEMBER_REFL_ARRAY "BS_RTTI_MEMBER_REFL_ARRAY"
+ - @ref bs::BS_RTTI_MEMBER_REFLPTR_ARRAY "BS_RTTI_MEMBER_REFLPTR_ARRAY"
+ 
+They perform the same function as their non-array counterparts, except the fields are expected to contain a **Vector<T>** instead of a single entry.
+
+~~~~~~~~~~~~~{.cpp}
+class MyComponent : public Component
+{
+public:
+	// ...
+
+	Vector<UINT32> myInts;
+	Vector<SPtr<MyClass>> myPtrClasses;
+	Vector<HMesh> meshes;
+
+	// ...
+};
+
+class MyComponentRTTI : public RTTIType<MyComponent, Component, MyComponentRTTI>
+{
+public:
+	BS_BEGIN_RTTI_MEMBERS
+		BS_RTTI_MEMBER_PLAIN_ARRAY(myInts, 0)
+		BS_RTTI_MEMBER_REFLPTR_ARRAY(myPtrClasses, 1)
+		BS_RTTI_MEMBER_REFL_ARRAY(meshes, 2)
+	BS_END_RTTI_MEMBERS
+
+	MyComponentRTTI()
+		:mInitMembers(this)
+	{ }
+	
+	// ... 
+};
+~~~~~~~~~~~~~
+
+# Using RTTI
+Once the RTTI has been created, in most cases it will be used automatically. In particular it will be automatically used if implemented for components or resources. If you implement it for normal classes, you might want to know how to use it manually.
+
+To manually serialize an object you can use the @ref bs::FileEncoder "FileEncoder" class. Create the file encoder with a path to the output file, followed by a call to @ref bs::FileEncoder::encode "FileEncoder::encode()" with the object to encode as the parameter. The system will encode the provided object, as well as any other referenced **IReflectable** objects. 
+
+~~~~~~~~~~~~~{.cpp}
+SPtr<IReflectable> myObject = bs_shared_ptr_new<MyClass>();
+
+FileEncoder fe("Path\To\My\File.asset");
+fe.encode(myObject.get());
+~~~~~~~~~~~~~
+
+Once ready to decode, create a @ref bs::FileDecoder "FileDecoder" with the same file path. Then call @ref bs::FileDecoder::decode "FileDecoder::decode()".
+
+~~~~~~~~~~~~~{.cpp}
+FileDecoder fd("Path\To\My\File.asset");
+SPtr<IReflectable> myObjectCopy = fd.decode();
+~~~~~~~~~~~~~
+
+You can also encode/decode to/from memory by using @ref bs::MemorySerializer "MemorySerializer".
+~~~~~~~~~~~~~{.cpp}
+SPtr<IReflectable> myObject = bs_shared_ptr_new<MyClass>();
+
+MemorySerializer ms;
+UINT32 size;
+UINT8* data = ms.encode(myObject.get(), size);
+SPtr<IReflectable> myObjectCopy2 = ms.decode(data, size);
+
+bs_free(data);
+~~~~~~~~~~~~~

+ 1 - 1
Documentation/Manuals/Native/gameObjects.md

@@ -73,7 +73,7 @@ The @ref bs::Component "Component" interface provides several methods which you
  - @ref bs::Component::onEnabled "Component::onEnabled" - Called whenever a component is enabled, or instantiated as enabled in which case it is called after @ref bs::Component::onInitialized "Component::onInitialized".
  - @ref bs::Component::onDisabled "Component::onDisabled" - Called whenever a component is disabled. This includes destruction where it is called before @ref bs::Component::onDestroyed "Component::onDestroyed". 
  - @ref bs::Component::onDestroyed "Component::onDestroyed" - Called before the component is destroyed. Destruction is usually delayed until the end of the current frame unless specified otherwise in a call to @ref bs::Component::destroy "Component::destroy". 
- - @ref bs::Component::onTransformChanged "Component::onTransformChanged" - Called when the transform of the owning scene object changes. You must subscribe to this event by calling @ref bs::Component::setNotifyFlags "Component::setNotifyFlags".
+ - @ref bs::Component::onTransformChanged "Component::onTransformChanged" - Called when the transform of the owning scene object changes. You must subscribe to this event by calling @ref bs::Component::_setNotifyFlags "Component::_setNotifyFlags".
  
 Since components are a part of the scene you must also make sure to implement their @ref bs::RTTITypeBase "RTTIType", so they can be saved and loaded. Read the [RTTI](@ref rtti) manual for more information. Their creation differs slightly to normal RTTI objects: when overloading @ref bs::RTTITypeBase::newRTTIObject "RTTIType::newRTTIObject" make sure to use `GameObjectRTTI::createGameObject<T>` to create the component, instead of manually creating the shared pointer. This ensures that the component handle is properly created.
 

+ 3 - 1
Documentation/Manuals/Native/manuals.md

@@ -32,6 +32,7 @@ Manuals									{#manuals}
  - [Input events](@ref inputEvents) 
  - [Virtual input](@ref virtualInput)
 - [Creating custom components](@ref customComponents)
+- [Serializing objects](@ref serializingObjects)
 - **GUI**
  - [Sprite textures](@ref spriteTextures)
  - [Basic setup](@ref guiSetup)
@@ -57,6 +58,8 @@ Manuals									{#manuals}
  - [Playing animation](@ref animation)
  - [Bones](@ref bones)
  - [Advanced animation](@ref advancedAnimation)
+- **Advanced**
+ - [Advanced RTTI](@ref advancedRtti) 
  
 # Developer guides
 
@@ -70,7 +73,6 @@ Name                                      | Description
 [Utilities](@ref utilities)               | Provides an overview of a variety of utility systems used throughout Banshee.
 [Core thread](@ref coreThread)            | Explains how core (rendering) thread works, how it interacts with simulation thread, what are core objects and how to create your own.
 [Resources](@ref resources)  			  | Explains how resources work, including saving, loading and creating brand new resource types.
-[RTTI](@ref rtti)                         | Shows you how to add run-time type information for your objects.
 [Game objects](@ref gameObjects)          | Explains what are scene objects and components and how can you use them to create your scene.
 [Scripting](@ref scripting)               | Shows you how to interact with the scripting system, and how to expose C++ objects to the scripting API.
 [Renderer](@ref renderer)    	  		  | Explains how the renderer works on the low level, and how to create a custom renderer so you may fully customize the look of your application.

+ 11 - 11
Documentation/Manuals/Native/renderer.md

@@ -84,11 +84,11 @@ To create your own renderer you must implement the @ref bs::ct::Renderer "ct::Re
 The renderer is mostly a core-thread system as then it has a more direct access to the @ref bs::RenderAPI "RenderAPI", as well as various utility functionality we'll describe later. Read the [core thread](@ref coreThread) manual for more information about the core thread and core objects, and the [render API](@ref renderAPI) manual on how to use the low level rendering functionality.
 
 The @ref bs::ct::Renderer "ct::Renderer" interface requires you to implement the following methods:
- - @ref bs::ct::CoreRenderer::getName "ct::Renderer::getName" - Returns a unique name of the renderer. This can be used by shader techniques to identify which renderer is active and when they should run, as described in the [material](@ref materials) manual.
- - @ref bs::ct::CoreRenderer::renderAll "ct::Renderer::renderAll" - This is a method called from the simulation thread that executes the rendering. It is called once per frame. In this method you should queue your actual rendering method for execution on the core thread.
- - @ref bs::ct::CoreRenderer::notifyCameraAdded "ct::Renderer::notifyCameraAdded" - Called on the core thread whenever a new @ref bs::Camera "Camera" is created (i.e. when a @ref bs::CCamera "CCamera" component is added to the scene). Also called when camera's properties change (camera is removed, then re-added).
- - @ref bs::ct::CoreRenderer::notifyCameraUpdated "ct::Renderer::notifyCameraUpdated" - Called on the core thread whenever a @ref bs::Camera "Camera's" position or rotation changes.
- - @ref bs::ct::CoreRenderer::notifyCameraRemoved "ct::Renderer::notifyCameraRemoved" - Called on the core thread whenever a @ref bs::Camera "Camera" is destroyed. Also called when camera's properties change (camera is removed, then re-added).
+ - @ref bs::ct::Renderer::getName "ct::Renderer::getName" - Returns a unique name of the renderer. This can be used by shader techniques to identify which renderer is active and when they should run, as described in the [material](@ref materials) manual.
+ - @ref bs::ct::Renderer::renderAll "ct::Renderer::renderAll" - This is a method called from the simulation thread that executes the rendering. It is called once per frame. In this method you should queue your actual rendering method for execution on the core thread.
+ - @ref bs::ct::Renderer::notifyCameraAdded "ct::Renderer::notifyCameraAdded" - Called on the core thread whenever a new @ref bs::Camera "Camera" is created (i.e. when a @ref bs::CCamera "CCamera" component is added to the scene). Also called when camera's properties change (camera is removed, then re-added).
+ - @ref bs::ct::Renderer::notifyCameraUpdated "ct::Renderer::notifyCameraUpdated" - Called on the core thread whenever a @ref bs::Camera "Camera's" position or rotation changes.
+ - @ref bs::ct::Renderer::notifyCameraRemoved "ct::Renderer::notifyCameraRemoved" - Called on the core thread whenever a @ref bs::Camera "Camera" is destroyed. Also called when camera's properties change (camera is removed, then re-added).
  - @ref bs::ct::Renderer::notifyRenderableAdded "ct::Renderer::notifyRenderableAdded" - Called on the core thread whenever a new @ref bs::Renderable "Renderable" is created (e.g. when a @ref bs::CRenderable "CRenderable" component is added to the scene).
  - @ref bs::ct::Renderer::notifyRenderableUpdated "ct::Renderer::notifyRenderableUpdated" - Called whenever @ref bs::Renderable "Renderable" properties change, e.g. when a scene object a renderable is attached to moves.
  - @ref bs::ct::Renderer::notifyRenderableRemoved "ct::Renderer::notifyRenderableRemoved" - Called whenever a @ref bs::Renderable "Renderable" is destroyed.
@@ -302,26 +302,26 @@ gRendererUtility().draw(mesh, mesh->getProperties().getSubMesh(0));
 ~~~~~~~~~~~~~
  
 ### RenderTexturePool {#renderer_b_a_f}
-Although you can create render textures manually as described in the [render target](@ref renderTargets) manual, @ref bs::ct::RenderTexturePool "ct::RenderTexturePool" provides a simpler and more efficient way of doing it. It will keep alive any referenced render textures, so that other systems may re-use them if their size/formats match. This can improve performance when using many temporary/intermediary render textures (like in post-processing).
+Although you can create render textures manually as described in the [render target](@ref renderTargets) manual, @ref bs::ct::GpuResourcePool "ct::GpuResourcePool" provides a simpler and more efficient way of doing it. It will keep alive any referenced render textures, so that other systems may re-use them if their size/formats match. This can improve performance when using many temporary/intermediary render textures (like in post-processing).
 
 To request a render texture, first populate the @ref bs::ct::POOLED_RENDER_TEXTURE_DESC "ct::POOLED_RENDER_TEXTURE_DESC" descriptor, by calling either @ref bs::ct::POOLED_RENDER_TEXTURE_DESC::create2D "ct::POOLED_RENDER_TEXTURE_DESC::create2D", @ref bs::ct::POOLED_RENDER_TEXTURE_DESC::create3D "ct::POOLED_RENDER_TEXTURE_DESC::create3D" or @ref bs::ct::POOLED_RENDER_TEXTURE_DESC::createCube "ct::POOLED_RENDER_TEXTURE_DESC::createCube".
 
-Then call @ref bs::ct::RenderTexturePool::get "ct::RenderTexturePool::get" which will either create a new render texture, or return one from the pool. The returned object is @ref bs::ct::PooledRenderTexture "ct::PooledRenderTexture" from which you can access the actual render texture.
+Then call @ref bs::ct::GpuResourcePool::get "ct::GpuResourcePool::get" which will either create a new render texture, or return one from the pool. The returned object is @ref bs::ct::PooledRenderTexture "ct::PooledRenderTexture" from which you can access the actual render texture.
 
-Once you are done using the texture, call @ref bs::ct::RenderTexturePool::release "ct::RenderTexturePool::release" to return the texture to the pool, and make it available for other systems. If you plan on using this texture again, make sure to keep a reference to the @ref bs::ct::PooledRenderTexture "ct::PooledRenderTexture". This will prevent the pool from fully destroying the texture so it may be reused.
+Once you are done using the texture, call @ref bs::ct::GpuResourcePool::release "ct::GpuResourcePool::release" to return the texture to the pool, and make it available for other systems. If you plan on using this texture again, make sure to keep a reference to the @ref bs::ct::PooledRenderTexture "ct::PooledRenderTexture". This will prevent the pool from fully destroying the texture so it may be reused.
 
 For example:
 ~~~~~~~~~~~~~{.cpp}
 POOLED_RENDER_TEXTURE_DESC desc = POOLED_RENDER_TEXTURE_DESC::create2D(PF_R8G8B8A8, 1024, 1024);
-SPtr<PooledRenderTexture> pooledRT = RenderTexturePool::instance().get(desc);
+SPtr<PooledRenderTexture> pooledRT = GpuResourcePool::instance().get(desc);
 
 RenderAPI::instance().setRenderTarget(pooledRT->renderTexture);
 ... render to target ...
-RenderTexturePool::instance().release(pooledRT);
+GpuResourcePool::instance().release(pooledRT);
 // Keep a reference to pooledRT if we plan on re-using it, then next time just call get() using the same descriptor
 ~~~~~~~~~~~~~
 
 ### Renderer options {#renderer_b_a_g}
-You can customize your rendering at runtime by implementing the @ref bs::ct::CoreRendererOptions "ct::RendererOptions" class. Your @ref bs::ct::CoreRendererOptions "ct::RendererOptions" implementation can then be assigned to the renderer by calling @ref bs::ct::CoreRenderer::setOptions "ct::Renderer::setOptions", and accessed within the renderer via the `mOptions` field. No default options are provided and it's up to your renderer to decide what it requires.
+You can customize your rendering at runtime by implementing the @ref bs::ct::RendererOptions "ct::RendererOptions" class. Your @ref bs::ct::RendererOptions "ct::RendererOptions" implementation can then be assigned to the renderer by calling @ref bs::ct::Renderer::setOptions "ct::Renderer::setOptions", and accessed within the renderer via the `mOptions` field. No default options are provided and it's up to your renderer to decide what it requires.
 
 Be aware that options are set from the simulation thread, and if you want to use them on the core thread to either properly synchronize the access, or send a copy of the options to the core thread.

+ 0 - 338
Documentation/Manuals/Native/rtti.md

@@ -1,338 +0,0 @@
-Run-time type information						{#rtti}
-===============
-[TOC]
-
-This manual describes how is run-time type information (RTTI) used to provide meta-information about C++ classes during program execution. In Banshee specifically it allows you to:
- - Serialize/deserialize objects with no additional code 
- - Get the name of a class, and exact polymorphic type of an object (including safe casting)
- - Get the hierarchy of base/derived classes of a specific type
- - Iterate over all fields in an object, find their name and type, get/set their value
- - Create new instances of a type with only its type-name
- - Generate "diffs" of objects
- 
-It is primarily used for saving/loading of objects (e.g. serialization/deserialization of a level), searching for objects (e.g. finding all resources used by a level) and generating "diffs" (Prefabs use diffs to persist/apply instance specific changes when the original changes).
-
-RTTI doesn't automatically work on all classes. You must manually specify the information required by the RTTI system. This involves two things:
- - Making sure your class derives from @ref bs::IReflectable "IReflectable" and implements the required methods
- - Implement the @ref bs::RTTIType<Type, BaseType, MyRTTIType> "RTTIType" interface
- 
-# Adding RTTI to your own objects {#rtti_a}
-Assume you have a simple object you want to serialize:
-~~~~~~~~~~~~~{.cpp}
-class Texture
-{
-	int width, height;
-};
-~~~~~~~~~~~~~
-
-First off ensure it implements @ref bs::IReflectable "IReflectable" and `getRTTIStatic` and `getRTTI` methods:
-~~~~~~~~~~~~~{.cpp}
-class Texture : public IReflectable
-{
-   int width, height;
-
-   static RTTITypeBase* getRTTIStatic()
-   { return TextureRTTI::instance(); }
-
-   RTTITypeBase* getRTTI() const override
-   { return Texture::getRTTIStatic(); }
-};
-~~~~~~~~~~~~~
-	
-This interface and its methods only serve to return an instance of `TextureRTTI`, which derives from @ref bs::RTTIType<Type, BaseType, MyRTTIType> "RTTIType" and contains all the necessary RTTI information. You will also usually want to make the RTTI type a `friend` of the type so it can easily access its private and protected fields.
-
-A basic implementation of @ref bs::RTTIType<Type, BaseType, MyRTTIType> "RTTIType" must provide information about the type name, unique ID of the type, its base class (@ref bs::IReflectable "IReflectable" if it doesn't derive from anything else), a way to create a new instance of the type and a list of fields with their getter/setter methods. A simple one for our example `Texture` class might look like so:
-~~~~~~~~~~~~~{.cpp}
-class TextureRTTI : public RTTIType<Texture, IReflectable, TextureRTTI> // Specify type the RTTI is for, its base type, and RTTI type itself
-{
-	// Specify getter/setter methods for each field we want to be able to access from RTTI.
-	// Each getter/setter method always accepts a pointer to the instance being queried as the first parameter.
-	int& getWidth(Texture* obj) { return obj->width; }
-	void setWidth(Texture* obj, int& value) { obj->width = value; }
-	
-	int& getHeight(Texture* obj) { return obj->height; }
-	void setHeight(Texture* obj, int& value) { obj->height = value; }
-
-	TextureRTTI ()
-	{
-		// Register the getter/setter methods above. You must specify a name and field id (both must be unique within the type).
-		addPlainField("width", 0, &TextureRTTI::getWidth, &TextureRTTI::setWidth);
-		addPlainField("height", 1, &TextureRTTI::getHeight, &TextureRTTI::setHeight);
-	}
-
-	const String& getRTTIName() override
-	{
-		static String name = "Texture"; // Returns human readable name of the type
-		return name;
-	}
-
-	UINT32 getRTTIId() override
-	{
-		return TID_Texture; // User-provided globally unique integer for the type
-	}
-
-	SPtr<IReflectable> newRTTIObject() override
-	{
-		return bs_shared_ptr_new<Texture>(); // Create a brand new empty instance
-	}
-};
-~~~~~~~~~~~~~
-
-This is the minimum you need to do to add a RTTI type. However there are some advanced features that you might be interested in. You may specify different types of fields that can handle references to other complex objects, as well as provide arrays, or supply a pre- and post- processing steps for serialization. We'll cover this in the next sections.
-
-Important thing to note about RTTI type fields is that they all require a unique ID. This ID ensures that serialized data isn't broken if the layout of the object changes during development. This means you can add new fields, or remove old ones and expect data saved using an older version to "just work". You do need to ensure never to assign an ID of a previously removed field to a new field. You also need to change the ID if the field's type changes (i.e. it used to be `int` but now it's `long`).
-
-# Advanced field types  {#rtti_b}
-
-When registering fields with the RTTI type, the systems supports a several sets of `add*Field` methods, each expecting a unique name/id, but different getter/setter methods.
-
-## Plain fields  {#rtti_b_a}
-In the example above we have shown how to provide getter/setter methods for fields of `int` type. These fields are considered "plain" fields by the engine, and fields for types like `float`, `bool` and any other built-in language type also falls into this category.
-
-You register plain fields by calling @ref bs::RTTIType<Type, BaseType, MyRTTIType>::addPlainField "RTTIType::addPlainField". The getter/setter methods must return/accept a reference to the value of the field.
-
-## Reflectable fields  {#rtti_b_b}
-Reflectable fields contain types deriving from @ref bs::IReflectable "IReflectable", meaning they're complex objects that contain their own RTTI types. For example if we were to add a `Material` class to our example, it might contain a texture. In such case we would provide getter/setter methods like so:
-~~~~~~~~~~~~~{.cpp}
-class Material : public IReflectable
-{ 
-	Texture texture;
-	
-	... 
-};
-
-class MaterialRTTI : public RTTIType<Material, IReflectable, MaterialRTTI>
-{
-	Texture& getTexture(Material* obj) { return obj->texture; }
-	void setTexture(Material* obj, Texture& value) { obj->texture = value; }
-	
-	MaterialRTTI ()
-	{
-		addReflectableField("texture", 0, &MaterialRTTI::getTexture, &MaterialRTTI::setTexture);
-	}
-	
-	...
-};
-~~~~~~~~~~~~~
-
-As you can see the reflectable field is similar to a plain field, only the @ref bs::RTTIType<Type, BaseType, MyRTTIType>::addReflectableField "RTTIType::addReflectableField" method is used instead. 
-
-The problem with this approach is that during serialization whenever a material references a texture, that entire texture will end up being serialized with it. This is something you normally want to avoid since multiple materials will usually be referencing the same texture. For that purpose "Reflectable pointer" fields exist.
-
-## Reflectable pointer fields  {#rtti_b_c}
-This type of field is similar to the reflectable field, as it also contains types deriving from @ref bs::IReflectable "IReflectable". However they only return a pointer to the owned object, instead of copying the object by value. This is relevant for serialization as the system will be smart enough to detect multiple fields pointing to the same instance of an @ref bs::IReflectable "IReflectable" object, and only serialize it once (instead of every time it is encountered). When deserializing the system will also properly restore the pointers, so that all fields keep pointing to the same instance.
-
-Reflectable pointer getter/setter methods must return shared pointers to the instance, and they're registered with @ref bs::RTTIType<Type, BaseType, MyRTTIType>::addReflectablePtrField "RTTIType::addReflectablePtrField". For example if we modified our `Material` class like so:
-~~~~~~~~~~~~~{.cpp}
-class Material : public IReflectable
-{ 
-	SPtr<Texture> texture;
-	
-	... 
-};
-
-class MaterialRTTI : public RTTIType<Material, IReflectable, MaterialRTTI>
-{
-	SPtr<Texture> getTexture(Material* obj) { return obj->texture; }
-	void setTexture(Material* obj, SPtr<Texture> value) { obj->texture = value; }
-	
-	MaterialRTTI ()
-	{
-		addReflectablePtrField("texture", 0, &MaterialRTTI::getTexture, &MaterialRTTI::setTexture);
-	}
-	
-	...
-};
-~~~~~~~~~~~~~
-
-## Array fields  {#rtti_b_d}
-Each of the valid field types (plain/reflectable/reflectable pointer), also come in array form. The array form requires two additional getter/setter methods that get/set array size, and normal getter/setter methods require an additional index parameter. For example if we wanted to extend our material so it contains multiple textures:
-~~~~~~~~~~~~~{.cpp}
-class Material : public IReflectable
-{ 
-	Vector<SPtr<Texture>> textures;
-	
-	... 
-};
-
-class MaterialRTTI : public RTTIType<Material, IReflectable, MaterialRTTI>
-{
-	SPtr<Texture> getTexture(Material* obj, UINT32 idx) { return obj->textures[idx]; }
-	void setTexture(Material* obj, UINT32 idx, SPtr<Texture> value) { obj->textures[idx] = value; }
-	
-	UINT32 getNumTextures(Material* obj) { return obj->textures.size(); }
-	void setNumTextures(Material* obj, UINT32 size) { obj->textures.resize(size); }
-	
-	MaterialRTTI ()
-	{
-		addReflectablePtrArrayField("texture", 0, &MaterialRTTI::getTexture, &MaterialRTTI::getNumTextures, 
-			&MaterialRTTI::setTexture, &MaterialRTTI::setNumTextures);
-	}
-	
-	...
-};
-~~~~~~~~~~~~~
-
-Methods for registering array fields are:
- - @ref bs::RTTIType<Type, BaseType, MyRTTIType>::addPlainArrayField "RTTIType::addPlainArrayField"
- - @ref bs::RTTIType<Type, BaseType, MyRTTIType>::addReflectableArrayField "RTTIType::addReflectableArrayField"
- - @ref bs::RTTIType<Type, BaseType, MyRTTIType>::addReflectablePtrArrayField "RTTIType::addReflectablePtrArrayField"
-
-They all follow the same syntax as in the example above.
- 
-## Advanced plain fields  {#rtti_b_e}
-Although plain fields are primarily intended for simple built-in types, sometimes they also needs to be used on complex types. For example a `std::string` is often used as a field type, but it is not a simple built-in type, nor can we make it derive from @ref bs::IReflectable "IReflectable" so we can't use reflectable fields either. For these purposes you can use @ref bs::RTTIPlainType<T> "RTTIPlainType". This is a templated class you can specialize for your specific type. 
-
-It provides methods for serializing/deserializing and retrieving object size. It has no advanced functionality like versioning (so if the structure of the type changes, it will break any previously serialized data), or keeping references to other objects.
-
-For example if we wanted to serialize a string:
-~~~~~~~~~~~~~{.cpp}
-template<> struct RTTIPlainType<std::string>
-{	
-	enum { id = 20 }; enum { hasDynamicSize = 1 }; // Provide unique ID, and a flag whether the size of the structure is dynamic.
-
-	static void toMemory(const std::string& data, char* memory)
-	{ 
-		UINT32 size = getDynamicSize(data);
-
-		memcpy(memory, &size, sizeof(UINT32));
-		memory += sizeof(UINT32);
-		size -= sizeof(UINT32);
-		memcpy(memory, data.data(), size); 
-	}
-
-	static UINT32 fromMemory(std::string& data, char* memory)
-	{ 
-		UINT32 size;
-		memcpy(&size, memory, sizeof(UINT32)); 
-		memory += sizeof(UINT32);
-
-		UINT32 stringSize = size - sizeof(UINT32);
-		data = std::string(memory, stringSize);
-
-		return size;
-	}
-
-	static UINT32 getDynamicSize(const std::string& data)	
-	{ 
-		UINT64 dataSize = data.size() * sizeof(std::string::value_type) + sizeof(UINT32);
-		return (UINT32)dataSize;
-	}	
-}; 
-~~~~~~~~~~~~~
-
-Each specialization must implement all three (`toMemory/fromMemory/getDynamicSize`) methods. It must also provide a flag `hasDynamicSize` which determines whether or not it has dynamic size. Any structure whose size varies with each instance must set this flag to true. You must also set it to true if the size is static but larger than 255 bytes.
-
-After you implement this class you will be able to use the type in getters/setters for plain fields as you would `int` or `float`. You can also use the @ref BS_ALLOW_MEMCPY_SERIALIZATION macro for simple structures. It will create a basic @ref bs::RTTIPlainType<T> "RTTIPlainType" specialization which uses `memcpy()`/`sizeof()` to implement the necessary methods.
-
-If possible you should prefer implementing an @ref bs::IReflectable "IReflectable" for complex objects instead of this approach. But it can be useful for types where no other option is available (like third party or standard library types) or types you are sure won't change or require other advanced functionality.
-
-@ref bs::RTTIPlainType<T> "RTTIPlainType" specializations can also be used as a more traditional form of serialization in case you find the RTTI system an overkill. For example if you needed to transfer data over a network. The system provides helper methods that allow you to easily work with plain types in such a case:
- - @ref bs::rttiReadElem "rttiReadElem" - Deserializes an object from the provided buffer and returns offset into the buffer after the read data
- - @ref bs::rttiWriteElem "rttiWriteElem" - Serializes an object into the provided buffer and returns offset into the buffer after the written data
- - @ref bs::rttiGetElemSize "rttiGetElemSize" - Returns a size an object
-
-## RTTI field macros  {#rtti_b_f} 
-In order to make definitions for fields in an RTTI type simpler, Banshee provides a set of macros you can use. These macros will automatically create getter/setter methods, and register the field. The macros are:
- - BS_RTTI_MEMBER_PLAIN(name, id) - Registers a new plain field for the variable `name` with a unique id `id`. 
- - BS_RTTI_MEMBER_PLAIN_NAMED(name, field, id) - Registers a new plain field for the variable `field` with a unique id `id`, and name `name`. Useful when the variable name cannot be used for the field name as it's done in BS_RTTI_MEMBER_PLAIN (e.g. if it is nested within another structure).
- - BS_RTTI_MEMBER_PLAIN_ARRAY(name, id) - Registers a new plain field for the variable `field` with a unique id `id`. The field contains a `Vector` of plain values.
- - BS_RTTI_MEMBER_REFL(name, id) - Same as BS_RTTI_MEMBER_PLAIN but for reflectable fields.
- - BS_RTTI_MEMBER_REFL_NAMED(name, field, id) - Same as BS_RTTI_MEMBER_PLAIN_NAMED but for reflectable fields.
- - BS_RTTI_MEMBER_REFL_ARRAY(name, id) - Same as BS_RTTI_MEMBER_PLAIN_ARRAY but for reflectable fields.
- - BS_RTTI_MEMBER_REFLPTR(name, id) - Same as BS_RTTI_MEMBER_PLAIN but for reflectable pointer fields.
- - BS_RTTI_MEMBER_REFLPTR_NAMED(name, field, id) - Same as BS_RTTI_MEMBER_PLAIN_NAMED but for reflectable pointer fields.
- - BS_RTTI_MEMBER_REFLPTR_ARRAY(name, id) - Same as BS_RTTI_MEMBER_PLAIN_ARRAY but for reflectable pointer fields.
- 
-Before you use any of those macros you must first call @ref BS_BEGIN_RTTI_MEMBERS() "BS_BEGIN_RTTI_MEMBERS" macro, and follow it with @ref BS_END_RTTI_MEMBERS() "BS_END_RTTI_MEMBERS" macro. These macros will define a new field `mInitMembers` in the @ref bs::RTTITypeBase "RTTIType", which you need to initialize in the constructor with the `this` pointer.
-
-If we refactor our `TextureRTTI` example from above to use macros, it would look like so:
-~~~~~~~~~~~~~{.cpp}
-class TextureRTTI : public RTTIType<Texture, IReflectable, TextureRTTI>
-{
-	BS_BEGIN_RTTI_MEMBERS
-		BS_RTTI_MEMBER_PLAIN(width, 0)
-		BS_RTTI_MEMBER_PLAIN(height, 1)
-	BS_END_RTTI_MEMBERS
-	
-	TextureRTTI ()
-		:mInitMembers(this)
-	{ }
-
-	const String& getRTTIName() override
-	{
-		static String name = "Texture";
-		return name;
-	}
-
-	UINT32 getRTTIId() override
-	{
-		return TID_Texture;
-	}
-
-	SPtr<IReflectable> newRTTIObject() override
-	{
-		return bs_shared_ptr_new<Texture>();
-	}
-};
-~~~~~~~~~~~~~
- 
-# Advanced serialization  {#rtti_c}
-Implementations of @ref bs::RTTIType<Type, BaseType, MyRTTIType> "RTTIType" can optionally override @ref bs::RTTIType<Type, BaseType, MyRTTIType>::onSerializationStarted "RTTIType::onSerializationStarted", @ref bs::RTTIType<Type, BaseType, MyRTTIType>::onSerializationEnded "RTTIType::onSerializationEnded", @ref bs::RTTIType<Type, BaseType, MyRTTIType>::onDeserializationStarted "RTTIType::onDeserializationStarted" and @ref bs::RTTIType<Type, BaseType, MyRTTIType>::onDeserializationEnded "RTTIType::onDeserializationEnded" methods. As their names imply they will get called during serialization/deserialization and allow you to do any pre- or post-processing of the data. Most other systems (other than serialization) that access field data will also call these functions before reading, and after writing field data.
-
-Each of those methods accepts an @ref bs::IReflectable "IReflectable" pointer to the object currently being processed. Each type that implements @ref bs::IReflectable "IReflectable" also comes with a `mRTTIData` field which is of @ref bs::Any "Any" type, and can be used for storing temporary data during serialization/deserialization (primarily when using the methods above).
-
-# Using RTTI  {#rtti_d}
-Once you have an object with a RTTI type fully implemented you can use it for various purposes.
-
-## Getting object information  {#rtti_d_a}
-
-~~~~~~~~~~~~~{.cpp}
-IReflectable* myObject = ...;
-
-rtti_is_of_type<Texture>(myObject); // Check if the object's type matches the provided type
-rtti_is_subclass<Texture>(myObject); // Check if type of the object is a subclass of the provided type
-rtti_create(TID_Texture); // Create a new empty instance of the object
-
-myObject->getTypeName(); // Name of the object's type
-myObject->getTypeId(); // Unique identifier of the object's type
-
-RTTITypeBase* rttiType = myObject->getRTTI(); // Returns the RTTIType object
-rttiType->getBaseClass(); // Get RTTI type for the base class
-rttiType->getDerivedClasses(); // Get all derived classes for an object
-rttiType->getNumFields(); // Get number of RTTI fields 
-rttiType->getField(index); // Get information about a field from its sequential index
-RTTIField* rttiField = rttiType->findField(name); // Get information about a field from its name
-rttiType->setPlainValue(myObject, "myField", someValue); // Set a value of a RTTI field (similar operations for all field types, including getters, and array fields)
-
-rttiField->isPlainType(); // Is field storing a plain type
-rttiField->isReflectableType(); // Is field storing a plain type
-rttiField->isReflectablePtrType(); // Is field storing a plain type
-rttiField->isArray(); // Does the field contain an array
-
-// Cast RTTIField* to RTTIPlainFieldBase*, RTTIReflectableFieldBase* or RTTIReflectablePtrFieldBase* according to exact type.
-// Use that type to access the field values (not shown here, but has the same effect as get/set methods on RTTIType* shown above, only more efficient)
-~~~~~~~~~~~~~
-
-## Serialization  {#rtti_d_b}
-Serialization uses all the features shown in the chapter above in order to serialize an @ref bs::IReflectable "IReflectable" object into a stream of bytes, and vice versa. By default binary serialization is used, but user can implement textual serialization (like XML or JSON) using the RTTI system, if needed.
-
-Binary serialized data can be output to memory, or to a file using: @ref bs::MemorySerializer "MemorySerializer", @ref bs::FileEncoder "FileEncoder", @ref bs::FileDecoder "FileDecoder". Their usage is simple:
-~~~~~~~~~~~~~{.cpp}
-IReflectable* myObject = ...;
-
-// Encode to file, then decode from it
-FileEncoder fe("Path\To\My\File.asset");
-fe.encode(myObject);
-
-FileDecoder fd("Path\To\My\File.asset");
-SPtr<IReflectable> myObjectCopy = fd.decode();
-
-// Encode to memory, then decode from it
-MemorySerializer ms;
-UINT32 size;
-UINT8* data = ms.encode(myObject, size);
-SPtr<IReflectable> myObjectCopy2 = ms.decode(data, size);
-
-bs_free(data);
-~~~~~~~~~~~~~

+ 9 - 0
Source/BansheeUtility/Include/BsRTTIField.h

@@ -95,10 +95,19 @@ namespace bs
 		SerializableFieldType mType;
 		UINT64 mFlags;
 
+		/** Checks is the field plain type and castable to RTTIPlainFieldBase. */
 		bool isPlainType() const { return mType == SerializableFT_Plain; }
+
+		/** Checks is the field a data block type and castable to RTTIManagedDataBlockFieldBase. */
 		bool isDataBlockType() const { return mType == SerializableFT_DataBlock; }
+
+		/** Checks is the field a reflectable type and castable to RTTIReflectableFieldBase. */
 		bool isReflectableType() const { return mType == SerializableFT_Reflectable; }
+
+		/** Checks is the field a reflectable pointer type and castable to RTTIReflectablePtrFieldBase. */
 		bool isReflectablePtrType() const { return mType == SerializableFT_ReflectablePtr; }
+
+		/** Checks is the field contains an array or a single entry. */
 		bool isArray() const { return mIsVectorType; }
 
 		/** Returns flags that were set in the field meta-data. */