15 #ifndef hifi_EntityItemPropertiesMacros_h
16 #define hifi_EntityItemPropertiesMacros_h
18 #include <EntityItemID.h>
19 #include <RegisteredMetaTypes.h>
20 #include <ScriptEngine.h>
21 #include <ScriptValue.h>
22 #include <ScriptValueUtils.h>
24 #define APPEND_ENTITY_PROPERTY(P,V) \
25 if (requestedProperties.getHasProperty(P)) { \
26 LevelDetails propertyLevel = packetData->startLevel(); \
27 successPropertyFits = packetData->appendValue(V); \
28 if (successPropertyFits) { \
30 propertiesDidntFit -= P; \
32 packetData->endLevel(propertyLevel); \
34 packetData->discardLevel(propertyLevel); \
35 appendState = OctreeElement::PARTIAL; \
38 propertiesDidntFit -= P; \
41 #define READ_ENTITY_PROPERTY(P,T,S) \
42 if (propertyFlags.getHasProperty(P)) { \
44 int bytes = OctreePacketData::unpackDataFromBytes(dataAt, fromBuffer); \
47 if (overwriteLocalData) { \
50 somethingChanged = true; \
53 #define SKIP_ENTITY_PROPERTY(P,T) \
54 if (propertyFlags.getHasProperty(P)) { \
56 int bytes = OctreePacketData::unpackDataFromBytes(dataAt, fromBuffer); \
61 #define DECODE_GROUP_PROPERTY_HAS_CHANGED(P,N) \
62 if (propertyFlags.getHasProperty(P)) { \
63 set##N##Changed(true); \
67 #define READ_ENTITY_PROPERTY_TO_PROPERTIES(P,T,O) \
68 if (propertyFlags.getHasProperty(P)) { \
70 int bytes = OctreePacketData::unpackDataFromBytes(dataAt, fromBuffer); \
72 processedBytes += bytes; \
73 properties.O(fromBuffer); \
76 #define SET_ENTITY_PROPERTY_FROM_PROPERTIES(P,M) \
77 if (properties._##P##Changed) { \
79 somethingChanged = true; \
82 #define SET_ENTITY_GROUP_PROPERTY_FROM_PROPERTIES(G,P,p,M) \
83 if (properties.get##G().p##Changed()) { \
84 M(properties.get##G().get##P()); \
85 somethingChanged = true; \
88 #define SET_ENTITY_PROPERTY_FROM_PROPERTIES_GETTER(C,G,S) \
89 if (properties.C()) { \
91 somethingChanged = true; \
94 #define COPY_ENTITY_PROPERTY_TO_PROPERTIES(P,M) \
95 properties._##P = M(); \
96 properties._##P##Changed = false;
98 #define COPY_ENTITY_GROUP_PROPERTY_TO_PROPERTIES(G,P,M) \
99 properties.get##G().set##P(M()); \
100 properties.get##G().set##P##Changed(false);
102 #define CHECK_PROPERTY_CHANGE(P,M) \
103 if (_##M##Changed) { \
104 changedProperties += P; \
109 inline ScriptValue vec3Color_convertScriptValue(
ScriptEngine* e,
const glm::vec3& v) {
return vec3ColorToScriptValue(e, v); }
110 inline ScriptValue convertScriptValue(
ScriptEngine* e,
const glm::u8vec3& v) {
return u8vec3ToScriptValue(e, v); }
111 inline ScriptValue u8vec3Color_convertScriptValue(
ScriptEngine* e,
const glm::u8vec3& v) {
return u8vec3ColorToScriptValue(e, v); }
122 inline ScriptValue convertScriptValue(
ScriptEngine* e,
const QVector<glm::vec3>& v) {
return qVectorVec3ToScriptValue(e, v); }
123 inline ScriptValue qVectorVec3Color_convertScriptValue(
ScriptEngine* e,
const QVector<glm::vec3>& v) {
return qVectorVec3ColorToScriptValue(e, v); }
124 inline ScriptValue convertScriptValue(
ScriptEngine* e,
const QVector<glm::quat>& v) {
return qVectorQuatToScriptValue(e, v); }
125 inline ScriptValue convertScriptValue(
ScriptEngine* e,
const QVector<bool>& v) {
return qVectorBoolToScriptValue(e, v); }
126 inline ScriptValue convertScriptValue(
ScriptEngine* e,
const QVector<float>& v) {
return qVectorFloatToScriptValue(e, v); }
127 inline ScriptValue convertScriptValue(
ScriptEngine* e,
const QVector<QUuid>& v) {
return qVectorQUuidToScriptValue(e, v); }
132 QByteArray b64 = v.toBase64();
133 return e->newValue(QString(b64));
140 #define COPY_GROUP_PROPERTY_TO_QSCRIPTVALUE(X,G,g,P,p) \
141 if (((!returnNothingOnEmptyPropertyFlags && desiredProperties.isEmpty()) || desiredProperties.getHasProperty(X)) && \
142 (!skipDefaults || defaultEntityProperties.get##G().get##P() != get##P())) { \
143 ScriptValue groupProperties = properties.property(#g); \
144 if (!groupProperties.isValid()) { \
145 groupProperties = engine->newObject(); \
147 ScriptValue V = convertScriptValue(engine, get##P()); \
148 groupProperties.setProperty(#p, V); \
149 properties.setProperty(#g, groupProperties); \
152 #define COPY_GROUP_PROPERTY_TO_QSCRIPTVALUE_TYPED(X,G,g,P,p,T) \
153 if (((!returnNothingOnEmptyPropertyFlags && desiredProperties.isEmpty()) || desiredProperties.getHasProperty(X)) && \
154 (!skipDefaults || defaultEntityProperties.get##G().get##P() != get##P())) { \
155 ScriptValue groupProperties = properties.property(#g); \
156 if (!groupProperties.isValid()) { \
157 groupProperties = engine->newObject(); \
159 ScriptValue V = T##_convertScriptValue(engine, get##P()); \
160 groupProperties.setProperty(#p, V); \
161 properties.setProperty(#g, groupProperties); \
164 #define COPY_GROUP_PROPERTY_TO_QSCRIPTVALUE_GETTER(X,G,g,P,p,M) \
165 if (((!returnNothingOnEmptyPropertyFlags && desiredProperties.isEmpty()) || desiredProperties.getHasProperty(X)) && \
166 (!skipDefaults || defaultEntityProperties.get##G().get##P() != get##P())) { \
167 ScriptValue groupProperties = properties.property(#g); \
168 if (!groupProperties.isValid()) { \
169 groupProperties = engine->newObject(); \
171 ScriptValue V = convertScriptValue(engine, M()); \
172 groupProperties.setProperty(#p, V); \
173 properties.setProperty(#g, groupProperties); \
176 #define COPY_PROPERTY_TO_QSCRIPTVALUE(p,P) \
177 if (((!returnNothingOnEmptyPropertyFlags && _desiredProperties.isEmpty()) || _desiredProperties.getHasProperty(p)) && \
178 (!skipDefaults || defaultEntityProperties._##P != _##P)) { \
179 ScriptValue V = convertScriptValue(engine, _##P); \
180 properties.setProperty(#P, V); \
183 #define COPY_PROPERTY_TO_QSCRIPTVALUE_TYPED(p,P,T) \
184 if (((!returnNothingOnEmptyPropertyFlags && _desiredProperties.isEmpty()) || _desiredProperties.getHasProperty(p)) && \
185 (!skipDefaults || defaultEntityProperties._##P != _##P)) { \
186 ScriptValue V = T##_convertScriptValue(engine, _##P); \
187 properties.setProperty(#P, V); \
190 #define COPY_PROPERTY_TO_QSCRIPTVALUE_GETTER_NO_SKIP(P, G) \
191 properties.setProperty(#P, G);
193 #define COPY_PROPERTY_TO_QSCRIPTVALUE_GETTER(p, P, G) \
194 if (((!returnNothingOnEmptyPropertyFlags && _desiredProperties.isEmpty()) || _desiredProperties.getHasProperty(p)) && \
195 (!skipDefaults || defaultEntityProperties._##P != _##P)) { \
196 ScriptValue V = convertScriptValue(engine, G); \
197 properties.setProperty(#P, V); \
200 #define COPY_PROPERTY_TO_QSCRIPTVALUE_GETTER_TYPED(p, P, G, T) \
201 if ((_desiredProperties.isEmpty() || _desiredProperties.getHasProperty(p)) && \
202 (!skipDefaults || defaultEntityProperties._##P != _##P)) { \
203 ScriptValue V = T##_convertScriptValue(engine, G); \
204 properties.setProperty(#P, V); \
208 #define COPY_PROXY_PROPERTY_TO_QSCRIPTVALUE_GETTER(p, P, X, G) \
209 if (((!returnNothingOnEmptyPropertyFlags && _desiredProperties.isEmpty()) || _desiredProperties.getHasProperty(p)) && \
210 (!skipDefaults || defaultEntityProperties._##P != _##P)) { \
211 ScriptValue V = convertScriptValue(engine, G); \
212 properties.setProperty(#X, V); \
215 #define COPY_PROPERTY_TO_QSCRIPTVALUE_GETTER_ALWAYS(P, G) \
216 if (!skipDefaults || defaultEntityProperties._##P != _##P) { \
217 ScriptValue V = convertScriptValue(engine, G); \
218 properties.setProperty(#P, V); \
221 #define COPY_PROPERTY_TO_QSCRIPTVALUE_IF_URL_PERMISSION(p, P) \
222 if (((!returnNothingOnEmptyPropertyFlags && _desiredProperties.isEmpty()) || _desiredProperties.getHasProperty(p)) && \
223 (!skipDefaults || defaultEntityProperties._##P != _##P)) { \
224 if (isMyOwnAvatarEntity || nodeList->getThisNodeCanViewAssetURLs()) { \
225 ScriptValue V = convertScriptValue(engine, _##P); \
226 properties.setProperty(#P, V); \
228 const QString emptyURL = ""; \
229 ScriptValue V = convertScriptValue(engine, emptyURL); \
230 properties.setProperty(#P, V); \
234 #define COPY_GROUP_PROPERTY_TO_QSCRIPTVALUE_IF_URL_PERMISSION(X, G, g, P, p) \
235 if (((!returnNothingOnEmptyPropertyFlags && desiredProperties.isEmpty()) || desiredProperties.getHasProperty(X)) && \
236 (!skipDefaults || defaultEntityProperties.get##G().get##P() != get##P())) { \
237 if (isMyOwnAvatarEntity || nodeList->getThisNodeCanViewAssetURLs()) { \
238 ScriptValue groupProperties = properties.property(#g); \
239 if (!groupProperties.isValid()) { \
240 groupProperties = engine->newObject(); \
242 ScriptValue V = convertScriptValue(engine, get##P()); \
243 groupProperties.setProperty(#p, V); \
244 properties.setProperty(#g, groupProperties); \
246 const QString emptyURL = ""; \
247 ScriptValue V = convertScriptValue(engine, emptyURL); \
248 properties.setProperty(#P, V); \
252 typedef QVector<glm::vec3> qVectorVec3;
253 typedef QVector<glm::quat> qVectorQuat;
254 typedef QVector<bool> qVectorBool;
255 typedef QVector<float> qVectorFloat;
256 typedef QVector<QUuid> qVectorQUuid;
257 inline float float_convertFromScriptValue(
const ScriptValue& v,
bool& isValid) {
return v.toVariant().toFloat(&isValid); }
258 inline quint64 quint64_convertFromScriptValue(
const ScriptValue& v,
bool& isValid) {
return v.toVariant().toULongLong(&isValid); }
259 inline quint32 quint32_convertFromScriptValue(
const ScriptValue& v,
bool& isValid) {
261 return v.toString().toUInt(&isValid);
263 inline quint16 quint16_convertFromScriptValue(
const ScriptValue& v,
bool& isValid) {
return v.toVariant().toInt(&isValid); }
264 inline uint16_t uint16_t_convertFromScriptValue(
const ScriptValue& v,
bool& isValid) {
return v.toVariant().toInt(&isValid); }
265 inline uint32_t uint32_t_convertFromScriptValue(
const ScriptValue& v,
bool& isValid) {
return v.toVariant().toInt(&isValid); }
266 inline int int_convertFromScriptValue(
const ScriptValue& v,
bool& isValid) {
return v.toVariant().toInt(&isValid); }
267 inline bool bool_convertFromScriptValue(
const ScriptValue& v,
bool& isValid) { isValid =
true;
return v.toVariant().toBool(); }
268 inline uint8_t uint8_t_convertFromScriptValue(
const ScriptValue& v,
bool& isValid) { isValid =
true;
return (uint8_t)(0xff & v.toVariant().toInt(&isValid)); }
269 inline QString QString_convertFromScriptValue(
const ScriptValue& v,
bool& isValid) { isValid =
true;
return v.toVariant().toString().trimmed(); }
270 inline QUuid QUuid_convertFromScriptValue(
const ScriptValue& v,
bool& isValid) { isValid =
true;
return v.toVariant().toUuid(); }
271 inline EntityItemID EntityItemID_convertFromScriptValue(
const ScriptValue& v,
bool& isValid) { isValid =
true;
return v.toVariant().toUuid(); }
273 inline QByteArray QByteArray_convertFromScriptValue(
const ScriptValue& v,
bool& isValid) {
275 QString b64 = v.toVariant().toString().trimmed();
276 return QByteArray::fromBase64(b64.toUtf8());
279 inline glm::vec2 vec2_convertFromScriptValue(
const ScriptValue& v,
bool& isValid) {
282 vec2FromScriptValue(v, vec2);
286 inline glm::vec3 vec3_convertFromScriptValue(
const ScriptValue& v,
bool& isValid) {
289 vec3FromScriptValue(v, vec3);
293 inline glm::vec3 vec3Color_convertFromScriptValue(
const ScriptValue& v,
bool& isValid) {
296 vec3FromScriptValue(v, vec3);
300 inline glm::u8vec3 u8vec3Color_convertFromScriptValue(
const ScriptValue& v,
bool& isValid) {
303 u8vec3FromScriptValue(v, vec3);
307 inline AACube AACube_convertFromScriptValue(
const ScriptValue& v,
bool& isValid) {
310 aaCubeFromScriptValue(v, result);
314 inline qVectorFloat qVectorFloat_convertFromScriptValue(
const ScriptValue& v,
bool& isValid) {
316 return qVectorFloatFromScriptValue(v);
319 inline qVectorVec3 qVectorVec3_convertFromScriptValue(
const ScriptValue& v,
bool& isValid) {
321 return qVectorVec3FromScriptValue(v);
324 inline qVectorQuat qVectorQuat_convertFromScriptValue(
const ScriptValue& v,
bool& isValid) {
326 return qVectorQuatFromScriptValue(v);
329 inline qVectorBool qVectorBool_convertFromScriptValue(
const ScriptValue& v,
bool& isValid) {
331 return qVectorBoolFromScriptValue(v);
334 inline qVectorQUuid qVectorQUuid_convertFromScriptValue(
const ScriptValue& v,
bool& isValid) {
336 return qVectorQUuidFromScriptValue(v);
339 inline glm::quat quat_convertFromScriptValue(
const ScriptValue& v,
bool& isValid) {
345 if (x.isValid() && y.isValid() && z.isValid() && w.isValid()) {
347 newValue.x = x.toVariant().toFloat();
348 newValue.y = y.toVariant().toFloat();
349 newValue.z = z.toVariant().toFloat();
350 newValue.w = w.toVariant().toFloat();
351 isValid = !glm::isnan(newValue.x) &&
352 !glm::isnan(newValue.y) &&
353 !glm::isnan(newValue.z) &&
354 !glm::isnan(newValue.w);
362 inline QRect QRect_convertFromScriptValue(
const ScriptValue& v,
bool& isValid) {
365 qRectFromScriptValue(v, rect);
369 #define COPY_PROPERTY_IF_CHANGED(P) \
371 if (other._##P##Changed) { \
378 #define COPY_PROPERTY_FROM_QSCRIPTVALUE(P, T, S) \
380 if (namesSet.contains(#P)) { \
381 ScriptValue V = object.property(#P); \
383 bool isValid = false; \
384 T newValue = T##_convertFromScriptValue(V, isValid); \
385 if (isValid && (_defaultSettings || newValue != _##P)) { \
392 #define COPY_PROPERTY_FROM_QSCRIPTVALUE_GETTER(P, T, S, G) \
394 if (namesSet.contains(#P)) { \
395 ScriptValue V = object.property(#P); \
397 bool isValid = false; \
398 T newValue = T##_convertFromScriptValue(V, isValid); \
399 if (isValid && (_defaultSettings || newValue != G())) { \
406 #define COPY_PROPERTY_FROM_QSCRIPTVALUE_NOCHECK(P, T, S) \
408 if (namesSet.contains(#P)) { \
409 ScriptValue V = object.property(#P); \
411 bool isValid = false; \
412 T newValue = T##_convertFromScriptValue(V, isValid); \
413 if (isValid && (_defaultSettings)) { \
420 #define COPY_GROUP_PROPERTY_FROM_QSCRIPTVALUE(G, P, T, S) \
422 if (namesSet.contains(#G)) { \
423 ScriptValue G = object.property(#G); \
425 ScriptValue V = G.property(#P); \
427 bool isValid = false; \
428 T newValue = T##_convertFromScriptValue(V, isValid); \
429 if (isValid && (_defaultSettings || newValue != _##P)) { \
437 #define COPY_PROPERTY_FROM_QSCRIPTVALUE_ENUM(P, S) \
439 if (namesSet.contains(#P)) { \
440 ScriptValue P = object.property(#P); \
442 QString newValue = P.toVariant().toString(); \
443 if (_defaultSettings || newValue != get##S##AsString()) { \
444 set##S##FromString(newValue); \
450 #define COPY_GROUP_PROPERTY_FROM_QSCRIPTVALUE_ENUM(G, P, S) \
452 if (namesSet.contains(#G)) { \
453 ScriptValue G = object.property(#G); \
455 ScriptValue P = G.property(#P); \
457 QString newValue = P.toVariant().toString(); \
458 if (_defaultSettings || newValue != get##S##AsString()) { \
459 set##S##FromString(newValue); \
466 #define DEFINE_PROPERTY_GROUP(N, n, T) \
468 const T& get##N() const { return _##n; } \
469 T& get##N() { return _##n; } \
475 #define ADD_PROPERTY_TO_MAP(P, N, n, T) \
477 EntityPropertyInfo propertyInfo { makePropertyInfo<T>(P) }; \
478 _propertyInfos[#n] = propertyInfo; \
479 _enumsToPropertyStrings[P] = #n; \
482 #define ADD_PROPERTY_TO_MAP_WITH_RANGE(P, N, n, T, M, X) \
484 EntityPropertyInfo propertyInfo = EntityPropertyInfo(P, M, X); \
485 _propertyInfos[#n] = propertyInfo; \
486 _enumsToPropertyStrings[P] = #n; \
489 #define ADD_GROUP_PROPERTY_TO_MAP(P, G, g, N, n) \
491 EntityPropertyInfo propertyInfo = EntityPropertyInfo(P); \
492 _propertyInfos[#g "." #n] = propertyInfo; \
493 _propertyInfos[#g].propertyEnums << P; \
494 _enumsToPropertyStrings[P] = #g "." #n; \
497 #define ADD_GROUP_PROPERTY_TO_MAP_WITH_RANGE(P, G, g, N, n, M, X) \
499 EntityPropertyInfo propertyInfo = EntityPropertyInfo(P, M, X); \
500 _propertyInfos[#g "." #n] = propertyInfo; \
501 _propertyInfos[#g].propertyEnums << P; \
502 _enumsToPropertyStrings[P] = #g "." #n; \
505 #define DEFINE_CORE(N, n, T, V) \
507 bool n##Changed() const { return _##n##Changed; } \
508 void set##N##Changed(bool value) { _##n##Changed = value; } \
511 bool _##n##Changed { false };
513 #define DEFINE_PROPERTY(P, N, n, T, V) \
515 T get##N() const { return _##n; } \
516 void set##N(T value) { _##n = value; _##n##Changed = true; } \
517 DEFINE_CORE(N, n, T, V)
519 #define DEFINE_PROPERTY_REF(P, N, n, T, V) \
521 const T& get##N() const { return _##n; } \
522 void set##N(const T& value) { _##n = value; _##n##Changed = true; } \
523 DEFINE_CORE(N, n, T, V)
525 #define DEFINE_PROPERTY_REF_WITH_SETTER(P, N, n, T, V) \
527 const T& get##N() const { return _##n; } \
528 void set##N(const T& value); \
529 DEFINE_CORE(N, n, T, V)
531 #define DEFINE_PROPERTY_REF_WITH_SETTER_AND_GETTER(P, N, n, T, V) \
534 void set##N(const T& value); \
535 DEFINE_CORE(N, n, T, V)
537 #define DEFINE_PROPERTY_REF_ENUM(P, N, n, T, V) \
539 const T& get##N() const { return _##n; } \
540 void set##N(const T& value) { _##n = value; _##n##Changed = true; } \
541 QString get##N##AsString() const; \
542 void set##N##FromString(const QString& name); \
543 DEFINE_CORE(N, n, T, V)
545 #define DEBUG_PROPERTY(D, P, N, n, x) \
546 D << " " << #n << ":" << P.get##N() << x << "[changed:" << P.n##Changed() << "]\n";
548 #define DEBUG_PROPERTY_IF_CHANGED(D, P, N, n, x) \
549 if (P.n##Changed()) { \
550 D << " " << #n << ":" << P.get##N() << x << "\n"; \
Abstract ID for editing model items. Used in EntityItem JS API.
Definition: EntityItemID.h:28
Provides an engine-independent interface for a scripting engine.
Definition: ScriptEngine.h:93
[ScriptInterface] Provides an engine-independent interface for QScriptValue
Definition: ScriptValue.h:40