diff --git a/libraries/metavoxels/src/Bitstream.cpp b/libraries/metavoxels/src/Bitstream.cpp index d27053aefb..7595580c33 100644 --- a/libraries/metavoxels/src/Bitstream.cpp +++ b/libraries/metavoxels/src/Bitstream.cpp @@ -411,7 +411,7 @@ void Bitstream::writeRawDelta(const QScriptValue& value, const QScriptValue& ref *this << value; } } else if (reference.isObject()) { - if (value.isObject()) { + if (value.isObject()) { *this << false; for (QScriptValueIterator it(value); it.hasNext(); ) { it.next(); @@ -1401,14 +1401,17 @@ Bitstream& Bitstream::operator>(AttributePointer& attribute) { return *this; } +const QString INVALID_STRING("%INVALID%"); + Bitstream& Bitstream::operator<(const QScriptString& string) { - return *this << string.toString(); + return *this << (string.isValid() ? string.toString() : INVALID_STRING); } Bitstream& Bitstream::operator>(QScriptString& string) { QString rawString; *this >> rawString; - string = ScriptCache::getInstance()->getEngine()->toStringHandle(rawString); + string = (rawString == INVALID_STRING) ? QScriptString() : + ScriptCache::getInstance()->getEngine()->toStringHandle(rawString); return *this; } diff --git a/libraries/metavoxels/src/ScriptCache.cpp b/libraries/metavoxels/src/ScriptCache.cpp index 9de624fb29..9648a047cb 100644 --- a/libraries/metavoxels/src/ScriptCache.cpp +++ b/libraries/metavoxels/src/ScriptCache.cpp @@ -20,6 +20,7 @@ #include "ScriptCache.h" static int scriptValueMetaTypeId = qRegisterMetaType(); +static bool scriptValueComparators = QMetaType::registerComparators(); bool operator==(const QScriptValue& first, const QScriptValue& second) { if (first.isUndefined()) { @@ -97,6 +98,10 @@ bool operator!=(const QScriptValue& first, const QScriptValue& second) { return !(first == second); } +bool operator<(const QScriptValue& first, const QScriptValue& second) { + return first.lessThan(second); +} + ScriptCache* ScriptCache::getInstance() { static ScriptCache cache; return &cache; diff --git a/libraries/metavoxels/src/ScriptCache.h b/libraries/metavoxels/src/ScriptCache.h index d88a967081..5d29157b3d 100644 --- a/libraries/metavoxels/src/ScriptCache.h +++ b/libraries/metavoxels/src/ScriptCache.h @@ -69,6 +69,7 @@ Q_DECLARE_METATYPE(QScriptValue) bool operator==(const QScriptValue& first, const QScriptValue& second); bool operator!=(const QScriptValue& first, const QScriptValue& second); +bool operator<(const QScriptValue& first, const QScriptValue& second); /// A program loaded from the network. class NetworkProgram : public Resource { diff --git a/tests/metavoxels/src/MetavoxelTests.cpp b/tests/metavoxels/src/MetavoxelTests.cpp index 81f1840342..4dc1cdddce 100644 --- a/tests/metavoxels/src/MetavoxelTests.cpp +++ b/tests/metavoxels/src/MetavoxelTests.cpp @@ -11,6 +11,8 @@ #include +#include + #include #include @@ -41,6 +43,8 @@ static int streamedBytesReceived = 0; static int sharedObjectsCreated = 0; static int sharedObjectsDestroyed = 0; static int objectMutationsPerformed = 0; +static int scriptObjectsCreated = 0; +static int scriptMutationsPerformed = 0; static QByteArray createRandomBytes(int minimumSize, int maximumSize) { QByteArray bytes(randIntInRange(minimumSize, maximumSize), 0); @@ -79,6 +83,49 @@ static TestSharedObjectA::TestFlags getRandomTestFlags() { return flags; } +static QScriptValue createRandomScriptValue() { + scriptObjectsCreated++; + switch (randIntInRange(0, 3)) { + case 0: + return QScriptValue(QScriptValue::NullValue); + + case 1: + return QScriptValue(randomBoolean()); + + case 2: + return QScriptValue(randFloat()); + + case 3: + default: + return QScriptValue(QString(createRandomBytes())); + + case 4: { + int length = randIntInRange(2, 6); + QScriptValue value = ScriptCache::getInstance()->getEngine()->newArray(length); + for (int i = 0; i < length; i++) { + value.setProperty(i, createRandomScriptValue()); + } + return value; + } + case 5: { + QScriptValue value = ScriptCache::getInstance()->getEngine()->newObject(); + if (randomBoolean()) { + value.setProperty("foo", createRandomScriptValue()); + } + if (randomBoolean()) { + value.setProperty("bar", createRandomScriptValue()); + } + if (randomBoolean()) { + value.setProperty("baz", createRandomScriptValue()); + } + if (randomBoolean()) { + value.setProperty("bong", createRandomScriptValue()); + } + return value; + } + } +} + static TestMessageC createRandomMessageC() { TestMessageC message; message.foo = randomBoolean(); @@ -86,6 +133,7 @@ static TestMessageC createRandomMessageC() { message.baz = randFloat(); message.bong.foo = createRandomBytes(); message.bong.baz = getRandomTestEnum(); + message.bizzle = createRandomScriptValue(); return message; } @@ -201,6 +249,7 @@ bool MetavoxelTests::run() { datagramsReceived << "with" << bytesReceived << "bytes"; qDebug() << "Created" << sharedObjectsCreated << "shared objects, destroyed" << sharedObjectsDestroyed; qDebug() << "Performed" << objectMutationsPerformed << "object mutations"; + qDebug() << "Created" << scriptObjectsCreated << "script objects, mutated" << scriptMutationsPerformed; qDebug(); qDebug() << "Running serialization tests..."; @@ -284,7 +333,7 @@ static QVariant createRandomMessage() { } static SharedObjectPointer mutate(const SharedObjectPointer& state) { - switch(randIntInRange(0, 3)) { + switch (randIntInRange(0, 4)) { case 0: { SharedObjectPointer newState = state->clone(true); static_cast(newState.data())->setFoo(randFloat()); @@ -303,6 +352,38 @@ static SharedObjectPointer mutate(const SharedObjectPointer& state) { objectMutationsPerformed++; return newState; } + case 3: { + SharedObjectPointer newState = state->clone(true); + QScriptValue oldValue = static_cast(newState.data())->getBizzle(); + QScriptValue newValue = ScriptCache::getInstance()->getEngine()->newObject(); + for (QScriptValueIterator it(oldValue); it.hasNext(); ) { + it.next(); + newValue.setProperty(it.scriptName(), it.value()); + } + switch (randIntInRange(0, 3)) { + case 0: { + QScriptValue oldArray = oldValue.property("foo"); + int oldLength = oldArray.property(ScriptCache::getInstance()->getLengthString()).toInt32(); + QScriptValue newArray = ScriptCache::getInstance()->getEngine()->newArray(oldLength); + for (int i = 0; i < oldLength; i++) { + newArray.setProperty(i, oldArray.property(i)); + } + newArray.setProperty(randIntInRange(0, oldLength - 1), createRandomScriptValue()); + break; + } + case 1: + newValue.setProperty("bar", QScriptValue(randFloat())); + break; + + default: + newValue.setProperty("baz", createRandomScriptValue()); + break; + } + static_cast(newState.data())->setBizzle(newValue); + scriptMutationsPerformed++; + objectMutationsPerformed++; + return newState; + } default: return state; } @@ -503,7 +584,10 @@ TestSharedObjectA::TestSharedObjectA(float foo, TestEnum baz, TestFlags bong) : _foo(foo), _baz(baz), _bong(bong) { - sharedObjectsCreated++; + sharedObjectsCreated++; + + _bizzle = ScriptCache::getInstance()->getEngine()->newObject(); + _bizzle.setProperty("foo", ScriptCache::getInstance()->getEngine()->newArray(4)); } TestSharedObjectA::~TestSharedObjectA() { diff --git a/tests/metavoxels/src/MetavoxelTests.h b/tests/metavoxels/src/MetavoxelTests.h index 345ea624df..ac9eda2659 100644 --- a/tests/metavoxels/src/MetavoxelTests.h +++ b/tests/metavoxels/src/MetavoxelTests.h @@ -16,6 +16,7 @@ #include #include +#include class SequencedTestMessage; @@ -96,7 +97,8 @@ class TestSharedObjectA : public SharedObject { Q_PROPERTY(float foo READ getFoo WRITE setFoo NOTIFY fooChanged) Q_PROPERTY(TestEnum baz READ getBaz WRITE setBaz) Q_PROPERTY(TestFlags bong READ getBong WRITE setBong) - + Q_PROPERTY(QScriptValue bizzle READ getBizzle WRITE setBizzle) + public: enum TestEnum { FIRST_TEST_ENUM, SECOND_TEST_ENUM, THIRD_TEST_ENUM }; @@ -116,6 +118,9 @@ public: void setBong(TestFlags bong) { _bong = bong; } TestFlags getBong() const { return _bong; } + void setBizzle(const QScriptValue& bizzle) { _bizzle = bizzle; } + const QScriptValue& getBizzle() const { return _bizzle; } + signals: void fooChanged(float foo); @@ -125,6 +130,7 @@ private: float _foo; TestEnum _baz; TestFlags _bong; + QScriptValue _bizzle; }; DECLARE_ENUM_METATYPE(TestSharedObjectA, TestEnum) @@ -204,6 +210,7 @@ class TestMessageC : STREAM public TestMessageA { public: STREAM TestMessageB bong; + STREAM QScriptValue bizzle; }; DECLARE_STREAMABLE_METATYPE(TestMessageC)