From 393b5cd1dc438872af89d334ef6e5fcc59f27d47 Mon Sep 17 00:00:00 2001 From: David Walter Seikel Date: Sun, 13 Jan 2013 17:24:39 +1000 Subject: Added Irrlicht 1.8, but without all the Windows binaries. --- .../irrlicht-1.8/examples/25.XmlHandling/main.cpp | 505 +++++++++++++++++++++ 1 file changed, 505 insertions(+) create mode 100644 libraries/irrlicht-1.8/examples/25.XmlHandling/main.cpp (limited to 'libraries/irrlicht-1.8/examples/25.XmlHandling/main.cpp') diff --git a/libraries/irrlicht-1.8/examples/25.XmlHandling/main.cpp b/libraries/irrlicht-1.8/examples/25.XmlHandling/main.cpp new file mode 100644 index 0000000..3eb261d --- /dev/null +++ b/libraries/irrlicht-1.8/examples/25.XmlHandling/main.cpp @@ -0,0 +1,505 @@ +/** Example 025 Xml Handling + +Demonstrates loading and saving of configurations via XML + +@author Y.M. Bosman \ + +This demo features a fully usable system for configuration handling. The code +can easily be integrated into own apps. + +*/ + +#include + +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 +
+		
+		
+			
+		
+	
+ */ + 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::Iterator i = SettingMap.getIterator(); + for(; !i.atEnd(); i++) + { + //write element as + //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::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 DriverOptions; //available options for driver config + map 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 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; igetSkin()->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(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(10,60,220,120), windowSettings, 1,true); + + //add all available options to the driver choice listbox + map::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(10,140,220,200), windowSettings, 1,true); + + //add all available options to the resolution listbox + map::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(10,220,220,240), windowSettings, -1, + L"Fullscreen"); + + //last but not least add save button + app.ButtonSave = app.Gui->addButton( + rect(80,250,150,270), windowSettings, 2, + L"Save video settings"); + + //exit/cancel button + app.ButtonExit = app.Gui->addButton( + rect(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::Node* driver = app.Settings->DriverOptions.find( app.Settings->getSetting("driver") ); + + if (driver) + { + if ( irr::IrrlichtDevice::isDriverSupported( static_cast( driver->getValue() ))) + { + // selected driver is supported, so we use it. + param.DriverType = static_cast( driver->getValue()); + } + } + + //map resolution setting to dimension in a similar way as demonstrated above + map::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