From 4f4c4c68d9ca1ddac431e7a405b1dbd8057e9d29 Mon Sep 17 00:00:00 2001 From: Andrzej Kapolka Date: Tue, 4 Feb 2014 18:31:18 -0800 Subject: [PATCH] Streaming cleanup, streaming script strings as repeated values. --- interface/resources/scripts/sphere.js | 171 --------------------- libraries/metavoxels/src/Bitstream.cpp | 75 +++++++-- libraries/metavoxels/src/Bitstream.h | 26 +++- libraries/metavoxels/src/MetavoxelData.cpp | 12 +- libraries/metavoxels/src/MetavoxelUtil.cpp | 40 ++++- libraries/metavoxels/src/MetavoxelUtil.h | 18 ++- libraries/metavoxels/src/ScriptCache.cpp | 29 +++- libraries/metavoxels/src/ScriptCache.h | 49 ++++-- 8 files changed, 206 insertions(+), 214 deletions(-) delete mode 100644 interface/resources/scripts/sphere.js diff --git a/interface/resources/scripts/sphere.js b/interface/resources/scripts/sphere.js deleted file mode 100644 index b696021fe8..0000000000 --- a/interface/resources/scripts/sphere.js +++ /dev/null @@ -1,171 +0,0 @@ -// -// sphere.js -// interface -// -// Created by Andrzej Kapolka on 12/17/13. -// Copyright (c) 2013 High Fidelity, Inc. All rights reserved. -// - -function strictIndexOf(array, element) { - for (var i = 0; i < array.length; i++) { - if (array[i] == element) { - return i; - } - } - return -1; -} - -var colorIndex; -var normalIndex; -var visitor; -var info; - -var MAX_DEPTH = 4; - -var sphereCenter = [ 0.5, 0.5, 0.5 ]; -var sphereColor = 0xFFFF00FF; -var sphereRadius = 0.25; -var sphereRadiusSquared = sphereRadius * sphereRadius; - -function lengthSquared(x, y, z) { - return x*x + y*y + z*z; -} - -function setNormal(vector) { - if (normalIndex != -1) { - var length = Math.sqrt(lengthSquared(vector[0], vector[1], vector[2])); - if (length == 0.0) { - info.inputValues[normalIndex] = 0x007F00; - - } else { - var scale = 127.0 / length; - info.inputValues[normalIndex] = - (Math.floor(vector[0] * scale) & 0xFF) << 16 | - (Math.floor(vector[1] * scale) & 0xFF) << 8 | - Math.floor(vector[2] * scale) & 0xFF; - } - } -} - -function guide(minimum, size, depth) { - info.minimum = minimum; - info.size = size; - - // start with a relative fast bounding volume test to find most non-intersecting states - var maximum = [ minimum[0] + size, minimum[1] + size, minimum[2] + size ]; - if (minimum[0] >= sphereCenter[0] + sphereRadius || - minimum[1] >= sphereCenter[1] + sphereRadius || - minimum[2] >= sphereCenter[2] + sphereRadius || - maximum[0] <= sphereCenter[0] - sphereRadius || - maximum[1] <= sphereCenter[1] - sphereRadius || - maximum[2] <= sphereCenter[2] - sphereRadius) { - info.isLeaf = true; - if (colorIndex != -1) { - info.inputValues[colorIndex] = 0x0; - } - visitor.visit(info); - return; - } - - var halfSize = size / 2; - var center = [ minimum[0] + halfSize, minimum[1] + halfSize, minimum[2] + halfSize ]; - var vector = [ center[0] - sphereCenter[0], center[1] - sphereCenter[1], center[2] - sphereCenter[2] ]; - - // count the number of points inside the sphere - var inside = 0; - if (lengthSquared(sphereCenter[0] - minimum[0], sphereCenter[1] - minimum[1], sphereCenter[2] - minimum[2]) <= - sphereRadiusSquared) { - inside++; - } - if (lengthSquared(sphereCenter[0] - maximum[0], sphereCenter[1] - minimum[1], sphereCenter[2] - minimum[2]) <= - sphereRadiusSquared) { - inside++; - } - if (lengthSquared(sphereCenter[0] - minimum[0], sphereCenter[1] - maximum[1], sphereCenter[2] - minimum[2]) <= - sphereRadiusSquared) { - inside++; - } - if (lengthSquared(sphereCenter[0] - maximum[0], sphereCenter[1] - maximum[1], sphereCenter[2] - minimum[2]) <= - sphereRadiusSquared) { - inside++; - } - if (lengthSquared(sphereCenter[0] - minimum[0], sphereCenter[1] - minimum[1], sphereCenter[2] - maximum[2]) <= - sphereRadiusSquared) { - inside++; - } - if (lengthSquared(sphereCenter[0] - maximum[0], sphereCenter[1] - minimum[1], sphereCenter[2] - maximum[2]) <= - sphereRadiusSquared) { - inside++; - } - if (lengthSquared(sphereCenter[0] - minimum[0], sphereCenter[1] - maximum[1], sphereCenter[2] - maximum[2]) <= - sphereRadiusSquared) { - inside++; - } - if (lengthSquared(sphereCenter[0] - maximum[0], sphereCenter[1] - maximum[1], sphereCenter[2] - maximum[2]) <= - sphereRadiusSquared) { - inside++; - } - - // see if all points are in the sphere - if (inside == 8) { - info.isLeaf = true; - if (colorIndex != -1) { - info.inputValues[colorIndex] = sphereColor; - } - setNormal(vector); - visitor.visit(info); - return; - } - - // if we've reached max depth, compute alpha using a volume estimate - if (depth == MAX_DEPTH) { - info.isLeaf = true; - if (inside >= 3) { - if (colorIndex != -1) { - info.inputValues[colorIndex] = sphereColor; - } - setNormal(vector); - - } else { - if (colorIndex != -1) { - info.inputValues[colorIndex] = 0x0; - } - } - visitor.visit(info); - return; - } - - // recurse - info.isLeaf = false; - if (!visitor.visit(info)) { - return; - } - depth += 1; - guide(minimum, halfSize, depth); - guide([ center[0], minimum[1], minimum[2] ], halfSize, depth); - guide([ minimum[0], center[1], minimum[2] ], halfSize, depth); - guide([ center[0], center[1], minimum[2] ], halfSize, depth); - guide([ minimum[0], minimum[1], center[2] ], halfSize, depth); - guide([ center[0], minimum[1], center[2] ], halfSize, depth); - guide([ minimum[0], center[1], center[2] ], halfSize, depth); - guide([ center[0], center[1], center[2] ], halfSize, depth); -} - -(function(visitation) { - var inputs = visitation.visitor.getInputs(); - colorIndex = strictIndexOf(inputs, AttributeRegistry.colorAttribute); - normalIndex = strictIndexOf(inputs, AttributeRegistry.normalAttribute); - visitor = visitation.visitor; - info = { inputValues: new Array(inputs.length) }; - - // have the sphere orbit the center and pulse in size - var time = new Date().getTime(); - var ROTATE_PERIOD = 400.0; - sphereCenter[0] = 0.5 + 0.25 * Math.cos(time / ROTATE_PERIOD); - sphereCenter[2] = 0.5 + 0.25 * Math.sin(time / ROTATE_PERIOD); - var PULSE_PERIOD = 300.0; - sphereRadius = 0.25 + 0.0625 * Math.cos(time / PULSE_PERIOD); - sphereRadiusSquared = sphereRadius * sphereRadius; - - guide(visitation.info.minimum, visitation.info.size, 0); -}) diff --git a/libraries/metavoxels/src/Bitstream.cpp b/libraries/metavoxels/src/Bitstream.cpp index 686508a973..dfc2c9bd75 100644 --- a/libraries/metavoxels/src/Bitstream.cpp +++ b/libraries/metavoxels/src/Bitstream.cpp @@ -18,6 +18,7 @@ #include "AttributeRegistry.h" #include "Bitstream.h" +#include "ScriptCache.h" REGISTER_SIMPLE_TYPE_STREAMER(bool) REGISTER_SIMPLE_TYPE_STREAMER(int) @@ -88,7 +89,8 @@ Bitstream::Bitstream(QDataStream& underlying) : _position(0), _metaObjectStreamer(*this), _typeStreamerStreamer(*this), - _attributeStreamer(*this) { + _attributeStreamer(*this), + _scriptStringStreamer(*this) { } const int BITS_IN_BYTE = 8; @@ -145,7 +147,8 @@ void Bitstream::reset() { Bitstream::WriteMappings Bitstream::getAndResetWriteMappings() { WriteMappings mappings = { _metaObjectStreamer.getAndResetTransientOffsets(), _typeStreamerStreamer.getAndResetTransientOffsets(), - _attributeStreamer.getAndResetTransientOffsets() }; + _attributeStreamer.getAndResetTransientOffsets(), + _scriptStringStreamer.getAndResetTransientOffsets() }; return mappings; } @@ -153,12 +156,14 @@ void Bitstream::persistWriteMappings(const WriteMappings& mappings) { _metaObjectStreamer.persistTransientOffsets(mappings.metaObjectOffsets); _typeStreamerStreamer.persistTransientOffsets(mappings.typeStreamerOffsets); _attributeStreamer.persistTransientOffsets(mappings.attributeOffsets); + _scriptStringStreamer.persistTransientOffsets(mappings.scriptStringOffsets); } Bitstream::ReadMappings Bitstream::getAndResetReadMappings() { ReadMappings mappings = { _metaObjectStreamer.getAndResetTransientValues(), _typeStreamerStreamer.getAndResetTransientValues(), - _attributeStreamer.getAndResetTransientValues() }; + _attributeStreamer.getAndResetTransientValues(), + _scriptStringStreamer.getAndResetTransientValues() }; return mappings; } @@ -166,6 +171,7 @@ void Bitstream::persistReadMappings(const ReadMappings& mappings) { _metaObjectStreamer.persistTransientValues(mappings.metaObjectValues); _typeStreamerStreamer.persistTransientValues(mappings.typeStreamerValues); _attributeStreamer.persistTransientValues(mappings.attributeValues); + _scriptStringStreamer.persistTransientValues(mappings.scriptStringValues); } Bitstream& Bitstream::operator<<(bool value) { @@ -238,6 +244,16 @@ Bitstream& Bitstream::operator>>(QString& string) { return read(string.data(), size * sizeof(QChar) * BITS_IN_BYTE); } +Bitstream& Bitstream::operator<<(const QScriptString& string) { + _scriptStringStreamer << string; + return *this; +} + +Bitstream& Bitstream::operator>>(QScriptString& string) { + _scriptStringStreamer >> string; + return *this; +} + Bitstream& Bitstream::operator<<(const QUrl& url) { return *this << url.toString(); } @@ -334,11 +350,41 @@ Bitstream& Bitstream::operator>>(QObject*& object) { } Bitstream& Bitstream::operator<<(const QMetaObject* metaObject) { - return *this << (metaObject ? QByteArray::fromRawData( - metaObject->className(), strlen(metaObject->className())) : QByteArray()); + _metaObjectStreamer << metaObject; + return *this; } Bitstream& Bitstream::operator>>(const QMetaObject*& metaObject) { + _metaObjectStreamer >> metaObject; + return *this; +} + +Bitstream& Bitstream::operator<<(const TypeStreamer* streamer) { + _typeStreamerStreamer << streamer; + return *this; +} + +Bitstream& Bitstream::operator>>(const TypeStreamer*& streamer) { + _typeStreamerStreamer >> streamer; + return *this; +} + +Bitstream& Bitstream::operator<<(const AttributePointer& attribute) { + _attributeStreamer << attribute; + return *this; +} + +Bitstream& Bitstream::operator>>(AttributePointer& attribute) { + _attributeStreamer >> attribute; + return *this; +} + +Bitstream& Bitstream::operator<(const QMetaObject* metaObject) { + return *this << (metaObject ? QByteArray::fromRawData(metaObject->className(), + strlen(metaObject->className())) : QByteArray()); +} + +Bitstream& Bitstream::operator>(const QMetaObject*& metaObject) { QByteArray className; *this >> className; if (className.isEmpty()) { @@ -352,12 +398,12 @@ Bitstream& Bitstream::operator>>(const QMetaObject*& metaObject) { return *this; } -Bitstream& Bitstream::operator<<(const TypeStreamer* streamer) { +Bitstream& Bitstream::operator<(const TypeStreamer* streamer) { const char* typeName = QMetaType::typeName(streamer->getType()); return *this << QByteArray::fromRawData(typeName, strlen(typeName)); } -Bitstream& Bitstream::operator>>(const TypeStreamer*& streamer) { +Bitstream& Bitstream::operator>(const TypeStreamer*& streamer) { QByteArray typeName; *this >> typeName; streamer = getTypeStreamers().value(QMetaType::type(typeName.constData())); @@ -367,17 +413,28 @@ Bitstream& Bitstream::operator>>(const TypeStreamer*& streamer) { return *this; } -Bitstream& Bitstream::operator<<(const AttributePointer& attribute) { +Bitstream& Bitstream::operator<(const AttributePointer& attribute) { return *this << (QObject*)attribute.data(); } -Bitstream& Bitstream::operator>>(AttributePointer& attribute) { +Bitstream& Bitstream::operator>(AttributePointer& attribute) { QObject* object; *this >> object; attribute = AttributeRegistry::getInstance()->registerAttribute(static_cast(object)); return *this; } +Bitstream& Bitstream::operator<(const QScriptString& string) { + return *this << string.toString(); +} + +Bitstream& Bitstream::operator>(QScriptString& string) { + QString rawString; + *this >> rawString; + string = ScriptCache::getInstance()->getEngine()->toStringHandle(rawString); + return *this; +} + QHash& Bitstream::getMetaObjects() { static QHash metaObjects; return metaObjects; diff --git a/libraries/metavoxels/src/Bitstream.h b/libraries/metavoxels/src/Bitstream.h index 0605cde50b..7798a00382 100644 --- a/libraries/metavoxels/src/Bitstream.h +++ b/libraries/metavoxels/src/Bitstream.h @@ -11,6 +11,7 @@ #include #include +#include #include #include #include @@ -127,7 +128,7 @@ template inline RepeatedValueStreamer& RepeatedValueStreamer::ope int& offset = _transientOffsets[value]; if (offset == 0) { _idStreamer << (_lastPersistentID + (offset = ++_lastTransientOffset)); - _stream << value; + _stream < value; } else { _idStreamer << (_lastPersistentID + offset); @@ -148,7 +149,7 @@ template inline RepeatedValueStreamer& RepeatedValueStreamer::ope int offset = id - _lastPersistentID; typename QHash::iterator it = _transientValues.find(offset); if (it == _transientValues.end()) { - _stream >> value; + _stream > value; _transientValues.insert(offset, value); } else { @@ -167,6 +168,7 @@ public: QHash metaObjectOffsets; QHash typeStreamerOffsets; QHash attributeOffsets; + QHash scriptStringOffsets; }; class ReadMappings { @@ -174,6 +176,7 @@ public: QHash metaObjectValues; QHash typeStreamerValues; QHash attributeValues; + QHash scriptStringValues; }; /// Registers a metaobject under its name so that instances of it can be streamed. @@ -206,9 +209,6 @@ public: /// Resets to the initial state. void reset(); - /// Returns a reference to the attribute streamer. - RepeatedValueStreamer& getAttributeStreamer() { return _attributeStreamer; } - /// Returns the set of transient mappings gathered during writing and resets them. WriteMappings getAndResetWriteMappings(); @@ -239,6 +239,9 @@ public: Bitstream& operator<<(const QString& string); Bitstream& operator>>(QString& string); + Bitstream& operator<<(const QScriptString& string); + Bitstream& operator>>(QScriptString& string); + Bitstream& operator<<(const QUrl& url); Bitstream& operator>>(QUrl& url); @@ -266,6 +269,18 @@ public: Bitstream& operator<<(const AttributePointer& attribute); Bitstream& operator>>(AttributePointer& attribute); + Bitstream& operator<(const QMetaObject* metaObject); + Bitstream& operator>(const QMetaObject*& metaObject); + + Bitstream& operator<(const TypeStreamer* streamer); + Bitstream& operator>(const TypeStreamer*& streamer); + + Bitstream& operator<(const AttributePointer& attribute); + Bitstream& operator>(AttributePointer& attribute); + + Bitstream& operator<(const QScriptString& string); + Bitstream& operator>(QScriptString& string); + private: QDataStream& _underlying; @@ -275,6 +290,7 @@ private: RepeatedValueStreamer _metaObjectStreamer; RepeatedValueStreamer _typeStreamerStreamer; RepeatedValueStreamer _attributeStreamer; + RepeatedValueStreamer _scriptStringStreamer; static QHash& getMetaObjects(); static QMultiHash& getMetaObjectSubClasses(); diff --git a/libraries/metavoxels/src/MetavoxelData.cpp b/libraries/metavoxels/src/MetavoxelData.cpp index 951378979b..b0e24405e6 100644 --- a/libraries/metavoxels/src/MetavoxelData.cpp +++ b/libraries/metavoxels/src/MetavoxelData.cpp @@ -136,7 +136,7 @@ void MetavoxelData::read(Bitstream& in) { in >> rootCount; for (int i = 0; i < rootCount; i++) { AttributePointer attribute; - in.getAttributeStreamer() >> attribute; + in >> attribute; MetavoxelNode*& root = _roots[attribute]; root = new MetavoxelNode(attribute); root->read(attribute, in); @@ -147,7 +147,7 @@ void MetavoxelData::write(Bitstream& out) const { out << _size; out << _roots.size(); for (QHash::const_iterator it = _roots.constBegin(); it != _roots.constEnd(); it++) { - out.getAttributeStreamer() << it.key(); + out << it.key(); it.value()->write(it.key(), out); } } @@ -176,7 +176,7 @@ void MetavoxelData::readDelta(const MetavoxelData& reference, Bitstream& in) { in >> changedCount; for (int i = 0; i < changedCount; i++) { AttributePointer attribute; - in.getAttributeStreamer() >> attribute; + in >> attribute; MetavoxelNode*& root = _roots[attribute]; if (root) { MetavoxelNode* oldRoot = root; @@ -194,7 +194,7 @@ void MetavoxelData::readDelta(const MetavoxelData& reference, Bitstream& in) { in >> removedCount; for (int i = 0; i < removedCount; i++) { AttributePointer attribute; - in.getAttributeStreamer() >> attribute; + in >> attribute; _roots.take(attribute)->decrementReferenceCount(attribute); } } @@ -234,7 +234,7 @@ void MetavoxelData::writeDelta(const MetavoxelData& reference, Bitstream& out) c for (QHash::const_iterator it = _roots.constBegin(); it != _roots.constEnd(); it++) { MetavoxelNode* referenceRoot = expandedReference->_roots.value(it.key()); if (it.value() != referenceRoot) { - out.getAttributeStreamer() << it.key(); + out << it.key(); if (referenceRoot) { it.value()->writeDelta(it.key(), *referenceRoot, out); } else { @@ -255,7 +255,7 @@ void MetavoxelData::writeDelta(const MetavoxelData& reference, Bitstream& out) c for (QHash::const_iterator it = expandedReference->_roots.constBegin(); it != expandedReference->_roots.constEnd(); it++) { if (!_roots.contains(it.key())) { - out.getAttributeStreamer() << it.key(); + out << it.key(); } } diff --git a/libraries/metavoxels/src/MetavoxelUtil.cpp b/libraries/metavoxels/src/MetavoxelUtil.cpp index 1620226386..58468bc271 100644 --- a/libraries/metavoxels/src/MetavoxelUtil.cpp +++ b/libraries/metavoxels/src/MetavoxelUtil.cpp @@ -21,9 +21,12 @@ #include #include "MetavoxelUtil.h" +#include "ScriptCache.h" +static int scriptHashType = qRegisterMetaType(); static int parameterizedURLType = qRegisterMetaType(); +REGISTER_SIMPLE_TYPE_STREAMER(ScriptHash) REGISTER_SIMPLE_TYPE_STREAMER(ParameterizedURL) class DelegatingItemEditorFactory : public QItemEditorFactory { @@ -106,7 +109,7 @@ bool Box::contains(const Box& other) const { other.minimum.z >= minimum.z && other.maximum.z <= maximum.z; } -ParameterizedURL::ParameterizedURL(const QUrl& url, const QVariantHash& parameters) : +ParameterizedURL::ParameterizedURL(const QUrl& url, const ScriptHash& parameters) : _url(url), _parameters(parameters) { } @@ -133,7 +136,7 @@ Bitstream& operator<<(Bitstream& out, const ParameterizedURL& url) { Bitstream& operator>>(Bitstream& in, ParameterizedURL& url) { QUrl qurl; in >> qurl; - QVariantHash parameters; + ScriptHash parameters; in >> parameters; url = ParameterizedURL(qurl, parameters); return in; @@ -146,16 +149,47 @@ ParameterizedURLEditor::ParameterizedURLEditor(QWidget* parent) : layout->setContentsMargins(QMargins()); setLayout(layout); - layout->addWidget(_line = new QLineEdit()); + QWidget* lineContainer = new QWidget(); + layout->addWidget(lineContainer); + + QHBoxLayout* lineLayout = new QHBoxLayout(); + lineContainer->setLayout(lineLayout); + lineLayout->setContentsMargins(QMargins()); + + lineLayout->addWidget(_line = new QLineEdit(), 1); connect(_line, SIGNAL(textChanged(const QString&)), SLOT(updateURL())); + + QPushButton* refresh = new QPushButton("..."); + connect(refresh, SIGNAL(clicked(bool)), SLOT(updateParameters())); + lineLayout->addWidget(refresh); } void ParameterizedURLEditor::setURL(const ParameterizedURL& url) { _url = url; _line->setText(url.getURL().toString()); + updateParameters(); } void ParameterizedURLEditor::updateURL() { _url = ParameterizedURL(_line->text()); emit urlChanged(_url); + if (_program) { + _program->disconnect(this); + } +} + +void ParameterizedURLEditor::updateParameters() { + if (_program) { + _program->disconnect(this); + } + _program = ScriptCache::getInstance()->getProgram(_url.getURL()); + if (_program->isLoaded()) { + continueUpdatingParameters(); + } else { + connect(_program.data(), SIGNAL(loaded()), SLOT(continueUpdatingParameters())); + } +} + +void ParameterizedURLEditor::continueUpdatingParameters() { + QScriptValue value = ScriptCache::getInstance()->getValue(_url.getURL())->getValue(); } diff --git a/libraries/metavoxels/src/MetavoxelUtil.h b/libraries/metavoxels/src/MetavoxelUtil.h index 1ae77766f7..ad3084fe56 100644 --- a/libraries/metavoxels/src/MetavoxelUtil.h +++ b/libraries/metavoxels/src/MetavoxelUtil.h @@ -9,6 +9,7 @@ #ifndef __interface__MetavoxelUtil__ #define __interface__MetavoxelUtil__ +#include #include #include #include @@ -19,6 +20,7 @@ class QByteArray; class QLineEdit; class HifiSockAddr; +class NetworkProgram; /// Reads and returns the session ID from a datagram. /// \param[out] headerPlusIDSize the size of the header (including the session ID) within the data @@ -39,19 +41,23 @@ public: DECLARE_STREAMABLE_METATYPE(Box) +typedef QHash ScriptHash; + +Q_DECLARE_METATYPE(ScriptHash) + /// Combines a URL with a set of typed parameters. class ParameterizedURL { public: - ParameterizedURL(const QUrl& url = QUrl(), const QVariantHash& parameters = QVariantHash()); + ParameterizedURL(const QUrl& url = QUrl(), const ScriptHash& parameters = ScriptHash()); bool isValid() const { return _url.isValid(); } void setURL(const QUrl& url) { _url = url; } const QUrl& getURL() const { return _url; } - void setParameters(const QVariantHash& parameters) { _parameters = parameters; } - const QVariantHash& getParameters() const { return _parameters; } + void setParameters(const ScriptHash& parameters) { _parameters = parameters; } + const ScriptHash& getParameters() const { return _parameters; } bool operator==(const ParameterizedURL& other) const; bool operator!=(const ParameterizedURL& other) const; @@ -59,7 +65,7 @@ public: private: QUrl _url; - QVariantHash _parameters; + ScriptHash _parameters; }; uint qHash(const ParameterizedURL& url, uint seed = 0); @@ -89,10 +95,14 @@ public slots: private slots: void updateURL(); + void updateParameters(); + void continueUpdatingParameters(); private: ParameterizedURL _url; + QSharedPointer _program; + QLineEdit* _line; }; diff --git a/libraries/metavoxels/src/ScriptCache.cpp b/libraries/metavoxels/src/ScriptCache.cpp index 18be6a1dea..8a6a5c39d9 100644 --- a/libraries/metavoxels/src/ScriptCache.cpp +++ b/libraries/metavoxels/src/ScriptCache.cpp @@ -15,7 +15,6 @@ #include #include "AttributeRegistry.h" -#include "MetavoxelUtil.h" #include "ScriptCache.h" ScriptCache* ScriptCache::getInstance() { @@ -49,7 +48,9 @@ QSharedPointer ScriptCache::getProgram(const QUrl& url) { QSharedPointer ScriptCache::getValue(const ParameterizedURL& url) { QSharedPointer value = _networkValues.value(url); if (value.isNull()) { - value = QSharedPointer(new NetworkValue(getProgram(url.getURL()), url.getParameters())); + value = QSharedPointer(url.getParameters().isEmpty() ? + (NetworkValue*)new RootNetworkValue(getProgram(url.getURL())) : + (NetworkValue*)new DerivedNetworkValue(getValue(url.getURL()), url.getParameters())); _networkValues.insert(url, value); } return value; @@ -94,6 +95,8 @@ void NetworkProgram::handleDownloadProgress(qint64 bytesReceived, qint64 bytesTo _reply->disconnect(this); _reply->deleteLater(); _reply = NULL; + + emit loaded(); } void NetworkProgram::handleReplyError() { @@ -112,14 +115,28 @@ void NetworkProgram::handleReplyError() { } } -NetworkValue::NetworkValue(const QSharedPointer& program, const QVariantHash& parameters) : - _program(program), - _parameters(parameters) { +NetworkValue::~NetworkValue() { } -QScriptValue& NetworkValue::getValue() { +RootNetworkValue::RootNetworkValue(const QSharedPointer& program) : + _program(program) { +} + +QScriptValue& RootNetworkValue::getValue() { if (!_value.isValid() && _program->isLoaded()) { _value = _program->getCache()->getEngine()->evaluate(_program->getProgram()); } return _value; } + +DerivedNetworkValue::DerivedNetworkValue(const QSharedPointer& baseValue, const ScriptHash& parameters) : + _baseValue(baseValue), + _parameters(parameters) { +} + +QScriptValue& DerivedNetworkValue::getValue() { + if (!_value.isValid() && _baseValue->isLoaded()) { + _value = _baseValue->getValue(); + } + return _value; +} diff --git a/libraries/metavoxels/src/ScriptCache.h b/libraries/metavoxels/src/ScriptCache.h index 6d4561d669..a75ae18c44 100644 --- a/libraries/metavoxels/src/ScriptCache.h +++ b/libraries/metavoxels/src/ScriptCache.h @@ -15,17 +15,16 @@ #include #include #include -#include #include +#include "MetavoxelUtil.h" + class QNetworkAccessManager; class QNetworkReply; class QScriptEngine; -class QUrl; class NetworkProgram; class NetworkValue; -class ParameterizedURL; /// Maintains a cache of loaded scripts. class ScriptCache : public QObject { @@ -55,6 +54,7 @@ private: QScriptEngine* _engine; QHash > _networkPrograms; QHash > _networkValues; + }; /// A program loaded from the network. @@ -71,7 +71,11 @@ public: bool isLoaded() const { return !_program.isNull(); } const QScriptProgram& getProgram() const { return _program; } - + +signals: + + void loaded(); + private slots: void makeRequest(); @@ -87,21 +91,46 @@ private: QScriptProgram _program; }; -/// A value loaded from the network. +/// Abstract base class of values loaded from the network. class NetworkValue { public: - NetworkValue(const QSharedPointer& program, const QVariantHash& parameters); - + virtual ~NetworkValue(); + bool isLoaded() { return getValue().isValid(); } - QScriptValue& getValue(); + virtual QScriptValue& getValue() = 0; + +protected: + + QScriptValue _value; +}; + +/// The direct result of running a program. +class RootNetworkValue : public NetworkValue { +public: + + RootNetworkValue(const QSharedPointer& program); + + virtual QScriptValue& getValue(); private: QSharedPointer _program; - QVariantHash _parameters; - QScriptValue _value; +}; + +/// The result of running a program's generator using a set of arguments. +class DerivedNetworkValue : public NetworkValue { +public: + + DerivedNetworkValue(const QSharedPointer& baseValue, const ScriptHash& parameters); + + virtual QScriptValue& getValue(); + +private: + + QSharedPointer _baseValue; + ScriptHash _parameters; }; #endif /* defined(__interface__ScriptCache__) */