Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

Ignore:
Timestamp:
Oct 4, 2015, 9:12:21 PM (9 years ago)
Author:
landauf
Message:

merged branch core7 back to trunk

Location:
code/trunk
Files:
2 edited

Legend:

Unmodified
Added
Removed
  • code/trunk

  • code/trunk/src/orxonox/Level.cc

    r9667 r10624  
    3535#include "core/XMLFile.h"
    3636#include "core/XMLPort.h"
     37#include "core/module/PluginReference.h"
    3738
    3839#include "infos/PlayerInfo.h"
     
    4950        RegisterObject(Level);
    5051
     52        this->setLevel(WeakPtr<Level>(this)); // store a weak-pointer to itself (a strong-pointer would create a recursive dependency)
    5153
    5254        this->registerVariables();
     
    6365
    6466            if (this->xmlfile_)
    65                 Loader::unload(this->xmlfile_);
     67                Loader::getInstance().unload(this->xmlfile_);
     68
     69            this->unloadPlugins();
    6670        }
    6771    }
     
    7175        SUPER(Level, XMLPort, xmlelement, mode);
    7276
     77        XMLPortParam(Level, "plugins",  setPluginsString,  getPluginsString,  xmlelement, mode);
    7378        XMLPortParam(Level, "gametype", setGametypeString, getGametypeString, xmlelement, mode).defaultValues("Gametype");
    7479
     
    95100        this->xmlfile_ = new XMLFile(mask, this->xmlfilename_);
    96101
    97         Loader::open(this->xmlfile_);
     102        Loader::getInstance().load(this->xmlfile_);
    98103    }
    99104
     
    105110            Template::getTemplate(*it)->applyOn(this);
    106111        }
     112    }
     113
     114    void Level::setPluginsString(const std::string& pluginsString)
     115    {
     116        // unload old plugins
     117        this->unloadPlugins();
     118
     119        // load new plugins
     120        this->pluginsString_ = pluginsString;
     121        SubString tokens(pluginsString, ",");
     122        for (size_t i = 0; i < tokens.size(); ++i)
     123            this->plugins_.push_back(new PluginReference(tokens[i]));
     124    }
     125
     126    void Level::unloadPlugins()
     127    {
     128        // use destroyLater() - this ensures that plugins are not unloaded too early.
     129        // Note: When a level gets unloaded, the Level object is usually the last object that gets destroyed. This is because all other
     130        //       objects inside a level have a StrongPtr (in BaseObject) that references the Level object. This means that the Level
     131        //       object is only destroyed, when all StrongPtrs that pointed to it were destroyed. But at the time when the last StrongPtr
     132        //       is destroyed, the other object is not yet fully destroyed because the StrongPtr is destroyed in ~BaseObject (and this
     133        //       means that e.g. ~Identifiable was not yet called for this object). This means that technically there are still other
     134        //       objects alive when ~Level is called. This is the reason why we cannot directly destroy() the Plugins - instead we need
     135        //       to call destroyLater() to ensure that no instances from this plugin exist anymore.
     136        for (std::list<PluginReference*>::iterator it = this->plugins_.begin(); it != this->plugins_.end(); ++it)
     137            (*it)->destroyLater();
     138        this->plugins_.clear();
    107139    }
    108140
     
    121153
    122154        Gametype* rootgametype = orxonox_cast<Gametype*>(identifier->fabricate(this));
    123         this->setGametype(rootgametype);
    124 
    125         for (std::list<BaseObject*>::iterator it = this->objects_.begin(); it != this->objects_.end(); ++it)
    126             (*it)->setGametype(rootgametype);
     155
     156        // store a weak-pointer to the gametype to avoid a circular dependency between this level and the gametype (which has a strong-reference on this level)
     157        this->setGametype(WeakPtr<Gametype>(rootgametype));
     158
     159        rootgametype->init(); // call init() AFTER the gametype was set
    127160
    128161        if (LevelManager::exists())
     
    134167    {
    135168        this->objects_.push_back(object);
    136         object->setGametype(this->getGametype());
    137         object->setLevel(this);
    138169    }
    139170
     
    170201    {
    171202        orxout(internal_info) << "player entered level (id: " << player->getClientID() << ", name: " << player->getName() << ')' << endl;
    172         player->setGametype(this->getGametype());
     203        player->switchGametype(this->getGametype());
    173204    }
    174205
     
    176207    {
    177208        orxout(internal_info) << "player left level (id: " << player->getClientID() << ", name: " << player->getName() << ')' << endl;
    178         player->setGametype(0);
     209        player->switchGametype(0);
    179210    }
    180211}
Note: See TracChangeset for help on using the changeset viewer.