Serializable.cpp 31 KB

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