1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
|
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/xhtml;charset=UTF-8"/>
<title>Irrlicht 3D Engine: Tutorial 25: Xml Handling</title>
<link href="tabs.css" rel="stylesheet" type="text/css"/>
<link href="doxygen.css" rel="stylesheet" type="text/css" />
<link href="navtree.css" rel="stylesheet" type="text/css"/>
<script type="text/javascript" src="jquery.js"></script>
<script type="text/javascript" src="resize.js"></script>
<script type="text/javascript" src="navtree.js"></script>
<script type="text/javascript">
$(document).ready(initResizable);
</script>
<link href="search/search.css" rel="stylesheet" type="text/css"/>
<script type="text/javascript" src="search/search.js"></script>
<script type="text/javascript">
$(document).ready(function() { searchBox.OnSelectItem(0); });
</script>
</head>
<body>
<div id="top"><!-- do not remove this div! -->
<div id="titlearea">
<table cellspacing="0" cellpadding="0">
<tbody>
<tr style="height: 56px;">
<td id="projectlogo"><img alt="Logo" src="irrlichtlogo.png"/></td>
<td style="padding-left: 0.5em;">
<div id="projectname">Irrlicht 3D Engine
</div>
</td>
<td> <div id="MSearchBox" class="MSearchBoxInactive">
<span class="left">
<img id="MSearchSelect" src="search/mag_sel.png"
onmouseover="return searchBox.OnSearchSelectShow()"
onmouseout="return searchBox.OnSearchSelectHide()"
alt=""/>
<input type="text" id="MSearchField" value="Search" accesskey="S"
onfocus="searchBox.OnSearchFieldFocus(true)"
onblur="searchBox.OnSearchFieldFocus(false)"
onkeyup="searchBox.OnSearchFieldChange(event)"/>
</span><span class="right">
<a id="MSearchClose" href="javascript:searchBox.CloseResultsWindow()"><img id="MSearchCloseImg" border="0" src="search/close.png" alt=""/></a>
</span>
</div>
</td>
</tr>
</tbody>
</table>
</div>
<!-- Generated by Doxygen 1.7.5.1 -->
<script type="text/javascript">
var searchBox = new SearchBox("searchBox", "search",false,'Search');
</script>
<script type="text/javascript" src="dynsections.js"></script>
</div>
<div id="side-nav" class="ui-resizable side-nav-resizable">
<div id="nav-tree">
<div id="nav-tree-contents">
</div>
</div>
<div id="splitbar" style="-moz-user-select:none;"
class="ui-resizable-handle">
</div>
</div>
<script type="text/javascript">
initNavTree('example025.html','');
</script>
<div id="doc-content">
<div class="header">
<div class="headertitle">
<div class="title">Tutorial 25: Xml Handling </div> </div>
</div>
<div class="contents">
<div class="textblock"><div class="image">
<img src="025shot.jpg" alt="025shot.jpg"/>
</div>
<p>Demonstrates loading and saving of configurations via XML</p>
<dl class="author"><dt><b>Author:</b></dt><dd>Y.M. Bosman <<a href="mailto:yoran.bosman@gmail.com">yoran.bosman@gmail.com</a>></dd></dl>
<p>This demo features a fully usable system for configuration handling. The code can easily be integrated into own apps.</p>
<div class="fragment"><pre class="fragment"><span class="preprocessor">#include <<a class="code" href="irrlicht_8h.html" title="Main header file of the irrlicht, the only file needed to include.">irrlicht.h</a>></span>
<span class="keyword">using namespace </span>irr;
<span class="keyword">using namespace </span>core;
<span class="keyword">using namespace </span>scene;
<span class="keyword">using namespace </span>video;
<span class="keyword">using namespace </span>io;
<span class="keyword">using namespace </span>gui;
<span class="preprocessor">#ifdef _IRR_WINDOWS_</span>
<span class="preprocessor"></span><span class="preprocessor">#pragma comment(lib, "Irrlicht.lib")</span>
<span class="preprocessor">#endif</span>
</pre></div><p> SettingManager class.</p>
<p>This class loads and writes the settings and manages the options.</p>
<p>The class makes use of irrMap which is a an associative arrays using a red-black tree it allows easy mapping of a key to a value, along the way there is some information on how to use it. </p>
<div class="fragment"><pre class="fragment"><span class="keyword">class </span>SettingManager
{
<span class="keyword">public</span>:
<span class="comment">// Construct setting managers and set default settings</span>
SettingManager(<span class="keyword">const</span> <a class="code" href="namespaceirr_1_1core.html#aef83fafbb1b36fcce44c07c9be23a7f2" title="Typedef for wide character strings.">stringw</a>& settings_file): SettingsFile(settings_file), NullDevice(0)
{
<span class="comment">// Irrlicht null device, we want to load settings before we actually created our device, therefore, nulldevice</span>
NullDevice = <a class="code" href="namespaceirr.html#abaf4d8719cc26b0d30813abf85e47c76" title="Creates an Irrlicht device. The Irrlicht device is the root object for using the engine.">irr::createDevice</a>(<a class="code" href="namespaceirr_1_1video.html#ae35a6de6d436c76107ad157fe42356d0acfdbd476cbfd4d05e72f9adffcc42210" title="Null driver, useful for applications to run the engine without visualisation.">irr::video::EDT_NULL</a>);
<span class="comment">//DriverOptions is an irrlicht map,</span>
<span class="comment">//we can insert values in the map in two ways by calling insert(key,value) or by using the [key] operator</span>
<span class="comment">//the [] operator overrides values if they already exist</span>
DriverOptions.insert(L<span class="stringliteral">"Software"</span>, <a class="code" href="namespaceirr_1_1video.html#ae35a6de6d436c76107ad157fe42356d0a1598cd235a1a6bd052e2011b559e8995" title="The Irrlicht Engine Software renderer.">EDT_SOFTWARE</a>);
DriverOptions.insert(L<span class="stringliteral">"OpenGL"</span>, <a class="code" href="namespaceirr_1_1video.html#ae35a6de6d436c76107ad157fe42356d0a2715182a79f1cb8e2826fd68a8150a53" title="OpenGL device, available on most platforms.">EDT_OPENGL</a>);
DriverOptions.insert(L<span class="stringliteral">"Direct3D9"</span>, <a class="code" href="namespaceirr_1_1video.html#ae35a6de6d436c76107ad157fe42356d0a4691ca314f9018f508dcf2c57dcaacec" title="Direct3D 9 device, only available on Win32 platforms.">EDT_DIRECT3D9</a>);
<span class="comment">//some resolution options</span>
ResolutionOptions.insert(L<span class="stringliteral">"640x480"</span>, <a class="code" href="namespaceirr_1_1core.html#ad2e562e3219072e2f7fc7c2bba0ef0cb" title="Typedef for an unsigned integer dimension.">dimension2du</a>(640,480));
ResolutionOptions.insert(L<span class="stringliteral">"800x600"</span>, <a class="code" href="namespaceirr_1_1core.html#ad2e562e3219072e2f7fc7c2bba0ef0cb" title="Typedef for an unsigned integer dimension.">dimension2du</a>(800,600));
ResolutionOptions.insert(L<span class="stringliteral">"1024x768"</span>, <a class="code" href="namespaceirr_1_1core.html#ad2e562e3219072e2f7fc7c2bba0ef0cb" title="Typedef for an unsigned integer dimension.">dimension2du</a>(1024,768));
<span class="comment">//our preferred defaults</span>
SettingMap.insert(L<span class="stringliteral">"driver"</span>, L<span class="stringliteral">"Direct3D9"</span>);
SettingMap.insert(L<span class="stringliteral">"resolution"</span>, L<span class="stringliteral">"640x480"</span>);
SettingMap.insert(L<span class="stringliteral">"fullscreen"</span>, L<span class="stringliteral">"0"</span>); <span class="comment">//0 is false</span>
}
<span class="comment">// Destructor, you could store settings automatically on exit of your</span>
<span class="comment">// application if you wanted to in our case we simply drop the</span>
<span class="comment">// nulldevice</span>
~SettingManager()
{
<span class="keywordflow">if</span> (NullDevice)
{
NullDevice->closeDevice();
NullDevice->drop();
}
};
</pre></div><p>Load xml from disk, overwrite default settings The xml we are trying to load has the following structure settings nested in sections nested in the root node, like so </p>
<pre>
<?xml version="1.0"?>
<mygame>
<video>
<setting name="driver" value="Direct3D9">
<setting name="fullscreen" value="0">
<setting name="resolution" value="1024x768">
</video>
</mygame>
</pre> <div class="fragment"><pre class="fragment"> <span class="keywordtype">bool</span> load()
{
<span class="comment">//if not able to create device don't attempt to load</span>
<span class="keywordflow">if</span> (!NullDevice)
<span class="keywordflow">return</span> <span class="keyword">false</span>;
<a class="code" href="classirr_1_1io_1_1_i_irr_x_m_l_reader.html" title="Interface providing easy read access to a XML file.">irr::io::IXMLReader</a>* xml = NullDevice->getFileSystem()->createXMLReader(SettingsFile); <span class="comment">//create xml reader</span>
<span class="keywordflow">if</span> (!xml)
<span class="keywordflow">return</span> <span class="keyword">false</span>;
<span class="keyword">const</span> <a class="code" href="namespaceirr_1_1core.html#aef83fafbb1b36fcce44c07c9be23a7f2" title="Typedef for wide character strings.">stringw</a> settingTag(L<span class="stringliteral">"setting"</span>); <span class="comment">//we'll be looking for this tag in the xml</span>
<a class="code" href="namespaceirr_1_1core.html#aef83fafbb1b36fcce44c07c9be23a7f2" title="Typedef for wide character strings.">stringw</a> currentSection; <span class="comment">//keep track of our current section</span>
<span class="keyword">const</span> <a class="code" href="namespaceirr_1_1core.html#aef83fafbb1b36fcce44c07c9be23a7f2" title="Typedef for wide character strings.">stringw</a> videoTag(L<span class="stringliteral">"video"</span>); <span class="comment">//constant for videotag</span>
<span class="comment">//while there is more to read</span>
<span class="keywordflow">while</span> (xml-><a class="code" href="classirr_1_1io_1_1_i_irr_x_m_l_reader.html#a157f458f7dabeeff173f72a0fb443a8e" title="Reads forward to the next xml node.">read</a>())
{
<span class="comment">//check the node type</span>
<span class="keywordflow">switch</span> (xml-><a class="code" href="classirr_1_1io_1_1_i_irr_x_m_l_reader.html#a3482e8e6bdc15965fc6a0bcef6e9a8e0" title="Returns the type of the current XML node.">getNodeType</a>())
{
<span class="comment">//we found a new element</span>
<span class="keywordflow">case</span> <a class="code" href="namespaceirr_1_1io.html#a86a02676c9cbb822e04d60c81b4f33eda9df4f5baccc23a0ad1f6fa64d8de2fc0" title="An xml element such as <foo>.">irr::io::EXN_ELEMENT</a>:
{
<span class="comment">//we currently are in the empty or mygame section and find the video tag so we set our current section to video</span>
<span class="keywordflow">if</span> (currentSection.empty() && videoTag.equals_ignore_case(xml-><a class="code" href="classirr_1_1io_1_1_i_irr_x_m_l_reader.html#a7d745b130c895d0f910f191d04e20e87" title="Returns the name of the current node.">getNodeName</a>()))
{
currentSection = videoTag;
}
<span class="comment">//we are in the video section and we find a setting to parse</span>
<span class="keywordflow">else</span> <span class="keywordflow">if</span> (currentSection.equals_ignore_case(videoTag) && settingTag.equals_ignore_case(xml-><a class="code" href="classirr_1_1io_1_1_i_irr_x_m_l_reader.html#a7d745b130c895d0f910f191d04e20e87" title="Returns the name of the current node.">getNodeName</a>() ))
{
<span class="comment">//read in the key</span>
<a class="code" href="namespaceirr_1_1core.html#aef83fafbb1b36fcce44c07c9be23a7f2" title="Typedef for wide character strings.">stringw</a> key = xml-><a class="code" href="classirr_1_1io_1_1_i_irr_x_m_l_reader.html#a7674852b2e24b2710b90aab10ef1fc22" title="Returns the value of an attribute in a safe way.">getAttributeValueSafe</a>(L<span class="stringliteral">"name"</span>);
<span class="comment">//if there actually is a key to set</span>
<span class="keywordflow">if</span> (!key.empty())
{
<span class="comment">//set the setting in the map to the value,</span>
<span class="comment">//the [] operator overrides values if they already exist or inserts a new key value</span>
<span class="comment">//pair into the settings map if it was not defined yet</span>
SettingMap[key] = xml-><a class="code" href="classirr_1_1io_1_1_i_irr_x_m_l_reader.html#a7674852b2e24b2710b90aab10ef1fc22" title="Returns the value of an attribute in a safe way.">getAttributeValueSafe</a>(L<span class="stringliteral">"value"</span>);
}
}
<span class="comment">//..</span>
<span class="comment">// You can add your own sections and tags to read in here</span>
<span class="comment">//..</span>
}
<span class="keywordflow">break</span>;
<span class="comment">//we found the end of an element</span>
<span class="keywordflow">case</span> <a class="code" href="namespaceirr_1_1io.html#a86a02676c9cbb822e04d60c81b4f33eda54ef1997279f08180634f4a897f771b8" title="End of an xml element such as </foo>.">irr::io::EXN_ELEMENT_END</a>:
<span class="comment">//we were at the end of the video section so we reset our tag</span>
currentSection=L<span class="stringliteral">""</span>;
<span class="keywordflow">break</span>;
}
}
<span class="comment">// don't forget to delete the xml reader</span>
xml->drop();
<span class="keywordflow">return</span> <span class="keyword">true</span>;
}
<span class="comment">// Save the xml to disk. We use the nulldevice.</span>
<span class="keywordtype">bool</span> save()
{
<span class="comment">//if not able to create device don't attempt to save</span>
<span class="keywordflow">if</span> (!NullDevice)
<span class="keywordflow">return</span> <span class="keyword">false</span>;
<span class="comment">//create xml writer</span>
<a class="code" href="classirr_1_1io_1_1_i_x_m_l_writer.html" title="Interface providing methods for making it easier to write XML files.">irr::io::IXMLWriter</a>* xwriter = NullDevice->getFileSystem()->createXMLWriter( SettingsFile );
<span class="keywordflow">if</span> (!xwriter)
<span class="keywordflow">return</span> <span class="keyword">false</span>;
<span class="comment">//write out the obligatory xml header. Each xml-file needs to have exactly one of those.</span>
xwriter-><a class="code" href="classirr_1_1io_1_1_i_x_m_l_writer.html#a66fd00f6528fc967e53ea2a83f4fbf09" title="Writes an xml 1.0 header.">writeXMLHeader</a>();
<span class="comment">//start element mygame, you replace the label "mygame" with anything you want</span>
xwriter-><a class="code" href="classirr_1_1io_1_1_i_x_m_l_writer.html#a09ffde58db20f23b7eba1bf08e1daf42">writeElement</a>(L<span class="stringliteral">"mygame"</span>);
xwriter-><a class="code" href="classirr_1_1io_1_1_i_x_m_l_writer.html#a98d9b558d991211f77f6d3f2f68d30d2" title="Writes a line break.">writeLineBreak</a>(); <span class="comment">//new line</span>
<span class="comment">//start section with video settings</span>
xwriter-><a class="code" href="classirr_1_1io_1_1_i_x_m_l_writer.html#a09ffde58db20f23b7eba1bf08e1daf42">writeElement</a>(L<span class="stringliteral">"video"</span>);
xwriter-><a class="code" href="classirr_1_1io_1_1_i_x_m_l_writer.html#a98d9b558d991211f77f6d3f2f68d30d2" title="Writes a line break.">writeLineBreak</a>(); <span class="comment">//new line</span>
<span class="comment">// getIterator gets us a pointer to the first node of the settings map</span>
<span class="comment">// every iteration we increase the iterator which gives us the next map node</span>
<span class="comment">// until we reach the end we write settings one by one by using the nodes key and value functions</span>
map<stringw, stringw>::Iterator i = SettingMap.getIterator();
<span class="keywordflow">for</span>(; !i.atEnd(); i++)
{
<span class="comment">//write element as <setting name="key" value="x" /></span>
<span class="comment">//the second parameter indicates this is an empty element with no children, just attributes</span>
xwriter-><a class="code" href="classirr_1_1io_1_1_i_x_m_l_writer.html#a09ffde58db20f23b7eba1bf08e1daf42">writeElement</a>(L<span class="stringliteral">"setting"</span>,<span class="keyword">true</span>, L<span class="stringliteral">"name"</span>, i->getKey().c_str(), L<span class="stringliteral">"value"</span>,i->getValue().c_str() );
xwriter-><a class="code" href="classirr_1_1io_1_1_i_x_m_l_writer.html#a98d9b558d991211f77f6d3f2f68d30d2" title="Writes a line break.">writeLineBreak</a>();
}
xwriter-><a class="code" href="classirr_1_1io_1_1_i_x_m_l_writer.html#a98d9b558d991211f77f6d3f2f68d30d2" title="Writes a line break.">writeLineBreak</a>();
<span class="comment">//close video section</span>
xwriter-><a class="code" href="classirr_1_1io_1_1_i_x_m_l_writer.html#a904c931fe03455eee04fcf41ef519715" title="Writes the closing tag for an element. Like "</foo>".">writeClosingTag</a>(L<span class="stringliteral">"video"</span>);
xwriter-><a class="code" href="classirr_1_1io_1_1_i_x_m_l_writer.html#a98d9b558d991211f77f6d3f2f68d30d2" title="Writes a line break.">writeLineBreak</a>();
<span class="comment">//..</span>
<span class="comment">// You can add writing sound settings, savegame information etc</span>
<span class="comment">//..</span>
<span class="comment">//close mygame section</span>
xwriter-><a class="code" href="classirr_1_1io_1_1_i_x_m_l_writer.html#a904c931fe03455eee04fcf41ef519715" title="Writes the closing tag for an element. Like "</foo>".">writeClosingTag</a>(L<span class="stringliteral">"mygame"</span>);
<span class="comment">//delete xml writer</span>
xwriter-><a class="code" href="classirr_1_1_i_reference_counted.html#afb169a857e0d2cdb96b8821cb9bff17a" title="Drops the object. Decrements the reference counter by one.">drop</a>();
<span class="keywordflow">return</span> <span class="keyword">true</span>;
}
<span class="comment">// Set setting in our manager</span>
<span class="keywordtype">void</span> setSetting(<span class="keyword">const</span> <a class="code" href="namespaceirr_1_1core.html#aef83fafbb1b36fcce44c07c9be23a7f2" title="Typedef for wide character strings.">stringw</a>& name, <span class="keyword">const</span> <a class="code" href="namespaceirr_1_1core.html#aef83fafbb1b36fcce44c07c9be23a7f2" title="Typedef for wide character strings.">stringw</a>& value)
{
SettingMap[name]=value;
}
<span class="comment">// set setting overload to quickly assign integers to our setting map</span>
<span class="keywordtype">void</span> setSetting(<span class="keyword">const</span> <a class="code" href="namespaceirr_1_1core.html#aef83fafbb1b36fcce44c07c9be23a7f2" title="Typedef for wide character strings.">stringw</a>& name, <a class="code" href="namespaceirr.html#ac66849b7a6ed16e30ebede579f9b47c6" title="32 bit signed variable.">s32</a> value)
{
SettingMap[name]=<a class="code" href="namespaceirr_1_1core.html#aef83fafbb1b36fcce44c07c9be23a7f2" title="Typedef for wide character strings.">stringw</a>(value);
}
<span class="comment">// Get setting as string</span>
<a class="code" href="namespaceirr_1_1core.html#aef83fafbb1b36fcce44c07c9be23a7f2" title="Typedef for wide character strings.">stringw</a> getSetting(<span class="keyword">const</span> <a class="code" href="namespaceirr_1_1core.html#aef83fafbb1b36fcce44c07c9be23a7f2" title="Typedef for wide character strings.">stringw</a>& key)<span class="keyword"> const</span>
<span class="keyword"> </span>{
<span class="comment">//the find function or irrmap returns a pointer to a map Node</span>
<span class="comment">//if the key can be found, otherwise it returns null</span>
<span class="comment">//the map node has the function getValue and getKey, as we already know the key, we return node->getValue()</span>
map<stringw, stringw>::Node* n = SettingMap.find(key);
<span class="keywordflow">if</span> (n)
<span class="keywordflow">return</span> n->getValue();
<span class="keywordflow">else</span>
<span class="keywordflow">return</span> L<span class="stringliteral">""</span>;
}
<span class="comment">//</span>
<span class="keywordtype">bool</span> getSettingAsBoolean(<span class="keyword">const</span> <a class="code" href="namespaceirr_1_1core.html#aef83fafbb1b36fcce44c07c9be23a7f2" title="Typedef for wide character strings.">stringw</a>& key )<span class="keyword"> const</span>
<span class="keyword"> </span>{
<a class="code" href="namespaceirr_1_1core.html#aef83fafbb1b36fcce44c07c9be23a7f2" title="Typedef for wide character strings.">stringw</a> s = getSetting(key);
<span class="keywordflow">if</span> (s.empty())
<span class="keywordflow">return</span> <span class="keyword">false</span>;
<span class="keywordflow">return</span> s.equals_ignore_case(L<span class="stringliteral">"1"</span>);
}
<span class="comment">//</span>
<a class="code" href="namespaceirr.html#ac66849b7a6ed16e30ebede579f9b47c6" title="32 bit signed variable.">s32</a> getSettingAsInteger(<span class="keyword">const</span> <a class="code" href="namespaceirr_1_1core.html#aef83fafbb1b36fcce44c07c9be23a7f2" title="Typedef for wide character strings.">stringw</a>& key)<span class="keyword"> const</span>
<span class="keyword"> </span>{
<span class="comment">//we implicitly cast to string instead of stringw because strtol10 does not accept wide strings</span>
<span class="keyword">const</span> <a class="code" href="namespaceirr_1_1core.html#ade1071a878633f2f6d8a75c5d11fec19" title="Typedef for character strings.">stringc</a> s = getSetting(key);
<span class="keywordflow">if</span> (s.empty())
<span class="keywordflow">return</span> 0;
<span class="keywordflow">return</span> <a class="code" href="namespaceirr_1_1core.html#a6ff97e442233218d18acd56add48766f" title="Convert a simple string of base 10 digits into a signed 32 bit integer.">strtol10</a>(s.c_str());
}
<span class="keyword">public</span>:
map<stringw, s32> DriverOptions; <span class="comment">//available options for driver config</span>
map<stringw, dimension2du> ResolutionOptions; <span class="comment">//available options for resolution config</span>
<span class="keyword">private</span>:
SettingManager(<span class="keyword">const</span> SettingManager& other); <span class="comment">// defined but not implemented</span>
SettingManager& operator=(<span class="keyword">const</span> SettingManager& other); <span class="comment">// defined but not implemented</span>
map<stringw, stringw> SettingMap; <span class="comment">//current config</span>
<a class="code" href="namespaceirr_1_1core.html#aef83fafbb1b36fcce44c07c9be23a7f2" title="Typedef for wide character strings.">stringw</a> SettingsFile; <span class="comment">// location of the xml, usually the</span>
<a class="code" href="classirr_1_1_irrlicht_device.html" title="The Irrlicht device. You can create it with createDevice() or createDeviceEx().">irr::IrrlichtDevice</a>* NullDevice;
};
</pre></div><p>Application context for global variables </p>
<div class="fragment"><pre class="fragment"><span class="keyword">struct </span>SAppContext
{
SAppContext()
: Device(0),Gui(0), Driver(0), Settings(0), ShouldQuit(false),
ButtonSave(0), ButtonExit(0), ListboxDriver(0),
ListboxResolution(0), CheckboxFullscreen(0)
{
}
~SAppContext()
{
<span class="keywordflow">if</span> (Settings)
<span class="keyword">delete</span> Settings;
<span class="keywordflow">if</span> (Device)
{
Device->closeDevice();
Device->drop();
}
}
IrrlichtDevice* Device;
IGUIEnvironment* Gui;
IVideoDriver* Driver;
SettingManager* Settings;
<span class="keywordtype">bool</span> ShouldQuit;
<span class="comment">//settings dialog</span>
IGUIButton* ButtonSave;
IGUIButton* ButtonExit;
IGUIListBox* ListboxDriver;
IGUIListBox* ListboxResolution;
IGUICheckBox* CheckboxFullscreen;
};
</pre></div><p>A typical event receiver. </p>
<div class="fragment"><pre class="fragment"><span class="keyword">class </span>MyEventReceiver : <span class="keyword">public</span> IEventReceiver
{
<span class="keyword">public</span>:
MyEventReceiver(SAppContext & a) : App(a) { }
<span class="keyword">virtual</span> <span class="keywordtype">bool</span> OnEvent(<span class="keyword">const</span> SEvent& event)
{
<span class="keywordflow">if</span> (event.EventType == <a class="code" href="namespaceirr.html#ac9eed96e06e85ce3c86fcbbbe9e48a0cae85bb44dd09a29c879d64a05047fc1d2" title="An event of the graphical user interface.">EET_GUI_EVENT</a> )
{
<span class="keywordflow">switch</span> ( event.GUIEvent.EventType )
{
<span class="comment">//handle button click events</span>
<span class="keywordflow">case</span> <a class="code" href="namespaceirr_1_1gui.html#aeac71ad17341a4b6e9026ae11d576808a308ee345c92444931f83e48354072d98" title="A button was clicked.">EGET_BUTTON_CLICKED</a>:
{
<span class="comment">//Our save button was called so we obtain the settings from our dialog and save them</span>
<span class="keywordflow">if</span> ( event.GUIEvent.Caller == App.ButtonSave )
{
<span class="comment">//if there is a selection write it</span>
<span class="keywordflow">if</span> ( App.ListboxDriver->getSelected() != -1)
App.Settings->setSetting(L<span class="stringliteral">"driver"</span>, App.ListboxDriver->getListItem(App.ListboxDriver->getSelected()));
<span class="comment">//if there is a selection write it</span>
<span class="keywordflow">if</span> ( App.ListboxResolution->getSelected() != -1)
App.Settings->setSetting(L<span class="stringliteral">"resolution"</span>, App.ListboxResolution->getListItem(App.ListboxResolution->getSelected()));
App.Settings->setSetting(L<span class="stringliteral">"fullscreen"</span>, App.CheckboxFullscreen->isChecked());
<span class="keywordflow">if</span> (App.Settings->save())
{
App.Gui->addMessageBox(L<span class="stringliteral">"settings save"</span>,L<span class="stringliteral">"settings saved, please restart for settings to change effect"</span>,<span class="stringliteral">""</span>,<span class="keyword">true</span>);
}
}
<span class="comment">// cancel/exit button clicked, tell the application to exit</span>
<span class="keywordflow">else</span> <span class="keywordflow">if</span> ( event.GUIEvent.Caller == App.ButtonExit)
{
App.ShouldQuit = <span class="keyword">true</span>;
}
}
<span class="keywordflow">break</span>;
}
}
<span class="keywordflow">return</span> <span class="keyword">false</span>;
}
<span class="keyword">private</span>:
SAppContext & App;
};
</pre></div><p>Function to create a video settings dialog This dialog shows the current settings from the configuration xml and allows them to be changed </p>
<div class="fragment"><pre class="fragment"><span class="keywordtype">void</span> createSettingsDialog(SAppContext& app)
{
<span class="comment">// first get rid of alpha in gui</span>
<span class="keywordflow">for</span> (<a class="code" href="namespaceirr.html#ac66849b7a6ed16e30ebede579f9b47c6" title="32 bit signed variable.">irr::s32</a> i=0; i<<a class="code" href="namespaceirr_1_1gui.html#abd15860fde29833c48daff5f95d5467aaf340f49e2e0827c0f06fdf65098554af">irr::gui::EGDC_COUNT</a> ; ++i)
{
<a class="code" href="classirr_1_1video_1_1_s_color.html" title="Class representing a 32 bit ARGB color.">irr::video::SColor</a> col = app.Gui->getSkin()->getColor((<a class="code" href="namespaceirr_1_1gui.html#abd15860fde29833c48daff5f95d5467a" title="Enumeration for skin colors.">irr::gui::EGUI_DEFAULT_COLOR</a>)i);
col.<a class="code" href="classirr_1_1video_1_1_s_color.html#a7bfe4abc30d563668b947c8bdb055bab" title="Sets the alpha component of the Color.">setAlpha</a>(255);
app.Gui->getSkin()->setColor((<a class="code" href="namespaceirr_1_1gui.html#abd15860fde29833c48daff5f95d5467a" title="Enumeration for skin colors.">irr::gui::EGUI_DEFAULT_COLOR</a>)i, col);
}
<span class="comment">//create video settings windows</span>
gui::IGUIWindow* windowSettings = app.Gui->addWindow(rect<s32>(10,10,400,400),<span class="keyword">true</span>,L<span class="stringliteral">"Videosettings"</span>);
app.Gui->addStaticText (L<span class="stringliteral">"Select your desired video settings"</span>, rect< s32 >(10,20, 200, 40), <span class="keyword">false</span>, <span class="keyword">true</span>, windowSettings);
<span class="comment">// add listbox for driver choice</span>
app.Gui->addStaticText (L<span class="stringliteral">"Driver"</span>, rect< s32 >(10,50, 200, 60), <span class="keyword">false</span>, <span class="keyword">true</span>, windowSettings);
app.ListboxDriver = app.Gui->addListBox(rect<s32>(10,60,220,120), windowSettings, 1,<span class="keyword">true</span>);
<span class="comment">//add all available options to the driver choice listbox</span>
map<stringw, s32>::Iterator i = app.Settings->DriverOptions.getIterator();
<span class="keywordflow">for</span>(; !i.atEnd(); i++)
app.ListboxDriver->addItem(i->getKey().c_str());
<span class="comment">//set currently selected driver</span>
app.ListboxDriver->setSelected(app.Settings->getSetting(<span class="stringliteral">"driver"</span>).c_str());
<span class="comment">// add listbox for resolution choice</span>
app.Gui->addStaticText (L<span class="stringliteral">"Resolution"</span>, rect< s32 >(10,130, 200, 140), <span class="keyword">false</span>, <span class="keyword">true</span>, windowSettings);
app.ListboxResolution = app.Gui->addListBox(rect<s32>(10,140,220,200), windowSettings, 1,<span class="keyword">true</span>);
<span class="comment">//add all available options to the resolution listbox</span>
map<stringw, dimension2du>::Iterator ri = app.Settings->ResolutionOptions.getIterator();
<span class="keywordflow">for</span>(; !ri.atEnd(); ri++)
app.ListboxResolution->addItem(ri->getKey().c_str());
<span class="comment">//set currently selected resolution</span>
app.ListboxResolution->setSelected(app.Settings->getSetting(<span class="stringliteral">"resolution"</span>).c_str());
<span class="comment">//add checkbox to toggle fullscreen, initially set to loaded setting</span>
app.CheckboxFullscreen = app.Gui->addCheckBox(
app.Settings->getSettingAsBoolean(<span class="stringliteral">"fullscreen"</span>),
rect<s32>(10,220,220,240), windowSettings, -1,
L<span class="stringliteral">"Fullscreen"</span>);
<span class="comment">//last but not least add save button</span>
app.ButtonSave = app.Gui->addButton(
rect<s32>(80,250,150,270), windowSettings, 2,
L<span class="stringliteral">"Save video settings"</span>);
<span class="comment">//exit/cancel button</span>
app.ButtonExit = app.Gui->addButton(
rect<s32>(160,250,240,270), windowSettings, 2,
L<span class="stringliteral">"Cancel and exit"</span>);
}
</pre></div><p>The main function. Creates all objects and does the XML handling. </p>
<div class="fragment"><pre class="fragment"><span class="keywordtype">int</span> main()
{
<span class="comment">//create new application context</span>
SAppContext app;
<span class="comment">//create device creation parameters that can get overwritten by our settings file</span>
SIrrlichtCreationParameters param;
param.<a class="code" href="structirr_1_1_s_irrlicht_creation_parameters.html#a1ea2f50c3b3a8eed6602a1a86e1cdf82" title="Type of video driver used to render graphics.">DriverType</a> = <a class="code" href="namespaceirr_1_1video.html#ae35a6de6d436c76107ad157fe42356d0a1598cd235a1a6bd052e2011b559e8995" title="The Irrlicht Engine Software renderer.">EDT_SOFTWARE</a>;
param.WindowSize.set(640,480);
<span class="comment">// Try to load config.</span>
<span class="comment">// I leave it as an exercise of the reader to store the configuration in the local application data folder,</span>
<span class="comment">// the only logical place to store config data for games. For all other operating systems I redirect to your manuals</span>
app.Settings = <span class="keyword">new</span> SettingManager(<span class="stringliteral">"../../media/settings.xml"</span>);
<span class="keywordflow">if</span> ( !app.Settings->load() )
{
<span class="comment">// ...</span>
<span class="comment">// Here add your own exception handling, for now we continue because there are defaults set in SettingManager constructor</span>
<span class="comment">// ...</span>
}
<span class="keywordflow">else</span>
{
<span class="comment">//settings xml loaded from disk,</span>
<span class="comment">//map driversetting to driver type and test if the setting is valid</span>
<span class="comment">//the DriverOptions map contains string representations mapped to to irrlicht E_DRIVER_TYPE enum</span>
<span class="comment">//e.g "direct3d9" will become 4</span>
<span class="comment">//see DriverOptions in the settingmanager class for details</span>
map<stringw, s32>::Node* driver = app.Settings->DriverOptions.find( app.Settings->getSetting(<span class="stringliteral">"driver"</span>) );
<span class="keywordflow">if</span> (driver)
{
<span class="keywordflow">if</span> ( <a class="code" href="classirr_1_1_irrlicht_device.html#a5a74995aec731b26c6a9cb5bea6842fe" title="Check if a driver type is supported by the engine.">irr::IrrlichtDevice::isDriverSupported</a>( static_cast<E_DRIVER_TYPE>( driver->getValue() )))
{
<span class="comment">// selected driver is supported, so we use it.</span>
param.DriverType = <span class="keyword">static_cast<</span><a class="code" href="namespaceirr_1_1video.html#ae35a6de6d436c76107ad157fe42356d0" title="An enum for all types of drivers the Irrlicht Engine supports.">E_DRIVER_TYPE</a><span class="keyword">></span>( driver->getValue());
}
}
<span class="comment">//map resolution setting to dimension in a similar way as demonstrated above</span>
map<stringw, dimension2du>::Node* res = app.Settings->ResolutionOptions.find( app.Settings->getSetting(<span class="stringliteral">"resolution"</span>) );
<span class="keywordflow">if</span> (res)
{
param.WindowSize = res->getValue();
}
<span class="comment">//get fullscreen setting from config</span>
param.Fullscreen = app.Settings->getSettingAsBoolean(<span class="stringliteral">"fullscreen"</span>);
}
<span class="comment">//create the irrlicht device using the settings</span>
app.Device = <a class="code" href="namespaceirr.html#ac83a30d674204dcb94d70f849e9b4a62" title="Creates an Irrlicht device with the option to specify advanced parameters.">createDeviceEx</a>(param);
<span class="keywordflow">if</span> (app.Device == 0)
{
<span class="comment">// You can add your own exception handling on driver failure</span>
exit(0);
}
app.Device->setWindowCaption(L<span class="stringliteral">"Xmlhandling - Irrlicht engine tutorial"</span>);
app.Driver = app.Device->getVideoDriver();
app.Gui = app.Device->getGUIEnvironment();
createSettingsDialog(app);
<span class="comment">//set event receiver so we can respond to gui events</span>
MyEventReceiver receiver(app);
app.Device->setEventReceiver(&receiver);
<span class="comment">//enter main loop</span>
<span class="keywordflow">while</span> (!app.ShouldQuit && app.Device->run())
{
<span class="keywordflow">if</span> (app.Device->isWindowActive())
{
app.Driver->beginScene(<span class="keyword">true</span>, <span class="keyword">true</span>, SColor(0,200,200,200));
app.Gui->drawAll();
app.Driver->endScene();
}
app.Device->sleep(10);
}
<span class="comment">//app destroys device in destructor</span>
<span class="keywordflow">return</span> 0;
}
</pre></div> </div></div>
</div>
<div id="nav-path" class="navpath">
<ul>
<!-- window showing the filter options -->
<div id="MSearchSelectWindow"
onmouseover="return searchBox.OnSearchSelectShow()"
onmouseout="return searchBox.OnSearchSelectHide()"
onkeydown="return searchBox.OnSearchSelectKey(event)">
<a class="SelectItem" href="javascript:void(0)" onclick="searchBox.OnSelectItem(0)"><span class="SelectionMark"> </span>All</a><a class="SelectItem" href="javascript:void(0)" onclick="searchBox.OnSelectItem(1)"><span class="SelectionMark"> </span>Classes</a><a class="SelectItem" href="javascript:void(0)" onclick="searchBox.OnSelectItem(2)"><span class="SelectionMark"> </span>Namespaces</a><a class="SelectItem" href="javascript:void(0)" onclick="searchBox.OnSelectItem(3)"><span class="SelectionMark"> </span>Files</a><a class="SelectItem" href="javascript:void(0)" onclick="searchBox.OnSelectItem(4)"><span class="SelectionMark"> </span>Functions</a><a class="SelectItem" href="javascript:void(0)" onclick="searchBox.OnSelectItem(5)"><span class="SelectionMark"> </span>Variables</a><a class="SelectItem" href="javascript:void(0)" onclick="searchBox.OnSelectItem(6)"><span class="SelectionMark"> </span>Typedefs</a><a class="SelectItem" href="javascript:void(0)" onclick="searchBox.OnSelectItem(7)"><span class="SelectionMark"> </span>Enumerations</a><a class="SelectItem" href="javascript:void(0)" onclick="searchBox.OnSelectItem(8)"><span class="SelectionMark"> </span>Enumerator</a><a class="SelectItem" href="javascript:void(0)" onclick="searchBox.OnSelectItem(9)"><span class="SelectionMark"> </span>Friends</a><a class="SelectItem" href="javascript:void(0)" onclick="searchBox.OnSelectItem(10)"><span class="SelectionMark"> </span>Defines</a></div>
<!-- iframe showing the search results (closed by default) -->
<div id="MSearchResultsWindow">
<iframe src="javascript:void(0)" frameborder="0"
name="MSearchResults" id="MSearchResults">
</iframe>
</div>
<li class="footer">
<a href="http://irrlicht.sourceforge.net" target="_blank">Irrlicht
Engine</a> Documentation © 2003-2012 by Nikolaus Gebhardt. Generated on Tue Nov 6 2012 11:06:02 for Irrlicht 3D Engine by
<a href="http://www.doxygen.org/index.html" target="_blank">Doxygen</a> 1.7.5.1 </li>
</ul>
</div>
</body>
</html>
|