Serializable.cpp 31 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039
  1. //
  2. // Copyright (c) 2008-2020 the Urho3D project.
  3. //
  4. // Permission is hereby granted, free of charge, to any person obtaining a copy
  5. // of this software and associated documentation files (the "Software"), to deal
  6. // in the Software without restriction, including without limitation the rights
  7. // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
  8. // copies of the Software, and to permit persons to whom the Software is
  9. // furnished to do so, subject to the following conditions:
  10. //
  11. // The above copyright notice and this permission notice shall be included in
  12. // all copies or substantial portions of the Software.
  13. //
  14. // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  15. // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  16. // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
  17. // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  18. // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
  19. // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
  20. // THE SOFTWARE.
  21. //
  22. #include "../Precompiled.h"
  23. #include "../Core/Context.h"
  24. #include "../IO/Deserializer.h"
  25. #include "../IO/Log.h"
  26. #include "../IO/Serializer.h"
  27. #include "../Resource/XMLElement.h"
  28. #include "../Resource/JSONValue.h"
  29. #include "../Scene/ReplicationState.h"
  30. #include "../Scene/SceneEvents.h"
  31. #include "../Scene/Serializable.h"
  32. #include "../DebugNew.h"
  33. namespace Urho3D
  34. {
  35. static unsigned RemapAttributeIndex(const Vector<AttributeInfo>* attributes, const AttributeInfo& netAttr, unsigned netAttrIndex)
  36. {
  37. if (!attributes)
  38. return netAttrIndex; // Could not remap
  39. for (unsigned i = 0; i < attributes->Size(); ++i)
  40. {
  41. const AttributeInfo& attr = attributes->At(i);
  42. // Compare accessor to avoid name string compare
  43. if (attr.accessor_.Get() && attr.accessor_.Get() == netAttr.accessor_.Get())
  44. return i;
  45. }
  46. return netAttrIndex; // Could not remap
  47. }
  48. Serializable::Serializable(Context* context) :
  49. Object(context),
  50. setInstanceDefault_(false),
  51. temporary_(false)
  52. {
  53. }
  54. Serializable::~Serializable() = default;
  55. void Serializable::OnSetAttribute(const AttributeInfo& attr, const Variant& src)
  56. {
  57. // TODO: may be could use an observer pattern here
  58. if (setInstanceDefault_)
  59. SetInstanceDefault(attr.name_, src);
  60. // Check for accessor function mode
  61. if (attr.accessor_)
  62. {
  63. attr.accessor_->Set(this, src);
  64. return;
  65. }
  66. // Get the destination address
  67. assert(attr.ptr_);
  68. void* dest = attr.ptr_;
  69. switch (attr.type_)
  70. {
  71. case VAR_INT:
  72. // If enum type, use the low 8 bits only
  73. if (attr.enumNames_)
  74. *(reinterpret_cast<unsigned char*>(dest)) = src.GetInt();
  75. else
  76. *(reinterpret_cast<int*>(dest)) = src.GetInt();
  77. break;
  78. case VAR_INT64:
  79. *(reinterpret_cast<long long*>(dest)) = src.GetInt64();
  80. break;
  81. case VAR_BOOL:
  82. *(reinterpret_cast<bool*>(dest)) = src.GetBool();
  83. break;
  84. case VAR_FLOAT:
  85. *(reinterpret_cast<float*>(dest)) = src.GetFloat();
  86. break;
  87. case VAR_VECTOR2:
  88. *(reinterpret_cast<Vector2*>(dest)) = src.GetVector2();
  89. break;
  90. case VAR_VECTOR3:
  91. *(reinterpret_cast<Vector3*>(dest)) = src.GetVector3();
  92. break;
  93. case VAR_VECTOR4:
  94. *(reinterpret_cast<Vector4*>(dest)) = src.GetVector4();
  95. break;
  96. case VAR_QUATERNION:
  97. *(reinterpret_cast<Quaternion*>(dest)) = src.GetQuaternion();
  98. break;
  99. case VAR_COLOR:
  100. *(reinterpret_cast<Color*>(dest)) = src.GetColor();
  101. break;
  102. case VAR_STRING:
  103. *(reinterpret_cast<String*>(dest)) = src.GetString();
  104. break;
  105. case VAR_BUFFER:
  106. *(reinterpret_cast<PODVector<unsigned char>*>(dest)) = src.GetBuffer();
  107. break;
  108. case VAR_RESOURCEREF:
  109. *(reinterpret_cast<ResourceRef*>(dest)) = src.GetResourceRef();
  110. break;
  111. case VAR_RESOURCEREFLIST:
  112. *(reinterpret_cast<ResourceRefList*>(dest)) = src.GetResourceRefList();
  113. break;
  114. case VAR_VARIANTVECTOR:
  115. *(reinterpret_cast<VariantVector*>(dest)) = src.GetVariantVector();
  116. break;
  117. case VAR_STRINGVECTOR:
  118. *(reinterpret_cast<StringVector*>(dest)) = src.GetStringVector();
  119. break;
  120. case VAR_VARIANTMAP:
  121. *(reinterpret_cast<VariantMap*>(dest)) = src.GetVariantMap();
  122. break;
  123. case VAR_INTRECT:
  124. *(reinterpret_cast<IntRect*>(dest)) = src.GetIntRect();
  125. break;
  126. case VAR_INTVECTOR2:
  127. *(reinterpret_cast<IntVector2*>(dest)) = src.GetIntVector2();
  128. break;
  129. case VAR_INTVECTOR3:
  130. *(reinterpret_cast<IntVector3*>(dest)) = src.GetIntVector3();
  131. break;
  132. case VAR_DOUBLE:
  133. *(reinterpret_cast<double*>(dest)) = src.GetDouble();
  134. break;
  135. default:
  136. URHO3D_LOGERROR("Unsupported attribute type for OnSetAttribute()");
  137. return;
  138. }
  139. // If it is a network attribute then mark it for next network update
  140. if (attr.mode_ & AM_NET)
  141. MarkNetworkUpdate();
  142. }
  143. void Serializable::OnGetAttribute(const AttributeInfo& attr, Variant& dest) const
  144. {
  145. // Check for accessor function mode
  146. if (attr.accessor_)
  147. {
  148. attr.accessor_->Get(this, dest);
  149. return;
  150. }
  151. // Get the source address
  152. assert(attr.ptr_);
  153. const void* src = attr.ptr_;
  154. switch (attr.type_)
  155. {
  156. case VAR_INT:
  157. // If enum type, use the low 8 bits only
  158. if (attr.enumNames_)
  159. dest = *(reinterpret_cast<const unsigned char*>(src));
  160. else
  161. dest = *(reinterpret_cast<const int*>(src));
  162. break;
  163. case VAR_INT64:
  164. dest = *(reinterpret_cast<const long long*>(src));
  165. break;
  166. case VAR_BOOL:
  167. dest = *(reinterpret_cast<const bool*>(src));
  168. break;
  169. case VAR_FLOAT:
  170. dest = *(reinterpret_cast<const float*>(src));
  171. break;
  172. case VAR_VECTOR2:
  173. dest = *(reinterpret_cast<const Vector2*>(src));
  174. break;
  175. case VAR_VECTOR3:
  176. dest = *(reinterpret_cast<const Vector3*>(src));
  177. break;
  178. case VAR_VECTOR4:
  179. dest = *(reinterpret_cast<const Vector4*>(src));
  180. break;
  181. case VAR_QUATERNION:
  182. dest = *(reinterpret_cast<const Quaternion*>(src));
  183. break;
  184. case VAR_COLOR:
  185. dest = *(reinterpret_cast<const Color*>(src));
  186. break;
  187. case VAR_STRING:
  188. dest = *(reinterpret_cast<const String*>(src));
  189. break;
  190. case VAR_BUFFER:
  191. dest = *(reinterpret_cast<const PODVector<unsigned char>*>(src));
  192. break;
  193. case VAR_RESOURCEREF:
  194. dest = *(reinterpret_cast<const ResourceRef*>(src));
  195. break;
  196. case VAR_RESOURCEREFLIST:
  197. dest = *(reinterpret_cast<const ResourceRefList*>(src));
  198. break;
  199. case VAR_VARIANTVECTOR:
  200. dest = *(reinterpret_cast<const VariantVector*>(src));
  201. break;
  202. case VAR_STRINGVECTOR:
  203. dest = *(reinterpret_cast<const StringVector*>(src));
  204. break;
  205. case VAR_VARIANTMAP:
  206. dest = *(reinterpret_cast<const VariantMap*>(src));
  207. break;
  208. case VAR_INTRECT:
  209. dest = *(reinterpret_cast<const IntRect*>(src));
  210. break;
  211. case VAR_INTVECTOR2:
  212. dest = *(reinterpret_cast<const IntVector2*>(src));
  213. break;
  214. case VAR_INTVECTOR3:
  215. dest = *(reinterpret_cast<const IntVector3*>(src));
  216. break;
  217. case VAR_DOUBLE:
  218. dest = *(reinterpret_cast<const double*>(src));
  219. break;
  220. default:
  221. URHO3D_LOGERROR("Unsupported attribute type for OnGetAttribute()");
  222. return;
  223. }
  224. }
  225. const Vector<AttributeInfo>* Serializable::GetAttributes() const
  226. {
  227. return context_->GetAttributes(GetType());
  228. }
  229. const Vector<AttributeInfo>* Serializable::GetNetworkAttributes() const
  230. {
  231. return networkState_ ? networkState_->attributes_ : context_->GetNetworkAttributes(GetType());
  232. }
  233. bool Serializable::Load(Deserializer& source)
  234. {
  235. const Vector<AttributeInfo>* attributes = GetAttributes();
  236. if (!attributes)
  237. return true;
  238. for (unsigned i = 0; i < attributes->Size(); ++i)
  239. {
  240. const AttributeInfo& attr = attributes->At(i);
  241. if (!(attr.mode_ & AM_FILE))
  242. continue;
  243. if (source.IsEof())
  244. {
  245. URHO3D_LOGERROR("Could not load " + GetTypeName() + ", stream not open or at end");
  246. return false;
  247. }
  248. Variant varValue = source.ReadVariant(attr.type_);
  249. OnSetAttribute(attr, varValue);
  250. }
  251. return true;
  252. }
  253. bool Serializable::Save(Serializer& dest) const
  254. {
  255. const Vector<AttributeInfo>* attributes = GetAttributes();
  256. if (!attributes)
  257. return true;
  258. Variant value;
  259. for (unsigned i = 0; i < attributes->Size(); ++i)
  260. {
  261. const AttributeInfo& attr = attributes->At(i);
  262. if (!(attr.mode_ & AM_FILE) || (attr.mode_ & AM_FILEREADONLY) == AM_FILEREADONLY)
  263. continue;
  264. OnGetAttribute(attr, value);
  265. if (!dest.WriteVariantData(value))
  266. {
  267. URHO3D_LOGERROR("Could not save " + GetTypeName() + ", writing to stream failed");
  268. return false;
  269. }
  270. }
  271. return true;
  272. }
  273. bool Serializable::LoadXML(const XMLElement& source)
  274. {
  275. if (source.IsNull())
  276. {
  277. URHO3D_LOGERROR("Could not load " + GetTypeName() + ", null source element");
  278. return false;
  279. }
  280. const Vector<AttributeInfo>* attributes = GetAttributes();
  281. if (!attributes)
  282. return true;
  283. XMLElement attrElem = source.GetChild("attribute");
  284. unsigned startIndex = 0;
  285. while (attrElem)
  286. {
  287. String name = attrElem.GetAttribute("name");
  288. unsigned i = startIndex;
  289. unsigned attempts = attributes->Size();
  290. while (attempts)
  291. {
  292. const AttributeInfo& attr = attributes->At(i);
  293. if ((attr.mode_ & AM_FILE) && !attr.name_.Compare(name, true))
  294. {
  295. Variant varValue;
  296. // If enums specified, do enum lookup and int assignment. Otherwise assign the variant directly
  297. if (attr.enumNames_)
  298. {
  299. String value = attrElem.GetAttribute("value");
  300. bool enumFound = false;
  301. int enumValue = 0;
  302. const char** enumPtr = attr.enumNames_;
  303. while (*enumPtr)
  304. {
  305. if (!value.Compare(*enumPtr, false))
  306. {
  307. enumFound = true;
  308. break;
  309. }
  310. ++enumPtr;
  311. ++enumValue;
  312. }
  313. if (enumFound)
  314. varValue = enumValue;
  315. else
  316. URHO3D_LOGWARNING("Unknown enum value " + value + " in attribute " + attr.name_);
  317. }
  318. else
  319. varValue = attrElem.GetVariantValue(attr.type_);
  320. if (!varValue.IsEmpty())
  321. OnSetAttribute(attr, varValue);
  322. startIndex = (i + 1) % attributes->Size();
  323. break;
  324. }
  325. else
  326. {
  327. i = (i + 1) % attributes->Size();
  328. --attempts;
  329. }
  330. }
  331. if (!attempts)
  332. URHO3D_LOGWARNING("Unknown attribute " + name + " in XML data");
  333. attrElem = attrElem.GetNext("attribute");
  334. }
  335. return true;
  336. }
  337. bool Serializable::LoadJSON(const JSONValue& source)
  338. {
  339. if (source.IsNull())
  340. {
  341. URHO3D_LOGERROR("Could not load " + GetTypeName() + ", null JSON source element");
  342. return false;
  343. }
  344. const Vector<AttributeInfo>* attributes = GetAttributes();
  345. if (!attributes)
  346. return true;
  347. // Get attributes value
  348. JSONValue attributesValue = source.Get("attributes");
  349. if (attributesValue.IsNull())
  350. return true;
  351. // Warn if the attributes value isn't an object
  352. if (!attributesValue.IsObject())
  353. {
  354. URHO3D_LOGWARNING("'attributes' object is present in " + GetTypeName() + " but is not a JSON object; skipping load");
  355. return true;
  356. }
  357. const JSONObject& attributesObject = attributesValue.GetObject();
  358. unsigned startIndex = 0;
  359. for (JSONObject::ConstIterator it = attributesObject.Begin(); it != attributesObject.End();)
  360. {
  361. String name = it->first_;
  362. const JSONValue& value = it->second_;
  363. unsigned i = startIndex;
  364. unsigned attempts = attributes->Size();
  365. while (attempts)
  366. {
  367. const AttributeInfo& attr = attributes->At(i);
  368. if ((attr.mode_ & AM_FILE) && !attr.name_.Compare(name, true))
  369. {
  370. Variant varValue;
  371. // If enums specified, do enum lookup ad int assignment. Otherwise assign variant directly
  372. if (attr.enumNames_)
  373. {
  374. const String& valueStr = value.GetString();
  375. bool enumFound = false;
  376. int enumValue = 0;
  377. const char** enumPtr = attr.enumNames_;
  378. while (*enumPtr)
  379. {
  380. if (!valueStr.Compare(*enumPtr, false))
  381. {
  382. enumFound = true;
  383. break;
  384. }
  385. ++enumPtr;
  386. ++enumValue;
  387. }
  388. if (enumFound)
  389. varValue = enumValue;
  390. else
  391. URHO3D_LOGWARNING("Unknown enum value " + valueStr + " in attribute " + attr.name_);
  392. }
  393. else
  394. varValue = value.GetVariantValue(attr.type_);
  395. if (!varValue.IsEmpty())
  396. OnSetAttribute(attr, varValue);
  397. startIndex = (i + 1) % attributes->Size();
  398. break;
  399. }
  400. else
  401. {
  402. i = (i + 1) % attributes->Size();
  403. --attempts;
  404. }
  405. }
  406. if (!attempts)
  407. URHO3D_LOGWARNING("Unknown attribute " + name + " in JSON data");
  408. it++;
  409. }
  410. return true;
  411. }
  412. bool Serializable::SaveXML(XMLElement& dest) const
  413. {
  414. if (dest.IsNull())
  415. {
  416. URHO3D_LOGERROR("Could not save " + GetTypeName() + ", null destination element");
  417. return false;
  418. }
  419. const Vector<AttributeInfo>* attributes = GetAttributes();
  420. if (!attributes)
  421. return true;
  422. Variant value;
  423. for (unsigned i = 0; i < attributes->Size(); ++i)
  424. {
  425. const AttributeInfo& attr = attributes->At(i);
  426. if (!(attr.mode_ & AM_FILE) || (attr.mode_ & AM_FILEREADONLY) == AM_FILEREADONLY)
  427. continue;
  428. OnGetAttribute(attr, value);
  429. Variant defaultValue(GetAttributeDefault(i));
  430. // In XML serialization default values can be skipped. This will make the file easier to read or edit manually
  431. if (value == defaultValue && !SaveDefaultAttributes())
  432. continue;
  433. XMLElement attrElem = dest.CreateChild("attribute");
  434. attrElem.SetAttribute("name", attr.name_);
  435. // If enums specified, set as an enum string. Otherwise set directly as a Variant
  436. if (attr.enumNames_)
  437. {
  438. int enumValue = value.GetInt();
  439. attrElem.SetAttribute("value", attr.enumNames_[enumValue]);
  440. }
  441. else
  442. attrElem.SetVariantValue(value);
  443. }
  444. return true;
  445. }
  446. bool Serializable::SaveJSON(JSONValue& dest) const
  447. {
  448. const Vector<AttributeInfo>* attributes = GetAttributes();
  449. if (!attributes)
  450. return true;
  451. Variant value;
  452. JSONValue attributesValue;
  453. for (unsigned i = 0; i < attributes->Size(); ++i)
  454. {
  455. const AttributeInfo& attr = attributes->At(i);
  456. if (!(attr.mode_ & AM_FILE) || (attr.mode_ & AM_FILEREADONLY) == AM_FILEREADONLY)
  457. continue;
  458. OnGetAttribute(attr, value);
  459. Variant defaultValue(GetAttributeDefault(i));
  460. // In JSON serialization default values can be skipped. This will make the file easier to read or edit manually
  461. if (value == defaultValue && !SaveDefaultAttributes())
  462. continue;
  463. JSONValue attrVal;
  464. // If enums specified, set as an enum string. Otherwise set directly as a Variant
  465. if (attr.enumNames_)
  466. {
  467. int enumValue = value.GetInt();
  468. attrVal = attr.enumNames_[enumValue];
  469. }
  470. else
  471. attrVal.SetVariantValue(value, context_);
  472. attributesValue.Set(attr.name_, attrVal);
  473. }
  474. dest.Set("attributes", attributesValue);
  475. return true;
  476. }
  477. bool Serializable::SetAttribute(unsigned index, const Variant& value)
  478. {
  479. const Vector<AttributeInfo>* attributes = GetAttributes();
  480. if (!attributes)
  481. {
  482. URHO3D_LOGERROR(GetTypeName() + " has no attributes");
  483. return false;
  484. }
  485. if (index >= attributes->Size())
  486. {
  487. URHO3D_LOGERROR("Attribute index out of bounds");
  488. return false;
  489. }
  490. const AttributeInfo& attr = attributes->At(index);
  491. // Check that the new value's type matches the attribute type
  492. if (value.GetType() == attr.type_)
  493. {
  494. OnSetAttribute(attr, value);
  495. return true;
  496. }
  497. else
  498. {
  499. URHO3D_LOGERROR("Could not set attribute " + attr.name_ + ": expected type " + Variant::GetTypeName(attr.type_) +
  500. " but got " + value.GetTypeName());
  501. return false;
  502. }
  503. }
  504. bool Serializable::SetAttribute(const String& name, const Variant& value)
  505. {
  506. const Vector<AttributeInfo>* attributes = GetAttributes();
  507. if (!attributes)
  508. {
  509. URHO3D_LOGERROR(GetTypeName() + " has no attributes");
  510. return false;
  511. }
  512. for (Vector<AttributeInfo>::ConstIterator i = attributes->Begin(); i != attributes->End(); ++i)
  513. {
  514. if (!i->name_.Compare(name, true))
  515. {
  516. // Check that the new value's type matches the attribute type
  517. if (value.GetType() == i->type_)
  518. {
  519. OnSetAttribute(*i, value);
  520. return true;
  521. }
  522. else
  523. {
  524. URHO3D_LOGERROR("Could not set attribute " + i->name_ + ": expected type " + Variant::GetTypeName(i->type_)
  525. + " but got " + value.GetTypeName());
  526. return false;
  527. }
  528. }
  529. }
  530. URHO3D_LOGERROR("Could not find attribute " + name + " in " + GetTypeName());
  531. return false;
  532. }
  533. void Serializable::ResetToDefault()
  534. {
  535. const Vector<AttributeInfo>* attributes = GetAttributes();
  536. if (!attributes)
  537. return;
  538. for (unsigned i = 0; i < attributes->Size(); ++i)
  539. {
  540. const AttributeInfo& attr = attributes->At(i);
  541. if (attr.mode_ & (AM_NOEDIT | AM_NODEID | AM_COMPONENTID | AM_NODEIDVECTOR))
  542. continue;
  543. Variant defaultValue = GetInstanceDefault(attr.name_);
  544. if (defaultValue.IsEmpty())
  545. defaultValue = attr.defaultValue_;
  546. OnSetAttribute(attr, defaultValue);
  547. }
  548. }
  549. void Serializable::RemoveInstanceDefault()
  550. {
  551. instanceDefaultValues_.Reset();
  552. }
  553. void Serializable::SetTemporary(bool enable)
  554. {
  555. if (enable != temporary_)
  556. {
  557. temporary_ = enable;
  558. using namespace TemporaryChanged;
  559. VariantMap& eventData = GetEventDataMap();
  560. eventData[P_SERIALIZABLE] = this;
  561. SendEvent(E_TEMPORARYCHANGED, eventData);
  562. }
  563. }
  564. void Serializable::SetInterceptNetworkUpdate(const String& attributeName, bool enable)
  565. {
  566. AllocateNetworkState();
  567. const Vector<AttributeInfo>* attributes = networkState_->attributes_;
  568. if (!attributes)
  569. return;
  570. for (unsigned i = 0; i < attributes->Size(); ++i)
  571. {
  572. const AttributeInfo& attr = attributes->At(i);
  573. if (!attr.name_.Compare(attributeName, true))
  574. {
  575. if (enable)
  576. networkState_->interceptMask_ |= 1ULL << i;
  577. else
  578. networkState_->interceptMask_ &= ~(1ULL << i);
  579. break;
  580. }
  581. }
  582. }
  583. void Serializable::AllocateNetworkState()
  584. {
  585. if (networkState_)
  586. return;
  587. const Vector<AttributeInfo>* networkAttributes = GetNetworkAttributes();
  588. networkState_ = new NetworkState();
  589. networkState_->attributes_ = networkAttributes;
  590. if (!networkAttributes)
  591. return;
  592. unsigned numAttributes = networkAttributes->Size();
  593. if (networkState_->currentValues_.Size() != numAttributes)
  594. {
  595. networkState_->currentValues_.Resize(numAttributes);
  596. networkState_->previousValues_.Resize(numAttributes);
  597. // Copy the default attribute values to the previous state as a starting point
  598. for (unsigned i = 0; i < numAttributes; ++i)
  599. networkState_->previousValues_[i] = networkAttributes->At(i).defaultValue_;
  600. }
  601. }
  602. void Serializable::WriteInitialDeltaUpdate(Serializer& dest, unsigned char timeStamp)
  603. {
  604. if (!networkState_)
  605. {
  606. URHO3D_LOGERROR("WriteInitialDeltaUpdate called without allocated NetworkState");
  607. return;
  608. }
  609. const Vector<AttributeInfo>* attributes = networkState_->attributes_;
  610. if (!attributes)
  611. return;
  612. unsigned numAttributes = attributes->Size();
  613. DirtyBits attributeBits;
  614. // Compare against defaults
  615. for (unsigned i = 0; i < numAttributes; ++i)
  616. {
  617. const AttributeInfo& attr = attributes->At(i);
  618. if (networkState_->currentValues_[i] != attr.defaultValue_)
  619. attributeBits.Set(i);
  620. }
  621. // First write the change bitfield, then attribute data for non-default attributes
  622. dest.WriteUByte(timeStamp);
  623. dest.Write(attributeBits.data_, (numAttributes + 7) >> 3u);
  624. for (unsigned i = 0; i < numAttributes; ++i)
  625. {
  626. if (attributeBits.IsSet(i))
  627. dest.WriteVariantData(networkState_->currentValues_[i]);
  628. }
  629. }
  630. void Serializable::WriteDeltaUpdate(Serializer& dest, const DirtyBits& attributeBits, unsigned char timeStamp)
  631. {
  632. if (!networkState_)
  633. {
  634. URHO3D_LOGERROR("WriteDeltaUpdate called without allocated NetworkState");
  635. return;
  636. }
  637. const Vector<AttributeInfo>* attributes = networkState_->attributes_;
  638. if (!attributes)
  639. return;
  640. unsigned numAttributes = attributes->Size();
  641. // First write the change bitfield, then attribute data for changed attributes
  642. // Note: the attribute bits should not contain LATESTDATA attributes
  643. dest.WriteUByte(timeStamp);
  644. dest.Write(attributeBits.data_, (numAttributes + 7) >> 3u);
  645. for (unsigned i = 0; i < numAttributes; ++i)
  646. {
  647. if (attributeBits.IsSet(i))
  648. dest.WriteVariantData(networkState_->currentValues_[i]);
  649. }
  650. }
  651. void Serializable::WriteLatestDataUpdate(Serializer& dest, unsigned char timeStamp)
  652. {
  653. if (!networkState_)
  654. {
  655. URHO3D_LOGERROR("WriteLatestDataUpdate called without allocated NetworkState");
  656. return;
  657. }
  658. const Vector<AttributeInfo>* attributes = networkState_->attributes_;
  659. if (!attributes)
  660. return;
  661. unsigned numAttributes = attributes->Size();
  662. dest.WriteUByte(timeStamp);
  663. for (unsigned i = 0; i < numAttributes; ++i)
  664. {
  665. if (attributes->At(i).mode_ & AM_LATESTDATA)
  666. dest.WriteVariantData(networkState_->currentValues_[i]);
  667. }
  668. }
  669. bool Serializable::ReadDeltaUpdate(Deserializer& source)
  670. {
  671. const Vector<AttributeInfo>* attributes = GetNetworkAttributes();
  672. if (!attributes)
  673. return false;
  674. unsigned numAttributes = attributes->Size();
  675. DirtyBits attributeBits;
  676. bool changed = false;
  677. unsigned long long interceptMask = networkState_ ? networkState_->interceptMask_ : 0;
  678. unsigned char timeStamp = source.ReadUByte();
  679. source.Read(attributeBits.data_, (numAttributes + 7) >> 3u);
  680. for (unsigned i = 0; i < numAttributes && !source.IsEof(); ++i)
  681. {
  682. if (attributeBits.IsSet(i))
  683. {
  684. const AttributeInfo& attr = attributes->At(i);
  685. if (!(interceptMask & (1ULL << i)))
  686. {
  687. OnSetAttribute(attr, source.ReadVariant(attr.type_));
  688. changed = true;
  689. }
  690. else
  691. {
  692. using namespace InterceptNetworkUpdate;
  693. VariantMap& eventData = GetEventDataMap();
  694. eventData[P_SERIALIZABLE] = this;
  695. eventData[P_TIMESTAMP] = (unsigned)timeStamp;
  696. eventData[P_INDEX] = RemapAttributeIndex(GetAttributes(), attr, i);
  697. eventData[P_NAME] = attr.name_;
  698. eventData[P_VALUE] = source.ReadVariant(attr.type_);
  699. SendEvent(E_INTERCEPTNETWORKUPDATE, eventData);
  700. }
  701. }
  702. }
  703. return changed;
  704. }
  705. bool Serializable::ReadLatestDataUpdate(Deserializer& source)
  706. {
  707. const Vector<AttributeInfo>* attributes = GetNetworkAttributes();
  708. if (!attributes)
  709. return false;
  710. unsigned numAttributes = attributes->Size();
  711. bool changed = false;
  712. unsigned long long interceptMask = networkState_ ? networkState_->interceptMask_ : 0;
  713. unsigned char timeStamp = source.ReadUByte();
  714. for (unsigned i = 0; i < numAttributes && !source.IsEof(); ++i)
  715. {
  716. const AttributeInfo& attr = attributes->At(i);
  717. if (attr.mode_ & AM_LATESTDATA)
  718. {
  719. if (!(interceptMask & (1ULL << i)))
  720. {
  721. OnSetAttribute(attr, source.ReadVariant(attr.type_));
  722. changed = true;
  723. }
  724. else
  725. {
  726. using namespace InterceptNetworkUpdate;
  727. VariantMap& eventData = GetEventDataMap();
  728. eventData[P_SERIALIZABLE] = this;
  729. eventData[P_TIMESTAMP] = (unsigned)timeStamp;
  730. eventData[P_INDEX] = RemapAttributeIndex(GetAttributes(), attr, i);
  731. eventData[P_NAME] = attr.name_;
  732. eventData[P_VALUE] = source.ReadVariant(attr.type_);
  733. SendEvent(E_INTERCEPTNETWORKUPDATE, eventData);
  734. }
  735. }
  736. }
  737. return changed;
  738. }
  739. Variant Serializable::GetAttribute(unsigned index) const
  740. {
  741. Variant ret;
  742. const Vector<AttributeInfo>* attributes = GetAttributes();
  743. if (!attributes)
  744. {
  745. URHO3D_LOGERROR(GetTypeName() + " has no attributes");
  746. return ret;
  747. }
  748. if (index >= attributes->Size())
  749. {
  750. URHO3D_LOGERROR("Attribute index out of bounds");
  751. return ret;
  752. }
  753. OnGetAttribute(attributes->At(index), ret);
  754. return ret;
  755. }
  756. Variant Serializable::GetAttribute(const String& name) const
  757. {
  758. Variant ret;
  759. const Vector<AttributeInfo>* attributes = GetAttributes();
  760. if (!attributes)
  761. {
  762. URHO3D_LOGERROR(GetTypeName() + " has no attributes");
  763. return ret;
  764. }
  765. for (Vector<AttributeInfo>::ConstIterator i = attributes->Begin(); i != attributes->End(); ++i)
  766. {
  767. if (!i->name_.Compare(name, true))
  768. {
  769. OnGetAttribute(*i, ret);
  770. return ret;
  771. }
  772. }
  773. URHO3D_LOGERROR("Could not find attribute " + name + " in " + GetTypeName());
  774. return ret;
  775. }
  776. Variant Serializable::GetAttributeDefault(unsigned index) const
  777. {
  778. const Vector<AttributeInfo>* attributes = GetAttributes();
  779. if (!attributes)
  780. {
  781. URHO3D_LOGERROR(GetTypeName() + " has no attributes");
  782. return Variant::EMPTY;
  783. }
  784. if (index >= attributes->Size())
  785. {
  786. URHO3D_LOGERROR("Attribute index out of bounds");
  787. return Variant::EMPTY;
  788. }
  789. AttributeInfo attr = attributes->At(index);
  790. Variant defaultValue = GetInstanceDefault(attr.name_);
  791. return defaultValue.IsEmpty() ? attr.defaultValue_ : defaultValue;
  792. }
  793. Variant Serializable::GetAttributeDefault(const String& name) const
  794. {
  795. Variant defaultValue = GetInstanceDefault(name);
  796. if (!defaultValue.IsEmpty())
  797. return defaultValue;
  798. const Vector<AttributeInfo>* attributes = GetAttributes();
  799. if (!attributes)
  800. {
  801. URHO3D_LOGERROR(GetTypeName() + " has no attributes");
  802. return Variant::EMPTY;
  803. }
  804. for (Vector<AttributeInfo>::ConstIterator i = attributes->Begin(); i != attributes->End(); ++i)
  805. {
  806. if (!i->name_.Compare(name, true))
  807. return i->defaultValue_;
  808. }
  809. URHO3D_LOGERROR("Could not find attribute " + name + " in " + GetTypeName());
  810. return Variant::EMPTY;
  811. }
  812. unsigned Serializable::GetNumAttributes() const
  813. {
  814. const Vector<AttributeInfo>* attributes = GetAttributes();
  815. return attributes ? attributes->Size() : 0;
  816. }
  817. unsigned Serializable::GetNumNetworkAttributes() const
  818. {
  819. const Vector<AttributeInfo>* attributes = networkState_ ? networkState_->attributes_ :
  820. context_->GetNetworkAttributes(GetType());
  821. return attributes ? attributes->Size() : 0;
  822. }
  823. bool Serializable::GetInterceptNetworkUpdate(const String& attributeName) const
  824. {
  825. const Vector<AttributeInfo>* attributes = GetNetworkAttributes();
  826. if (!attributes)
  827. return false;
  828. unsigned long long interceptMask = networkState_ ? networkState_->interceptMask_ : 0;
  829. for (unsigned i = 0; i < attributes->Size(); ++i)
  830. {
  831. const AttributeInfo& attr = attributes->At(i);
  832. if (!attr.name_.Compare(attributeName, true))
  833. return interceptMask & (1ULL << i) ? true : false;
  834. }
  835. return false;
  836. }
  837. void Serializable::SetInstanceDefault(const String& name, const Variant& defaultValue)
  838. {
  839. // Allocate the instance level default value
  840. if (!instanceDefaultValues_)
  841. instanceDefaultValues_ = new VariantMap();
  842. instanceDefaultValues_->operator [](name) = defaultValue;
  843. }
  844. Variant Serializable::GetInstanceDefault(const String& name) const
  845. {
  846. if (instanceDefaultValues_)
  847. {
  848. VariantMap::ConstIterator i = instanceDefaultValues_->Find(name);
  849. if (i != instanceDefaultValues_->End())
  850. return i->second_;
  851. }
  852. return Variant::EMPTY;
  853. }
  854. }