From e620518d2f938c14ae36717d8ec8ced13a436852 Mon Sep 17 00:00:00 2001 From: Andrzej Kapolka Date: Fri, 6 Jun 2014 17:59:30 -0700 Subject: [PATCH 1/8] Working on streaming script values. --- libraries/metavoxels/src/Bitstream.cpp | 92 ++++++++++++++++++++++++++ libraries/metavoxels/src/Bitstream.h | 4 ++ 2 files changed, 96 insertions(+) diff --git a/libraries/metavoxels/src/Bitstream.cpp b/libraries/metavoxels/src/Bitstream.cpp index d9242ad9b7..63ef8b09bb 100644 --- a/libraries/metavoxels/src/Bitstream.cpp +++ b/libraries/metavoxels/src/Bitstream.cpp @@ -543,6 +543,98 @@ Bitstream& Bitstream::operator>>(QScriptString& string) { return *this; } +enum ScriptValueType { + INVALID_SCRIPT_VALUE, + UNDEFINED_SCRIPT_VALUE, + NULL_SCRIPT_VALUE, + BOOL_SCRIPT_VALUE, + NUMBER_SCRIPT_VALUE, + STRING_SCRIPT_VALUE, + QVARIANT_SCRIPT_VALUE, + QOBJECT_SCRIPT_VALUE, + DATE_SCRIPT_VALUE, + REGEXP_SCRIPT_VALUE, + ARRAY_SCRIPT_VALUE, + OBJECT_SCRIPT_VALUE +}; + +const int SCRIPT_VALUE_BITS = 4; + +void writeScriptValueType(Bitstream& out, ScriptValueType type) { + out.write(&type, SCRIPT_VALUE_BITS); +} + +ScriptValueType readScriptValueType(Bitstream& in) { + ScriptValueType type = (ScriptValueType)0; + in.read(&type, SCRIPT_VALUE_BITS); + return type; +} + +Bitstream& Bitstream::operator<<(const QScriptValue& value) { + if (value.isUndefined()) { + writeScriptValueType(*this, UNDEFINED_SCRIPT_VALUE); + + } else if (value.isNull()) { + writeScriptValueType(*this, NULL_SCRIPT_VALUE); + + } else if (value.isBool()) { + writeScriptValueType(*this, BOOL_SCRIPT_VALUE); + + } else if (value.isNumber()) { + writeScriptValueType(*this, NUMBER_SCRIPT_VALUE); + + } else if (value.isString()) { + writeScriptValueType(*this, STRING_SCRIPT_VALUE); + + } else if (value.isArray()) { + writeScriptValueType(*this, ARRAY_SCRIPT_VALUE); + + } else if (value.isObject()) { + writeScriptValueType(*this, OBJECT_SCRIPT_VALUE); + + } else { + writeScriptValueType(*this, INVALID_SCRIPT_VALUE); + } + return *this; +} + +Bitstream& Bitstream::operator>>(QScriptValue& value) { + switch (readScriptValueType(*this)) { + case UNDEFINED_SCRIPT_VALUE: + value = QScriptValue(QScriptValue::UndefinedValue); + break; + + case NULL_SCRIPT_VALUE: + value = QScriptValue(QScriptValue::NullValue); + break; + + case BOOL_SCRIPT_VALUE: + value = QScriptValue(); + break; + + case NUMBER_SCRIPT_VALUE: + value = QScriptValue(); + break; + + case STRING_SCRIPT_VALUE: + value = QScriptValue(); + break; + + case ARRAY_SCRIPT_VALUE: + value = QScriptValue(); + break; + + case OBJECT_SCRIPT_VALUE: + value = QScriptValue(); + break; + + default: + value = QScriptValue(); + break; + } + return *this; +} + Bitstream& Bitstream::operator<<(const SharedObjectPointer& object) { _sharedObjectStreamer << object; return *this; diff --git a/libraries/metavoxels/src/Bitstream.h b/libraries/metavoxels/src/Bitstream.h index 80adfc4e8b..3b1459109c 100644 --- a/libraries/metavoxels/src/Bitstream.h +++ b/libraries/metavoxels/src/Bitstream.h @@ -29,6 +29,7 @@ class QByteArray; class QColor; class QDataStream; +class QScriptValue; class QUrl; class Attribute; @@ -372,6 +373,9 @@ public: Bitstream& operator<<(const QScriptString& string); Bitstream& operator>>(QScriptString& string); + Bitstream& operator<<(const QScriptValue& value); + Bitstream& operator>>(QScriptValue& value); + Bitstream& operator<<(const SharedObjectPointer& object); Bitstream& operator>>(SharedObjectPointer& object); From 4d423c679c2700646d7d54bd6a4f9dd3a65d84a7 Mon Sep 17 00:00:00 2001 From: Andrzej Kapolka Date: Mon, 9 Jun 2014 10:21:55 -0700 Subject: [PATCH 2/8] Added some typedefs to simplify the various mapping types. --- libraries/metavoxels/src/Bitstream.cpp | 42 +++++++++++++------------- libraries/metavoxels/src/Bitstream.h | 20 ++++++++---- 2 files changed, 35 insertions(+), 27 deletions(-) diff --git a/libraries/metavoxels/src/Bitstream.cpp b/libraries/metavoxels/src/Bitstream.cpp index 63ef8b09bb..e621484986 100644 --- a/libraries/metavoxels/src/Bitstream.cpp +++ b/libraries/metavoxels/src/Bitstream.cpp @@ -653,7 +653,7 @@ Bitstream& Bitstream::operator<(const QMetaObject* metaObject) { if (_metadataType == NO_METADATA) { return *this; } - const QVector& propertyWriters = getPropertyWriters().value(metaObject); + const PropertyWriterVector& propertyWriters = getPropertyWriters().value(metaObject); *this << propertyWriters.size(); QCryptographicHash hash(QCryptographicHash::Md5); foreach (const PropertyWriter& propertyWriter, propertyWriters) { @@ -692,7 +692,7 @@ Bitstream& Bitstream::operator>(ObjectReader& objectReader) { } int storedPropertyCount; *this >> storedPropertyCount; - QVector properties(storedPropertyCount); + PropertyReaderVector properties(storedPropertyCount); for (int i = 0; i < storedPropertyCount; i++) { TypeReader typeReader; *this >> typeReader; @@ -711,7 +711,7 @@ Bitstream& Bitstream::operator>(ObjectReader& objectReader) { QCryptographicHash hash(QCryptographicHash::Md5); bool matches = true; if (metaObject) { - const QVector& propertyWriters = getPropertyWriters().value(metaObject); + const PropertyWriterVector& propertyWriters = getPropertyWriters().value(metaObject); if (propertyWriters.size() == properties.size()) { for (int i = 0; i < propertyWriters.size(); i++) { const PropertyWriter& propertyWriter = propertyWriters.at(i); @@ -1082,17 +1082,17 @@ QHash& Bitstream::getTypeStreamers() { return typeStreamers; } -const QHash, const TypeStreamer*>& Bitstream::getEnumStreamers() { - static QHash, const TypeStreamer*> enumStreamers = createEnumStreamers(); +const QHash& Bitstream::getEnumStreamers() { + static QHash enumStreamers = createEnumStreamers(); return enumStreamers; } -QHash, const TypeStreamer*> Bitstream::createEnumStreamers() { - QHash, const TypeStreamer*> enumStreamers; +QHash Bitstream::createEnumStreamers() { + QHash enumStreamers; foreach (const QMetaObject* metaObject, getMetaObjects()) { for (int i = 0; i < metaObject->enumeratorCount(); i++) { QMetaEnum metaEnum = metaObject->enumerator(i); - const TypeStreamer*& streamer = enumStreamers[QPair(metaEnum.scope(), metaEnum.name())]; + const TypeStreamer*& streamer = enumStreamers[ScopeNamePair(metaEnum.scope(), metaEnum.name())]; if (!streamer) { streamer = new EnumTypeStreamer(metaEnum); } @@ -1114,15 +1114,15 @@ QHash Bitstream::createEnumStreamersByName() { return enumStreamersByName; } -const QHash >& Bitstream::getPropertyReaders() { - static QHash > propertyReaders = createPropertyReaders(); +const QHash& Bitstream::getPropertyReaders() { + static QHash propertyReaders = createPropertyReaders(); return propertyReaders; } -QHash > Bitstream::createPropertyReaders() { - QHash > propertyReaders; +QHash Bitstream::createPropertyReaders() { + QHash propertyReaders; foreach (const QMetaObject* metaObject, getMetaObjects()) { - QVector& readers = propertyReaders[metaObject]; + PropertyReaderVector& readers = propertyReaders[metaObject]; for (int i = 0; i < metaObject->propertyCount(); i++) { QMetaProperty property = metaObject->property(i); if (!property.isStored()) { @@ -1131,7 +1131,7 @@ QHash > Bitstream::createPropertyRea const TypeStreamer* streamer; if (property.isEnumType()) { QMetaEnum metaEnum = property.enumerator(); - streamer = getEnumStreamers().value(QPair( + streamer = getEnumStreamers().value(ScopeNamePair( QByteArray::fromRawData(metaEnum.scope(), strlen(metaEnum.scope())), QByteArray::fromRawData(metaEnum.name(), strlen(metaEnum.name())))); } else { @@ -1145,15 +1145,15 @@ QHash > Bitstream::createPropertyRea return propertyReaders; } -const QHash >& Bitstream::getPropertyWriters() { - static QHash > propertyWriters = createPropertyWriters(); +const QHash& Bitstream::getPropertyWriters() { + static QHash propertyWriters = createPropertyWriters(); return propertyWriters; } -QHash > Bitstream::createPropertyWriters() { - QHash > propertyWriters; +QHash Bitstream::createPropertyWriters() { + QHash propertyWriters; foreach (const QMetaObject* metaObject, getMetaObjects()) { - QVector& writers = propertyWriters[metaObject]; + PropertyWriterVector& writers = propertyWriters[metaObject]; for (int i = 0; i < metaObject->propertyCount(); i++) { QMetaProperty property = metaObject->property(i); if (!property.isStored()) { @@ -1162,7 +1162,7 @@ QHash > Bitstream::createPropertyWri const TypeStreamer* streamer; if (property.isEnumType()) { QMetaEnum metaEnum = property.enumerator(); - streamer = getEnumStreamers().value(QPair( + streamer = getEnumStreamers().value(ScopeNamePair( QByteArray::fromRawData(metaEnum.scope(), strlen(metaEnum.scope())), QByteArray::fromRawData(metaEnum.name(), strlen(metaEnum.name())))); } else { @@ -1416,7 +1416,7 @@ void FieldReader::readDelta(Bitstream& in, const TypeStreamer* streamer, QVarian } ObjectReader::ObjectReader(const QByteArray& className, const QMetaObject* metaObject, - const QVector& properties) : + const PropertyReaderVector& properties) : _className(className), _metaObject(metaObject), _properties(properties) { diff --git a/libraries/metavoxels/src/Bitstream.h b/libraries/metavoxels/src/Bitstream.h index 3b1459109c..4fe136f720 100644 --- a/libraries/metavoxels/src/Bitstream.h +++ b/libraries/metavoxels/src/Bitstream.h @@ -45,6 +45,10 @@ class TypeStreamer; typedef SharedObjectPointerTemplate AttributePointer; +typedef QPair ScopeNamePair; +typedef QVector PropertyReaderVector; +typedef QVector PropertyWriterVector; + /// Streams integer identifiers that conform to the following pattern: each ID encountered in the stream is either one that /// has been sent (received) before, or is one more than the highest previously encountered ID (starting at zero). This allows /// us to use the minimum number of bits to encode the IDs. @@ -426,14 +430,18 @@ private: static QHash& getMetaObjects(); static QMultiHash& getMetaObjectSubClasses(); static QHash& getTypeStreamers(); - static const QHash, const TypeStreamer*>& getEnumStreamers(); - static QHash, const TypeStreamer*> createEnumStreamers(); + + static const QHash& getEnumStreamers(); + static QHash createEnumStreamers(); + static const QHash& getEnumStreamersByName(); static QHash createEnumStreamersByName(); - static const QHash >& getPropertyReaders(); - static QHash > createPropertyReaders(); - static const QHash >& getPropertyWriters(); - static QHash > createPropertyWriters(); + + static const QHash& getPropertyReaders(); + static QHash createPropertyReaders(); + + static const QHash& getPropertyWriters(); + static QHash createPropertyWriters(); }; template inline void Bitstream::writeDelta(const T& value, const T& reference) { From ae22aa1a215d5fa540082d346b9aff24ece51946 Mon Sep 17 00:00:00 2001 From: Andrzej Kapolka Date: Mon, 9 Jun 2014 10:53:44 -0700 Subject: [PATCH 3/8] Working on JS type streaming. --- libraries/metavoxels/src/Bitstream.cpp | 72 +++++++++++++++++++++++++- libraries/metavoxels/src/Bitstream.h | 12 +++++ 2 files changed, 83 insertions(+), 1 deletion(-) diff --git a/libraries/metavoxels/src/Bitstream.cpp b/libraries/metavoxels/src/Bitstream.cpp index e621484986..8f813adf90 100644 --- a/libraries/metavoxels/src/Bitstream.cpp +++ b/libraries/metavoxels/src/Bitstream.cpp @@ -350,6 +350,14 @@ Bitstream& Bitstream::operator>>(uint& value) { return *this; } +Bitstream& Bitstream::operator<<(qint64 value) { + return write(&value, 64); +} + +Bitstream& Bitstream::operator>>(qint64& value) { + return read(&value, 64); +} + Bitstream& Bitstream::operator<<(float value) { return write(&value, 32); } @@ -358,6 +366,14 @@ Bitstream& Bitstream::operator>>(float& value) { return read(&value, 32); } +Bitstream& Bitstream::operator<<(double value) { + return write(&value, 64); +} + +Bitstream& Bitstream::operator>>(double& value) { + return read(&value, 64); +} + Bitstream& Bitstream::operator<<(const glm::vec3& value) { return *this << value.x << value.y << value.z; } @@ -420,6 +436,36 @@ Bitstream& Bitstream::operator>>(QUrl& url) { return *this; } +Bitstream& Bitstream::operator<<(const QDateTime& dateTime) { + return *this << dateTime.toMSecsSinceEpoch(); +} + +Bitstream& Bitstream::operator>>(QDateTime& dateTime) { + qint64 msecsSinceEpoch; + *this >> msecsSinceEpoch; + dateTime = QDateTime::fromMSecsSinceEpoch(msecsSinceEpoch); + return *this; +} + +Bitstream& Bitstream::operator<<(const QRegExp& regExp) { + *this << regExp.pattern(); + + return *this; +} + +Bitstream& Bitstream::operator>>(QRegExp& regExp) { + QString pattern; + *this >> pattern; + Qt::CaseSensitivity caseSensitivity = (Qt::CaseSensitivity)0; + read(&caseSensitivity, 1); + QRegExp::PatternSyntax syntax = (QRegExp::PatternSyntax)0; + read(&syntax, 3); + + regExp = QRegExp(pattern, caseSensitivity, syntax); + + return *this; +} + Bitstream& Bitstream::operator<<(const QVariant& value) { if (!value.isValid()) { _typeStreamerStreamer << NULL; @@ -550,8 +596,9 @@ enum ScriptValueType { BOOL_SCRIPT_VALUE, NUMBER_SCRIPT_VALUE, STRING_SCRIPT_VALUE, - QVARIANT_SCRIPT_VALUE, + VARIANT_SCRIPT_VALUE, QOBJECT_SCRIPT_VALUE, + QMETAOBJECT_SCRIPT_VALUE, DATE_SCRIPT_VALUE, REGEXP_SCRIPT_VALUE, ARRAY_SCRIPT_VALUE, @@ -579,12 +626,35 @@ Bitstream& Bitstream::operator<<(const QScriptValue& value) { } else if (value.isBool()) { writeScriptValueType(*this, BOOL_SCRIPT_VALUE); + *this << value.toBool(); } else if (value.isNumber()) { writeScriptValueType(*this, NUMBER_SCRIPT_VALUE); + *this << value.toNumber(); } else if (value.isString()) { writeScriptValueType(*this, STRING_SCRIPT_VALUE); + *this << value.toString(); + + } else if (value.isVariant()) { + writeScriptValueType(*this, VARIANT_SCRIPT_VALUE); + *this << value.toVariant(); + + } else if (value.isQObject()) { + writeScriptValueType(*this, QOBJECT_SCRIPT_VALUE); + *this << value.toQObject(); + + } else if (value.isQMetaObject()) { + writeScriptValueType(*this, QMETAOBJECT_SCRIPT_VALUE); + *this << value.toQMetaObject(); + + } else if (value.isDate()) { + writeScriptValueType(*this, DATE_SCRIPT_VALUE); + *this << value.toDateTime(); + + } else if (value.isRegExp()) { + writeScriptValueType(*this, REGEXP_SCRIPT_VALUE); + *this << value.toRegExp(); } else if (value.isArray()) { writeScriptValueType(*this, ARRAY_SCRIPT_VALUE); diff --git a/libraries/metavoxels/src/Bitstream.h b/libraries/metavoxels/src/Bitstream.h index 4fe136f720..83733674a4 100644 --- a/libraries/metavoxels/src/Bitstream.h +++ b/libraries/metavoxels/src/Bitstream.h @@ -321,9 +321,15 @@ public: Bitstream& operator<<(uint value); Bitstream& operator>>(uint& value); + Bitstream& operator<<(qint64 value); + Bitstream& operator>>(qint64& value); + Bitstream& operator<<(float value); Bitstream& operator>>(float& value); + Bitstream& operator<<(double value); + Bitstream& operator>>(double& value); + Bitstream& operator<<(const glm::vec3& value); Bitstream& operator>>(glm::vec3& value); @@ -342,6 +348,12 @@ public: Bitstream& operator<<(const QUrl& url); Bitstream& operator>>(QUrl& url); + Bitstream& operator<<(const QDateTime& dateTime); + Bitstream& operator>>(QDateTime& dateTime); + + Bitstream& operator<<(const QRegExp& regExp); + Bitstream& operator>>(QRegExp& regExp); + Bitstream& operator<<(const QVariant& value); Bitstream& operator>>(QVariant& value); From 58bd1f7ab57c312933370a28242b1f8c8b68d97f Mon Sep 17 00:00:00 2001 From: Andrzej Kapolka Date: Mon, 9 Jun 2014 11:54:43 -0700 Subject: [PATCH 4/8] More script streaming bits. --- libraries/metavoxels/src/Bitstream.cpp | 110 ++++++++++++++++++++----- 1 file changed, 89 insertions(+), 21 deletions(-) diff --git a/libraries/metavoxels/src/Bitstream.cpp b/libraries/metavoxels/src/Bitstream.cpp index 8f813adf90..c3d0348ee8 100644 --- a/libraries/metavoxels/src/Bitstream.cpp +++ b/libraries/metavoxels/src/Bitstream.cpp @@ -14,6 +14,7 @@ #include #include #include +#include #include #include @@ -449,8 +450,11 @@ Bitstream& Bitstream::operator>>(QDateTime& dateTime) { Bitstream& Bitstream::operator<<(const QRegExp& regExp) { *this << regExp.pattern(); - - return *this; + Qt::CaseSensitivity caseSensitivity = regExp.caseSensitivity(); + write(&caseSensitivity, 1); + QRegExp::PatternSyntax syntax = regExp.patternSyntax(); + write(&syntax, 3); + return *this << regExp.isMinimal(); } Bitstream& Bitstream::operator>>(QRegExp& regExp) { @@ -460,9 +464,10 @@ Bitstream& Bitstream::operator>>(QRegExp& regExp) { read(&caseSensitivity, 1); QRegExp::PatternSyntax syntax = (QRegExp::PatternSyntax)0; read(&syntax, 3); - regExp = QRegExp(pattern, caseSensitivity, syntax); - + bool minimal; + *this >> minimal; + regExp.setMinimal(minimal); return *this; } @@ -658,10 +663,20 @@ Bitstream& Bitstream::operator<<(const QScriptValue& value) { } else if (value.isArray()) { writeScriptValueType(*this, ARRAY_SCRIPT_VALUE); - + int length = value.property(ScriptCache::getInstance()->getLengthString()).toInt32(); + *this << length; + for (int i = 0; i < length; i++) { + *this << value.property(i); + } } else if (value.isObject()) { writeScriptValueType(*this, OBJECT_SCRIPT_VALUE); - + for (QScriptValueIterator it(value); it.hasNext(); ) { + it.next(); + *this << it.scriptName(); + *this << it.value(); + } + *this << QScriptString(); + } else { writeScriptValueType(*this, INVALID_SCRIPT_VALUE); } @@ -678,26 +693,79 @@ Bitstream& Bitstream::operator>>(QScriptValue& value) { value = QScriptValue(QScriptValue::NullValue); break; - case BOOL_SCRIPT_VALUE: - value = QScriptValue(); + case BOOL_SCRIPT_VALUE: { + bool boolValue; + *this >> boolValue; + value = QScriptValue(boolValue); break; - - case NUMBER_SCRIPT_VALUE: - value = QScriptValue(); + } + case NUMBER_SCRIPT_VALUE: { + qsreal numberValue; + *this >> numberValue; + value = QScriptValue(numberValue); break; - - case STRING_SCRIPT_VALUE: - value = QScriptValue(); + } + case STRING_SCRIPT_VALUE: { + QString stringValue; + *this >> stringValue; + value = QScriptValue(stringValue); break; - - case ARRAY_SCRIPT_VALUE: - value = QScriptValue(); + } + case VARIANT_SCRIPT_VALUE: { + QVariant variantValue; + *this >> variantValue; + value = ScriptCache::getInstance()->getEngine()->newVariant(variantValue); break; - - case OBJECT_SCRIPT_VALUE: - value = QScriptValue(); + } + case QOBJECT_SCRIPT_VALUE: { + QObject* object; + *this >> object; + ScriptCache::getInstance()->getEngine()->newQObject(object, QScriptEngine::ScriptOwnership); break; - + } + case QMETAOBJECT_SCRIPT_VALUE: { + const QMetaObject* metaObject; + *this >> metaObject; + ScriptCache::getInstance()->getEngine()->newQMetaObject(metaObject); + break; + } + case DATE_SCRIPT_VALUE: { + QDateTime dateTime; + *this >> dateTime; + value = ScriptCache::getInstance()->getEngine()->newDate(dateTime); + break; + } + case REGEXP_SCRIPT_VALUE: { + QRegExp regExp; + *this >> regExp; + value = ScriptCache::getInstance()->getEngine()->newRegExp(regExp); + break; + } + case ARRAY_SCRIPT_VALUE: { + int length; + *this >> length; + value = ScriptCache::getInstance()->getEngine()->newArray(length); + for (int i = 0; i < length; i++) { + QScriptValue element; + *this >> element; + value.setProperty(i, element); + } + break; + } + case OBJECT_SCRIPT_VALUE: { + value = ScriptCache::getInstance()->getEngine()->newObject(); + forever { + QScriptString name; + *this >> name; + if (!name.isValid()) { + break; + } + QScriptValue scriptValue; + *this >> scriptValue; + value.setProperty(name, scriptValue); + } + break; + } default: value = QScriptValue(); break; From fd469c543c7b8cb7ef778ad280adda64bb3f6768 Mon Sep 17 00:00:00 2001 From: Andrzej Kapolka Date: Mon, 9 Jun 2014 14:35:20 -0700 Subject: [PATCH 5/8] More script streaming bits. --- libraries/metavoxels/src/Bitstream.cpp | 276 ++++++++++++++++++++++- libraries/metavoxels/src/Bitstream.h | 4 + libraries/metavoxels/src/ScriptCache.cpp | 79 +++++++ libraries/metavoxels/src/ScriptCache.h | 5 + 4 files changed, 362 insertions(+), 2 deletions(-) diff --git a/libraries/metavoxels/src/Bitstream.cpp b/libraries/metavoxels/src/Bitstream.cpp index c3d0348ee8..d27053aefb 100644 --- a/libraries/metavoxels/src/Bitstream.cpp +++ b/libraries/metavoxels/src/Bitstream.cpp @@ -31,6 +31,7 @@ REGISTER_SIMPLE_TYPE_STREAMER(uint) REGISTER_SIMPLE_TYPE_STREAMER(float) REGISTER_SIMPLE_TYPE_STREAMER(QByteArray) REGISTER_SIMPLE_TYPE_STREAMER(QColor) +REGISTER_SIMPLE_TYPE_STREAMER(QScriptValue) REGISTER_SIMPLE_TYPE_STREAMER(QString) REGISTER_SIMPLE_TYPE_STREAMER(QUrl) REGISTER_SIMPLE_TYPE_STREAMER(QVariantList) @@ -286,6 +287,12 @@ void Bitstream::writeDelta(const QVariant& value, const QVariant& reference) { streamer->writeRawDelta(*this, value, reference); } +void Bitstream::writeRawDelta(const QVariant& value, const QVariant& reference) { + const TypeStreamer* streamer = getTypeStreamers().value(value.userType()); + _typeStreamerStreamer << streamer; + streamer->writeRawDelta(*this, value, reference); +} + void Bitstream::readRawDelta(QVariant& value, const QVariant& reference) { TypeReader typeReader; _typeStreamerStreamer >> typeReader; @@ -310,6 +317,271 @@ void Bitstream::readRawDelta(QObject*& value, const QObject* reference) { value = objectReader.readDelta(*this, reference); } +void Bitstream::writeRawDelta(const QScriptValue& value, const QScriptValue& reference) { + if (reference.isUndefined() || reference.isNull()) { + *this << value; + + } else if (reference.isBool()) { + if (value.isBool()) { + *this << false; + *this << value.toBool(); + + } else { + *this << true; + *this << value; + } + } else if (reference.isNumber()) { + if (value.isNumber()) { + *this << false; + *this << value.toNumber(); + + } else { + *this << true; + *this << value; + } + } else if (reference.isString()) { + if (value.isString()) { + *this << false; + *this << value.toString(); + + } else { + *this << true; + *this << value; + } + } else if (reference.isVariant()) { + if (value.isVariant()) { + *this << false; + writeRawDelta(value.toVariant(), reference.toVariant()); + + } else { + *this << true; + *this << value; + } + } else if (reference.isQObject()) { + if (value.isQObject()) { + *this << false; + writeRawDelta(value.toQObject(), reference.toQObject()); + + } else { + *this << true; + *this << value; + } + } else if (reference.isQMetaObject()) { + if (value.isQMetaObject()) { + *this << false; + *this << value.toQMetaObject(); + + } else { + *this << true; + *this << value; + } + } else if (reference.isDate()) { + if (value.isDate()) { + *this << false; + *this << value.toDateTime(); + + } else { + *this << true; + *this << value; + } + } else if (reference.isRegExp()) { + if (value.isRegExp()) { + *this << false; + *this << value.toRegExp(); + + } else { + *this << true; + *this << value; + } + } else if (reference.isArray()) { + if (value.isArray()) { + *this << false; + int length = value.property(ScriptCache::getInstance()->getLengthString()).toInt32(); + *this << length; + int referenceLength = reference.property(ScriptCache::getInstance()->getLengthString()).toInt32(); + for (int i = 0; i < length; i++) { + if (i < referenceLength) { + writeDelta(value.property(i), reference.property(i)); + } else { + *this << value.property(i); + } + } + } else { + *this << true; + *this << value; + } + } else if (reference.isObject()) { + if (value.isObject()) { + *this << false; + for (QScriptValueIterator it(value); it.hasNext(); ) { + it.next(); + QScriptValue referenceValue = reference.property(it.scriptName()); + if (it.value() != referenceValue) { + *this << it.scriptName(); + writeRawDelta(it.value(), referenceValue); + } + } + for (QScriptValueIterator it(reference); it.hasNext(); ) { + it.next(); + if (!value.property(it.scriptName()).isValid()) { + *this << it.scriptName(); + writeRawDelta(QScriptValue(), it.value()); + } + } + *this << QScriptString(); + + } else { + *this << true; + *this << value; + } + } else { + *this << value; + } +} + +void Bitstream::readRawDelta(QScriptValue& value, const QScriptValue& reference) { + if (reference.isUndefined() || reference.isNull()) { + *this >> value; + + } else if (reference.isBool()) { + bool typeChanged; + *this >> typeChanged; + if (typeChanged) { + *this >> value; + + } else { + bool boolValue; + *this >> boolValue; + value = QScriptValue(boolValue); + } + } else if (reference.isNumber()) { + bool typeChanged; + *this >> typeChanged; + if (typeChanged) { + *this >> value; + + } else { + qsreal numberValue; + *this >> numberValue; + value = QScriptValue(numberValue); + } + } else if (reference.isString()) { + bool typeChanged; + *this >> typeChanged; + if (typeChanged) { + *this >> value; + + } else { + QString stringValue; + *this >> stringValue; + value = QScriptValue(stringValue); + } + } else if (reference.isVariant()) { + bool typeChanged; + *this >> typeChanged; + if (typeChanged) { + *this >> value; + + } else { + QVariant variant; + readRawDelta(variant, reference.toVariant()); + value = ScriptCache::getInstance()->getEngine()->newVariant(variant); + } + } else if (reference.isQObject()) { + bool typeChanged; + *this >> typeChanged; + if (typeChanged) { + *this >> value; + + } else { + QObject* object; + readRawDelta(object, reference.toQObject()); + value = ScriptCache::getInstance()->getEngine()->newQObject(object, QScriptEngine::ScriptOwnership); + } + } else if (reference.isQMetaObject()) { + bool typeChanged; + *this >> typeChanged; + if (typeChanged) { + *this >> value; + + } else { + const QMetaObject* metaObject; + *this >> metaObject; + value = ScriptCache::getInstance()->getEngine()->newQMetaObject(metaObject); + } + } else if (reference.isDate()) { + bool typeChanged; + *this >> typeChanged; + if (typeChanged) { + *this >> value; + + } else { + QDateTime dateTime; + *this >> dateTime; + value = ScriptCache::getInstance()->getEngine()->newDate(dateTime); + } + } else if (reference.isRegExp()) { + bool typeChanged; + *this >> typeChanged; + if (typeChanged) { + *this >> value; + + } else { + QRegExp regExp; + *this >> regExp; + value = ScriptCache::getInstance()->getEngine()->newRegExp(regExp); + } + } else if (reference.isArray()) { + bool typeChanged; + *this >> typeChanged; + if (typeChanged) { + *this >> value; + + } else { + int length; + *this >> length; + value = ScriptCache::getInstance()->getEngine()->newArray(length); + int referenceLength = reference.property(ScriptCache::getInstance()->getLengthString()).toInt32(); + for (int i = 0; i < length; i++) { + QScriptValue element; + if (i < referenceLength) { + readDelta(element, reference.property(i)); + } else { + *this >> element; + } + value.setProperty(i, element); + } + } + } else if (reference.isObject()) { + bool typeChanged; + *this >> typeChanged; + if (typeChanged) { + *this >> value; + + } else { + // start by shallow-copying the reference + value = ScriptCache::getInstance()->getEngine()->newObject(); + for (QScriptValueIterator it(reference); it.hasNext(); ) { + it.next(); + value.setProperty(it.scriptName(), it.value()); + } + // then apply the requested changes + forever { + QScriptString name; + *this >> name; + if (!name.isValid()) { + break; + } + QScriptValue scriptValue; + readRawDelta(scriptValue, reference.property(name)); + value.setProperty(name, scriptValue); + } + } + } else { + *this >> value; + } +} + Bitstream& Bitstream::operator<<(bool value) { if (value) { _byte |= (1 << _position); @@ -612,11 +884,11 @@ enum ScriptValueType { const int SCRIPT_VALUE_BITS = 4; -void writeScriptValueType(Bitstream& out, ScriptValueType type) { +static void writeScriptValueType(Bitstream& out, ScriptValueType type) { out.write(&type, SCRIPT_VALUE_BITS); } -ScriptValueType readScriptValueType(Bitstream& in) { +static ScriptValueType readScriptValueType(Bitstream& in) { ScriptValueType type = (ScriptValueType)0; in.read(&type, SCRIPT_VALUE_BITS); return type; diff --git a/libraries/metavoxels/src/Bitstream.h b/libraries/metavoxels/src/Bitstream.h index 83733674a4..d05f6574c0 100644 --- a/libraries/metavoxels/src/Bitstream.h +++ b/libraries/metavoxels/src/Bitstream.h @@ -292,11 +292,15 @@ public: template void writeDelta(const T& value, const T& reference); template void readDelta(T& value, const T& reference); + void writeRawDelta(const QVariant& value, const QVariant& reference); void readRawDelta(QVariant& value, const QVariant& reference); void writeRawDelta(const QObject* value, const QObject* reference); void readRawDelta(QObject*& value, const QObject* reference); + void writeRawDelta(const QScriptValue& value, const QScriptValue& reference); + void readRawDelta(QScriptValue& value, const QScriptValue& reference); + template void writeRawDelta(const T& value, const T& reference); template void readRawDelta(T& value, const T& reference); diff --git a/libraries/metavoxels/src/ScriptCache.cpp b/libraries/metavoxels/src/ScriptCache.cpp index dd090613b7..9de624fb29 100644 --- a/libraries/metavoxels/src/ScriptCache.cpp +++ b/libraries/metavoxels/src/ScriptCache.cpp @@ -13,11 +13,90 @@ #include #include +#include #include #include "AttributeRegistry.h" #include "ScriptCache.h" +static int scriptValueMetaTypeId = qRegisterMetaType(); + +bool operator==(const QScriptValue& first, const QScriptValue& second) { + if (first.isUndefined()) { + return second.isUndefined(); + + } else if (first.isNull()) { + return second.isNull(); + + } else if (first.isBool()) { + return second.isBool() && first.toBool() == second.toBool(); + + } else if (first.isNumber()) { + return second.isNumber() && first.toNumber() == second.toNumber(); + + } else if (first.isString()) { + return second.isString() && first.toString() == second.toString(); + + } else if (first.isVariant()) { + return second.isVariant() && first.toVariant() == second.toVariant(); + + } else if (first.isQObject()) { + return second.isQObject() && first.toQObject() == second.toQObject(); + + } else if (first.isQMetaObject()) { + return second.isQMetaObject() && first.toQMetaObject() == second.toQMetaObject(); + + } else if (first.isDate()) { + return second.isDate() && first.toDateTime() == second.toDateTime(); + + } else if (first.isRegExp()) { + return second.isRegExp() && first.toRegExp() == second.toRegExp(); + + } else if (first.isArray()) { + if (!second.isArray()) { + return false; + } + int length = first.property(ScriptCache::getInstance()->getLengthString()).toInt32(); + if (second.property(ScriptCache::getInstance()->getLengthString()).toInt32() != length) { + return false; + } + for (int i = 0; i < length; i++) { + if (first.property(i) != second.property(i)) { + return false; + } + } + return true; + + } else if (first.isObject()) { + if (!second.isObject()) { + return false; + } + int propertyCount = 0; + for (QScriptValueIterator it(first); it.hasNext(); ) { + it.next(); + if (second.property(it.scriptName()) != it.value()) { + return false; + } + propertyCount++; + } + // make sure the second has exactly as many properties as the first + for (QScriptValueIterator it(second); it.hasNext(); ) { + it.next(); + if (--propertyCount < 0) { + return false; + } + } + return true; + + } else { + return !second.isValid(); + } +} + +bool operator!=(const QScriptValue& first, const QScriptValue& second) { + return !(first == second); +} + ScriptCache* ScriptCache::getInstance() { static ScriptCache cache; return &cache; diff --git a/libraries/metavoxels/src/ScriptCache.h b/libraries/metavoxels/src/ScriptCache.h index f393d0e0a8..d88a967081 100644 --- a/libraries/metavoxels/src/ScriptCache.h +++ b/libraries/metavoxels/src/ScriptCache.h @@ -65,6 +65,11 @@ private: QScriptString _generatorString; }; +Q_DECLARE_METATYPE(QScriptValue) + +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 { Q_OBJECT From 590f045ed1ce8806f964d252042a173c6f15ff12 Mon Sep 17 00:00:00 2001 From: Andrzej Kapolka Date: Mon, 9 Jun 2014 16:51:41 -0700 Subject: [PATCH 6/8] Script value streaming tests, fixes. --- libraries/metavoxels/src/Bitstream.cpp | 9 ++- libraries/metavoxels/src/ScriptCache.cpp | 5 ++ libraries/metavoxels/src/ScriptCache.h | 1 + tests/metavoxels/src/MetavoxelTests.cpp | 88 +++++++++++++++++++++++- tests/metavoxels/src/MetavoxelTests.h | 9 ++- 5 files changed, 106 insertions(+), 6 deletions(-) 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) From 3293ab788b7340c98fbc923d509b216445362e09 Mon Sep 17 00:00:00 2001 From: Andrzej Kapolka Date: Mon, 9 Jun 2014 17:19:36 -0700 Subject: [PATCH 7/8] Fix for script object deltas. --- libraries/metavoxels/src/Bitstream.cpp | 3 ++- tests/metavoxels/src/MetavoxelTests.cpp | 15 +++++++-------- 2 files changed, 9 insertions(+), 9 deletions(-) diff --git a/libraries/metavoxels/src/Bitstream.cpp b/libraries/metavoxels/src/Bitstream.cpp index 7595580c33..d7e15a9dd6 100644 --- a/libraries/metavoxels/src/Bitstream.cpp +++ b/libraries/metavoxels/src/Bitstream.cpp @@ -411,7 +411,8 @@ void Bitstream::writeRawDelta(const QScriptValue& value, const QScriptValue& ref *this << value; } } else if (reference.isObject()) { - if (value.isObject()) { + if (value.isObject() && !(value.isArray() || value.isRegExp() || value.isDate() || + value.isQMetaObject() || value.isQObject() || value.isVariant())) { *this << false; for (QScriptValueIterator it(value); it.hasNext(); ) { it.next(); diff --git a/tests/metavoxels/src/MetavoxelTests.cpp b/tests/metavoxels/src/MetavoxelTests.cpp index 4dc1cdddce..c7e98ab0cf 100644 --- a/tests/metavoxels/src/MetavoxelTests.cpp +++ b/tests/metavoxels/src/MetavoxelTests.cpp @@ -83,9 +83,9 @@ static TestSharedObjectA::TestFlags getRandomTestFlags() { return flags; } -static QScriptValue createRandomScriptValue() { +static QScriptValue createRandomScriptValue(bool complex = false) { scriptObjectsCreated++; - switch (randIntInRange(0, 3)) { + switch (randIntInRange(0, complex ? 5 : 2)) { case 0: return QScriptValue(QScriptValue::NullValue); @@ -96,7 +96,6 @@ static QScriptValue createRandomScriptValue() { return QScriptValue(randFloat()); case 3: - default: return QScriptValue(QString(createRandomBytes())); case 4: { @@ -107,7 +106,7 @@ static QScriptValue createRandomScriptValue() { } return value; } - case 5: { + default: { QScriptValue value = ScriptCache::getInstance()->getEngine()->newObject(); if (randomBoolean()) { value.setProperty("foo", createRandomScriptValue()); @@ -133,7 +132,7 @@ static TestMessageC createRandomMessageC() { message.baz = randFloat(); message.bong.foo = createRandomBytes(); message.bong.baz = getRandomTestEnum(); - message.bizzle = createRandomScriptValue(); + message.bizzle = createRandomScriptValue(true); return message; } @@ -360,7 +359,7 @@ static SharedObjectPointer mutate(const SharedObjectPointer& state) { it.next(); newValue.setProperty(it.scriptName(), it.value()); } - switch (randIntInRange(0, 3)) { + switch (randIntInRange(0, 2)) { case 0: { QScriptValue oldArray = oldValue.property("foo"); int oldLength = oldArray.property(ScriptCache::getInstance()->getLengthString()).toInt32(); @@ -368,7 +367,7 @@ static SharedObjectPointer mutate(const SharedObjectPointer& state) { for (int i = 0; i < oldLength; i++) { newArray.setProperty(i, oldArray.property(i)); } - newArray.setProperty(randIntInRange(0, oldLength - 1), createRandomScriptValue()); + newArray.setProperty(randIntInRange(0, oldLength - 1), createRandomScriptValue(true)); break; } case 1: @@ -376,7 +375,7 @@ static SharedObjectPointer mutate(const SharedObjectPointer& state) { break; default: - newValue.setProperty("baz", createRandomScriptValue()); + newValue.setProperty("baz", createRandomScriptValue(true)); break; } static_cast(newState.data())->setBizzle(newValue); From d1549b00abffccc56dfad0951302054a15e71521 Mon Sep 17 00:00:00 2001 From: Andrzej Kapolka Date: Mon, 9 Jun 2014 17:22:44 -0700 Subject: [PATCH 8/8] Might as well include strings in the "simple" random script objects. --- tests/metavoxels/src/MetavoxelTests.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/metavoxels/src/MetavoxelTests.cpp b/tests/metavoxels/src/MetavoxelTests.cpp index c7e98ab0cf..6ec2331b14 100644 --- a/tests/metavoxels/src/MetavoxelTests.cpp +++ b/tests/metavoxels/src/MetavoxelTests.cpp @@ -85,7 +85,7 @@ static TestSharedObjectA::TestFlags getRandomTestFlags() { static QScriptValue createRandomScriptValue(bool complex = false) { scriptObjectsCreated++; - switch (randIntInRange(0, complex ? 5 : 2)) { + switch (randIntInRange(0, complex ? 5 : 3)) { case 0: return QScriptValue(QScriptValue::NullValue);