Showing the changes to libraries/script-engine/src/ScriptValueUtils.cpp (1 of 260 files). Show all
Unified · Split
| @@ -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 | |||
| 30 | bool 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 | |||
| 50 | void 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 | |||
| 82 | ScriptValuePointer 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 | |||
| 101 | void 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 | |||
| 126 | ScriptValuePointer 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 | |||
| 151 | ScriptValuePointer 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 | |||
| 176 | void 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 | |||
| 224 | ScriptValuePointer 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 | |||
| 249 | ScriptValuePointer 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 | |||
| 274 | void 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 | |||
| 322 | ScriptValuePointer 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 | |||
| 331 | void 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 | |||
| 338 | ScriptValuePointer 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 | |||
| 359 | void 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 | |||
| 378 | ScriptValuePointer 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 | |||
| 386 | ScriptValuePointer 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 | |||
| 394 | QVector<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 | |||
| 406 | void 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 | |||
| 416 | ScriptValuePointer 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 | |||
| 429 | void 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 | |||
| 444 | ScriptValuePointer 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 | |||
| 452 | ScriptValuePointer 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 | |||
| 460 | QVector<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 | |||
| 476 | ScriptValuePointer 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 | |||
| 484 | void 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 | |||
| 492 | QVector<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 | |||
| 507 | ScriptValuePointer 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 | |||
| 516 | ScriptValuePointer 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 | |||
| 525 | void 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 | |||
| 533 | void 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 | |||
| 541 | QVector<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 | |||
| 553 | void 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 | |||
| 563 | QVector<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 | |||
| 573 | void 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 | |||
| 581 | ScriptValuePointer 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 | |||
| 590 | void 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 | |||
| 597 | ScriptValuePointer 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 | |||
| 606 | void 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 | |||
| 613 | ScriptValuePointer 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 | */ | ||
| 631 | ScriptValuePointer 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 | |||
| 641 | void 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 | |||
| 651 | void 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 | |||
| 665 | ScriptValuePointer qURLToScriptValue(ScriptEngine* engine, const QUrl& url) { | ||
| 666 | return engine->newValue(url.toString()); | ||
| 667 | } | ||
| 668 | |||
| 669 | void qURLFromScriptValue(const ScriptValuePointer& object, QUrl& url) { | ||
| 670 | url = object->toString(); | ||
| 671 | } | ||
| 672 | |||
| 673 | ScriptValuePointer 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 | |||
| 682 | void 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 | */ | ||
| 717 | ScriptValuePointer 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 | |||
| 728 | void collisionFromScriptValue(const ScriptValuePointer& object, Collision& collision) { | ||
| 729 | // TODO: implement this when we know what it means to accept collision events from JS | ||
| 730 | } | ||
| 731 | |||
| 732 | ScriptValuePointer 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 | |||
| 740 | void 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 | */ | ||
| 756 | ScriptValuePointer 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 | |||
| 763 | void 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 | */ | ||
| 787 | ScriptValuePointer 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 | |||
| 804 | void animationDetailsFromScriptValue(const ScriptValuePointer& object, AnimationDetails& details) { | ||
| 805 | // nothing for now... | ||
| 806 | } | ||
| 807 | |||
| 808 | ScriptValuePointer meshToScriptValue(ScriptEngine* engine, MeshProxy* const& in) { | ||
| 809 | return engine->newQObject(in, ScriptEngine::QtOwnership, | ||
| 810 | ScriptEngine::ExcludeDeleteLater | ScriptEngine::ExcludeChildObjects); | ||
| 811 | } | ||
| 812 | |||
| 813 | void meshFromScriptValue(const ScriptValuePointer& value, MeshProxy*& out) { | ||
| 814 | out = qobject_cast<MeshProxy*>(value->toQObject()); | ||
| 815 | } | ||
| 816 | |||
| 817 | ScriptValuePointer 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 | |||
| 825 | void 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 | */ | ||
| 846 | ScriptValuePointer meshFaceToScriptValue(ScriptEngine* engine, const MeshFace& meshFace) { | ||
| 847 | ScriptValuePointer obj = engine->newObject(); | ||
| 848 | obj->setProperty("vertices", qVectorIntToScriptValue(engine, meshFace.vertexIndices)); | ||
| 849 | return obj; | ||
| 850 | } | ||
| 851 | |||
| 852 | void meshFaceFromScriptValue(const ScriptValuePointer& object, MeshFace& meshFaceResult) { | ||
| 853 | qVectorIntFromScriptValue(object->property("vertices"), meshFaceResult.vertexIndices); | ||
| 854 | } | ||
| 855 | |||
| 856 | ScriptValuePointer 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 | |||
| 864 | void 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 | |||
| 875 | ScriptValuePointer stencilMaskModeToScriptValue(ScriptEngine* engine, const StencilMaskMode& stencilMode) { | ||
| 876 | return engine->newValue((int)stencilMode); | ||
| 877 | } | ||
| 878 | |||
| 879 | void stencilMaskModeFromScriptValue(const ScriptValuePointer& object, StencilMaskMode& stencilMode) { | ||
| 880 | stencilMode = StencilMaskMode(object->toVariant().toInt()); | ||
| 881 | } | ||
| 882 | |||
| 883 | void promiseFromScriptValue(const ScriptValuePointer& object, std::shared_ptr<MiniPromise>& promise) { | ||
| 884 | Q_ASSERT(false); | ||
| 885 | } | ||
| 886 | ScriptValuePointer promiseToScriptValue(ScriptEngine* engine, const std::shared_ptr<MiniPromise>& promise) { | ||
| 887 | return engine->newQObject(promise.get()); | ||
| 888 | } | ||