Last active
March 10, 2020 07:16
-
-
Save nariakiiwatani/ac5ea80f979fe889040e43cdfb3cecae to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#pragma once | |
#include "ofxWatchFile.h" | |
#include "ofxJsonUtils.h" | |
#define KVCS1(name) kv(name) | |
#define KVCS2(name, ...) KVCS1(name), KVCS1(__VA_ARGS__) | |
#define KVCS3(name, ...) KVCS1(name), KVCS2(__VA_ARGS__) | |
#define KVCS4(name, ...) KVCS1(name), KVCS3(__VA_ARGS__) | |
#define KVCS5(name, ...) KVCS1(name), KVCS4(__VA_ARGS__) | |
#define KVCS6(name, ...) KVCS1(name), KVCS5(__VA_ARGS__) | |
#define KVCS7(name, ...) KVCS1(name), KVCS6(__VA_ARGS__) | |
#define KVCS8(name, ...) KVCS1(name), KVCS7(__VA_ARGS__) | |
#define KVCS9(name, ...) KVCS1(name), KVCS8(__VA_ARGS__) | |
#define GET_MACRO(_1,_2,_3,_4,_5,_6,_7,_8,_9,NAME,...) NAME | |
#define KV_COMMA_SEPARATION(...) GET_MACRO(__VA_ARGS__, KVCS9, KVCS8, KVCS7, KVCS6, KVCS5, KVCS4, KVCS3, KVCS2, KVCS1)(__VA_ARGS__) | |
#define JSON_FUNCS(...) \ | |
void loadJson(const ofJson &json) {ofxJsonUtils::load(json, KV_COMMA_SEPARATION(__VA_ARGS__));}\ | |
ofJson toJson() const { return ofxJsonUtils::create(KV_COMMA_SEPARATION(__VA_ARGS__));} | |
namespace ofx { namespace JsonUtils { | |
static inline const ofJson &convert(const ofJson &json) { | |
return json; | |
} | |
static const inline void parse(const ofJson &src, ofJson &dst) { | |
dst = src; | |
} | |
}} | |
template<typename ConvertType, bool NDJson=false> | |
class AutoJson_ : public ConvertType | |
{ | |
public: | |
using Type = ConvertType; | |
using Json = typename std::conditional<NDJson, std::vector<ofJson>, ofJson>::type; | |
AutoJson_() { | |
watcher_.addListener(this, &AutoJson_::reload); | |
} | |
bool load(const std::string &filepath, std::vector<std::string> hierarchy={}) { | |
hierarchy_ = hierarchy; | |
filepath_ = filepath; | |
return watcher_.setTargetPath(filepath); | |
} | |
void setTargetPath(const std::string &filepath) { | |
filepath_ = filepath; | |
watcher_.setTargetPath(filepath, false); | |
} | |
void setWillSaveListener(std::function<void(const Type&, Json&)> callback) { | |
save_callback_ = callback; | |
} | |
void setDidLoadListener(std::function<void(Type&, const Json&)> callback) { | |
loaded_callback_ = callback; | |
} | |
bool reload() { | |
return watcher_.load(); | |
} | |
bool overwrite(int indent=-1) const { | |
return writeToFile(filepath_, indent); | |
} | |
bool writeToFile(const std::string &filepath, int indent=-1) const { | |
if(filepath == "") { | |
return false; | |
} | |
Json json = loadFunc(filepath); | |
Json local = ofxJsonUtils::convert(*(Type*)this); | |
if(save_callback_) { | |
save_callback_(*this, local); | |
} | |
hierarchySet(local, json); | |
return saveFunc(filepath, json, true, indent); | |
} | |
void loadJson(const ofJson &json) { | |
ofxJsonUtils::parse(json, *(Type*)this); | |
} | |
ofJson toJson() const { | |
return ofxJsonUtils::convert(*(Type*)this); | |
} | |
template<typename ReturnType, typename ...ArgTypes> | |
ReturnType userFunc(ArgTypes...); | |
private: | |
void reload(ofFile &file) { | |
Json json = loadFunc(file.path()); | |
json = hierarchyGet(json); | |
ofxJsonUtils::parse(json, *this); | |
if(loaded_callback_) { | |
loaded_callback_(*this, json); | |
} | |
} | |
ofxWatchFile watcher_; | |
std::string filepath_=""; | |
std::vector<std::string> hierarchy_={}; | |
std::function<void(const Type&, Json&)> save_callback_ = nullptr; | |
std::function<void(Type&, const Json&)> loaded_callback_ = nullptr; | |
template<typename T = Json> | |
auto loadFunc(const std::string &filepath) const | |
-> typename std::enable_if<NDJson, T>::type { | |
return ofxJsonUtils::loadNDJsonFromFile(filepath); | |
} | |
template<typename T = Json> | |
auto loadFunc(const std::string &filepath) const | |
-> typename std::enable_if<!NDJson, T>::type { | |
return ofxJsonUtils::loadFromFile(filepath); | |
} | |
template<typename T = bool> | |
auto saveFunc(const std::string &filepath, const Json &json, bool isInDataDir = true, int indent = -1) const | |
-> typename std::enable_if<NDJson, T>::type { | |
return ofxJsonUtils::writeToNDJsonFile(filepath, json, isInDataDir, -1); | |
} | |
template<typename T = bool> | |
auto saveFunc(const std::string &filepath, const Json &json, bool isInDataDir = true, int indent = -1) const | |
-> typename std::enable_if<!NDJson, T>::type { | |
return ofxJsonUtils::writeToFile(filepath, json, isInDataDir, indent); | |
} | |
std::vector<ofJson> hierarchyGet(const std::vector<ofJson> &json) const { | |
auto ret = json; | |
for(auto &j : ret) { | |
for(auto &h : hierarchy_) { | |
j = j[h]; | |
} | |
} | |
return ret; | |
} | |
ofJson hierarchyGet(const ofJson &json) const { | |
auto ret = json; | |
for(auto &h : hierarchy_) { | |
ret = ret[h]; | |
} | |
return ret; | |
} | |
void hierarchySet(const std::vector<ofJson> &json, std::vector<ofJson> &root) const { | |
root.resize(json.size()); | |
for(int i = 0, num = json.size(); i < num; ++i) { | |
auto *dst = &root[i]; | |
for(auto &h : hierarchy_) { | |
dst = &(*dst)[h]; | |
} | |
*dst = json[i]; | |
} | |
} | |
void hierarchySet(const ofJson &json, ofJson &root) const { | |
auto *dst = &root; | |
for(auto &h : hierarchy_) { | |
dst = &(*dst)[h]; | |
} | |
*dst = json; | |
} | |
}; | |
using AutoJson = AutoJson_<ofJson>; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#pragma once | |
#include "imgui.h" | |
namespace AutoJsonUtils_ImGui { | |
namespace IO { | |
template<typename Json> | |
bool Save(Json &json, const std::string &default_filename="", int indent=4) { | |
bool success = false; | |
bool tried = false; | |
if(ImGui::Button("Save")) { | |
tried = true; | |
success = json.overwrite(indent); | |
} | |
ImGui::SameLine(); | |
if(ImGui::Button("Save As") || (tried && !success)) { | |
auto result = ofSystemSaveDialog(default_filename, "Save As..."); | |
if(result.bSuccess) { | |
if(json.writeToFile(result.getPath(), indent)) { | |
json.setTargetPath(result.getPath()); | |
success = true; | |
} | |
} | |
} | |
return success; | |
} | |
template<typename Json> | |
bool Load(Json &json) { | |
bool success = false; | |
bool tried = false; | |
if(ImGui::Button("Reload")) { | |
tried = true; | |
success = json.reload(); | |
} | |
ImGui::SameLine(); | |
if(ImGui::Button("Load From") || (tried && !success)) { | |
auto result = ofSystemLoadDialog("Load From..."); | |
if(result.bSuccess) { | |
if(json.load(result.getPath())) { | |
json.setTargetPath(result.getPath()); | |
success = true; | |
} | |
} | |
} | |
return success; | |
} | |
template<typename Json> | |
void SaveLoad(Json &json, bool &saved, bool &loaded, const std::string &default_filename="", int indent=4) { | |
saved = Save(json, default_filename, indent); | |
ImGui::SameLine(); | |
loaded = Load(json); | |
} | |
template<typename Json> | |
void SaveLoad(Json &json, const std::string &default_filename="", int indent=4) { | |
Save(json, default_filename, indent); | |
ImGui::SameLine(); | |
Load(json); | |
} | |
}} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
moved to https://github.com/nariakiiwatani/ofxJsonUtilsUtils