changeset 21:a60cbb7359dd

Window settings now come from options, and may use OpenGL (enabled/disabled at compile time). committer: Diggory Hardy <diggory.hardy@gmail.com>
author Diggory Hardy <diggory.hardy@gmail.com>
date Mon, 24 Mar 2008 17:53:28 +0000
parents 838577503598
children 249eb6620685
files codeDoc/jobs.txt data/conf/options.mtt mde/SDL.d mde/events.d mde/mde.d mde/options.d mde/scheduler/Init.d mde/scheduler/InitStage.d
diffstat 8 files changed, 111 insertions(+), 36 deletions(-) [+]
line wrap: on
line diff
--- a/codeDoc/jobs.txt	Sat Mar 22 16:22:59 2008 +0000
+++ b/codeDoc/jobs.txt	Mon Mar 24 17:53:28 2008 +0000
@@ -41,3 +41,4 @@
 
 
 Done (for git log message):
+Window settings now come from options.
\ No newline at end of file
--- a/data/conf/options.mtt	Sat Mar 22 16:22:59 2008 +0000
+++ b/data/conf/options.mtt	Mon Mar 24 17:53:28 2008 +0000
@@ -3,3 +3,12 @@
 <char[]|L10n="en-GB">
 <bool|useThreads=true>
 <int|logLevel=1>
+
+{video}
+<bool|noFrame=false>
+<bool|resizable=false>
+<bool|hardware=true>
+<bool|fullscreen=true>
+<int|height=1024>
+<int|width=1280>
+
--- a/mde/SDL.d	Sat Mar 22 16:22:59 2008 +0000
+++ b/mde/SDL.d	Mon Mar 24 17:53:28 2008 +0000
@@ -19,6 +19,7 @@
 
 import mde.scheduler.InitStage;
 import mde.input.joystick;
+import mde.options;
 
 import tango.util.log.Log : Log, Logger;
 import tango.stdc.stringz;
@@ -36,6 +37,8 @@
 }
 
 void initSdlAndGl() {   // init2 func
+    logger.trace ("init2: initSdlAndGl() started");
+    
     // Load SDL and GL dynamic libs
     try {
         DerelictSDL.load();
@@ -44,7 +47,7 @@
         logger.fatal ("Loading dynamic library failed:");
         logger.fatal (de.msg);
         
-        init2.setFailure ();
+        setInitFailure ();
         return;
     }
     logger.trace ("Derelict: loaded SDL and OpenGL");
@@ -55,7 +58,7 @@
         char* msg = SDL_GetError ();
         logger.fatal (msg ? fromStringz(msg) : "no reason available");
         
-        init2.setFailure ();
+        setInitFailure ();
         return;
     }
     
@@ -65,23 +68,56 @@
     // Must be called after SDL has been initialised, so cannot be a separate Init function.
     openJoysticks ();                   // after SDL init
     cleanup2.addFunc (&closeJoysticks);
+
+    logger.trace ("init2: initSdlAndGl() finished");
 }
 
 void setupWindow() {    // init4 func
+    logger.trace ("init4: setupWindow() started");
+    
+    // Window creation flags
+    /* NOTE: I'm getting an API mismatch error from the nvidia driver when using OpenGL,
+    * thus I've temporarily disabled it. */
+    version (MDE_OPENGL) uint flags = SDL_OPENGL;
+    else uint flags = 0;
+    if (Options.video.fullscreen) flags |= SDL_FULLSCREEN;
+    else {
+        if (Options.video.resizable) flags |= SDL_RESIZABLE;
+        if (Options.video.noFrame) flags |= SDL_NOFRAME;
+    }
+    if (Options.video.hardware) flags |= SDL_HWSURFACE | SDL_DOUBLEBUF;
+    else flags |= SDL_SWSURFACE;
+    
+    version (MDE_OPENGL) {
+    // OpenGL attributes
+    SDL_GL_SetAttribute(SDL_GL_RED_SIZE,    8);
+    SDL_GL_SetAttribute(SDL_GL_GREEN_SIZE,  8);
+    SDL_GL_SetAttribute(SDL_GL_BLUE_SIZE,   8);
+    SDL_GL_SetAttribute(SDL_GL_DEPTH_SIZE,  16);
+    SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER,1);
+    }
+    
     // Open a window
-    // FIXME: provide a way to re-set video mode and change settings
-    if (SDL_SetVideoMode (800, 600, 0, 0) is null) {   // Can't open in windows!!
+    if (SDL_SetVideoMode (Options.video.width, Options.video.height, 32, flags) is null) {
         logger.fatal ("Unable to set video mode:");
         char* msg = SDL_GetError ();
         logger.fatal (msg ? fromStringz(msg) : "no reason available");
         
-        init4.setFailure ();
+        setInitFailure ();
         return;
     }
+    
+    // Window-manager settings
+    SDL_WM_SetCaption (toStringz ("mde"), null);
+    // SDL_WM_GrabInput (use later)
+    
+    logger.trace ("init4: setupWindow() finished");
 }
 
-void cleanupSDL () {
+void cleanupSDL () {    // cleanup2 func
+    logger.trace ("cleanup2: cleanupSDL() started");
     SDL_Quit();
+    logger.trace ("cleanup2: cleanupSDL() finished");
 }
 
     /+ Load of info-printing stuff (currently doesn't have a use)
--- a/mde/events.d	Sat Mar 22 16:22:59 2008 +0000
+++ b/mde/events.d	Mon Mar 24 17:53:28 2008 +0000
@@ -36,14 +36,18 @@
 }
 
 void initInput () { // init2 func
+    logger.trace ("init2: initInput() started");
+    
     try {
         global.input = new Input();
         global.input.loadConfig ();         // (may also create instance)
                 
         Scheduler.perFrame (&pollEvents);
     } catch (Exception e) {
-        init2.setFailure ();                // must clean up properly
+        setInitFailure ();                // must clean up properly
     }
+    
+    logger.trace ("init2: initInput() finished");
 }
 
 void pollEvents (double) {
--- a/mde/mde.d	Sat Mar 22 16:22:59 2008 +0000
+++ b/mde/mde.d	Mon Mar 24 17:53:28 2008 +0000
@@ -44,7 +44,8 @@
     //BEGIN Initialisation
     Logger logger = Log.getLogger ("mde.mde");
     logger.info ("Starting mde...");
-        
+    
+    scope Init init;
     try {
         init = new Init();	// initialisation
     } catch (InitException e) {
--- a/mde/options.d	Sat Mar 22 16:22:59 2008 +0000
+++ b/mde/options.d	Mon Mar 24 17:53:28 2008 +0000
@@ -79,6 +79,7 @@
     //BEGIN Static
     // Each individual section
     static OptionsMisc  misc;
+    static OptionsVideo video;
     
     /* Load/save options from file.
     *
@@ -88,7 +89,8 @@
     static void load () {
         // Create all uncreated sections now, so that if we return early they are still created.
         if (misc is null) misc = new OptionsMisc;
-        
+        if (video is null) video = new OptionsVideo;
+                
         // Check it exists (if not it should still be created on exit).
         // Don't bother checking it's not a folder, because it could still be a block or something.
         if (!confDir.exists (fileName)) return;
@@ -100,6 +102,7 @@
                 /* Recognise each defined section, and return null for unrecognised sections. */
                 
                 if (id == cast(ID) "misc") return misc;
+                else if (id == cast(ID) "video") return video;
                 else return null;
             };
             reader.read;
@@ -108,12 +111,11 @@
             logger.error (e.msg);
             throw new optionsLoadException ("Loading aborted: mergetag exception");
         }
-        
-        if (misc is null) throw new optionsLoadException ("Loading failed: section \"misc\" not found");
     }
     static void save () {
         DataSet ds = new DataSet();
         ds.sec[cast(ID) "misc"] = misc;
+        ds.sec[cast(ID) "video"] = video;
         
         IWriter writer;
         try {
@@ -146,3 +148,17 @@
         optsInt     = ["logLevel":&logLevel];
     }
 }
+
+/** All video options. */
+class OptionsVideo : Options {
+    int width, height;  // screen/window dimensions
+    bool fullscreen;
+    bool resizable;     // when not fullscreen, window can be resized
+    bool noFrame;       // when not fullscreen, don't draw the window decorations
+    bool hardware;      // use a hardware surface. Relevant with OpenGL?
+    
+    this () {
+        optsBool    = ["fullscreen"[]:&fullscreen, "hardware":&hardware, "noFrame":&noFrame, "resizable":&resizable];
+        optsInt     = ["height"[]:&height, "width":&width];
+    }
+}
--- a/mde/scheduler/Init.d	Sat Mar 22 16:22:59 2008 +0000
+++ b/mde/scheduler/Init.d	Mon Mar 24 17:53:28 2008 +0000
@@ -84,9 +84,6 @@
 {
 }
 
-// Global instance, since called init functions need to interact:
-scope Init init;
-
 /**
  * Init class
  *
@@ -138,22 +135,26 @@
         * Current method is to try using threads, and on failure assume no threads were actually
         * created and run functions in a non-threaded manner. */
         
-        try {   // init2
-            cleanupStages ~= &cleanup2; // add appropriate cleanup stage
-            
+        // init2
+        cleanupStages ~= &cleanup2;     // add appropriate cleanup stage
+        try {
+            logger.trace ("Init: init2");
             if (runStageThreaded (init2)) runStageForward (init2);
         }
         catch (InitStageException) {    // This init stage failed.
+            logger.trace ("Init: init2 failed");
             runCleanupStages();
             throw new InitException ("Initialisation failed during stage init2");
         }
         
-        try {   // init4
-            cleanupStages ~= &cleanup4; // add appropriate cleanup stage
-            
+        // init4
+        cleanupStages ~= &cleanup4;     // add appropriate cleanup stage
+        try {
+            logger.trace ("Init: init4");
             if (runStageThreaded (init4)) runStageForward (init4);
         }
         catch (InitStageException) {    // This init stage failed.
+            logger.trace ("Init: init4 failed");
             runCleanupStages();
             throw new InitException ("Initialisation failed during stage init4");
         }
@@ -181,24 +182,25 @@
     private static {
         /* The following three functions, runStage*, each run all functions in a stage in some order,
         * catching any exceptions thrown by the functions (although this isn't guaranteed for threads),
-        * and throw an InitStageException on failure. */
+        * and throw an InitStageException on initFailure. */
     
         const UFE = "Unhandled exception from Init function:";
         /* Runs all functions consecutively, first-to-last.
         * If any function fails, halts immediately. */
         void runStageForward (InitStage s) {
             foreach (func; s.funcs) {
-                if (s.failure) break;
+                if (initFailure) break;
                 try {
                     func();
                 } catch (Exception e) {
                     logger.fatal (UFE);
                     logger.fatal (e.msg);
                 
-                    s.setFailure();
+                    setInitFailure();
                 }
             }
-            if (s.failure) throw new InitStageException;    // Problem running; abort and cleanup from here.
+            
+            if (initFailure) throw new InitStageException;    // Problem running; abort and cleanup from here.
         }
         /* Runs all functions consecutively, last-to-first.
         * If any function fails, continue until all have been run. */
@@ -210,10 +212,10 @@
                     logger.fatal (UFE);
                     logger.fatal (e.msg);
                 
-                    s.setFailure();
+                    setInitFailure();
                 }
             }
-            if (s.failure) throw new InitStageException;    // Problem running; abort and cleanup from here.
+            if (initFailure) throw new InitStageException;    // Problem running; abort and cleanup from here.
         }
         /* Tries running functions in a threaded way. Returns false if successful, true if not but
         * functions should be run without threads. */
@@ -247,11 +249,11 @@
                     logger.fatal ("Unhandled exception from Init function:");
                     logger.fatal (e.msg);
                 
-                    s.setFailure ();        // abort (but join other threads first)
+                    setInitFailure ();        // abort (but join other threads first)
                 }
             }
-        
-            if (s.failure) throw new InitStageException;    // Problem running; abort and cleanup from here.
+            
+            if (initFailure) throw new InitStageException;    // Problem running; abort and cleanup from here.
             return false;                   // Done successfully
         }
     }
--- a/mde/scheduler/InitStage.d	Sat Mar 22 16:22:59 2008 +0000
+++ b/mde/scheduler/InitStage.d	Mon Mar 24 17:53:28 2008 +0000
@@ -21,6 +21,12 @@
 */
 module mde.scheduler.InitStage;
 
+import tango.util.log.Log : Log, Logger;
+private Logger logger;
+static this() {
+    logger = Log.getLogger ("mde.scheduler.InitStage");
+}
+
 /** Represents all functions to be called for a particular init stage.
 *
 * No code is included here to run the functions intentionally, to keep dependancies minimal.
@@ -40,13 +46,7 @@
         funcs ~= f;
     }
     
-    /** Should be called by an init function when a failure occurs. */
-    void setFailure () {
-        synchronized failure = true;
-    }
-    
-    package InitFunction[]  funcs   = [];
-    package bool            failure = false;
+    package InitFunction[] funcs = [];
 }
 
 /** Init can be divided up into these stages, each run in order:
@@ -87,3 +87,9 @@
 InitStage init4;    /// ditto
 InitStage cleanup2; /// ditto
 InitStage cleanup4; /// ditto
+
+/** Should be called by an init function when a failure occurs. */
+void setInitFailure () {
+    initFailure = true;
+}
+package bool initFailure = false;