Demonstrates loading and saving of configurations via XML
- Author
- Y.M. Bosman <yoran.nosp@m..bos.nosp@m.man@g.nosp@m.mail.nosp@m..com>
This demo features a fully usable system for configuration handling. The code can easily be integrated into own apps.
using namespace irr;
using namespace core;
using namespace scene;
using namespace video;
using namespace io;
using namespace gui;
#ifdef _IRR_WINDOWS_
#pragma comment(lib, "Irrlicht.lib")
#endif
SettingManager class.
This class loads and writes the settings and manages the options.
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.
class SettingManager
{
public:
SettingManager(
const stringw& settings_file): SettingsFile(settings_file), NullDevice(0)
{
ResolutionOptions.insert(L
"640x480",
dimension2du(640,480));
ResolutionOptions.insert(L
"800x600",
dimension2du(800,600));
ResolutionOptions.insert(L
"1024x768",
dimension2du(1024,768));
SettingMap.insert(L"driver", L"Direct3D9");
SettingMap.insert(L"resolution", L"640x480");
SettingMap.insert(L"fullscreen", L"0");
}
~SettingManager()
{
if (NullDevice)
{
NullDevice->closeDevice();
NullDevice->drop();
}
};
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
<?xml version="1.0"?>
<mygame>
<video>
<setting name="driver" value="Direct3D9">
<setting name="fullscreen" value="0">
<setting name="resolution" value="1024x768">
</video>
</mygame>
bool load()
{
if (!NullDevice)
return false;
if (!xml)
return false;
const stringw settingTag(L
"setting");
{
{
{
if (currentSection.empty() && videoTag.equals_ignore_case(xml->
getNodeName()))
{
currentSection = videoTag;
}
else if (currentSection.equals_ignore_case(videoTag) && settingTag.equals_ignore_case(xml->
getNodeName() ))
{
if (!key.empty())
{
}
}
}
break;
currentSection=L"";
break;
}
}
xml->drop();
return true;
}
bool save()
{
if (!NullDevice)
return false;
if (!xwriter)
return false;
map<stringw, stringw>::Iterator i = SettingMap.getIterator();
for(; !i.atEnd(); i++)
{
xwriter->
writeElement(L
"setting",
true, L
"name", i->getKey().c_str(), L
"value",i->getValue().c_str() );
}
return true;
}
{
SettingMap[name]=value;
}
{
}
{
map<stringw, stringw>::Node* n = SettingMap.find(key);
if (n)
return n->getValue();
else
return L"";
}
bool getSettingAsBoolean(
const stringw& key )
const
{
if (s.empty())
return false;
return s.equals_ignore_case(L"1");
}
{
if (s.empty())
return 0;
}
public:
map<stringw, s32> DriverOptions;
map<stringw, dimension2du> ResolutionOptions;
private:
SettingManager(const SettingManager& other);
SettingManager& operator=(const SettingManager& other);
map<stringw, stringw> SettingMap;
};
Application context for global variables
struct SAppContext
{
SAppContext()
: Device(0),Gui(0), Driver(0), Settings(0), ShouldQuit(false),
ButtonSave(0), ButtonExit(0), ListboxDriver(0),
ListboxResolution(0), CheckboxFullscreen(0)
{
}
~SAppContext()
{
if (Settings)
delete Settings;
if (Device)
{
Device->closeDevice();
Device->drop();
}
}
IrrlichtDevice* Device;
IGUIEnvironment* Gui;
IVideoDriver* Driver;
SettingManager* Settings;
bool ShouldQuit;
IGUIButton* ButtonSave;
IGUIButton* ButtonExit;
IGUIListBox* ListboxDriver;
IGUIListBox* ListboxResolution;
IGUICheckBox* CheckboxFullscreen;
};
A typical event receiver.
class MyEventReceiver : public IEventReceiver
{
public:
MyEventReceiver(SAppContext & a) : App(a) { }
virtual bool OnEvent(const SEvent& event)
{
{
switch ( event.GUIEvent.EventType )
{
{
if ( event.GUIEvent.Caller == App.ButtonSave )
{
if ( App.ListboxDriver->getSelected() != -1)
App.Settings->setSetting(L"driver", App.ListboxDriver->getListItem(App.ListboxDriver->getSelected()));
if ( App.ListboxResolution->getSelected() != -1)
App.Settings->setSetting(L"resolution", App.ListboxResolution->getListItem(App.ListboxResolution->getSelected()));
App.Settings->setSetting(L"fullscreen", App.CheckboxFullscreen->isChecked());
if (App.Settings->save())
{
App.Gui->addMessageBox(L"settings save",L"settings saved, please restart for settings to change effect","",true);
}
}
else if ( event.GUIEvent.Caller == App.ButtonExit)
{
App.ShouldQuit = true;
}
}
break;
}
}
return false;
}
private:
SAppContext & App;
};
Function to create a video settings dialog This dialog shows the current settings from the configuration xml and allows them to be changed
void createSettingsDialog(SAppContext& app)
{
{
}
gui::IGUIWindow* windowSettings = app.Gui->addWindow(rect<s32>(10,10,400,400),true,L"Videosettings");
app.Gui->addStaticText (L
"Select your desired video settings",
rect< s32 >(10,20, 200, 40),
false,
true, windowSettings);
app.Gui->addStaticText (L
"Driver",
rect< s32 >(10,50, 200, 60),
false,
true, windowSettings);
app.ListboxDriver = app.Gui->addListBox(rect<s32>(10,60,220,120), windowSettings, 1,true);
map<stringw, s32>::Iterator i = app.Settings->DriverOptions.getIterator();
for(; !i.atEnd(); i++)
app.ListboxDriver->addItem(i->getKey().c_str());
app.ListboxDriver->setSelected(app.Settings->getSetting("driver").c_str());
app.Gui->addStaticText (L
"Resolution",
rect< s32 >(10,130, 200, 140),
false,
true, windowSettings);
app.ListboxResolution = app.Gui->addListBox(rect<s32>(10,140,220,200), windowSettings, 1,true);
map<stringw, dimension2du>::Iterator ri = app.Settings->ResolutionOptions.getIterator();
for(; !ri.atEnd(); ri++)
app.ListboxResolution->addItem(ri->getKey().c_str());
app.ListboxResolution->setSelected(app.Settings->getSetting("resolution").c_str());
app.CheckboxFullscreen = app.Gui->addCheckBox(
app.Settings->getSettingAsBoolean("fullscreen"),
rect<s32>(10,220,220,240), windowSettings, -1,
L"Fullscreen");
app.ButtonSave = app.Gui->addButton(
rect<s32>(80,250,150,270), windowSettings, 2,
L"Save video settings");
app.ButtonExit = app.Gui->addButton(
rect<s32>(160,250,240,270), windowSettings, 2,
L"Cancel and exit");
}
The main function. Creates all objects and does the XML handling.
int main()
{
SAppContext app;
SIrrlichtCreationParameters param;
param.WindowSize.set(640,480);
app.Settings = new SettingManager("../../media/settings.xml");
if ( !app.Settings->load() )
{
}
else
{
map<stringw, s32>::Node* driver = app.Settings->DriverOptions.find( app.Settings->getSetting("driver") );
if (driver)
{
{
param.DriverType =
static_cast<E_DRIVER_TYPE>( driver->getValue());
}
}
map<stringw, dimension2du>::Node* res = app.Settings->ResolutionOptions.find( app.Settings->getSetting("resolution") );
if (res)
{
param.WindowSize = res->getValue();
}
param.Fullscreen = app.Settings->getSettingAsBoolean("fullscreen");
}
if (app.Device == 0)
{
exit(0);
}
app.Device->setWindowCaption(L"Xmlhandling - Irrlicht engine tutorial");
app.Driver = app.Device->getVideoDriver();
app.Gui = app.Device->getGUIEnvironment();
createSettingsDialog(app);
MyEventReceiver receiver(app);
app.Device->setEventReceiver(&receiver);
while (!app.ShouldQuit && app.Device->run())
{
if (app.Device->isWindowActive())
{
app.Driver->beginScene(true, true, SColor(0,200,200,200));
app.Gui->drawAll();
app.Driver->endScene();
}
app.Device->sleep(10);
}
return 0;
}