How to keep a registry of variable parameter functions

106 Views Asked by At

I'll explain what I'm trying to do:

I'm working on a game. In order to handle the graphics, I have a stack of ScreenLayers that I update and draw. The ScreenLayer is responsible for providing visualization for some aspect of the game (inventory, party overview, wolrd map, tilemap, etc.)

In order to handle screen transitions, I want to create a registry of functions for the various screen types, and then the screens would call into this registry to push and pop screen layers from the draw stack. (i.e. when on a tile map, if you push start, the tile map will call into the registry and tell it to create a root start menu screen. The start menu will be pushed overtop of the tile map and will take control of the input until the start menu is closed, at which point it pops itself off the stack and gives control back to the layer that called it)

The problem is that each screen layer needs a different set of parameters to construct it

i.e.

CharacterOverviewScreen(boost::shared_ptr<Engine>& engine, const std::string& rmlDoc, Game::Character::Party* party);

vs.

MapViewLayer(boost::shared_ptr<Engine>& engine, const std::string &mapFile, const sf::Vector2f &startPos, const std::string &name, int layerID, bool draw, Game::Character::Party* party);

Ideally I'd like each screen to be able register a small function that wraps up my screenlayer and makes it into a proper ScreenStack

i.e.

ScreenStack CharacterOverviewStackCreator(boost::shared_ptr<Engine>& engine, const std::string& stackName const std::string& rmlDoc, Game::Character::Party* party)
{
    return ScreenStack(stackName, engine->GetUID(), boost:shared_ptr<ScreenLayer>(new CharacterOverviewScreen(engine, rmlDoc, party)));
}

I need a way to register ScreenStack creation functions that take in variadic parameters, and if at all possible, to allow each ScreenLayer derived class to register this stack creation function itself.

My initial thought was to try something like this:

typedef boost::function<ScreenStack (boost::shared_ptr<Engine>& engine, const std::string stackName, ...)> ScreenCreationFunction;

class ScreenManager : public AnimatedDraw
{
public:
    ScreenManager(boost::shared_ptr<Engine>& engine);
    bool RegisterScreenMakerFunction(const ScreenCreationFunction& creatorFunction, bool overwriteExisting = false);
    ScreenCreationFunction& GetScreenMakerFunction(const std::string& makerName);

    ScreenStack MakeStack(const std::string& makerFunction, const std::string, const std::vector<std::string>& TryToCopyStacks, ...);

protected:
private:
    boost::shared_ptr<Engine> engine;
    boost::unordered_map<std::string, ScreenCreationFunction> ScreenMakerFunctions;
};

However, boost::function doesn't work with the "..." from <cstdarg>. Additionally, I have no way that I can see to pre-register screens before I try and instantiate them.

I considered switching to some generic void function pointer over boost::function, but if I can avoid doing this I'd like to. I think it's possible to do the stack registration using the preprocessor, but I don't have alot of expereience with the preprocessor so I have no idea how to do this.

I was considering using a factory to create the screen stack, but I'll have to keep updating the factory functions as I add more and more screenlayer types and various parameters, so this doesn't seem like a very good solution.

If someone could help me with this, it'd be greatly appreciated. If I'm not being clear about something, let me know

0

There are 0 best solutions below