changeset 86:79d816b3e2d2

New InitStage system, Screen & Screen.Drawable, separate testing and guiDemo binaries. This (and the previous) commit are the result of several quite significant changes to mde. All the unittests run, but it hasn't had a huge amount of testing so don't be surprised if bugs show up.
author Diggory Hardy <diggory.hardy@gmail.com>
date Fri, 12 Sep 2008 17:36:14 +0100
parents 56c0ddd90193
children 2212285f714c
files codeDoc/jobs.txt mde/file/deserialize.d mde/file/mergetag/Writer.d mde/file/serialize.d mde/font/FontTexture.d mde/font/font.d mde/gui/WidgetManager.d mde/input/Config.d mde/input/joystick.d mde/lookup/Options.d mde/mde.d mde/setup/Init.d mde/setup/Screen.d
diffstat 13 files changed, 61 insertions(+), 93 deletions(-) [+]
line wrap: on
line diff
--- a/codeDoc/jobs.txt	Thu Sep 11 11:33:51 2008 +0100
+++ b/codeDoc/jobs.txt	Fri Sep 12 17:36:14 2008 +0100
@@ -3,10 +3,7 @@
 
 
 In progress:
-why is nothing drawn until a resize? seems to be working now (??)
-why isn't font texture drawn in mde?
-why does mde&guiDemo hang on exit, only if no resize occurred?
-wierd things with options.mtt (font section getting output twice)
+Sometimes nothing is drawn until a resize, and fonts are blocks? External bug?
 CircularIterator
 unittest again!
 
--- a/mde/file/deserialize.d	Thu Sep 11 11:33:51 2008 +0100
+++ b/mde/file/deserialize.d	Fri Sep 12 17:36:14 2008 +0100
@@ -525,7 +525,6 @@
             dg();
         } catch (Exception e) {
             r = true;
-            logger.trace ("Exception caught: "~e.msg);
         }
         return r;
     }
--- a/mde/file/mergetag/Writer.d	Thu Sep 11 11:33:51 2008 +0100
+++ b/mde/file/mergetag/Writer.d	Fri Sep 12 17:36:14 2008 +0100
@@ -162,8 +162,6 @@
     public this (char[] path, DataSet ds = null) {
         _path = path;
         _dataset = ds;
-        foreach (i,s; _dataset.sec)
-            debug logger.trace ("sec ID length: {}", i.length);
     }
 //END CTOR / DTOR
     
@@ -180,38 +178,28 @@
         if (!_dataset) throwMTErr ("write(): no Dataset available to write from!", new MTNoDataSetException ());
         
         try {
-            debug logger.trace ("W.w: 1");
             FileConduit conduit;	// actual conduit; don't use directly when there's content in the buffer
             IBuffer buffer;		// write strings directly to this (use opCall(void[]) )
             
-            debug logger.trace ("W.w: 2");
             // Open a conduit on the file:
             conduit = new FileConduit (_path, FileConduit.WriteCreate);
             scope(exit) conduit.close();
             
-            debug logger.trace ("W.w: 3");
             buffer = new Buffer(conduit);	// And a buffer
             scope(exit) buffer.flush();
             
-            debug logger.trace ("W.w: 4");
             // Write the header:
             buffer ("{MT" ~ MTFormatVersion.CurrentString ~ "}" ~ Eol);
-            debug logger.trace ("W.w: 5");
             if (_dataset.header !is null) writeSection (buffer, _dataset.header);
         
-            debug logger.trace ("W.w: 6");
             // Write the rest:
             foreach (ID id, IDataSection sec; _dataset.sec) {
-                debug logger.trace ("W.w: 71");
                 writeSectionIdentifier (buffer, id);
-                debug logger.trace ("W.w: 72");
                 writeSection (buffer, sec);
             }
             
-            debug logger.trace ("W.w: 8");
             buffer.flush();
             
-            debug logger.trace ("W.w: 9");
         }
         catch (IOException e) {
             throwMTErr ("Error writing to file: " ~ e.msg, new MTFileIOException);
@@ -222,14 +210,8 @@
     }
         
     private void writeSectionIdentifier (IBuffer buffer, ID id) {
-        debug logger.trace ("W.wSI: 0");
-        debug logger.trace ("W.wSI: id ({})",id.length);
-        debug logger.trace ("W.wSI: Eol ({})",Eol.length);
         char[] tp = "{" ~ cast(char[])id ~ "}" ~ Eol;
-        debug logger.trace ("W.wSI: 0.1");
-        debug logger.trace ("W.wSI: string ({}): {}",tp.length, tp);
         buffer (tp);
-        debug logger.trace ("W.wSI: 1");
     }
     
     private void writeSection (IBuffer buffer, IDataSection sec) {
--- a/mde/file/serialize.d	Thu Sep 11 11:33:51 2008 +0100
+++ b/mde/file/serialize.d	Fri Sep 12 17:36:14 2008 +0100
@@ -311,7 +311,6 @@
             dg();
         } catch (Exception e) {
             r = true;
-            logger.trace ("Exception caught: "~e.msg);
         }
         return r;
     }
--- a/mde/font/FontTexture.d	Thu Sep 11 11:33:51 2008 +0100
+++ b/mde/font/FontTexture.d	Fri Sep 12 17:36:14 2008 +0100
@@ -329,7 +329,6 @@
         glBlendFunc (GL_ONE, GL_ONE_MINUS_SRC_COLOR);
         float[4] Cc = [ 1.0f, 1f, 1f, 1f ];
         glTexEnvfv(GL_TEXTURE_ENV, GL_TEXTURE_ENV_COLOR, Cc.ptr);
-        glColor3f (1f, 0f, 0f);
         
         glBegin (GL_QUADS);
         glTexCoord2f (0f, 0f);	glVertex2i (0, 0);
--- a/mde/font/font.d	Thu Sep 11 11:33:51 2008 +0100
+++ b/mde/font/font.d	Fri Sep 12 17:36:14 2008 +0100
@@ -130,13 +130,10 @@
         //FIXME: don't use GC for FontStyle resources
         /** Cleanup: delete all fonts. */
         StageState cleanup () {
-            // Clear loaded fonts:
+            // Clear loaded fonts (each has an FT_Face object needing to be freed):
             foreach (fs; fonts)
                 delete fs;
-            fonts = null;
-            delete fallback;
             
-            delete fontTex;     // clear texture
             FT_Done_FreeType (library); // free the library
             
             return StageState.INACTIVE;
@@ -226,7 +223,10 @@
      *
      * This function will only actually update the cache if it is invalid, caused either by the
      * font being changed or if cache.cacheVer < 0. */
-    void updateBlock (char[] str, ref TextBlock cache) {
+    void updateBlock (char[] str, ref TextBlock cache)
+    in {
+        debug assert (face, "FontStyle: face is null");
+    } body {
         try {
             fontTex.updateCache (face, str, cache);
         } catch (Exception e) {
@@ -259,7 +259,10 @@
      * than this cache only serves as a small optimisation. However, the only way to get the size
      * of a text block is to use a TextBlock cache and update it, either with this function or with
      * the updateBlock function. */
-    void textBlock (int x, int y, char[] str, ref TextBlock cache, Colour col) {
+    void textBlock (int x, int y, char[] str, ref TextBlock cache, Colour col)
+    in {
+        debug assert (face, "FontStyle: face is null");
+    } body {
         try {
             fontTex.drawCache (face, str, cache, x, y, col);
         } catch (Exception e) {
@@ -267,7 +270,10 @@
         }
     }
     /** ditto */
-    void textBlock (int x, int y, char[] str, Colour col) {
+    void textBlock (int x, int y, char[] str, Colour col)
+    in {
+        debug assert (face, "FontStyle: face is null");
+    } body {
         try {
             // Using the cache method for one-time use is slightly less than optimal, but doing so
             // isn't really recommended anyway (and maintaining two versions of fontTex.drawText
@@ -283,7 +289,10 @@
      *
      * Set the alpha by calling glColor*() first. See FontTexture.drawCacheA()'s documentation for
      * details. */
-    void textBlockA (int x, int y, char[] str, ref TextBlock cache, Colour col) {
+    void textBlockA (int x, int y, char[] str, ref TextBlock cache, Colour col) 
+    in {
+        debug assert (face, "FontStyle: face is null");
+    } body {
         try {
             fontTex.drawCacheA (face, str, cache, x, y, col);
         } catch (Exception e) {
@@ -297,9 +306,7 @@
     }
     
     ~this () {
-        debug logger.trace ("{}.~this: start", this);
         FT_Done_Face (face);
-        debug logger.trace ("{}.~this: done", this);
     }
     
 private:
--- a/mde/gui/WidgetManager.d	Thu Sep 11 11:33:51 2008 +0100
+++ b/mde/gui/WidgetManager.d	Fri Sep 12 17:36:14 2008 +0100
@@ -50,7 +50,7 @@
  * 
  * Aside from the IWidgetManager methods, this class should be thread-safe.
  *************************************************************************************************/
-class WidgetManager : WidgetLoader, Screen.Drawable {
+class WidgetManager : WidgetLoader, Screen.IDrawable {
     /** Construct a new widget manager.
      * 
      * params:
@@ -74,7 +74,6 @@
     
     /** Draw the gui. */
     void draw() {
-        debug logger.trace ("drawing; w,h = {},{}",w,h);
         synchronized(mutex)
             if (child)
                 child.draw;
@@ -117,7 +116,7 @@
     }
     
     
-    void sizeEvent (int nw, int nh) {   // Drawable function
+    void sizeEvent (int nw, int nh) {   // IDrawable function
         mutex.lock;
         scope(exit) mutex.unlock;
         
--- a/mde/input/Config.d	Thu Sep 11 11:33:51 2008 +0100
+++ b/mde/input/Config.d	Fri Sep 12 17:36:14 2008 +0100
@@ -161,16 +161,6 @@
             if (c) configs[i] = c;		// Check, because we don't want null entries in configs
             else debug logger.error ("Ended up with DataSection of wrong type; this should never happen.");
         }
-        
-        debug (MDE_CONFIG_DUMP) {
-            logger.trace ("Loaded {} config sections.", configs.length);
-            foreach (id, cfg; configs) {
-                logger.trace ("Section " ~ id ~
-                ":\n\tbutton:\t\t" ~ parseFrom!(uint[][][uint])(cfg.button) ~
-                "\n\taxis:\t\t" ~ parseFrom!(uint[][][uint])(cfg.axis) ~
-                "\n\trelMotion:\t" ~ parseFrom!(uint[][][uint])(cfg.relMotion) );
-            }
-        }
     }
     
     private this() {}	// Private since this class should only be created from here.
--- a/mde/input/joystick.d	Thu Sep 11 11:33:51 2008 +0100
+++ b/mde/input/joystick.d	Fri Sep 12 17:36:14 2008 +0100
@@ -54,9 +54,7 @@
 StageState closeJoysticks () {
     foreach (js; joysticks) {
         // FIXME: This sometimes causes a SIGSEGV (Address boundary error) when init fails.
-        debug logger.trace ("Closing joysticks (this sometimes fails when mde exits prematurely)");
         if(js !is null) SDL_JoystickClose(js);	// only close if successfully opened
-        debug logger.trace ("Done closing joysticks");
     }
     return StageState.INACTIVE;
 }
--- a/mde/lookup/Options.d	Thu Sep 11 11:33:51 2008 +0100
+++ b/mde/lookup/Options.d	Fri Sep 12 17:36:14 2008 +0100
@@ -136,7 +136,6 @@
             assert (c !is null);    // Instance must be created before calling addOptionsClass
             assert (((cast(ID) i) in subClasses) is null);  // Don't allow a silent replacement
         } body {
-            debug logger.trace ("Adding Options subClass: "~i);
             subClasses[cast(ID) i] = c;
         }
     
@@ -169,27 +168,18 @@
         }
         void save () {
             if (!changed) return;   // no changes to save
-            // Types:
-            // interface IDataSection {...}
-            // class Options {...}
-            // alias char[] ID;
-            // IDataSection[ID] ds.sec;
-            // Options[ID] subClasses;
+            debug logger.trace ("Saving options...");
+            
             DataSet ds = new DataSet();
-            foreach (id, subOpts; subClasses) {
+            foreach (id, subOpts; subClasses)
                 ds.sec[id] = subOpts.optionChanges;
-                debug logger.trace ("Saving options section: "~id);
-            }
-            foreach (i,s; ds.sec)
-                debug logger.trace ("sec ID length: {}", i.length);
-            debug logger.trace ("0");
             
             // Read locally-stored options
             try {
                 IReader reader;
                 reader = confDir.makeMTReader (fileName, PRIORITY.HIGH_ONLY, ds);
                 reader.dataSecCreator = delegate IDataSection(ID id) {
-                    debug logger.trace ("New section to save ignored: "~id);
+                    debug logger.warn ("New section appearing in options.mtt during save (ignored & overwritten): "~id);
                     return null;    // All recognised sections are already in the dataset.
                 };
                 reader.read;
@@ -201,15 +191,9 @@
             }
         
             try {
-                debug logger.trace ("1");
                 IWriter writer;
-                foreach (i,s; ds.sec)
-                    debug logger.trace ("sec ID length: {}", i.length);
-                debug logger.trace ("2");
-                writer = confDir.makeMTWriter (fileName, ds);   // FIXME - sometimes SIGSEGV
-                debug logger.trace ("3");
-                writer.write(); // FIXME - this is causing hang at exit!
-                debug logger.trace ("4");
+                writer = confDir.makeMTWriter (fileName, ds);
+                writer.write();
             } catch (Exception e) {
                 logger.error ("Saving options aborted: "~e.msg);
             }
--- a/mde/mde.d	Thu Sep 11 11:33:51 2008 +0100
+++ b/mde/mde.d	Fri Sep 12 17:36:14 2008 +0100
@@ -30,22 +30,45 @@
 import tango.core.Thread : Thread;	// Thread.sleep()
 import tango.time.Clock;                // Clock.now()
 import tango.util.log.Log : Log, Logger;
-debug (mdeUnitTest) {
+debug (mdeUnitTest) {                   // These modules contain unittests which wouldn't be run otherwise.
     import mde.file.ssi;
     import mde.file.mergetag.mdeUT;
 }
 
+//BEGIN A simple drawable to print a message in the window.
+import mde.font.font;
+class SimpleDrawable : Screen.IDrawable {
+    this () {
+        msg = "Welcome to mde.\nThis executable is only for testing, and\nas such doesn't do anything interesting.";
+        debug msg ~= "\nRunning in debug mode.";
+        font = FontStyle.get("default");// get the default or fallback font
+    }
+    void sizeEvent (int,int) {};        // Don't care what the size is
+    void draw () {
+        font.textBlock (16,32, msg, textCache, Colour.WHITE);
+    }
+    char[] msg;
+    FontStyle font;
+    TextBlock textCache;
+}
+//END A simple drawable to print a message in the window.
+
+
 int main(char[][] args)
 {
+    Logger logger = Log.getLogger ("mde.mde");
+    
     // If compiled with unittests, notify that they completed and exit:
     debug (mdeUnitTest) {
-        Logger logger = Log.getLogger ("mde.mde");
         logger.info ("Compiled unittests have completed; terminating.");
         return 0;
     }
     
     scope Init init = new Init(args);	// initialize mde
     
+    // Note: must create the drawable after init, since it uses font (initialized in init).
+    Screen.addDrawable (new SimpleDrawable);    // a drawable to print a message.
+    
     // Make sure pollInterval has a sane value. FIXME: get Options class to enforce range
     if (miscOpts.pollInterval !<= 1.0 || miscOpts.pollInterval !>= 0.0)
         miscOpts.set!(double) ("pollInterval", 0.01);
--- a/mde/setup/Init.d	Thu Sep 11 11:33:51 2008 +0100
+++ b/mde/setup/Init.d	Fri Sep 12 17:36:14 2008 +0100
@@ -257,7 +257,6 @@
                 }
             }
         }
-        debug logger.trace ("Added {} init/cleanup stages", toRun.size);
         int numWorking = miscOpts.numThreads;
         bool abortInit = false;
         Mutex toRunM = new Mutex;       // synchronization on toRun, numWorking
@@ -275,7 +274,6 @@
          *      if no other threads are working, notify waiting threads and terminate (finished)
          * When notified, threads start at 1. */
         void initThreadFct () {
-            debug logger.trace ("initThreadFct: starting");
             try {       // created as a thread - must not throw exceptions
             InitStage* stage;
             
@@ -346,7 +344,6 @@
                 abortInit = true;
             }
             toRunC.notifyAll(); // Most likely if we're exiting, we should make sure others aren't waiting.
-            debug logger.trace ("initThreadFct: returning");
             return;
         }
         
@@ -396,8 +393,6 @@
     }
     
     debug (mdeUnitTest) unittest {
-        logger.trace ("Starting unittest");
-        
         auto realInit = stages;         // backup the real init stages
         stages = new typeof(stages);    // an empty test-bed
         
--- a/mde/setup/Screen.d	Thu Sep 11 11:33:51 2008 +0100
+++ b/mde/setup/Screen.d	Fri Sep 12 17:36:14 2008 +0100
@@ -35,7 +35,7 @@
 struct Screen {
     // TYPES (these mustn't be static):
     /** Interface for anything hooking into the screen for drawing, etc. */
-    interface Drawable {
+    interface IDrawable {
         /** Called on window creation and whenever the window manager resizes the window, before
          * the new size is set. The new size is passed.
          *
@@ -63,7 +63,6 @@
             
             throw new InitException ("SDL Initialization failed");
         }
-        debug logger.trace ("SDL initialised");
         return StageState.ACTIVE;
     }
     /** SDL shutdown */
@@ -99,7 +98,6 @@
         SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER,1);
         
         // Open a window
-        debug logger.trace ("Opening a window (this can crash if the libraries are messed up)");
         if (setWindow (w, h)) {
             throw new InitException ("Failed to open a window");
         }
@@ -169,11 +167,12 @@
             imde.run = false;
     }
     
-    /** Add a drawable element to the screen (see Drawable interface).
+    /** Add a drawable element to the screen (see IDrawable interface).
      *
-     * Should be called before Init to get initial size. Currently no means to remove drawables,
-     * and not really designed for more than one. */
-    void addDrawable (Drawable d) {
+     * Should be called before Init to get the initial size (sizeEvent is only called when the size
+     * is set). Currently no means to remove drawables, and not really designed for more than one.
+     */
+    void addDrawable (IDrawable d) {
         drawables ~= d;
     }
     
@@ -181,13 +180,10 @@
     void draw (TimeSpan) {
         glClear(GL_COLOR_BUFFER_BIT);
         
-        foreach (Drawable d; drawables)
+        foreach (IDrawable d; drawables)
             d.draw;
         
-        debug (drawGlyphCache) {
-            logger.trace ("Drawing font texture");
-            FontStyle.drawTexture;
-        }
+        debug (drawGlyphCache) FontStyle.drawTexture;
         
         // Error check:
         GLenum err = glGetError();
@@ -206,7 +202,7 @@
         foreach (d; drawables)  // Tell all drawables the new window size.
             d.sizeEvent (w,h);
         
-        debug logger.trace ("Setting video mode {}x{}, 32-bit, flags: {}", w,h,flags);
+        //debug logger.trace ("Setting video mode {}x{}, 32-bit, flags: {}", w,h,flags);
         if (SDL_SetVideoMode (w, h, 32, flags) is null) {
             logger.fatal ("Unable to set video mode:");
             char* msg = SDL_GetError ();
@@ -263,7 +259,7 @@
     // DATA:
 private:
     uint flags = 0;
-    Drawable[] drawables;
+    IDrawable[] drawables;
     Logger logger;
     OptionsVideo vidOpts;
 }