Object.cpp 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552
  1. //
  2. // Copyright (c) 2008-2017 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 "../Core/Thread.h"
  25. #include "../IO/Log.h"
  26. #include "../DebugNew.h"
  27. namespace Urho3D
  28. {
  29. TypeInfo::TypeInfo(const char* typeName, const TypeInfo* baseTypeInfo) :
  30. type_(typeName),
  31. typeName_(typeName),
  32. baseTypeInfo_(baseTypeInfo)
  33. {
  34. }
  35. TypeInfo::~TypeInfo() = default;
  36. bool TypeInfo::IsTypeOf(StringHash type) const
  37. {
  38. const TypeInfo* current = this;
  39. while (current)
  40. {
  41. if (current->GetType() == type)
  42. return true;
  43. current = current->GetBaseTypeInfo();
  44. }
  45. return false;
  46. }
  47. bool TypeInfo::IsTypeOf(const TypeInfo* typeInfo) const
  48. {
  49. const TypeInfo* current = this;
  50. while (current)
  51. {
  52. if (current == typeInfo)
  53. return true;
  54. current = current->GetBaseTypeInfo();
  55. }
  56. return false;
  57. }
  58. Object::Object(Context* context) :
  59. context_(context),
  60. blockEvents_(false)
  61. {
  62. assert(context_);
  63. }
  64. Object::~Object()
  65. {
  66. UnsubscribeFromAllEvents();
  67. context_->RemoveEventSender(this);
  68. }
  69. void Object::OnEvent(Object* sender, StringHash eventType, VariantMap& eventData)
  70. {
  71. if (blockEvents_)
  72. return;
  73. // Make a copy of the context pointer in case the object is destroyed during event handler invocation
  74. Context* context = context_;
  75. EventHandler* specific = nullptr;
  76. EventHandler* nonSpecific = nullptr;
  77. EventHandler* handler = eventHandlers_.First();
  78. while (handler)
  79. {
  80. if (handler->GetEventType() == eventType)
  81. {
  82. if (!handler->GetSender())
  83. nonSpecific = handler;
  84. else if (handler->GetSender() == sender)
  85. {
  86. specific = handler;
  87. break;
  88. }
  89. }
  90. handler = eventHandlers_.Next(handler);
  91. }
  92. // Specific event handlers have priority, so if found, invoke first
  93. if (specific)
  94. {
  95. context->SetEventHandler(specific);
  96. specific->Invoke(eventData);
  97. context->SetEventHandler(nullptr);
  98. return;
  99. }
  100. if (nonSpecific)
  101. {
  102. context->SetEventHandler(nonSpecific);
  103. nonSpecific->Invoke(eventData);
  104. context->SetEventHandler(nullptr);
  105. }
  106. }
  107. bool Object::IsInstanceOf(StringHash type) const
  108. {
  109. return GetTypeInfo()->IsTypeOf(type);
  110. }
  111. bool Object::IsInstanceOf(const TypeInfo* typeInfo) const
  112. {
  113. return GetTypeInfo()->IsTypeOf(typeInfo);
  114. }
  115. void Object::SubscribeToEvent(StringHash eventType, EventHandler* handler)
  116. {
  117. if (!handler)
  118. return;
  119. handler->SetSenderAndEventType(nullptr, eventType);
  120. // Remove old event handler first
  121. EventHandler* previous;
  122. EventHandler* oldHandler = FindSpecificEventHandler(nullptr, eventType, &previous);
  123. if (oldHandler)
  124. {
  125. eventHandlers_.Erase(oldHandler, previous);
  126. eventHandlers_.InsertFront(handler);
  127. }
  128. else
  129. {
  130. eventHandlers_.InsertFront(handler);
  131. context_->AddEventReceiver(this, eventType);
  132. }
  133. }
  134. void Object::SubscribeToEvent(Object* sender, StringHash eventType, EventHandler* handler)
  135. {
  136. // If a null sender was specified, the event can not be subscribed to. Delete the handler in that case
  137. if (!sender || !handler)
  138. {
  139. delete handler;
  140. return;
  141. }
  142. handler->SetSenderAndEventType(sender, eventType);
  143. // Remove old event handler first
  144. EventHandler* previous;
  145. EventHandler* oldHandler = FindSpecificEventHandler(sender, eventType, &previous);
  146. if (oldHandler)
  147. {
  148. eventHandlers_.Erase(oldHandler, previous);
  149. eventHandlers_.InsertFront(handler);
  150. }
  151. else
  152. {
  153. eventHandlers_.InsertFront(handler);
  154. context_->AddEventReceiver(this, sender, eventType);
  155. }
  156. }
  157. void Object::SubscribeToEvent(StringHash eventType, const std::function<void(StringHash, VariantMap&)>& function, void* userData/*=0*/)
  158. {
  159. SubscribeToEvent(eventType, new EventHandler11Impl(function, userData));
  160. }
  161. void Object::SubscribeToEvent(Object* sender, StringHash eventType, const std::function<void(StringHash, VariantMap&)>& function, void* userData/*=0*/)
  162. {
  163. SubscribeToEvent(sender, eventType, new EventHandler11Impl(function, userData));
  164. }
  165. void Object::UnsubscribeFromEvent(StringHash eventType)
  166. {
  167. for (;;)
  168. {
  169. EventHandler* previous;
  170. EventHandler* handler = FindEventHandler(eventType, &previous);
  171. if (handler)
  172. {
  173. if (handler->GetSender())
  174. context_->RemoveEventReceiver(this, handler->GetSender(), eventType);
  175. else
  176. context_->RemoveEventReceiver(this, eventType);
  177. eventHandlers_.Erase(handler, previous);
  178. }
  179. else
  180. break;
  181. }
  182. }
  183. void Object::UnsubscribeFromEvent(Object* sender, StringHash eventType)
  184. {
  185. if (!sender)
  186. return;
  187. EventHandler* previous;
  188. EventHandler* handler = FindSpecificEventHandler(sender, eventType, &previous);
  189. if (handler)
  190. {
  191. context_->RemoveEventReceiver(this, handler->GetSender(), eventType);
  192. eventHandlers_.Erase(handler, previous);
  193. }
  194. }
  195. void Object::UnsubscribeFromEvents(Object* sender)
  196. {
  197. if (!sender)
  198. return;
  199. for (;;)
  200. {
  201. EventHandler* previous;
  202. EventHandler* handler = FindSpecificEventHandler(sender, &previous);
  203. if (handler)
  204. {
  205. context_->RemoveEventReceiver(this, handler->GetSender(), handler->GetEventType());
  206. eventHandlers_.Erase(handler, previous);
  207. }
  208. else
  209. break;
  210. }
  211. }
  212. void Object::UnsubscribeFromAllEvents()
  213. {
  214. for (;;)
  215. {
  216. EventHandler* handler = eventHandlers_.First();
  217. if (handler)
  218. {
  219. if (handler->GetSender())
  220. context_->RemoveEventReceiver(this, handler->GetSender(), handler->GetEventType());
  221. else
  222. context_->RemoveEventReceiver(this, handler->GetEventType());
  223. eventHandlers_.Erase(handler);
  224. }
  225. else
  226. break;
  227. }
  228. }
  229. void Object::UnsubscribeFromAllEventsExcept(const PODVector<StringHash>& exceptions, bool onlyUserData)
  230. {
  231. EventHandler* handler = eventHandlers_.First();
  232. EventHandler* previous = nullptr;
  233. while (handler)
  234. {
  235. EventHandler* next = eventHandlers_.Next(handler);
  236. if ((!onlyUserData || handler->GetUserData()) && !exceptions.Contains(handler->GetEventType()))
  237. {
  238. if (handler->GetSender())
  239. context_->RemoveEventReceiver(this, handler->GetSender(), handler->GetEventType());
  240. else
  241. context_->RemoveEventReceiver(this, handler->GetEventType());
  242. eventHandlers_.Erase(handler, previous);
  243. }
  244. else
  245. previous = handler;
  246. handler = next;
  247. }
  248. }
  249. void Object::SendEvent(StringHash eventType)
  250. {
  251. VariantMap noEventData;
  252. SendEvent(eventType, noEventData);
  253. }
  254. void Object::SendEvent(StringHash eventType, VariantMap& eventData)
  255. {
  256. if (!Thread::IsMainThread())
  257. {
  258. URHO3D_LOGERROR("Sending events is only supported from the main thread");
  259. return;
  260. }
  261. if (blockEvents_)
  262. return;
  263. // Make a weak pointer to self to check for destruction during event handling
  264. WeakPtr<Object> self(this);
  265. Context* context = context_;
  266. HashSet<Object*> processed;
  267. context->BeginSendEvent(this, eventType);
  268. // Check first the specific event receivers
  269. // Note: group is held alive with a shared ptr, as it may get destroyed along with the sender
  270. SharedPtr<EventReceiverGroup> group(context->GetEventReceivers(this, eventType));
  271. if (group)
  272. {
  273. group->BeginSendEvent();
  274. const unsigned numReceivers = group->receivers_.Size();
  275. for (unsigned i = 0; i < numReceivers; ++i)
  276. {
  277. Object* receiver = group->receivers_[i];
  278. // Holes may exist if receivers removed during send
  279. if (!receiver)
  280. continue;
  281. receiver->OnEvent(this, eventType, eventData);
  282. // If self has been destroyed as a result of event handling, exit
  283. if (self.Expired())
  284. {
  285. group->EndSendEvent();
  286. context->EndSendEvent();
  287. return;
  288. }
  289. processed.Insert(receiver);
  290. }
  291. group->EndSendEvent();
  292. }
  293. // Then the non-specific receivers
  294. group = context->GetEventReceivers(eventType);
  295. if (group)
  296. {
  297. group->BeginSendEvent();
  298. if (processed.Empty())
  299. {
  300. const unsigned numReceivers = group->receivers_.Size();
  301. for (unsigned i = 0; i < numReceivers; ++i)
  302. {
  303. Object* receiver = group->receivers_[i];
  304. if (!receiver)
  305. continue;
  306. receiver->OnEvent(this, eventType, eventData);
  307. if (self.Expired())
  308. {
  309. group->EndSendEvent();
  310. context->EndSendEvent();
  311. return;
  312. }
  313. }
  314. }
  315. else
  316. {
  317. // If there were specific receivers, check that the event is not sent doubly to them
  318. const unsigned numReceivers = group->receivers_.Size();
  319. for (unsigned i = 0; i < numReceivers; ++i)
  320. {
  321. Object* receiver = group->receivers_[i];
  322. if (!receiver || processed.Contains(receiver))
  323. continue;
  324. receiver->OnEvent(this, eventType, eventData);
  325. if (self.Expired())
  326. {
  327. group->EndSendEvent();
  328. context->EndSendEvent();
  329. return;
  330. }
  331. }
  332. }
  333. group->EndSendEvent();
  334. }
  335. context->EndSendEvent();
  336. }
  337. VariantMap& Object::GetEventDataMap() const
  338. {
  339. return context_->GetEventDataMap();
  340. }
  341. const Variant& Object::GetGlobalVar(StringHash key) const
  342. {
  343. return context_->GetGlobalVar(key);
  344. }
  345. const VariantMap& Object::GetGlobalVars() const
  346. {
  347. return context_->GetGlobalVars();
  348. }
  349. void Object::SetGlobalVar(StringHash key, const Variant& value)
  350. {
  351. context_->SetGlobalVar(key, value);
  352. }
  353. Object* Object::GetSubsystem(StringHash type) const
  354. {
  355. return context_->GetSubsystem(type);
  356. }
  357. Object* Object::GetEventSender() const
  358. {
  359. return context_->GetEventSender();
  360. }
  361. EventHandler* Object::GetEventHandler() const
  362. {
  363. return context_->GetEventHandler();
  364. }
  365. bool Object::HasSubscribedToEvent(StringHash eventType) const
  366. {
  367. return FindEventHandler(eventType) != nullptr;
  368. }
  369. bool Object::HasSubscribedToEvent(Object* sender, StringHash eventType) const
  370. {
  371. if (!sender)
  372. return false;
  373. else
  374. return FindSpecificEventHandler(sender, eventType) != nullptr;
  375. }
  376. const String& Object::GetCategory() const
  377. {
  378. const HashMap<String, Vector<StringHash> >& objectCategories = context_->GetObjectCategories();
  379. for (HashMap<String, Vector<StringHash> >::ConstIterator i = objectCategories.Begin(); i != objectCategories.End(); ++i)
  380. {
  381. if (i->second_.Contains(GetType()))
  382. return i->first_;
  383. }
  384. return String::EMPTY;
  385. }
  386. EventHandler* Object::FindEventHandler(StringHash eventType, EventHandler** previous) const
  387. {
  388. EventHandler* handler = eventHandlers_.First();
  389. if (previous)
  390. *previous = nullptr;
  391. while (handler)
  392. {
  393. if (handler->GetEventType() == eventType)
  394. return handler;
  395. if (previous)
  396. *previous = handler;
  397. handler = eventHandlers_.Next(handler);
  398. }
  399. return nullptr;
  400. }
  401. EventHandler* Object::FindSpecificEventHandler(Object* sender, EventHandler** previous) const
  402. {
  403. EventHandler* handler = eventHandlers_.First();
  404. if (previous)
  405. *previous = nullptr;
  406. while (handler)
  407. {
  408. if (handler->GetSender() == sender)
  409. return handler;
  410. if (previous)
  411. *previous = handler;
  412. handler = eventHandlers_.Next(handler);
  413. }
  414. return nullptr;
  415. }
  416. EventHandler* Object::FindSpecificEventHandler(Object* sender, StringHash eventType, EventHandler** previous) const
  417. {
  418. EventHandler* handler = eventHandlers_.First();
  419. if (previous)
  420. *previous = nullptr;
  421. while (handler)
  422. {
  423. if (handler->GetSender() == sender && handler->GetEventType() == eventType)
  424. return handler;
  425. if (previous)
  426. *previous = handler;
  427. handler = eventHandlers_.Next(handler);
  428. }
  429. return nullptr;
  430. }
  431. void Object::RemoveEventSender(Object* sender)
  432. {
  433. EventHandler* handler = eventHandlers_.First();
  434. EventHandler* previous = nullptr;
  435. while (handler)
  436. {
  437. if (handler->GetSender() == sender)
  438. {
  439. EventHandler* next = eventHandlers_.Next(handler);
  440. eventHandlers_.Erase(handler, previous);
  441. handler = next;
  442. }
  443. else
  444. {
  445. previous = handler;
  446. handler = eventHandlers_.Next(handler);
  447. }
  448. }
  449. }
  450. Urho3D::StringHash EventNameRegistrar::RegisterEventName(const char* eventName)
  451. {
  452. StringHash id(eventName);
  453. GetEventNameMap()[id] = eventName;
  454. return id;
  455. }
  456. const String& EventNameRegistrar::GetEventName(StringHash eventID)
  457. {
  458. HashMap<StringHash, String>::ConstIterator it = GetEventNameMap().Find(eventID);
  459. return it != GetEventNameMap().End() ? it->second_ : String::EMPTY ;
  460. }
  461. HashMap<StringHash, String>& EventNameRegistrar::GetEventNameMap()
  462. {
  463. static HashMap<StringHash, String> eventNames_;
  464. return eventNames_;
  465. }
  466. }