mirror of
https://github.com/minetest/irrlicht.git
synced 2024-11-16 15:30:25 +01:00
c481179825
Add some for newer examples which didn't have those so far. Only updating this once now as some were broken. Next time on release. git-svn-id: svn://svn.code.sf.net/p/irrlicht/code/trunk@6204 dfc29bdd-3216-0410-991c-e03cc46cb475
220 lines
42 KiB
HTML
220 lines
42 KiB
HTML
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
|
|
<html>
|
|
<head>
|
|
<meta http-equiv="Content-Type" content="text/xhtml;charset=UTF-8"/>
|
|
<meta http-equiv="X-UA-Compatible" content="IE=9"/>
|
|
<meta name="generator" content="Doxygen 1.8.13"/>
|
|
<meta name="viewport" content="width=device-width, initial-scale=1"/>
|
|
<title>Tutorial 25: Xml Handling</title>
|
|
<html xmlns="http://www.w3.org/1999/xhtml">
|
|
<!-- Wanted to avoid copying .css to each folder, so copied default .css from doxyen in here, kicked out most stuff we don't need for examples and modified some a little bit.
|
|
Target was having a single html in each example folder which is created from the main.cpp files and needs no files besides some images below media folder.
|
|
Feel free to improve :)
|
|
-->
|
|
<style>
|
|
body, table, div, p, dl {
|
|
font: 400 14px/22px;
|
|
}
|
|
body {
|
|
background-color: #F0F0F0;
|
|
color: black;
|
|
margin-left: 5%;
|
|
margin-right: 5%;
|
|
}
|
|
p.reference, p.definition {
|
|
font: 400 14px/22px;
|
|
}
|
|
.title {
|
|
font: 400 14px/28px;
|
|
font-size: 150%;
|
|
font-weight: bold;
|
|
margin: 10px 2px;
|
|
}
|
|
h1, h2, h3, h4, h5, h6 {
|
|
-webkit-transition: text-shadow 0.5s linear;
|
|
-moz-transition: text-shadow 0.5s linear;
|
|
-ms-transition: text-shadow 0.5s linear;
|
|
-o-transition: text-shadow 0.5s linear;
|
|
transition: text-shadow 0.5s linear;
|
|
margin-right: 15px;
|
|
}
|
|
caption {
|
|
font-weight: bold;
|
|
}
|
|
h3.version {
|
|
font-size: 90%;
|
|
text-align: center;
|
|
}
|
|
a {
|
|
color: #3D578C;
|
|
font-weight: normal;
|
|
text-decoration: none;
|
|
}
|
|
.contents a:visited {
|
|
color: #4665A2;
|
|
}
|
|
a:hover {
|
|
text-decoration: underline;
|
|
}
|
|
a.el {
|
|
font-weight: bold;
|
|
}
|
|
a.code, a.code:visited, a.line, a.line:visited {
|
|
color: #4665A2;
|
|
}
|
|
a.codeRef, a.codeRef:visited, a.lineRef, a.lineRef:visited {
|
|
color: #4665A2;
|
|
}
|
|
pre.fragment {
|
|
border: 1px solid #C4CFE5;
|
|
background-color: #FBFCFD;
|
|
padding: 4px 6px;
|
|
margin: 4px 8px 4px 2px;
|
|
overflow: auto;
|
|
word-wrap: break-word;
|
|
font-size: 9pt;
|
|
line-height: 125%;
|
|
font-family: monospace, fixed;
|
|
font-size: 105%;
|
|
}
|
|
div.fragment {
|
|
padding: 0px;
|
|
margin: 4px 8px 4px 2px;
|
|
background-color: #FBFCFD;
|
|
border: 1px solid #C4CFE5;
|
|
}
|
|
div.line {
|
|
font-family: monospace, fixed;
|
|
font-size: 13px;
|
|
min-height: 13px;
|
|
line-height: 1.0;
|
|
text-wrap: unrestricted;
|
|
white-space: -moz-pre-wrap; /* Moz */
|
|
white-space: -pre-wrap; /* Opera 4-6 */
|
|
white-space: -o-pre-wrap; /* Opera 7 */
|
|
white-space: pre-wrap; /* CSS3 */
|
|
word-wrap: break-word; /* IE 5.5+ */
|
|
text-indent: -53px;
|
|
padding-left: 53px;
|
|
padding-bottom: 0px;
|
|
margin: 0px;
|
|
-webkit-transition-property: background-color, box-shadow;
|
|
-webkit-transition-duration: 0.5s;
|
|
-moz-transition-property: background-color, box-shadow;
|
|
-moz-transition-duration: 0.5s;
|
|
-ms-transition-property: background-color, box-shadow;
|
|
-ms-transition-duration: 0.5s;
|
|
-o-transition-property: background-color, box-shadow;
|
|
-o-transition-duration: 0.5s;
|
|
transition-property: background-color, box-shadow;
|
|
transition-duration: 0.5s;
|
|
}
|
|
div.contents {
|
|
margin-top: 10px;
|
|
margin-left: 12px;
|
|
margin-right: 8px;
|
|
}
|
|
div.center {
|
|
text-align: center;
|
|
margin-top: 0px;
|
|
margin-bottom: 0px;
|
|
padding: 0px;
|
|
}
|
|
div.center img {
|
|
border: 0px;
|
|
}
|
|
span.keyword {
|
|
color: #008000
|
|
}
|
|
span.keywordtype {
|
|
color: #604020
|
|
}
|
|
span.keywordflow {
|
|
color: #e08000
|
|
}
|
|
span.comment {
|
|
color: #800000
|
|
}
|
|
span.preprocessor {
|
|
color: #806020
|
|
}
|
|
span.stringliteral {
|
|
color: #002080
|
|
}
|
|
span.charliteral {
|
|
color: #008080
|
|
}
|
|
blockquote {
|
|
background-color: #F7F8FB;
|
|
border-left: 2px solid #9CAFD4;
|
|
margin: 0 24px 0 4px;
|
|
padding: 0 12px 0 16px;
|
|
}
|
|
hr {
|
|
height: 0px;
|
|
border: none;
|
|
border-top: 1px solid #4A6AAA;
|
|
}
|
|
address {
|
|
font-style: normal;
|
|
color: #2A3D61;
|
|
}
|
|
div.header {
|
|
background-image:url('nav_h.png');
|
|
background-repeat:repeat-x;
|
|
background-color: #F9FAFC;
|
|
margin: 0px;
|
|
border-bottom: 1px solid #C4CFE5;
|
|
}
|
|
div.headertitle {
|
|
padding: 5px 5px 5px 10px;
|
|
}
|
|
.image {
|
|
text-align: center;
|
|
}
|
|
.caption {
|
|
font-weight: bold;
|
|
}
|
|
div.zoom {
|
|
border: 1px solid #90A5CE;
|
|
}
|
|
tr.heading h2 {
|
|
margin-top: 12px;
|
|
margin-bottom: 4px;
|
|
}
|
|
</style>
|
|
</head>
|
|
<div id="top"><!-- do not remove this div, it is closed by doxygen! -->
|
|
<!--END TITLEAREA-->
|
|
<!-- end header part -->
|
|
<!-- Generated by Doxygen 1.8.13 -->
|
|
</div><!-- top -->
|
|
<div class="header">
|
|
<div class="headertitle">
|
|
<div class="title">Tutorial 25: Xml Handling </div> </div>
|
|
</div><!--header-->
|
|
<div class="contents">
|
|
<div class="textblock"><div class="image">
|
|
<img src="../../media/example_screenshots/025shot.jpg" alt="025shot.jpg"/>
|
|
</div>
|
|
<p>Demonstrates loading and saving of configurations via XML</p>
|
|
<dl class="section author"><dt>Author</dt><dd>Y.M. Bosman <<a href="#" onclick="location.href='mai'+'lto:'+'yor'+'an'+'.bo'+'sm'+'an@'+'gm'+'ail'+'.c'+'om'; return false;">yoran<span style="display: none;">.nosp@m.</span>.bos<span style="display: none;">.nosp@m.</span>man@g<span style="display: none;">.nosp@m.</span>mail<span style="display: none;">.nosp@m.</span>.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"><div class="line"><span class="preprocessor">#include <irrlicht.h></span></div><div class="line"><span class="preprocessor">#include "exampleHelper.h"</span></div><div class="line"></div><div class="line"><span class="keyword">using namespace </span>irr;</div><div class="line"><span class="keyword">using namespace </span>core;</div><div class="line"><span class="keyword">using namespace </span>scene;</div><div class="line"><span class="keyword">using namespace </span>video;</div><div class="line"><span class="keyword">using namespace </span>io;</div><div class="line"><span class="keyword">using namespace </span>gui;</div><div class="line"></div><div class="line"><span class="preprocessor">#ifdef _MSC_VER</span></div><div class="line"><span class="preprocessor">#pragma comment(lib, "Irrlicht.lib")</span></div><div class="line"><span class="preprocessor">#endif</span></div></div><!-- fragment --><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"><div class="line"><span class="keyword">class </span>SettingManager</div><div class="line">{</div><div class="line"><span class="keyword">public</span>:</div><div class="line"></div><div class="line"> <span class="comment">// Construct setting managers and set default settings</span></div><div class="line"> SettingManager(<span class="keyword">const</span> stringw& settings_file): SettingsFile(settings_file), NullDevice(0)</div><div class="line"> {</div><div class="line"> <span class="comment">// Irrlicht null device, we want to load settings before we actually created our device, therefore, nulldevice</span></div><div class="line"> NullDevice = irr::createDevice(irr::video::EDT_NULL);</div><div class="line"></div><div class="line"> <span class="comment">//DriverOptions is an irrlicht map,</span></div><div class="line"> <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></div><div class="line"> <span class="comment">//the [] operator overrides values if they already exist</span></div><div class="line"> DriverOptions.insert(L<span class="stringliteral">"Software"</span>, EDT_SOFTWARE);</div><div class="line"> DriverOptions.insert(L<span class="stringliteral">"OpenGL"</span>, EDT_OPENGL);</div><div class="line"> DriverOptions.insert(L<span class="stringliteral">"Direct3D9"</span>, EDT_DIRECT3D9);</div><div class="line"></div><div class="line"> <span class="comment">//some resolution options</span></div><div class="line"> ResolutionOptions.insert(L<span class="stringliteral">"640x480"</span>, dimension2du(640,480));</div><div class="line"> ResolutionOptions.insert(L<span class="stringliteral">"800x600"</span>, dimension2du(800,600));</div><div class="line"> ResolutionOptions.insert(L<span class="stringliteral">"1024x768"</span>, dimension2du(1024,768));</div><div class="line"></div><div class="line"> <span class="comment">//our preferred defaults</span></div><div class="line"> SettingMap.insert(L<span class="stringliteral">"driver"</span>, L<span class="stringliteral">"Direct3D9"</span>);</div><div class="line"> SettingMap.insert(L<span class="stringliteral">"resolution"</span>, L<span class="stringliteral">"640x480"</span>);</div><div class="line"> SettingMap.insert(L<span class="stringliteral">"fullscreen"</span>, L<span class="stringliteral">"0"</span>); <span class="comment">//0 is false</span></div><div class="line"> }</div><div class="line"></div><div class="line"> <span class="comment">// Destructor, you could store settings automatically on exit of your</span></div><div class="line"> <span class="comment">// application if you wanted to in our case we simply drop the</span></div><div class="line"> <span class="comment">// nulldevice</span></div><div class="line"> ~SettingManager()</div><div class="line"> {</div><div class="line"> <span class="keywordflow">if</span> (NullDevice)</div><div class="line"> {</div><div class="line"> NullDevice->closeDevice();</div><div class="line"> NullDevice->drop();</div><div class="line"> }</div><div class="line"> };</div></div><!-- fragment --><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: </p><pre class="fragment"> <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></pre> <div class="fragment"><div class="line"> <span class="keywordtype">bool</span> load()</div><div class="line"> {</div><div class="line"> <span class="comment">//if not able to create device don't attempt to load</span></div><div class="line"> <span class="keywordflow">if</span> (!NullDevice)</div><div class="line"> <span class="keywordflow">return</span> <span class="keyword">false</span>;</div><div class="line"></div><div class="line"> irr::io::IXMLReader* xml = NullDevice->getFileSystem()->createXMLReader(SettingsFile); <span class="comment">//create xml reader</span></div><div class="line"> <span class="keywordflow">if</span> (!xml)</div><div class="line"> <span class="keywordflow">return</span> <span class="keyword">false</span>;</div><div class="line"></div><div class="line"> <span class="keyword">const</span> stringw settingTag(L<span class="stringliteral">"setting"</span>); <span class="comment">//we'll be looking for this tag in the xml</span></div><div class="line"> stringw currentSection; <span class="comment">//keep track of our current section</span></div><div class="line"> <span class="keyword">const</span> stringw videoTag(L<span class="stringliteral">"video"</span>); <span class="comment">//constant for videotag</span></div><div class="line"></div><div class="line"> <span class="comment">//while there is more to read</span></div><div class="line"> <span class="keywordflow">while</span> (xml->read())</div><div class="line"> {</div><div class="line"> <span class="comment">//check the node type</span></div><div class="line"> <span class="keywordflow">switch</span> (xml->getNodeType())</div><div class="line"> {</div><div class="line"> <span class="comment">//we found a new element</span></div><div class="line"> <span class="keywordflow">case</span> irr::io::EXN_ELEMENT:</div><div class="line"> {</div><div class="line"> <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></div><div class="line"> <span class="keywordflow">if</span> (currentSection.empty() && videoTag.equals_ignore_case(xml->getNodeName()))</div><div class="line"> {</div><div class="line"> currentSection = videoTag;</div><div class="line"> }</div><div class="line"> <span class="comment">//we are in the video section and we find a setting to parse</span></div><div class="line"> <span class="keywordflow">else</span> <span class="keywordflow">if</span> (currentSection.equals_ignore_case(videoTag) && settingTag.equals_ignore_case(xml->getNodeName() ))</div><div class="line"> {</div><div class="line"> <span class="comment">//read in the key</span></div><div class="line"> stringw key = xml->getAttributeValueSafe(L<span class="stringliteral">"name"</span>);</div><div class="line"> <span class="comment">//if there actually is a key to set</span></div><div class="line"> <span class="keywordflow">if</span> (!key.empty())</div><div class="line"> {</div><div class="line"> <span class="comment">//set the setting in the map to the value,</span></div><div class="line"> <span class="comment">//the [] operator overrides values if they already exist or inserts a new key value</span></div><div class="line"> <span class="comment">//pair into the settings map if it was not defined yet</span></div><div class="line"> SettingMap[key] = xml->getAttributeValueSafe(L<span class="stringliteral">"value"</span>);</div><div class="line"> }</div><div class="line"> }</div><div class="line"></div><div class="line"> <span class="comment">//..</span></div><div class="line"> <span class="comment">// You can add your own sections and tags to read in here</span></div><div class="line"> <span class="comment">//..</span></div><div class="line"> }</div><div class="line"> <span class="keywordflow">break</span>;</div><div class="line"></div><div class="line"> <span class="comment">//we found the end of an element</span></div><div class="line"> <span class="keywordflow">case</span> irr::io::EXN_ELEMENT_END:</div><div class="line"> <span class="comment">//we were at the end of the video section so we reset our tag</span></div><div class="line"> currentSection=L<span class="stringliteral">""</span>;</div><div class="line"> <span class="keywordflow">break</span>;</div><div class="line"> <span class="keywordflow">default</span>:</div><div class="line"> <span class="keywordflow">break</span>;</div><div class="line"> }</div><div class="line"> }</div><div class="line"></div><div class="line"> <span class="comment">// don't forget to delete the xml reader</span></div><div class="line"> xml->drop();</div><div class="line"></div><div class="line"> <span class="keywordflow">return</span> <span class="keyword">true</span>;</div><div class="line"> }</div><div class="line"></div><div class="line"> <span class="comment">// Save the xml to disk. We use the nulldevice.</span></div><div class="line"> <span class="keywordtype">bool</span> save()</div><div class="line"> {</div><div class="line"></div><div class="line"> <span class="comment">//if not able to create device don't attempt to save</span></div><div class="line"> <span class="keywordflow">if</span> (!NullDevice)</div><div class="line"> <span class="keywordflow">return</span> <span class="keyword">false</span>;</div><div class="line"></div><div class="line"> <span class="comment">//create xml writer</span></div><div class="line"> irr::io::IXMLWriter* xwriter = NullDevice->getFileSystem()->createXMLWriter( SettingsFile );</div><div class="line"> <span class="keywordflow">if</span> (!xwriter)</div><div class="line"> <span class="keywordflow">return</span> <span class="keyword">false</span>;</div><div class="line"></div><div class="line"> <span class="comment">//write out the obligatory xml header. Each xml-file needs to have exactly one of those.</span></div><div class="line"> xwriter->writeXMLHeader();</div><div class="line"></div><div class="line"> <span class="comment">//start element mygame, you replace the label "mygame" with anything you want</span></div><div class="line"> xwriter->writeElement(L<span class="stringliteral">"mygame"</span>);</div><div class="line"> xwriter->writeLineBreak(); <span class="comment">//new line</span></div><div class="line"></div><div class="line"> <span class="comment">//start section with video settings</span></div><div class="line"> xwriter->writeElement(L<span class="stringliteral">"video"</span>);</div><div class="line"> xwriter->writeLineBreak(); <span class="comment">//new line</span></div><div class="line"></div><div class="line"> <span class="comment">// getIterator gets us a pointer to the first node of the settings map</span></div><div class="line"> <span class="comment">// every iteration we increase the iterator which gives us the next map node</span></div><div class="line"> <span class="comment">// until we reach the end we write settings one by one by using the nodes key and value functions</span></div><div class="line"> map<stringw, stringw>::Iterator i = SettingMap.getIterator();</div><div class="line"> <span class="keywordflow">for</span>(; !i.atEnd(); i++)</div><div class="line"> {</div><div class="line"> <span class="comment">//write element as <setting name="key" value="x" /></span></div><div class="line"> <span class="comment">//the second parameter indicates this is an empty element with no children, just attributes</span></div><div class="line"> xwriter->writeElement(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() );</div><div class="line"> xwriter->writeLineBreak();</div><div class="line"> }</div><div class="line"> xwriter->writeLineBreak();</div><div class="line"></div><div class="line"> <span class="comment">//close video section</span></div><div class="line"> xwriter->writeClosingTag(L<span class="stringliteral">"video"</span>);</div><div class="line"> xwriter->writeLineBreak();</div><div class="line"></div><div class="line"> <span class="comment">//..</span></div><div class="line"> <span class="comment">// You can add writing sound settings, savegame information etc</span></div><div class="line"> <span class="comment">//..</span></div><div class="line"></div><div class="line"> <span class="comment">//close mygame section</span></div><div class="line"> xwriter->writeClosingTag(L<span class="stringliteral">"mygame"</span>);</div><div class="line"></div><div class="line"> <span class="comment">//delete xml writer</span></div><div class="line"> xwriter->drop();</div><div class="line"></div><div class="line"> <span class="keywordflow">return</span> <span class="keyword">true</span>;</div><div class="line"> }</div><div class="line"></div><div class="line"> <span class="comment">// Set setting in our manager</span></div><div class="line"> <span class="keywordtype">void</span> setSetting(<span class="keyword">const</span> stringw& name, <span class="keyword">const</span> stringw& value)</div><div class="line"> {</div><div class="line"> SettingMap[name]=value;</div><div class="line"> }</div><div class="line"></div><div class="line"> <span class="comment">// set setting overload to quickly assign integers to our setting map</span></div><div class="line"> <span class="keywordtype">void</span> setSetting(<span class="keyword">const</span> stringw& name, s32 value)</div><div class="line"> {</div><div class="line"> SettingMap[name]=stringw(value);</div><div class="line"> }</div><div class="line"></div><div class="line"> <span class="comment">// Get setting as string</span></div><div class="line"> stringw getSetting(<span class="keyword">const</span> stringw& key)<span class="keyword"> const</span></div><div class="line"><span class="keyword"> </span>{</div><div class="line"> <span class="comment">//the find function or irrmap returns a pointer to a map Node</span></div><div class="line"> <span class="comment">//if the key can be found, otherwise it returns null</span></div><div class="line"> <span class="comment">//the map node has the function getValue and getKey, as we already know the key, we return node->getValue()</span></div><div class="line"> map<stringw, stringw>::Node* n = SettingMap.find(key);</div><div class="line"> <span class="keywordflow">if</span> (n)</div><div class="line"> <span class="keywordflow">return</span> n->getValue();</div><div class="line"> <span class="keywordflow">else</span></div><div class="line"> <span class="keywordflow">return</span> L<span class="stringliteral">""</span>;</div><div class="line"> }</div><div class="line"></div><div class="line"> <span class="comment">//</span></div><div class="line"> <span class="keywordtype">bool</span> getSettingAsBoolean(<span class="keyword">const</span> stringw& key )<span class="keyword"> const</span></div><div class="line"><span class="keyword"> </span>{</div><div class="line"> stringw s = getSetting(key);</div><div class="line"> <span class="keywordflow">if</span> (s.empty())</div><div class="line"> <span class="keywordflow">return</span> <span class="keyword">false</span>;</div><div class="line"> <span class="keywordflow">return</span> s.equals_ignore_case(L<span class="stringliteral">"1"</span>);</div><div class="line"> }</div><div class="line"></div><div class="line"> <span class="comment">//</span></div><div class="line"> s32 getSettingAsInteger(<span class="keyword">const</span> stringw& key)<span class="keyword"> const</span></div><div class="line"><span class="keyword"> </span>{</div><div class="line"> <span class="comment">//we implicitly cast to string instead of stringw because strtol10 does not accept wide strings</span></div><div class="line"> <span class="keyword">const</span> stringc s = getSetting(key);</div><div class="line"> <span class="keywordflow">if</span> (s.empty())</div><div class="line"> <span class="keywordflow">return</span> 0;</div><div class="line"></div><div class="line"> <span class="keywordflow">return</span> strtol10(s.c_str());</div><div class="line"> }</div><div class="line"></div><div class="line"><span class="keyword">public</span>:</div><div class="line"> map<stringw, s32> DriverOptions; <span class="comment">//available options for driver config</span></div><div class="line"> map<stringw, dimension2du> ResolutionOptions; <span class="comment">//available options for resolution config</span></div><div class="line"><span class="keyword">private</span>:</div><div class="line"> SettingManager(<span class="keyword">const</span> SettingManager& other); <span class="comment">// defined but not implemented</span></div><div class="line"> SettingManager& operator=(<span class="keyword">const</span> SettingManager& other); <span class="comment">// defined but not implemented</span></div><div class="line"></div><div class="line"> map<stringw, stringw> SettingMap; <span class="comment">//current config</span></div><div class="line"></div><div class="line"> stringw SettingsFile; <span class="comment">// location of the xml, usually the</span></div><div class="line"> irr::IrrlichtDevice* NullDevice;</div><div class="line">};</div></div><!-- fragment --><p> Application context for global variables </p><div class="fragment"><div class="line"><span class="keyword">struct </span>SAppContext</div><div class="line">{</div><div class="line"> SAppContext()</div><div class="line"> : Device(0),Gui(0), Driver(0), Settings(0), ShouldQuit(false),</div><div class="line"> ButtonSave(0), ButtonExit(0), ListboxDriver(0),</div><div class="line"> ListboxResolution(0), CheckboxFullscreen(0)</div><div class="line"> {</div><div class="line"> }</div><div class="line"></div><div class="line"> ~SAppContext()</div><div class="line"> {</div><div class="line"> <span class="keywordflow">if</span> (Settings)</div><div class="line"> <span class="keyword">delete</span> Settings;</div><div class="line"></div><div class="line"> <span class="keywordflow">if</span> (Device)</div><div class="line"> {</div><div class="line"> Device->closeDevice();</div><div class="line"> Device->drop();</div><div class="line"> }</div><div class="line"> }</div><div class="line"></div><div class="line"> IrrlichtDevice* Device;</div><div class="line"> IGUIEnvironment* Gui;</div><div class="line"> IVideoDriver* Driver;</div><div class="line"> SettingManager* Settings;</div><div class="line"> <span class="keywordtype">bool</span> ShouldQuit;</div><div class="line"></div><div class="line"> <span class="comment">//settings dialog</span></div><div class="line"> IGUIButton* ButtonSave;</div><div class="line"> IGUIButton* ButtonExit;</div><div class="line"> IGUIListBox* ListboxDriver;</div><div class="line"> IGUIListBox* ListboxResolution;</div><div class="line"> IGUICheckBox* CheckboxFullscreen;</div><div class="line">};</div></div><!-- fragment --><p> A typical event receiver. </p><div class="fragment"><div class="line"><span class="keyword">class </span>MyEventReceiver : <span class="keyword">public</span> IEventReceiver</div><div class="line">{</div><div class="line"><span class="keyword">public</span>:</div><div class="line"> MyEventReceiver(SAppContext & a) : App(a) { }</div><div class="line"></div><div class="line"> <span class="keyword">virtual</span> <span class="keywordtype">bool</span> OnEvent(<span class="keyword">const</span> SEvent& event)</div><div class="line"> {</div><div class="line"> <span class="keywordflow">if</span> (event.EventType == EET_GUI_EVENT )</div><div class="line"> {</div><div class="line"> <span class="keywordflow">switch</span> ( event.GUIEvent.EventType )</div><div class="line"> {</div><div class="line"> <span class="comment">//handle button click events</span></div><div class="line"> <span class="keywordflow">case</span> EGET_BUTTON_CLICKED:</div><div class="line"> {</div><div class="line"> <span class="comment">//Our save button was called so we obtain the settings from our dialog and save them</span></div><div class="line"> <span class="keywordflow">if</span> ( event.GUIEvent.Caller == App.ButtonSave )</div><div class="line"> {</div><div class="line"> <span class="comment">//if there is a selection write it</span></div><div class="line"> <span class="keywordflow">if</span> ( App.ListboxDriver->getSelected() != -1)</div><div class="line"> App.Settings->setSetting(L<span class="stringliteral">"driver"</span>, App.ListboxDriver->getListItem(App.ListboxDriver->getSelected()));</div><div class="line"></div><div class="line"> <span class="comment">//if there is a selection write it</span></div><div class="line"> <span class="keywordflow">if</span> ( App.ListboxResolution->getSelected() != -1)</div><div class="line"> App.Settings->setSetting(L<span class="stringliteral">"resolution"</span>, App.ListboxResolution->getListItem(App.ListboxResolution->getSelected()));</div><div class="line"></div><div class="line"> App.Settings->setSetting(L<span class="stringliteral">"fullscreen"</span>, App.CheckboxFullscreen->isChecked());</div><div class="line"></div><div class="line"></div><div class="line"> <span class="keywordflow">if</span> (App.Settings->save())</div><div class="line"> {</div><div class="line"> 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>);</div><div class="line"> }</div><div class="line"> }</div><div class="line"> <span class="comment">// cancel/exit button clicked, tell the application to exit</span></div><div class="line"> <span class="keywordflow">else</span> <span class="keywordflow">if</span> ( event.GUIEvent.Caller == App.ButtonExit)</div><div class="line"> {</div><div class="line"> App.ShouldQuit = <span class="keyword">true</span>;</div><div class="line"> }</div><div class="line"> }</div><div class="line"> <span class="keywordflow">break</span>;</div><div class="line"> <span class="keywordflow">default</span>:</div><div class="line"> <span class="keywordflow">break</span>;</div><div class="line"> }</div><div class="line"> }</div><div class="line"></div><div class="line"> <span class="keywordflow">return</span> <span class="keyword">false</span>;</div><div class="line"> }</div><div class="line"></div><div class="line"><span class="keyword">private</span>:</div><div class="line"> SAppContext & App;</div><div class="line">};</div></div><!-- fragment --><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"><div class="line"><span class="keywordtype">void</span> createSettingsDialog(SAppContext& app)</div><div class="line">{</div><div class="line"> <span class="comment">// first get rid of alpha in gui</span></div><div class="line"> <span class="keywordflow">for</span> (irr::s32 i=0; i<irr::gui::EGDC_COUNT ; ++i)</div><div class="line"> {</div><div class="line"> irr::video::SColor col = app.Gui->getSkin()->getColor((irr::gui::EGUI_DEFAULT_COLOR)i);</div><div class="line"> col.setAlpha(255);</div><div class="line"> app.Gui->getSkin()->setColor((irr::gui::EGUI_DEFAULT_COLOR)i, col);</div><div class="line"> }</div><div class="line"></div><div class="line"> <span class="comment">//create video settings windows</span></div><div class="line"> gui::IGUIWindow* windowSettings = app.Gui->addWindow(rect<s32>(10,10,400,400),<span class="keyword">true</span>,L<span class="stringliteral">"Videosettings"</span>);</div><div class="line"> 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);</div><div class="line"></div><div class="line"> <span class="comment">// add listbox for driver choice</span></div><div class="line"> 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);</div><div class="line"> app.ListboxDriver = app.Gui->addListBox(rect<s32>(10,60,220,120), windowSettings, 1,<span class="keyword">true</span>);</div><div class="line"></div><div class="line"> <span class="comment">//add all available options to the driver choice listbox</span></div><div class="line"> map<stringw, s32>::Iterator i = app.Settings->DriverOptions.getIterator();</div><div class="line"> <span class="keywordflow">for</span>(; !i.atEnd(); i++)</div><div class="line"> app.ListboxDriver->addItem(i->getKey().c_str());</div><div class="line"></div><div class="line"> <span class="comment">//set currently selected driver</span></div><div class="line"> app.ListboxDriver->setSelected(app.Settings->getSetting(<span class="stringliteral">"driver"</span>).c_str());</div><div class="line"></div><div class="line"> <span class="comment">// add listbox for resolution choice</span></div><div class="line"> 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);</div><div class="line"> app.ListboxResolution = app.Gui->addListBox(rect<s32>(10,140,220,200), windowSettings, 1,<span class="keyword">true</span>);</div><div class="line"></div><div class="line"> <span class="comment">//add all available options to the resolution listbox</span></div><div class="line"> map<stringw, dimension2du>::Iterator ri = app.Settings->ResolutionOptions.getIterator();</div><div class="line"> <span class="keywordflow">for</span>(; !ri.atEnd(); ri++)</div><div class="line"> app.ListboxResolution->addItem(ri->getKey().c_str());</div><div class="line"></div><div class="line"> <span class="comment">//set currently selected resolution</span></div><div class="line"> app.ListboxResolution->setSelected(app.Settings->getSetting(<span class="stringliteral">"resolution"</span>).c_str());</div><div class="line"></div><div class="line"> <span class="comment">//add checkbox to toggle fullscreen, initially set to loaded setting</span></div><div class="line"> app.CheckboxFullscreen = app.Gui->addCheckBox(</div><div class="line"> app.Settings->getSettingAsBoolean(<span class="stringliteral">"fullscreen"</span>),</div><div class="line"> rect<s32>(10,220,220,240), windowSettings, -1,</div><div class="line"> L<span class="stringliteral">"Fullscreen"</span>);</div><div class="line"></div><div class="line"> <span class="comment">//last but not least add save button</span></div><div class="line"> app.ButtonSave = app.Gui->addButton(</div><div class="line"> rect<s32>(80,250,150,270), windowSettings, 2,</div><div class="line"> L<span class="stringliteral">"Save video settings"</span>);</div><div class="line"></div><div class="line"> <span class="comment">//exit/cancel button</span></div><div class="line"> app.ButtonExit = app.Gui->addButton(</div><div class="line"> rect<s32>(160,250,240,270), windowSettings, 2,</div><div class="line"> L<span class="stringliteral">"Cancel and exit"</span>);</div><div class="line">}</div></div><!-- fragment --><p> The main function. Creates all objects and does the XML handling. </p><div class="fragment"><div class="line"><span class="keywordtype">int</span> main()</div><div class="line">{</div><div class="line"> <span class="comment">//create new application context</span></div><div class="line"> SAppContext app;</div><div class="line"></div><div class="line"> <span class="comment">//create device creation parameters that can get overwritten by our settings file</span></div><div class="line"> SIrrlichtCreationParameters param;</div><div class="line"> param.DriverType = EDT_SOFTWARE;</div><div class="line"> param.WindowSize.set(640,480);</div><div class="line"></div><div class="line"> <span class="comment">// Try to load config.</span></div><div class="line"> <span class="comment">// I leave it as an exercise of the reader to store the configuration in the local application data folder,</span></div><div class="line"> <span class="comment">// the only logical place to store config data for games. For all other operating systems I redirect to your manuals</span></div><div class="line"> app.Settings = <span class="keyword">new</span> SettingManager(getExampleMediaPath() + <span class="stringliteral">"settings.xml"</span>);</div><div class="line"> <span class="keywordflow">if</span> ( !app.Settings->load() )</div><div class="line"> {</div><div class="line"> <span class="comment">// ...</span></div><div class="line"> <span class="comment">// Here add your own exception handling, for now we continue because there are defaults set in SettingManager constructor</span></div><div class="line"> <span class="comment">// ...</span></div><div class="line"> }</div><div class="line"> <span class="keywordflow">else</span></div><div class="line"> {</div><div class="line"> <span class="comment">//settings xml loaded from disk,</span></div><div class="line"></div><div class="line"> <span class="comment">//map driversetting to driver type and test if the setting is valid</span></div><div class="line"> <span class="comment">//the DriverOptions map contains string representations mapped to to irrlicht E_DRIVER_TYPE enum</span></div><div class="line"> <span class="comment">//e.g "direct3d9" will become 4</span></div><div class="line"> <span class="comment">//see DriverOptions in the settingmanager class for details</span></div><div class="line"> map<stringw, s32>::Node* driver = app.Settings->DriverOptions.find( app.Settings->getSetting(<span class="stringliteral">"driver"</span>) );</div><div class="line"></div><div class="line"> <span class="keywordflow">if</span> (driver)</div><div class="line"> {</div><div class="line"> <span class="keywordflow">if</span> ( irr::IrrlichtDevice::isDriverSupported( static_cast<E_DRIVER_TYPE>( driver->getValue() )))</div><div class="line"> {</div><div class="line"> <span class="comment">// selected driver is supported, so we use it.</span></div><div class="line"> param.DriverType = <span class="keyword">static_cast<</span>E_DRIVER_TYPE<span class="keyword">></span>( driver->getValue());</div><div class="line"> }</div><div class="line"> }</div><div class="line"></div><div class="line"> <span class="comment">//map resolution setting to dimension in a similar way as demonstrated above</span></div><div class="line"> map<stringw, dimension2du>::Node* res = app.Settings->ResolutionOptions.find( app.Settings->getSetting(<span class="stringliteral">"resolution"</span>) );</div><div class="line"> <span class="keywordflow">if</span> (res)</div><div class="line"> {</div><div class="line"> param.WindowSize = res->getValue();</div><div class="line"> }</div><div class="line"></div><div class="line"> <span class="comment">//get fullscreen setting from config</span></div><div class="line"> param.Fullscreen = app.Settings->getSettingAsBoolean(<span class="stringliteral">"fullscreen"</span>);</div><div class="line"> }</div><div class="line"></div><div class="line"> <span class="comment">//create the irrlicht device using the settings</span></div><div class="line"> app.Device = createDeviceEx(param);</div><div class="line"> <span class="keywordflow">if</span> (app.Device == 0)</div><div class="line"> {</div><div class="line"> <span class="comment">// You can add your own exception handling on driver failure</span></div><div class="line"> exit(0);</div><div class="line"> }</div><div class="line"></div><div class="line"> app.Device->setWindowCaption(L<span class="stringliteral">"Xmlhandling - Irrlicht engine tutorial"</span>);</div><div class="line"> app.Driver = app.Device->getVideoDriver();</div><div class="line"> app.Gui = app.Device->getGUIEnvironment();</div><div class="line"></div><div class="line"> createSettingsDialog(app);</div><div class="line"></div><div class="line"> <span class="comment">//set event receiver so we can respond to gui events</span></div><div class="line"> MyEventReceiver receiver(app);</div><div class="line"> app.Device->setEventReceiver(&receiver);</div><div class="line"></div><div class="line"> <span class="comment">//enter main loop</span></div><div class="line"> <span class="keywordflow">while</span> (!app.ShouldQuit && app.Device->run())</div><div class="line"> {</div><div class="line"> <span class="keywordflow">if</span> (app.Device->isWindowActive())</div><div class="line"> {</div><div class="line"> app.Driver->beginScene(video::ECBF_COLOR | video::ECBF_DEPTH, SColor(0,200,200,200));</div><div class="line"> app.Gui->drawAll();</div><div class="line"> app.Driver->endScene();</div><div class="line"> }</div><div class="line"> app.Device->sleep(10);</div><div class="line"> }</div><div class="line"></div><div class="line"> <span class="comment">//app destroys device in destructor</span></div><div class="line"></div><div class="line"> <span class="keywordflow">return</span> 0;</div><div class="line">}</div></div><!-- fragment --> </div></div><!-- contents -->
|
|
<!-- HTML footer for doxygen 1.8.13-->
|
|
<!-- start footer part -->
|
|
<p> </p>
|
|
</body>
|
|
</html>
|