#pragma once #include #include #include #include #include "utility.hpp" /* * Our own intermediate data solution (used for saving/loading, etc) */ class IntermediateType { public: enum Type { String, SignedInteger, UnsignedInteger, Float, Vec3, Vec2, Quat, Bool }; struct Data { std::string m_string; signed int m_integer; unsigned int m_unsignedInteger; float m_float; glm::vec3 m_vec3; glm::vec2 m_vec2; glm::quat m_quat; bool m_bool; }; IntermediateType() {} ~IntermediateType() {} IntermediateType(const IntermediateType& copy) { m_data = copy.m_data; m_type = copy.m_type; } IntermediateType(const std::string& value) { m_data.m_string = value; m_type = String; } IntermediateType(signed int value) { m_data.m_integer = value; m_type = SignedInteger; } IntermediateType(unsigned int value) { m_data.m_unsignedInteger = value; m_type = UnsignedInteger; } IntermediateType(float value) { m_data.m_float = value; m_type = Float; } IntermediateType(glm::vec3 value) { m_data.m_vec3 = value; m_type = Vec3; } IntermediateType(glm::vec2 value) { m_data.m_vec2 = value; m_type = Vec2; } IntermediateType(glm::quat value) { m_data.m_quat = value; m_type = Quat; } IntermediateType(bool value) { m_data.m_bool = value; m_type = Bool; } IntermediateType& operator=(const IntermediateType& rhs) { m_data = rhs.m_data; m_type = rhs.m_type; return *this; } operator std::string&() { return m_data.m_string; } operator signed int&() { return m_data.m_integer; } operator unsigned int&() { return m_data.m_unsignedInteger; } operator float&() { //workaround: //our json library does NOT guarantee floats will be stored as floats if(m_type == SignedInteger) { m_data.m_float = static_cast(m_data.m_integer); } else if(m_type == UnsignedInteger) { m_data.m_float = static_cast(m_data.m_unsignedInteger); } return m_data.m_float; } operator glm::vec3&() { return m_data.m_vec3; } operator glm::vec2&() { return m_data.m_vec2; } operator glm::quat&() { return m_data.m_quat; } operator bool&() { return m_data.m_bool; } Type GetType() const { return m_type; } Data GetData() const { return m_data; } private: Data m_data; Type m_type; }; class IntermediateData { public: IntermediateData() {} ~IntermediateData() {} IntermediateData(const IntermediateData& inData) { data = inData.data; } IntermediateData(nlohmann::json json) { for(auto it = json.begin(); it != json.end(); it++) { std::string key = it.key(); if(it.value().is_number_integer()) { int val = it.value(); data[key] = val; } if(it.value().is_boolean()) { bool val = it.value(); data[key] = val; } //crappy detection of vectors (since they are technically stored in strings) if(it.value().is_string()) { std::string s = it.value(); size_t n = std::count(s.begin(), s.end(), ','); switch(n) { case 1: data[key] = Utility::StringToVec2(s.c_str()); //vec2 break; case 2: data[key] = Utility::StringToVec3(s); //vec3 break; case 3: data[key] = Utility::StringToQuat(s.c_str()); //quat break; default: { if(Utility::IsFloat(s)) { data[key] = stof(s); } else { data[key] = s; //if its actually a string } } break; } } } } nlohmann::json GetJSON() { nlohmann::json tmp; for(auto itr : data) { switch(itr.second.GetType()) { case IntermediateType::String: tmp[itr.first] = itr.second.GetData().m_string; break; case IntermediateType::SignedInteger: tmp[itr.first] = itr.second.GetData().m_integer; break; case IntermediateType::UnsignedInteger: tmp[itr.first] = itr.second.GetData().m_unsignedInteger; break; case IntermediateType::Float: tmp[itr.first] = itr.second.GetData().m_float; break; case IntermediateType::Vec3: tmp[itr.first] = Utility::Vec3ToString(itr.second); break; case IntermediateType::Vec2: tmp[itr.first] = Utility::Vec2ToString(itr.second); break; case IntermediateType::Quat: tmp[itr.first] = Utility::QuatToString(itr.second); break; case IntermediateType::Bool: tmp[itr.first] = itr.second.GetData().m_bool; break; } } return tmp; } auto& operator[](const std::string& key) { return data[key]; } bool operator!=(IntermediateData& b) { return GetJSON() == b.GetJSON(); } std::map data; };