diff mde/setup/InitStage.d @ 85:56c0ddd90193

Intermediate commit (not stable). Changes to init system.
author Diggory Hardy <diggory.hardy@gmail.com>
date Thu, 11 Sep 2008 11:33:51 +0100
parents mde/setup/init2.d@e0f1ec7fe73a
children 4d5d53e4f881
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/mde/setup/InitStage.d	Thu Sep 11 11:33:51 2008 +0100
@@ -0,0 +1,110 @@
+/* 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 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;      // NOTE - little hack to read as a 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 {
+        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) {
+        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) {
+        StageState delegate() i,c;
+        i.funcptr = init;
+        c.funcptr = cleanup;
+        addInitStage (name, i, c, 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).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 () {
+    imde.input.loadConfig ("input");
+    
+    // Quit on escape. NOTE: quit via SDL_QUIT event is handled completely independently!
+    imde.input.addButtonCallback (cast(Input.inputID) 0x0u, delegate void(Input.inputID i, bool b) {
+        if (b) {
+            logger.info ("Quiting...");
+            imde.run = false;
+        }
+    } );
+    return StageState.ACTIVE;
+}