Serializable.h 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280
  1. // Copyright (c) 2008-2023 the Urho3D project
  2. // License: MIT
  3. #pragma once
  4. #include "../Core/Attribute.h"
  5. #include "../Core/Object.h"
  6. #include <cstddef>
  7. #include <memory>
  8. #include <type_traits>
  9. namespace Urho3D
  10. {
  11. class Connection;
  12. class Deserializer;
  13. class Serializer;
  14. class XMLElement;
  15. class JSONValue;
  16. struct DirtyBits;
  17. struct NetworkState;
  18. struct ReplicationState;
  19. /// Base class for objects with automatic serialization through attributes.
  20. class URHO3D_API Serializable : public Object
  21. {
  22. URHO3D_OBJECT(Serializable, Object);
  23. public:
  24. /// Construct.
  25. explicit Serializable(Context* context);
  26. /// Destruct.
  27. ~Serializable() override;
  28. /// Handle attribute write access. Default implementation writes to the variable at offset, or invokes the set accessor.
  29. virtual void OnSetAttribute(const AttributeInfo& attr, const Variant& src);
  30. /// Handle attribute read access. Default implementation reads the variable at offset, or invokes the get accessor.
  31. virtual void OnGetAttribute(const AttributeInfo& attr, Variant& dest) const;
  32. /// Return attribute descriptions, or null if none defined.
  33. virtual const Vector<AttributeInfo>* GetAttributes() const;
  34. /// Return network replication attribute descriptions, or null if none defined.
  35. virtual const Vector<AttributeInfo>* GetNetworkAttributes() const;
  36. /// Load from binary data. Return true if successful.
  37. virtual bool Load(Deserializer& source);
  38. /// Save as binary data. Return true if successful.
  39. virtual bool Save(Serializer& dest) const;
  40. /// Load from XML data. Return true if successful.
  41. virtual bool LoadXML(const XMLElement& source);
  42. /// Save as XML data. Return true if successful.
  43. virtual bool SaveXML(XMLElement& dest) const;
  44. /// Load from JSON data. Return true if successful.
  45. virtual bool LoadJSON(const JSONValue& source);
  46. /// Save as JSON data. Return true if successful.
  47. virtual bool SaveJSON(JSONValue& dest) const;
  48. /// Apply attribute changes that can not be applied immediately. Called after scene load or a network update.
  49. virtual void ApplyAttributes() { }
  50. /// Return whether should save default-valued attributes into XML. Default false.
  51. virtual bool SaveDefaultAttributes() const { return false; }
  52. /// Mark for attribute check on the next network update.
  53. virtual void MarkNetworkUpdate() { }
  54. /// Set attribute by index. Return true if successfully set.
  55. /// @property{set_attributes}
  56. bool SetAttribute(unsigned index, const Variant& value);
  57. /// Set attribute by name. Return true if successfully set.
  58. bool SetAttribute(const String& name, const Variant& value);
  59. /// Set instance-level default flag.
  60. void SetInstanceDefault(bool enable) { setInstanceDefault_ = enable; }
  61. /// Reset all editable attributes to their default values.
  62. void ResetToDefault();
  63. /// Remove instance's default values if they are set previously.
  64. void RemoveInstanceDefault();
  65. /// Set temporary flag. Temporary objects will not be saved.
  66. /// @property
  67. void SetTemporary(bool enable);
  68. /// Enable interception of an attribute from network updates. Intercepted attributes are sent as events instead of applying directly. This can be used to implement client side prediction.
  69. void SetInterceptNetworkUpdate(const String& attributeName, bool enable);
  70. /// Allocate network attribute state.
  71. void AllocateNetworkState();
  72. /// Write initial delta network update.
  73. void WriteInitialDeltaUpdate(Serializer& dest, unsigned char timeStamp);
  74. /// Write a delta network update according to dirty attribute bits.
  75. void WriteDeltaUpdate(Serializer& dest, const DirtyBits& attributeBits, unsigned char timeStamp);
  76. /// Write a latest data network update.
  77. void WriteLatestDataUpdate(Serializer& dest, unsigned char timeStamp);
  78. /// Read and apply a network delta update. Return true if attributes were changed.
  79. bool ReadDeltaUpdate(Deserializer& source);
  80. /// Read and apply a network latest data update. Return true if attributes were changed.
  81. bool ReadLatestDataUpdate(Deserializer& source);
  82. /// Return attribute value by index. Return empty if illegal index.
  83. /// @property{get_attributes}
  84. Variant GetAttribute(unsigned index) const;
  85. /// Return attribute value by name. Return empty if not found.
  86. Variant GetAttribute(const String& name) const;
  87. /// Return attribute default value by index. Return empty if illegal index.
  88. /// @property{get_attributeDefaults}
  89. Variant GetAttributeDefault(unsigned index) const;
  90. /// Return attribute default value by name. Return empty if not found.
  91. Variant GetAttributeDefault(const String& name) const;
  92. /// Return number of attributes.
  93. /// @property
  94. unsigned GetNumAttributes() const;
  95. /// Return number of network replication attributes.
  96. unsigned GetNumNetworkAttributes() const;
  97. /// Return whether is temporary.
  98. /// @property
  99. bool IsTemporary() const { return temporary_; }
  100. /// Return whether an attribute's network updates are being intercepted.
  101. bool GetInterceptNetworkUpdate(const String& attributeName) const;
  102. /// Return the network attribute state, if allocated.
  103. NetworkState* GetNetworkState() const { return networkState_.get(); }
  104. protected:
  105. /// Network attribute state.
  106. std::unique_ptr<NetworkState> networkState_;
  107. private:
  108. /// Set instance-level default value. Allocate the internal data structure as necessary.
  109. void SetInstanceDefault(const String& name, const Variant& defaultValue);
  110. /// Get instance-level default value.
  111. Variant GetInstanceDefault(const String& name) const;
  112. /// Attribute default value at each instance level.
  113. std::unique_ptr<VariantMap> instanceDefaultValues_;
  114. /// When true, store the attribute value as instance's default value (internal use only).
  115. bool setInstanceDefault_;
  116. /// Temporary flag.
  117. bool temporary_;
  118. };
  119. /// Template implementation of the variant attribute accessor.
  120. template <class TClassType, class TGetFunction, class TSetFunction>
  121. class VariantAttributeAccessorImpl : public AttributeAccessor
  122. {
  123. public:
  124. /// Construct.
  125. VariantAttributeAccessorImpl(TGetFunction getFunction, TSetFunction setFunction) : getFunction_(getFunction), setFunction_(setFunction) { }
  126. /// Invoke getter function.
  127. void Get(const Serializable* ptr, Variant& value) const override
  128. {
  129. assert(ptr);
  130. const auto classPtr = static_cast<const TClassType*>(ptr);
  131. getFunction_(*classPtr, value);
  132. }
  133. /// Invoke setter function.
  134. void Set(Serializable* ptr, const Variant& value) override
  135. {
  136. assert(ptr);
  137. auto classPtr = static_cast<TClassType*>(ptr);
  138. setFunction_(*classPtr, value);
  139. }
  140. private:
  141. /// Get functor.
  142. TGetFunction getFunction_;
  143. /// Set functor.
  144. TSetFunction setFunction_;
  145. };
  146. /// Make variant attribute accessor implementation.
  147. /// \tparam TClassType Serializable class type.
  148. /// \tparam TGetFunction Functional object with call signature `void getFunction(const TClassType& self, Variant& value)`
  149. /// \tparam TSetFunction Functional object with call signature `void setFunction(TClassType& self, const Variant& value)`
  150. template <class TClassType, class TGetFunction, class TSetFunction>
  151. SharedPtr<AttributeAccessor> MakeVariantAttributeAccessor(TGetFunction getFunction, TSetFunction setFunction)
  152. {
  153. return SharedPtr<AttributeAccessor>(new VariantAttributeAccessorImpl<TClassType, TGetFunction, TSetFunction>(getFunction, setFunction));
  154. }
  155. /// Make member attribute accessor.
  156. #define URHO3D_MAKE_MEMBER_ATTRIBUTE_ACCESSOR(typeName, variable) Urho3D::MakeVariantAttributeAccessor<ClassName>( \
  157. [](const ClassName& self, Urho3D::Variant& value) { value = self.variable; }, \
  158. [](ClassName& self, const Urho3D::Variant& value) { self.variable = value.Get<typeName>(); })
  159. /// Make member attribute accessor with custom post-set callback.
  160. #define URHO3D_MAKE_MEMBER_ATTRIBUTE_ACCESSOR_EX(typeName, variable, postSetCallback) Urho3D::MakeVariantAttributeAccessor<ClassName>( \
  161. [](const ClassName& self, Urho3D::Variant& value) { value = self.variable; }, \
  162. [](ClassName& self, const Urho3D::Variant& value) { self.variable = value.Get<typeName>(); self.postSetCallback(); })
  163. /// Make get/set attribute accessor.
  164. #define URHO3D_MAKE_GET_SET_ATTRIBUTE_ACCESSOR(getFunction, setFunction, typeName) Urho3D::MakeVariantAttributeAccessor<ClassName>( \
  165. [](const ClassName& self, Urho3D::Variant& value) { value = self.getFunction(); }, \
  166. [](ClassName& self, const Urho3D::Variant& value) { self.setFunction(value.Get<typeName>()); })
  167. /// Make member enum attribute accessor.
  168. #define URHO3D_MAKE_MEMBER_ENUM_ATTRIBUTE_ACCESSOR(variable) Urho3D::MakeVariantAttributeAccessor<ClassName>( \
  169. [](const ClassName& self, Urho3D::Variant& value) { value = static_cast<int>(self.variable); }, \
  170. [](ClassName& self, const Urho3D::Variant& value) { self.variable = static_cast<decltype(self.variable)>(value.Get<int>()); })
  171. /// Make member enum attribute accessor with custom post-set callback.
  172. #define URHO3D_MAKE_MEMBER_ENUM_ATTRIBUTE_ACCESSOR_EX(variable, postSetCallback) Urho3D::MakeVariantAttributeAccessor<ClassName>( \
  173. [](const ClassName& self, Urho3D::Variant& value) { value = static_cast<int>(self.variable); }, \
  174. [](ClassName& self, const Urho3D::Variant& value) { self.variable = static_cast<decltype(self.variable)>(value.Get<int>()); self.postSetCallback(); })
  175. /// Make get/set enum attribute accessor.
  176. #define URHO3D_MAKE_GET_SET_ENUM_ATTRIBUTE_ACCESSOR(getFunction, setFunction, typeName) Urho3D::MakeVariantAttributeAccessor<ClassName>( \
  177. [](const ClassName& self, Urho3D::Variant& value) { value = static_cast<int>(self.getFunction()); }, \
  178. [](ClassName& self, const Urho3D::Variant& value) { self.setFunction(static_cast<typeName>(value.Get<int>())); })
  179. /// Attribute metadata.
  180. namespace AttributeMetadata
  181. {
  182. /// Names of vector struct elements. StringVector.
  183. static const StringHash P_VECTOR_STRUCT_ELEMENTS("VectorStructElements");
  184. }
  185. /// Get result type of a class member function with zero args.
  186. #define URHO3D_GETTER_RETURN_TYPE(getFunction) \
  187. std::remove_cv_t<std::remove_reference_t<std::invoke_result_t<decltype(&ClassName::getFunction), ClassName>>>
  188. // The following macros need to be used within a class member function such as ClassName::RegisterObject().
  189. // A variable called "context" needs to exist in the current scope and point to a valid Context object.
  190. /// Copy attributes from a base class.
  191. #define URHO3D_COPY_BASE_ATTRIBUTES(sourceClassName) context->CopyBaseAttributes<sourceClassName, ClassName>()
  192. /// Update the default value of an already registered attribute.
  193. #define URHO3D_UPDATE_ATTRIBUTE_DEFAULT_VALUE(name, defaultValue) context->UpdateAttributeDefaultValue<ClassName>(name, defaultValue)
  194. /// Remove attribute by name.
  195. #define URHO3D_REMOVE_ATTRIBUTE(name) context->RemoveAttribute<ClassName>(name)
  196. /// Define an object member attribute.
  197. #define URHO3D_ATTRIBUTE(name, variable, defaultValue, mode) context->RegisterAttribute<ClassName>(Urho3D::AttributeInfo( \
  198. Urho3D::GetVariantType<std::remove_reference_t<decltype(variable)>>(), name, URHO3D_MAKE_MEMBER_ATTRIBUTE_ACCESSOR(std::remove_reference_t<decltype(variable)>, variable), nullptr, defaultValue, mode))
  199. /// Define an object member attribute with forced type. Allows use custom type convertible to variant type (e.g. serialize u8 as int).
  200. #define URHO3D_ATTRIBUTE_FORCE_TYPE(name, typeName, variable, defaultValue, mode) context->RegisterAttribute<ClassName>(Urho3D::AttributeInfo( \
  201. Urho3D::GetVariantType<typeName>(), name, URHO3D_MAKE_MEMBER_ATTRIBUTE_ACCESSOR(typeName, variable), nullptr, defaultValue, mode))
  202. /// Define an object member attribute. Post-set member function callback is called when attribute set.
  203. #define URHO3D_ATTRIBUTE_EX(name, variable, postSetCallback, defaultValue, mode) context->RegisterAttribute<ClassName>(Urho3D::AttributeInfo( \
  204. Urho3D::GetVariantType<std::remove_reference_t<decltype(variable)>>(), name, URHO3D_MAKE_MEMBER_ATTRIBUTE_ACCESSOR_EX(std::remove_reference_t<decltype(variable)>, variable, postSetCallback), nullptr, defaultValue, mode))
  205. /// Define an object member attribute with forced type. Allows use custom type convertible to variant type (e.g. serialize u8 as int). Post-set member function callback is called when attribute set.
  206. #define URHO3D_ATTRIBUTE_FORCE_TYPE_EX(name, typeName, variable, postSetCallback, defaultValue, mode) context->RegisterAttribute<ClassName>(Urho3D::AttributeInfo( \
  207. Urho3D::GetVariantType<typeName>(), name, URHO3D_MAKE_MEMBER_ATTRIBUTE_ACCESSOR_EX(typeName, variable, postSetCallback), nullptr, defaultValue, mode))
  208. /// Define an attribute that uses get and set functions.
  209. #define URHO3D_ACCESSOR_ATTRIBUTE(name, getFunction, setFunction, defaultValue, mode) context->RegisterAttribute<ClassName>(Urho3D::AttributeInfo( \
  210. Urho3D::GetVariantType<URHO3D_GETTER_RETURN_TYPE(getFunction)>(), name, URHO3D_MAKE_GET_SET_ATTRIBUTE_ACCESSOR(getFunction, setFunction, URHO3D_GETTER_RETURN_TYPE(getFunction)), nullptr, defaultValue, mode))
  211. /// Define an attribute that uses get and set functions with forced type.
  212. #define URHO3D_ACCESSOR_ATTRIBUTE_FORCE_TYPE(name, getFunction, setFunction, typeName, defaultValue, mode) context->RegisterAttribute<ClassName>(Urho3D::AttributeInfo( \
  213. Urho3D::GetVariantType<typeName>(), name, URHO3D_MAKE_GET_SET_ATTRIBUTE_ACCESSOR(getFunction, setFunction, typeName), nullptr, defaultValue, mode))
  214. /// Define an object member attribute. Zero-based enum values are mapped to names through an array of C string pointers.
  215. #define URHO3D_ENUM_ATTRIBUTE(name, variable, enumNames, defaultValue, mode) context->RegisterAttribute<ClassName>(Urho3D::AttributeInfo( \
  216. Urho3D::VAR_INT, name, URHO3D_MAKE_MEMBER_ENUM_ATTRIBUTE_ACCESSOR(variable), enumNames, static_cast<int>(defaultValue), mode))
  217. /// Define an object member attribute. Zero-based enum values are mapped to names through an array of C string pointers. Post-set member function callback is called when attribute set.
  218. #define URHO3D_ENUM_ATTRIBUTE_EX(name, variable, postSetCallback, enumNames, defaultValue, mode) context->RegisterAttribute<ClassName>(Urho3D::AttributeInfo( \
  219. Urho3D::VAR_INT, name, URHO3D_MAKE_MEMBER_ENUM_ATTRIBUTE_ACCESSOR_EX(variable, postSetCallback), enumNames, static_cast<int>(defaultValue), mode))
  220. /// Define an attribute that uses get and set functions. Zero-based enum values are mapped to names through an array of C string pointers.
  221. #define URHO3D_ENUM_ACCESSOR_ATTRIBUTE(name, getFunction, setFunction, enumNames, defaultValue, mode) context->RegisterAttribute<ClassName>(Urho3D::AttributeInfo( \
  222. Urho3D::VAR_INT, name, URHO3D_MAKE_GET_SET_ENUM_ATTRIBUTE_ACCESSOR(getFunction, setFunction, URHO3D_GETTER_RETURN_TYPE(getFunction)), enumNames, static_cast<int>(defaultValue), mode))
  223. /// Define an attribute that uses get and set functions with forced type. Zero-based enum values are mapped to names through an array of C string pointers.
  224. #define URHO3D_ENUM_ACCESSOR_ATTRIBUTE_FORCE_TYPE(name, getFunction, setFunction, typeName, enumNames, defaultValue, mode) context->RegisterAttribute<ClassName>(Urho3D::AttributeInfo( \
  225. Urho3D::VAR_INT, name, URHO3D_MAKE_GET_SET_ENUM_ATTRIBUTE_ACCESSOR(getFunction, setFunction, typeName), enumNames, static_cast<int>(defaultValue), mode))
  226. /// Define an attribute with custom setter and getter.
  227. #define URHO3D_CUSTOM_ATTRIBUTE(name, getFunction, setFunction, typeName, defaultValue, mode) context->RegisterAttribute<ClassName>(Urho3D::AttributeInfo( \
  228. Urho3D::GetVariantType<typeName>(), name, Urho3D::MakeVariantAttributeAccessor<ClassName>(getFunction, setFunction), nullptr, defaultValue, mode))
  229. /// Define an enum attribute with custom setter and getter. Zero-based enum values are mapped to names through an array of C string pointers.
  230. #define URHO3D_CUSTOM_ENUM_ATTRIBUTE(name, getFunction, setFunction, enumNames, defaultValue, mode) context->RegisterAttribute<ClassName>(Urho3D::AttributeInfo( \
  231. Urho3D::VAR_INT, name, Urho3D::MakeVariantAttributeAccessor<ClassName>(getFunction, setFunction), enumNames, static_cast<int>(defaultValue), mode))
  232. }