Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

source: code/branches/objecthierarchy2/src/core/Super.h @ 2254

Last change on this file since 2254 was 2254, checked in by landauf, 16 years ago

Update your media repository and delete keybindings.ini if you want to use boost (space).

  • Added new class "Engine" to control the speed of a SpaceShip (Engine is an Item, MultiStateEngine is a specialized version of Engine)
  • Added FadingBillboard, a billboard with the ability to fade in and out smoothly when activated/deactivated.
  • Several changes in Backlight, it's now a child of FadingBillboard
  • Some changes concerning local control in ControllableEntity
  • Fixed a bug in WorldEntity caused by different destruction order of attached objects on server and client
  • Added a "MainState" to BaseObject. An object has several states (activity, visibility, …) and one of it can be defined as "MainState" in the XML file. Other objects can change this state without knowing which state it really is (used by MultiStateEngine).
  • Property svn:eol-style set to native
File size: 21.7 KB
RevLine 
[1679]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
[1684]29/**
[2171]30    @file
[1684]31    @brief Definition of all super-function related macros.
32
33    This file defines all macros needed to add a new "super-function".
34    If you add a super-function, you can call SUPER(myclass, functionname) inside your
35    code and the function of the parentclass gets called. This is comparable with
36    super.functionname() in Java or other languages.
37
38    This works only with virtual functions that return nothing (void) and belong to
39    classes that have an Identifier. Arguments however are supported.
40
[1687]41    To add a new super-function, you have process 4 steps:
[1684]42
43    1) Add a new SUPER macro
44       This allows you to call the super-function in your code.
[1687]45       Location: This file (Super.h), marked with --> HERE <-- comments (1/3)
[1684]46
47    2) Call the SUPER_FUNCTION_GLOBAL_DECLARATION_PART1/2 macros.
48       This defines some global classes and templates, needed to create and call the super-functions.
[1687]49       Location: This file (Super.h), marked with --> HERE <-- comments (2/3)
[1684]50
51    3) Call the SUPER_INTRUSIVE_DECLARATION macro.
52       This will be included into the declaration of ClassIdentifier<T>.
[1687]53       Location: This file (Super.h), marked with --> HERE <-- comments (3/3)
[1684]54
[1687]55    4) Call the SUPER_FUNCTION macro.
[1684]56       This defines a partially specialized template that will decide if a class is "super" to another class.
57       If the check returns true, a SuperFunctionCaller gets created, which will be used by the SUPER macro.
58       You have to add this into the header-file of the baseclass of the super-function (the class that first
59       implements the function), below the class declaration. You can't call it directly in this file, because
60       otherwise you had to include the headerfile right here, which would cause some ugly backdependencies,
61       include loops and slower compilation.
62       Dont forget to include Super.h in the header-file.
63       Location: The header-file of the baseclass (Baseclass.h), below the class declaration
64*/
65
[1679]66#ifndef _Super_H__
67#define _Super_H__
68
69#include <iostream>
70
[1684]71#include "CorePrereqs.h"
[1679]72
[1684]73#include "util/Debug.h"
[1841]74#include "XMLIncludes.h"
[2087]75#include "Event.h"
[1679]76
[1684]77///////////////////////
78// Macro definitions //
79///////////////////////
80
81//// Common macros ////
82
83    /**
84        @brief Declares a new super-function by creating a specialized template. Add this below the class declaration of the baseclass.
85        @param functionnumber Each super-function needs a unique number, starting with zero, increasing by one
86        @param baseclass The baseclass of the super-function (~the root)
87        @param functionname The name of the super-function
88        @param purevirtualbase "true" if the function is pure virtual in the baseclass, "false" if the function is implemented (without "")
89    */
90    #define SUPER_FUNCTION(functionnumber, baseclass, functionname, purevirtualbase) \
91        template <class T, int templatehack2> \
92        struct SuperFunctionCondition<functionnumber, T, 0, templatehack2> \
93        { \
94            static void check() \
95            { \
96                SuperFunctionCondition<functionnumber, T, 0, templatehack2>::apply((T*)0); \
97                SuperFunctionCondition<functionnumber + 1, T, 0, templatehack2>::check(); \
98            } \
99            \
100            static void apply(void* temp) {} \
101            static void apply(baseclass* temp) \
102            { \
103                ClassIdentifier<T>* identifier = ClassIdentifier<T>::getIdentifier(); \
104                for (std::set<const Identifier*>::iterator it = identifier->getDirectChildrenIntern().begin(); it != identifier->getDirectChildrenIntern().end(); ++it) \
105                { \
106                    if (!((ClassIdentifier<T>*)(*it))->superFunctionCaller_##functionname##_) \
107                    { \
[1736]108                        COUT(5) << "Added SuperFunctionCaller for " << #functionname << ": " << ClassIdentifier<T>::getIdentifier()->getName() << " <- " << ((ClassIdentifier<T>*)(*it))->getName() << std::endl; \
[1684]109                        ((ClassIdentifier<T>*)(*it))->superFunctionCaller_##functionname##_ = new SuperFunctionClassCaller_##functionname <T>; \
110                    } \
111                } \
112            } \
113        }; \
114        \
115        SUPER_FUNCTION_PUREVIRTUAL_WORKAROUND##purevirtualbase(functionnumber, baseclass)
116
117    #define SUPER_FUNCTION_PUREVIRTUAL_WORKAROUND0(functionnumber, baseclass) SUPER_FUNCTION_PUREVIRTUAL_WORKAROUNDfalse(functionnumber, baseclass)
118    #define SUPER_FUNCTION_PUREVIRTUAL_WORKAROUND1(functionnumber, baseclass) SUPER_FUNCTION_PUREVIRTUAL_WORKAROUNDtrue(functionnumber, baseclass)
119    #define SUPER_FUNCTION_PUREVIRTUAL_WORKAROUNDfalse(functionnumber, baseclass)
120    #define SUPER_FUNCTION_PUREVIRTUAL_WORKAROUNDtrue(functionnumber, baseclass) \
121        template <int templatehack2> \
122        struct SuperFunctionCondition<functionnumber, baseclass, 0, templatehack2> \
123        { \
124            static void check() \
125            { \
126                SuperFunctionCondition<functionnumber + 1, baseclass, 0, templatehack2>::check(); \
127            } \
128        };
129
130
131    /*
132    //// Comments about the macro ////
133
134        // Partially specialized template (templatehack is now specialized too).
135        //
136        // This ensures the compiler takes THIS template if the header-file of the super-function
137        // is included. In any other case, the compiler just uses the fallback template which is
138        // defined in this file.
139        template <class T, templatehack2>
140        struct SuperFunctionCondition<functionnumber, T, 0, templatehack2>
141        {
142            static void check()
143            {
144                // This call to the apply-function is the whole check. By calling the function with
145                // a T* pointer, the right function get's called.
146                SuperFunctionCondition<functionnumber, T, 0, templatehack2>::apply((T*)0);
147
148                // Go go the check for of next super-function (functionnumber + 1)
149                SuperFunctionCondition<functionnumber + 1, T, 0, templatehack2>::check();
150            }
151
152            // This function gets called if T is not a child of the baseclass.
153            // The function does nothing.
154            static void apply(void* temp) {}
155
156            // This function gets called if T is a child of the baseclass and can therefore be converted.
157            // The function adds a SuperFunctionCaller to the Identifier of all subclasses of T.
158            static void apply(baseclass* temp)
159            {
160                ClassIdentifier<T>* identifier = ClassIdentifier<T>::getIdentifier();
161
162                // Iterate through all children
163                for (std::set<const Identifier*>::iterator it = identifier->getDirectChildrenIntern().begin(); it != identifier->getDirectChildrenIntern().end(); ++it)
164                {
165                    // Check if there's not already a caller
166                    if (!((ClassIdentifier<T>*)(*it))->superFunctionCaller_##functionname##_)
167                    {
168                        // Add the SuperFunctionCaller
169                        COUT(5) << "adding functionpointer to " << ((ClassIdentifier<T>*)(*it))->getName() << std::endl;
170                        ((ClassIdentifier<T>*)(*it))->superFunctionCaller_##functionname##_ = new SuperFunctionClassCaller_##functionname <T>;
171                    }
172                }
173            }
174        };
175        SUPER_FUNCTION_PUREVIRTUAL_WORKAROUND##purevirtualbase
176
177
178        // The following piece of code is only added if purevirtualbase = true
179
180        // Explicit specialization of the Condition template for the baseclass to avoid
181        // errors if the function is pure virtual in the baseclass.
182        template <int templatehack2> \
183        struct SuperFunctionCondition<functionnumber, baseclass, 0, templatehack2> \
184        { \
185            // The check function just behaves like the fallback - it advances to the check for the next super-function (functionnumber + 1)
186            static void check() \
187            { \
188                SuperFunctionCondition<functionnumber + 1, baseclass, 0, templatehack2>::check(); \
189            } \
190        };
191    */
192
193    // SUPER-macro: Calls Parent::functionname() where Parent is the direct parent of classname
194    #define SUPER(classname, functionname, ...) \
195        SUPER_##functionname(classname, functionname, __VA_ARGS__)
196
197    // helper macro: for functions without arguments
198    #define SUPER_NOARGS(classname, functionname) \
199        (*ClassIdentifier<classname>::getIdentifier()->superFunctionCaller_##functionname##_)(this)
200
201    // helper macro: for functions with arguments
202    #define SUPER_ARGS(classname, functionname, ...) \
203        (*ClassIdentifier<classname>::getIdentifier()->superFunctionCaller_##functionname##_)(this, __VA_ARGS__)
204
205
206//// Function-specific macros ////
207
208    /*
209        Add a macro for each super-function
210
211        Example (no arguments):
212        #define SUPER_myfunction(classname, functionname, ...) \
213            SUPER_NOARGS(classname, functionname)
214
215        Example (with arguments):
216        #define SUPER_myfunction(classname, functionname, ...) \
217            SUPER_ARGS(classname, functionname, __VA_ARGS__)
218    */
219
[1687]220    // (1/3) --> HERE <-- --> HERE <-- --> HERE <-- --> HERE <-- --> HERE <-- --> HERE <-- --> HERE <--
[1684]221    #define SUPER_XMLPort(classname, functionname, ...) \
222        SUPER_ARGS(classname, functionname, __VA_ARGS__)
223
224    #define SUPER_tick(classname, functionname, ...) \
225        SUPER_ARGS(classname, functionname, __VA_ARGS__)
226
227    #define SUPER_changedActivity(classname, functionname, ...) \
228        SUPER_NOARGS(classname, functionname)
229
230    #define SUPER_changedVisibility(classname, functionname, ...) \
231        SUPER_NOARGS(classname, functionname)
[2087]232
233    #define SUPER_processEvent(classname, functionname, ...) \
234        SUPER_ARGS(classname, functionname, __VA_ARGS__)
[2212]235
236    #define SUPER_changedScale(classname, functionname, ...) \
237        SUPER_NOARGS(classname, functionname)
[2254]238
239    #define SUPER_changedMainState(classname, functionname, ...) \
240        SUPER_NOARGS(classname, functionname)
[1687]241    // (1/3) --> HERE <-- --> HERE <-- --> HERE <-- --> HERE <-- --> HERE <-- --> HERE <-- --> HERE <--
[1684]242
243
[1679]244namespace orxonox
245{
[1684]246    /////////////////////////////////////////////////////////////////////////////////////////////////////
247    // This code gets included by Identifier.h and every other header file that needs a super-function //
248    /////////////////////////////////////////////////////////////////////////////////////////////////////
[1679]249
[1684]250    //// Common code ////
[1679]251
[1687]252        // Base templates
253        /**
254            @brief Creates the SuperFunctionCaller if T is a child of the super-functions baseclass.
255        */
[1684]256        template <int functionnumber, class T, int templatehack1, int templatehack2>
257        struct SuperFunctionCondition
[1679]258        {
[1684]259            static void check() {}
260        };
[1679]261
[1687]262        /**
263            @brief Initializes the SuperFunctionCaller-pointer with zero.
264        */
265        template <int functionnumber, class T>
266        struct SuperFunctionInitialization
267        {
268            static void initialize(ClassIdentifier<T>* identifier) {}
269        };
[1679]270
[1687]271        /**
272            @brief Deletes the SuperFunctionCaller.
273        */
274        template <int functionnumber, class T>
275        struct SuperFunctionDestruction
276        {
277            static void destroy(ClassIdentifier<T>* identifier) {}
278        };
279
280
[1684]281    //// Function-specific code ////
282
283        /**
284            @brief Creates the needed objects and templates to call a super-function.
285            @param functionnumber Each super-function needs a unique number, starting with zero, increasing by one
286            @param functionname The name of the super-function
287            @param hasarguments "false" if the function doesn't take any arguments, "true" if it does (without "")
288            @param ... Variadic: If the function takes arguments, add them here with type and name. Example: int myvalue, float myothervalue
289        */
290        #define SUPER_FUNCTION_GLOBAL_DECLARATION_PART1(functionnumber, functionname, hasarguments, ...) \
291            template <class T, int templatehack1, int templatehack2> \
292            struct SuperFunctionCondition<functionnumber, T, templatehack1, templatehack2> \
293            { \
294                static void check() \
295                { \
296                    SuperFunctionCondition<functionnumber + 1, T, templatehack1, templatehack2>::check(); \
297                } \
298            }; \
299            \
[1687]300            template <class T> \
301            struct SuperFunctionInitialization<functionnumber, T> \
302            { \
303                static void initialize(ClassIdentifier<T>* identifier) \
304                { \
305                    identifier->superFunctionCaller_##functionname##_ = 0; \
306                    SuperFunctionInitialization<functionnumber + 1, T>::initialize(identifier); \
307                } \
308            }; \
309            \
310            template <class T> \
311            struct SuperFunctionDestruction<functionnumber, T> \
312            { \
313                static void destroy(ClassIdentifier<T>* identifier) \
314                { \
315                    if (identifier->superFunctionCaller_##functionname##_) \
316                        delete identifier->superFunctionCaller_##functionname##_; \
317                    SuperFunctionDestruction<functionnumber + 1, T>::destroy(identifier); \
318                } \
319            }; \
320            \
[1684]321            class _CoreExport SuperFunctionCaller_##functionname \
322            { \
323                public: \
324                    virtual void operator()( SUPER_CALL_ARGUMENTS##hasarguments(__VA_ARGS__) ) = 0; \
325                    virtual ~SuperFunctionCaller_##functionname () {} \
326            }; \
327            \
328            template <class T> \
329            class SuperFunctionClassCaller_##functionname : public SuperFunctionCaller_##functionname \
330            { \
331                public: \
332                    inline void operator()( SUPER_CALL_ARGUMENTS##hasarguments(__VA_ARGS__) ) \
333                    { \
334                        (dynamic_cast<T*>(object))->T:: functionname
335
336        /*
337            JUST ADD THE FUNCTION ARGUMENTS BETWEEN BOTH MACROS, ENCLOSED BY BRACKETS
338            EXAMPLE:
339
340              SUPER_FUNCTION_GLOBAL_DECLARATION_PART1(0, myfunction, true, int myvalue, float myothervalue) <-- !!! DONT ADD A SEMICOLON HERE !!!
341                (myvalue, myothervalue)
342              SUPER_FUNCTION_GLOBAL_DECLARATION_PART2
343        */
344
345        #define SUPER_FUNCTION_GLOBAL_DECLARATION_PART2 \
346                                                        ; \
347                    } \
348            };
349
350        #define SUPER_CALL_ARGUMENTSfalse(...) OrxonoxClass* object
351        #define SUPER_CALL_ARGUMENTS0(...)     OrxonoxClass* object
352        #define SUPER_CALL_ARGUMENTStrue(...) OrxonoxClass* object, __VA_ARGS__
353        #define SUPER_CALL_ARGUMENTS1(...)    OrxonoxClass* object, __VA_ARGS__
354
355
356    /*
357    //// COMMENTS ABOUT THE MACRO ////
358
359        // Partially specialized template (templatehack not yet specialized, this
360        // will be done by the real condition in the header-file of the super-function)
361        // Only used as fallback
362        template <class T, int templatehack1, int templatehack2>
363        struct SuperFunctionCondition<functionnumber, T, templatehack1, templatehack2>
364        {
365            // If this function gets called, the header-file of the super function is not
366            // included, so this fallback template (templatehack not specialized) is used
367            static void check()
[1679]368            {
[1684]369                // Calls the condition-check of the next super-function (functionnumber + 1)
370                SuperFunctionCondition<functionnumber + 1, T, templatehack1, templatehack2>::check();
[1679]371            }
[1684]372        };
373
[1687]374        // Initializes the SuperFunctionCaller-pointer with zero.
375        template <class T>
376        struct SuperFunctionInitialization<functionnumber, T>
377        {
378            static void initialize(ClassIdentifier<T>* identifier)
379            {
380                identifier->superFunctionCaller_##functionname##_ = 0;
381
382                // Calls the initialization of the next super-function (functionnumber + 1)
383                SuperFunctionInitialization<functionnumber + 1, T>::initialize(identifier);
384            }
385        };
386
387        // Deletes the SuperFunctionCaller.
388        template <class T>
389        struct SuperFunctionDestruction<functionnumber, T>
390        {
391            static void destroy(ClassIdentifier<T>* identifier)
392            {
393                if (identifier->superFunctionCaller_##functionname##_)
394                    delete identifier->superFunctionCaller_##functionname##_;
395
396                // Calls the destruction of the next super-function (functionnumber + 1)
397                SuperFunctionDestruction<functionnumber + 1, T>::destroy(identifier);
398            }
399        };
400
[1684]401        // Baseclass of the super-function caller. The real call will be done by a
402        // templatized subclass through the virtual () operator.
403        class _CoreExport SuperFunctionCaller_##functionname
404        {
405            public:
406                virtual void operator()( SUPER_CALL_ARGUMENTS##hasarguments(__VA_ARGS__) ) = 0;
407                virtual ~SuperFunctionCaller_##functionname () {}
408        };
409
410        // The real super-function caller: Calls T::functionname()
411        // T should be the parent, but this will be done by the spezialized condition template
412        template <class T>
413        class SuperFunctionClassCaller_##functionname : public SuperFunctionCaller_##functionname
414        {
415            public:
416                // @brief Calls the function.
417                // @param object The object to call the function on
418                // @param ... The arguments of the function
419                inline void operator()( SUPER_CALL_ARGUMENTS##hasarguments(__VA_ARGS__) )
420                {
421                    (dynamic_cast<T*>(object))->T:: functionname ( Call the function with it's arguments );
422                }
423        }
424    */
425
[1687]426
[1684]427    //// Execute the code for each super-function ////
[1687]428
429        // (2/3) --> HERE <-- --> HERE <-- --> HERE <-- --> HERE <-- --> HERE <-- --> HERE <-- --> HERE <--
[1736]430        SUPER_FUNCTION_GLOBAL_DECLARATION_PART1(0, XMLPort, true, Element& xmlelement, XMLPort::Mode mode)
[1684]431            (xmlelement, mode)
432        SUPER_FUNCTION_GLOBAL_DECLARATION_PART2;
433
[1736]434        SUPER_FUNCTION_GLOBAL_DECLARATION_PART1(1, tick, true, float dt)
[1684]435            (dt)
436        SUPER_FUNCTION_GLOBAL_DECLARATION_PART2;
437
[1736]438        SUPER_FUNCTION_GLOBAL_DECLARATION_PART1(2, changedActivity, false)
[1684]439            ()
440        SUPER_FUNCTION_GLOBAL_DECLARATION_PART2;
441
[1736]442        SUPER_FUNCTION_GLOBAL_DECLARATION_PART1(3, changedVisibility, false)
[1684]443            ()
444        SUPER_FUNCTION_GLOBAL_DECLARATION_PART2;
[2087]445
446        SUPER_FUNCTION_GLOBAL_DECLARATION_PART1(4, processEvent, true, Event& event)
447            (event)
448        SUPER_FUNCTION_GLOBAL_DECLARATION_PART2;
[2212]449
450        SUPER_FUNCTION_GLOBAL_DECLARATION_PART1(5, changedScale, false)
451            ()
452        SUPER_FUNCTION_GLOBAL_DECLARATION_PART2;
[2254]453
454        SUPER_FUNCTION_GLOBAL_DECLARATION_PART1(6, changedMainState, false)
455            ()
456        SUPER_FUNCTION_GLOBAL_DECLARATION_PART2;
[1687]457        // (2/3) --> HERE <-- --> HERE <-- --> HERE <-- --> HERE <-- --> HERE <-- --> HERE <-- --> HERE <--
[1684]458
[1679]459}
460
461#else /* _Super_H__ */
[1684]462  #ifdef SUPER_INTRUSIVE_DECLARATION_INCLUDE
[1679]463
[1684]464//////////////////////////////////////////////////////////////////////////
465// This code gets included within the declaration of ClassIdentifier<T> //
466//////////////////////////////////////////////////////////////////////////
[1679]467
[1684]468//// Common code ////
[1679]469
[1684]470    private:
[1687]471
[1684]472        template <int functionnumber, class TT, int templatehack1, int templatehack2>
473        friend struct SuperFunctionCondition;
[1679]474
[1684]475        // Creates the super-function-callers by calling the first SuperFunctionCondition check
476        // This get's called within the initialization of an Identifier
477        virtual void createSuperFunctionCaller() const
478        {
479            SuperFunctionCondition<0, T, 0, 0>::check();
480        }
[1679]481
482
[1684]483//// Function-specific code ////
484
485    public:
486        /**
487            @brief Adds a pointer to the SuperFunctionCaller as a member of ClassIdentifier.
488            @param functionname The name of the super-function
489        */
490        #ifndef SUPER_INTRUSIVE_DECLARATION
491          #define SUPER_INTRUSIVE_DECLARATION(functionname) \
492            SuperFunctionCaller_##functionname * superFunctionCaller_##functionname##_
493        #endif
494
495
496//// Execute the code for each super-function ////
[1687]497
498    // (3/3) --> HERE <-- --> HERE <-- --> HERE <-- --> HERE <-- --> HERE <-- --> HERE <-- --> HERE <--
[1684]499    SUPER_INTRUSIVE_DECLARATION(XMLPort);
500    SUPER_INTRUSIVE_DECLARATION(tick);
501    SUPER_INTRUSIVE_DECLARATION(changedActivity);
502    SUPER_INTRUSIVE_DECLARATION(changedVisibility);
[2087]503    SUPER_INTRUSIVE_DECLARATION(processEvent);
[2212]504    SUPER_INTRUSIVE_DECLARATION(changedScale);
[2254]505    SUPER_INTRUSIVE_DECLARATION(changedMainState);
[1687]506    // (3/3) --> HERE <-- --> HERE <-- --> HERE <-- --> HERE <-- --> HERE <-- --> HERE <-- --> HERE <--
[1684]507
508
509    #undef SUPER_INTRUSIVE_DECLARATION_INCLUDE
510  #endif /* SUPER_INTRUSIVE_DECLARATION_INCLUDE */
[1679]511#endif /* _Super_H__ */
Note: See TracBrowser for help on using the repository browser.