view mde/setup/InitStage.d @ 132:264028f4115a

Cleaned up mde.imde and a couple of widget functions. New mde.menus module to add default menus. The input singleton is now created in mde.input.Input instead of mde.imde.
author Diggory Hardy <diggory.hardy@gmail.com>
date Fri, 23 Jan 2009 14:59:05 +0000
parents 1655693702fc
children
line wrap: on
line source

/* LICENSE BLOCK
Part of mde: a Modular D game-oriented Engine
Copyright © 2007-2008 Diggory Hardy

This program is free software: you can redistribute it and/or modify it under the terms
of the GNU General Public License as published by the Free Software Foundation, either
version 2 of the License, or (at your option) any later version.

This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
See the GNU General Public License for more details.

You should have received a copy of the GNU General Public License
along with this program.  If not, see <http://www.gnu.org/licenses/>. */

/******************************************************************************
 * The infrastructure for handling external startup/shutdown code.
 *****************************************************************************/
module mde.setup.InitStage;

public import mde.setup.exception;
import mde.util;

import tango.util.container.HashMap;
import tango.util.log.Log : Log, Logger;

    // use as hash type for better performance than char[]
    alias uint StageName;
    StageName toStageName (char[4] x) {
        return *cast(uint*) x.ptr;      // convert to a unique uint
    }
    
    /** Initialization and cleanup functions for one stage.
     * 
     * The init and cleanup functions should return the new StageState. Returning ERROR does not
     * indicate that the program should abort but that the module in question is not usable and
     * that init & cleanup should not be called. Throwing an exception sets the state to ERROR (or
     * the value passed to an InitStageException) and indicates that the program should abort.
     * If the program aborts, all stages with state ACTIVE have their cleanup run (as with a normal
     * shutdown).
     * 
     * Not setting a cleanup function will result in the state being left at ACTIVE on shutdown, so
     * if a second initialization occurs (not currently possible), init will not be re-run. */
    struct InitStage {
        char[] name;                    // used for debug-mode trace messages about stages
        StageState delegate() init;     // the initialization function
        StageState delegate() cleanup;  // the associated cleanup function
        StageName[] depends;            // anything function depends on completing before its run
        StageName[] rdepends;           // reverse dependencies, set during init
        StageState state = StageState.INACTIVE;
    }
    
    /// Add a stage to be initialized.
    void addInitStage (char[4] name, InitStage* stage) {
        stage.name = name;
        stages[toStageName(name)] = stage;
    }
    /// Add a stage to be initialized.
    void addInitStage (char[4] name, StageState function() init, StageState function() cleanup = null, char[4][] depends = null) {
        addInitStage (name, toDg(init), toDg(cleanup), depends);
    }
    /// Add a stage to be initialized.
    void addInitStage (char[4] name, StageState delegate() init, StageState delegate() cleanup = null, char[4][] depends = null) {
        InitStage* stage = new InitStage;
        stage.name = name;
        (*stage).init = init;
        stage.cleanup = cleanup;
        stage.depends.length = depends.length;
        foreach (i,d; depends)
            stage.depends[i] = toStageName(d);
        stages[toStageName(name)] = stage;
    }
    
    package HashMap!(StageName,InitStage*) stages;
    
    static this () {
        stages = new typeof(stages);
        logger = Log.getLogger ("mde.setup.InitStage");
    }
    Logger logger;



/******************************************************************************
 * Initialization functions.
 *****************************************************************************/
import imde = mde.imde;
import mde.input.Input;
import mde.setup.Screen;
import mde.input.joystick;
import mde.font.font;

static this() {
    addInitStage ("Inpt", &initInput);
    addInitStage ("SSDL", &Screen.init, &Screen.cleanup );
    addInitStage ("SJoy", &openJoysticks, &closeJoysticks, ["SSDL"]);
    addInitStage ("SWnd", &Screen.initWindow, null, ["SSDL"]);
    addInitStage ("Font", &FontStyle.initialize, &FontStyle.cleanup);
}

StageState initInput () {
    Input.singleton.loadConfig ("input");
    
    // Quit on escape.
    Input.singleton.addButtonCallback (cast(Input.inputID) 0x0u, delegate void(Input.inputID i, bool b) {
        if (b) {
            debug logger.trace ("Quit (from Esc)");
            imde.run = false;
        }
    } );
    return StageState.ACTIVE;
}