Changeset 30:467c74d4804d

Show
Ignore:
Timestamp:
04/28/08 05:59:47 (9 months ago)
Author:
Diggory Hardy <diggory.hardy@gmail.com>
branch:
default
convert_revision:
370135618612be4dee7d72022ab12c3d6f694b72
Message:

Major changes to the scheduler, previously only used by the main loop.

Revamped Scheduler. Functions can be removed, have multiple schedules, have their scheduling changed, etc.
Scheduler has a unittest. Checked all pass.
Main loop scheduler moved to mde. Draw-on-demand currently disabled, simplifying this.
Made mtunitest.d remove the temporary file it uses afterwards.

committer: Diggory Hardy <diggory.hardy@gmail.com>

Files:

Legend:

Unmodified
Added
Removed
Modified
Copied
Moved
  • codeDoc/jobs.txt

    r29 r30  
    44 
    55In progress: 
     6Started buttonWidget (on hold) 
    67 
    78 
    8 To do: 
    9 Also see todo.txt. 
    10 *   Windows building/compatibility (currently partial) 
    11 *   gdc building/compatibility (wait for tango 0.99.5 release?) 
    12 *   OutOfMemoryException is not currently checked for − it should be at least in critical places (use high-level catching of all errors?). 
    13 *   Sensitivity adjustments. From es_a_out: 
     9 
     10To do (importance 0-5: 0 pointless, 1 no obvious impact now, 2 todo sometime, 3 useful, 4 important, 5 urgent): 
     11Also see todo.txt and FIXME/NOTE comment marks. 
     124   OutOfMemoryException is not currently checked for − it should be at least in critical places (use high-level catching of all errors?). 
     133   on-event draw support (mde.events and GUI need to tell mde.mde) 
     143   Scheduler for drawing only windows which need redrawing. 
     153   Update scheduler as outlined in FIXME. 
     163   Windows building/compatibility (currently partial) 
     172   Command-line options for paths to by-pass normal path finding functionality. 
     182   Consider replacing byte/short types with int type 
     192   File loading from compressed archives 
     202   gdc building/compatibility (wait for tango 0.99.5 release?) 
     212   Sensitivity adjustments. From es_a_out: 
    1422        /+ FIXME: revise. 
    1523        + I can't see any point using HALF_RANGE here, since it should really be used dependant on 
     
    3846        myThis.axis[cast(inputID) s.pop()] = y; 
    3947        +/ 
     481   Mergetag binary support 
    4049 
    4150 
    4251Done (for git log message): 
    43 GUI: Implemented a GridWidget to layout several sub-widgets. 
    44 Improved log messages about init functions. 
    45 Moved all dynamic-library loading into a separate init stage. 
     52Revamped Scheduler. Functions can be removed, have multiple schedules, have their scheduling changed, etc. 
     53Scheduler has a unittest. Checked all pass. 
     54Main loop scheduler moved to mde. Draw-on-demand currently disabled, simplifying this. 
     55Made mtunitest.d remove the temporary file it uses afterwards. 
  • mde/events.d

    r29 r30  
    1818 
    1919import global = mde.global; 
    20 static import mde.SDL; 
     20import sdl = mde.SDL;           // resizeWindow 
    2121 
    2222import mde.input.input; 
     
    2424 
    2525import mde.scheduler.InitFunctions; 
    26 import mde.scheduler.runTime; 
    2726 
    2827import derelict.sdl.events; 
    2928 
     29import tango.time.Time; 
    3030import tango.util.log.Log : Log, Logger; 
    3131 
     
    3535     
    3636    init.addFunc (&initInput, "initInput"); 
    37  
    38     Scheduler.perFrame (&mde.events.pollEvents); 
    3937} 
    4038 
     
    5553} 
    5654 
    57 void pollEvents (double) { 
     55void pollEvents (TimeSpan) { 
    5856    SDL_Event event; 
    5957    while (SDL_PollEvent (&event)) { 
     
    6462                break; 
    6563            case SDL_VIDEORESIZE: 
    66                 mde.SDL.resizeWindow (event.resize.w, event.resize.h); 
    67                 Scheduler.requestUpdate(RF_KEYS.DRAW); 
     64                sdl.resizeWindow (event.resize.w, event.resize.h); 
     65                //global.scheduler.request(global.SCHEDULE.DRAW); 
    6866                break; 
    69             case SDL_ACTIVEEVENT: 
     67            /+case SDL_ACTIVEEVENT: 
    7068            case SDL_VIDEOEXPOSE: 
    71                 Scheduler.requestUpdate(RF_KEYS.DRAW); 
    72                 break; 
     69                //global.scheduler.request(global.SCHEDULE.DRAW); 
     70                break;+/ 
    7371            default: 
    7472                try { 
  • mde/gl.d

    r27 r30  
    1919module mde.gl; 
    2020 
    21 import mde.scheduler.runTime; 
     21import global = mde.global; 
     22import mde.gui.gui; 
    2223 
    2324import derelict.sdl.sdl; 
    2425import derelict.opengl.gl; 
    2526 
    26 static this () { 
    27     Scheduler.perRequest (RF_KEYS.DRAW, &mde.gl.draw); 
    28 
     27import tango.time.Time;     // TimeSpan (type only; unused) 
    2928 
    3029//BEGIN GL & window setup 
     
    6665//BEGIN Drawing loop 
    6766// Temporary draw function 
    68 void draw () { 
     67void draw (TimeSpan) { 
    6968    glClear(GL_COLOR_BUFFER_BIT); 
    7069     
    71     foreach (func; drawCallbacks) 
    72         func(); 
     70    gui.draw (); 
    7371     
    7472    glFlush(); 
    7573    SDL_GL_SwapBuffers(); 
    7674} 
    77  
    78 alias void delegate() DrawingFunc; 
    79 void addDrawCallback (DrawingFunc f) { 
    80     drawCallbacks ~= f; 
    81 } 
    82 private DrawingFunc[] drawCallbacks; 
    8375//END Drawing loop 
  • mde/global.d

    r26 r30  
    2525 
    2626import mde.input.input; 
     27import mde.scheduler.Scheduler; 
     28 
     29/** Some enums used by per request functions. */ 
     30enum SCHEDULE : Scheduler.ID { 
     31    DRAW 
     32}; 
    2733 
    2834bool run = true;    // main loop continues if this is true 
  • mde/gui/IWindow.d

    r28 r30  
    3131    * been created, creates it using the Window's widget creation data (throws on error; don't 
    3232    * catch the exception). */ 
    33     Widget getWidget (widgetID i); 
     33    IWidget getWidget (widgetID i); 
     34     
     35    /** Called by a sub-widget when a redraw is necessary (since drawing may sometimes be done on 
     36    * event. */ 
     37    void requestRedraw (); 
    3438} 
  • mde/gui/Widget.d

    r29 r30  
    2323import mde.scheduler.InitFunctions; 
    2424 
    25 /** Interface for widgets (may become a class). 
     25//BEGIN Iface and createWidget 
     26/** Interface for widgets (may become a base class). 
    2627* 
    27 * Variable loading/saving efficiency and code-reuse need to be revised later! 
    28 * Give each Widget an int[] of data which it should check in this() and throw if bad? 
     28* A widget is a region of a GUI window which handles rendering and user-interaction for itself 
     29* and is able to communicate with it's window and parent/child widgets as necessary. 
     30
     31* A widget's constructor should have this prototype: 
     32* ---------------------------------- 
     33* this (IWindow window, int[] data); 
     34* ---------------------------------- 
     35* Where window is the parent window and data is an array of initialisation data. The method should 
     36* throw a WidgetDataException (created without parameters) if the data has wrong length or is 
     37* otherwise invalid. 
    2938*/ 
    30 interface Widget 
    31 
    32     /* this() should look like this: 
    33     this (IWindow window, int[] data) 
    34     * where: 
    35     *   window is the parent window (only needed for getting sub-widgets, hence no need to store) 
    36     *   data is the widget creation data, stripped of the widget type (see createWidget). 
    37     */ 
    38      
     39//FIXME: check code reuse later! 
     40interface IWidget 
     41
    3942    /** Draw, starting from given x and y. 
    4043    * 
    41     * Maybe replace later with drawClipped, especially for cases where only part of the widget is 
    42     * visible behind a scrolling window or hidden window. */ 
     44    * Maybe later enforce clipping of all sub-widget drawing, particularly for cases where only 
     45    * part of the widget is visible: scroll bars or a hidden window. */ 
    4346    void draw (int x, int y); 
    4447     
    45     /** Calculate the size of the widget, taking into account child-widgets. 
     48    /** Calculate the minimum size the widget could be shrunk to, taking into account 
     49    * child-widgets. */ 
     50    void getMinimumSize (out int w, out int h); 
     51     
     52    /** Get the current size of the widget. 
    4653    * 
    47     * Later will work out how to make this more flexible. */ 
    48     void getSize (out int w, out int h); 
    49 
    50  
     54    * On the first call (during loading), this may be a value saved as part of the config or 
     55    * something else (e.g. revert to getMinimumSize). */ 
     56    void getCurrentSize (out int w, out int h); 
     57
     58 
     59/// Widget types. Start high so they can be reordered easily later. 
     60enum WIDGET_TYPES : int { 
     61    BOX = 1001, GRID 
     62
     63 
     64/** Create a widget of type data[0] (see enum WIDGET_TYPES) for _window window, with initialisation 
     65* data [1..$]. */ 
     66IWidget createWidget (IWindow window, int[] data) { 
     67    if (data.length < 1) throw new WidgetDataException ("No widget data"); 
     68    int type = data[0];     // type is first element of data 
     69    data = data[1..$];      // the rest is passed to the Widget 
     70     
     71    if (type == WIDGET_TYPES.BOX) return new BoxWidget (window, data); 
     72    else if (type == WIDGET_TYPES.GRID) return new GridWidget (window, data); 
     73    else throw new WidgetDataException ("Bad widget type"); 
     74
     75//END Iface and createWidget 
     76 
     77//BEGIN Widgets 
    5178/// Draws a box. That's it. 
    52 class BoxWidget : Widget 
     79class BoxWidget : IWidget 
    5380{ 
    5481    int w, h;   // size 
     
    6693    } 
    6794     
    68     void getSize (out int w, out int h) { 
     95    void getMinimumSize (out int w, out int h) { 
     96        w = h = 0;  // box has no content 
     97    } 
     98    void getCurrentSize (out int w, out int h) { 
    6999        w = this.w; 
    70100        h = this.h; 
     
    73103 
    74104/// Encapsulates a grid of Widgets 
    75 class GridWidget : Widget 
    76 
    77     const PADDING = 1;  // padding between rows/cols 
    78     const BORDER = 1;  // border width 
     105class GridWidget : IWidget 
     106
     107    //NOTE: maybe remove the padding and have each widget include a border? Or vice-versa (no borders on widgets)? 
     108    const PADDING = 3;  // padding between rows/cols 
     109    const BORDER = 8;   // border width 
    79110    int w, h;           // size 
    80111    int rows, cols;     // number of cells in grid 
     
    83114    int[] rowY;         // cumulative rowH[i-1] + BORDER/PADDING 
    84115    int[] colX;         // cumulative colW[i-1] + BORDER/PADDING 
    85     Widget[] subWidgets;// all widgets in the grid (by row): 
     116    IWidget[] subWidgets;   // all widgets in the grid (by row): 
    86117    /* SubWidget order:    [ 2 3 ] 
    87118    *                      [ 0 1 ] */ 
     
    95126        // Get all sub-widgets 
    96127        if (data.length != 2 + rows * cols) throw new WidgetDataException; 
     128        subWidgets.length = rows*cols; 
     129        foreach (i, inout subWidget; subWidgets) { 
     130            subWidget = window.getWidget (data[i+2]); 
     131        } 
     132         
     133        getMinimumSize (w,h);   // Calculate the size (current size is not saved) 
     134    } 
     135     
     136    void draw (int x, int y) { 
     137        gl.setColor (1.0f, 0.6f, 0.0f); 
     138        gl.drawBox (x,x+w, y,y+h); 
     139         
     140        foreach (i,widget; subWidgets) { 
     141            widget.draw (x + colX[i % cols], y + rowY[i / cols]); 
     142        } 
     143    } 
     144     
     145    /** Also recalculates row/column widths. */ 
     146    void getMinimumSize (out int w, out int h) { 
    97147        if (rows*cols == 0) {    // special case 
    98148            w = h = 2*BORDER; 
    99149            return; 
    100150        } 
    101         subWidgets.length = rows*cols; 
    102         for (uint i = 2; i < data.length; ++i) { 
    103             subWidgets[i-2] = window.getWidget (data[i]); 
    104         } 
    105151         
    106152        // Find the sizes of all subWidgets 
    107153        int[] widgetW = new int[subWidgets.length]; // dimensions 
    108154        int[] widgetH = new int[subWidgets.length]; 
    109         foreach (i,widget; subWidgets) widget.getSize (widgetW[i],widgetH[i]); 
     155        foreach (i,widget; subWidgets) widget.getCurrentSize (widgetW[i],widgetH[i]); 
    110156         
    111157        // Find row heights and column widths (non cumulative) 
     
    135181        w = cum + BORDER - PADDING;     // total width 
    136182    } 
     183    void getCurrentSize (out int wC, out int hC) { 
     184        wC = w; 
     185        hC = h; 
     186    } 
     187} 
     188/+ On hold until after next commit 
     189/// First interactible widget 
     190class ButtonWidget : IWidget 
     191{ 
     192    const BORDER = 5;   // border width 
     193    int w, h;           // size 
     194    bool pushed = false;// true if button is pushed in 
     195     
     196    this (IWindow, int[] data) { 
     197        if (data.length != 2) throw new WidgetDataException; 
     198         
     199        w = data[0] + 2*BORDER; 
     200        h = data[1] + 2*BORDER; 
     201    } 
    137202     
    138203    void draw (int x, int y) { 
    139         gl.setColor (1.0f, 0.6f, 0.0f); 
     204        if (pushed) 
     205            gl.setColor (1f, 0f, 1f); 
     206        else 
     207            gl.setColor (.6f, 0f, .6f); 
    140208        gl.drawBox (x,x+w, y,y+h); 
    141          
    142         foreach (i,widget; subWidgets) { 
    143             widget.draw (x + colX[i % cols], y + rowY[i / cols]); 
    144         } 
    145     } 
    146      
    147     void getSize (out int w, out int h) { 
     209    } 
     210     
     211    void getMinimumSize (out int w, out int h) { 
     212        w = this.w; // button is not resizable 
     213        h = this.h; 
     214    } 
     215    void getCurrentSize (out int w, out int h) { 
    148216        w = this.w; 
    149217        h = this.h; 
    150218    } 
    151 
    152  
    153 // Widget types. Start high so they can be reordered easily later. 
    154 enum WIDGET_TYPES : int { 
    155     BOX = 1001, GRID 
    156 
    157  
    158 Widget createWidget (IWindow window, int[] data) { 
    159     if (data.length < 1) throw new WidgetDataException ("No widget data"); 
    160     int type = data[0];     // type is first element of data 
    161     data = data[1..$];      // the rest is passed to the Widget 
    162      
    163     if (type == WIDGET_TYPES.BOX) return new BoxWidget (window, data); 
    164     else if (type == WIDGET_TYPES.GRID) return new GridWidget (window, data); 
    165     else throw new WidgetDataException ("Bad widget type"); 
    166 
     219     
     220
     221+/ 
     222//END Widgets 
  • mde/gui/gui.d

    r29 r30  
    3131import tango.scrapple.text.convert.parseFrom : parseFrom; 
    3232 
     33import tango.util.log.Log : Log, Logger; 
     34 
    3335private Logger logger; 
    3436static this () { 
    3537    logger = Log.getLogger ("mde.gui.gui"); 
    3638     
    37     init.addFunc (&GUI.load, "GUI.load"); 
    38 
    39  
     39    init.addFunc (&loadGUI, "loadGUI"); 
     40
     41 
     42GUI gui;    // Currently just one instance; handle differently later. 
     43// Wrap gui.load, since init doesn't handle delegates 
     44// (do it this way since GUI handling will eventually be changed) 
     45void loadGUI () { 
     46    gui.load(); 
     47
     48 
     49/** A GUI handles a bunch of windows, all to be drawn to the same device. */ 
    4050struct GUI { 
    41 static: 
    42     private const fileName = "gui"; 
     51    /** Load all windows from the file gui. */ 
    4352    void load() { 
     53        static const fileName = "gui"; 
    4454        if (!confDir.exists (fileName)) { 
    4555            logger.error ("Unable to load GUI: no config file!"); 
     
    6676        foreach (sec; reader.dataset.sec) { 
    6777            Window w = cast(Window) sec; 
    68             if (w !is null) {                       // extra safety 
    69                 windows ~= w; 
    70                 try { 
    71                     w.finalise(); 
    72                      
    73                     gl.addDrawCallback (&w.draw); 
    74                 } catch (WindowLoadException e) { 
    75                     logger.error ("Window failed to load: " ~ e.msg); 
    76                 } 
    77             } 
    78         } 
    79     } 
    80      
    81 private: 
     78            debug if (w is null) { 
     79                logger.error (__FILE__ ~ "(GUI.load): code error (w is null)"); 
     80                continue; 
     81            } 
     82            try { 
     83                //logger.trace ("1"); 
     84                int x; 
     85                w.finalise(); 
     86                x = 6; 
     87                windows ~= w;       // only add if load successful 
     88            } catch (WindowLoadException e) { 
     89                logger.error ("Window failed to load: " ~ e.msg); 
     90            } 
     91        } 
     92    } 
     93     
     94    /** Draw each window. 
     95    * 
     96    * Currently no concept of how to draw overlapping windows, or how to not bother drawing windows 
     97    * which don't need redrawing. */ 
     98    void draw() { 
     99        foreach (w; windows) 
     100            w.draw(); 
     101    } 
     102     
     103    private: 
    82104    Window[] windows; 
    83105} 
     
    96118{ 
    97119    alias int widgetID;     // Widget ID type. Each ID is unique under this window. Type is int since this is the widget data type. 
    98     private int[][widgetID] widgetData;     // Data for all widgets under this window. 
    99     private Widget[widgetID] widgets;       // List of all widgets under this window (created on demand). 
    100      
    101     Widget widget;                  // The primary widget in this window. 
    102     int x,y;                        // Window position 
    103     int w,h;                        // Window size (calculated from Widgets) 
    104      
    105     const BORDER_WIDTH = 8;         // Temporary way to handle window decorations 
    106      
    107      
    108     // Call after loading is finished to setup the window and confirm that it's valid. 
     120     
     121    /** Call after loading is finished to setup the window and confirm that it's valid. 
     122    * 
     123    * Throws: WindowLoadException. Do not use the instance in this case! */ 
    109124    void finalise () { 
    110         // Create the widget, throwing on error: 
     125        // Check data was loaded: 
     126        if (widgetData is null) throw new WindowLoadException ("No widget data"); 
     127         
     128        // Create the primary widget (and indirectly all sub-widgets), throwing on error: 
    111129        widget = getWidget (0);     // primary widget always has ID 0. 
    112         widget.getSize (w,h);       // Find the initial size 
     130         
     131        widgetData = null;          // data is no longer needed: allow GC to collect (cannot safely delete) 
     132         
     133        widget.getCurrentSize (w,h);// Find the initial size 
    113134        w += BORDER_WIDTH * 2;      // Adjust for border 
    114135        h += BORDER_WIDTH * 2; 
    115136    } 
    116137     
    117     Widget getWidget (widgetID i) { 
     138    /** Get/create a widget by ID. 
     139    * 
     140    * Should $(I only) be called internally and by sub-widgets! */ 
     141    IWidget getWidget (widgetID i) 
     142    in { 
     143        // widgetData is normally left to be garbage collected after widgets have been created: 
     144        assert (widgetData !is null, "getWidget: widgetData is null"); 
     145    } body { 
    118146        // See if it's already been created: 
    119         Widget* p = i in widgets; 
     147        IWidget* p = i in widgets; 
    120148        if (p !is null) return *p;  // yes 
    121149        else {                      // no 
     
    124152             
    125153            // Throws WidgetDataException (a WindowLoadException) if bad data: 
    126             Widget w = createWidget (this, *d); 
     154            IWidget w = createWidget (this, *d); 
    127155            widgets[i] = w; 
    128156            return w; 
    129157        } 
     158    } 
     159     
     160    void requestRedraw () { 
     161    //FIXME 
    130162    } 
    131163     
     
    157189    } 
    158190    //END Mergetag code 
    159 
     191     
     192    private: 
     193    int[][widgetID] widgetData;     // Data for all widgets under this window (deleted after loading) 
     194    IWidget[widgetID] widgets;      // List of all widgets under this window (created on demand). 
     195     
     196    IWidget widget;                 // The primary widget in this window. 
     197    int x,y;                        // Window position 
     198    int w,h;                        // Window size (calculated from Widgets) 
     199     
     200    const BORDER_WIDTH = 8;         // Temporary way to handle window decorations 
     201 
     202
  • mde/mde.d

    r27 r30  
    2323 
    2424import global = mde.global;             // global.run 
    25 import mde.SDL;                         // unused (but must be linked in) 
    26 import mde.events;                      // unused (but must be linked in) 
    27 import mde.gui.gui;                     // unused (but must be linked in) 
     25import gl = mde.gl;                     // gl.draw 
     26import mde.events;                      // pollEvents 
    2827 
    2928import mde.scheduler.Init; 
    30 import mde.scheduler.runTime;           // Scheduler.run() 
     29import mde.scheduler.Scheduler;         // Scheduler.run() 
    3130import mde.scheduler.exception;         // InitException 
    3231 
     
    5049    //END Initialisation 
    5150     
     51    //BEGIN Main loop setup 
     52    Scheduler scheduler = new Scheduler;    // main loop's scheduler 
     53     
     54    scheduler.add (scheduler.getNewID, &mde.events.pollEvents).frame = true; 
     55    scheduler.add (global.SCHEDULE.DRAW, &gl.draw).frame = true;    // draw. for now, every frame. 
     56    //END Main loop setup 
     57     
    5258    while (global.run) { 
    53         Scheduler.run (Clock.now()); 
     59        scheduler.execute (Clock.now()); 
    5460         
    5561        Thread.sleep (0.050);   // sleep this many seconds 
  • mde/mergetag/mtunittest.d

    r26 r30  
    1717module mde.mergetag.mtunittest; 
    1818 
    19 import mde.mergetag.Reader; 
    20 import mde.mergetag.Writer; 
    21 import mde.mergetag.DataSet; 
    22 import mde.mergetag.DefaultData; 
    23  
    24 import tango.scrapple.text.convert.parseTo : parseTo; 
    25 import tango.scrapple.text.convert.parseFrom : parseFrom; 
    26  
    27 import tango.util.log.Log : Log, Logger; 
    28  
    2919debug (mdeUnitTest) { 
     20    import mde.mergetag.Reader; 
     21    import mde.mergetag.Writer; 
     22    import mde.mergetag.DataSet; 
     23    import mde.mergetag.DefaultData; 
     24     
     25    import tango.scrapple.text.convert.parseTo : parseTo; 
     26    import tango.scrapple.text.convert.parseFrom : parseFrom; 
     27     
     28    import tango.io.FilePath; 
     29    import tango.util.log.Log : Log, Logger; 
     30     
    3031    private Logger logger; 
    3132    static this() { 
    3233        logger = Log.getLogger ("mde.mergetag.mtunittest"); 
    3334    } 
    34  
     35     
    3536    unittest { 
    3637        /* This does a basic write-out and read-in test for each type with its default value. 
     
    9293        } 
    9394        mixin (genCheckCode (`secW`,`secR`)); 
    94      
     95         
     96        // Delete the unittest file now 
     97        FilePath (file~".mtt").remove; 
     98         
    9599        logger.info ("Unittest complete (for DefaultData)."); 
    96100    } 
  • mde/scheduler/Init.d

    r29 r30  
    4747import derelict.opengl.gl; 
    4848import derelict.sdl.sdl; 
    49 //import derelict.freetype.ft; 
     49import derelict.freetype.ft; 
    5050import derelict.util.exception; 
    5151 
     
    151151            DerelictSDL.load(); 
    152152            DerelictGL.load(); 
    153             //DerelictFT.load(); 
     153            DerelictFT.load(); 
    154154        } catch (DerelictException de) { 
    155155            logger.fatal ("Loading dynamic library failed:"); 
     
    157157             
    158158            throw new InitException ("Loading dynamic libraries failed (see above)."); 
    159             return; 
    160159        } 
    161160        //END Load dynamic libraries 
     
    309308        static void initFunc () { 
    310309            initialised = true; 
    311             cleanupUT.addFunc (&cleanupFunc1); 
    312             cleanupUT.addFunc (&cleanupFunc2); 
    313         } 
    314          
    315         initUT.addFunc (&initFunc); 
     310            cleanupUT.addFunc (&cleanupFunc1, "UT cleanup 1"); 
     311            cleanupUT.addFunc (&cleanupFunc2, "UT cleanup 2"); 
     312        } 
     313         
     314        initUT.addFunc (&initFunc, "UT init"); 
    316315         
    317316        runStageForward (initUT); 
  • mde/scheduler/InitFunctions.d

    r29 r30  
    2323* "out cleanupFunc[]". */ 
    2424module mde.scheduler.InitFunctions; 
    25  
    26 static import mde.gl; 
    2725 
    2826import tango.util.log.Log : Log, Logger; 
  • test/mdeTest.d

    r26 r30  
    2929import mde.exception; 
    3030import mde.scheduler.Init; 
     31import mde.scheduler.Scheduler; 
    3132import mde.i18n.I18nTranslation; 
    3233