Changeset 98:49e7cfed4b34
- Timestamp:
- 11/12/08 08:18:51
(2 months ago)
- Author:
- Diggory Hardy <diggory.hardy@gmail.com>
- branch:
- default
- Message:
All types of Option have been converted to use ValueContent? classes, and their values can be displayed.
-
Files:
-
Legend:
- Unmodified
- Added
- Removed
- Modified
- Copied
- Moved
| r95 |
r98 |
|
| 2 | 2 | {en-GB} |
|---|
| 3 | 3 | <entry|maxThreads={0:"Max threads",1:"Maximum number of threads to use in mde (currently only applies to init stages run in parallel)."}> |
|---|
| 4 | | <entry|logLevel={0:"Logging level",1:"Controls which messages are logged, from 0=trace to 6=none (default: 1=info)."}> |
|---|
| | 4 | <entry|logLevel={0:"Logging level",1:"Lowest level to log messages; 0=trace, 1=info (default), 2=warn, 3=error, 4=fatal, 5=none."}> |
|---|
| | 5 | <entry|logOutput={0:"Logging output",1:"Output to: 0=nowhere, 1=the console, 2=a file, 3=both"}> |
|---|
| 5 | 6 | <entry|L10n={0:"Localisation",1:"Specifies the language to use."}> |
|---|
| 6 | 7 | <entry|pollInterval={0:"Polling interval",1:"Delay in main loop to limit CPU usage"}> |
|---|
| r97 |
r98 |
|
| 8 | 8 | <WidgetData|button={0:[0x10,50,50]}> |
|---|
| 9 | 9 | <WidgetData|blank={0:[0x2]}> |
|---|
| 10 | | <WidgetData|opts={0:[0x8110,0],1:["optDBox","VideoOptions"]}> |
|---|
| | 10 | <WidgetData|opts={0:[0x8110,0],1:["optDBox","MiscOptions"]}> |
|---|
| 11 | 11 | <WidgetData|optDBox={0:[0xC100,1,2,1],1:["optBox","optDesc"]}> |
|---|
| 12 | 12 | <WidgetData|optBox={0:[0xC100,1,1,3],1:["optName","optSep","optVal"]}> |
|---|
| … | … | |
| 17 | 17 | <WidgetData|floating={0:[0x8200,1,6,14],1:["text","button","blank"]}> |
|---|
| 18 | 18 | <WidgetData|text={0:[0x21,0xE0E000],1:["Floating text"]}> |
|---|
| 19 | | <WDims|root=[6,590,196,6,580,6]> |
|---|
| 20 | | <WDims|content=[590,190,364,18]> |
|---|
| 21 | | <WDims|floating=[25,21,103,27,437,23,74,74,217,90,123,100]> |
|---|
| | 19 | <WDims|content=[736,221,272,79]> |
|---|
| | 20 | <WDims|root=[6,736,50,6,580,6]> |
|---|
| | 21 | <WDims|floating=[25,0,103,27,572,26,74,74,242,128,168,93]> |
|---|
| 22 | 22 | {Basic} |
|---|
| 23 | 23 | <WidgetData|root={0:[0x21,0x90D970],1:["A string!"]}> |
|---|
| r95 |
r98 |
|
| 4 | 4 | <bool|exitImmediately=false> |
|---|
| 5 | 5 | <char[]|L10n="en-GB"> |
|---|
| 6 | | <int|logOptions=0x3000> |
|---|
| | 6 | <int|logLevel=1> |
|---|
| | 7 | <int|logOutput=3> |
|---|
| 7 | 8 | <double|pollInterval=0.01> |
|---|
| 8 | 9 | |
|---|
| r95 |
r98 |
|
| 58 | 58 | scope Init init = new Init(args); // initialize mde |
|---|
| 59 | 59 | |
|---|
| 60 | | // Make sure pollInterval has a sane value. FIXME: get Options class to enforce range |
|---|
| 61 | | if (miscOpts.pollInterval !<= 1.0 || miscOpts.pollInterval !>= 0.0) |
|---|
| 62 | | miscOpts.set!(double) ("pollInterval", 0.01); |
|---|
| 63 | | |
|---|
| 64 | 60 | //BEGIN Main loop setup |
|---|
| 65 | 61 | /* Note: the main loop is currently controlled by the scheduler. This is not really ideal, |
|---|
| … | … | |
| 75 | 71 | mainSchedule.execute (Clock.now()); |
|---|
| 76 | 72 | |
|---|
| 77 | | Thread.sleep (miscOpts.pollInterval); // sleep this many seconds |
|---|
| | 73 | Thread.sleep (miscOpts.pollInterval()); // sleep this many seconds |
|---|
| 78 | 74 | } |
|---|
| 79 | 75 | |
|---|
| r97 |
r98 |
|
| 230 | 230 | |
|---|
| 231 | 231 | // Use renderMode from options, masking bits which are allowable: |
|---|
| 232 | | if (FT_Load_Glyph (face, gi, FT_LOAD_RENDER | (fontOpts.renderMode & 0xF0000))) |
|---|
| | 232 | if (FT_Load_Glyph (face, gi, FT_LOAD_RENDER | (fontOpts.renderMode() & 0xF0000))) |
|---|
| 233 | 233 | throw new fontGlyphException ("Unable to render glyph"); |
|---|
| 234 | 234 | |
|---|
| … | … | |
| 281 | 281 | } |
|---|
| 282 | 282 | |
|---|
| 283 | | format = (fontOpts.renderMode & RENDER_LCD_BGR) ? GL_BGR : GL_RGB; |
|---|
| | 283 | format = (fontOpts.renderMode() & RENDER_LCD_BGR) ? GL_BGR : GL_RGB; |
|---|
| 284 | 284 | } else if (b.pixel_mode == FT_Pixel_Mode.FT_PIXEL_MODE_LCD_V) { |
|---|
| 285 | 285 | // NOTE: Notes above apply. But in this case converting the buffers seems essential. |
|---|
| … | … | |
| 293 | 293 | } |
|---|
| 294 | 294 | |
|---|
| 295 | | format = (fontOpts.renderMode & RENDER_LCD_BGR) ? GL_BGR : GL_RGB; |
|---|
| | 295 | format = (fontOpts.renderMode() & RENDER_LCD_BGR) ? GL_BGR : GL_RGB; |
|---|
| 296 | 296 | } else |
|---|
| 297 | 297 | throw new fontGlyphException ("Unsupported freetype bitmap format"); |
|---|
| r97 |
r98 |
|
| 72 | 72 | // Set LCD filtering method if LCD rendering is enabled. |
|---|
| 73 | 73 | const RMF = FT_LOAD_TARGET_LCD | FT_LOAD_TARGET_LCD_V; |
|---|
| 74 | | if (fontOpts.renderMode & RMF && |
|---|
| 75 | | FT_Library_SetLcdFilter(library, cast(FT_LcdFilter)fontOpts.lcdFilter)) { |
|---|
| | 74 | if (fontOpts.renderMode() & RMF && |
|---|
| | 75 | FT_Library_SetLcdFilter(library, cast(FT_LcdFilter)fontOpts.lcdFilter())) { |
|---|
| 76 | 76 | /* An error occurred, presumably because LCD rendering support |
|---|
| 77 | 77 | * is not compiled into the library. */ |
|---|
| … | … | |
| 80 | 80 | |
|---|
| 81 | 81 | // Reset the default filter (in case an invalid value was set in config files). |
|---|
| 82 | | fontOpts.set!(int) ("lcdFilter", FT_LcdFilter.FT_LCD_FILTER_DEFAULT); |
|---|
| | 82 | fontOpts.lcdFilter = FT_LcdFilter.FT_LCD_FILTER_DEFAULT; |
|---|
| 83 | 83 | |
|---|
| 84 | 84 | /* If no support for LCD filtering, then LCD rendering only emulates NORMAL with 3 |
|---|
| 85 | 85 | * times wider glyphs. So disable and save the extra work. */ |
|---|
| 86 | | fontOpts.set!(int) ("renderMode", FT_LOAD_TARGET_NORMAL); |
|---|
| | 86 | fontOpts.renderMode = FT_LOAD_TARGET_NORMAL; |
|---|
| 87 | 87 | } |
|---|
| 88 | 88 | |
|---|
| r95 |
r98 |
|
| 18 | 18 | module mde.gui.content.Content; |
|---|
| 19 | 19 | |
|---|
| | 20 | //FIXME: efficient conversions? Need to dup result when formatting a string anyway? |
|---|
| 20 | 21 | import Int = tango.text.convert.Integer; |
|---|
| | 22 | import Float = tango.text.convert.Float; |
|---|
| 21 | 23 | |
|---|
| 22 | 24 | debug { |
|---|
| … | … | |
| 93 | 95 | } |
|---|
| 94 | 96 | |
|---|
| | 97 | template VContentN(T) { |
|---|
| | 98 | static if (is(T == bool)) { |
|---|
| | 99 | const char[] VContentN = "BoolContent"; |
|---|
| | 100 | } else static if (is(T == int)) { |
|---|
| | 101 | const char[] VContentN = "IntContent"; |
|---|
| | 102 | } else static if (is(T == double)) { |
|---|
| | 103 | const char[] VContentN = "DoubleContent"; |
|---|
| | 104 | } else static if (is(T == char[])) { |
|---|
| | 105 | const char[] VContentN = "TextContent"; |
|---|
| | 106 | } else |
|---|
| | 107 | static assert (false, "No ValueContent of type "~T.stringof); |
|---|
| | 108 | } |
|---|
| | 109 | |
|---|
| 95 | 110 | class BoolContent : ValueContent |
|---|
| 96 | 111 | { |
|---|
| … | … | |
| 123 | 138 | return v; |
|---|
| 124 | 139 | } |
|---|
| | 140 | alias opCall opCast; |
|---|
| 125 | 141 | |
|---|
| 126 | 142 | bool v; //FIXME: should be protected but Options needs to set without calling callbacks |
|---|
| … | … | |
| 133 | 149 | class TextContent : ValueContent |
|---|
| 134 | 150 | { |
|---|
| 135 | | this () {} |
|---|
| 136 | | this (char[] text, char[] name = null) { |
|---|
| 137 | | text_ = text; |
|---|
| 138 | | name_ = name; |
|---|
| 139 | | } |
|---|
| 140 | | /+ |
|---|
| 141 | | ContentText dup () { |
|---|
| 142 | | return new ContentText (text_); |
|---|
| 143 | | } |
|---|
| 144 | | |
|---|
| 145 | | ContentText toText () { |
|---|
| 146 | | return this; |
|---|
| 147 | | } |
|---|
| 148 | | ContentInt toInt () { |
|---|
| 149 | | // FIXME: convert |
|---|
| 150 | | return null; |
|---|
| 151 | | } |
|---|
| 152 | | +/ |
|---|
| 153 | | |
|---|
| 154 | | /// Get the text. |
|---|
| 155 | | char[] toString (uint i) { |
|---|
| 156 | | debug logger.trace ("TextContent.toString"); |
|---|
| 157 | | return (i == 0) ? text_ |
|---|
| | 151 | this (char[] symbol, char[] val = null) { |
|---|
| | 152 | symb = symbol; |
|---|
| | 153 | v = val; |
|---|
| | 154 | } |
|---|
| | 155 | |
|---|
| | 156 | /** Adds cb to the list of callback functions called when the value is changed. Returns this. */ |
|---|
| | 157 | TextContent addChangeCb (void delegate (char[] symbol,char[] value) cb) { |
|---|
| | 158 | cngCb ~= cb; |
|---|
| | 159 | return this; |
|---|
| | 160 | } |
|---|
| | 161 | |
|---|
| | 162 | /// Get the text. |
|---|
| | 163 | char[] toString (uint i) { |
|---|
| | 164 | return (i == 0) ? v |
|---|
| 158 | 165 | : (i == 1) ? name_ |
|---|
| 159 | 166 | : (i == 2) ? desc_ |
|---|
| … | … | |
| 161 | 168 | } |
|---|
| 162 | 169 | |
|---|
| 163 | | protected: |
|---|
| 164 | | char[] text_; |
|---|
| 165 | | } |
|---|
| 166 | | /+ |
|---|
| | 170 | void opAssign (char[] val) { |
|---|
| | 171 | v = val; |
|---|
| | 172 | foreach (cb; cngCb) |
|---|
| | 173 | cb(symb, val); |
|---|
| | 174 | } |
|---|
| | 175 | char[] opCall () { |
|---|
| | 176 | return v; |
|---|
| | 177 | } |
|---|
| | 178 | alias opCall opCast; |
|---|
| | 179 | |
|---|
| | 180 | char[] v; |
|---|
| | 181 | protected: |
|---|
| | 182 | char[] symb; |
|---|
| | 183 | void delegate (char[],char[])[] cngCb; |
|---|
| | 184 | } |
|---|
| | 185 | |
|---|
| 167 | 186 | /** Integer content. */ |
|---|
| 168 | | class ContentInt : IContent |
|---|
| 169 | | { |
|---|
| 170 | | this () {} |
|---|
| 171 | | this (int integer) { |
|---|
| 172 | | int_ = integer; |
|---|
| 173 | | } |
|---|
| 174 | | |
|---|
| 175 | | ContentInt dup () { |
|---|
| 176 | | return new ContentInt (int_); |
|---|
| 177 | | } |
|---|
| 178 | | |
|---|
| 179 | | ContentText toText () { |
|---|
| 180 | | return new ContentText(toString); |
|---|
| 181 | | } |
|---|
| 182 | | ContentInt toInt () { |
|---|
| 183 | | return this; |
|---|
| 184 | | } |
|---|
| 185 | | |
|---|
| 186 | | /// Get the integer. |
|---|
| 187 | | int integer () { |
|---|
| 188 | | return int_; |
|---|
| 189 | | } |
|---|
| 190 | | |
|---|
| 191 | | char[] toString () { |
|---|
| 192 | | return Int.toString (int_); |
|---|
| 193 | | } |
|---|
| 194 | | |
|---|
| 195 | | protected: |
|---|
| 196 | | int int_; |
|---|
| 197 | | } |
|---|
| 198 | | +/ |
|---|
| | 187 | class IntContent : ValueContent |
|---|
| | 188 | { |
|---|
| | 189 | /** Create a content with _symbol name symbol. */ |
|---|
| | 190 | this (char[] symbol, int val = 0) { |
|---|
| | 191 | symb = symbol; |
|---|
| | 192 | v = val; |
|---|
| | 193 | } |
|---|
| | 194 | |
|---|
| | 195 | /** Adds cb to the list of callback functions called when the value is changed. Returns this. */ |
|---|
| | 196 | IntContent addChangeCb (void delegate (char[] symbol,int value) cb) { |
|---|
| | 197 | cngCb ~= cb; |
|---|
| | 198 | return this; |
|---|
| | 199 | } |
|---|
| | 200 | |
|---|
| | 201 | /// Get the text. |
|---|
| | 202 | char[] toString (uint i) { |
|---|
| | 203 | return (i == 0) ? Int.toString (v) |
|---|
| | 204 | : (i == 1) ? name_ |
|---|
| | 205 | : (i == 2) ? desc_ |
|---|
| | 206 | : null; |
|---|
| | 207 | } |
|---|
| | 208 | |
|---|
| | 209 | void opAssign (int val) { |
|---|
| | 210 | v = val; |
|---|
| | 211 | foreach (cb; cngCb) |
|---|
| | 212 | cb(symb, val); |
|---|
| | 213 | } |
|---|
| | 214 | int opCall () { |
|---|
| | 215 | return v; |
|---|
| | 216 | } |
|---|
| | 217 | alias opCall opCast; |
|---|
| | 218 | |
|---|
| | 219 | int v; |
|---|
| | 220 | protected: |
|---|
| | 221 | char[] symb; |
|---|
| | 222 | void delegate (char[],int)[] cngCb; |
|---|
| | 223 | } |
|---|
| | 224 | |
|---|
| | 225 | /** Double content. */ |
|---|
| | 226 | class DoubleContent : ValueContent |
|---|
| | 227 | { |
|---|
| | 228 | /** Create a content with _symbol name symbol. */ |
|---|
| | 229 | this (char[] symbol, double val = 0) { |
|---|
| | 230 | symb = symbol; |
|---|
| | 231 | v = val; |
|---|
| | 232 | } |
|---|
| | 233 | |
|---|
| | 234 | /** Adds cb to the list of callback functions called when the value is changed. Returns this. */ |
|---|
| | 235 | DoubleContent addChangeCb (void delegate (char[] symbol,double value) cb) { |
|---|
| | 236 | cngCb ~= cb; |
|---|
| | 237 | return this; |
|---|
| | 238 | } |
|---|
| | 239 | |
|---|
| | 240 | /// Get the text. |
|---|
| | 241 | char[] toString (uint i) { |
|---|
| | 242 | return (i == 0) ? Float.toString (v) |
|---|
| | 243 | : (i == 1) ? name_ |
|---|
| | 244 | : (i == 2) ? desc_ |
|---|
| | 245 | : null; |
|---|
| | 246 | } |
|---|
| | 247 | |
|---|
| | 248 | void opAssign (double val) { |
|---|
| | 249 | v = val; |
|---|
| | 250 | foreach (cb; cngCb) |
|---|
| | 251 | cb(symb, val); |
|---|
| | 252 | } |
|---|
| | 253 | double opCall () { |
|---|
| | 254 | return v; |
|---|
| | 255 | } |
|---|
| | 256 | alias opCall opCast; |
|---|
| | 257 | |
|---|
| | 258 | double v; |
|---|
| | 259 | protected: |
|---|
| | 260 | char[] symb; |
|---|
| | 261 | void delegate (char[],double)[] cngCb; |
|---|
| | 262 | } |
|---|
| r95 |
r98 |
|
| 104 | 104 | // content editables: 0x30 |
|---|
| 105 | 105 | editContent = FUNCTION | TAKES_CONTENT | 0x30, |
|---|
| | 106 | DisplayContent = TAKES_CONTENT | 0x30, |
|---|
| 106 | 107 | BoolContent = TAKES_CONTENT | 0x31, |
|---|
| 107 | 108 | |
|---|
| … | … | |
| 122 | 123 | "TextLabel", |
|---|
| 123 | 124 | "ContentLabel", |
|---|
| | 125 | "DisplayContent", |
|---|
| 124 | 126 | "BoolContent", |
|---|
| 125 | 127 | "editContent", |
|---|
| r95 |
r98 |
|
| 82 | 82 | // the supported types simply by changing this list now (untested). |
|---|
| 83 | 83 | template store(A...) { alias A store; } |
|---|
| 84 | | alias store!(bool, int, double, char[]) TYPES; |
|---|
| 85 | | alias store!(int, double, char[]) TYPES2; |
|---|
| | 84 | // NOTE: currently all types have transitioned to the new method, but the old method remains |
|---|
| | 85 | alias store!(bool, int, double, char[]) TYPES; // all types |
|---|
| | 86 | alias store!(bool, int, double, char[]) CTYPES; // types stored with a content |
|---|
| 86 | 87 | //BEGIN Templates: internal |
|---|
| 87 | 88 | private { |
|---|
| … | … | |
| 98 | 99 | template PLists(A...) { |
|---|
| 99 | 100 | static if (A.length) { |
|---|
| 100 | | static if (is (T == bool)) { |
|---|
| | 101 | static if (TIsIn!(A[0], CTYPES)) { |
|---|
| 101 | 102 | const char[] PLists = PLists!(A[1..$]); |
|---|
| 102 | 103 | } else |
|---|
| … | … | |
| 119 | 120 | // For addTag |
|---|
| 120 | 121 | template addTagMixin(T, A...) { |
|---|
| 121 | | static if (is(T == bool)) { |
|---|
| | 122 | static if (TIsIn!(T, CTYPES)) { |
|---|
| 122 | 123 | const char[] ifBlock = `if (tp == "`~T.stringof~`") { |
|---|
| 123 | 124 | auto p = id in opts; |
|---|
| 124 | 125 | if (p) { |
|---|
| 125 | | auto q = cast(BoolContent) (*p); |
|---|
| | 126 | auto q = cast(`~VContentN!(T)~`) (*p); |
|---|
| 126 | 127 | if (q) q.v = parseTo!(`~T.stringof~`) (dt); |
|---|
| 127 | 128 | } |
|---|
| … | … | |
| 141 | 142 | template listMixin(A...) { |
|---|
| 142 | 143 | static if (A.length) { |
|---|
| 143 | | const char[] listMixin = `ret ~= opts`~TName!(A[0])~`.keys;` ~ listMixin!(A[1..$]); |
|---|
| | 144 | static if (TIsIn!(A, CTYPES)) |
|---|
| | 145 | const char[] listMixin = listMixin!(A[1..$]); |
|---|
| | 146 | else |
|---|
| | 147 | const char[] listMixin = `ret ~= opts`~TName!(A[0])~`.keys;` ~ listMixin!(A[1..$]); |
|---|
| 144 | 148 | } else |
|---|
| 145 | 149 | const char[] listMixin = ``; |
|---|
| … | … | |
| 249 | 253 | * must be changed in two separate places. */ |
|---|
| 250 | 254 | void set(T) (char[] symbol, T val) { |
|---|
| 251 | | static assert (TIsIn!(T,TYPES) && !is(T == bool), "Options does not support type "~T.stringof); |
|---|
| | 255 | static assert (TIsIn!(T,TYPES) && !TIsIn!(T, CTYPES), "Options.set does not support type "~T.stringof); |
|---|
| 252 | 256 | |
|---|
| 253 | 257 | changed = true; // something got set (don't bother checking this isn't what it already was) |
|---|
| … | … | |
| 281 | 285 | char[][] list () { |
|---|
| 282 | 286 | char[][] ret; |
|---|
| 283 | | mixin (listMixin!(TYPES2)); |
|---|
| | 287 | mixin (listMixin!(TYPES)); |
|---|
| 284 | 288 | return ret; |
|---|
| 285 | 289 | } |
|---|
| … | … | |
| 298 | 302 | |
|---|
| 299 | 303 | // The "pointer lists", e.g. char[]*[ID] optscharA; |
|---|
| 300 | | mixin (PLists!(TYPES2)); //FIXME |
|---|
| | 304 | mixin (PLists!(TYPES)); |
|---|
| 301 | 305 | ValueContent[char[]] opts; // generic list of option values |
|---|
| 302 | 306 | } |
|---|
| … | … | |
| 316 | 320 | // Replace, e.g., bool, with BoolContent |
|---|
| 317 | 321 | template contentName(A) { |
|---|
| 318 | | static if (is(A == bool)) { |
|---|
| 319 | | const char[] contentName = "BoolContent"; |
|---|
| 320 | | } else static if (is(A == int)) { |
|---|
| 321 | | const char[] contentName = "int";// no IntContent yet |
|---|
| 322 | | } else static if (is(A == double)) { |
|---|
| 323 | | const char[] contentName = "double"; |
|---|
| 324 | | } else static if (is(A == char[])) { |
|---|
| 325 | | const char[] contentName = "char[]"; |
|---|
| 326 | | } else |
|---|
| 327 | | static assert (false, "unsuppurted type: "~ A); |
|---|
| | 322 | static if (TIsIn!(A, CTYPES)) { |
|---|
| | 323 | const char[] contentName = VContentN!(A); |
|---|
| | 324 | } else |
|---|
| | 325 | const char[] contentName = A.stringof; |
|---|
| 328 | 326 | } |
|---|
| 329 | 327 | // Return index of first comma, or halts if not found. |
|---|
| … | … | |
| 371 | 369 | } |
|---|
| 372 | 370 | // May have a trailing comma. Assumes cIndex always returns less than A.$ . |
|---|
| 373 | | template aaVarsBool(char[] A) {//FIXME |
|---|
| | 371 | template aaVarsContent(char[] A) {//FIXME |
|---|
| 374 | 372 | static if (A.length == 0) |
|---|
| 375 | | const char[] aaVarsBool = ""; |
|---|
| | 373 | const char[] aaVarsContent = ""; |
|---|
| 376 | 374 | else static if (A[0] == ' ') |
|---|
| 377 | | const char[] aaVarsBool = aaVarsBool!(A[1..$]); |
|---|
| 378 | | else |
|---|
| 379 | | const char[] aaVarsBool = "\""~A[0..cIndex!(A)]~"\"[]:"~A[0..cIndex!(A)] ~ "," ~ |
|---|
| 380 | | aaVarsBool!(A[cIndex!(A)+1..$]); |
|---|
| | 375 | const char[] aaVarsContent = aaVarsContent!(A[1..$]); |
|---|
| | 376 | else |
|---|
| | 377 | const char[] aaVarsContent = "\""~A[0..cIndex!(A)]~"\"[]:cast(ValueContent)"~A[0..cIndex!(A)] ~ "," ~ |
|---|
| | 378 | aaVarsContent!(A[cIndex!(A)+1..$]); |
|---|
| 381 | 379 | } |
|---|
| 382 | 380 | // strip Trailing Comma |
|---|
| … | … | |
| 404 | 402 | } |
|---|
| 405 | 403 | // foreach decl... |
|---|
| 406 | | template createBCs(char[] A) { |
|---|
| | 404 | template createContents(T, char[] A) { |
|---|
| 407 | 405 | static if (A.length == 0) |
|---|
| 408 | | const char[] createBCs = ""; |
|---|
| | 406 | const char[] createContents = ""; |
|---|
| 409 | 407 | else static if (A[0] == ' ') |
|---|
| 410 | | const char[] createBCs = createBCs!(A[1..$]); |
|---|
| 411 | | else |
|---|
| 412 | | const char[] createBCs = A[0..cIndex!(A)]~ ` = (new BoolContent ("`~A[0..cIndex!(A)]~"\")).addChangeCb (&optionChanges.set);\n"~ |
|---|
| 413 | | createBCs!(A[cIndex!(A)+1..$]); |
|---|
| | 408 | const char[] createContents = createContents!(T,A[1..$]); |
|---|
| | 409 | else |
|---|
| | 410 | const char[] createContents = "opts[\""~A[0..cIndex!(A)]~"\"] = " ~ A[0..cIndex!(A)]~ " = (new "~VContentN!(T)~" (\""~A[0..cIndex!(A)]~"\")).addChangeCb (&optionChanges.set);\n"~ |
|---|
| | 411 | createContents!(T,A[cIndex!(A)+1..$]); |
|---|
| 414 | 412 | } |
|---|
| 415 | 413 | // for recursing on TYPES |
|---|
| 416 | 414 | template optionsThisInternal(char[] A, B...) { |
|---|
| 417 | 415 | static if (B.length) { |
|---|
| 418 | | static if (is(B[0] == bool)) {//FIXME |
|---|
| 419 | | const char[] optionsThisInternal = createBCs!(parseT!(B[0].stringof,A))~ |
|---|
| 420 | | `opts = `~listOrNull!(sTC!(aaVarsBool!(parseT!(B[0].stringof,A))))~";\n" ~ |
|---|
| | 416 | static if (TIsIn!(B[0], CTYPES)) { |
|---|
| | 417 | const char[] optionsThisInternal = createContents!(B[0],parseT!(B[0].stringof,A))~ |
|---|
| 421 | 418 | optionsThisInternal!(A,B[1..$]); |
|---|
| 422 | 419 | } else |
|---|
| … | … | |
| 558 | 555 | MiscOptions miscOpts; |
|---|
| 559 | 556 | class MiscOptions : Options { |
|---|
| 560 | | const A = "bool exitImmediately; int maxThreads, logOptions; double pollInterval; char[] L10n;"; |
|---|
| | 557 | const A = "bool exitImmediately; int maxThreads, logLevel, logOutput; double pollInterval; char[] L10n;"; |
|---|
| 561 | 558 | //pragma (msg, impl!(A)); |
|---|
| 562 | 559 | mixin (impl!(A)); |
|---|
| … | … | |
| 564 | 561 | void validate() { |
|---|
| 565 | 562 | // Try to enforce sensible values, whilst being reasonably flexible: |
|---|
| 566 | | if (miscOpts.maxThreads < 1 || miscOpts.maxThreads > 64) { |
|---|
| | 563 | if (maxThreads() < 1 || maxThreads() > 64) { |
|---|
| 567 | 564 | logger.warn ("maxThreads must be in the range 1-64. Defaulting to 4."); |
|---|
| 568 | | miscOpts.set!(int)("maxThreads", 4); |
|---|
| 569 | | } |
|---|
| 570 | | if (pollInterval !<= 1.0 || pollInterval !>= 0.0) |
|---|
| 571 | | set!(double) ("pollInterval", 0.01); |
|---|
| | 565 | maxThreads = 4; |
|---|
| | 566 | } |
|---|
| | 567 | if (pollInterval() !<= 1.0 || pollInterval() !>= 0.0) |
|---|
| | 568 | pollInterval = 0.01; |
|---|
| 572 | 569 | } |
|---|
| 573 | 570 | |
|---|
| r81 |
r98 |
|
| 114 | 114 | = [cast(ID) miscOpts.L10n]; // start by loading the current locale |
|---|
| 115 | 115 | |
|---|
| 116 | | Translation transl = new Translation (name, miscOpts.L10n); |
|---|
| | 116 | Translation transl = new Translation (name, miscOpts.L10n()); |
|---|
| 117 | 117 | |
|---|
| 118 | 118 | IReader reader; |
|---|
| r95 |
r98 |
|
| 37 | 37 | |
|---|
| 38 | 38 | //BEGIN A simple drawable to print a message in the window. |
|---|
| | 39 | /* This block of code is to draw the message you see on the screen. Most users of mde would be |
|---|
| | 40 | better off using the gui drawable in gui.WidgetManager than this. */ |
|---|
| 39 | 41 | import mde.font.font; |
|---|
| 40 | 42 | class SimpleDrawable : Screen.IDrawable { |
|---|
| r95 |
r98 |
|
| 147 | 147 | Logger root; |
|---|
| 148 | 148 | try { |
|---|
| 149 | | enum LOG { |
|---|
| 150 | | LEVEL = 0xF, // mask for log level |
|---|
| 151 | | CONSOLE = 0x1000, // log to console? |
|---|
| 152 | | ROLLFILE= 0x2000 // use Rolling/Switching File Appender? |
|---|
| 153 | | } |
|---|
| 154 | | |
|---|
| 155 | 149 | // Where logging is done to is determined at compile-time, currently just via static ifs. |
|---|
| 156 | 150 | root = Log.root; |
|---|
| … | … | |
| 158 | 152 | |
|---|
| 159 | 153 | // Now re-set the logging level, using the value from the config file: |
|---|
| 160 | | root.level (cast(Level) (miscOpts.logOptions & LOG.LEVEL), true); |
|---|
| | 154 | root.level (miscOpts.logOutput() == 0 ? Level.None : cast(Level) miscOpts.logLevel(), true); |
|---|
| 161 | 155 | |
|---|
| 162 | | // Log to a file (first appender so root seperator messages don't show on console): |
|---|
| 163 | | if (miscOpts.logOptions & LOG.ROLLFILE) { |
|---|
| 164 | | // Use 2 log files with a maximum size of 1 MB: |
|---|
| 165 | | root.add (new AppendFiles (paths.logDir~"/log-.txt", 2, 1024*1024)); |
|---|
| 166 | | root.info (""); // some kind of separation between runs |
|---|
| 167 | | root.info (""); |
|---|
| 168 | | } else if (!(miscOpts.logOptions & LOG.CONSOLE)) { |
|---|
| 169 | | // make sure at least one logger is enabled |
|---|
| 170 | | miscOpts.set!(int) ("logOptions", miscOpts.logOptions | LOG.CONSOLE); |
|---|
| | 156 | if (miscOpts.logOutput() & 2) { // first appender so root seperator messages don't show on console |
|---|
| | 157 | // Use 2 log files with a maximum size of 16kiB: |
|---|
| | 158 | root.add (new AppendFiles (paths.logDir~"/log-.txt", 2, 16*1024)); |
|---|
| | 159 | root.append (Level.None, ""); // some kind of separation between runs |
|---|
| | 160 | root.append (Level.None, ""); |
|---|
| 171 | 161 | } |
|---|
| 172 | | if (miscOpts.logOptions & LOG.CONSOLE) { // Log to the console |
|---|
| | 162 | if (miscOpts.logOutput() & 1) |
|---|
| 173 | 163 | root.add(new AppendConsole); |
|---|
| 174 | | } |
|---|
| 175 | 164 | logger.info ("Starting mde [no version] on " ~ TimeStamp.toString(WallClock.now)); |
|---|
| 176 | 165 | } catch (Exception e) { |
|---|
| … | … | |
| 257 | 246 | } |
|---|
| 258 | 247 | // Counts number of active threads, and before threads are started is number to use: |
|---|
| 259 | | size_t numWorking = (toRun.size < miscOpts.maxThreads) ? toRun.size : miscOpts.maxThreads; |
|---|
| | 248 | size_t numWorking = (toRun.size < miscOpts.maxThreads()) ? toRun.size : miscOpts.maxThreads(); |
|---|
| 260 | 249 | enum STATE { WORKING = 0, DONE = 1, ABORT = 2 } |
|---|
| 261 | 250 | STATE doneInit = STATE.WORKING; |
|---|
| … | … | |
| 382 | 371 | logger.error ("Exception while using threads: "~e.msg); |
|---|
| 383 | 372 | logger.error ("Disabling threads and attempting to continue."); |
|---|
| 384 | | miscOpts.set!(int)("NumThreads", 1); // count includes current thread |
|---|
| | 373 | miscOpts.maxThreads = 1; // count includes current thread |
|---|
| 385 | 374 | auto x = new InitStageThread (0); |
|---|
| 386 | 375 | x.initThreadFct(); // try with just this thread |
|---|
| r97 |
r98 |
|
| 83 | 83 | if (videoOpts.fullscreen()) { |
|---|
| 84 | 84 | flags |= SDL_FULLSCREEN; |
|---|
| 85 | | w = videoOpts.screenW; |
|---|
| 86 | | h = videoOpts.screenH; |
|---|
| | 85 | w = videoOpts.screenW(); |
|---|
| | 86 | h = videoOpts.screenH(); |
|---|
| 87 | 87 | } |
|---|
| 88 | 88 | else { |
|---|
| 89 | 89 | if (videoOpts.resizable()) flags |= SDL_RESIZABLE; |
|---|
| 90 | 90 | if (videoOpts.noFrame()) flags |= SDL_NOFRAME; |
|---|
| 91 | | w = videoOpts.windowW; |
|---|
| 92 | | h = videoOpts.windowH; |
|---|
| | 91 | w = videoOpts.windowW(); |
|---|
| | 92 | h = videoOpts.windowH(); |
|---|
| 93 | 93 | } |
|---|
| 94 | 94 | |
|---|
| … | … | |
| 158 | 158 | // Save new size to config |
|---|
| 159 | 159 | if (videoOpts.fullscreen()) { // probably resizeEvent only called when not fullscreen |
|---|
| 160 | | videoOpts.set!(int) ("screenW", w); |
|---|
| 161 | | videoOpts.set!(int) ("screenH", h); |
|---|
| | 160 | videoOpts.screenW = w; |
|---|
| | 161 | videoOpts.screenH = h; |
|---|
| 162 | 162 | } else { |
|---|
| 163 | | videoOpts.set!(int) ("windowW", w); |
|---|
| 164 | | videoOpts.set!(int) ("windowH", h); |
|---|
| | 163 | videoOpts.windowW = w; |
|---|
| | 164 | videoOpts.windowH = h; |
|---|
| 165 | 165 | } |
|---|
| 166 | 166 | |
|---|