1//************************************ bs::framework - Copyright 2018 Marko Pintera **************************************//
2//*********** Licensed under the MIT license. See LICENSE.md for full terms. This notice is not to be removed. ***********//
3#pragma once
4
5#include "Prerequisites/BsPrerequisitesUtil.h"
6#include "Reflection/BsRTTIField.h"
7
8namespace bs
9{
10 /** @addtogroup Internal-Utility
11 * @{
12 */
13
14 /** @addtogroup RTTI-Internal
15 * @{
16 */
17
18 /**
19 * Base class containing common functionality for a managed data block class field.
20 *
21 * @note
22 * Managed data blocks are just blocks of memory that may, or may not be released automatically when they are no longer
23 * referenced. They are useful when wanting to return some temporary data only for serialization purposes.
24 */
25 struct RTTIManagedDataBlockFieldBase : public RTTIField
26 {
27 /** Retrieves a managed data block from the specified instance. */
28 virtual SPtr<DataStream> getValue(RTTITypeBase* rtti, void* object, UINT32& size) = 0;
29
30 /** Sets a managed data block on the specified instance. */
31 virtual void setValue(RTTITypeBase* rtti, void* object, const SPtr<DataStream>& data, UINT32 size) = 0;
32 };
33
34 /** Class containing a managed data block field containing a specific type. */
35 template <class InterfaceType, class DataType, class ObjectType>
36 struct RTTIManagedDataBlockField : public RTTIManagedDataBlockFieldBase
37 {
38 typedef SPtr<DataStream> (InterfaceType::*GetterType)(ObjectType*, UINT32&);
39 typedef void (InterfaceType::*SetterType)(ObjectType*, const SPtr<DataStream>&, UINT32);
40
41 /**
42 * Initializes a field that returns a block of bytes. Can be used for serializing pretty much anything.
43 *
44 * @param[in] name Name of the field.
45 * @param[in] uniqueId Unique identifier for this field. Although name is also a unique identifier we want a
46 * small data type that can be used for efficiently serializing data to disk and similar.
47 * It is primarily used for compatibility between different versions of serialized data.
48 * @param[in] getter The getter method for the field.
49 * @param[in] setter The setter method for the field.
50 * @param[in] info Various optional information about the field.
51 */
52 void initSingle(String name, UINT16 uniqueId, GetterType getter, SetterType setter, const RTTIFieldInfo& info)
53 {
54 this->getter = getter;
55 this->setter = setter;
56
57 init(std::move(name), uniqueId, false, SerializableFT_DataBlock, info);
58 }
59
60 /** @copydoc RTTIField::getTypeSize */
61 UINT32 getTypeSize() override
62 {
63 return 0; // Data block types don't store size the conventional way
64 }
65
66 /** @copydoc RTTIField::hasDynamicSize */
67 bool hasDynamicSize() override
68 {
69 return true;
70 }
71
72 /** @copydoc RTTIField::getArraySize */
73 UINT32 getArraySize(RTTITypeBase* rtti, void* object) override
74 {
75 BS_EXCEPT(InternalErrorException,
76 "Data block types don't support arrays.");
77
78 return 0;
79 }
80
81 /** @copydoc RTTIField::setArraySize */
82 void setArraySize(RTTITypeBase* rtti, void* object, UINT32 size) override
83 {
84 BS_EXCEPT(InternalErrorException,
85 "Data block types don't support arrays.");
86 }
87
88 /** @copydoc RTTIManagedDataBlockFieldBase::getValue */
89 SPtr<DataStream> getValue(RTTITypeBase* rtti, void* object, UINT32& size) override
90 {
91 InterfaceType* rttiObject = static_cast<InterfaceType*>(rtti);
92 ObjectType* castObj = static_cast<ObjectType*>(object);
93
94 return (rttiObject->*getter)(castObj, size);
95 }
96
97 /** @copydoc RTTIManagedDataBlockFieldBase::setValue */
98 void setValue(RTTITypeBase* rtti, void* object, const SPtr<DataStream>& value, UINT32 size) override
99 {
100 InterfaceType* rttiObject = static_cast<InterfaceType*>(rtti);
101 ObjectType* castObj = static_cast<ObjectType*>(object);
102
103 (rttiObject->*setter)(castObj, value, size);
104 }
105
106 private:
107 GetterType getter;
108 SetterType setter;
109 };
110
111 /** @} */
112 /** @} */
113}