overte-HifiExperiments/libraries/entities/src/EntityItemPropertiesMacros.h
2018-01-17 18:08:05 -08:00

441 lines
20 KiB
C

//
// EntityItemPropertiesMacros.h
// libraries/entities/src
//
// Created by Brad Hefta-Gaub on 9/10/14.
// Copyright 2014 High Fidelity, Inc.
//
// Distributed under the Apache License, Version 2.0.
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
//
#ifndef hifi_EntityItemPropertiesMacros_h
#define hifi_EntityItemPropertiesMacros_h
#include <QDateTime>
#include "EntityItemID.h"
#include <RegisteredMetaTypes.h>
#define APPEND_ENTITY_PROPERTY(P,V) \
if (requestedProperties.getHasProperty(P)) { \
LevelDetails propertyLevel = packetData->startLevel(); \
successPropertyFits = packetData->appendValue(V); \
if (successPropertyFits) { \
propertyFlags |= P; \
propertiesDidntFit -= P; \
propertyCount++; \
packetData->endLevel(propertyLevel); \
} else { \
packetData->discardLevel(propertyLevel); \
appendState = OctreeElement::PARTIAL; \
} \
} else { \
propertiesDidntFit -= P; \
}
#define READ_ENTITY_PROPERTY(P,T,S) \
if (propertyFlags.getHasProperty(P)) { \
T fromBuffer; \
int bytes = OctreePacketData::unpackDataFromBytes(dataAt, fromBuffer); \
dataAt += bytes; \
bytesRead += bytes; \
if (overwriteLocalData) { \
S(fromBuffer); \
} \
somethingChanged = true; \
}
#define SKIP_ENTITY_PROPERTY(P,T) \
if (propertyFlags.getHasProperty(P)) { \
T fromBuffer; \
int bytes = OctreePacketData::unpackDataFromBytes(dataAt, fromBuffer); \
dataAt += bytes; \
bytesRead += bytes; \
}
#define DECODE_GROUP_PROPERTY_HAS_CHANGED(P,N) \
if (propertyFlags.getHasProperty(P)) { \
set##N##Changed(true); \
}
#define READ_ENTITY_PROPERTY_TO_PROPERTIES(P,T,O) \
if (propertyFlags.getHasProperty(P)) { \
T fromBuffer; \
int bytes = OctreePacketData::unpackDataFromBytes(dataAt, fromBuffer); \
dataAt += bytes; \
processedBytes += bytes; \
properties.O(fromBuffer); \
}
#define SET_ENTITY_PROPERTY_FROM_PROPERTIES(P,M) \
if (properties._##P##Changed) { \
M(properties._##P); \
somethingChanged = true; \
}
#define SET_ENTITY_GROUP_PROPERTY_FROM_PROPERTIES(G,P,p,M) \
if (properties.get##G().p##Changed()) { \
M(properties.get##G().get##P()); \
somethingChanged = true; \
}
#define SET_ENTITY_PROPERTY_FROM_PROPERTIES_GETTER(C,G,S) \
if (properties.C()) { \
S(properties.G()); \
somethingChanged = true; \
}
#define COPY_ENTITY_PROPERTY_TO_PROPERTIES(P,M) \
properties._##P = M(); \
properties._##P##Changed = false;
#define COPY_ENTITY_GROUP_PROPERTY_TO_PROPERTIES(G,P,M) \
properties.get##G().set##P(M()); \
properties.get##G().set##P##Changed(false);
#define CHECK_PROPERTY_CHANGE(P,M) \
if (_##M##Changed) { \
changedProperties += P; \
}
inline QScriptValue convertScriptValue(QScriptEngine* e, const glm::vec3& v) { return vec3toScriptValue(e, v); }
inline QScriptValue convertScriptValue(QScriptEngine* e, float v) { return QScriptValue(v); }
inline QScriptValue convertScriptValue(QScriptEngine* e, int v) { return QScriptValue(v); }
inline QScriptValue convertScriptValue(QScriptEngine* e, quint16 v) { return QScriptValue(v); }
inline QScriptValue convertScriptValue(QScriptEngine* e, quint32 v) { return QScriptValue(v); }
inline QScriptValue convertScriptValue(QScriptEngine* e, quint64 v) { return QScriptValue((qsreal)v); }
inline QScriptValue convertScriptValue(QScriptEngine* e, const QString& v) { return QScriptValue(v); }
inline QScriptValue convertScriptValue(QScriptEngine* e, const xColor& v) { return xColorToScriptValue(e, v); }
inline QScriptValue convertScriptValue(QScriptEngine* e, const glm::quat& v) { return quatToScriptValue(e, v); }
inline QScriptValue convertScriptValue(QScriptEngine* e, const QScriptValue& v) { return v; }
inline QScriptValue convertScriptValue(QScriptEngine* e, const QVector<glm::vec3>& v) {return qVectorVec3ToScriptValue(e, v); }
inline QScriptValue convertScriptValue(QScriptEngine* e, const QVector<glm::quat>& v) {return qVectorQuatToScriptValue(e, v); }
inline QScriptValue convertScriptValue(QScriptEngine* e, const QVector<bool>& v) {return qVectorBoolToScriptValue(e, v); }
inline QScriptValue convertScriptValue(QScriptEngine* e, const QVector<float>& v) { return qVectorFloatToScriptValue(e, v); }
inline QScriptValue convertScriptValue(QScriptEngine* e, const QByteArray& v) {
QByteArray b64 = v.toBase64();
return QScriptValue(QString(b64));
}
inline QScriptValue convertScriptValue(QScriptEngine* e, const EntityItemID& v) { return QScriptValue(QUuid(v).toString()); }
inline QScriptValue convertScriptValue(QScriptEngine* e, const AACube& v) { return aaCubeToScriptValue(e, v); }
#define COPY_GROUP_PROPERTY_TO_QSCRIPTVALUE(X,G,g,P,p) \
if ((desiredProperties.isEmpty() || desiredProperties.getHasProperty(X)) && \
(!skipDefaults || defaultEntityProperties.get##G().get##P() != get##P())) { \
QScriptValue groupProperties = properties.property(#g); \
if (!groupProperties.isValid()) { \
groupProperties = engine->newObject(); \
} \
QScriptValue V = convertScriptValue(engine, get##P()); \
groupProperties.setProperty(#p, V); \
properties.setProperty(#g, groupProperties); \
}
#define COPY_GROUP_PROPERTY_TO_QSCRIPTVALUE_GETTER(X,G,g,P,p,M) \
if ((desiredProperties.isEmpty() || desiredProperties.getHasProperty(X)) && \
(!skipDefaults || defaultEntityProperties.get##G().get##P() != get##P())) { \
QScriptValue groupProperties = properties.property(#g); \
if (!groupProperties.isValid()) { \
groupProperties = engine->newObject(); \
} \
QScriptValue V = convertScriptValue(engine, M()); \
groupProperties.setProperty(#p, V); \
properties.setProperty(#g, groupProperties); \
}
#define COPY_PROPERTY_TO_QSCRIPTVALUE(p,P) \
if ((_desiredProperties.isEmpty() || _desiredProperties.getHasProperty(p)) && \
(!skipDefaults || defaultEntityProperties._##P != _##P)) { \
QScriptValue V = convertScriptValue(engine, _##P); \
properties.setProperty(#P, V); \
}
#define COPY_PROPERTY_TO_QSCRIPTVALUE_GETTER_NO_SKIP(P, G) \
properties.setProperty(#P, G);
#define COPY_PROPERTY_TO_QSCRIPTVALUE_GETTER(p, P, G) \
if ((_desiredProperties.isEmpty() || _desiredProperties.getHasProperty(p)) && \
(!skipDefaults || defaultEntityProperties._##P != _##P)) { \
QScriptValue V = convertScriptValue(engine, G); \
properties.setProperty(#P, V); \
}
// same as COPY_PROPERTY_TO_QSCRIPTVALUE_GETTER but uses #X instead of #P in the setProperty() step
#define COPY_PROXY_PROPERTY_TO_QSCRIPTVALUE_GETTER(p, P, X, G) \
if ((_desiredProperties.isEmpty() || _desiredProperties.getHasProperty(p)) && \
(!skipDefaults || defaultEntityProperties._##P != _##P)) { \
QScriptValue V = convertScriptValue(engine, G); \
properties.setProperty(#X, V); \
}
#define COPY_PROPERTY_TO_QSCRIPTVALUE_GETTER_ALWAYS(P, G) \
if (!skipDefaults || defaultEntityProperties._##P != _##P) { \
QScriptValue V = convertScriptValue(engine, G); \
properties.setProperty(#P, V); \
}
typedef glm::vec3 glmVec3;
typedef glm::quat glmQuat;
typedef QVector<glm::vec3> qVectorVec3;
typedef QVector<glm::quat> qVectorQuat;
typedef QVector<bool> qVectorBool;
typedef QVector<float> qVectorFloat;
inline float float_convertFromScriptValue(const QScriptValue& v, bool& isValid) { return v.toVariant().toFloat(&isValid); }
inline quint64 quint64_convertFromScriptValue(const QScriptValue& v, bool& isValid) { return v.toVariant().toULongLong(&isValid); }
inline quint32 quint32_convertFromScriptValue(const QScriptValue& v, bool& isValid) {
// Use QString::toUInt() so that isValid is set to false if the number is outside the quint32 range.
return v.toString().toUInt(&isValid);
}
inline quint16 quint16_convertFromScriptValue(const QScriptValue& v, bool& isValid) { return v.toVariant().toInt(&isValid); }
inline uint16_t uint16_t_convertFromScriptValue(const QScriptValue& v, bool& isValid) { return v.toVariant().toInt(&isValid); }
inline int int_convertFromScriptValue(const QScriptValue& v, bool& isValid) { return v.toVariant().toInt(&isValid); }
inline bool bool_convertFromScriptValue(const QScriptValue& v, bool& isValid) { isValid = true; return v.toVariant().toBool(); }
inline uint8_t uint8_t_convertFromScriptValue(const QScriptValue& v, bool& isValid) { isValid = true; return (uint8_t)(0xff & v.toVariant().toInt(&isValid)); }
inline QString QString_convertFromScriptValue(const QScriptValue& v, bool& isValid) { isValid = true; return v.toVariant().toString().trimmed(); }
inline QUuid QUuid_convertFromScriptValue(const QScriptValue& v, bool& isValid) { isValid = true; return v.toVariant().toUuid(); }
inline EntityItemID EntityItemID_convertFromScriptValue(const QScriptValue& v, bool& isValid) { isValid = true; return v.toVariant().toUuid(); }
inline QDateTime QDateTime_convertFromScriptValue(const QScriptValue& v, bool& isValid) {
isValid = true;
auto result = QDateTime::fromString(v.toVariant().toString().trimmed(), Qt::ISODate);
// result.setTimeSpec(Qt::OffsetFromUTC);
return result;
}
inline QByteArray QByteArray_convertFromScriptValue(const QScriptValue& v, bool& isValid) {
isValid = true;
QString b64 = v.toVariant().toString().trimmed();
return QByteArray::fromBase64(b64.toUtf8());
}
inline glmVec3 glmVec3_convertFromScriptValue(const QScriptValue& v, bool& isValid) {
isValid = false; /// assume it can't be converted
QScriptValue x = v.property("x");
QScriptValue y = v.property("y");
QScriptValue z = v.property("z");
if (x.isValid() && y.isValid() && z.isValid()) {
glm::vec3 newValue(0);
newValue.x = x.toVariant().toFloat();
newValue.y = y.toVariant().toFloat();
newValue.z = z.toVariant().toFloat();
isValid = !glm::isnan(newValue.x) &&
!glm::isnan(newValue.y) &&
!glm::isnan(newValue.z);
if (isValid) {
return newValue;
}
}
return glm::vec3(0);
}
inline AACube AACube_convertFromScriptValue(const QScriptValue& v, bool& isValid) {
isValid = true;
AACube result;
aaCubeFromScriptValue(v, result);
return result;
}
inline qVectorFloat qVectorFloat_convertFromScriptValue(const QScriptValue& v, bool& isValid) {
isValid = true;
return qVectorFloatFromScriptValue(v);
}
inline qVectorVec3 qVectorVec3_convertFromScriptValue(const QScriptValue& v, bool& isValid) {
isValid = true;
return qVectorVec3FromScriptValue(v);
}
inline qVectorQuat qVectorQuat_convertFromScriptValue(const QScriptValue& v, bool& isValid) {
isValid = true;
return qVectorQuatFromScriptValue(v);
}
inline qVectorBool qVectorBool_convertFromScriptValue(const QScriptValue& v, bool& isValid) {
isValid = true;
return qVectorBoolFromScriptValue(v);
}
inline glmQuat glmQuat_convertFromScriptValue(const QScriptValue& v, bool& isValid) {
isValid = false; /// assume it can't be converted
QScriptValue x = v.property("x");
QScriptValue y = v.property("y");
QScriptValue z = v.property("z");
QScriptValue w = v.property("w");
if (x.isValid() && y.isValid() && z.isValid() && w.isValid()) {
glm::quat newValue;
newValue.x = x.toVariant().toFloat();
newValue.y = y.toVariant().toFloat();
newValue.z = z.toVariant().toFloat();
newValue.w = w.toVariant().toFloat();
isValid = !glm::isnan(newValue.x) &&
!glm::isnan(newValue.y) &&
!glm::isnan(newValue.z) &&
!glm::isnan(newValue.w);
if (isValid) {
return newValue;
}
}
return glm::quat();
}
inline xColor xColor_convertFromScriptValue(const QScriptValue& v, bool& isValid) {
xColor newValue { 255, 255, 255 };
isValid = false; /// assume it can't be converted
QScriptValue r = v.property("red");
QScriptValue g = v.property("green");
QScriptValue b = v.property("blue");
if (r.isValid() && g.isValid() && b.isValid()) {
newValue.red = r.toVariant().toInt();
newValue.green = g.toVariant().toInt();
newValue.blue = b.toVariant().toInt();
isValid = true;
}
return newValue;
}
#define COPY_PROPERTY_IF_CHANGED(P) \
{ \
if (other._##P##Changed) { \
_##P = other._##P; \
} \
}
#define COPY_PROPERTY_FROM_QSCRIPTVALUE(P, T, S) \
{ \
QScriptValue V = object.property(#P); \
if (V.isValid()) { \
bool isValid = false; \
T newValue = T##_convertFromScriptValue(V, isValid); \
if (isValid && (_defaultSettings || newValue != _##P)) { \
S(newValue); \
} \
} \
}
#define COPY_PROPERTY_FROM_QSCRIPTVALUE_GETTER(P, T, S, G) \
{ \
QScriptValue V = object.property(#P); \
if (V.isValid()) { \
bool isValid = false; \
T newValue = T##_convertFromScriptValue(V, isValid); \
if (isValid && (_defaultSettings || newValue != G())) { \
S(newValue); \
} \
} \
}
#define COPY_PROPERTY_FROM_QSCRIPTVALUE_NOCHECK(P, T, S) \
{ \
QScriptValue V = object.property(#P); \
if (V.isValid()) { \
bool isValid = false; \
T newValue = T##_convertFromScriptValue(V, isValid); \
if (isValid && (_defaultSettings)) { \
S(newValue); \
} \
} \
}
#define COPY_GROUP_PROPERTY_FROM_QSCRIPTVALUE(G, P, T, S) \
{ \
QScriptValue G = object.property(#G); \
if (G.isValid()) { \
QScriptValue V = G.property(#P); \
if (V.isValid()) { \
bool isValid = false; \
T newValue = T##_convertFromScriptValue(V, isValid); \
if (isValid && (_defaultSettings || newValue != _##P)) { \
S(newValue); \
} \
} \
} \
}
#define COPY_PROPERTY_FROM_QSCRIPTVALUE_ENUM(P, S) \
QScriptValue P = object.property(#P); \
if (P.isValid()) { \
QString newValue = P.toVariant().toString(); \
if (_defaultSettings || newValue != get##S##AsString()) { \
set##S##FromString(newValue); \
} \
}
#define DEFINE_PROPERTY_GROUP(N, n, T) \
public: \
const T& get##N() const { return _##n; } \
T& get##N() { return _##n; } \
private: \
T _##n; \
static T _static##N;
#define ADD_PROPERTY_TO_MAP(P, N, n, T) \
_propertyStringsToEnums[#n] = P;
#define ADD_GROUP_PROPERTY_TO_MAP(P, G, g, N, n) \
_propertyStringsToEnums[#g "." #n] = P;
#define DEFINE_CORE(N, n, T, V) \
public: \
bool n##Changed() const { return _##n##Changed; } \
void set##N##Changed(bool value) { _##n##Changed = value; } \
private: \
T _##n = V; \
bool _##n##Changed { false };
#define DEFINE_PROPERTY(P, N, n, T, V) \
public: \
T get##N() const { return _##n; } \
void set##N(T value) { _##n = value; _##n##Changed = true; } \
DEFINE_CORE(N, n, T, V)
#define DEFINE_PROPERTY_REF(P, N, n, T, V) \
public: \
const T& get##N() const { return _##n; } \
void set##N(const T& value) { _##n = value; _##n##Changed = true; } \
DEFINE_CORE(N, n, T, V)
#define DEFINE_PROPERTY_REF_WITH_SETTER(P, N, n, T, V) \
public: \
const T& get##N() const { return _##n; } \
void set##N(const T& value); \
DEFINE_CORE(N, n, T, V)
#define DEFINE_PROPERTY_REF_WITH_SETTER_AND_GETTER(P, N, n, T, V) \
public: \
T get##N() const; \
void set##N(const T& value); \
DEFINE_CORE(N, n, T, V)
#define DEFINE_PROPERTY_REF_ENUM(P, N, n, T, V) \
public: \
const T& get##N() const { return _##n; } \
void set##N(const T& value) { _##n = value; _##n##Changed = true; } \
QString get##N##AsString() const; \
void set##N##FromString(const QString& name); \
DEFINE_CORE(N, n, T, V)
#define DEBUG_PROPERTY(D, P, N, n, x) \
D << " " << #n << ":" << P.get##N() << x << "[changed:" << P.n##Changed() << "]\n";
#define DEBUG_PROPERTY_IF_CHANGED(D, P, N, n, x) \
if (P.n##Changed()) { \
D << " " << #n << ":" << P.get##N() << x << "\n"; \
}
#endif // hifi_EntityItemPropertiesMacros_h