Overte C++ Documentation
EntityItemPropertiesMacros.h
1 //
2 // EntityItemPropertiesMacros.h
3 // libraries/entities/src
4 //
5 // Created by Brad Hefta-Gaub on 9/10/14.
6 // Copyright 2014 High Fidelity, Inc.
7 // Copyright 2023 Overte e.V.
8 //
9 // Distributed under the Apache License, Version 2.0.
10 // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
11 // SPDX-License-Identifier: Apache-2.0
12 //
13 
14 
15 #ifndef hifi_EntityItemPropertiesMacros_h
16 #define hifi_EntityItemPropertiesMacros_h
17 
18 #include <EntityItemID.h>
19 #include <RegisteredMetaTypes.h>
20 #include <ScriptEngine.h>
21 #include <ScriptValue.h>
22 #include <ScriptValueUtils.h>
23 
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) { \
29  propertyFlags |= P; \
30  propertiesDidntFit -= P; \
31  propertyCount++; \
32  packetData->endLevel(propertyLevel); \
33  } else { \
34  packetData->discardLevel(propertyLevel); \
35  appendState = OctreeElement::PARTIAL; \
36  } \
37  } else { \
38  propertiesDidntFit -= P; \
39  }
40 
41 #define READ_ENTITY_PROPERTY(P,T,S) \
42  if (propertyFlags.getHasProperty(P)) { \
43  T fromBuffer; \
44  int bytes = OctreePacketData::unpackDataFromBytes(dataAt, fromBuffer); \
45  dataAt += bytes; \
46  bytesRead += bytes; \
47  if (overwriteLocalData) { \
48  S(fromBuffer); \
49  } \
50  somethingChanged = true; \
51  }
52 
53 #define SKIP_ENTITY_PROPERTY(P,T) \
54  if (propertyFlags.getHasProperty(P)) { \
55  T fromBuffer; \
56  int bytes = OctreePacketData::unpackDataFromBytes(dataAt, fromBuffer); \
57  dataAt += bytes; \
58  bytesRead += bytes; \
59  }
60 
61 #define DECODE_GROUP_PROPERTY_HAS_CHANGED(P,N) \
62  if (propertyFlags.getHasProperty(P)) { \
63  set##N##Changed(true); \
64  }
65 
66 
67 #define READ_ENTITY_PROPERTY_TO_PROPERTIES(P,T,O) \
68  if (propertyFlags.getHasProperty(P)) { \
69  T fromBuffer; \
70  int bytes = OctreePacketData::unpackDataFromBytes(dataAt, fromBuffer); \
71  dataAt += bytes; \
72  processedBytes += bytes; \
73  properties.O(fromBuffer); \
74  }
75 
76 #define SET_ENTITY_PROPERTY_FROM_PROPERTIES(P,M) \
77  if (properties._##P##Changed) { \
78  M(properties._##P); \
79  somethingChanged = true; \
80  }
81 
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; \
86  }
87 
88 #define SET_ENTITY_PROPERTY_FROM_PROPERTIES_GETTER(C,G,S) \
89  if (properties.C()) { \
90  S(properties.G()); \
91  somethingChanged = true; \
92  }
93 
94 #define COPY_ENTITY_PROPERTY_TO_PROPERTIES(P,M) \
95  properties._##P = M(); \
96  properties._##P##Changed = false;
97 
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);
101 
102 #define CHECK_PROPERTY_CHANGE(P,M) \
103  if (_##M##Changed) { \
104  changedProperties += P; \
105  }
106 
107 inline ScriptValue convertScriptValue(ScriptEngine* e, const glm::vec2& v) { return vec2ToScriptValue(e, v); }
108 inline ScriptValue convertScriptValue(ScriptEngine* e, const glm::vec3& v) { return vec3ToScriptValue(e, v); }
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); }
112 inline ScriptValue convertScriptValue(ScriptEngine* e, float v) { return e->newValue(v); }
113 inline ScriptValue convertScriptValue(ScriptEngine* e, int v) { return e->newValue(v); }
114 inline ScriptValue convertScriptValue(ScriptEngine* e, bool v) { return e->newValue(v); }
115 inline ScriptValue convertScriptValue(ScriptEngine* e, quint16 v) { return e->newValue(v); }
116 inline ScriptValue convertScriptValue(ScriptEngine* e, quint32 v) { return e->newValue(v); }
117 inline ScriptValue convertScriptValue(ScriptEngine* e, quint64 v) { return e->newValue((double)v); }
118 inline ScriptValue convertScriptValue(ScriptEngine* e, const QString& v) { return e->newValue(v); }
119 
120 inline ScriptValue convertScriptValue(ScriptEngine* e, const glm::quat& v) { return quatToScriptValue(e, v); }
121 inline ScriptValue convertScriptValue(ScriptEngine* e, const ScriptValue& v) { return 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); }
128 
129 inline ScriptValue convertScriptValue(ScriptEngine* e, const QRect& v) { return qRectToScriptValue(e, v); }
130 
131 inline ScriptValue convertScriptValue(ScriptEngine* e, const QByteArray& v) {
132  QByteArray b64 = v.toBase64();
133  return e->newValue(QString(b64));
134 }
135 
136 inline ScriptValue convertScriptValue(ScriptEngine* e, const EntityItemID& v) { return e->newValue(QUuid(v).toString()); }
137 
138 inline ScriptValue convertScriptValue(ScriptEngine* e, const AACube& v) { return aaCubeToScriptValue(e, v); }
139 
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(); \
146  } \
147  ScriptValue V = convertScriptValue(engine, get##P()); \
148  groupProperties.setProperty(#p, V); \
149  properties.setProperty(#g, groupProperties); \
150  }
151 
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(); \
158  } \
159  ScriptValue V = T##_convertScriptValue(engine, get##P()); \
160  groupProperties.setProperty(#p, V); \
161  properties.setProperty(#g, groupProperties); \
162  }
163 
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(); \
170  } \
171  ScriptValue V = convertScriptValue(engine, M()); \
172  groupProperties.setProperty(#p, V); \
173  properties.setProperty(#g, groupProperties); \
174  }
175 
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); \
181  }
182 
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); \
188  }
189 
190 #define COPY_PROPERTY_TO_QSCRIPTVALUE_GETTER_NO_SKIP(P, G) \
191  properties.setProperty(#P, G);
192 
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); \
198  }
199 
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); \
205  }
206 
207 // same as COPY_PROPERTY_TO_QSCRIPTVALUE_GETTER but uses #X instead of #P in the setProperty() step
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); \
213  }
214 
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); \
219  }
220 
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); \
227  } else { \
228  const QString emptyURL = ""; \
229  ScriptValue V = convertScriptValue(engine, emptyURL); \
230  properties.setProperty(#P, V); \
231  } \
232  }
233 
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(); \
241  } \
242  ScriptValue V = convertScriptValue(engine, get##P()); \
243  groupProperties.setProperty(#p, V); \
244  properties.setProperty(#g, groupProperties); \
245  } else { \
246  const QString emptyURL = ""; \
247  ScriptValue V = convertScriptValue(engine, emptyURL); \
248  properties.setProperty(#P, V); \
249  } \
250  }
251 
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) {
260  // Use QString::toUInt() so that isValid is set to false if the number is outside the quint32 range.
261  return v.toString().toUInt(&isValid);
262 }
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(); }
272 
273 inline QByteArray QByteArray_convertFromScriptValue(const ScriptValue& v, bool& isValid) {
274  isValid = true;
275  QString b64 = v.toVariant().toString().trimmed();
276  return QByteArray::fromBase64(b64.toUtf8());
277 }
278 
279 inline glm::vec2 vec2_convertFromScriptValue(const ScriptValue& v, bool& isValid) {
280  isValid = true;
281  glm::vec2 vec2;
282  vec2FromScriptValue(v, vec2);
283  return vec2;
284 }
285 
286 inline glm::vec3 vec3_convertFromScriptValue(const ScriptValue& v, bool& isValid) {
287  isValid = true;
288  glm::vec3 vec3;
289  vec3FromScriptValue(v, vec3);
290  return vec3;
291 }
292 
293 inline glm::vec3 vec3Color_convertFromScriptValue(const ScriptValue& v, bool& isValid) {
294  isValid = true;
295  glm::vec3 vec3;
296  vec3FromScriptValue(v, vec3);
297  return vec3;
298 }
299 
300 inline glm::u8vec3 u8vec3Color_convertFromScriptValue(const ScriptValue& v, bool& isValid) {
301  isValid = true;
302  glm::u8vec3 vec3;
303  u8vec3FromScriptValue(v, vec3);
304  return vec3;
305 }
306 
307 inline AACube AACube_convertFromScriptValue(const ScriptValue& v, bool& isValid) {
308  isValid = true;
309  AACube result;
310  aaCubeFromScriptValue(v, result);
311  return result;
312 }
313 
314 inline qVectorFloat qVectorFloat_convertFromScriptValue(const ScriptValue& v, bool& isValid) {
315  isValid = true;
316  return qVectorFloatFromScriptValue(v);
317 }
318 
319 inline qVectorVec3 qVectorVec3_convertFromScriptValue(const ScriptValue& v, bool& isValid) {
320  isValid = true;
321  return qVectorVec3FromScriptValue(v);
322 }
323 
324 inline qVectorQuat qVectorQuat_convertFromScriptValue(const ScriptValue& v, bool& isValid) {
325  isValid = true;
326  return qVectorQuatFromScriptValue(v);
327 }
328 
329 inline qVectorBool qVectorBool_convertFromScriptValue(const ScriptValue& v, bool& isValid) {
330  isValid = true;
331  return qVectorBoolFromScriptValue(v);
332 }
333 
334 inline qVectorQUuid qVectorQUuid_convertFromScriptValue(const ScriptValue& v, bool& isValid) {
335  isValid = true;
336  return qVectorQUuidFromScriptValue(v);
337 }
338 
339 inline glm::quat quat_convertFromScriptValue(const ScriptValue& v, bool& isValid) {
340  isValid = false;
341  ScriptValue x = v.property("x");
342  ScriptValue y = v.property("y");
343  ScriptValue z = v.property("z");
344  ScriptValue w = v.property("w");
345  if (x.isValid() && y.isValid() && z.isValid() && w.isValid()) {
346  glm::quat newValue;
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);
355  if (isValid) {
356  return newValue;
357  }
358  }
359  return glm::quat();
360 }
361 
362 inline QRect QRect_convertFromScriptValue(const ScriptValue& v, bool& isValid) {
363  isValid = true;
364  QRect rect;
365  qRectFromScriptValue(v, rect);
366  return rect;
367 }
368 
369 #define COPY_PROPERTY_IF_CHANGED(P) \
370 { \
371  if (other._##P##Changed) { \
372  _##P = other._##P; \
373  } \
374 }
375 
376 
377 
378 #define COPY_PROPERTY_FROM_QSCRIPTVALUE(P, T, S) \
379  { \
380  if (namesSet.contains(#P)) { \
381  ScriptValue V = object.property(#P); \
382  if (V.isValid()) { \
383  bool isValid = false; \
384  T newValue = T##_convertFromScriptValue(V, isValid); \
385  if (isValid && (_defaultSettings || newValue != _##P)) { \
386  S(newValue); \
387  } \
388  } \
389  } \
390  }
391 
392 #define COPY_PROPERTY_FROM_QSCRIPTVALUE_GETTER(P, T, S, G) \
393 { \
394  if (namesSet.contains(#P)) { \
395  ScriptValue V = object.property(#P); \
396  if (V.isValid()) { \
397  bool isValid = false; \
398  T newValue = T##_convertFromScriptValue(V, isValid); \
399  if (isValid && (_defaultSettings || newValue != G())) { \
400  S(newValue); \
401  } \
402  } \
403  } \
404 }
405 
406 #define COPY_PROPERTY_FROM_QSCRIPTVALUE_NOCHECK(P, T, S) \
407 { \
408  if (namesSet.contains(#P)) { \
409  ScriptValue V = object.property(#P); \
410  if (V.isValid()) { \
411  bool isValid = false; \
412  T newValue = T##_convertFromScriptValue(V, isValid); \
413  if (isValid && (_defaultSettings)) { \
414  S(newValue); \
415  } \
416  } \
417  } \
418 }
419 
420 #define COPY_GROUP_PROPERTY_FROM_QSCRIPTVALUE(G, P, T, S) \
421  { \
422  if (namesSet.contains(#G)) { \
423  ScriptValue G = object.property(#G); \
424  if (G.isValid()) { \
425  ScriptValue V = G.property(#P); \
426  if (V.isValid()) { \
427  bool isValid = false; \
428  T newValue = T##_convertFromScriptValue(V, isValid); \
429  if (isValid && (_defaultSettings || newValue != _##P)) { \
430  S(newValue); \
431  } \
432  } \
433  } \
434  } \
435  }
436 
437 #define COPY_PROPERTY_FROM_QSCRIPTVALUE_ENUM(P, S) \
438  { \
439  if (namesSet.contains(#P)) { \
440  ScriptValue P = object.property(#P); \
441  if (P.isValid()) { \
442  QString newValue = P.toVariant().toString(); \
443  if (_defaultSettings || newValue != get##S##AsString()) { \
444  set##S##FromString(newValue); \
445  } \
446  } \
447  } \
448  }
449 
450 #define COPY_GROUP_PROPERTY_FROM_QSCRIPTVALUE_ENUM(G, P, S) \
451  { \
452  if (namesSet.contains(#G)) { \
453  ScriptValue G = object.property(#G); \
454  if (G.isValid()) { \
455  ScriptValue P = G.property(#P); \
456  if (P.isValid()) { \
457  QString newValue = P.toVariant().toString(); \
458  if (_defaultSettings || newValue != get##S##AsString()) { \
459  set##S##FromString(newValue); \
460  } \
461  } \
462  } \
463  } \
464  }
465 
466 #define DEFINE_PROPERTY_GROUP(N, n, T) \
467  public: \
468  const T& get##N() const { return _##n; } \
469  T& get##N() { return _##n; } \
470  private: \
471  T _##n; \
472  static T _static##N;
473 
474 
475 #define ADD_PROPERTY_TO_MAP(P, N, n, T) \
476  { \
477  EntityPropertyInfo propertyInfo { makePropertyInfo<T>(P) }; \
478  _propertyInfos[#n] = propertyInfo; \
479  _enumsToPropertyStrings[P] = #n; \
480  }
481 
482 #define ADD_PROPERTY_TO_MAP_WITH_RANGE(P, N, n, T, M, X) \
483  { \
484  EntityPropertyInfo propertyInfo = EntityPropertyInfo(P, M, X); \
485  _propertyInfos[#n] = propertyInfo; \
486  _enumsToPropertyStrings[P] = #n; \
487  }
488 
489 #define ADD_GROUP_PROPERTY_TO_MAP(P, G, g, N, n) \
490  { \
491  EntityPropertyInfo propertyInfo = EntityPropertyInfo(P); \
492  _propertyInfos[#g "." #n] = propertyInfo; \
493  _propertyInfos[#g].propertyEnums << P; \
494  _enumsToPropertyStrings[P] = #g "." #n; \
495  }
496 
497 #define ADD_GROUP_PROPERTY_TO_MAP_WITH_RANGE(P, G, g, N, n, M, X) \
498  { \
499  EntityPropertyInfo propertyInfo = EntityPropertyInfo(P, M, X); \
500  _propertyInfos[#g "." #n] = propertyInfo; \
501  _propertyInfos[#g].propertyEnums << P; \
502  _enumsToPropertyStrings[P] = #g "." #n; \
503  }
504 
505 #define DEFINE_CORE(N, n, T, V) \
506  public: \
507  bool n##Changed() const { return _##n##Changed; } \
508  void set##N##Changed(bool value) { _##n##Changed = value; } \
509  private: \
510  T _##n = V; \
511  bool _##n##Changed { false };
512 
513 #define DEFINE_PROPERTY(P, N, n, T, V) \
514  public: \
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)
518 
519 #define DEFINE_PROPERTY_REF(P, N, n, T, V) \
520  public: \
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)
524 
525 #define DEFINE_PROPERTY_REF_WITH_SETTER(P, N, n, T, V) \
526  public: \
527  const T& get##N() const { return _##n; } \
528  void set##N(const T& value); \
529  DEFINE_CORE(N, n, T, V)
530 
531 #define DEFINE_PROPERTY_REF_WITH_SETTER_AND_GETTER(P, N, n, T, V) \
532  public: \
533  T get##N() const; \
534  void set##N(const T& value); \
535  DEFINE_CORE(N, n, T, V)
536 
537 #define DEFINE_PROPERTY_REF_ENUM(P, N, n, T, V) \
538  public: \
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)
544 
545 #define DEBUG_PROPERTY(D, P, N, n, x) \
546  D << " " << #n << ":" << P.get##N() << x << "[changed:" << P.n##Changed() << "]\n";
547 
548 #define DEBUG_PROPERTY_IF_CHANGED(D, P, N, n, x) \
549  if (P.n##Changed()) { \
550  D << " " << #n << ":" << P.get##N() << x << "\n"; \
551  }
552 
553 #endif // hifi_EntityItemPropertiesMacros_h
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