// Copyright (c) 2008-2023 the Urho3D project // License: MIT #pragma once #include "../Container/HashSet.h" #include "../Core/Attribute.h" #include "../Core/Object.h" namespace Urho3D { /// Tracking structure for event receivers. class URHO3D_API EventReceiverGroup : public RefCounted { public: /// Construct. EventReceiverGroup() : inSend_(0), dirty_(false) { } /// Begin event send. When receivers are removed during send, group has to be cleaned up afterward. void BeginSendEvent(); /// End event send. Clean up if necessary. void EndSendEvent(); /// Add receiver. Same receiver must not be double-added! void Add(Object* object); /// Remove receiver. Leave holes during send, which requires later cleanup. void Remove(Object* object); /// Receivers. May contain holes during sending. Vector receivers_; private: /// "In send" recursion counter. unsigned inSend_; /// Cleanup required flag. bool dirty_; }; /// Urho3D execution context. Provides access to subsystems, object factories and attributes, and event receivers. class URHO3D_API Context : public RefCounted { friend class Object; public: /// Construct. Context(); /// Destruct. ~Context() override; /// Create an object by type. Return pointer to it or null if no factory found. template inline SharedPtr CreateObject() { return StaticCast(CreateObject(T::GetTypeStatic())); } /// Create an object by type hash. Return pointer to it or null if no factory found. SharedPtr CreateObject(StringHash objectType); /// Register a factory for an object type. void RegisterFactory(ObjectFactory* factory); /// Register a factory for an object type and specify the object category. void RegisterFactory(ObjectFactory* factory, const char* category); /// Register a subsystem. void RegisterSubsystem(Object* object); /// Remove a subsystem. void RemoveSubsystem(StringHash objectType); /// Register object attribute. AttributeHandle RegisterAttribute(StringHash objectType, const AttributeInfo& attr); /// Remove object attribute. void RemoveAttribute(StringHash objectType, const char* name); /// Remove all object attributes. void RemoveAllAttributes(StringHash objectType); /// Update object attribute's default value. void UpdateAttributeDefaultValue(StringHash objectType, const char* name, const Variant& defaultValue); /// Return a preallocated map for event data. Used for optimization to avoid constant re-allocation of event data maps. VariantMap& GetEventDataMap(); /// Initialises the specified SDL systems, if not already. Returns true if successful. This call must be matched with ReleaseSDL() when SDL functions are no longer required, even if this call fails. bool RequireSDL(unsigned int sdlFlags); /// Indicate that you are done with using SDL. Must be called after using RequireSDL(). void ReleaseSDL(); #ifdef URHO3D_IK /// Initialises the IK library, if not already. This call must be matched with ReleaseIK() when the IK library is no longer required. void RequireIK(); /// Indicate that you are done with using the IK library. void ReleaseIK(); #endif /// Copy base class attributes to derived class. void CopyBaseAttributes(StringHash baseType, StringHash derivedType); /// Template version of registering an object factory. template void RegisterFactory(); /// Template version of registering an object factory with category. template void RegisterFactory(const char* category); /// Template version of registering subsystem. template T* RegisterSubsystem(); /// Template version of removing a subsystem. template void RemoveSubsystem(); /// Template version of registering an object attribute. template AttributeHandle RegisterAttribute(const AttributeInfo& attr); /// Template version of removing an object attribute. template void RemoveAttribute(const char* name); /// Template version of removing all object attributes. template void RemoveAllAttributes(); /// Template version of copying base class attributes to derived class. template void CopyBaseAttributes(); /// Template version of updating an object attribute's default value. template void UpdateAttributeDefaultValue(const char* name, const Variant& defaultValue); /// Return subsystem by type. Object* GetSubsystem(StringHash type) const; /// Return global variable based on key. const Variant& GetGlobalVar(StringHash key) const; /// Return all global variables. const VariantMap& GetGlobalVars() const { return globalVars_; } /// Set global variable with the respective key and value. void SetGlobalVar(StringHash key, const Variant& value); /// Return all subsystems. const HashMap>& GetSubsystems() const { return subsystems_; } /// Return all object factories. const HashMap>& GetObjectFactories() const { return factories_; } /// Return all object categories. const HashMap>& GetObjectCategories() const { return objectCategories_; } /// Return active event sender. Null outside event handling. Object* GetEventSender() const; /// Return active event handler. Set by Object. Null outside event handling. EventHandler* GetEventHandler() const { return eventHandler_; } /// Return object type name from hash, or empty if unknown. const String& GetTypeName(StringHash objectType) const; /// Return a specific attribute description for an object, or null if not found. AttributeInfo* GetAttribute(StringHash objectType, const char* name); /// Template version of returning a subsystem. template T* GetSubsystem() const; /// Template version of returning a specific attribute description. template AttributeInfo* GetAttribute(const char* name); /// Return attribute descriptions for an object type, or null if none defined. const Vector* GetAttributes(StringHash type) const { HashMap>::ConstIterator i = attributes_.Find(type); return i != attributes_.End() ? &i->second_ : nullptr; } /// Return network replication attribute descriptions for an object type, or null if none defined. const Vector* GetNetworkAttributes(StringHash type) const { HashMap>::ConstIterator i = networkAttributes_.Find(type); return i != networkAttributes_.End() ? &i->second_ : nullptr; } /// Return all registered attributes. const HashMap>& GetAllAttributes() const { return attributes_; } /// Return event receivers for a sender and event type, or null if they do not exist. EventReceiverGroup* GetEventReceivers(Object* sender, StringHash eventType) { HashMap>>::Iterator i = specificEventReceivers_.Find(sender); if (i != specificEventReceivers_.End()) { HashMap>::Iterator j = i->second_.Find(eventType); return j != i->second_.End() ? j->second_ : nullptr; } else return nullptr; } /// Return event receivers for an event type, or null if they do not exist. EventReceiverGroup* GetEventReceivers(StringHash eventType) { HashMap>::Iterator i = eventReceivers_.Find(eventType); return i != eventReceivers_.End() ? i->second_ : nullptr; } private: /// Add event receiver. void AddEventReceiver(Object* receiver, StringHash eventType); /// Add event receiver for specific event. void AddEventReceiver(Object* receiver, Object* sender, StringHash eventType); /// Remove an event sender from all receivers. Called on its destruction. void RemoveEventSender(Object* sender); /// Remove event receiver from specific events. void RemoveEventReceiver(Object* receiver, Object* sender, StringHash eventType); /// Remove event receiver from non-specific events. void RemoveEventReceiver(Object* receiver, StringHash eventType); /// Begin event send. void BeginSendEvent(Object* sender, StringHash eventType); /// End event send. Clean up event receivers removed in the meanwhile. void EndSendEvent(); /// Set current event handler. Called by Object. void SetEventHandler(EventHandler* handler) { eventHandler_ = handler; } /// Object factories. HashMap> factories_; /// Subsystems. HashMap> subsystems_; /// Attribute descriptions per object type. HashMap> attributes_; /// Network replication attribute descriptions per object type. HashMap> networkAttributes_; /// Event receivers for non-specific events. HashMap> eventReceivers_; /// Event receivers for specific senders' events. HashMap>> specificEventReceivers_; /// Event sender stack. Vector eventSenders_; /// Event data stack. Vector eventDataMaps_; /// Active event handler. Not stored in a stack for performance reasons; is needed only in esoteric cases. EventHandler* eventHandler_; /// Object categories. HashMap> objectCategories_; /// Variant map for global variables that can persist throughout application execution. VariantMap globalVars_; }; template void Context::RegisterFactory() { RegisterFactory(new ObjectFactoryImpl(this)); } template void Context::RegisterFactory(const char* category) { RegisterFactory(new ObjectFactoryImpl(this), category); } template T* Context::RegisterSubsystem() { T* subsystem = new T(this); RegisterSubsystem(subsystem); return subsystem; } template void Context::RemoveSubsystem() { RemoveSubsystem(T::GetTypeStatic()); } template AttributeHandle Context::RegisterAttribute(const AttributeInfo& attr) { return RegisterAttribute(T::GetTypeStatic(), attr); } template void Context::RemoveAttribute(const char* name) { RemoveAttribute(T::GetTypeStatic(), name); } template void Context::RemoveAllAttributes() { RemoveAllAttributes(T::GetTypeStatic()); } template void Context::CopyBaseAttributes() { CopyBaseAttributes(T::GetTypeStatic(), U::GetTypeStatic()); } template T* Context::GetSubsystem() const { return static_cast(GetSubsystem(T::GetTypeStatic())); } template AttributeInfo* Context::GetAttribute(const char* name) { return GetAttribute(T::GetTypeStatic(), name); } template void Context::UpdateAttributeDefaultValue(const char* name, const Variant& defaultValue) { UpdateAttributeDefaultValue(T::GetTypeStatic(), name, defaultValue); } }