Serializable.cpp 30 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031
  1. //
  2. // Copyright (c) 2008-2015 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 = attributesObject.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. if (dest.IsNull())
  451. {
  452. URHO3D_LOGERROR("Could not save " + GetTypeName() + ", null destination JSON value");
  453. return false;
  454. }
  455. const Vector<AttributeInfo>* attributes = GetAttributes();
  456. if (!attributes)
  457. return true;
  458. Variant value;
  459. JSONValue attributesValue;
  460. for (unsigned i = 0; i < attributes->Size(); ++i)
  461. {
  462. const AttributeInfo& attr = attributes->At(i);
  463. if (!(attr.mode_ & AM_FILE))
  464. continue;
  465. OnGetAttribute(attr, value);
  466. Variant defaultValue(GetAttributeDefault(i));
  467. // In JSON serialization default values can be skipped. This will make the file easier to read or edit manually
  468. if (value == defaultValue && !SaveDefaultAttributes())
  469. continue;
  470. JSONValue attrVal;
  471. // If enums specified, set as an enum string. Otherwise set directly as a Variant
  472. if (attr.enumNames_)
  473. {
  474. int enumValue = value.GetInt();
  475. attrVal = attr.enumNames_[enumValue];
  476. }
  477. else
  478. attrVal.SetVariantValue(value);
  479. attributesValue.Set(attr.name_, attrVal);
  480. }
  481. dest.Set("attributes", attributesValue);
  482. return true;
  483. }
  484. bool Serializable::SetAttribute(unsigned index, const Variant& value)
  485. {
  486. const Vector<AttributeInfo>* attributes = GetAttributes();
  487. if (!attributes)
  488. {
  489. URHO3D_LOGERROR(GetTypeName() + " has no attributes");
  490. return false;
  491. }
  492. if (index >= attributes->Size())
  493. {
  494. URHO3D_LOGERROR("Attribute index out of bounds");
  495. return false;
  496. }
  497. const AttributeInfo& attr = attributes->At(index);
  498. // Check that the new value's type matches the attribute type
  499. if (value.GetType() == attr.type_)
  500. {
  501. OnSetAttribute(attr, value);
  502. return true;
  503. }
  504. else
  505. {
  506. URHO3D_LOGERROR("Could not set attribute " + attr.name_ + ": expected type " + Variant::GetTypeName(attr.type_) +
  507. " but got " + value.GetTypeName());
  508. return false;
  509. }
  510. }
  511. bool Serializable::SetAttribute(const String& name, const Variant& value)
  512. {
  513. const Vector<AttributeInfo>* attributes = GetAttributes();
  514. if (!attributes)
  515. {
  516. URHO3D_LOGERROR(GetTypeName() + " has no attributes");
  517. return false;
  518. }
  519. for (Vector<AttributeInfo>::ConstIterator i = attributes->Begin(); i != attributes->End(); ++i)
  520. {
  521. if (!i->name_.Compare(name, true))
  522. {
  523. // Check that the new value's type matches the attribute type
  524. if (value.GetType() == i->type_)
  525. {
  526. OnSetAttribute(*i, value);
  527. return true;
  528. }
  529. else
  530. {
  531. URHO3D_LOGERROR("Could not set attribute " + i->name_ + ": expected type " + Variant::GetTypeName(i->type_)
  532. + " but got " + value.GetTypeName());
  533. return false;
  534. }
  535. }
  536. }
  537. URHO3D_LOGERROR("Could not find attribute " + name + " in " + GetTypeName());
  538. return false;
  539. }
  540. void Serializable::ResetToDefault()
  541. {
  542. const Vector<AttributeInfo>* attributes = GetAttributes();
  543. if (!attributes)
  544. return;
  545. for (unsigned i = 0; i < attributes->Size(); ++i)
  546. {
  547. const AttributeInfo& attr = attributes->At(i);
  548. if (attr.mode_ & (AM_NOEDIT | AM_NODEID | AM_COMPONENTID | AM_NODEIDVECTOR))
  549. continue;
  550. Variant defaultValue = GetInstanceDefault(attr.name_);
  551. if (defaultValue.IsEmpty())
  552. defaultValue = attr.defaultValue_;
  553. OnSetAttribute(attr, defaultValue);
  554. }
  555. }
  556. void Serializable::RemoveInstanceDefault()
  557. {
  558. delete instanceDefaultValues_;
  559. instanceDefaultValues_ = 0;
  560. }
  561. void Serializable::SetTemporary(bool enable)
  562. {
  563. if (enable != temporary_)
  564. {
  565. temporary_ = enable;
  566. using namespace TemporaryChanged;
  567. VariantMap& eventData = GetEventDataMap();
  568. eventData[P_SERIALIZABLE] = this;
  569. SendEvent(E_TEMPORARYCHANGED, eventData);
  570. }
  571. }
  572. void Serializable::SetInterceptNetworkUpdate(const String& attributeName, bool enable)
  573. {
  574. const Vector<AttributeInfo>* attributes = GetNetworkAttributes();
  575. if (!attributes)
  576. return;
  577. AllocateNetworkState();
  578. for (unsigned i = 0; i < attributes->Size(); ++i)
  579. {
  580. const AttributeInfo& attr = attributes->At(i);
  581. if (!attr.name_.Compare(attributeName, true))
  582. {
  583. if (enable)
  584. networkState_->interceptMask_ |= 1ULL << i;
  585. else
  586. networkState_->interceptMask_ &= ~(1ULL << i);
  587. break;
  588. }
  589. }
  590. }
  591. void Serializable::AllocateNetworkState()
  592. {
  593. if (!networkState_)
  594. {
  595. const Vector<AttributeInfo>* networkAttributes = GetNetworkAttributes();
  596. networkState_ = new NetworkState();
  597. networkState_->attributes_ = networkAttributes;
  598. }
  599. }
  600. void Serializable::WriteInitialDeltaUpdate(Serializer& dest, unsigned char timeStamp)
  601. {
  602. if (!networkState_)
  603. {
  604. URHO3D_LOGERROR("WriteInitialDeltaUpdate called without allocated NetworkState");
  605. return;
  606. }
  607. const Vector<AttributeInfo>* attributes = networkState_->attributes_;
  608. if (!attributes)
  609. return;
  610. unsigned numAttributes = attributes->Size();
  611. DirtyBits attributeBits;
  612. // Compare against defaults
  613. for (unsigned i = 0; i < numAttributes; ++i)
  614. {
  615. const AttributeInfo& attr = attributes->At(i);
  616. if (networkState_->currentValues_[i] != attr.defaultValue_)
  617. attributeBits.Set(i);
  618. }
  619. // First write the change bitfield, then attribute data for non-default attributes
  620. dest.WriteUByte(timeStamp);
  621. dest.Write(attributeBits.data_, (numAttributes + 7) >> 3);
  622. for (unsigned i = 0; i < numAttributes; ++i)
  623. {
  624. if (attributeBits.IsSet(i))
  625. dest.WriteVariantData(networkState_->currentValues_[i]);
  626. }
  627. }
  628. void Serializable::WriteDeltaUpdate(Serializer& dest, const DirtyBits& attributeBits, unsigned char timeStamp)
  629. {
  630. if (!networkState_)
  631. {
  632. URHO3D_LOGERROR("WriteDeltaUpdate called without allocated NetworkState");
  633. return;
  634. }
  635. const Vector<AttributeInfo>* attributes = networkState_->attributes_;
  636. if (!attributes)
  637. return;
  638. unsigned numAttributes = attributes->Size();
  639. // First write the change bitfield, then attribute data for changed attributes
  640. // Note: the attribute bits should not contain LATESTDATA attributes
  641. dest.WriteUByte(timeStamp);
  642. dest.Write(attributeBits.data_, (numAttributes + 7) >> 3);
  643. for (unsigned i = 0; i < numAttributes; ++i)
  644. {
  645. if (attributeBits.IsSet(i))
  646. dest.WriteVariantData(networkState_->currentValues_[i]);
  647. }
  648. }
  649. void Serializable::WriteLatestDataUpdate(Serializer& dest, unsigned char timeStamp)
  650. {
  651. if (!networkState_)
  652. {
  653. URHO3D_LOGERROR("WriteLatestDataUpdate called without allocated NetworkState");
  654. return;
  655. }
  656. const Vector<AttributeInfo>* attributes = networkState_->attributes_;
  657. if (!attributes)
  658. return;
  659. unsigned numAttributes = attributes->Size();
  660. dest.WriteUByte(timeStamp);
  661. for (unsigned i = 0; i < numAttributes; ++i)
  662. {
  663. if (attributes->At(i).mode_ & AM_LATESTDATA)
  664. dest.WriteVariantData(networkState_->currentValues_[i]);
  665. }
  666. }
  667. bool Serializable::ReadDeltaUpdate(Deserializer& source)
  668. {
  669. const Vector<AttributeInfo>* attributes = GetNetworkAttributes();
  670. if (!attributes)
  671. return false;
  672. unsigned numAttributes = attributes->Size();
  673. DirtyBits attributeBits;
  674. bool changed = false;
  675. unsigned long long interceptMask = networkState_ ? networkState_->interceptMask_ : 0;
  676. unsigned char timeStamp = source.ReadUByte();
  677. source.Read(attributeBits.data_, (numAttributes + 7) >> 3);
  678. for (unsigned i = 0; i < numAttributes && !source.IsEof(); ++i)
  679. {
  680. if (attributeBits.IsSet(i))
  681. {
  682. const AttributeInfo& attr = attributes->At(i);
  683. if (!(interceptMask & (1ULL << i)))
  684. {
  685. OnSetAttribute(attr, source.ReadVariant(attr.type_));
  686. changed = true;
  687. }
  688. else
  689. {
  690. using namespace InterceptNetworkUpdate;
  691. VariantMap& eventData = GetEventDataMap();
  692. eventData[P_SERIALIZABLE] = this;
  693. eventData[P_TIMESTAMP] = (unsigned)timeStamp;
  694. eventData[P_INDEX] = RemapAttributeIndex(GetAttributes(), attr, i);
  695. eventData[P_NAME] = attr.name_;
  696. eventData[P_VALUE] = source.ReadVariant(attr.type_);
  697. SendEvent(E_INTERCEPTNETWORKUPDATE, eventData);
  698. }
  699. }
  700. }
  701. return changed;
  702. }
  703. bool Serializable::ReadLatestDataUpdate(Deserializer& source)
  704. {
  705. const Vector<AttributeInfo>* attributes = GetNetworkAttributes();
  706. if (!attributes)
  707. return false;
  708. unsigned numAttributes = attributes->Size();
  709. bool changed = false;
  710. unsigned long long interceptMask = networkState_ ? networkState_->interceptMask_ : 0;
  711. unsigned char timeStamp = source.ReadUByte();
  712. for (unsigned i = 0; i < numAttributes && !source.IsEof(); ++i)
  713. {
  714. const AttributeInfo& attr = attributes->At(i);
  715. if (attr.mode_ & AM_LATESTDATA)
  716. {
  717. if (!(interceptMask & (1ULL << i)))
  718. {
  719. OnSetAttribute(attr, source.ReadVariant(attr.type_));
  720. changed = true;
  721. }
  722. else
  723. {
  724. using namespace InterceptNetworkUpdate;
  725. VariantMap& eventData = GetEventDataMap();
  726. eventData[P_SERIALIZABLE] = this;
  727. eventData[P_TIMESTAMP] = (unsigned)timeStamp;
  728. eventData[P_INDEX] = RemapAttributeIndex(GetAttributes(), attr, i);
  729. eventData[P_NAME] = attr.name_;
  730. eventData[P_VALUE] = source.ReadVariant(attr.type_);
  731. SendEvent(E_INTERCEPTNETWORKUPDATE, eventData);
  732. }
  733. }
  734. }
  735. return changed;
  736. }
  737. Variant Serializable::GetAttribute(unsigned index) const
  738. {
  739. Variant ret;
  740. const Vector<AttributeInfo>* attributes = GetAttributes();
  741. if (!attributes)
  742. {
  743. URHO3D_LOGERROR(GetTypeName() + " has no attributes");
  744. return ret;
  745. }
  746. if (index >= attributes->Size())
  747. {
  748. URHO3D_LOGERROR("Attribute index out of bounds");
  749. return ret;
  750. }
  751. OnGetAttribute(attributes->At(index), ret);
  752. return ret;
  753. }
  754. Variant Serializable::GetAttribute(const String& name) const
  755. {
  756. Variant ret;
  757. const Vector<AttributeInfo>* attributes = GetAttributes();
  758. if (!attributes)
  759. {
  760. URHO3D_LOGERROR(GetTypeName() + " has no attributes");
  761. return ret;
  762. }
  763. for (Vector<AttributeInfo>::ConstIterator i = attributes->Begin(); i != attributes->End(); ++i)
  764. {
  765. if (!i->name_.Compare(name, true))
  766. {
  767. OnGetAttribute(*i, ret);
  768. return ret;
  769. }
  770. }
  771. URHO3D_LOGERROR("Could not find attribute " + name + " in " + GetTypeName());
  772. return ret;
  773. }
  774. Variant Serializable::GetAttributeDefault(unsigned index) const
  775. {
  776. const Vector<AttributeInfo>* attributes = GetAttributes();
  777. if (!attributes)
  778. {
  779. URHO3D_LOGERROR(GetTypeName() + " has no attributes");
  780. return Variant::EMPTY;
  781. }
  782. if (index >= attributes->Size())
  783. {
  784. URHO3D_LOGERROR("Attribute index out of bounds");
  785. return Variant::EMPTY;
  786. }
  787. AttributeInfo attr = attributes->At(index);
  788. Variant defaultValue = GetInstanceDefault(attr.name_);
  789. return defaultValue.IsEmpty() ? attr.defaultValue_ : defaultValue;
  790. }
  791. Variant Serializable::GetAttributeDefault(const String& name) const
  792. {
  793. Variant defaultValue = GetInstanceDefault(name);
  794. if (!defaultValue.IsEmpty())
  795. return defaultValue;
  796. const Vector<AttributeInfo>* attributes = GetAttributes();
  797. if (!attributes)
  798. {
  799. URHO3D_LOGERROR(GetTypeName() + " has no attributes");
  800. return Variant::EMPTY;
  801. }
  802. for (Vector<AttributeInfo>::ConstIterator i = attributes->Begin(); i != attributes->End(); ++i)
  803. {
  804. if (!i->name_.Compare(name, true))
  805. return i->defaultValue_;
  806. }
  807. URHO3D_LOGERROR("Could not find attribute " + name + " in " + GetTypeName());
  808. return Variant::EMPTY;
  809. }
  810. unsigned Serializable::GetNumAttributes() const
  811. {
  812. const Vector<AttributeInfo>* attributes = GetAttributes();
  813. return attributes ? attributes->Size() : 0;
  814. }
  815. unsigned Serializable::GetNumNetworkAttributes() const
  816. {
  817. const Vector<AttributeInfo>* attributes = networkState_ ? networkState_->attributes_ :
  818. context_->GetNetworkAttributes(GetType());
  819. return attributes ? attributes->Size() : 0;
  820. }
  821. bool Serializable::GetInterceptNetworkUpdate(const String& attributeName) const
  822. {
  823. const Vector<AttributeInfo>* attributes = GetNetworkAttributes();
  824. if (!attributes)
  825. return false;
  826. unsigned long long interceptMask = networkState_ ? networkState_->interceptMask_ : 0;
  827. for (unsigned i = 0; i < attributes->Size(); ++i)
  828. {
  829. const AttributeInfo& attr = attributes->At(i);
  830. if (!attr.name_.Compare(attributeName, true))
  831. return interceptMask & (1ULL << i) ? true : false;
  832. }
  833. return false;
  834. }
  835. void Serializable::SetInstanceDefault(const String& name, const Variant& defaultValue)
  836. {
  837. // Allocate the instance level default value
  838. if (!instanceDefaultValues_)
  839. instanceDefaultValues_ = new VariantMap();
  840. instanceDefaultValues_->operator [](name) = defaultValue;
  841. }
  842. Variant Serializable::GetInstanceDefault(const String& name) const
  843. {
  844. if (instanceDefaultValues_)
  845. {
  846. VariantMap::ConstIterator i = instanceDefaultValues_->Find(name);
  847. if (i != instanceDefaultValues_->End())
  848. return i->second_;
  849. }
  850. return Variant::EMPTY;
  851. }
  852. }