| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294 |
- //********************************** Banshee Engine (www.banshee3d.com) **************************************************//
- //**************** Copyright (c) 2016 Marko Pintera ([email protected]). All rights reserved. **********************//
- #pragma once
- #include "Prerequisites/BsPrerequisitesUtil.h"
- #include "Reflection/BsRTTIField.h"
- #include "Error/BsException.h"
- namespace bs
- {
- /** @addtogroup Internal-Utility
- * @{
- */
- /** @addtogroup RTTI-Internal
- * @{
- */
- /**
- * Base class containing common functionality for a plain class field.
- *
- * @note
- * Plain fields are considered those that may be serialized directly by copying their memory. (All built-in types,
- * strings, etc.)
- */
- struct RTTIPlainFieldBase : public RTTIField
- {
- virtual ~RTTIPlainFieldBase() { }
- /** Throws an exception if the current field type and provided template types don't match. */
- template<class DataType>
- void checkType()
- {
- // TODO: Low priority. Because I wanted to get rid of SerializableType I have no way of checking the actual
- // type of the field and the type provided to get/set methods matches
- /*if(mType.id != SerializableType<DataType>().id)
- {
- BS_EXCEPT(InternalErrorException,
- "Invalid field type.",
- "SerializableSimpleTypeFieldBase::checkType()");
- }*/
- }
-
- /** Returns the unique identifier for the type owned by the field. */
- virtual UINT32 getTypeId()
- {
- return 0;
- }
- /** @copydoc RTTIField::hasDynamicSize */
- bool hasDynamicSize() override
- {
- return false;
- }
- /** Gets the dynamic size of the object. If object has no dynamic size, static size of the object is returned. */
- virtual UINT32 getDynamicSize(void* object)
- {
- return 0;
- }
- /**
- * Gets the dynamic size of an array element. If the element has no dynamic size, static size of the element
- * is returned.
- */
- virtual UINT32 getArrayElemDynamicSize(void* object, int index)
- {
- return 0;
- }
- /**
- * Retrieves the value from the provided field of the provided object, and copies it into the buffer. It does not
- * check if buffer is large enough.
- */
- virtual void toBuffer(void* object, void* buffer) = 0;
- /**
- * Retrieves the value at the specified array index on the provided field of the provided object, and copies it into
- * the buffer. It does not check if buffer is large enough.
- */
- virtual void arrayElemToBuffer(void* object, int index, void* buffer) = 0;
- /**
- * Sets the value on the provided field of the provided object. Value is copied from the buffer. It does not check
- * the value in the buffer in any way. You must make sure buffer points to the proper location and contains the
- * proper type.
- */
- virtual void fromBuffer(void* object, void* buffer) = 0;
- /**
- * Sets the value at the specified array index on the provided field of the provided object. Value is copied from
- * the buffer. It does not check the value in the buffer in any way. You must make sure buffer points to the proper
- * location and contains the proper type.
- */
- virtual void arrayElemFromBuffer(void* object, int index, void* buffer) = 0;
- };
- /** Represents a plain class field containing a specific type. */
- template <class DataType, class ObjectType>
- struct RTTIPlainField : public RTTIPlainFieldBase
- {
- /**
- * Initializes a plain field containing a single value.
- *
- * @param[in] name Name of the field.
- * @param[in] uniqueId Unique identifier for this field. Although name is also a unique identifier we want a
- * small data type that can be used for efficiently serializing data to disk and similar.
- * It is primarily used for compatibility between different versions of serialized data.
- * @param[in] getter The getter method for the field. Must be a specific signature: DataType(ObjectType*).
- * @param[in] setter The setter method for the field. Must be a specific signature: void(ObjectType*, DataType)
- * @param[in] flags Various flags you can use to specialize how outside systems handle this field. See "RTTIFieldFlag".
- */
- void initSingle(const String& name, UINT16 uniqueId, Any getter, Any setter, UINT64 flags)
- {
- static_assert(sizeof(RTTIPlainType<DataType>::id) > 0, "Type has no RTTI ID."); // Just making sure provided type has a type ID
- static_assert((RTTIPlainType<DataType>::hasDynamicSize != 0 || (sizeof(DataType) <= 255)),
- "Trying to create a plain RTTI field with size larger than 255. In order to use larger sizes for plain types please specialize " \
- " RTTIPlainType, set hasDynamicSize to true.");
- initAll(getter, setter, nullptr, nullptr, name, uniqueId, false, SerializableFT_Plain, flags);
- }
- /**
- * Initializes a plain field containing multiple values in an array.
- *
- * @param[in] name Name of the field.
- * @param[in] uniqueId Unique identifier for this field. Although name is also a unique identifier we want a
- * small data type that can be used for efficiently serializing data to disk and similar.
- * It is primarily used for compatibility between different versions of serialized data.
- * @param[in] getter The getter method for the field. Must be a specific signature: DataType(ObjectType*, UINT32)
- * @param[in] getSize Getter method that returns the size of an array. Must be a specific signature: UINT32(ObjectType*)
- * @param[in] setter The setter method for the field. Must be a specific signature: void(ObjectType*, UINT32, DataType)
- * @param[in] setSize Setter method that allows you to resize an array. Can be null. Must be a specific signature: void(ObjectType*, UINT32)
- * @param[in] flags Various flags you can use to specialize how outside systems handle this field. See "RTTIFieldFlag".
- */
- void initArray(const String& name, UINT16 uniqueId, Any getter,
- Any getSize, Any setter, Any setSize, UINT64 flags)
- {
- static_assert((RTTIPlainType<DataType>::id != 0) || true, ""); // Just making sure provided type has a type ID
- static_assert((RTTIPlainType<DataType>::hasDynamicSize != 0 || (sizeof(DataType) <= 255)),
- "Trying to create a plain RTTI field with size larger than 255. In order to use larger sizes for plain types please specialize " \
- " RTTIPlainType, set hasDynamicSize to true.");
- initAll(getter, setter, getSize, setSize, name, uniqueId, true, SerializableFT_Plain, flags);
- }
- /** @copydoc RTTIField::getTypeSize */
- UINT32 getTypeSize() override
- {
- return sizeof(DataType);
- }
- /** @copydoc RTTIPlainFieldBase::getTypeId */
- UINT32 getTypeId() override
- {
- return RTTIPlainType<DataType>::id;
- }
- /** @copydoc RTTIPlainFieldBase::hasDynamicSize */
- bool hasDynamicSize() override
- {
- return RTTIPlainType<DataType>::hasDynamicSize != 0;
- }
- /** @copydoc RTTIPlainFieldBase::getDynamicSize */
- UINT32 getDynamicSize(void* object) override
- {
- checkIsArray(false);
- checkType<DataType>();
- ObjectType* castObject = static_cast<ObjectType*>(object);
- std::function<DataType&(ObjectType*)> f = any_cast<std::function<DataType&(ObjectType*)>>(valueGetter);
- DataType value = f(castObject);
- return RTTIPlainType<DataType>::getDynamicSize(value);
- }
- /** @copydoc RTTIPlainFieldBase::getArrayElemDynamicSize */
- UINT32 getArrayElemDynamicSize(void* object, int index) override
- {
- checkIsArray(true);
- checkType<DataType>();
- ObjectType* castObject = static_cast<ObjectType*>(object);
- std::function<DataType&(ObjectType*, UINT32)> f = any_cast<std::function<DataType&(ObjectType*, UINT32)>>(valueGetter);
- DataType value = f(castObject, index);
- return RTTIPlainType<DataType>::getDynamicSize(value);
- }
- /** Returns the size of the array managed by the field. */
- UINT32 getArraySize(void* object) override
- {
- checkIsArray(true);
- std::function<UINT32(ObjectType*)> f = any_cast<std::function<UINT32(ObjectType*)>>(arraySizeGetter);
- ObjectType* castObject = static_cast<ObjectType*>(object);
- return f(castObject);
- }
- /** Changes the size of the array managed by the field. Array must be re-populated after. */
- void setArraySize(void* object, UINT32 size) override
- {
- checkIsArray(true);
- if(arraySizeSetter.empty())
- {
- BS_EXCEPT(InternalErrorException, "Specified field (" + mName + ") has no array size setter.");
- }
- std::function<void(ObjectType*, UINT32)> f = any_cast<std::function<void(ObjectType*, UINT32)>>(arraySizeSetter);
- ObjectType* castObject = static_cast<ObjectType*>(object);
- f(castObject, size);
- }
- /** @copydoc RTTIPlainFieldBase::toBuffer */
- void toBuffer(void* object, void* buffer) override
- {
- checkIsArray(false);
- checkType<DataType>();
- ObjectType* castObject = static_cast<ObjectType*>(object);
- std::function<DataType&(ObjectType*)> f = any_cast<std::function<DataType&(ObjectType*)>>(valueGetter);
- DataType value = f(castObject);
- RTTIPlainType<DataType>::toMemory(value, (char*)buffer);
- }
- /** @copydoc RTTIPlainFieldBase::arrayElemToBuffer */
- void arrayElemToBuffer(void* object, int index, void* buffer) override
- {
- checkIsArray(true);
- checkType<DataType>();
- ObjectType* castObject = static_cast<ObjectType*>(object);
- std::function<DataType&(ObjectType*, UINT32)> f = any_cast<std::function<DataType&(ObjectType*, UINT32)>>(valueGetter);
- DataType value = f(castObject, index);
- RTTIPlainType<DataType>::toMemory(value, (char*)buffer);
- }
- /** @copydoc RTTIPlainFieldBase::fromBuffer */
- void fromBuffer(void* object, void* buffer) override
- {
- checkIsArray(false);
- checkType<DataType>();
- ObjectType* castObject = static_cast<ObjectType*>(object);
- DataType value;
- RTTIPlainType<DataType>::fromMemory(value, (char*)buffer);
- if(valueSetter.empty())
- {
- BS_EXCEPT(InternalErrorException,
- "Specified field (" + mName + ") has no setter.");
- }
- std::function<void(ObjectType*, DataType&)> f = any_cast<std::function<void(ObjectType*, DataType&)>>(valueSetter);
- f(castObject, value);
- }
- /** @copydoc RTTIPlainFieldBase::arrayElemFromBuffer */
- void arrayElemFromBuffer(void* object, int index, void* buffer) override
- {
- checkIsArray(true);
- checkType<DataType>();
- ObjectType* castObject = static_cast<ObjectType*>(object);
- DataType value;
- RTTIPlainType<DataType>::fromMemory(value, (char*)buffer);
- if(valueSetter.empty())
- {
- BS_EXCEPT(InternalErrorException,
- "Specified field (" + mName + ") has no setter.");
- }
- std::function<void(ObjectType*, UINT32, DataType&)> f = any_cast<std::function<void(ObjectType*, UINT32, DataType&)>>(valueSetter);
- f(castObject, index, value);
- }
- };
- /** @} */
- /** @} */
- }
|