History

isolate calls to the QtScript libraries to an interface we control

Heather Anderson committed 5 years ago

Commit 1e018db1 parent 713b29e260 files · +6904 −5064Browse files

Showing the changes to libraries/script-engine/src/ScriptValueUtils.cpp (1 of 260 files). Show all

Unified · Split

libraries/script-engine/src/ScriptValueUtils.cpp+888−0
@@ -0,0 +1,888 @@
1//
2// ScriptValueUtils.cpp
3// libraries/shared/src
4//
5// Created by Anthony Thibault on 4/15/16.
6// Copyright 2016 High Fidelity, Inc.
7//
8// Utilities for working with QtScriptValues
9//
10// Distributed under the Apache License, Version 2.0.
11// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
12//
13
14#include "ScriptValueUtils.h"
15
16#include <QtCore/QVariant>
17#include <QtGui/QColor>
18#include <QtCore/QRect>
19#include <QtCore/QUrl>
20#include <QtCore/QUuid>
21
22#include <AACube.h>
23#include <shared/MiniPromises.h>
24#include <RegisteredMetaTypes.h>
25
26#include "ScriptEngine.h"
27#include "ScriptEngineCast.h"
28#include "ScriptValueIterator.h"
29
30bool isListOfStrings(const ScriptValuePointer& arg) {
31 if (!arg->isArray()) {
32 return false;
33 }
34
35 auto lengthProperty = arg->property("length");
36 if (!lengthProperty->isNumber()) {
37 return false;
38 }
39
40 int length = lengthProperty->toInt32();
41 for (int i = 0; i < length; i++) {
42 if (!arg->property(i)->isString()) {
43 return false;
44 }
45 }
46
47 return true;
48}
49
50void registerMetaTypes(ScriptEngine* engine) {
51 scriptRegisterMetaType(engine, vec2ToScriptValue, vec2FromScriptValue);
52 scriptRegisterMetaType(engine, vec3ToScriptValue, vec3FromScriptValue);
53 scriptRegisterMetaType(engine, u8vec3ToScriptValue, u8vec3FromScriptValue);
54 scriptRegisterMetaType(engine, vec4toScriptValue, vec4FromScriptValue);
55 scriptRegisterMetaType(engine, quatToScriptValue, quatFromScriptValue);
56 scriptRegisterMetaType(engine, mat4toScriptValue, mat4FromScriptValue);
57
58 scriptRegisterMetaType(engine, qVectorVec3ToScriptValue, qVectorVec3FromScriptValue);
59 scriptRegisterMetaType(engine, qVectorQuatToScriptValue, qVectorQuatFromScriptValue);
60 scriptRegisterMetaType(engine, qVectorBoolToScriptValue, qVectorBoolFromScriptValue);
61 scriptRegisterMetaType(engine, qVectorFloatToScriptValue, qVectorFloatFromScriptValue);
62 scriptRegisterMetaType(engine, qVectorIntToScriptValue, qVectorIntFromScriptValue);
63 scriptRegisterMetaType(engine, qVectorQUuidToScriptValue, qVectorQUuidFromScriptValue);
64
65 scriptRegisterMetaType(engine, qSizeFToScriptValue, qSizeFFromScriptValue);
66 scriptRegisterMetaType(engine, qRectToScriptValue, qRectFromScriptValue);
67 scriptRegisterMetaType(engine, qURLToScriptValue, qURLFromScriptValue);
68 scriptRegisterMetaType(engine, qColorToScriptValue, qColorFromScriptValue);
69
70 scriptRegisterMetaType(engine, pickRayToScriptValue, pickRayFromScriptValue);
71 scriptRegisterMetaType(engine, collisionToScriptValue, collisionFromScriptValue);
72 scriptRegisterMetaType(engine, quuidToScriptValue, quuidFromScriptValue);
73 scriptRegisterMetaType(engine, aaCubeToScriptValue, aaCubeFromScriptValue);
74
75 scriptRegisterMetaType(engine, stencilMaskModeToScriptValue, stencilMaskModeFromScriptValue);
76
77 scriptRegisterMetaType(engine, promiseToScriptValue, promiseFromScriptValue);
78
79 scriptRegisterSequenceMetaType<QVector<unsigned int>>(engine);
80}
81
82ScriptValuePointer vec2ToScriptValue(ScriptEngine* engine, const glm::vec2& vec2) {
83 auto prototype = engine->globalObject()->property("__hifi_vec2__");
84 if (!prototype->property("defined")->toBool()) {
85 prototype = engine->evaluate(
86 "__hifi_vec2__ = Object.defineProperties({}, { "
87 "defined: { value: true },"
88 "0: { set: function(nv) { return this.x = nv; }, get: function() { return this.x; } },"
89 "1: { set: function(nv) { return this.y = nv; }, get: function() { return this.y; } },"
90 "u: { set: function(nv) { return this.x = nv; }, get: function() { return this.x; } },"
91 "v: { set: function(nv) { return this.y = nv; }, get: function() { return this.y; } }"
92 "})");
93 }
94 ScriptValuePointer value = engine->newObject();
95 value->setProperty("x", vec2.x);
96 value->setProperty("y", vec2.y);
97 value->setPrototype(prototype);
98 return value;
99}
100
101void vec2FromScriptValue(const ScriptValuePointer& object, glm::vec2& vec2) {
102 if (object->isNumber()) {
103 vec2 = glm::vec2(object->toVariant().toFloat());
104 } else if (object->isArray()) {
105 QVariantList list = object->toVariant().toList();
106 if (list.length() == 2) {
107 vec2.x = list[0].toFloat();
108 vec2.y = list[1].toFloat();
109 }
110 } else {
111 ScriptValuePointer x = object->property("x");
112 if (!x->isValid()) {
113 x = object->property("u");
114 }
115
116 ScriptValuePointer y = object->property("y");
117 if (!y->isValid()) {
118 y = object->property("v");
119 }
120
121 vec2.x = x->toVariant().toFloat();
122 vec2.y = y->toVariant().toFloat();
123 }
124}
125
126ScriptValuePointer vec3ToScriptValue(ScriptEngine* engine, const glm::vec3& vec3) {
127 auto prototype = engine->globalObject()->property("__hifi_vec3__");
128 if (!prototype->property("defined")->toBool()) {
129 prototype = engine->evaluate(
130 "__hifi_vec3__ = Object.defineProperties({}, { "
131 "defined: { value: true },"
132 "0: { set: function(nv) { return this.x = nv; }, get: function() { return this.x; } },"
133 "1: { set: function(nv) { return this.y = nv; }, get: function() { return this.y; } },"
134 "2: { set: function(nv) { return this.z = nv; }, get: function() { return this.z; } },"
135 "r: { set: function(nv) { return this.x = nv; }, get: function() { return this.x; } },"
136 "g: { set: function(nv) { return this.y = nv; }, get: function() { return this.y; } },"
137 "b: { set: function(nv) { return this.z = nv; }, get: function() { return this.z; } },"
138 "red: { set: function(nv) { return this.x = nv; }, get: function() { return this.x; } },"
139 "green: { set: function(nv) { return this.y = nv; }, get: function() { return this.y; } },"
140 "blue: { set: function(nv) { return this.z = nv; }, get: function() { return this.z; } }"
141 "})");
142 }
143 ScriptValuePointer value = engine->newObject();
144 value->setProperty("x", vec3.x);
145 value->setProperty("y", vec3.y);
146 value->setProperty("z", vec3.z);
147 value->setPrototype(prototype);
148 return value;
149}
150
151ScriptValuePointer vec3ColorToScriptValue(ScriptEngine* engine, const glm::vec3& vec3) {
152 auto prototype = engine->globalObject()->property("__hifi_vec3_color__");
153 if (!prototype->property("defined")->toBool()) {
154 prototype = engine->evaluate(
155 "__hifi_vec3_color__ = Object.defineProperties({}, { "
156 "defined: { value: true },"
157 "0: { set: function(nv) { return this.red = nv; }, get: function() { return this.red; } },"
158 "1: { set: function(nv) { return this.green = nv; }, get: function() { return this.green; } },"
159 "2: { set: function(nv) { return this.blue = nv; }, get: function() { return this.blue; } },"
160 "r: { set: function(nv) { return this.red = nv; }, get: function() { return this.red; } },"
161 "g: { set: function(nv) { return this.green = nv; }, get: function() { return this.green; } },"
162 "b: { set: function(nv) { return this.blue = nv; }, get: function() { return this.blue; } },"
163 "x: { set: function(nv) { return this.red = nv; }, get: function() { return this.red; } },"
164 "y: { set: function(nv) { return this.green = nv; }, get: function() { return this.green; } },"
165 "z: { set: function(nv) { return this.blue = nv; }, get: function() { return this.blue; } }"
166 "})");
167 }
168 ScriptValuePointer value = engine->newObject();
169 value->setProperty("red", vec3.x);
170 value->setProperty("green", vec3.y);
171 value->setProperty("blue", vec3.z);
172 value->setPrototype(prototype);
173 return value;
174}
175
176void vec3FromScriptValue(const ScriptValuePointer& object, glm::vec3& vec3) {
177 if (object->isNumber()) {
178 vec3 = glm::vec3(object->toVariant().toFloat());
179 } else if (object->isString()) {
180 QColor qColor(object->toString());
181 if (qColor.isValid()) {
182 vec3.x = qColor.red();
183 vec3.y = qColor.green();
184 vec3.z = qColor.blue();
185 }
186 } else if (object->isArray()) {
187 QVariantList list = object->toVariant().toList();
188 if (list.length() == 3) {
189 vec3.x = list[0].toFloat();
190 vec3.y = list[1].toFloat();
191 vec3.z = list[2].toFloat();
192 }
193 } else {
194 ScriptValuePointer x = object->property("x");
195 if (!x->isValid()) {
196 x = object->property("r");
197 }
198 if (!x->isValid()) {
199 x = object->property("red");
200 }
201
202 ScriptValuePointer y = object->property("y");
203 if (!y->isValid()) {
204 y = object->property("g");
205 }
206 if (!y->isValid()) {
207 y = object->property("green");
208 }
209
210 ScriptValuePointer z = object->property("z");
211 if (!z->isValid()) {
212 z = object->property("b");
213 }
214 if (!z->isValid()) {
215 z = object->property("blue");
216 }
217
218 vec3.x = x->toVariant().toFloat();
219 vec3.y = y->toVariant().toFloat();
220 vec3.z = z->toVariant().toFloat();
221 }
222}
223
224ScriptValuePointer u8vec3ToScriptValue(ScriptEngine* engine, const glm::u8vec3& vec3) {
225 auto prototype = engine->globalObject()->property("__hifi_u8vec3__");
226 if (!prototype->property("defined")->toBool()) {
227 prototype = engine->evaluate(
228 "__hifi_u8vec3__ = Object.defineProperties({}, { "
229 "defined: { value: true },"
230 "0: { set: function(nv) { return this.x = nv; }, get: function() { return this.x; } },"
231 "1: { set: function(nv) { return this.y = nv; }, get: function() { return this.y; } },"
232 "2: { set: function(nv) { return this.z = nv; }, get: function() { return this.z; } },"
233 "r: { set: function(nv) { return this.x = nv; }, get: function() { return this.x; } },"
234 "g: { set: function(nv) { return this.y = nv; }, get: function() { return this.y; } },"
235 "b: { set: function(nv) { return this.z = nv; }, get: function() { return this.z; } },"
236 "red: { set: function(nv) { return this.x = nv; }, get: function() { return this.x; } },"
237 "green: { set: function(nv) { return this.y = nv; }, get: function() { return this.y; } },"
238 "blue: { set: function(nv) { return this.z = nv; }, get: function() { return this.z; } }"
239 "})");
240 }
241 ScriptValuePointer value = engine->newObject();
242 value->setProperty("x", vec3.x);
243 value->setProperty("y", vec3.y);
244 value->setProperty("z", vec3.z);
245 value->setPrototype(prototype);
246 return value;
247}
248
249ScriptValuePointer u8vec3ColorToScriptValue(ScriptEngine* engine, const glm::u8vec3& vec3) {
250 auto prototype = engine->globalObject()->property("__hifi_u8vec3_color__");
251 if (!prototype->property("defined")->toBool()) {
252 prototype = engine->evaluate(
253 "__hifi_u8vec3_color__ = Object.defineProperties({}, { "
254 "defined: { value: true },"
255 "0: { set: function(nv) { return this.red = nv; }, get: function() { return this.red; } },"
256 "1: { set: function(nv) { return this.green = nv; }, get: function() { return this.green; } },"
257 "2: { set: function(nv) { return this.blue = nv; }, get: function() { return this.blue; } },"
258 "r: { set: function(nv) { return this.red = nv; }, get: function() { return this.red; } },"
259 "g: { set: function(nv) { return this.green = nv; }, get: function() { return this.green; } },"
260 "b: { set: function(nv) { return this.blue = nv; }, get: function() { return this.blue; } },"
261 "x: { set: function(nv) { return this.red = nv; }, get: function() { return this.red; } },"
262 "y: { set: function(nv) { return this.green = nv; }, get: function() { return this.green; } },"
263 "z: { set: function(nv) { return this.blue = nv; }, get: function() { return this.blue; } }"
264 "})");
265 }
266 ScriptValuePointer value = engine->newObject();
267 value->setProperty("red", vec3.x);
268 value->setProperty("green", vec3.y);
269 value->setProperty("blue", vec3.z);
270 value->setPrototype(prototype);
271 return value;
272}
273
274void u8vec3FromScriptValue(const ScriptValuePointer& object, glm::u8vec3& vec3) {
275 if (object->isNumber()) {
276 vec3 = glm::vec3(object->toVariant().toUInt());
277 } else if (object->isString()) {
278 QColor qColor(object->toString());
279 if (qColor.isValid()) {
280 vec3.x = (uint8_t)qColor.red();
281 vec3.y = (uint8_t)qColor.green();
282 vec3.z = (uint8_t)qColor.blue();
283 }
284 } else if (object->isArray()) {
285 QVariantList list = object->toVariant().toList();
286 if (list.length() == 3) {
287 vec3.x = list[0].toUInt();
288 vec3.y = list[1].toUInt();
289 vec3.z = list[2].toUInt();
290 }
291 } else {
292 ScriptValuePointer x = object->property("x");
293 if (!x->isValid()) {
294 x = object->property("r");
295 }
296 if (!x->isValid()) {
297 x = object->property("red");
298 }
299
300 ScriptValuePointer y = object->property("y");
301 if (!y->isValid()) {
302 y = object->property("g");
303 }
304 if (!y->isValid()) {
305 y = object->property("green");
306 }
307
308 ScriptValuePointer z = object->property("z");
309 if (!z->isValid()) {
310 z = object->property("b");
311 }
312 if (!z->isValid()) {
313 z = object->property("blue");
314 }
315
316 vec3.x = x->toVariant().toUInt();
317 vec3.y = y->toVariant().toUInt();
318 vec3.z = z->toVariant().toUInt();
319 }
320}
321
322ScriptValuePointer vec4toScriptValue(ScriptEngine* engine, const glm::vec4& vec4) {
323 ScriptValuePointer obj = engine->newObject();
324 obj->setProperty("x", vec4.x);
325 obj->setProperty("y", vec4.y);
326 obj->setProperty("z", vec4.z);
327 obj->setProperty("w", vec4.w);
328 return obj;
329}
330
331void vec4FromScriptValue(const ScriptValuePointer& object, glm::vec4& vec4) {
332 vec4.x = object->property("x")->toVariant().toFloat();
333 vec4.y = object->property("y")->toVariant().toFloat();
334 vec4.z = object->property("z")->toVariant().toFloat();
335 vec4.w = object->property("w")->toVariant().toFloat();
336}
337
338ScriptValuePointer mat4toScriptValue(ScriptEngine* engine, const glm::mat4& mat4) {
339 ScriptValuePointer obj = engine->newObject();
340 obj->setProperty("r0c0", mat4[0][0]);
341 obj->setProperty("r1c0", mat4[0][1]);
342 obj->setProperty("r2c0", mat4[0][2]);
343 obj->setProperty("r3c0", mat4[0][3]);
344 obj->setProperty("r0c1", mat4[1][0]);
345 obj->setProperty("r1c1", mat4[1][1]);
346 obj->setProperty("r2c1", mat4[1][2]);
347 obj->setProperty("r3c1", mat4[1][3]);
348 obj->setProperty("r0c2", mat4[2][0]);
349 obj->setProperty("r1c2", mat4[2][1]);
350 obj->setProperty("r2c2", mat4[2][2]);
351 obj->setProperty("r3c2", mat4[2][3]);
352 obj->setProperty("r0c3", mat4[3][0]);
353 obj->setProperty("r1c3", mat4[3][1]);
354 obj->setProperty("r2c3", mat4[3][2]);
355 obj->setProperty("r3c3", mat4[3][3]);
356 return obj;
357}
358
359void mat4FromScriptValue(const ScriptValuePointer& object, glm::mat4& mat4) {
360 mat4[0][0] = object->property("r0c0")->toVariant().toFloat();
361 mat4[0][1] = object->property("r1c0")->toVariant().toFloat();
362 mat4[0][2] = object->property("r2c0")->toVariant().toFloat();
363 mat4[0][3] = object->property("r3c0")->toVariant().toFloat();
364 mat4[1][0] = object->property("r0c1")->toVariant().toFloat();
365 mat4[1][1] = object->property("r1c1")->toVariant().toFloat();
366 mat4[1][2] = object->property("r2c1")->toVariant().toFloat();
367 mat4[1][3] = object->property("r3c1")->toVariant().toFloat();
368 mat4[2][0] = object->property("r0c2")->toVariant().toFloat();
369 mat4[2][1] = object->property("r1c2")->toVariant().toFloat();
370 mat4[2][2] = object->property("r2c2")->toVariant().toFloat();
371 mat4[2][3] = object->property("r3c2")->toVariant().toFloat();
372 mat4[3][0] = object->property("r0c3")->toVariant().toFloat();
373 mat4[3][1] = object->property("r1c3")->toVariant().toFloat();
374 mat4[3][2] = object->property("r2c3")->toVariant().toFloat();
375 mat4[3][3] = object->property("r3c3")->toVariant().toFloat();
376}
377
378ScriptValuePointer qVectorVec3ColorToScriptValue(ScriptEngine* engine, const QVector<glm::vec3>& vector) {
379 ScriptValuePointer array = engine->newArray();
380 for (int i = 0; i < vector.size(); i++) {
381 array->setProperty(i, vec3ColorToScriptValue(engine, vector.at(i)));
382 }
383 return array;
384}
385
386ScriptValuePointer qVectorVec3ToScriptValue(ScriptEngine* engine, const QVector<glm::vec3>& vector) {
387 ScriptValuePointer array = engine->newArray();
388 for (int i = 0; i < vector.size(); i++) {
389 array->setProperty(i, vec3ToScriptValue(engine, vector.at(i)));
390 }
391 return array;
392}
393
394QVector<glm::vec3> qVectorVec3FromScriptValue(const ScriptValuePointer& array) {
395 QVector<glm::vec3> newVector;
396 int length = array->property("length")->toInteger();
397
398 for (int i = 0; i < length; i++) {
399 glm::vec3 newVec3 = glm::vec3();
400 vec3FromScriptValue(array->property(i), newVec3);
401 newVector << newVec3;
402 }
403 return newVector;
404}
405
406void qVectorVec3FromScriptValue(const ScriptValuePointer& array, QVector<glm::vec3>& vector) {
407 int length = array->property("length")->toInteger();
408
409 for (int i = 0; i < length; i++) {
410 glm::vec3 newVec3 = glm::vec3();
411 vec3FromScriptValue(array->property(i), newVec3);
412 vector << newVec3;
413 }
414}
415
416ScriptValuePointer quatToScriptValue(ScriptEngine* engine, const glm::quat& quat) {
417 ScriptValuePointer obj = engine->newObject();
418 if (quat.x != quat.x || quat.y != quat.y || quat.z != quat.z || quat.w != quat.w) {
419 // if quat contains a NaN don't try to convert it
420 return obj;
421 }
422 obj->setProperty("x", quat.x);
423 obj->setProperty("y", quat.y);
424 obj->setProperty("z", quat.z);
425 obj->setProperty("w", quat.w);
426 return obj;
427}
428
429void quatFromScriptValue(const ScriptValuePointer& object, glm::quat& quat) {
430 quat.x = object->property("x")->toVariant().toFloat();
431 quat.y = object->property("y")->toVariant().toFloat();
432 quat.z = object->property("z")->toVariant().toFloat();
433 quat.w = object->property("w")->toVariant().toFloat();
434
435 // enforce normalized quaternion
436 float length = glm::length(quat);
437 if (length > FLT_EPSILON) {
438 quat /= length;
439 } else {
440 quat = glm::quat();
441 }
442}
443
444ScriptValuePointer qVectorQuatToScriptValue(ScriptEngine* engine, const QVector<glm::quat>& vector) {
445 ScriptValuePointer array = engine->newArray();
446 for (int i = 0; i < vector.size(); i++) {
447 array->setProperty(i, quatToScriptValue(engine, vector.at(i)));
448 }
449 return array;
450}
451
452ScriptValuePointer qVectorBoolToScriptValue(ScriptEngine* engine, const QVector<bool>& vector) {
453 ScriptValuePointer array = engine->newArray();
454 for (int i = 0; i < vector.size(); i++) {
455 array->setProperty(i, vector.at(i));
456 }
457 return array;
458}
459
460QVector<float> qVectorFloatFromScriptValue(const ScriptValuePointer& array) {
461 if (!array->isArray()) {
462 return QVector<float>();
463 }
464 QVector<float> newVector;
465 int length = array->property("length")->toInteger();
466 newVector.reserve(length);
467 for (int i = 0; i < length; i++) {
468 if (array->property(i)->isNumber()) {
469 newVector << array->property(i)->toNumber();
470 }
471 }
472
473 return newVector;
474}
475
476ScriptValuePointer qVectorQUuidToScriptValue(ScriptEngine* engine, const QVector<QUuid>& vector) {
477 ScriptValuePointer array = engine->newArray();
478 for (int i = 0; i < vector.size(); i++) {
479 array->setProperty(i, quuidToScriptValue(engine, vector.at(i)));
480 }
481 return array;
482}
483
484void qVectorQUuidFromScriptValue(const ScriptValuePointer& array, QVector<QUuid>& vector) {
485 int length = array->property("length")->toInteger();
486
487 for (int i = 0; i < length; i++) {
488 vector << array->property(i)->toVariant().toUuid();
489 }
490}
491
492QVector<QUuid> qVectorQUuidFromScriptValue(const ScriptValuePointer& array) {
493 if (!array->isArray()) {
494 return QVector<QUuid>();
495 }
496 QVector<QUuid> newVector;
497 int length = array->property("length")->toInteger();
498 newVector.reserve(length);
499 for (int i = 0; i < length; i++) {
500 QString uuidAsString = array->property(i)->toString();
501 QUuid fromString(uuidAsString);
502 newVector << fromString;
503 }
504 return newVector;
505}
506
507ScriptValuePointer qVectorFloatToScriptValue(ScriptEngine* engine, const QVector<float>& vector) {
508 ScriptValuePointer array = engine->newArray();
509 for (int i = 0; i < vector.size(); i++) {
510 float num = vector.at(i);
511 array->setProperty(i, engine->newValue(num));
512 }
513 return array;
514}
515
516ScriptValuePointer qVectorIntToScriptValue(ScriptEngine* engine, const QVector<uint32_t>& vector) {
517 ScriptValuePointer array = engine->newArray();
518 for (int i = 0; i < vector.size(); i++) {
519 int num = vector.at(i);
520 array->setProperty(i, engine->newValue(num));
521 }
522 return array;
523}
524
525void qVectorFloatFromScriptValue(const ScriptValuePointer& array, QVector<float>& vector) {
526 int length = array->property("length")->toInteger();
527
528 for (int i = 0; i < length; i++) {
529 vector << array->property(i)->toVariant().toFloat();
530 }
531}
532
533void qVectorIntFromScriptValue(const ScriptValuePointer& array, QVector<uint32_t>& vector) {
534 int length = array->property("length")->toInteger();
535
536 for (int i = 0; i < length; i++) {
537 vector << array->property(i)->toVariant().toInt();
538 }
539}
540
541QVector<glm::quat> qVectorQuatFromScriptValue(const ScriptValuePointer& array) {
542 QVector<glm::quat> newVector;
543 int length = array->property("length")->toInteger();
544
545 for (int i = 0; i < length; i++) {
546 glm::quat newQuat = glm::quat();
547 quatFromScriptValue(array->property(i), newQuat);
548 newVector << newQuat;
549 }
550 return newVector;
551}
552
553void qVectorQuatFromScriptValue(const ScriptValuePointer& array, QVector<glm::quat>& vector) {
554 int length = array->property("length")->toInteger();
555
556 for (int i = 0; i < length; i++) {
557 glm::quat newQuat = glm::quat();
558 quatFromScriptValue(array->property(i), newQuat);
559 vector << newQuat;
560 }
561}
562
563QVector<bool> qVectorBoolFromScriptValue(const ScriptValuePointer& array) {
564 QVector<bool> newVector;
565 int length = array->property("length")->toInteger();
566
567 for (int i = 0; i < length; i++) {
568 newVector << array->property(i)->toBool();
569 }
570 return newVector;
571}
572
573void qVectorBoolFromScriptValue(const ScriptValuePointer& array, QVector<bool>& vector) {
574 int length = array->property("length")->toInteger();
575
576 for (int i = 0; i < length; i++) {
577 vector << array->property(i)->toBool();
578 }
579}
580
581ScriptValuePointer qRectToScriptValue(ScriptEngine* engine, const QRect& rect) {
582 ScriptValuePointer obj = engine->newObject();
583 obj->setProperty("x", rect.x());
584 obj->setProperty("y", rect.y());
585 obj->setProperty("width", rect.width());
586 obj->setProperty("height", rect.height());
587 return obj;
588}
589
590void qRectFromScriptValue(const ScriptValuePointer& object, QRect& rect) {
591 rect.setX(object->property("x")->toVariant().toInt());
592 rect.setY(object->property("y")->toVariant().toInt());
593 rect.setWidth(object->property("width")->toVariant().toInt());
594 rect.setHeight(object->property("height")->toVariant().toInt());
595}
596
597ScriptValuePointer qRectFToScriptValue(ScriptEngine* engine, const QRectF& rect) {
598 ScriptValuePointer obj = engine->newObject();
599 obj->setProperty("x", rect.x());
600 obj->setProperty("y", rect.y());
601 obj->setProperty("width", rect.width());
602 obj->setProperty("height", rect.height());
603 return obj;
604}
605
606void qRectFFromScriptValue(const ScriptValuePointer& object, QRectF& rect) {
607 rect.setX(object->property("x")->toVariant().toFloat());
608 rect.setY(object->property("y")->toVariant().toFloat());
609 rect.setWidth(object->property("width")->toVariant().toFloat());
610 rect.setHeight(object->property("height")->toVariant().toFloat());
611}
612
613ScriptValuePointer qColorToScriptValue(ScriptEngine* engine, const QColor& color) {
614 ScriptValuePointer object = engine->newObject();
615 object->setProperty("red", color.red());
616 object->setProperty("green", color.green());
617 object->setProperty("blue", color.blue());
618 object->setProperty("alpha", color.alpha());
619 return object;
620}
621
622/**jsdoc
623 * An axis-aligned cube, defined as the bottom right near (minimum axes values) corner of the cube plus the dimension of its
624 * sides.
625 * @typedef {object} AACube
626 * @property {number} x - X coordinate of the brn corner of the cube.
627 * @property {number} y - Y coordinate of the brn corner of the cube.
628 * @property {number} z - Z coordinate of the brn corner of the cube.
629 * @property {number} scale - The dimensions of each side of the cube.
630 */
631ScriptValuePointer aaCubeToScriptValue(ScriptEngine* engine, const AACube& aaCube) {
632 ScriptValuePointer obj = engine->newObject();
633 const glm::vec3& corner = aaCube.getCorner();
634 obj->setProperty("x", corner.x);
635 obj->setProperty("y", corner.y);
636 obj->setProperty("z", corner.z);
637 obj->setProperty("scale", aaCube.getScale());
638 return obj;
639}
640
641void aaCubeFromScriptValue(const ScriptValuePointer& object, AACube& aaCube) {
642 glm::vec3 corner;
643 corner.x = object->property("x")->toVariant().toFloat();
644 corner.y = object->property("y")->toVariant().toFloat();
645 corner.z = object->property("z")->toVariant().toFloat();
646 float scale = object->property("scale")->toVariant().toFloat();
647
648 aaCube.setBox(corner, scale);
649}
650
651void qColorFromScriptValue(const ScriptValuePointer& object, QColor& color) {
652 if (object->isNumber()) {
653 color.setRgb(object->toUInt32());
654
655 } else if (object->isString()) {
656 color.setNamedColor(object->toString());
657
658 } else {
659 ScriptValuePointer alphaValue = object->property("alpha");
660 color.setRgb(object->property("red")->toInt32(), object->property("green")->toInt32(), object->property("blue")->toInt32(),
661 alphaValue->isNumber() ? alphaValue->toInt32() : 255);
662 }
663}
664
665ScriptValuePointer qURLToScriptValue(ScriptEngine* engine, const QUrl& url) {
666 return engine->newValue(url.toString());
667}
668
669void qURLFromScriptValue(const ScriptValuePointer& object, QUrl& url) {
670 url = object->toString();
671}
672
673ScriptValuePointer pickRayToScriptValue(ScriptEngine* engine, const PickRay& pickRay) {
674 ScriptValuePointer obj = engine->newObject();
675 ScriptValuePointer origin = vec3ToScriptValue(engine, pickRay.origin);
676 obj->setProperty("origin", origin);
677 ScriptValuePointer direction = vec3ToScriptValue(engine, pickRay.direction);
678 obj->setProperty("direction", direction);
679 return obj;
680}
681
682void pickRayFromScriptValue(const ScriptValuePointer& object, PickRay& pickRay) {
683 ScriptValuePointer originValue = object->property("origin");
684 if (originValue->isValid()) {
685 auto x = originValue->property("x");
686 auto y = originValue->property("y");
687 auto z = originValue->property("z");
688 if (x->isValid() && y->isValid() && z->isValid()) {
689 pickRay.origin.x = x->toVariant().toFloat();
690 pickRay.origin.y = y->toVariant().toFloat();
691 pickRay.origin.z = z->toVariant().toFloat();
692 }
693 }
694 ScriptValuePointer directionValue = object->property("direction");
695 if (directionValue->isValid()) {
696 auto x = directionValue->property("x");
697 auto y = directionValue->property("y");
698 auto z = directionValue->property("z");
699 if (x->isValid() && y->isValid() && z->isValid()) {
700 pickRay.direction.x = x->toVariant().toFloat();
701 pickRay.direction.y = y->toVariant().toFloat();
702 pickRay.direction.z = z->toVariant().toFloat();
703 }
704 }
705}
706
707/**jsdoc
708 * Details of a collision between avatars and entities.
709 * @typedef {object} Collision
710 * @property {ContactEventType} type - The contact type of the collision event.
711 * @property {Uuid} idA - The ID of one of the avatars or entities in the collision.
712 * @property {Uuid} idB - The ID of the other of the avatars or entities in the collision.
713 * @property {Vec3} penetration - The amount of penetration between the two items.
714 * @property {Vec3} contactPoint - The point of contact.
715 * @property {Vec3} velocityChange - The change in relative velocity of the two items, in m/s.
716 */
717ScriptValuePointer collisionToScriptValue(ScriptEngine* engine, const Collision& collision) {
718 ScriptValuePointer obj = engine->newObject();
719 obj->setProperty("type", collision.type);
720 obj->setProperty("idA", quuidToScriptValue(engine, collision.idA));
721 obj->setProperty("idB", quuidToScriptValue(engine, collision.idB));
722 obj->setProperty("penetration", vec3ToScriptValue(engine, collision.penetration));
723 obj->setProperty("contactPoint", vec3ToScriptValue(engine, collision.contactPoint));
724 obj->setProperty("velocityChange", vec3ToScriptValue(engine, collision.velocityChange));
725 return obj;
726}
727
728void collisionFromScriptValue(const ScriptValuePointer& object, Collision& collision) {
729 // TODO: implement this when we know what it means to accept collision events from JS
730}
731
732ScriptValuePointer quuidToScriptValue(ScriptEngine* engine, const QUuid& uuid) {
733 if (uuid.isNull()) {
734 return engine->nullValue();
735 }
736 ScriptValuePointer obj(engine->newValue(uuid.toString()));
737 return obj;
738}
739
740void quuidFromScriptValue(const ScriptValuePointer& object, QUuid& uuid) {
741 if (object.isNull()) {
742 uuid = QUuid();
743 return;
744 }
745 QString uuidAsString = object->toVariant().toString();
746 QUuid fromString(uuidAsString);
747 uuid = fromString;
748}
749
750/**jsdoc
751 * A 2D size value.
752 * @typedef {object} Size
753 * @property {number} height - The height value.
754 * @property {number} width - The width value.
755 */
756ScriptValuePointer qSizeFToScriptValue(ScriptEngine* engine, const QSizeF& qSizeF) {
757 ScriptValuePointer obj = engine->newObject();
758 obj->setProperty("width", qSizeF.width());
759 obj->setProperty("height", qSizeF.height());
760 return obj;
761}
762
763void qSizeFFromScriptValue(const ScriptValuePointer& object, QSizeF& qSizeF) {
764 qSizeF.setWidth(object->property("width")->toVariant().toFloat());
765 qSizeF.setHeight(object->property("height")->toVariant().toFloat());
766}
767
768/**jsdoc
769 * The details of an animation that is playing.
770 * @typedef {object} Avatar.AnimationDetails
771 * @property {string} role - <em>Not used.</em>
772 * @property {string} url - The URL to the animation file. Animation files need to be in glTF or FBX format but only need to
773 * contain the avatar skeleton and animation data. glTF models may be in JSON or binary format (".gltf" or ".glb" URLs
774 * respectively).
775 * <p><strong>Warning:</strong> glTF animations currently do not always animate correctly.</p>
776 * @property {number} fps - The frames per second(FPS) rate for the animation playback. 30 FPS is normal speed.
777 * @property {number} priority - <em>Not used.</em>
778 * @property {boolean} loop - <code>true</code> if the animation should loop, <code>false</code> if it shouldn't.
779 * @property {boolean} hold - <em>Not used.</em>
780 * @property {number} firstFrame - The frame the animation should start at.
781 * @property {number} lastFrame - The frame the animation should stop at.
782 * @property {boolean} running - <em>Not used.</em>
783 * @property {number} currentFrame - The current frame being played.
784 * @property {boolean} startAutomatically - <em>Not used.</em>
785 * @property {boolean} allowTranslation - <em>Not used.</em>
786 */
787ScriptValuePointer animationDetailsToScriptValue(ScriptEngine* engine, const AnimationDetails& details) {
788 ScriptValuePointer obj = engine->newObject();
789 obj->setProperty("role", details.role);
790 obj->setProperty("url", details.url.toString());
791 obj->setProperty("fps", details.fps);
792 obj->setProperty("priority", details.priority);
793 obj->setProperty("loop", details.loop);
794 obj->setProperty("hold", details.hold);
795 obj->setProperty("startAutomatically", details.startAutomatically);
796 obj->setProperty("firstFrame", details.firstFrame);
797 obj->setProperty("lastFrame", details.lastFrame);
798 obj->setProperty("running", details.running);
799 obj->setProperty("currentFrame", details.currentFrame);
800 obj->setProperty("allowTranslation", details.allowTranslation);
801 return obj;
802}
803
804void animationDetailsFromScriptValue(const ScriptValuePointer& object, AnimationDetails& details) {
805 // nothing for now...
806}
807
808ScriptValuePointer meshToScriptValue(ScriptEngine* engine, MeshProxy* const& in) {
809 return engine->newQObject(in, ScriptEngine::QtOwnership,
810 ScriptEngine::ExcludeDeleteLater | ScriptEngine::ExcludeChildObjects);
811}
812
813void meshFromScriptValue(const ScriptValuePointer& value, MeshProxy*& out) {
814 out = qobject_cast<MeshProxy*>(value->toQObject());
815}
816
817ScriptValuePointer meshesToScriptValue(ScriptEngine* engine, const MeshProxyList& in) {
818 // ScriptValueList result;
819 ScriptValuePointer result = engine->newArray();
820 int i = 0;
821 foreach (MeshProxy* const meshProxy, in) { result->setProperty(i++, meshToScriptValue(engine, meshProxy)); }
822 return result;
823}
824
825void meshesFromScriptValue(const ScriptValuePointer& value, MeshProxyList& out) {
826 ScriptValueIteratorPointer itr(value->newIterator());
827
828 qDebug() << "in meshesFromScriptValue, value.length =" << value->property("length")->toInt32();
829
830 while (itr->hasNext()) {
831 itr->next();
832 MeshProxy* meshProxy = scriptvalue_cast<MeshProxyList::value_type>(itr->value());
833 if (meshProxy) {
834 out.append(meshProxy);
835 } else {
836 qDebug() << "null meshProxy";
837 }
838 }
839}
840
841/**jsdoc
842 * A triangle in a mesh.
843 * @typedef {object} MeshFace
844 * @property {number[]} vertices - The indexes of the three vertices that make up the face.
845 */
846ScriptValuePointer meshFaceToScriptValue(ScriptEngine* engine, const MeshFace& meshFace) {
847 ScriptValuePointer obj = engine->newObject();
848 obj->setProperty("vertices", qVectorIntToScriptValue(engine, meshFace.vertexIndices));
849 return obj;
850}
851
852void meshFaceFromScriptValue(const ScriptValuePointer& object, MeshFace& meshFaceResult) {
853 qVectorIntFromScriptValue(object->property("vertices"), meshFaceResult.vertexIndices);
854}
855
856ScriptValuePointer qVectorMeshFaceToScriptValue(ScriptEngine* engine, const QVector<MeshFace>& vector) {
857 ScriptValuePointer array = engine->newArray();
858 for (int i = 0; i < vector.size(); i++) {
859 array->setProperty(i, meshFaceToScriptValue(engine, vector.at(i)));
860 }
861 return array;
862}
863
864void qVectorMeshFaceFromScriptValue(const ScriptValuePointer& array, QVector<MeshFace>& result) {
865 int length = array->property("length")->toInteger();
866 result.clear();
867
868 for (int i = 0; i < length; i++) {
869 MeshFace meshFace = MeshFace();
870 meshFaceFromScriptValue(array->property(i), meshFace);
871 result << meshFace;
872 }
873}
874
875ScriptValuePointer stencilMaskModeToScriptValue(ScriptEngine* engine, const StencilMaskMode& stencilMode) {
876 return engine->newValue((int)stencilMode);
877}
878
879void stencilMaskModeFromScriptValue(const ScriptValuePointer& object, StencilMaskMode& stencilMode) {
880 stencilMode = StencilMaskMode(object->toVariant().toInt());
881}
882
883void promiseFromScriptValue(const ScriptValuePointer& object, std::shared_ptr<MiniPromise>& promise) {
884 Q_ASSERT(false);
885}
886ScriptValuePointer promiseToScriptValue(ScriptEngine* engine, const std::shared_ptr<MiniPromise>& promise) {
887 return engine->newQObject(promise.get());
888}