From f9158592e1478b2013afc7041d9ed041cf2d2f4a Mon Sep 17 00:00:00 2001 From: David Walter Seikel Date: Mon, 13 Jan 2014 19:47:58 +1000 Subject: Update Irrlicht to 1.8.1. Include actual change markers this time. lol --- libraries/irrlicht-1.8.1/doc/html/example025.html | 588 ++++++++++++++++++++++ 1 file changed, 588 insertions(+) create mode 100644 libraries/irrlicht-1.8.1/doc/html/example025.html (limited to 'libraries/irrlicht-1.8.1/doc/html/example025.html') diff --git a/libraries/irrlicht-1.8.1/doc/html/example025.html b/libraries/irrlicht-1.8.1/doc/html/example025.html new file mode 100644 index 0000000..a79b0fe --- /dev/null +++ b/libraries/irrlicht-1.8.1/doc/html/example025.html @@ -0,0 +1,588 @@ + + + + +Irrlicht 3D Engine: Tutorial 25: Xml Handling + + + + + + + + + + + + + + +
+ + +
+ + + + + + + + + + + + + + + + + +
+
Irrlicht 3D Engine + +
+ +
+ + + + + + +
+
+
+ + + + +
+
+ +
+
+
+ +
+
+
+
Tutorial 25: Xml Handling
+
+
+
+025shot.jpg +
+

Demonstrates loading and saving of configurations via XML

+
Author:
Y.M. Bosman <yoran.bosman@gmail.com>
+

This demo features a fully usable system for configuration handling. The code can easily be integrated into own apps.

+
#include <irrlicht.h>
+
+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:
+
+    // Construct setting managers and set default settings
+    SettingManager(const stringw& settings_file): SettingsFile(settings_file), NullDevice(0)
+    {
+        // Irrlicht null device, we want to load settings before we actually created our device, therefore, nulldevice
+        NullDevice = irr::createDevice(irr::video::EDT_NULL);
+
+        //DriverOptions is an irrlicht map,
+        //we can insert values in the map in two ways by calling insert(key,value) or by using the [key] operator
+        //the [] operator overrides values if they already exist
+        DriverOptions.insert(L"Software", EDT_SOFTWARE);
+        DriverOptions.insert(L"OpenGL", EDT_OPENGL);
+        DriverOptions.insert(L"Direct3D9", EDT_DIRECT3D9);
+
+        //some resolution options
+        ResolutionOptions.insert(L"640x480", dimension2du(640,480));
+        ResolutionOptions.insert(L"800x600", dimension2du(800,600));
+        ResolutionOptions.insert(L"1024x768", dimension2du(1024,768));
+
+        //our preferred defaults
+        SettingMap.insert(L"driver", L"Direct3D9");
+        SettingMap.insert(L"resolution", L"640x480");
+        SettingMap.insert(L"fullscreen", L"0"); //0 is false
+    }
+
+    // Destructor, you could store settings automatically on exit of your
+    // application if you wanted to in our case we simply drop the
+    // nulldevice
+    ~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 not able to create device don't attempt to load
+        if (!NullDevice)
+            return false;
+
+        irr::io::IXMLReader* xml = NullDevice->getFileSystem()->createXMLReader(SettingsFile);  //create xml reader
+        if (!xml)
+            return false;
+
+        const stringw settingTag(L"setting"); //we'll be looking for this tag in the xml
+        stringw currentSection; //keep track of our current section
+        const stringw videoTag(L"video"); //constant for videotag
+
+        //while there is more to read
+        while (xml->read())
+        {
+            //check the node type
+            switch (xml->getNodeType())
+            {
+                //we found a new element
+                case irr::io::EXN_ELEMENT:
+                {
+                    //we currently are in the empty or mygame section and find the video tag so we set our current section to video
+                    if (currentSection.empty() && videoTag.equals_ignore_case(xml->getNodeName()))
+                    {
+                        currentSection = videoTag;
+                    }
+                    //we are in the video section and we find a setting to parse
+                    else if (currentSection.equals_ignore_case(videoTag) && settingTag.equals_ignore_case(xml->getNodeName() ))
+                    {
+                        //read in the key
+                        stringw key = xml->getAttributeValueSafe(L"name");
+                        //if there actually is a key to set
+                        if (!key.empty())
+                        {
+                            //set the setting in the map to the value,
+                            //the [] operator overrides values if they already exist or inserts a new key value
+                            //pair into the settings map if it was not defined yet
+                            SettingMap[key] = xml->getAttributeValueSafe(L"value");
+                        }
+                    }
+
+                    //..
+                    // You can add your own sections and tags to read in here
+                    //..
+                }
+                break;
+
+                //we found the end of an element
+                case irr::io::EXN_ELEMENT_END:
+                    //we were at the end of the video section so we reset our tag
+                    currentSection=L"";
+                break;
+            }
+        }
+
+        // don't forget to delete the xml reader
+        xml->drop();
+
+        return true;
+    }
+
+    // Save the xml to disk. We use the nulldevice.
+    bool save()
+    {
+
+        //if not able to create device don't attempt to save
+        if (!NullDevice)
+            return false;
+
+        //create xml writer
+        irr::io::IXMLWriter* xwriter = NullDevice->getFileSystem()->createXMLWriter( SettingsFile );
+        if (!xwriter)
+            return false;
+
+        //write out the obligatory xml header. Each xml-file needs to have exactly one of those.
+        xwriter->writeXMLHeader();
+
+        //start element mygame, you replace the label "mygame" with anything you want
+        xwriter->writeElement(L"mygame");
+        xwriter->writeLineBreak();                  //new line
+
+        //start section with video settings
+        xwriter->writeElement(L"video");
+        xwriter->writeLineBreak();                  //new line
+
+        // getIterator gets us a pointer to the first node of the settings map
+        // every iteration we increase the iterator which gives us the next map node
+        // until we reach the end we write settings one by one by using the nodes key and value functions
+        map<stringw, stringw>::Iterator i = SettingMap.getIterator();
+        for(; !i.atEnd(); i++)
+        {
+            //write element as <setting name="key" value="x" />
+            //the second parameter indicates this is an empty element with no children, just attributes
+            xwriter->writeElement(L"setting",true, L"name", i->getKey().c_str(), L"value",i->getValue().c_str() );
+            xwriter->writeLineBreak();
+        }
+        xwriter->writeLineBreak();
+
+        //close video section
+        xwriter->writeClosingTag(L"video");
+        xwriter->writeLineBreak();
+
+        //..
+        // You can add writing sound settings, savegame information etc
+        //..
+
+        //close mygame section
+        xwriter->writeClosingTag(L"mygame");
+
+        //delete xml writer
+        xwriter->drop();
+
+        return true;
+    }
+
+    // Set setting in our manager
+    void setSetting(const stringw& name, const stringw& value)
+    {
+        SettingMap[name]=value;
+    }
+
+    // set setting overload to quickly assign integers to our setting map
+    void setSetting(const stringw& name, s32 value)
+    {
+        SettingMap[name]=stringw(value);
+    }
+
+    // Get setting as string
+    stringw getSetting(const stringw& key) const
+    {
+        //the find function or irrmap returns a pointer to a map Node
+        //if the key can be found, otherwise it returns null
+        //the map node has the function getValue and getKey, as we already know the key, we return node->getValue()
+        map<stringw, stringw>::Node* n = SettingMap.find(key);
+        if (n)
+            return n->getValue();
+        else
+            return L"";
+    }
+
+    //
+    bool getSettingAsBoolean(const stringw& key ) const
+    {
+        stringw s = getSetting(key);
+        if (s.empty())
+            return false;
+        return s.equals_ignore_case(L"1");
+    }
+
+    //
+    s32 getSettingAsInteger(const stringw& key) const
+    {
+        //we implicitly cast to string instead of stringw because strtol10 does not accept wide strings
+        const stringc s = getSetting(key);
+        if (s.empty())
+            return 0;
+
+        return strtol10(s.c_str());
+    }
+
+public:
+    map<stringw, s32> DriverOptions; //available options for driver config
+    map<stringw, dimension2du> ResolutionOptions; //available options for resolution config
+private:
+    SettingManager(const SettingManager& other); // defined but not implemented
+    SettingManager& operator=(const SettingManager& other); // defined but not implemented
+
+    map<stringw, stringw> SettingMap; //current config
+
+    stringw SettingsFile; // location of the xml, usually the
+    irr::IrrlichtDevice* NullDevice;
+};
+

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;
+
+    //settings dialog
+    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)
+    {
+        if (event.EventType == EET_GUI_EVENT )
+        {
+            switch ( event.GUIEvent.EventType )
+            {
+                //handle button click events
+                case EGET_BUTTON_CLICKED:
+                {
+                    //Our save button was called so we obtain the settings from our dialog and save them
+                    if ( event.GUIEvent.Caller == App.ButtonSave )
+                    {
+                        //if there is a selection write it
+                        if ( App.ListboxDriver->getSelected() != -1)
+                            App.Settings->setSetting(L"driver", App.ListboxDriver->getListItem(App.ListboxDriver->getSelected()));
+
+                        //if there is a selection write it
+                        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);
+                        }
+                    }
+                    // cancel/exit button clicked, tell the application to exit
+                    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)
+{
+    // first get rid of alpha in gui
+    for (irr::s32 i=0; i<irr::gui::EGDC_COUNT ; ++i)
+    {
+        irr::video::SColor col = app.Gui->getSkin()->getColor((irr::gui::EGUI_DEFAULT_COLOR)i);
+        col.setAlpha(255);
+        app.Gui->getSkin()->setColor((irr::gui::EGUI_DEFAULT_COLOR)i, col);
+    }
+
+    //create video settings windows
+    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);
+
+    // add listbox for driver choice
+    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);
+
+    //add all available options to the driver choice listbox
+    map<stringw, s32>::Iterator i = app.Settings->DriverOptions.getIterator();
+    for(; !i.atEnd(); i++)
+        app.ListboxDriver->addItem(i->getKey().c_str());
+
+    //set currently selected driver
+    app.ListboxDriver->setSelected(app.Settings->getSetting("driver").c_str());
+
+    // add listbox for resolution choice
+    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);
+
+    //add all available options to the resolution listbox
+    map<stringw, dimension2du>::Iterator ri = app.Settings->ResolutionOptions.getIterator();
+    for(; !ri.atEnd(); ri++)
+        app.ListboxResolution->addItem(ri->getKey().c_str());
+
+    //set currently selected resolution
+    app.ListboxResolution->setSelected(app.Settings->getSetting("resolution").c_str());
+
+    //add checkbox to toggle fullscreen, initially set to loaded setting
+    app.CheckboxFullscreen = app.Gui->addCheckBox(
+            app.Settings->getSettingAsBoolean("fullscreen"),
+            rect<s32>(10,220,220,240), windowSettings, -1,
+            L"Fullscreen");
+
+    //last but not least add save button
+    app.ButtonSave = app.Gui->addButton(
+            rect<s32>(80,250,150,270), windowSettings, 2,
+            L"Save video settings");
+
+    //exit/cancel button
+    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()
+{
+    //create new application context
+    SAppContext app;
+
+    //create device creation parameters that can get overwritten by our settings file
+    SIrrlichtCreationParameters param;
+    param.DriverType = EDT_SOFTWARE;
+    param.WindowSize.set(640,480);
+
+    // Try to load config.
+    // I leave it as an exercise of the reader to store the configuration in the local application data folder,
+    // the only logical place to store config data for games. For all other operating systems I redirect to your manuals
+    app.Settings = new SettingManager("../../media/settings.xml");
+    if ( !app.Settings->load() )
+    {
+        // ...
+        // Here add your own exception handling, for now we continue because there are defaults set in SettingManager constructor
+        // ...
+    }
+    else
+    {
+        //settings xml loaded from disk,
+
+        //map driversetting to driver type and test if the setting is valid
+        //the DriverOptions map contains string representations mapped to to irrlicht E_DRIVER_TYPE enum
+        //e.g "direct3d9" will become 4
+        //see DriverOptions in the settingmanager class for details
+        map<stringw, s32>::Node* driver = app.Settings->DriverOptions.find( app.Settings->getSetting("driver") );
+
+        if (driver)
+        {
+            if ( irr::IrrlichtDevice::isDriverSupported( static_cast<E_DRIVER_TYPE>( driver->getValue() )))
+            {
+                // selected driver is supported, so we use it.
+                param.DriverType = static_cast<E_DRIVER_TYPE>( driver->getValue());
+            }
+        }
+
+        //map resolution setting to dimension in a similar way as demonstrated above
+        map<stringw, dimension2du>::Node* res = app.Settings->ResolutionOptions.find( app.Settings->getSetting("resolution") );
+        if (res)
+        {
+            param.WindowSize = res->getValue();
+        }
+
+        //get fullscreen setting from config
+        param.Fullscreen = app.Settings->getSettingAsBoolean("fullscreen");
+    }
+
+    //create the irrlicht device using the settings
+    app.Device = createDeviceEx(param);
+    if (app.Device == 0)
+    {
+        // You can add your own exception handling on driver failure
+        exit(0);
+    }
+
+    app.Device->setWindowCaption(L"Xmlhandling - Irrlicht engine tutorial");
+    app.Driver  = app.Device->getVideoDriver();
+    app.Gui     = app.Device->getGUIEnvironment();
+
+    createSettingsDialog(app);
+
+    //set event receiver so we can respond to gui events
+    MyEventReceiver receiver(app);
+    app.Device->setEventReceiver(&receiver);
+
+    //enter main loop
+    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);
+    }
+
+    //app destroys device in destructor
+
+    return 0;
+}
+
+
+ + + + + -- cgit v1.1