Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

source: code/trunk/src/libraries/core/Identifier.cc @ 7073

Last change on this file since 7073 was 6536, checked in by rgrieder, 15 years ago

Merged revisions 6430-6440 from the gamestate branch to the trunk.
This adds keybindings merging functionality.

(from log of r6437)
When running development builds, the keybinder will merge the local file and the one from the data folder.
Catch: if you want to remove a binding, you'll have to write "NoBinding" (not case sensitive) to override the default command

The keybind command already does that for you though.

  • Property svn:eol-style set to native
File size: 21.0 KB
RevLine 
[790]1/*
2 *   ORXONOX - the hottest 3D action shooter ever to exist
[1505]3 *                    > www.orxonox.net <
[790]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
[871]29/**
[2171]30    @file
[790]31    @brief Implementation of the Identifier class.
32*/
33
[1505]34#include "Identifier.h"
35
36#include <ostream>
37
[3280]38#include "util/StringUtils.h"
[1747]39#include "ConfigValueContainer.h"
[5781]40#include "ConsoleCommand.h"
[5929]41#include "ClassFactory.h"
[5781]42#include "XMLPort.h"
[790]43
44namespace orxonox
45{
46    // ###############################
47    // ###       Identifier        ###
48    // ###############################
[3325]49    int Identifier::hierarchyCreatingCounter_s = 0;
50    unsigned int Identifier::classIDCounter_s = 0;
[790]51
52    /**
53        @brief Constructor: No factory, no object created, new ObjectList and a unique networkID.
54    */
55    Identifier::Identifier()
[3325]56        : classID_(classIDCounter_s++)
[790]57    {
[1747]58        this->objects_ = new ObjectListBase(this);
59
[790]60        this->bCreatedOneObject_ = false;
[1747]61        this->bSetName_ = false;
[1505]62        this->factory_ = 0;
[5929]63        this->bLoadable_ = false;
[1505]64
65        this->bHasConfigValues_ = false;
[5781]66        this->bHasConsoleCommands_ = false;
[790]67
[5781]68        // Default network ID is the class ID
69        this->networkID_ = this->classID_;
[790]70    }
71
72    /**
[871]73        @brief Destructor: Deletes the list containing the children.
[790]74    */
75    Identifier::~Identifier()
76    {
[1747]77        delete this->objects_;
78
79        if (this->factory_)
80            delete this->factory_;
81
[5781]82        for (std::map<std::string, ConsoleCommand*>::iterator it = this->consoleCommands_.begin(); it != this->consoleCommands_.end(); ++it)
83            delete (it->second);
[1747]84        for (std::map<std::string, ConfigValueContainer*>::iterator it = this->configValues_.begin(); it != this->configValues_.end(); ++it)
85            delete (it->second);
[5781]86        for (std::map<std::string, XMLPortParamContainer*>::iterator it = this->xmlportParamContainers_.begin(); it != this->xmlportParamContainers_.end(); ++it)
87            delete (it->second);
88        for (std::map<std::string, XMLPortObjectContainer*>::iterator it = this->xmlportObjectContainers_.begin(); it != this->xmlportObjectContainers_.end(); ++it)
89            delete (it->second);
[790]90    }
91
92    /**
[2662]93        @brief Returns the identifier map with the names as received by typeid(). This is only used internally.
94    */
95    std::map<std::string, Identifier*>& Identifier::getTypeIDIdentifierMap()
96    {
97        static std::map<std::string, Identifier*> identifiers;    //!< The map to store all Identifiers.
98        return identifiers;
99    }
100
101    /**
[1543]102        @brief Returns an identifier by name and adds it if not available
103        @param name The name of the identifier as typeid().name() suggests
104        @param proposal A pointer to a newly created identifier for the case of non existance in the map
105        @return The identifier (unique instance)
106    */
[1747]107    Identifier* Identifier::getIdentifierSingleton(const std::string& name, Identifier* proposal)
[1543]108    {
[2662]109        std::map<std::string, Identifier*>::const_iterator it = getTypeIDIdentifierMap().find(name);
[1747]110
[2662]111        if (it != getTypeIDIdentifierMap().end())
[1543]112        {
[1747]113            // There is already an entry: return it and delete the proposal
114            delete proposal;
[5929]115            return it->second;
[1543]116        }
117        else
118        {
[1747]119            // There is no entry: put the proposal into the map and return it
[2662]120            getTypeIDIdentifierMap()[name] = proposal;
[1747]121            return proposal;
[1543]122        }
123    }
124
125    /**
[1856]126        @brief Registers a class, which means that the name and the parents get stored.
127        @param parents A list, containing the Identifiers of all parents of the class
128        @param bRootClass True if the class is either an Interface or the BaseObject itself
129    */
130    void Identifier::initializeClassHierarchy(std::set<const Identifier*>* parents, bool bRootClass)
131    {
132        // Check if at least one object of the given type was created
133        if (!this->bCreatedOneObject_ && Identifier::isCreatingHierarchy())
134        {
[5695]135            // If no: We have to store the information and initialize the Identifier
[1856]136            COUT(4) << "*** ClassIdentifier: Register Class in " << this->getName() << "-Singleton -> Initialize Singleton." << std::endl;
137            if (bRootClass)
138                this->initialize(0); // If a class is derived from two interfaces, the second interface might think it's derived from the first because of the order of constructor-calls. Thats why we set parents to zero in that case.
139            else
140                this->initialize(parents);
141        }
142    }
143
144    /**
[871]145        @brief Initializes the Identifier with a list containing all parents of the class the Identifier belongs to.
146        @param parents A list containing all parents
[790]147    */
[1052]148    void Identifier::initialize(std::set<const Identifier*>* parents)
[790]149    {
[871]150        COUT(4) << "*** Identifier: Initialize " << this->name_ << "-Singleton." << std::endl;
[790]151        this->bCreatedOneObject_ = true;
152
153        if (parents)
[1505]154        {
155            this->parents_ = (*parents);
156            this->directParents_ = (*parents);
157
[871]158            // Iterate through all parents
[1052]159            for (std::set<const Identifier*>::iterator it = parents->begin(); it != parents->end(); ++it)
[1505]160            {
161                // Tell the parent we're one of it's children
[5929]162                (*it)->children_.insert((*it)->children_.end(), this);
[1505]163
164                // Erase all parents of our parent from our direct-parent-list
165                for (std::set<const Identifier*>::const_iterator it1 = (*it)->getParents().begin(); it1 != (*it)->getParents().end(); ++it1)
166                {
167                    // Search for the parent's parent in our direct-parent-list
168                    for (std::set<const Identifier*>::iterator it2 = this->directParents_.begin(); it2 != this->directParents_.end(); ++it2)
169                    {
170                        if ((*it1) == (*it2))
171                        {
172                            // We've found a non-direct parent in our list: Erase it
173                            this->directParents_.erase(it2);
174                            break;
175                        }
176                    }
177                }
[790]178            }
[1505]179
180            // Now iterate through all direct parents
181            for (std::set<const Identifier*>::iterator it = this->directParents_.begin(); it != this->directParents_.end(); ++it)
182            {
183                // Tell the parent we're one of it's direct children
[5929]184                (*it)->directChildren_.insert((*it)->directChildren_.end(), this);
[5781]185
186                // Create the super-function dependencies
187                (*it)->createSuperFunctionCaller();
[1505]188            }
[790]189        }
190    }
191
192    /**
[5929]193        @brief Creates the class-hierarchy by creating and destroying one object of each type.
194    */
195    void Identifier::createClassHierarchy()
196    {
197        COUT(3) << "*** Identifier: Create class-hierarchy" << std::endl;
198        Identifier::startCreatingHierarchy();
199        for (std::map<std::string, Identifier*>::const_iterator it = Identifier::getStringIdentifierMap().begin(); it != Identifier::getStringIdentifierMap().end(); ++it)
200        {
201            // To create the new branch of the class-hierarchy, we create a new object and delete it afterwards.
202            if (it->second->hasFactory())
203            {
204                BaseObject* temp = it->second->fabricate(0);
205                temp->destroy();
206            }
207        }
208        Identifier::stopCreatingHierarchy();
209        COUT(3) << "*** Identifier: Finished class-hierarchy creation" << std::endl;
210    }
211
212    /**
[1747]213        @brief Destroys all Identifiers. Called when exiting the program.
214    */
215    void Identifier::destroyAllIdentifiers()
216    {
[2662]217        for (std::map<std::string, Identifier*>::iterator it = Identifier::getTypeIDIdentifierMap().begin(); it != Identifier::getTypeIDIdentifierMap().end(); ++it)
[1747]218            delete (it->second);
219    }
220
221    /**
222        @brief Sets the name of the class.
223        @param name The name
224    */
225    void Identifier::setName(const std::string& name)
226    {
227        if (!this->bSetName_)
228        {
229            this->name_ = name;
230            this->bSetName_ = true;
[5929]231            Identifier::getStringIdentifierMapIntern()[name] = this;
232            Identifier::getLowercaseStringIdentifierMapIntern()[getLowercase(name)] = this;
233            Identifier::getIDIdentifierMapIntern()[this->networkID_] = this;
[1747]234        }
235    }
236
237    /**
[790]238        @brief Creates an object of the type the Identifier belongs to.
239        @return The new object
240    */
[2087]241    BaseObject* Identifier::fabricate(BaseObject* creator)
[790]242    {
243        if (this->factory_)
244        {
[2087]245            return this->factory_->fabricate(creator); // We have to return a BaseObject, because we don't know the exact type.
[790]246        }
247        else
248        {
[1505]249            COUT(1) << "An error occurred in Identifier.cc:" << std::endl;
[871]250            COUT(1) << "Error: Cannot fabricate an object of type '" << this->name_ << "'. Class has no factory." << std::endl;
[790]251            COUT(1) << "Aborting..." << std::endl;
252            abort();
[5929]253            return 0;
[790]254        }
255    }
256
257    /**
[5929]258        @brief Sets the network ID to a new value and changes the entry in the ID-Identifier-map.
[5781]259        @param id The new network ID
260    */
261    void Identifier::setNetworkID(uint32_t id)
262    {
[5929]263//        Identifier::getIDIdentifierMapIntern().erase(this->networkID_);
264        Identifier::getIDIdentifierMapIntern()[id] = this;
[5781]265        this->networkID_ = id;
266    }
267
268    /**
[871]269        @brief Returns true, if the Identifier is at least of the given type.
[790]270        @param identifier The identifier to compare with
271    */
272    bool Identifier::isA(const Identifier* identifier) const
273    {
[1059]274        return (identifier == this || (this->parents_.find(identifier) != this->parents_.end()));
[790]275    }
276
277    /**
[871]278        @brief Returns true, if the Identifier is exactly of the given type.
[790]279        @param identifier The identifier to compare with
280    */
[871]281    bool Identifier::isExactlyA(const Identifier* identifier) const
[790]282    {
283        return (identifier == this);
284    }
285
286    /**
[871]287        @brief Returns true, if the assigned identifier is a child of the given identifier.
[790]288        @param identifier The identifier to compare with
289    */
290    bool Identifier::isChildOf(const Identifier* identifier) const
291    {
[1060]292        return (this->parents_.find(identifier) != this->parents_.end());
[1505]293    }
[790]294
295    /**
[1505]296        @brief Returns true, if the assigned identifier is a direct child of the given identifier.
297        @param identifier The identifier to compare with
298    */
299    bool Identifier::isDirectChildOf(const Identifier* identifier) const
300    {
301        return (this->directParents_.find(identifier) != this->directParents_.end());
302    }
303
304    /**
[871]305        @brief Returns true, if the assigned identifier is a parent of the given identifier.
[790]306        @param identifier The identifier to compare with
307    */
308    bool Identifier::isParentOf(const Identifier* identifier) const
309    {
[5929]310        return (this->children_.find(identifier) != this->children_.end());
[1505]311    }
312
313    /**
314        @brief Returns true, if the assigned identifier is a direct parent of the given identifier.
315        @param identifier The identifier to compare with
316    */
317    bool Identifier::isDirectParentOf(const Identifier* identifier) const
318    {
[5929]319        return (this->directChildren_.find(identifier) != this->directChildren_.end());
[1505]320    }
321
322    /**
[5929]323        @brief Returns the map that stores all Identifiers with their names.
[1505]324        @return The map
325    */
[5929]326    std::map<std::string, Identifier*>& Identifier::getStringIdentifierMapIntern()
[1505]327    {
328        static std::map<std::string, Identifier*> identifierMap;
329        return identifierMap;
330    }
331
332    /**
[5929]333        @brief Returns the map that stores all Identifiers with their names in lowercase.
[1505]334        @return The map
335    */
[5929]336    std::map<std::string, Identifier*>& Identifier::getLowercaseStringIdentifierMapIntern()
[1505]337    {
338        static std::map<std::string, Identifier*> lowercaseIdentifierMap;
339        return lowercaseIdentifierMap;
340    }
341
342    /**
[5929]343        @brief Returns the map that stores all Identifiers with their network IDs.
344        @return The map
345    */
346    std::map<uint32_t, Identifier*>& Identifier::getIDIdentifierMapIntern()
347    {
348        static std::map<uint32_t, Identifier*> identifierMap;
349        return identifierMap;
350    }
351
352    /**
353        @brief Returns the Identifier with a given name.
354        @param name The name of the wanted Identifier
355        @return The Identifier
356    */
357    Identifier* Identifier::getIdentifierByString(const std::string& name)
358    {
359        std::map<std::string, Identifier*>::const_iterator it = Identifier::getStringIdentifierMapIntern().find(name);
360        if (it != Identifier::getStringIdentifierMapIntern().end())
361            return it->second;
362        else
363            return 0;
364    }
365
366    /**
367        @brief Returns the Identifier with a given name in lowercase.
368        @param name The name of the wanted Identifier
369        @return The Identifier
370    */
371    Identifier* Identifier::getIdentifierByLowercaseString(const std::string& name)
372    {
373        std::map<std::string, Identifier*>::const_iterator it = Identifier::getLowercaseStringIdentifierMapIntern().find(name);
374        if (it != Identifier::getLowercaseStringIdentifierMapIntern().end())
375            return it->second;
376        else
377            return 0;
378    }
379
380    /**
381        @brief Returns the Identifier with a given network ID.
382        @param id The network ID of the wanted Identifier
383        @return The Identifier
384    */
385    Identifier* Identifier::getIdentifierByID(const uint32_t id)
386    {
387        std::map<uint32_t, Identifier*>::const_iterator it = Identifier::getIDIdentifierMapIntern().find(id);
388        if (it != Identifier::getIDIdentifierMapIntern().end())
389            return it->second;
390        else
391            return 0;
392    }
393
394    /**
395        @brief Cleans the NetworkID map (needed on clients for correct initialization)
396    */
397    void Identifier::clearNetworkIDs()
398    {
399        Identifier::getIDIdentifierMapIntern().clear();
400    }
401
402    /**
[1505]403        @brief Adds the ConfigValueContainer of a variable, given by the string of its name.
404        @param varname The name of the variablee
405        @param container The container
406    */
407    void Identifier::addConfigValueContainer(const std::string& varname, ConfigValueContainer* container)
408    {
409        std::map<std::string, ConfigValueContainer*>::const_iterator it = this->configValues_.find(varname);
410        if (it != this->configValues_.end())
411        {
[6417]412            COUT(2) << "Warning: Overwriting config-value with name " << varname << " in class " << this->getName() << '.' << std::endl;
[1747]413            delete (it->second);
[1505]414        }
415
416        this->bHasConfigValues_ = true;
417        this->configValues_[varname] = container;
418    }
419
420    /**
421        @brief Returns the ConfigValueContainer of a variable, given by the string of its name.
422        @param varname The name of the variable
423        @return The ConfigValueContainer
424    */
425    ConfigValueContainer* Identifier::getConfigValueContainer(const std::string& varname)
426    {
427        std::map<std::string, ConfigValueContainer*>::const_iterator it = configValues_.find(varname);
428        if (it != configValues_.end())
[5929]429            return it->second;
[1505]430        else
431            return 0;
432    }
433
434    /**
[5781]435        @brief Adds a new console command of this class.
436        @param executor The executor of the command
437        @param bCreateShortcut If this is true a shortcut gets created so you don't have to add the classname to access this command
438        @return The executor of the command
439    */
440    ConsoleCommand& Identifier::addConsoleCommand(ConsoleCommand* command, bool bCreateShortcut)
441    {
442        std::map<std::string, ConsoleCommand*>::const_iterator it = this->consoleCommands_.find(command->getName());
443        if (it != this->consoleCommands_.end())
444        {
[6417]445            COUT(2) << "Warning: Overwriting console-command with name " << command->getName() << " in class " << this->getName() << '.' << std::endl;
[5781]446            delete (it->second);
447        }
448
449        this->bHasConsoleCommands_ = true;
450        this->consoleCommands_[command->getName()] = command;
451        this->consoleCommands_LC_[getLowercase(command->getName())] = command;
452
453        if (bCreateShortcut)
454            CommandExecutor::addConsoleCommandShortcut(command);
455
456        return (*command);
457    }
458
459    /**
460        @brief Returns the executor of a console command with given name.
461        @brief name The name of the requested console command
462        @return The executor of the requested console command
463    */
464    ConsoleCommand* Identifier::getConsoleCommand(const std::string& name) const
465    {
466        std::map<std::string, ConsoleCommand*>::const_iterator it = this->consoleCommands_.find(name);
467        if (it != this->consoleCommands_.end())
[5929]468            return it->second;
[5781]469        else
470            return 0;
471    }
472
473    /**
474        @brief Returns the executor of a console command with given name in lowercase.
475        @brief name The name of the requested console command in lowercae
476        @return The executor of the requested console command
477    */
478    ConsoleCommand* Identifier::getLowercaseConsoleCommand(const std::string& name) const
479    {
480        std::map<std::string, ConsoleCommand*>::const_iterator it = this->consoleCommands_LC_.find(name);
481        if (it != this->consoleCommands_LC_.end())
[5929]482            return it->second;
[5781]483        else
484            return 0;
485    }
486
487    /**
488        @brief Returns a XMLPortParamContainer that loads a parameter of this class.
489        @param paramname The name of the parameter
490        @return The container
491    */
492    XMLPortParamContainer* Identifier::getXMLPortParamContainer(const std::string& paramname)
493    {
494        std::map<std::string, XMLPortParamContainer*>::const_iterator it = this->xmlportParamContainers_.find(paramname);
495        if (it != this->xmlportParamContainers_.end())
[5929]496            return it->second;
[5781]497        else
498            return 0;
499    }
500
501    /**
502        @brief Adds a new XMLPortParamContainer that loads a parameter of this class.
503        @param paramname The name of the parameter
504        @param container The container
505    */
506    void Identifier::addXMLPortParamContainer(const std::string& paramname, XMLPortParamContainer* container)
507    {
508        std::map<std::string, XMLPortParamContainer*>::const_iterator it = this->xmlportParamContainers_.find(paramname);
509        if (it != this->xmlportParamContainers_.end())
510        {
[6417]511            COUT(2) << "Warning: Overwriting XMLPortParamContainer in class " << this->getName() << '.' << std::endl;
[5781]512            delete (it->second);
513        }
514
515        this->xmlportParamContainers_[paramname] = container;
516    }
517
518    /**
519        @brief Returns a XMLPortObjectContainer that attaches an object to this class.
520        @param sectionname The name of the section that contains the attachable objects
521        @return The container
522    */
523    XMLPortObjectContainer* Identifier::getXMLPortObjectContainer(const std::string& sectionname)
524    {
525        std::map<std::string, XMLPortObjectContainer*>::const_iterator it = this->xmlportObjectContainers_.find(sectionname);
526        if (it != this->xmlportObjectContainers_.end())
[5929]527            return it->second;
[5781]528        else
529            return 0;
530    }
531
532    /**
533        @brief Adds a new XMLPortObjectContainer that attaches an object to this class.
534        @param sectionname The name of the section that contains the attachable objects
535        @param container The container
536    */
537    void Identifier::addXMLPortObjectContainer(const std::string& sectionname, XMLPortObjectContainer* container)
538    {
539        std::map<std::string, XMLPortObjectContainer*>::const_iterator it = this->xmlportObjectContainers_.find(sectionname);
540        if (it != this->xmlportObjectContainers_.end())
541        {
[6417]542            COUT(2) << "Warning: Overwriting XMLPortObjectContainer in class " << this->getName() << '.' << std::endl;
[5781]543            delete (it->second);
544        }
545
546        this->xmlportObjectContainers_[sectionname] = container;
547    }
548
549    /**
[1505]550        @brief Lists the names of all Identifiers in a std::set<const Identifier*>.
551        @param out The outstream
552        @param list The list (or set) of Identifiers
553        @return The outstream
554    */
555    std::ostream& operator<<(std::ostream& out, const std::set<const Identifier*>& list)
556    {
557        for (std::set<const Identifier*>::const_iterator it = list.begin(); it != list.end(); ++it)
[5929]558        {
559            if (it != list.begin())
[6417]560                out << ' ';
[5929]561            out << (*it)->getName();
562        }
[1505]563
564        return out;
565    }
[790]566}
Note: See TracBrowser for help on using the repository browser.