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 
23 #pragma once
24 
25 #include "../Container/HashSet.h"
26 #include "../Core/Attribute.h"
27 #include "../Core/Object.h"
28 
29 namespace Urho3D
30 {
31 
32 /// Tracking structure for event receivers.
33 class URHO3D_API EventReceiverGroup : public RefCounted
34 {
35 public:
36     /// Construct.
EventReceiverGroup()37     EventReceiverGroup() :
38         inSend_(0),
39         dirty_(false)
40     {
41     }
42 
43     /// Begin event send. When receivers are removed during send, group has to be cleaned up afterward.
44     void BeginSendEvent();
45 
46     /// End event send. Clean up if necessary.
47     void EndSendEvent();
48 
49     /// Add receiver. Same receiver must not be double-added!
50     void Add(Object* object);
51 
52     /// Remove receiver. Leave holes during send, which requires later cleanup.
53     void Remove(Object* object);
54 
55     /// Receivers. May contain holes during sending.
56     PODVector<Object*> receivers_;
57 
58 private:
59     /// "In send" recursion counter.
60     unsigned inSend_;
61     /// Cleanup required flag.
62     bool dirty_;
63 };
64 
65 /// Urho3D execution context. Provides access to subsystems, object factories and attributes, and event receivers.
66 class URHO3D_API Context : public RefCounted
67 {
68     friend class Object;
69 
70 public:
71     /// Construct.
72     Context();
73     /// Destruct.
74     ~Context();
75 
76     /// Create an object by type. Return pointer to it or null if no factory found.
CreateObject()77     template <class T> inline SharedPtr<T> CreateObject()
78     {
79         return StaticCast<T>(CreateObject(T::GetTypeStatic()));
80     }
81     /// Create an object by type hash. Return pointer to it or null if no factory found.
82     SharedPtr<Object> CreateObject(StringHash objectType);
83     /// Register a factory for an object type.
84     void RegisterFactory(ObjectFactory* factory);
85     /// Register a factory for an object type and specify the object category.
86     void RegisterFactory(ObjectFactory* factory, const char* category);
87     /// Register a subsystem.
88     void RegisterSubsystem(Object* subsystem);
89     /// Remove a subsystem.
90     void RemoveSubsystem(StringHash objectType);
91     /// Register object attribute.
92     void RegisterAttribute(StringHash objectType, const AttributeInfo& attr);
93     /// Remove object attribute.
94     void RemoveAttribute(StringHash objectType, const char* name);
95     /// Update object attribute's default value.
96     void UpdateAttributeDefaultValue(StringHash objectType, const char* name, const Variant& defaultValue);
97     /// Return a preallocated map for event data. Used for optimization to avoid constant re-allocation of event data maps.
98     VariantMap& GetEventDataMap();
99     /// 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.
100     bool RequireSDL(unsigned int sdlFlags);
101     /// Indicate that you are done with using SDL. Must be called after using RequireSDL().
102     void ReleaseSDL();
103 #ifdef URHO3D_IK
104     /// Initialises the IK library, if not already. This call must be matched with ReleaseIK() when the IK library is no longer required.
105     void RequireIK();
106     /// Indicate that you are done with using the IK library.
107     void ReleaseIK();
108 #endif
109 
110     /// Copy base class attributes to derived class.
111     void CopyBaseAttributes(StringHash baseType, StringHash derivedType);
112     /// Template version of registering an object factory.
113     template <class T> void RegisterFactory();
114     /// Template version of registering an object factory with category.
115     template <class T> void RegisterFactory(const char* category);
116     /// Template version of removing a subsystem.
117     template <class T> void RemoveSubsystem();
118     /// Template version of registering an object attribute.
119     template <class T> void RegisterAttribute(const AttributeInfo& attr);
120     /// Template version of removing an object attribute.
121     template <class T> void RemoveAttribute(const char* name);
122     /// Template version of copying base class attributes to derived class.
123     template <class T, class U> void CopyBaseAttributes();
124     /// Template version of updating an object attribute's default value.
125     template <class T> void UpdateAttributeDefaultValue(const char* name, const Variant& defaultValue);
126 
127     /// Return subsystem by type.
128     Object* GetSubsystem(StringHash type) const;
129 
130     /// Return global variable based on key
131     const Variant& GetGlobalVar(StringHash key) const ;
132 
133     /// Return all global variables.
GetGlobalVars()134     const VariantMap& GetGlobalVars() const { return globalVars_; }
135 
136     /// Set global variable with the respective key and value
137     void SetGlobalVar(StringHash key, const Variant& value);
138 
139     /// Return all subsystems.
GetSubsystems()140     const HashMap<StringHash, SharedPtr<Object> >& GetSubsystems() const { return subsystems_; }
141 
142     /// Return all object factories.
GetObjectFactories()143     const HashMap<StringHash, SharedPtr<ObjectFactory> >& GetObjectFactories() const { return factories_; }
144 
145     /// Return all object categories.
GetObjectCategories()146     const HashMap<String, Vector<StringHash> >& GetObjectCategories() const { return objectCategories_; }
147 
148     /// Return active event sender. Null outside event handling.
149     Object* GetEventSender() const;
150 
151     /// Return active event handler. Set by Object. Null outside event handling.
GetEventHandler()152     EventHandler* GetEventHandler() const { return eventHandler_; }
153 
154     /// Return object type name from hash, or empty if unknown.
155     const String& GetTypeName(StringHash objectType) const;
156     /// Return a specific attribute description for an object, or null if not found.
157     AttributeInfo* GetAttribute(StringHash objectType, const char* name);
158     /// Template version of returning a subsystem.
159     template <class T> T* GetSubsystem() const;
160     /// Template version of returning a specific attribute description.
161     template <class T> AttributeInfo* GetAttribute(const char* name);
162 
163     /// Return attribute descriptions for an object type, or null if none defined.
GetAttributes(StringHash type)164     const Vector<AttributeInfo>* GetAttributes(StringHash type) const
165     {
166         HashMap<StringHash, Vector<AttributeInfo> >::ConstIterator i = attributes_.Find(type);
167         return i != attributes_.End() ? &i->second_ : 0;
168     }
169 
170     /// Return network replication attribute descriptions for an object type, or null if none defined.
GetNetworkAttributes(StringHash type)171     const Vector<AttributeInfo>* GetNetworkAttributes(StringHash type) const
172     {
173         HashMap<StringHash, Vector<AttributeInfo> >::ConstIterator i = networkAttributes_.Find(type);
174         return i != networkAttributes_.End() ? &i->second_ : 0;
175     }
176 
177     /// Return all registered attributes.
GetAllAttributes()178     const HashMap<StringHash, Vector<AttributeInfo> >& GetAllAttributes() const { return attributes_; }
179 
180     /// Return event receivers for a sender and event type, or null if they do not exist.
GetEventReceivers(Object * sender,StringHash eventType)181     EventReceiverGroup* GetEventReceivers(Object* sender, StringHash eventType)
182     {
183         HashMap<Object*, HashMap<StringHash, SharedPtr<EventReceiverGroup> > >::Iterator i = specificEventReceivers_.Find(sender);
184         if (i != specificEventReceivers_.End())
185         {
186             HashMap<StringHash, SharedPtr<EventReceiverGroup> >::Iterator j = i->second_.Find(eventType);
187             return j != i->second_.End() ? j->second_ : (EventReceiverGroup*)0;
188         }
189         else
190             return 0;
191     }
192 
193     /// Return event receivers for an event type, or null if they do not exist.
GetEventReceivers(StringHash eventType)194     EventReceiverGroup* GetEventReceivers(StringHash eventType)
195     {
196         HashMap<StringHash, SharedPtr<EventReceiverGroup> >::Iterator i = eventReceivers_.Find(eventType);
197         return i != eventReceivers_.End() ? i->second_ : (EventReceiverGroup*)0;
198     }
199 
200 private:
201     /// Add event receiver.
202     void AddEventReceiver(Object* receiver, StringHash eventType);
203     /// Add event receiver for specific event.
204     void AddEventReceiver(Object* receiver, Object* sender, StringHash eventType);
205     /// Remove an event sender from all receivers. Called on its destruction.
206     void RemoveEventSender(Object* sender);
207     /// Remove event receiver from specific events.
208     void RemoveEventReceiver(Object* receiver, Object* sender, StringHash eventType);
209     /// Remove event receiver from non-specific events.
210     void RemoveEventReceiver(Object* receiver, StringHash eventType);
211     /// Begin event send.
212     void BeginSendEvent(Object* sender, StringHash eventType);
213     /// End event send. Clean up event receivers removed in the meanwhile.
214     void EndSendEvent();
215 
216     /// Set current event handler. Called by Object.
SetEventHandler(EventHandler * handler)217     void SetEventHandler(EventHandler* handler) { eventHandler_ = handler; }
218 
219     /// Object factories.
220     HashMap<StringHash, SharedPtr<ObjectFactory> > factories_;
221     /// Subsystems.
222     HashMap<StringHash, SharedPtr<Object> > subsystems_;
223     /// Attribute descriptions per object type.
224     HashMap<StringHash, Vector<AttributeInfo> > attributes_;
225     /// Network replication attribute descriptions per object type.
226     HashMap<StringHash, Vector<AttributeInfo> > networkAttributes_;
227     /// Event receivers for non-specific events.
228     HashMap<StringHash, SharedPtr<EventReceiverGroup> > eventReceivers_;
229     /// Event receivers for specific senders' events.
230     HashMap<Object*, HashMap<StringHash, SharedPtr<EventReceiverGroup> > > specificEventReceivers_;
231     /// Event sender stack.
232     PODVector<Object*> eventSenders_;
233     /// Event data stack.
234     PODVector<VariantMap*> eventDataMaps_;
235     /// Active event handler. Not stored in a stack for performance reasons; is needed only in esoteric cases.
236     EventHandler* eventHandler_;
237     /// Object categories.
238     HashMap<String, Vector<StringHash> > objectCategories_;
239     /// Variant map for global variables that can persist throughout application execution.
240     VariantMap globalVars_;
241 };
242 
RegisterFactory()243 template <class T> void Context::RegisterFactory() { RegisterFactory(new ObjectFactoryImpl<T>(this)); }
244 
RegisterFactory(const char * category)245 template <class T> void Context::RegisterFactory(const char* category)
246 {
247     RegisterFactory(new ObjectFactoryImpl<T>(this), category);
248 }
249 
RemoveSubsystem()250 template <class T> void Context::RemoveSubsystem() { RemoveSubsystem(T::GetTypeStatic()); }
251 
RegisterAttribute(const AttributeInfo & attr)252 template <class T> void Context::RegisterAttribute(const AttributeInfo& attr) { RegisterAttribute(T::GetTypeStatic(), attr); }
253 
RemoveAttribute(const char * name)254 template <class T> void Context::RemoveAttribute(const char* name) { RemoveAttribute(T::GetTypeStatic(), name); }
255 
CopyBaseAttributes()256 template <class T, class U> void Context::CopyBaseAttributes() { CopyBaseAttributes(T::GetTypeStatic(), U::GetTypeStatic()); }
257 
GetSubsystem()258 template <class T> T* Context::GetSubsystem() const { return static_cast<T*>(GetSubsystem(T::GetTypeStatic())); }
259 
GetAttribute(const char * name)260 template <class T> AttributeInfo* Context::GetAttribute(const char* name) { return GetAttribute(T::GetTypeStatic(), name); }
261 
UpdateAttributeDefaultValue(const char * name,const Variant & defaultValue)262 template <class T> void Context::UpdateAttributeDefaultValue(const char* name, const Variant& defaultValue)
263 {
264     UpdateAttributeDefaultValue(T::GetTypeStatic(), name, defaultValue);
265 }
266 
267 }
268