Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

source: code/branches/core7/src/libraries/core/CoreIncludes.h @ 10365

Last change on this file since 10365 was 10362, checked in by landauf, 10 years ago

use static identifier initializer to store the inheritance definition of abstract classes. this prevents that identifiers are used (via Class(Name)) before they are properly initialized.

  • Property svn:eol-style set to native
File size: 8.8 KB
Line 
1/*
2 *   ORXONOX - the hottest 3D action shooter ever to exist
3 *                    > www.orxonox.net <
4 *
5 *
6 *   License notice:
7 *
8 *   This program is free software; you can redistribute it and/or
9 *   modify it under the terms of the GNU General Public License
10 *   as published by the Free Software Foundation; either version 2
11 *   of the License, or (at your option) any later version.
12 *
13 *   This program is distributed in the hope that it will be useful,
14 *   but WITHOUT ANY WARRANTY; without even the implied warranty of
15 *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16 *   GNU General Public License for more details.
17 *
18 *   You should have received a copy of the GNU General Public License
19 *   along with this program; if not, write to the Free Software
20 *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
21 *
22 *   Author:
23 *      Fabian 'x3n' Landau
24 *   Co-authors:
25 *      ...
26 *
27 */
28
29/**
30    @defgroup Factory RegisterObject() and RegisterClass()
31    @ingroup Object
32*/
33
34/**
35    @file
36    @ingroup Object Factory Class Identifier
37    @brief Defines several very important macros used to register objects, register classes, and to work with identifiers.
38
39    Every class needs the @c RegisterObject(class) macro in its constructor.
40
41    To register @a class in the class-hierarchy, use the @c RegisterClass(class) macro outside of the class implementation,
42    so it gets executed statically before @c main(). If you don't want @a class to be loadable, but still register it, call
43    @c RegisterUnloadableClass(class).
44
45    Abstract classes are registered with @c RegisterAbstractClass(class). For abstract classes, the inheritance must be
46    defined manually with @c RegisterAbstractClass(class).inheritsFrom(Class(parent)). Multiple parent classes can be defined
47    by chaining the above command.
48
49    Example:
50    @code
51    // register MyClass
52    RegisterClass(MyClass);
53
54    // Constructor:
55    MyClass::MyClass()
56    {
57        // Register the object in the Identifier of MyClass
58        RegisterObject(MyClass);
59    }
60    @endcode
61
62    This file also defines a number of other useful macros, like, for example, @c Class(class) which
63    returns the @ref orxonox::Identifier "Identifier" of @a class, or @c ClassByString("class") which
64    returns the Identifier of a class with name @a "class".
65
66    Example:
67    @code
68    // Assigns the Identifier of MyClass
69    Identifier* identifier = Class(MyClass);
70    @endcode
71    @code
72    // Assigns the Identifier of a class named "MyClass"
73    Identifier* identifier = ClassByString("MyClass");
74    @endcode
75*/
76
77#ifndef _CoreIncludes_H__
78#define _CoreIncludes_H__
79
80#include "CorePrereqs.h"
81
82#include "util/Output.h"
83#include "class/IdentifierManager.h"
84#include "object/ClassFactory.h"
85#include "object/ObjectList.h"
86#include "module/StaticallyInitializedInstance.h"
87
88// resolve macro conflict on windows
89#if defined(ORXONOX_PLATFORM_WINDOWS)
90#   define WIN32_LEAN_AND_MEAN
91#   include <windows.h>
92#   undef RegisterClass
93#endif
94
95
96/**
97    @brief Registers the class in the framework.
98    @param ClassName The name of the class
99*/
100#define RegisterClass(ClassName) \
101    RegisterClassWithFactory(ClassName, new orxonox::ClassFactoryWithContext<ClassName>(), true)
102
103/**
104    @brief Registers the class in the framework (for classes without arguments in their constructor).
105    @param ClassName The name of the class
106*/
107#define RegisterClassNoArgs(ClassName) \
108    RegisterClassWithFactory(ClassName, new orxonox::ClassFactoryNoArgs<ClassName>(), true)
109
110/**
111    @brief Registers the class in the framework (for classes which should not be loaded through XML).
112    @param ClassName The name of the class
113*/
114#define RegisterUnloadableClass(ClassName) \
115    RegisterClassWithFactory(ClassName, new orxonox::ClassFactoryWithContext<ClassName>(), false)
116
117/**
118    @brief Registers an abstract class in the framework. Should be used in combination with inheritsFrom(base-class-identifier).
119    @param ClassName The name of the class
120*/
121#define RegisterAbstractClass(ClassName) \
122    RegisterClassWithFactory(ClassName, static_cast<ClassFactory<ClassName>*>(NULL), false)
123
124/**
125    @brief Registers the class in the framework with a given Factory.
126    @param ClassName The name of the class
127*/
128#define RegisterClassWithFactory(ClassName, FactoryInstance, bLoadable) \
129    orxonox::SI_I& _##ClassName##Identifier = (*new orxonox::SI_I(orxonox::registerClass<ClassName>(#ClassName, FactoryInstance, bLoadable)))
130
131/**
132    @brief Registers a newly created object in the framework. Has to be called at the beginning of the constructor of @a ClassName.
133    @param ClassName The name of the class
134*/
135#define RegisterObject(ClassName) \
136    if (ClassIdentifier<ClassName>::getIdentifier(#ClassName)->initializeObject(this)) \
137        return; \
138    else \
139        ((void)0)
140
141/**
142    @brief Returns the Identifier of the given class.
143    @param ClassName The name of the class
144*/
145#define Class(ClassName) \
146    orxonox::ClassIdentifier<ClassName>::getIdentifier()
147
148
149namespace orxonox
150{
151    /**
152     * @brief Overload of registerClass() which determines T implicitly by the template argument of the ClassFactory.
153     */
154    template <class T>
155    inline Identifier* registerClass(const std::string& name, ClassFactory<T>* factory, bool bLoadable = true)
156    {
157        return registerClass<T>(name, static_cast<Factory*>(factory), bLoadable);
158    }
159
160    /**
161     * @brief Registers a class in the framework.
162     * @param name The name of the class
163     * @param factory The factory which is able to create new instances of this class
164     * @param bLoadable Whether the class is allowed to be loaded through XML
165     */
166    template <class T>
167    inline Identifier* registerClass(const std::string& name, Factory* factory, bool bLoadable = true)
168    {
169        orxout(verbose, context::misc::factory) << "Create entry for " << name << " in Factory." << endl;
170        Identifier* identifier = ClassIdentifier<T>::getIdentifier(name);
171        identifier->setFactory(factory);
172        identifier->setLoadable(bLoadable);
173        return identifier;
174    }
175
176    /**
177        @brief Returns the Identifier with a given name.
178        @param name The name of the class
179    */
180    inline Identifier* ClassByString(const std::string& name)
181    {
182        return IdentifierManager::getInstance().getIdentifierByString(name);
183    }
184
185    /**
186        @brief Returns the Identifier with a given lowercase name.
187        @param name The lowercase name of the class
188    */
189    inline Identifier* ClassByLowercaseString(const std::string& name)
190    {
191        return IdentifierManager::getInstance().getIdentifierByLowercaseString(name);
192    }
193
194    /**
195        @brief Returns the Identifier with a given network ID.
196        @param id The network ID of the class
197    */
198    inline Identifier* ClassByID(uint32_t id)
199    {
200        return IdentifierManager::getInstance().getIdentifierByID(id);
201    }
202
203    /**
204        @brief Returns the Identifier with a given 'this' pointer.
205        @note This of course only works with Identifiables.
206              The only use is in conjunction with macros that don't know the class type.
207        @param object Pointer to an Identifiable
208    */
209    template <class T>
210    inline Identifier* ClassByObjectType(const T*)
211    {
212        return ClassIdentifier<T>::getIdentifier();
213    }
214
215
216
217
218    /**
219     * The static initializer stores the parent classes of this identifier. The corresponding identifiers are later loaded. This prevents identifiers from
220     * being used before they are completely initialized.
221     */
222    class _CoreExport StaticallyInitializedIdentifier : public StaticallyInitializedInstance
223    {
224        struct InheritsFrom
225        {
226            virtual ~InheritsFrom() {}
227            virtual Identifier* getParent() = 0;
228        };
229
230        template <class T>
231        struct InheritsFromClass : public InheritsFrom
232        {
233            virtual Identifier* getParent() { return Class(T); }
234        };
235
236        public:
237            StaticallyInitializedIdentifier(Identifier* identifier) : identifier_(identifier) {}
238            ~StaticallyInitializedIdentifier()
239            {
240                for (size_t i = 0; i < this->parents_.size(); ++i)
241                    delete parents_[i];
242            }
243
244            virtual void load()
245            {
246                for (size_t i = 0; i < this->parents_.size(); ++i)
247                    this->identifier_->inheritsFrom(this->parents_[i]->getParent());
248            }
249
250            inline Identifier& getIdentifier()
251                { return *this->identifier_; }
252
253            template <class T>
254            inline StaticallyInitializedIdentifier& inheritsFrom()
255                { this->parents_.push_back(new InheritsFromClass<T>()); return *this; }
256
257        private:
258            Identifier* identifier_;
259            std::vector<InheritsFrom*> parents_;
260    };
261
262    typedef StaticallyInitializedIdentifier SI_I;
263}
264
265#endif /* _CoreIncludes_H__ */
Note: See TracBrowser for help on using the repository browser.