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