openFrameworks addon for providing a convenient, JSON-based settings manager
This addon depends on ofxJSON.
Clone this addon into your openFrameworks/addons
folder.
cd path/to/openFrameworks/addons/
# if you don't have it yet
git clone https://github.com/jefftimesten/ofxJSON.git
git clone https://github.com/mattfelsen/ofxJsonSettings.git
Include the header wherever you want to have the settings available. You don't need to instantiate this addon – a singleton instance will be created upon first use.
In your header file
#include "ofxJsonSettings.h"
In your cpp file...
// Use Settings::get() to access the singleton instance
// The load() and save() methods will use "settings.json" if you don't specify a filename
Settings::get().load("data.json");
If you want to save your settings, such as during app exit or on a gui button press...
Settings::get().save("data.json");
// Or disable the default pretty print with..
Settings::get().save("data.json", false);
You can use the following methods to get your settings...
Settings::getString("key")
Settings::getBool("key")
Settings::getInt("key")
Settings::getFloat("key")
Settings::getDouble("key")
ofSetFullscreen(Settings::getBool("fullscreen"));
You can also get nested keys like so...
heading.load(Settings::getString("fonts/heading/face"), Settings::getFloat("fonts/heading/size"));
body.load(Settings::getString("fonts/body/face"), Settings::getFloat("fonts/body/size"));
Accessing nested keys as shown above will parse/save json as such:
{
"fonts" : {
"body" : {
"face": "font-body.ttf",
"size": 16
},
"heading" : {
"face": "font-heading.ttf",
"size": 32
}
}
}
Because all of the getters return references, you can also assign to them...
Settings::getFloat("x-pos") = 100;
Settings::getFloat("y-pos") = 100;
Settings::getFloat("size") = 50;
Or assign a nested structure...
Settings::getFloat("object/x") = 10;
Settings::getFloat("object/y") = 20;
By default, the delimiter is "/" but you can change it with...
Settings::get().setDelimiter("|")
If you have classes that want to get notified of when the settings are loaded or saved, i.e. if you need to reload a font when the json file is loaded, you can...
ofAddListener(Settings::get().settingsLoaded, this, &ofApp::onSettingsLoaded);
ofAddListener(Settings::get().settingsSaved, this, &ofApp::onSettingsSaved);
Set up a hypothetical websocket client
string host = Settings::getString("server/host");
int port = Settings::getInt("server/port");
bool reconnect = Settings::getBool("server/reconnect");
websocketClient.setup(host, port, reconnect)
Bind settings directly to a GUI that supports variable binding, like ofxUI or ofxDatGui
gui->addSlider("X Position", Settings::getFloat("x-pos"));
gui->addSlider("Y Position", Settings::getFloat("y-pos"));
gui->addSlider("Size", Settings::getFloat("size"));
If you're binding variables to a GUI, you'll want to load your settings file before setting up the GUI, and save back to a file on a button press or automatically when the app exits.
A few reasons...
A few addons like ofxUI, ofxDatGui, and ofxRemoteUI support binding variables to GUI elements so that they get updated when you drag a slider, for example. ofxJSON's getter methods, such as json["key"].asString()
return values, not references, so you can't utilize variable binding. This addon's getters, such as Settings::getString("key")
, return references so you can bind away!
This may be subjective, but I find it easier to type slashes rather than lots of double-quotes and square brackets for lookups such as...
- ofxJSON:
json["fonts"]["heading"]["face"].asString()
- ofxJsonSettings:
Settings::getString("fonts/heading/face")
This addon provides a singleton object so that you can access your settings from any file by including the ofxJsonSettings.h
header file. This means you can do things like manage & manipulated GUI-bound settings in some top-level class (like ofApp) and have separate classes which can easily access those values.