diff --git a/src/Settings.cpp b/src/Settings.cpp index 37cf61c30..3ce442708 100644 --- a/src/Settings.cpp +++ b/src/Settings.cpp @@ -1,11 +1,15 @@ #include "Settings.h" #include "Log.h" +#include "pugiXML/pugixml.hpp" +#include "platform.h" +#include Settings* Settings::sInstance = NULL; Settings::Settings() { setDefaults(); + loadFile(); } Settings* Settings::getInstance() @@ -31,18 +35,67 @@ void Settings::setDefaults() mIntMap["DIMTIME"] = 30*1000; } +template +void saveMap(pugi::xml_document& doc, std::map& map, const char* type) +{ + for(auto iter = map.begin(); iter != map.end(); iter++) + { + pugi::xml_node node = doc.append_child(type); + node.append_attribute("name").set_value(iter->first.c_str()); + node.append_attribute("value").set_value(iter->second); + } +} + +void Settings::saveFile() +{ + const std::string path = getHomePath() + "/.emulationstation/es_settings.cfg"; + + pugi::xml_document doc; + + saveMap(doc, mBoolMap, "bool"); + saveMap(doc, mIntMap, "int"); + saveMap(doc, mFloatMap, "float"); + + doc.save_file(path.c_str()); +} + +void Settings::loadFile() +{ + const std::string path = getHomePath() + "/.emulationstation/es_settings.cfg"; + + if(!boost::filesystem::exists(path)) + return; + + pugi::xml_document doc; + pugi::xml_parse_result result = doc.load_file(path.c_str()); + if(!result) + { + LOG(LogError) << "Could not parse Settings file!\n " << result.description(); + return; + } + + for(pugi::xml_node node = doc.child("bool"); node; node = node.next_sibling()) + setBool(node.attribute("name").as_string(), node.attribute("value").as_bool()); + for(pugi::xml_node node = doc.child("int"); node; node = node.next_sibling()) + setInt(node.attribute("name").as_string(), node.attribute("value").as_int()); + for(pugi::xml_node node = doc.child("float"); node; node = node.next_sibling()) + setFloat(node.attribute("name").as_string(), node.attribute("value").as_float()); +} + //Print a warning message if the setting we're trying to get doesn't already exist in the map, then return the value in the map. -#define SETTINGS_GET(type, mapName, methodName) type Settings::##methodName##(const std::string& name) \ +#define SETTINGS_GETSET(type, mapName, getMethodName, setMethodName) type Settings::##getMethodName##(const std::string& name) \ { \ if(mapName.find(name) == mapName.end()) \ { \ LOG(LogError) << "Tried to use unset setting " << name << "!"; \ } \ return mapName[name]; \ +} \ +void Settings::##setMethodName##(const std::string& name, type value) \ +{ \ + mapName[name] = value; \ } -SETTINGS_GET(bool, mBoolMap, getBool); -SETTINGS_GET(int, mIntMap, getInt); - -void Settings::setBool(const std::string& name, bool value) { mBoolMap[name] = value; } -void Settings::setInt(const std::string& name, int value) { mIntMap[name] = value; } +SETTINGS_GETSET(bool, mBoolMap, getBool, setBool); +SETTINGS_GETSET(int, mIntMap, getInt, setInt); +SETTINGS_GETSET(float, mFloatMap, getFloat, setFloat); diff --git a/src/Settings.h b/src/Settings.h index 5babf70c7..099a0afa7 100644 --- a/src/Settings.h +++ b/src/Settings.h @@ -10,15 +10,17 @@ class Settings public: static Settings* getInstance(); - void loadFile(const std::string& path); - void saveFile(const std::string& path); + void loadFile(); + void saveFile(); //You will get a warning if you try a get on a key that is not already present. bool getBool(const std::string& name); int getInt(const std::string& name); + float getFloat(const std::string& name); void setBool(const std::string& name, bool value); void setInt(const std::string& name, int value); + void setFloat(const std::string& name, float value); private: static Settings* sInstance; @@ -30,6 +32,7 @@ private: std::map mBoolMap; std::map mIntMap; + std::map mFloatMap; }; #endif diff --git a/src/components/ComponentListComponent.cpp b/src/components/ComponentListComponent.cpp index acc97632a..0e6af1060 100644 --- a/src/components/ComponentListComponent.cpp +++ b/src/components/ComponentListComponent.cpp @@ -310,3 +310,10 @@ void ComponentListComponent::onOffsetChanged() { updateComponentOffsets(); } + +GuiComponent* ComponentListComponent::getSelectedComponent() +{ + if(!cursorValid()) + return NULL; + return getCell(mCursor.x, mCursor.y)->component; +} diff --git a/src/components/ComponentListComponent.h b/src/components/ComponentListComponent.h index 95faf527b..2045ec53a 100644 --- a/src/components/ComponentListComponent.h +++ b/src/components/ComponentListComponent.h @@ -31,6 +31,8 @@ public: void resetCursor(); bool cursorValid(); + GuiComponent* getSelectedComponent(); + private: class ComponentEntry { diff --git a/src/components/GuiSettingsMenu.cpp b/src/components/GuiSettingsMenu.cpp index 3e31d7fc0..981f11db5 100644 --- a/src/components/GuiSettingsMenu.cpp +++ b/src/components/GuiSettingsMenu.cpp @@ -1,12 +1,16 @@ #include "GuiSettingsMenu.h" #include "../Renderer.h" #include "../Settings.h" -#include "SliderComponent.h" +#include "../VolumeControl.h" GuiSettingsMenu::GuiSettingsMenu(Window* window) : GuiComponent(window), mList(window, Vector2u(2, 3)), - mDrawFramerateSwitch(window) + mDrawFramerateSwitch(window), + mVolumeSlider(window, 0, 100, 1), + mSaveLabel(window) { + loadStates(); + addChild(&mList); mList.setOffset(Renderer::getScreenWidth() / 4, 0); @@ -21,23 +25,19 @@ GuiSettingsMenu::GuiSettingsMenu(Window* window) : GuiComponent(window), mList.setEntry(Vector2u(1, 0), Vector2u(1, 1), &mDrawFramerateSwitch, true, ComponentListComponent::AlignCenter, Vector2(true, true)); label = new TextComponent(mWindow); - label->setText("Volume: "); + label->setText("System volume: "); label->setColor(0x0000FFFF); mList.setEntry(Vector2u(0, 1), Vector2u(1, 1), label, false, ComponentListComponent::AlignRight, Vector2(true, true)); //volume slider - SliderComponent* slider = new SliderComponent(mWindow, 0, 1); - mList.setEntry(Vector2u(1, 1), Vector2u(1, 1), slider, true, ComponentListComponent::AlignCenter, Vector2(true, true)); + mList.setEntry(Vector2u(1, 1), Vector2u(1, 1), &mVolumeSlider, true, ComponentListComponent::AlignCenter, Vector2(true, true)); - label = new TextComponent(mWindow); - label->setText("B TO CLOSE"); - label->setColor(0x00FF00FF); - mList.setEntry(Vector2u(0, 2), Vector2u(2, 1), label, true, ComponentListComponent::AlignCenter, Vector2(false, true)); - mLabels.push_back(label); + //save label + mSaveLabel.setText("SAVE"); + mSaveLabel.setColor(0x000000FF); + mList.setEntry(Vector2u(0, 2), Vector2u(2, 1), &mSaveLabel, true, ComponentListComponent::AlignCenter, Vector2(false, true)); mList.setOffset(Renderer::getScreenWidth() / 2 - mList.getSize().x / 2, 0); - - loadStates(); } GuiSettingsMenu::~GuiSettingsMenu() @@ -60,6 +60,13 @@ bool GuiSettingsMenu::input(InputConfig* config, Input input) return true; } + if(config->isMappedTo("a", input) && mList.getSelectedComponent() == &mSaveLabel && input.value) + { + applyStates(); + delete this; + return true; + } + return false; } @@ -67,4 +74,16 @@ void GuiSettingsMenu::loadStates() { Settings* s = Settings::getInstance(); mDrawFramerateSwitch.setState(s->getBool("DRAWFRAMERATE")); + + mVolumeSlider.setValue((float)VolumeControl::getInstance()->getVolume()); +} + +void GuiSettingsMenu::applyStates() +{ + Settings* s = Settings::getInstance(); + s->setBool("DRAWFRAMERATE", mDrawFramerateSwitch.getState()); + + VolumeControl::getInstance()->setVolume((int)mVolumeSlider.getValue()); + + s->saveFile(); } diff --git a/src/components/GuiSettingsMenu.h b/src/components/GuiSettingsMenu.h index 8f123a335..0b9af8dc3 100644 --- a/src/components/GuiSettingsMenu.h +++ b/src/components/GuiSettingsMenu.h @@ -5,6 +5,7 @@ #include "ComponentListComponent.h" #include #include "SwitchComponent.h" +#include "SliderComponent.h" #include "TextComponent.h" class GuiSettingsMenu : public GuiComponent @@ -22,6 +23,8 @@ private: ComponentListComponent mList; SwitchComponent mDrawFramerateSwitch; + SliderComponent mVolumeSlider; + TextComponent mSaveLabel; std::vector mLabels; }; diff --git a/src/components/SliderComponent.cpp b/src/components/SliderComponent.cpp index 117d84600..e9e92f49a 100644 --- a/src/components/SliderComponent.cpp +++ b/src/components/SliderComponent.cpp @@ -2,15 +2,15 @@ #include #include "../Renderer.h" -SliderComponent::SliderComponent(Window* window, float min, float max) : GuiComponent(window), - mMin(min), mMax(max), mMoveRate(0) +SliderComponent::SliderComponent(Window* window, float min, float max, float increment) : GuiComponent(window), + mMin(min), mMax(max), mIncrement(increment), mMoveRate(0), mRepeatWaitTimer(0) { assert((min - max) != 0); mValue = (max + min) / 2; //calculate move scale - mMoveScale = (max - min) * 0.0007f; + mMoveScale = ((max - min) * 0.0007f) / increment; setSize(Vector2u(128, 32)); } @@ -20,19 +20,24 @@ bool SliderComponent::input(InputConfig* config, Input input) if(config->isMappedTo("left", input)) { if(input.value) - mMoveRate = -1; + mMoveRate = -mIncrement; else mMoveRate = 0; + //setting mRepeatWaitTimer to 0 will trigger an initial move in our update method + mRepeatWaitTimer = 0; + return true; } if(config->isMappedTo("right", input)) { if(input.value) - mMoveRate = 1; + mMoveRate = mIncrement; else mMoveRate = 0; + mRepeatWaitTimer = 0; + return true; } @@ -41,13 +46,22 @@ bool SliderComponent::input(InputConfig* config, Input input) void SliderComponent::update(int deltaTime) { - mValue += mMoveRate * deltaTime * mMoveScale; + if(mMoveRate != 0) + { + if(mRepeatWaitTimer == 0) + mValue += mMoveRate; + else if(mRepeatWaitTimer >= 450) + mValue += mMoveRate * deltaTime * mMoveScale; - if(mValue < mMin) - mValue = mMin; - if(mValue > mMax) - mValue = mMax; + if(mValue < mMin) + mValue = mMin; + if(mValue > mMax) + mValue = mMax; + if(mRepeatWaitTimer < 450) + mRepeatWaitTimer += deltaTime; + } + GuiComponent::update(deltaTime); } @@ -75,3 +89,13 @@ void SliderComponent::setSize(Vector2u size) { mSize = size; } + +void SliderComponent::setValue(float value) +{ + mValue = value; +} + +float SliderComponent::getValue() +{ + return mValue; +} diff --git a/src/components/SliderComponent.h b/src/components/SliderComponent.h index 4550cf652..c6c49ad0d 100644 --- a/src/components/SliderComponent.h +++ b/src/components/SliderComponent.h @@ -5,7 +5,8 @@ class SliderComponent : public GuiComponent { public: - SliderComponent(Window* window, float min, float max); + //Minimum value (far left of the slider), maximum value (far right of the slider), increment size (how much just pressing L/R moves by). + SliderComponent(Window* window, float min, float max, float increment); void setValue(float val); float getValue(); @@ -19,7 +20,9 @@ public: private: float mMin, mMax; float mValue; + float mIncrement; float mMoveScale; + int mRepeatWaitTimer; float mMoveRate; };