├── example ├── bin │ └── data │ │ ├── .gitkeep │ │ ├── IQFONT-bold.otf │ │ ├── Lato-Regular.ttf │ │ └── data.json ├── addons.make ├── src │ ├── main.cpp │ ├── ofApp.h │ └── ofApp.cpp ├── Project.xcconfig ├── openFrameworks-Info.plist └── example.xcodeproj │ ├── xcshareddata │ └── xcschemes │ │ ├── example Debug.xcscheme │ │ └── example Release.xcscheme │ └── project.pbxproj ├── .gitignore ├── src ├── ofxJsonSettings.h └── ofxJsonSettings.cpp └── README.md /example/bin/data/.gitkeep: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /example/addons.make: -------------------------------------------------------------------------------- 1 | ofxJSON 2 | ofxJsonSettings 3 | -------------------------------------------------------------------------------- /example/bin/data/IQFONT-bold.otf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mattfelsen/ofxJsonSettings/HEAD/example/bin/data/IQFONT-bold.otf -------------------------------------------------------------------------------- /example/bin/data/Lato-Regular.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mattfelsen/ofxJsonSettings/HEAD/example/bin/data/Lato-Regular.ttf -------------------------------------------------------------------------------- /example/src/main.cpp: -------------------------------------------------------------------------------- 1 | #include "ofMain.h" 2 | #include "ofApp.h" 3 | 4 | //======================================================================== 5 | int main( ){ 6 | ofSetupOpenGL(1024,768,OF_WINDOW); // <-------- setup the GL context 7 | 8 | // this kicks off the running of my app 9 | // can be OF_WINDOW or OF_FULLSCREEN 10 | // pass in width and height too: 11 | ofRunApp(new ofApp()); 12 | 13 | } 14 | -------------------------------------------------------------------------------- /example/bin/data/data.json: -------------------------------------------------------------------------------- 1 | { 2 | "fonts" : { 3 | "body" : { 4 | "face" : "Lato-Regular.ttf", 5 | "size" : 18 6 | }, 7 | "heading" : { 8 | "face" : "IQFONT-bold.otf", 9 | "size" : 64 10 | } 11 | }, 12 | "fullscreen" : false, 13 | "server" : { 14 | "host" : "192.168.0.1", 15 | "port" : 3000, 16 | "reconnect" : true 17 | } 18 | } 19 | 20 | -------------------------------------------------------------------------------- /example/src/ofApp.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "ofMain.h" 4 | #include "ofxJsonSettings.h" 5 | 6 | class ofApp : public ofBaseApp{ 7 | 8 | public: 9 | void setup(); 10 | void update(); 11 | void draw(); 12 | 13 | void onSettingsLoaded(); 14 | void onSettingsSaved(); 15 | 16 | void keyPressed(int key); 17 | 18 | ofTrueTypeFont heading, body; 19 | 20 | // Note that you do not have to crete an instance of ofxJsonSettings! 21 | // It will be automatically be available to any class that includes the 22 | // header file 23 | 24 | }; 25 | -------------------------------------------------------------------------------- /example/Project.xcconfig: -------------------------------------------------------------------------------- 1 | //THE PATH TO THE ROOT OF OUR OF PATH RELATIVE TO THIS PROJECT. 2 | //THIS NEEDS TO BE DEFINED BEFORE CoreOF.xcconfig IS INCLUDED 3 | OF_PATH = ../../.. 4 | 5 | //THIS HAS ALL THE HEADER AND LIBS FOR OF CORE 6 | #include "../../../libs/openFrameworksCompiled/project/osx/CoreOF.xcconfig" 7 | 8 | //ICONS - NEW IN 0072 9 | ICON_NAME_DEBUG = icon-debug.icns 10 | ICON_NAME_RELEASE = icon.icns 11 | ICON_FILE_PATH = $(OF_PATH)/libs/openFrameworksCompiled/project/osx/ 12 | 13 | //IF YOU WANT AN APP TO HAVE A CUSTOM ICON - PUT THEM IN YOUR DATA FOLDER AND CHANGE ICON_FILE_PATH to: 14 | //ICON_FILE_PATH = bin/data/ 15 | 16 | OTHER_LDFLAGS = $(OF_CORE_LIBS) $(OF_CORE_FRAMEWORKS) 17 | HEADER_SEARCH_PATHS = $(OF_CORE_HEADERS) 18 | -------------------------------------------------------------------------------- /example/openFrameworks-Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | English 7 | CFBundleExecutable 8 | ${EXECUTABLE_NAME} 9 | CFBundleIdentifier 10 | cc.openFrameworks.ofapp 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundlePackageType 14 | APPL 15 | CFBundleSignature 16 | ???? 17 | CFBundleVersion 18 | 1.0 19 | CFBundleIconFile 20 | ${ICON} 21 | 22 | 23 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | ######################### 2 | # openFrameworks patterns 3 | ######################### 4 | 5 | # build files 6 | openFrameworks.a 7 | openFrameworksDebug.a 8 | openFrameworksUniversal.a 9 | libs/openFrameworksCompiled/lib/*/* 10 | !libs/openFrameworksCompiled/lib/*/.gitkeep 11 | 12 | # apothecary 13 | scripts/apothecary/build 14 | 15 | # rule to avoid non-official addons going into git 16 | # see addons/.gitignore 17 | addons/* 18 | 19 | # rule to avoid non-official apps going into git 20 | # see apps/.gitignore 21 | apps/* 22 | 23 | # also, see examples/.gitignore 24 | 25 | ######################### 26 | # general 27 | ######################### 28 | 29 | [Bb]uild/ 30 | [Oo]bj/ 31 | *.o 32 | examples/**/[Dd]ebug*/ 33 | examples/**/[Rr]elease*/ 34 | examples/**/gcc-debug/ 35 | examples/**/gcc-release/ 36 | tests/**/[Dd]ebug*/ 37 | tests/**/[Rr]elease*/ 38 | tests/**/gcc-debug/ 39 | tests/**/gcc-release/ 40 | *.mode* 41 | *.app/ 42 | *.pyc 43 | .svn/ 44 | *.log 45 | *.cpp.eep 46 | *.cpp.elf 47 | *.cpp.hex 48 | 49 | ######################### 50 | # IDE 51 | ######################### 52 | 53 | # XCode 54 | *.pbxuser 55 | *.perspective 56 | *.perspectivev3 57 | *.mode1v3 58 | *.mode2v3 59 | # XCode 4 60 | xcuserdata 61 | *.xcworkspace 62 | 63 | # Code::Blocks 64 | *.depend 65 | *.layout 66 | 67 | # Visual Studio 68 | *.sdf 69 | *.opensdf 70 | *.suo 71 | *.pdb 72 | *.ilk 73 | *.aps 74 | ipch/ 75 | 76 | # Eclipse 77 | .metadata 78 | local.properties 79 | .externalToolBuilders 80 | 81 | # Android Studio 82 | .idea 83 | .gradle 84 | gradle 85 | gradlew 86 | gradlew.bat 87 | 88 | # QtCreator 89 | *.qbs.user 90 | *.pro.user 91 | *.pri 92 | 93 | 94 | ######################### 95 | # operating system 96 | ######################### 97 | 98 | # Linux 99 | *~ 100 | # KDE 101 | .directory 102 | .AppleDouble 103 | 104 | # OSX 105 | .DS_Store 106 | *.swp 107 | *~.nib 108 | # Thumbnails 109 | ._* 110 | 111 | # Windows 112 | # Windows image file caches 113 | Thumbs.db 114 | # Folder config file 115 | Desktop.ini 116 | 117 | # Android 118 | .csettings 119 | /libs/openFrameworksCompiled/project/android/paths.make 120 | 121 | # Android Studio 122 | *.iml 123 | 124 | ######################### 125 | # miscellaneous 126 | ######################### 127 | 128 | .mailmap -------------------------------------------------------------------------------- /example/src/ofApp.cpp: -------------------------------------------------------------------------------- 1 | #include "ofApp.h" 2 | 3 | //-------------------------------------------------------------- 4 | void ofApp::setup(){ 5 | // Use Settings::get() to get the singleton instance 6 | Settings::get().load("data.json"); 7 | 8 | // If you want to save your settings, such as during app exit or on a gui 9 | // button press... 10 | // Settings::get().save("data.json"); 11 | // Or disable the default pretty print with.. 12 | // Settings::get().save("data.json", false); 13 | 14 | // Let's use some data from the settings file! 15 | // You can use the following methods to get your settings... 16 | // - Settings::getString("key") 17 | // - Settings::getBool("key") 18 | // - Settings::getInt("key") 19 | // - Settings::getFloat("key") 20 | // - Settings::getDouble("key") 21 | ofSetFullscreen(Settings::getBool("fullscreen")); 22 | 23 | // You can also get nested keys like so... 24 | heading.load(Settings::getString("fonts/heading/face"), Settings::getFloat("fonts/heading/size")); 25 | body.load(Settings::getString("fonts/body/face"), Settings::getFloat("fonts/body/size")); 26 | 27 | // Update or add a setting... 28 | Settings::getFloat("x-pos") = 100; 29 | Settings::getFloat("y-pos") = 100; 30 | Settings::getFloat("size") = 50; 31 | Settings::getFloat("object/x") = 10; 32 | Settings::getFloat("object/y") = 20; 33 | 34 | // By default, the delimiter is "/" but you can change it with... 35 | // Settings::get().setDelimiter("|") 36 | 37 | // If you have classes that want to get notified of when the 38 | // settings are loaded or saved, i.e. if you need to reload a font 39 | // when the json file is loaded, you can... 40 | ofAddListener(Settings::get().settingsLoaded, this, &ofApp::onSettingsLoaded); 41 | ofAddListener(Settings::get().settingsSaved, this, &ofApp::onSettingsSaved); 42 | 43 | // More examples... 44 | 45 | // Set up a hypothetical websocket client 46 | string host = Settings::getString("server/host"); 47 | int port = Settings::getInt("server/port"); 48 | bool reconnect = Settings::getBool("server/reconnect"); 49 | // websocketClient.setup(host, port, reconnect) 50 | 51 | // Bind settings directly to a GUI that supports variable binding, 52 | // like ofxUI or ofxDatGui 53 | // gui->addSlider("X Position", &Settings::getFloat("x-pos")); 54 | // gui->addSlider("Y Position", &Settings::getFloat("y-pos")); 55 | // gui->addSlider("Size", &Settings::getFloat("size")); 56 | } 57 | 58 | //-------------------------------------------------------------- 59 | void ofApp::update(){ 60 | 61 | } 62 | 63 | //-------------------------------------------------------------- 64 | void ofApp::draw(){ 65 | heading.drawString("This is my header", 20, 100); 66 | body.drawString("And this is my body. Not bad...", 20, 150); 67 | } 68 | 69 | //-------------------------------------------------------------- 70 | void ofApp::onSettingsLoaded(){ 71 | ofLogNotice() << "Settings loaded!"; 72 | 73 | // Reload your font here? 74 | } 75 | 76 | //-------------------------------------------------------------- 77 | void ofApp::onSettingsSaved(){ 78 | ofLogNotice() << "Settings saved!"; 79 | } 80 | 81 | //-------------------------------------------------------------- 82 | void ofApp::keyPressed(int key){ 83 | if (key == 'l') 84 | Settings::get().load("data.json"); 85 | if (key == 's') 86 | Settings::get().save("data.json"); 87 | } 88 | -------------------------------------------------------------------------------- /example/example.xcodeproj/xcshareddata/xcschemes/example Debug.xcscheme: -------------------------------------------------------------------------------- 1 | 2 | 5 | 8 | 9 | 15 | 21 | 22 | 23 | 24 | 25 | 30 | 31 | 32 | 33 | 39 | 40 | 41 | 42 | 51 | 52 | 58 | 59 | 60 | 61 | 62 | 63 | 69 | 70 | 76 | 77 | 78 | 79 | 81 | 82 | 85 | 86 | 87 | -------------------------------------------------------------------------------- /example/example.xcodeproj/xcshareddata/xcschemes/example Release.xcscheme: -------------------------------------------------------------------------------- 1 | 2 | 5 | 8 | 9 | 15 | 21 | 22 | 23 | 24 | 25 | 30 | 31 | 32 | 33 | 39 | 40 | 41 | 42 | 51 | 52 | 58 | 59 | 60 | 61 | 62 | 63 | 69 | 70 | 76 | 77 | 78 | 79 | 81 | 82 | 85 | 86 | 87 | -------------------------------------------------------------------------------- /src/ofxJsonSettings.h: -------------------------------------------------------------------------------- 1 | // 2 | // ofxJsonSettings.h 3 | // ofxJsonSettings 4 | // 5 | // Created by Matt Felsen on 12/7/15. 6 | // 7 | // 8 | 9 | #pragma once 10 | 11 | #include "ofMain.h" 12 | #include "ofxJSON.h" 13 | 14 | // helper for shorter syntax 15 | class ofxJsonSettings; 16 | typedef ofxJsonSettings Settings; 17 | 18 | class ofxJsonSettings { 19 | public: 20 | ofxJsonSettings(); 21 | 22 | // Singleton.. 23 | static ofxJsonSettings& get() { 24 | static ofxJsonSettings instance; 25 | return instance; 26 | } 27 | 28 | void setDelimiter(string delim); 29 | bool load(string file = "settings.json"); 30 | bool save(string file = "settings.json", bool prettyPrint = true); 31 | 32 | string getAsJsonString(); //in case you want to print / read 33 | 34 | // Use this to get values 35 | // These return references, so you can bind directly to a GUI library that 36 | // supports variable binding 37 | static string& getString(string key); 38 | static bool& getBool(string key); 39 | static int& getInt(string key); 40 | static float& getFloat(string key); 41 | static double& getDouble(string key); 42 | static ofVec2f& getVec2(string key); 43 | static ofVec3f& getVec3(string key); 44 | static ofVec4f& getVec4(string key); 45 | static ofColor& getColor(string key); 46 | static ofxJSON getJson(string key); 47 | 48 | // Use this to check if a key exists 49 | static bool exists(string key); 50 | 51 | static bool remove(string key); 52 | 53 | ofEvent settingsLoaded; 54 | ofEvent settingsSaved; 55 | 56 | protected: 57 | string& _stringVal(string& key); 58 | bool& _boolVal(string& key); 59 | int& _intVal(string& key); 60 | float& _floatVal(string& key); 61 | double& _doubleVal(string& key); 62 | ofVec2f& _vec2Val(string& key); 63 | ofVec3f& _vec3Val(string& key); 64 | ofVec4f& _vec4Val(string& key); 65 | ofColor& _colorVal(string& key); 66 | ofxJSON _jsonVal(string& key); 67 | 68 | string _stringValFromJson(ofxJSON& data, string& key); 69 | bool _boolValFromJson(ofxJSON& data, string& key); 70 | int _intValFromJson(ofxJSON& data, string& key); 71 | float _floatValFromJson(ofxJSON& data, string& key); 72 | double _doubleValFromJson(ofxJSON& data, string& key); 73 | ofVec2f _vec2ValFromJson(ofxJSON& data, string& key); 74 | ofVec3f _vec3ValFromJson(ofxJSON& data, string& key); 75 | ofVec4f _vec4ValFromJson(ofxJSON& data, string& key); 76 | ofColor _colorValFromJson(ofxJSON& data, string& key); 77 | 78 | bool _exists(string key); 79 | bool _remove(string key); 80 | 81 | ofxJSON getNestedChild(ofxJSON data, string key, bool supressWarning = false); 82 | ofxJSON getNestedChild(ofxJSON data, vector keys, bool supressWarning = false); 83 | 84 | template 85 | void setNestedChild(ofxJSON& data, string key, T val); 86 | 87 | template 88 | void setNestedChild(ofxJSON& data, vector keys, T val); 89 | 90 | template 91 | void cacheToJson(T& container, ofxJSON& data); 92 | 93 | void cacheToJson(unordered_map& container, ofxJSON& data); 94 | void cacheToJson(unordered_map& container, ofxJSON& data); 95 | void cacheToJson(unordered_map& container, ofxJSON& data); 96 | void cacheToJson(unordered_map& container, ofxJSON& data); 97 | 98 | template 99 | bool exists(T& container, const string &key); 100 | 101 | template 102 | void printMap(T& container, const string& text = ""); 103 | 104 | ofxJSON jsonStore; 105 | unordered_map stringMap; 106 | unordered_map intMap; 107 | unordered_map boolMap; 108 | unordered_map floatMap; 109 | unordered_map doubleMap; 110 | unordered_map vec2Map; 111 | unordered_map vec3Map; 112 | unordered_map vec4Map; 113 | unordered_map colorMap; 114 | 115 | string delimiter; 116 | 117 | private: 118 | // make sure there are no copies 119 | ofxJsonSettings(ofxJsonSettings const&); 120 | void operator=(ofxJsonSettings const&); 121 | }; 122 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # ofxJsonSettings 2 | 3 | openFrameworks addon for providing a convenient, JSON-based settings manager 4 | 5 | ## Requirements 6 | 7 | This addon depends on [ofxJSON](https://github.com/jefftimesten/ofxJSON). 8 | 9 | ## Setup 10 | 11 | Clone this addon into your `openFrameworks/addons` folder. 12 | 13 | ``` 14 | cd path/to/openFrameworks/addons/ 15 | 16 | # if you don't have it yet 17 | git clone https://github.com/jefftimesten/ofxJSON.git 18 | 19 | git clone https://github.com/mattfelsen/ofxJsonSettings.git 20 | ``` 21 | 22 | ## Usage 23 | 24 | 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. 25 | 26 | In your header file 27 | 28 | `#include "ofxJsonSettings.h"` 29 | 30 | In your cpp file... 31 | 32 | #### Load 33 | 34 | ``` 35 | // Use Settings::get() to access the singleton instance 36 | // The load() and save() methods will use "settings.json" if you don't specify a filename 37 | Settings::get().load("data.json"); 38 | ``` 39 | 40 | #### Save 41 | 42 | If you want to save your settings, such as during app exit or on a gui button press... 43 | 44 | ``` 45 | Settings::get().save("data.json"); 46 | // Or disable the default pretty print with.. 47 | Settings::get().save("data.json", false); 48 | ``` 49 | 50 | #### Accessing settings 51 | 52 | You can use the following methods to get your settings... 53 | 54 | - `Settings::getString("key")` 55 | - `Settings::getBool("key")` 56 | - `Settings::getInt("key")` 57 | - `Settings::getFloat("key")` 58 | - `Settings::getDouble("key")` 59 | 60 | ``` 61 | ofSetFullscreen(Settings::getBool("fullscreen")); 62 | ``` 63 | 64 | You can also get nested keys like so... 65 | 66 | ``` 67 | heading.load(Settings::getString("fonts/heading/face"), Settings::getFloat("fonts/heading/size")); 68 | body.load(Settings::getString("fonts/body/face"), Settings::getFloat("fonts/body/size")); 69 | ``` 70 | 71 | Accessing nested keys as shown above will parse/save json as such: 72 | 73 | ``` 74 | { 75 | "fonts" : { 76 | "body" : { 77 | "face": "font-body.ttf", 78 | "size": 16 79 | }, 80 | "heading" : { 81 | "face": "font-heading.ttf", 82 | "size": 32 83 | } 84 | } 85 | } 86 | ``` 87 | 88 | #### Updating or adding a setting... 89 | 90 | Because all of the getters return references, you can also assign to them... 91 | 92 | ``` 93 | Settings::getFloat("x-pos") = 100; 94 | Settings::getFloat("y-pos") = 100; 95 | Settings::getFloat("size") = 50; 96 | ``` 97 | 98 | Or assign a nested structure... 99 | 100 | ``` 101 | Settings::getFloat("object/x") = 10; 102 | Settings::getFloat("object/y") = 20; 103 | ``` 104 | 105 | #### Delimiter 106 | 107 | By default, the delimiter is "/" but you can change it with... 108 | 109 | ``` 110 | Settings::get().setDelimiter("|") 111 | ``` 112 | 113 | #### Events 114 | 115 | 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... 116 | 117 | ``` 118 | ofAddListener(Settings::get().settingsLoaded, this, &ofApp::onSettingsLoaded); 119 | ofAddListener(Settings::get().settingsSaved, this, &ofApp::onSettingsSaved); 120 | ``` 121 | 122 | #### More examples... 123 | 124 | Set up a hypothetical websocket client 125 | 126 | ``` 127 | string host = Settings::getString("server/host"); 128 | int port = Settings::getInt("server/port"); 129 | bool reconnect = Settings::getBool("server/reconnect"); 130 | websocketClient.setup(host, port, reconnect) 131 | ``` 132 | 133 | Bind settings directly to a GUI that supports variable binding, like ofxUI or ofxDatGui 134 | 135 | ``` 136 | gui->addSlider("X Position", Settings::getFloat("x-pos")); 137 | gui->addSlider("Y Position", Settings::getFloat("y-pos")); 138 | gui->addSlider("Size", Settings::getFloat("size")); 139 | ``` 140 | 141 | 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. 142 | 143 | ## Wait, why not just use ofxJSON directly? 144 | 145 | A few reasons... 146 | 147 | ### Variable binding for GUIs 148 | 149 | A few addons like [ofxUI](https://github.com/rezaali/ofxUI), [ofxDatGui](https://github.com/braitsch/ofxDatGui), and [ofxRemoteUI](https://github.com/armadillu/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! 150 | 151 | ### More concise syntax for nested keys 152 | 153 | 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... 154 | 155 | - ofxJSON: `json["fonts"]["heading"]["face"].asString()` 156 | - ofxJsonSettings: `Settings::getString("fonts/heading/face")` 157 | 158 | ### Global access 159 | 160 | 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. 161 | -------------------------------------------------------------------------------- /src/ofxJsonSettings.cpp: -------------------------------------------------------------------------------- 1 | // 2 | // ofxJsonSettings.cpp 3 | // ofxJsonSettings 4 | // 5 | // Created by Matt Felsen on 12/10/15. 6 | // 7 | // 8 | 9 | #include "ofxJsonSettings.h" 10 | 11 | ofxJsonSettings::ofxJsonSettings() { 12 | delimiter = "/"; 13 | } 14 | 15 | void ofxJsonSettings::setDelimiter(string delim) { 16 | delimiter = delim; 17 | } 18 | 19 | bool ofxJsonSettings::load(string file) { 20 | ofxJSON loadData; 21 | bool success = loadData.open(file); 22 | 23 | if (success) { 24 | jsonStore = loadData; 25 | 26 | 27 | // Any values bound to gui are bound to memory address of value 28 | // inside various cached map objects, so we can't clear() the maps 29 | // Instead, load new values from new json object to cached maps 30 | 31 | // TODO: remove old keys when loading 32 | // Any keys that were in the old json that have been removed from 33 | // the new file won't be deleted from the cached maps. Need to compare 34 | // jsonStore vs loadData objects and remove missing keys? 35 | for (auto& it : stringMap) { 36 | string key = it.first; 37 | stringMap[key] = _stringValFromJson(jsonStore, key); 38 | } 39 | for (auto& it : boolMap) { 40 | string key = it.first; 41 | boolMap[key] = _boolValFromJson(jsonStore, key); 42 | } 43 | for (auto& it : intMap) { 44 | string key = it.first; 45 | intMap[key] = _intValFromJson(jsonStore, key); 46 | } 47 | for (auto& it : floatMap) { 48 | string key = it.first; 49 | floatMap[key] = _floatValFromJson(jsonStore, key); 50 | } 51 | for (auto& it : doubleMap) { 52 | string key = it.first; 53 | doubleMap[key] = _doubleValFromJson(jsonStore, key); 54 | } 55 | for (auto& it : vec2Map) { 56 | string key = it.first; 57 | vec2Map[key] = _vec2ValFromJson(jsonStore, key); 58 | } 59 | for (auto& it : vec3Map) { 60 | string key = it.first; 61 | vec3Map[key] = _vec3ValFromJson(jsonStore, key); 62 | } 63 | for (auto& it : vec4Map) { 64 | string key = it.first; 65 | vec4Map[key] = _vec4ValFromJson(jsonStore, key); 66 | } 67 | for (auto& it : colorMap) { 68 | string key = it.first; 69 | colorMap[key] = _colorValFromJson(jsonStore, key); 70 | } 71 | 72 | ofNotifyEvent(settingsLoaded); 73 | } else { 74 | ofLogError("Settings") << "could not load file! " << file; 75 | } 76 | 77 | return success; 78 | } 79 | 80 | bool ofxJsonSettings::save(string file, bool prettyPrint) { 81 | // Write cached values back to JSON object 82 | cacheToJson(stringMap, jsonStore); 83 | cacheToJson(boolMap, jsonStore); 84 | cacheToJson(intMap, jsonStore); 85 | cacheToJson(floatMap, jsonStore); 86 | cacheToJson(doubleMap, jsonStore); 87 | cacheToJson(vec2Map, jsonStore); 88 | cacheToJson(vec3Map, jsonStore); 89 | cacheToJson(vec4Map, jsonStore); 90 | cacheToJson(colorMap, jsonStore); 91 | bool success = jsonStore.save(file, prettyPrint); 92 | 93 | if (success) { 94 | ofNotifyEvent(settingsSaved); 95 | } else { 96 | ofLogError("Settings") << "could not save file! " << file; 97 | } 98 | 99 | return success; 100 | } 101 | 102 | string ofxJsonSettings::getAsJsonString(){ 103 | 104 | ofxJSON tempJson = jsonStore; 105 | cacheToJson(stringMap, tempJson); 106 | cacheToJson(boolMap, tempJson); 107 | cacheToJson(intMap, tempJson); 108 | cacheToJson(floatMap, tempJson); 109 | cacheToJson(doubleMap, tempJson); 110 | cacheToJson(vec2Map, tempJson); 111 | cacheToJson(vec3Map, tempJson); 112 | cacheToJson(vec4Map, tempJson); 113 | cacheToJson(colorMap, tempJson); 114 | string pretty = tempJson.getRawString(true); 115 | return pretty; 116 | } 117 | 118 | string& ofxJsonSettings::getString(string key) { 119 | return get()._stringVal(key); 120 | } 121 | bool& ofxJsonSettings::getBool(string key) { 122 | return get()._boolVal(key); 123 | } 124 | int& ofxJsonSettings::getInt(string key) { 125 | return get()._intVal(key); 126 | } 127 | float& ofxJsonSettings::getFloat(string key) { 128 | return get()._floatVal(key); 129 | } 130 | double& ofxJsonSettings::getDouble(string key) { 131 | return get()._doubleVal(key); 132 | } 133 | ofVec2f& ofxJsonSettings::getVec2(string key) { 134 | return get()._vec2Val(key); 135 | } 136 | ofVec3f& ofxJsonSettings::getVec3(string key) { 137 | return get()._vec3Val(key); 138 | } 139 | ofVec4f& ofxJsonSettings::getVec4(string key) { 140 | return get()._vec4Val(key); 141 | } 142 | ofColor& ofxJsonSettings::getColor(string key) { 143 | return get()._colorVal(key); 144 | } 145 | ofxJSON ofxJsonSettings::getJson(string key) { 146 | return get()._jsonVal(key); 147 | } 148 | 149 | bool ofxJsonSettings::exists(string key) { 150 | return get()._exists(key); 151 | } 152 | 153 | bool ofxJsonSettings::remove(string key) { 154 | return get()._remove(key); 155 | } 156 | 157 | string& ofxJsonSettings::_stringVal(string& key) { 158 | if (!exists(stringMap, key)) { 159 | stringMap[key] = _stringValFromJson(jsonStore, key); 160 | } 161 | 162 | // printMap(stringMap, "strings"); 163 | return stringMap[key]; 164 | } 165 | 166 | bool& ofxJsonSettings::_boolVal(string& key) { 167 | if (!exists(boolMap, key)) { 168 | boolMap[key] = _boolValFromJson(jsonStore, key); 169 | } 170 | 171 | // printMap(boolMap, "bools"); 172 | return boolMap[key]; 173 | } 174 | 175 | int& ofxJsonSettings::_intVal(string& key) { 176 | if (!exists(intMap, key)) { 177 | intMap[key] = _intValFromJson(jsonStore, key); 178 | } 179 | 180 | // printMap(intMap, "ints"); 181 | return intMap[key]; 182 | } 183 | 184 | float& ofxJsonSettings::_floatVal(string& key) { 185 | if (!exists(floatMap, key)) { 186 | floatMap[key] = _floatValFromJson(jsonStore, key); 187 | } 188 | 189 | // printMap(floatMap, "floats"); 190 | return floatMap[key]; 191 | } 192 | 193 | double& ofxJsonSettings::_doubleVal(string& key) { 194 | if (!exists(doubleMap, key)) { 195 | doubleMap[key] = _doubleValFromJson(jsonStore, key); 196 | } 197 | 198 | // printMap(doubleMap, "doubles"); 199 | return doubleMap[key]; 200 | } 201 | 202 | ofVec2f& ofxJsonSettings::_vec2Val(string& key) { 203 | if (!exists(vec2Map, key)) { 204 | vec2Map[key] = _vec2ValFromJson(jsonStore, key); 205 | } 206 | 207 | // printMap(vec2Map, "vec2s"); 208 | return vec2Map[key]; 209 | } 210 | 211 | ofVec3f& ofxJsonSettings::_vec3Val(string& key) { 212 | if (!exists(vec3Map, key)) { 213 | vec3Map[key] = _vec3ValFromJson(jsonStore, key); 214 | } 215 | 216 | // printMap(vec3Map, "vec3s"); 217 | return vec3Map[key]; 218 | } 219 | 220 | ofVec4f& ofxJsonSettings::_vec4Val(string& key) { 221 | if (!exists(vec4Map, key)) { 222 | vec4Map[key] = _vec4ValFromJson(jsonStore, key); 223 | } 224 | 225 | // printMap(vec4Map, "vec4s"); 226 | return vec4Map[key]; 227 | } 228 | 229 | ofColor& ofxJsonSettings::_colorVal(string& key) { 230 | if (!exists(colorMap, key)) { 231 | colorMap[key] = _colorValFromJson(jsonStore, key); 232 | } 233 | 234 | // printMap(colorMap, "colors"); 235 | return colorMap[key]; 236 | } 237 | 238 | ofxJSON ofxJsonSettings::_jsonVal(string& key) { 239 | if (ofStringTimesInString(key, delimiter)) { 240 | return getNestedChild(jsonStore, key); 241 | } else if (jsonStore.isMember(key)) { 242 | return jsonStore[key]; 243 | } 244 | } 245 | 246 | string ofxJsonSettings::_stringValFromJson(ofxJSON& data, string& key) { 247 | try { 248 | // For keys like "fonts/face/serif", split the string and do a recursive 249 | // lookup to find that json element 250 | if (ofStringTimesInString(key, delimiter)) { 251 | return getNestedChild(data, key).asString(); 252 | } 253 | // Otherwise do a direct lookup if the key exists 254 | else if (data.isMember(key)) { 255 | return data[key].asString(); 256 | } 257 | else { 258 | ofLogWarning("Settings") << "no setting found for: " << key; 259 | return ""; 260 | } 261 | } catch (const runtime_error& e) { 262 | ofLogError("Settings") << "error for key: " << key << ": " << e.what(); 263 | return ""; 264 | } 265 | } 266 | 267 | bool ofxJsonSettings::_boolValFromJson(ofxJSON& data, string& key) { 268 | // See _stringValFromJson() for explanation 269 | try { 270 | if (ofStringTimesInString(key, delimiter)) { 271 | return getNestedChild(data, key).asBool(); 272 | } else if (data.isMember(key)) { 273 | return data[key].asBool(); 274 | } else { 275 | ofLogWarning("Settings") << "no setting found for: " << key; 276 | return false; 277 | } 278 | } catch (const runtime_error& e) { 279 | ofLogError("Settings") << "error for key: " << key << ": " << e.what(); 280 | return false; 281 | } 282 | } 283 | 284 | int ofxJsonSettings::_intValFromJson(ofxJSON& data, string& key) { 285 | // See _stringValFromJson() for explanation 286 | try { 287 | if (ofStringTimesInString(key, delimiter)) { 288 | return getNestedChild(data, key).asInt(); 289 | } else if (data.isMember(key)) { 290 | return data[key].asInt(); 291 | } else { 292 | ofLogWarning("Settings") << "no setting found for: " << key; 293 | return 0; 294 | } 295 | } catch (const runtime_error& e) { 296 | ofLogError("Settings") << "error for key: " << key << ": " << e.what(); 297 | return 0; 298 | } 299 | } 300 | 301 | float ofxJsonSettings::_floatValFromJson(ofxJSON& data, string& key) { 302 | // See _stringValFromJson() for explanation 303 | try { 304 | if (ofStringTimesInString(key, delimiter)) { 305 | return getNestedChild(data, key).asFloat(); 306 | } else if (data.isMember(key)) { 307 | return data[key].asFloat(); 308 | } else { 309 | ofLogWarning("Settings") << "no setting found for: " << key; 310 | return 0; 311 | } 312 | } catch (const runtime_error& e) { 313 | ofLogError("Settings") << "error for key: " << key << ": " << e.what(); 314 | return 0; 315 | } 316 | } 317 | 318 | double ofxJsonSettings::_doubleValFromJson(ofxJSON& data, string& key) { 319 | // See _stringValFromJson() for explanation 320 | try { 321 | if (ofStringTimesInString(key, delimiter)) { 322 | return getNestedChild(data, key).asDouble(); 323 | } else if (data.isMember(key)) { 324 | return data[key].asDouble(); 325 | } else { 326 | ofLogWarning("Settings") << "no setting found for: " << key; 327 | return 0; 328 | } 329 | } catch (const runtime_error& e) { 330 | ofLogError("Settings") << "error for key: " << key << ": " << e.what(); 331 | return 0; 332 | } 333 | } 334 | 335 | ofVec2f ofxJsonSettings::_vec2ValFromJson(ofxJSON& data, string& key) { 336 | // See _stringValFromJson() for explanation 337 | ofVec2f vec; 338 | 339 | try { 340 | if (ofStringTimesInString(key, delimiter)) { 341 | vec.x = getNestedChild(data, key)[0].asFloat(); 342 | vec.y = getNestedChild(data, key)[1].asFloat(); 343 | } else if (data.isMember(key)) { 344 | vec.x = data[key][0].asFloat(); 345 | vec.y = data[key][1].asFloat(); 346 | } else { 347 | ofLogWarning("Settings") << "no setting found for: " << key; 348 | } 349 | } catch (const runtime_error& e) { 350 | ofLogError("Settings") << "error for key: " << key << ": " << e.what(); 351 | } 352 | 353 | return vec; 354 | } 355 | 356 | ofVec3f ofxJsonSettings::_vec3ValFromJson(ofxJSON& data, string& key) { 357 | // See _stringValFromJson() for explanation 358 | ofVec3f vec; 359 | 360 | try { 361 | if (ofStringTimesInString(key, delimiter)) { 362 | vec.x = getNestedChild(data, key)[0].asFloat(); 363 | vec.y = getNestedChild(data, key)[1].asFloat(); 364 | vec.z = getNestedChild(data, key)[2].asFloat(); 365 | } else if (data.isMember(key)) { 366 | vec.x = data[key][0].asFloat(); 367 | vec.y = data[key][1].asFloat(); 368 | vec.z = data[key][2].asFloat(); 369 | } else { 370 | ofLogWarning("Settings") << "no setting found for: " << key; 371 | } 372 | } catch (const runtime_error& e) { 373 | ofLogError("Settings") << "error for key: " << key << ": " << e.what(); 374 | } 375 | 376 | return vec; 377 | } 378 | 379 | ofVec4f ofxJsonSettings::_vec4ValFromJson(ofxJSON& data, string& key) { 380 | // See _stringValFromJson() for explanation 381 | ofVec4f vec; 382 | 383 | try { 384 | if (ofStringTimesInString(key, delimiter)) { 385 | vec.x = getNestedChild(data, key)[0].asFloat(); 386 | vec.y = getNestedChild(data, key)[1].asFloat(); 387 | vec.z = getNestedChild(data, key)[2].asFloat(); 388 | vec.w = getNestedChild(data, key)[3].asFloat(); 389 | } else if (data.isMember(key)) { 390 | vec.x = data[key][0].asFloat(); 391 | vec.y = data[key][1].asFloat(); 392 | vec.z = data[key][2].asFloat(); 393 | vec.w = data[key][3].asFloat(); 394 | } else { 395 | ofLogWarning("Settings") << "no setting found for: " << key; 396 | } 397 | } catch (const runtime_error& e) { 398 | ofLogError("Settings") << "error for key: " << key << ": " << e.what(); 399 | } 400 | 401 | return vec; 402 | } 403 | 404 | ofColor ofxJsonSettings::_colorValFromJson(ofxJSON& data, string& key) { 405 | // See _stringValFromJson() for explanation 406 | ofColor c; 407 | 408 | try { 409 | if (ofStringTimesInString(key, delimiter)) { 410 | c.r = getNestedChild(data, key)[0].asFloat(); 411 | c.g = getNestedChild(data, key)[1].asFloat(); 412 | c.b = getNestedChild(data, key)[2].asFloat(); 413 | } else if (data.isMember(key)) { 414 | c.r = data[key][0].asFloat(); 415 | c.g = data[key][1].asFloat(); 416 | c.b = data[key][2].asFloat(); 417 | } else { 418 | ofLogWarning("Settings") << "no setting found for: " << key; 419 | } 420 | } catch (const runtime_error& e) { 421 | ofLogError("Settings") << "error for key: " << key << ": " << e.what(); 422 | } 423 | 424 | return c; 425 | } 426 | 427 | bool ofxJsonSettings::_exists(string key) { 428 | try { 429 | if (ofStringTimesInString(key, delimiter)) 430 | return (getNestedChild(jsonStore, key, true) != ofxJSON()); 431 | else 432 | return jsonStore.isMember(key); 433 | } catch (const runtime_error& e) { 434 | ofLogError("Settings") << "error for key: " << key << ": " << e.what(); 435 | return false; 436 | } 437 | } 438 | 439 | bool ofxJsonSettings::_remove(string key) { 440 | try { 441 | if (ofStringTimesInString(key, delimiter)) 442 | // TODO: removing non top-level data 443 | ofLogWarning("Settings") << "remove() is only support on top-level (not nested) keys!"; 444 | else { 445 | jsonStore.removeMember(key); 446 | stringMap.erase(key); 447 | intMap.erase(key); 448 | boolMap.erase(key); 449 | floatMap.erase(key); 450 | doubleMap.erase(key); 451 | vec2Map.erase(key); 452 | vec3Map.erase(key); 453 | vec4Map.erase(key); 454 | colorMap.erase(key); 455 | } 456 | } catch (const runtime_error& e) { 457 | ofLogError("Settings") << "error for key: " << key << ": " << e.what(); 458 | return false; 459 | } 460 | } 461 | 462 | ofxJSON ofxJsonSettings::getNestedChild(ofxJSON data, string key, bool supressWarning) { 463 | auto keys = ofSplitString(key, delimiter); 464 | return getNestedChild(data, keys, supressWarning); 465 | } 466 | 467 | ofxJSON ofxJsonSettings::getNestedChild(ofxJSON data, vector keys, bool supressWarning) { 468 | // Given a lookup key like "fonts/face/serif", find the corresponding 469 | // json object data["fonts"]["face"]["serif"] 470 | // (The other signature of this function actually splits the string into a 471 | // vector of keys) 472 | if (keys.size()) { 473 | string key = keys.front(); 474 | keys.erase(keys.begin()); 475 | 476 | if (data.isMember(key)) { 477 | return getNestedChild(data[key], keys, supressWarning); 478 | } else { 479 | if (!supressWarning) 480 | ofLogWarning("Settings") << "no setting found for: " << key; 481 | 482 | return ofxJSON(); 483 | } 484 | } 485 | 486 | return data; 487 | } 488 | 489 | template 490 | void ofxJsonSettings::setNestedChild(ofxJSON& data, string key, T val) { 491 | auto keys = ofSplitString(key, delimiter); 492 | setNestedChild(data, keys, val); 493 | } 494 | 495 | template 496 | void ofxJsonSettings::setNestedChild(ofxJSON& data, vector keys, T val) { 497 | // Given a lookup key like "fonts/face/serif", find the corresponding 498 | // json object data["fonts"]["face"]["serif"] and set its value 499 | // (The other signature of this function actually splits the string into a 500 | // vector of keys) 501 | auto* object = &data; 502 | 503 | if (keys.size() < 2) { 504 | ofLogError("Settings") 505 | << "setNestedChild() malformed key (should be at least object/key): " 506 | << ofJoinString(keys, delimiter); 507 | return; 508 | } 509 | 510 | while (keys.size()) { 511 | string key = keys.front(); 512 | if (keys.size() == 1) { 513 | (*object)[key] = val; 514 | return; 515 | } else { 516 | keys.erase(keys.begin()); 517 | object = (ofxJSON *) &(*object)[key]; 518 | } 519 | } 520 | } 521 | 522 | template 523 | void ofxJsonSettings::cacheToJson(T& container, ofxJSON& data) { 524 | for (auto& it : container) { 525 | string key = it.first; 526 | if (ofStringTimesInString(key, delimiter)) { 527 | setNestedChild(data, key, it.second); 528 | } else { 529 | data[key] = container[key]; 530 | } 531 | } 532 | } 533 | 534 | void ofxJsonSettings::cacheToJson(unordered_map& container, ofxJSON& data) { 535 | for (auto& it : container) { 536 | string key = it.first; 537 | 538 | ofxJSON array; 539 | array.append(it.second.x); 540 | array.append(it.second.y); 541 | 542 | if (ofStringTimesInString(key, delimiter)) { 543 | setNestedChild(data, key, array); 544 | } else { 545 | data[key] = array; 546 | } 547 | } 548 | } 549 | 550 | void ofxJsonSettings::cacheToJson(unordered_map& container, ofxJSON& data) { 551 | for (auto& it : container) { 552 | string key = it.first; 553 | 554 | ofxJSON array; 555 | array.append(it.second.x); 556 | array.append(it.second.y); 557 | array.append(it.second.z); 558 | 559 | if (ofStringTimesInString(key, delimiter)) { 560 | setNestedChild(data, key, array); 561 | } else { 562 | data[key] = array; 563 | } 564 | } 565 | } 566 | 567 | void ofxJsonSettings::cacheToJson(unordered_map& container, ofxJSON& data) { 568 | for (auto& it : container) { 569 | string key = it.first; 570 | 571 | ofxJSON array; 572 | array.append(it.second.x); 573 | array.append(it.second.y); 574 | array.append(it.second.z); 575 | array.append(it.second.w); 576 | 577 | if (ofStringTimesInString(key, delimiter)) { 578 | setNestedChild(data, key, array); 579 | } else { 580 | data[key] = array; 581 | } 582 | } 583 | } 584 | 585 | void ofxJsonSettings::cacheToJson(unordered_map& container, ofxJSON& data) { 586 | for (auto& it : container) { 587 | string key = it.first; 588 | 589 | ofxJSON array; 590 | array.append(it.second.r); 591 | array.append(it.second.g); 592 | array.append(it.second.b); 593 | 594 | if (ofStringTimesInString(key, delimiter)) { 595 | setNestedChild(data, key, array); 596 | } else { 597 | data[key] = array; 598 | } 599 | } 600 | } 601 | 602 | template 603 | bool ofxJsonSettings::exists(T& container, const string &key) { 604 | return container.find(key) != container.end(); 605 | } 606 | 607 | template 608 | void ofxJsonSettings::printMap(T& container, const string& text) { 609 | for (auto& it : container) { 610 | ofLogNotice() << text << ": " << it.first << ": " << it.second; 611 | } 612 | } 613 | -------------------------------------------------------------------------------- /example/example.xcodeproj/project.pbxproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | archiveVersion 5 | 1 6 | classes 7 | 8 | objectVersion 9 | 46 10 | objects 11 | 12 | 75518C7E199C3E1899D48A1C 13 | 14 | explicitFileType 15 | sourcecode.c.h 16 | fileEncoding 17 | 30 18 | isa 19 | PBXFileReference 20 | name 21 | ofxJsonSettings.h 22 | path 23 | ../../../addons/ofxJsonSettings/src/ofxJsonSettings.h 24 | sourceTree 25 | SOURCE_ROOT 26 | 27 | D8BD50F2ECD44CC0EA9CFC4B 28 | 29 | children 30 | 31 | 7063D69378AE7A2726B5CD32 32 | 75518C7E199C3E1899D48A1C 33 | 34 | isa 35 | PBXGroup 36 | name 37 | src 38 | sourceTree 39 | <group> 40 | 41 | FECB24CC26FE943EF8E1DDF5 42 | 43 | children 44 | 45 | D8BD50F2ECD44CC0EA9CFC4B 46 | 47 | isa 48 | PBXGroup 49 | name 50 | ofxJsonSettings 51 | sourceTree 52 | <group> 53 | 54 | 045CDF359630386A720A2524 55 | 56 | fileRef 57 | 7063D69378AE7A2726B5CD32 58 | isa 59 | PBXBuildFile 60 | 61 | 7063D69378AE7A2726B5CD32 62 | 63 | explicitFileType 64 | sourcecode.cpp.cpp 65 | fileEncoding 66 | 30 67 | isa 68 | PBXFileReference 69 | name 70 | ofxJsonSettings.cpp 71 | path 72 | ../../../addons/ofxJsonSettings/src/ofxJsonSettings.cpp 73 | sourceTree 74 | SOURCE_ROOT 75 | 76 | CCDC6F9CCF925CC402160B85 77 | 78 | children 79 | 80 | 21BDE665988474F1B1F4D302 81 | 82 | isa 83 | PBXGroup 84 | name 85 | src 86 | sourceTree 87 | <group> 88 | 89 | FB84AAF8D1B7A95266DB5C09 90 | 91 | fileRef 92 | 21BDE665988474F1B1F4D302 93 | isa 94 | PBXBuildFile 95 | 96 | 21BDE665988474F1B1F4D302 97 | 98 | explicitFileType 99 | sourcecode.cpp.cpp 100 | fileEncoding 101 | 30 102 | isa 103 | PBXFileReference 104 | name 105 | jsoncpp.cpp 106 | path 107 | ../../../addons/ofxJSON/libs/jsoncpp/src/jsoncpp.cpp 108 | sourceTree 109 | SOURCE_ROOT 110 | 111 | 2C7CF000B7B4F782C187C353 112 | 113 | explicitFileType 114 | sourcecode.c.h 115 | fileEncoding 116 | 30 117 | isa 118 | PBXFileReference 119 | name 120 | json.h 121 | path 122 | ../../../addons/ofxJSON/libs/jsoncpp/include/json/json.h 123 | sourceTree 124 | SOURCE_ROOT 125 | 126 | 58AD3BD71B781D9BC25763C8 127 | 128 | children 129 | 130 | 61313493CDB52744E22A604D 131 | 2C7CF000B7B4F782C187C353 132 | 133 | isa 134 | PBXGroup 135 | name 136 | json 137 | sourceTree 138 | <group> 139 | 140 | D486FC87F063317BB47E9FAC 141 | 142 | children 143 | 144 | 58AD3BD71B781D9BC25763C8 145 | 146 | isa 147 | PBXGroup 148 | name 149 | include 150 | sourceTree 151 | <group> 152 | 153 | 977A836DD2C489CCC5E330FF 154 | 155 | children 156 | 157 | D486FC87F063317BB47E9FAC 158 | CCDC6F9CCF925CC402160B85 159 | 160 | isa 161 | PBXGroup 162 | name 163 | jsoncpp 164 | sourceTree 165 | <group> 166 | 167 | F40E80CB2D443CBA9581DD03 168 | 169 | children 170 | 171 | 977A836DD2C489CCC5E330FF 172 | 173 | isa 174 | PBXGroup 175 | name 176 | libs 177 | sourceTree 178 | <group> 179 | 180 | 61313493CDB52744E22A604D 181 | 182 | explicitFileType 183 | sourcecode.c.h 184 | fileEncoding 185 | 30 186 | isa 187 | PBXFileReference 188 | name 189 | json-forwards.h 190 | path 191 | ../../../addons/ofxJSON/libs/jsoncpp/include/json/json-forwards.h 192 | sourceTree 193 | SOURCE_ROOT 194 | 195 | 1645F56257269CD0356320BD 196 | 197 | explicitFileType 198 | sourcecode.c.h 199 | fileEncoding 200 | 30 201 | isa 202 | PBXFileReference 203 | name 204 | ofxJSON.h 205 | path 206 | ../../../addons/ofxJSON/src/ofxJSON.h 207 | sourceTree 208 | SOURCE_ROOT 209 | 210 | 292AF6148769654D0DF26018 211 | 212 | children 213 | 214 | 8CEA9A3FA2DD575EBF7839D4 215 | 1645F56257269CD0356320BD 216 | 217 | isa 218 | PBXGroup 219 | name 220 | src 221 | sourceTree 222 | <group> 223 | 224 | 2865DAEF86B1907A704CA70B 225 | 226 | children 227 | 228 | 292AF6148769654D0DF26018 229 | F40E80CB2D443CBA9581DD03 230 | 231 | isa 232 | PBXGroup 233 | name 234 | ofxJSON 235 | sourceTree 236 | <group> 237 | 238 | EA1838CCB5F7BA2A48AEF0CF 239 | 240 | fileRef 241 | 8CEA9A3FA2DD575EBF7839D4 242 | isa 243 | PBXBuildFile 244 | 245 | 8CEA9A3FA2DD575EBF7839D4 246 | 247 | explicitFileType 248 | sourcecode.cpp.cpp 249 | fileEncoding 250 | 30 251 | isa 252 | PBXFileReference 253 | name 254 | ofxJSON.cpp 255 | path 256 | ../../../addons/ofxJSON/src/ofxJSON.cpp 257 | sourceTree 258 | SOURCE_ROOT 259 | 260 | 6948EE371B920CB800B5AC1A 261 | 262 | children 263 | 264 | isa 265 | PBXGroup 266 | name 267 | local_addons 268 | sourceTree 269 | <group> 270 | 271 | 8466F1851C04CA0E00918B1C 272 | 273 | buildActionMask 274 | 12 275 | files 276 | 277 | inputPaths 278 | 279 | isa 280 | PBXShellScriptBuildPhase 281 | outputPaths 282 | 283 | runOnlyForDeploymentPostprocessing 284 | 0 285 | shellPath 286 | /bin/sh 287 | shellScript 288 | # ---- Code Sign App Package ---- 289 | 290 | # WARNING: You may have to run Clean in Xcode after changing CODE_SIGN_IDENTITY! 291 | 292 | # Verify that $CODE_SIGN_IDENTITY is set 293 | if [ -z "${CODE_SIGN_IDENTITY}" ] ; then 294 | echo "CODE_SIGN_IDENTITY needs to be set for framework code-signing" 295 | exit 0 296 | fi 297 | 298 | if [ -z "${CODE_SIGN_ENTITLEMENTS}" ] ; then 299 | echo "CODE_SIGN_ENTITLEMENTS needs to be set for framework code-signing!" 300 | 301 | if [ "${CONFIGURATION}" = "Release" ] ; then 302 | exit 1 303 | else 304 | # Code-signing is optional for non-release builds. 305 | exit 0 306 | fi 307 | fi 308 | 309 | ITEMS="" 310 | 311 | FRAMEWORKS_DIR="${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}" 312 | echo "$FRAMEWORKS_DIR" 313 | if [ -d "$FRAMEWORKS_DIR" ] ; then 314 | FRAMEWORKS=$(find "${FRAMEWORKS_DIR}" -depth -type d -name "*.framework" -or -name "*.dylib" -or -name "*.bundle" | sed -e "s/\(.*framework\)/\1\/Versions\/A\//") 315 | RESULT=$? 316 | if [[ $RESULT != 0 ]] ; then 317 | exit 1 318 | fi 319 | 320 | ITEMS="${FRAMEWORKS}" 321 | fi 322 | 323 | LOGINITEMS_DIR="${TARGET_BUILD_DIR}/${CONTENTS_FOLDER_PATH}/Library/LoginItems/" 324 | if [ -d "$LOGINITEMS_DIR" ] ; then 325 | LOGINITEMS=$(find "${LOGINITEMS_DIR}" -depth -type d -name "*.app") 326 | RESULT=$? 327 | if [[ $RESULT != 0 ]] ; then 328 | exit 1 329 | fi 330 | 331 | ITEMS="${ITEMS}"$'\n'"${LOGINITEMS}" 332 | fi 333 | 334 | # Prefer the expanded name, if available. 335 | CODE_SIGN_IDENTITY_FOR_ITEMS="${EXPANDED_CODE_SIGN_IDENTITY_NAME}" 336 | if [ "${CODE_SIGN_IDENTITY_FOR_ITEMS}" = "" ] ; then 337 | # Fall back to old behavior. 338 | CODE_SIGN_IDENTITY_FOR_ITEMS="${CODE_SIGN_IDENTITY}" 339 | fi 340 | 341 | echo "Identity:" 342 | echo "${CODE_SIGN_IDENTITY_FOR_ITEMS}" 343 | 344 | echo "Entitlements:" 345 | echo "${CODE_SIGN_ENTITLEMENTS}" 346 | 347 | echo "Found:" 348 | echo "${ITEMS}" 349 | 350 | # Change the Internal Field Separator (IFS) so that spaces in paths will not cause problems below. 351 | SAVED_IFS=$IFS 352 | IFS=$(echo -en "\n\b") 353 | 354 | # Loop through all items. 355 | for ITEM in $ITEMS; 356 | do 357 | echo "Signing '${ITEM}'" 358 | codesign --force --verbose --sign "${CODE_SIGN_IDENTITY_FOR_ITEMS}" --entitlements "${CODE_SIGN_ENTITLEMENTS}" "${ITEM}" 359 | RESULT=$? 360 | if [[ $RESULT != 0 ]] ; then 361 | echo "Failed to sign '${ITEM}'." 362 | IFS=$SAVED_IFS 363 | exit 1 364 | fi 365 | done 366 | 367 | # Restore $IFS. 368 | IFS=$SAVED_IFS 369 | 370 | 371 | BB4B014C10F69532006C3DED 372 | 373 | children 374 | 375 | 2865DAEF86B1907A704CA70B 376 | FECB24CC26FE943EF8E1DDF5 377 | 378 | isa 379 | PBXGroup 380 | name 381 | addons 382 | sourceTree 383 | <group> 384 | 385 | E4328143138ABC890047C5CB 386 | 387 | isa 388 | PBXFileReference 389 | lastKnownFileType 390 | wrapper.pb-project 391 | name 392 | openFrameworksLib.xcodeproj 393 | path 394 | ../../../libs/openFrameworksCompiled/project/osx/openFrameworksLib.xcodeproj 395 | sourceTree 396 | SOURCE_ROOT 397 | 398 | E4328144138ABC890047C5CB 399 | 400 | children 401 | 402 | E4328148138ABC890047C5CB 403 | 404 | isa 405 | PBXGroup 406 | name 407 | Products 408 | sourceTree 409 | <group> 410 | 411 | E4328147138ABC890047C5CB 412 | 413 | containerPortal 414 | E4328143138ABC890047C5CB 415 | isa 416 | PBXContainerItemProxy 417 | proxyType 418 | 2 419 | remoteGlobalIDString 420 | E4B27C1510CBEB8E00536013 421 | remoteInfo 422 | openFrameworks 423 | 424 | E4328148138ABC890047C5CB 425 | 426 | fileType 427 | archive.ar 428 | isa 429 | PBXReferenceProxy 430 | path 431 | openFrameworksDebug.a 432 | remoteRef 433 | E4328147138ABC890047C5CB 434 | sourceTree 435 | BUILT_PRODUCTS_DIR 436 | 437 | E4328149138ABC9F0047C5CB 438 | 439 | fileRef 440 | E4328148138ABC890047C5CB 441 | isa 442 | PBXBuildFile 443 | 444 | E4B69B4A0A3A1720003C02F2 445 | 446 | children 447 | 448 | E4B6FCAD0C3E899E008CF71C 449 | E4EB6923138AFD0F00A09F29 450 | E4B69E1C0A3A1BDC003C02F2 451 | E4EEC9E9138DF44700A80321 452 | BB4B014C10F69532006C3DED 453 | 6948EE371B920CB800B5AC1A 454 | E4B69B5B0A3A1756003C02F2 455 | 456 | isa 457 | PBXGroup 458 | sourceTree 459 | <group> 460 | 461 | E4B69B4C0A3A1720003C02F2 462 | 463 | attributes 464 | 465 | LastUpgradeCheck 466 | 0600 467 | 468 | buildConfigurationList 469 | E4B69B4D0A3A1720003C02F2 470 | compatibilityVersion 471 | Xcode 3.2 472 | developmentRegion 473 | English 474 | hasScannedForEncodings 475 | 0 476 | isa 477 | PBXProject 478 | knownRegions 479 | 480 | English 481 | Japanese 482 | French 483 | German 484 | 485 | mainGroup 486 | E4B69B4A0A3A1720003C02F2 487 | productRefGroup 488 | E4B69B4A0A3A1720003C02F2 489 | projectDirPath 490 | 491 | projectReferences 492 | 493 | 494 | ProductGroup 495 | E4328144138ABC890047C5CB 496 | ProjectRef 497 | E4328143138ABC890047C5CB 498 | 499 | 500 | projectRoot 501 | 502 | targets 503 | 504 | E4B69B5A0A3A1756003C02F2 505 | 506 | 507 | E4B69B4D0A3A1720003C02F2 508 | 509 | buildConfigurations 510 | 511 | E4B69B4E0A3A1720003C02F2 512 | E4B69B4F0A3A1720003C02F2 513 | 514 | defaultConfigurationIsVisible 515 | 0 516 | defaultConfigurationName 517 | Release 518 | isa 519 | XCConfigurationList 520 | 521 | E4B69B4E0A3A1720003C02F2 522 | 523 | baseConfigurationReference 524 | E4EB6923138AFD0F00A09F29 525 | buildSettings 526 | 527 | HEADER_SEARCH_PATHS 528 | 529 | $(OF_CORE_HEADERS) 530 | src 531 | ../../../addons/ofxJSON/libs 532 | ../../../addons/ofxJSON/libs/jsoncpp 533 | ../../../addons/ofxJSON/libs/jsoncpp/include 534 | ../../../addons/ofxJSON/libs/jsoncpp/include/json 535 | ../../../addons/ofxJSON/libs/jsoncpp/src 536 | ../../../addons/ofxJSON/src 537 | ../../../addons/ofxJsonSettings/src 538 | 539 | CONFIGURATION_BUILD_DIR 540 | $(SRCROOT)/bin/ 541 | COPY_PHASE_STRIP 542 | NO 543 | DEAD_CODE_STRIPPING 544 | YES 545 | GCC_AUTO_VECTORIZATION 546 | YES 547 | GCC_ENABLE_SSE3_EXTENSIONS 548 | YES 549 | GCC_ENABLE_SUPPLEMENTAL_SSE3_INSTRUCTIONS 550 | YES 551 | GCC_INLINES_ARE_PRIVATE_EXTERN 552 | NO 553 | GCC_OPTIMIZATION_LEVEL 554 | 0 555 | GCC_SYMBOLS_PRIVATE_EXTERN 556 | NO 557 | GCC_WARN_ABOUT_DEPRECATED_FUNCTIONS 558 | YES 559 | GCC_WARN_ABOUT_INVALID_OFFSETOF_MACRO 560 | NO 561 | GCC_WARN_ALLOW_INCOMPLETE_PROTOCOL 562 | NO 563 | GCC_WARN_UNINITIALIZED_AUTOS 564 | NO 565 | GCC_WARN_UNUSED_VALUE 566 | NO 567 | GCC_WARN_UNUSED_VARIABLE 568 | NO 569 | MACOSX_DEPLOYMENT_TARGET 570 | 10.8 571 | ONLY_ACTIVE_ARCH 572 | YES 573 | OTHER_CPLUSPLUSFLAGS 574 | 575 | -D__MACOSX_CORE__ 576 | -mtune=native 577 | 578 | SDKROOT 579 | macosx 580 | 581 | isa 582 | XCBuildConfiguration 583 | name 584 | Debug 585 | 586 | E4B69B4F0A3A1720003C02F2 587 | 588 | baseConfigurationReference 589 | E4EB6923138AFD0F00A09F29 590 | buildSettings 591 | 592 | HEADER_SEARCH_PATHS 593 | 594 | $(OF_CORE_HEADERS) 595 | src 596 | ../../../addons/ofxJSON/libs 597 | ../../../addons/ofxJSON/libs/jsoncpp 598 | ../../../addons/ofxJSON/libs/jsoncpp/include 599 | ../../../addons/ofxJSON/libs/jsoncpp/include/json 600 | ../../../addons/ofxJSON/libs/jsoncpp/src 601 | ../../../addons/ofxJSON/src 602 | ../../../addons/ofxJsonSettings/src 603 | 604 | CONFIGURATION_BUILD_DIR 605 | $(SRCROOT)/bin/ 606 | COPY_PHASE_STRIP 607 | YES 608 | DEAD_CODE_STRIPPING 609 | YES 610 | GCC_AUTO_VECTORIZATION 611 | YES 612 | GCC_ENABLE_SSE3_EXTENSIONS 613 | YES 614 | GCC_ENABLE_SUPPLEMENTAL_SSE3_INSTRUCTIONS 615 | YES 616 | GCC_INLINES_ARE_PRIVATE_EXTERN 617 | NO 618 | GCC_OPTIMIZATION_LEVEL 619 | 3 620 | GCC_SYMBOLS_PRIVATE_EXTERN 621 | NO 622 | GCC_UNROLL_LOOPS 623 | YES 624 | GCC_WARN_ABOUT_DEPRECATED_FUNCTIONS 625 | YES 626 | GCC_WARN_ABOUT_INVALID_OFFSETOF_MACRO 627 | NO 628 | GCC_WARN_ALLOW_INCOMPLETE_PROTOCOL 629 | NO 630 | GCC_WARN_UNINITIALIZED_AUTOS 631 | NO 632 | GCC_WARN_UNUSED_VALUE 633 | NO 634 | GCC_WARN_UNUSED_VARIABLE 635 | NO 636 | MACOSX_DEPLOYMENT_TARGET 637 | 10.8 638 | OTHER_CPLUSPLUSFLAGS 639 | 640 | -D__MACOSX_CORE__ 641 | -mtune=native 642 | 643 | SDKROOT 644 | macosx 645 | 646 | isa 647 | XCBuildConfiguration 648 | name 649 | Release 650 | 651 | E4B69B580A3A1756003C02F2 652 | 653 | buildActionMask 654 | 2147483647 655 | files 656 | 657 | E4B69E200A3A1BDC003C02F2 658 | E4B69E210A3A1BDC003C02F2 659 | EA1838CCB5F7BA2A48AEF0CF 660 | FB84AAF8D1B7A95266DB5C09 661 | 045CDF359630386A720A2524 662 | 663 | isa 664 | PBXSourcesBuildPhase 665 | runOnlyForDeploymentPostprocessing 666 | 0 667 | 668 | E4B69B590A3A1756003C02F2 669 | 670 | buildActionMask 671 | 2147483647 672 | files 673 | 674 | E4328149138ABC9F0047C5CB 675 | 676 | isa 677 | PBXFrameworksBuildPhase 678 | runOnlyForDeploymentPostprocessing 679 | 0 680 | 681 | E4B69B5A0A3A1756003C02F2 682 | 683 | buildConfigurationList 684 | E4B69B5F0A3A1757003C02F2 685 | buildPhases 686 | 687 | E4B69B580A3A1756003C02F2 688 | E4B69B590A3A1756003C02F2 689 | E4B6FFFD0C3F9AB9008CF71C 690 | E4C2427710CC5ABF004149E2 691 | 8466F1851C04CA0E00918B1C 692 | 693 | buildRules 694 | 695 | dependencies 696 | 697 | E4EEB9AC138B136A00A80321 698 | 699 | isa 700 | PBXNativeTarget 701 | name 702 | example 703 | productName 704 | myOFApp 705 | productReference 706 | E4B69B5B0A3A1756003C02F2 707 | productType 708 | com.apple.product-type.application 709 | 710 | E4B69B5B0A3A1756003C02F2 711 | 712 | explicitFileType 713 | wrapper.application 714 | includeInIndex 715 | 0 716 | isa 717 | PBXFileReference 718 | path 719 | exampleDebug.app 720 | sourceTree 721 | BUILT_PRODUCTS_DIR 722 | 723 | E4B69B5F0A3A1757003C02F2 724 | 725 | buildConfigurations 726 | 727 | E4B69B600A3A1757003C02F2 728 | E4B69B610A3A1757003C02F2 729 | 730 | defaultConfigurationIsVisible 731 | 0 732 | defaultConfigurationName 733 | Release 734 | isa 735 | XCConfigurationList 736 | 737 | E4B69B600A3A1757003C02F2 738 | 739 | baseConfigurationReference 740 | E4EB6923138AFD0F00A09F29 741 | buildSettings 742 | 743 | HEADER_SEARCH_PATHS 744 | 745 | $(OF_CORE_HEADERS) 746 | src 747 | ../../../addons/ofxJSON/libs 748 | ../../../addons/ofxJSON/libs/jsoncpp 749 | ../../../addons/ofxJSON/libs/jsoncpp/include 750 | ../../../addons/ofxJSON/libs/jsoncpp/include/json 751 | ../../../addons/ofxJSON/libs/jsoncpp/src 752 | ../../../addons/ofxJSON/src 753 | ../../../addons/ofxJsonSettings/src 754 | 755 | COMBINE_HIDPI_IMAGES 756 | YES 757 | COPY_PHASE_STRIP 758 | NO 759 | FRAMEWORK_SEARCH_PATHS 760 | 761 | $(inherited) 762 | $(FRAMEWORK_SEARCH_PATHS_QUOTED_FOR_TARGET_1) 763 | 764 | FRAMEWORK_SEARCH_PATHS_QUOTED_FOR_TARGET_1 765 | "$(SRCROOT)/../../../libs/glut/lib/osx" 766 | GCC_DYNAMIC_NO_PIC 767 | NO 768 | GCC_GENERATE_DEBUGGING_SYMBOLS 769 | YES 770 | GCC_MODEL_TUNING 771 | NONE 772 | ICON 773 | $(ICON_NAME_DEBUG) 774 | ICON_FILE 775 | $(ICON_FILE_PATH)$(ICON) 776 | INFOPLIST_FILE 777 | openFrameworks-Info.plist 778 | INSTALL_PATH 779 | /Applications 780 | LIBRARY_SEARCH_PATHS 781 | $(inherited) 782 | PRODUCT_NAME 783 | $(TARGET_NAME)Debug 784 | WRAPPER_EXTENSION 785 | app 786 | 787 | isa 788 | XCBuildConfiguration 789 | name 790 | Debug 791 | 792 | E4B69B610A3A1757003C02F2 793 | 794 | baseConfigurationReference 795 | E4EB6923138AFD0F00A09F29 796 | buildSettings 797 | 798 | HEADER_SEARCH_PATHS 799 | 800 | $(OF_CORE_HEADERS) 801 | src 802 | ../../../addons/ofxJSON/libs 803 | ../../../addons/ofxJSON/libs/jsoncpp 804 | ../../../addons/ofxJSON/libs/jsoncpp/include 805 | ../../../addons/ofxJSON/libs/jsoncpp/include/json 806 | ../../../addons/ofxJSON/libs/jsoncpp/src 807 | ../../../addons/ofxJSON/src 808 | ../../../addons/ofxJsonSettings/src 809 | 810 | COMBINE_HIDPI_IMAGES 811 | YES 812 | COPY_PHASE_STRIP 813 | YES 814 | FRAMEWORK_SEARCH_PATHS 815 | 816 | $(inherited) 817 | $(FRAMEWORK_SEARCH_PATHS_QUOTED_FOR_TARGET_1) 818 | 819 | FRAMEWORK_SEARCH_PATHS_QUOTED_FOR_TARGET_1 820 | "$(SRCROOT)/../../../libs/glut/lib/osx" 821 | GCC_GENERATE_DEBUGGING_SYMBOLS 822 | YES 823 | GCC_MODEL_TUNING 824 | NONE 825 | ICON 826 | $(ICON_NAME_RELEASE) 827 | ICON_FILE 828 | $(ICON_FILE_PATH)$(ICON) 829 | INFOPLIST_FILE 830 | openFrameworks-Info.plist 831 | INSTALL_PATH 832 | /Applications 833 | LIBRARY_SEARCH_PATHS 834 | $(inherited) 835 | PRODUCT_NAME 836 | $(TARGET_NAME) 837 | WRAPPER_EXTENSION 838 | app 839 | baseConfigurationReference 840 | E4EB6923138AFD0F00A09F29 841 | 842 | isa 843 | XCBuildConfiguration 844 | name 845 | Release 846 | 847 | E4B69E1C0A3A1BDC003C02F2 848 | 849 | children 850 | 851 | E4B69E1D0A3A1BDC003C02F2 852 | E4B69E1E0A3A1BDC003C02F2 853 | E4B69E1F0A3A1BDC003C02F2 854 | 855 | isa 856 | PBXGroup 857 | path 858 | src 859 | sourceTree 860 | SOURCE_ROOT 861 | 862 | E4B69E1D0A3A1BDC003C02F2 863 | 864 | fileEncoding 865 | 30 866 | isa 867 | PBXFileReference 868 | lastKnownFileType 869 | sourcecode.cpp.cpp 870 | name 871 | main.cpp 872 | path 873 | src/main.cpp 874 | sourceTree 875 | SOURCE_ROOT 876 | 877 | E4B69E1E0A3A1BDC003C02F2 878 | 879 | explicitFileType 880 | sourcecode.cpp.cpp 881 | fileEncoding 882 | 30 883 | isa 884 | PBXFileReference 885 | name 886 | ofApp.cpp 887 | path 888 | src/ofApp.cpp 889 | sourceTree 890 | SOURCE_ROOT 891 | 892 | E4B69E1F0A3A1BDC003C02F2 893 | 894 | fileEncoding 895 | 30 896 | isa 897 | PBXFileReference 898 | lastKnownFileType 899 | sourcecode.c.h 900 | name 901 | ofApp.h 902 | path 903 | src/ofApp.h 904 | sourceTree 905 | SOURCE_ROOT 906 | 907 | E4B69E200A3A1BDC003C02F2 908 | 909 | fileRef 910 | E4B69E1D0A3A1BDC003C02F2 911 | isa 912 | PBXBuildFile 913 | 914 | E4B69E210A3A1BDC003C02F2 915 | 916 | fileRef 917 | E4B69E1E0A3A1BDC003C02F2 918 | isa 919 | PBXBuildFile 920 | 921 | E4B6FCAD0C3E899E008CF71C 922 | 923 | fileEncoding 924 | 30 925 | isa 926 | PBXFileReference 927 | lastKnownFileType 928 | text.plist.xml 929 | path 930 | openFrameworks-Info.plist 931 | sourceTree 932 | <group> 933 | 934 | E4B6FFFD0C3F9AB9008CF71C 935 | 936 | buildActionMask 937 | 2147483647 938 | files 939 | 940 | inputPaths 941 | 942 | isa 943 | PBXShellScriptBuildPhase 944 | outputPaths 945 | 946 | runOnlyForDeploymentPostprocessing 947 | 0 948 | shellPath 949 | /bin/sh 950 | shellScript 951 | mkdir -p "$TARGET_BUILD_DIR/$PRODUCT_NAME.app/Contents/Resources/" 952 | # Copy default icon file into App/Resources 953 | rsync -aved "$ICON_FILE" "$TARGET_BUILD_DIR/$PRODUCT_NAME.app/Contents/Resources/" 954 | # Copy bin/data into App/Resources 955 | rsync -avz --exclude='.DS_Store' "${SRCROOT}/bin/data/" "${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/data/" 956 | # Copy libfmod and change install directory for fmod to run 957 | rsync -aved ../../../libs/fmodex/lib/osx/libfmodex.dylib "$TARGET_BUILD_DIR/$PRODUCT_NAME.app/Contents/Frameworks/"; 958 | install_name_tool -change @executable_path/libfmodex.dylib @executable_path/../Frameworks/libfmodex.dylib "$TARGET_BUILD_DIR/$PRODUCT_NAME.app/Contents/MacOS/$PRODUCT_NAME"; 959 | # Copy GLUT framework (must remove for AppStore submissions) 960 | rsync -aved ../../../libs/glut/lib/osx/GLUT.framework "$TARGET_BUILD_DIR/$PRODUCT_NAME.app/Contents/Frameworks/" 961 | 962 | 963 | E4C2427710CC5ABF004149E2 964 | 965 | buildActionMask 966 | 2147483647 967 | dstPath 968 | 969 | dstSubfolderSpec 970 | 10 971 | files 972 | 973 | isa 974 | PBXCopyFilesBuildPhase 975 | runOnlyForDeploymentPostprocessing 976 | 0 977 | 978 | E4EB691F138AFCF100A09F29 979 | 980 | fileEncoding 981 | 4 982 | isa 983 | PBXFileReference 984 | lastKnownFileType 985 | text.xcconfig 986 | name 987 | CoreOF.xcconfig 988 | path 989 | ../../../libs/openFrameworksCompiled/project/osx/CoreOF.xcconfig 990 | sourceTree 991 | SOURCE_ROOT 992 | 993 | E4EB6923138AFD0F00A09F29 994 | 995 | fileEncoding 996 | 4 997 | isa 998 | PBXFileReference 999 | lastKnownFileType 1000 | text.xcconfig 1001 | path 1002 | Project.xcconfig 1003 | sourceTree 1004 | <group> 1005 | 1006 | E4EEB9AB138B136A00A80321 1007 | 1008 | containerPortal 1009 | E4328143138ABC890047C5CB 1010 | isa 1011 | PBXContainerItemProxy 1012 | proxyType 1013 | 1 1014 | remoteGlobalIDString 1015 | E4B27C1410CBEB8E00536013 1016 | remoteInfo 1017 | openFrameworks 1018 | 1019 | E4EEB9AC138B136A00A80321 1020 | 1021 | isa 1022 | PBXTargetDependency 1023 | name 1024 | openFrameworks 1025 | targetProxy 1026 | E4EEB9AB138B136A00A80321 1027 | 1028 | E4EEC9E9138DF44700A80321 1029 | 1030 | children 1031 | 1032 | E4EB691F138AFCF100A09F29 1033 | E4328143138ABC890047C5CB 1034 | 1035 | isa 1036 | PBXGroup 1037 | name 1038 | openFrameworks 1039 | sourceTree 1040 | <group> 1041 | 1042 | 1043 | rootObject 1044 | E4B69B4C0A3A1720003C02F2 1045 | 1046 | 1047 | --------------------------------------------------------------------------------