229 lines
6.1 KiB
C++
229 lines
6.1 KiB
C++
#ifndef PROPERTY_H
|
|
#define PROPERTY_H
|
|
|
|
#include <vector>
|
|
#include <iostream>
|
|
#include <glm/ext.hpp>
|
|
|
|
// PROPERTIES MACROS (used by Serializable class)
|
|
|
|
#define PROPERTY(type, var)\
|
|
Property<type> var##Property;\
|
|
type &var = var##Property.getValueRef();\
|
|
|
|
#define INT(var) PROPERTY(int, var)
|
|
#define UINT(var) PROPERTY(unsigned int, var)
|
|
#define LONG(var) PROPERTY(long, var)
|
|
#define SHORT(var) PROPERTY(short, var)
|
|
#define BYTE(var) PROPERTY(char, var)
|
|
#define DOUBLE(var) PROPERTY(double, var)
|
|
#define FLOAT(var) PROPERTY(float, var)
|
|
#define BOOL(var) PROPERTY(bool, var)
|
|
#define VEC2(var) PROPERTY(glm::vec2, var)
|
|
#define VEC3(var) PROPERTY(glm::vec3, var)
|
|
#define MAT4(var) PROPERTY(glm::mat4, var)
|
|
#define STRING(var) PROPERTY(std::string, var)
|
|
|
|
// the provided type must be a class inheriting Serializable
|
|
#define REFERENCE(type, var)\
|
|
Property<Serializable*> var##Property;\
|
|
type*& var = (type*&)(var##Property.getValueRef());\
|
|
|
|
#define VECTOR_PROPERTY(type, var)\
|
|
ArrayProperty<type> var##Property;\
|
|
std::vector<type> &var = var##Property.getValueRef();\
|
|
|
|
|
|
#define VECTOR_INT(var) VECTOR_PROPERTY(int, var)
|
|
#define VECTOR_UINT(var) VECTOR_PROPERTY(unsigned int, var)
|
|
#define VECTOR_FLOAT(var) VECTOR_PROPERTY(float, var)
|
|
#define VECTOR_BOOL(var) VECTOR_PROPERTY(bool, var)
|
|
#define VECTOR_SHORT(var) VECTOR_PROPERTY(short, var)
|
|
#define VECTOR_BYTE(var) VECTOR_PROPERTY(char, var)
|
|
#define VECTOR_LONG(var) VECTOR_PROPERTY(long, var)
|
|
#define VECTOR_DOUBLE(var) VECTOR_PROPERTY(double, var)
|
|
#define VECTOR_VEC2(var) VECTOR_PROPERTY(glm::vec2, var)
|
|
#define VECTOR_VEC3(var) VECTOR_PROPERTY(glm::vec3, var)
|
|
#define VECTOR_MAT4(var) VECTOR_PROPERTY(glm::mat4, var)
|
|
#define VECTOR_STRING(var) VECTOR_PROPERTY(std::string, var)
|
|
#define VECTOR_REFERENCE(type, var) VECTOR_PROPERTY(type*, var)
|
|
|
|
#define CAST(var) (AbstractProperty*)&var##Property
|
|
|
|
// FORWARD DECLARATIONS AND TYPES
|
|
|
|
class AbstractProperty;
|
|
class Serializable;
|
|
|
|
typedef std::vector<AbstractProperty*> PropertySet;
|
|
|
|
// PROPERTY INTERFACE
|
|
|
|
class AbstractProperty
|
|
{
|
|
public:
|
|
enum PropertyType
|
|
{
|
|
UNDEFINED,
|
|
|
|
INTEGER,
|
|
SHORT,
|
|
LONG,
|
|
BYTE,
|
|
UNSIGNED_INTEGER,
|
|
FLOAT,
|
|
DOUBLE,
|
|
BOOLEAN,
|
|
VEC2,
|
|
VEC3,
|
|
MAT4,
|
|
STRING,
|
|
REFERENCE,
|
|
ARRAY, // this is a bit special, an array must also have one of the other types
|
|
|
|
// keep last
|
|
NB_PROPERTY_TYPES
|
|
};
|
|
|
|
virtual ~AbstractProperty() {}
|
|
|
|
virtual std::ostream& saveBinary(std::ostream& os) = 0;
|
|
virtual std::ostream& saveAscii(std::ostream& os) = 0;
|
|
|
|
virtual std::istream& loadBinary(std::istream& is) = 0;
|
|
virtual std::istream& loadAscii(std::istream& is) = 0;
|
|
|
|
virtual PropertyType getPropertyType() = 0;
|
|
|
|
friend PropertySet& operator << (PropertySet &properties, AbstractProperty& p)
|
|
{ properties.push_back(&p); return properties; }
|
|
};
|
|
|
|
// GENERIC PROPERTY
|
|
|
|
template <typename T>
|
|
class Property : public AbstractProperty
|
|
{
|
|
T value;
|
|
public:
|
|
Property(T val) : value(val) {}
|
|
Property() {}
|
|
~Property() {}
|
|
|
|
std::ostream& saveBinary(std::ostream& os);
|
|
std::ostream& saveAscii(std::ostream& os);
|
|
|
|
std::istream& loadBinary(std::istream& is);
|
|
std::istream& loadAscii(std::istream& is);
|
|
|
|
PropertyType getPropertyType() { return getStaticPropertyType(); }
|
|
static PropertyType getStaticPropertyType();
|
|
|
|
T &getValueRef() { return value; }
|
|
};
|
|
|
|
/**
|
|
* Reference properties are implemented through partial specialization of Property,
|
|
* it can compile with any pointer,
|
|
* but will only work will pointers to a class that inherits Serializable
|
|
*/
|
|
template <typename T>
|
|
class Property<T*> : public AbstractProperty
|
|
{
|
|
T* value;
|
|
public:
|
|
Property(T* val) : value(val) {}
|
|
Property() {}
|
|
~Property() {}
|
|
|
|
// will not be used, serialization of references is entirely done by the serialization manager
|
|
std::ostream& saveBinary(std::ostream& os) { return os; }
|
|
std::ostream& saveAscii(std::ostream& os) { return os; }
|
|
std::istream& loadBinary(std::istream& is) { return is; }
|
|
std::istream& loadAscii(std::istream& is) { return is; }
|
|
|
|
PropertyType getPropertyType() { return getStaticPropertyType(); }
|
|
static PropertyType getStaticPropertyType() { return REFERENCE; }
|
|
T*& getValueRef() { return value; }
|
|
};
|
|
|
|
// GENERIC VECTOR PROPERTY
|
|
|
|
class AbstractArrayProperty : public AbstractProperty
|
|
{
|
|
public:
|
|
PropertyType getPropertyType() { return ARRAY; }
|
|
|
|
virtual PropertyType getDataType() { return UNDEFINED; }
|
|
};
|
|
|
|
template <typename T>
|
|
class ArrayProperty : public AbstractArrayProperty
|
|
{
|
|
std::vector<T> value;
|
|
public:
|
|
ArrayProperty(const std::vector<T> &val) : value(val) {}
|
|
ArrayProperty() {}
|
|
~ArrayProperty() {}
|
|
|
|
std::ostream& saveBinary(std::ostream& os)
|
|
{
|
|
Property<int> size(value.size());
|
|
size.saveBinary(os);
|
|
for(T &it : value)
|
|
Property<T>(it).saveBinary(os);
|
|
return os;
|
|
}
|
|
|
|
std::ostream& saveAscii(std::ostream& os)
|
|
{
|
|
os << "[";
|
|
int i = value.size();
|
|
for(T &it : value)
|
|
{
|
|
Property<T>(it).saveAscii(os);
|
|
if(--i) os << ", ";
|
|
}
|
|
return os << "]";
|
|
}
|
|
|
|
std::istream& loadBinary(std::istream& is)
|
|
{
|
|
Property<int> size;
|
|
size.loadBinary(is);
|
|
value.resize(size.getValueRef());
|
|
Property<T> p;
|
|
for(int i=0; i<size.getValueRef(); ++i)
|
|
{
|
|
p.loadBinary(is);
|
|
value[i] = p.getValueRef();
|
|
}
|
|
return is;
|
|
}
|
|
|
|
std::istream& loadAscii(std::istream& is)
|
|
{
|
|
value.clear();
|
|
is.ignore(1); // [
|
|
Property<T> p;
|
|
while(is.peek() != ']')
|
|
{
|
|
p.loadAscii(is);
|
|
value.push_back(p.getValueRef());
|
|
if(is.peek() == ',')
|
|
is.ignore(1); // ,
|
|
}
|
|
return is.ignore(1);
|
|
}
|
|
|
|
// array specific methods
|
|
|
|
PropertyType getDataType() { return Property<T>::getStaticPropertyType(); }
|
|
|
|
std::vector<T> &getValueRef() { return value; }
|
|
|
|
unsigned int getArraySize() { return value.size(); }
|
|
};
|
|
|
|
#endif // PROPERTY_H
|