From f1a586520103301f0a733afe2a866690ed369d02 Mon Sep 17 00:00:00 2001 From: ZappoMan Date: Thu, 12 Feb 2015 15:17:48 -0800 Subject: [PATCH 01/11] added more logging to persist and backup, fixed bug in start up case for no models.svo and backup --- libraries/octree/src/OctreePersistThread.cpp | 30 ++++++++++++++------ 1 file changed, 21 insertions(+), 9 deletions(-) diff --git a/libraries/octree/src/OctreePersistThread.cpp b/libraries/octree/src/OctreePersistThread.cpp index f0612cc9b1..b247f88059 100644 --- a/libraries/octree/src/OctreePersistThread.cpp +++ b/libraries/octree/src/OctreePersistThread.cpp @@ -213,7 +213,9 @@ void OctreePersistThread::persist() { } _tree->unlock(); + qDebug() << "persist operation calling backup..."; backup(); // handle backup if requested + qDebug() << "persist operation DONE with backup..."; // create our "lock" file to indicate we're saving. @@ -347,6 +349,7 @@ void OctreePersistThread::rollOldBackupVersions(const BackupRule& rule) { void OctreePersistThread::backup() { + qDebug() << "backup operation wantBackup:" << _wantBackup; if (_wantBackup) { quint64 now = usecTimestampNow(); @@ -354,10 +357,12 @@ void OctreePersistThread::backup() { BackupRule& rule = _backupRules[i]; quint64 sinceLastBackup = now - rule.lastBackup; - quint64 SECS_TO_USECS = 1000 * 1000; quint64 intervalToBackup = rule.interval * SECS_TO_USECS; - + + qDebug() << "Checking [" << rule.name << "] - Time since last backup [" << sinceLastBackup << "] " << + "compared to backup interval [" << intervalToBackup << "]..."; + if (sinceLastBackup > intervalToBackup) { qDebug() << "Time since last backup [" << sinceLastBackup << "] for rule [" << rule.name << "] exceeds backup interval [" << intervalToBackup << "] doing backup now..."; @@ -379,15 +384,22 @@ void OctreePersistThread::backup() { } - qDebug() << "backing up persist file " << _filename << "to" << backupFileName << "..."; - bool result = QFile::copy(_filename, backupFileName); - if (result) { - qDebug() << "DONE backing up persist file..."; + QFile persistFile(_filename); + if (persistFile.exists()) { + qDebug() << "backing up persist file " << _filename << "to" << backupFileName << "..."; + bool result = QFile::copy(_filename, backupFileName); + if (result) { + qDebug() << "DONE backing up persist file..."; + rule.lastBackup = now; // only record successful backup in this case. + } else { + qDebug() << "ERROR in backing up persist file..."; + } } else { - qDebug() << "ERROR in backing up persist file..."; + qDebug() << "persist file " << _filename << " does not exist. " << + "nothing to backup for this rule ["<< rule.name << "]..."; } - - rule.lastBackup = now; + } else { + qDebug() << "Backup not needed for this rule ["<< rule.name << "]..."; } } } From 07a12f8b4c818bbb1a6575c930c5b961b233cd80 Mon Sep 17 00:00:00 2001 From: Andrew Meadows Date: Thu, 12 Feb 2015 16:55:14 -0800 Subject: [PATCH 02/11] remove a couple crash modes on shutdown --- interface/src/Application.cpp | 37 ++++++++++++++++++++--------------- 1 file changed, 21 insertions(+), 16 deletions(-) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index c720ed7606..e33938d959 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -519,37 +519,31 @@ void Application::aboutToQuit() { } Application::~Application() { + // stop idle calls + delete idleTimer; + + // save settings QMetaObject::invokeMethod(&_settingsTimer, "stop", Qt::BlockingQueuedConnection); _settingsThread.quit(); saveSettings(); - - _entities.getTree()->setSimulation(NULL); - qInstallMessageHandler(NULL); - _window->saveGeometry(); - int DELAY_TIME = 1000; - UserActivityLogger::getInstance().close(DELAY_TIME); - - // make sure we don't call the idle timer any more - delete idleTimer; - // let the avatar mixer know we're out MyAvatar::sendKillAvatar(); + // log activity (sends data over HTTP) + // NOTE: there is still an occasional crash in UserActivitiyLogger::close() + int DELAY_TIME = 1000; + UserActivityLogger::getInstance().close(DELAY_TIME); + // ask the datagram processing thread to quit and wait until it is done _nodeThread->quit(); _nodeThread->wait(); - // kill any audio injectors that are still around + // kill audio AudioScriptingInterface::getInstance().stopAllInjectors(); - auto audioIO = DependencyManager::get(); - - // stop the audio process QMetaObject::invokeMethod(audioIO.data(), "stop", Qt::BlockingQueuedConnection); - - // ask the audio thread to quit and wait until it is done audioIO->thread()->quit(); audioIO->thread()->wait(); @@ -566,6 +560,17 @@ Application::~Application() { DependencyManager::destroy(); DependencyManager::destroy(); DependencyManager::destroy(); + + EntityTree* tree = _entities.getTree(); + tree->lockForWrite(); + _entities.getTree()->setSimulation(NULL); + tree->unlock(); + + qInstallMessageHandler(NULL); + + // At this point we return all memory to the operating system ASAP + // and don't worry about proper cleanup of global variables. + exit(0); } void Application::initializeGL() { From c3b432c4b5be2780244ebbb59154b7941400fb93 Mon Sep 17 00:00:00 2001 From: Andrew Meadows Date: Thu, 12 Feb 2015 17:02:21 -0800 Subject: [PATCH 03/11] wrap explicit exit() in #ifndef DEBUG --- interface/src/Application.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index e33938d959..57e7ffe065 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -568,9 +568,11 @@ Application::~Application() { qInstallMessageHandler(NULL); +#ifndef DEBUG // At this point we return all memory to the operating system ASAP // and don't worry about proper cleanup of global variables. exit(0); +#endif } void Application::initializeGL() { From 589077bce64ab3761b7e78db85d9372b03d6f093 Mon Sep 17 00:00:00 2001 From: Andrew Meadows Date: Fri, 13 Feb 2015 14:01:56 -0800 Subject: [PATCH 04/11] try again: move stuff around in ~Application --- interface/src/Application.cpp | 28 ++++++++++++++-------------- 1 file changed, 14 insertions(+), 14 deletions(-) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index a99fcde7ee..1e94d79457 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -523,13 +523,21 @@ void Application::aboutToQuit() { } void Application::cleanupBeforeQuit() { + // make sure we don't call the idle timer any more + delete idleTimer; + + // save state QMetaObject::invokeMethod(&_settingsTimer, "stop", Qt::BlockingQueuedConnection); _settingsThread.quit(); saveSettings(); + _window->saveGeometry(); // TODO: now that this is in cleanupBeforeQuit do we really need it to stop and force // an event loop to send the packet? UserActivityLogger::getInstance().close(); + + // let the avatar mixer know we're out + MyAvatar::sendKillAvatar(); // stop the AudioClient QMetaObject::invokeMethod(DependencyManager::get().data(), @@ -540,13 +548,12 @@ void Application::cleanupBeforeQuit() { } Application::~Application() { - _window->saveGeometry(); - - // make sure we don't call the idle timer any more - delete idleTimer; - - // let the avatar mixer know we're out - MyAvatar::sendKillAvatar(); + EntityTree* tree = _entities.getTree(); + tree->lockForWrite(); + _entities.getTree()->setSimulation(NULL); + tree->unlock(); + + qInstallMessageHandler(NULL); // ask the datagram processing thread to quit and wait until it is done _nodeThread->quit(); @@ -565,13 +572,6 @@ Application::~Application() { DependencyManager::destroy(); DependencyManager::destroy(); DependencyManager::destroy(); - - EntityTree* tree = _entities.getTree(); - tree->lockForWrite(); - _entities.getTree()->setSimulation(NULL); - tree->unlock(); - - qInstallMessageHandler(NULL); } void Application::initializeGL() { From bc5a1477e6bcd827b43daa5afddce72e6acc6609 Mon Sep 17 00:00:00 2001 From: ZappoMan Date: Fri, 13 Feb 2015 14:59:57 -0800 Subject: [PATCH 05/11] added logging of edit commands in the server --- .../src/entities/EntityServer.cpp | 11 ++++ assignment-client/src/entities/EntityServer.h | 1 + .../resources/describe-settings.json | 7 +++ libraries/entities/src/EntityItemProperties.h | 58 +++++++++++++++++-- .../entities/src/EntityItemPropertiesMacros.h | 4 ++ libraries/entities/src/EntityTree.cpp | 4 ++ libraries/entities/src/EntityTree.h | 5 ++ 7 files changed, 84 insertions(+), 6 deletions(-) diff --git a/assignment-client/src/entities/EntityServer.cpp b/assignment-client/src/entities/EntityServer.cpp index d882ea19ac..85d0a7414c 100644 --- a/assignment-client/src/entities/EntityServer.cpp +++ b/assignment-client/src/entities/EntityServer.cpp @@ -147,3 +147,14 @@ void EntityServer::pruneDeletedEntities() { } } +void EntityServer::readAdditionalConfiguration(const QJsonObject& settingsSectionObject) { + bool wantEditLogging = false; + readOptionBool(QString("wantEditLogging"), settingsSectionObject, wantEditLogging); + qDebug("wantEditLogging=%s", debug::valueOf(wantEditLogging)); + + + EntityTree* tree = static_cast(_tree); + tree->setWantEditLogging(wantEditLogging); +} + + diff --git a/assignment-client/src/entities/EntityServer.h b/assignment-client/src/entities/EntityServer.h index d072d18cdf..d8c2e39f3b 100644 --- a/assignment-client/src/entities/EntityServer.h +++ b/assignment-client/src/entities/EntityServer.h @@ -41,6 +41,7 @@ public: virtual int sendSpecialPacket(const SharedNodePointer& node, OctreeQueryNode* queryNode, int& packetsSent); virtual void entityCreated(const EntityItem& newEntity, const SharedNodePointer& senderNode); + virtual void readAdditionalConfiguration(const QJsonObject& settingsSectionObject); public slots: void pruneDeletedEntities(); diff --git a/domain-server/resources/describe-settings.json b/domain-server/resources/describe-settings.json index 1ff82f58eb..fdaede8c44 100644 --- a/domain-server/resources/describe-settings.json +++ b/domain-server/resources/describe-settings.json @@ -409,6 +409,13 @@ "default": "", "advanced": true }, + { + "name": "wantEditLogging", + "type": "checkbox", + "help": "Logging of all edits to entities", + "default": true, + "advanced": true + }, { "name": "verboseDebug", "type": "checkbox", diff --git a/libraries/entities/src/EntityItemProperties.h b/libraries/entities/src/EntityItemProperties.h index 4db6cd5d79..51779d3f56 100644 --- a/libraries/entities/src/EntityItemProperties.h +++ b/libraries/entities/src/EntityItemProperties.h @@ -194,6 +194,7 @@ public: bool containsBoundsProperties() const { return (_positionChanged || _dimensionsChanged); } bool containsPositionChange() const { return _positionChanged; } bool containsDimensionsChange() const { return _dimensionsChanged; } + bool containsAnimationSettingsChange() const { return _animationSettingsChanged; } float getGlowLevel() const { return _glowLevel; } float getLocalRenderAlpha() const { return _localRenderAlpha; } @@ -256,12 +257,57 @@ inline void EntityItemProperties::setPosition(const glm::vec3& value) inline QDebug operator<<(QDebug debug, const EntityItemProperties& properties) { - debug << "EntityItemProperties[" << "\n" - << " position:" << properties.getPosition() << "in meters" << "\n" - << " velocity:" << properties.getVelocity() << "in meters" << "\n" - << " last edited:" << properties.getLastEdited() << "\n" - << " edited ago:" << properties.getEditedAgo() << "\n" - << "]"; + debug << "EntityItemProperties[" << "\n"; + + // TODO: figure out why position and animationSettings don't seem to like the macro approach + if (properties.containsPositionChange()) { + debug << " position:" << properties.getPosition() << "in meters" << "\n"; + } + if (properties.containsAnimationSettingsChange()) { + debug << " animationSettings:" << properties.getAnimationSettings() << "\n"; + } + + DEBUG_PROPERTY_IF_CHANGED(debug, properties, Dimensions, dimensions, "in meters"); + DEBUG_PROPERTY_IF_CHANGED(debug, properties, Velocity, velocity, "in meters"); + DEBUG_PROPERTY_IF_CHANGED(debug, properties, Visible, visible, ""); + DEBUG_PROPERTY_IF_CHANGED(debug, properties, Rotation, rotation, ""); + DEBUG_PROPERTY_IF_CHANGED(debug, properties, Density, density, ""); + DEBUG_PROPERTY_IF_CHANGED(debug, properties, Gravity, gravity, ""); + DEBUG_PROPERTY_IF_CHANGED(debug, properties, Damping, damping, ""); + DEBUG_PROPERTY_IF_CHANGED(debug, properties, Lifetime, lifetime, ""); + DEBUG_PROPERTY_IF_CHANGED(debug, properties, Script, script, ""); + DEBUG_PROPERTY_IF_CHANGED(debug, properties, Color, color, ""); + DEBUG_PROPERTY_IF_CHANGED(debug, properties, ModelURL, modelURL, ""); + DEBUG_PROPERTY_IF_CHANGED(debug, properties, AnimationURL, animationURL, ""); + DEBUG_PROPERTY_IF_CHANGED(debug, properties, AnimationFPS, animationFPS, ""); + DEBUG_PROPERTY_IF_CHANGED(debug, properties, AnimationFrameIndex, animationFrameIndex, ""); + DEBUG_PROPERTY_IF_CHANGED(debug, properties, AnimationIsPlaying, animationIsPlaying, ""); + DEBUG_PROPERTY_IF_CHANGED(debug, properties, RegistrationPoint, registrationPoint, ""); + DEBUG_PROPERTY_IF_CHANGED(debug, properties, AngularVelocity, angularVelocity, ""); + DEBUG_PROPERTY_IF_CHANGED(debug, properties, AngularDamping, angularDamping, ""); + DEBUG_PROPERTY_IF_CHANGED(debug, properties, IgnoreForCollisions, ignoreForCollisions, ""); + DEBUG_PROPERTY_IF_CHANGED(debug, properties, CollisionsWillMove, collisionsWillMove, ""); + DEBUG_PROPERTY_IF_CHANGED(debug, properties, IsSpotlight, isSpotlight, ""); + DEBUG_PROPERTY_IF_CHANGED(debug, properties, DiffuseColor, diffuseColor, ""); + DEBUG_PROPERTY_IF_CHANGED(debug, properties, AmbientColor, ambientColor, ""); + DEBUG_PROPERTY_IF_CHANGED(debug, properties, SpecularColor, specularColor, ""); + DEBUG_PROPERTY_IF_CHANGED(debug, properties, ConstantAttenuation, constantAttenuation, ""); + DEBUG_PROPERTY_IF_CHANGED(debug, properties, LinearAttenuation, linearAttenuation, ""); + DEBUG_PROPERTY_IF_CHANGED(debug, properties, QuadraticAttenuation, quadraticAttenuation, ""); + DEBUG_PROPERTY_IF_CHANGED(debug, properties, Exponent, exponent, ""); + DEBUG_PROPERTY_IF_CHANGED(debug, properties, Cutoff, cutoff, ""); + DEBUG_PROPERTY_IF_CHANGED(debug, properties, Locked, locked, ""); + DEBUG_PROPERTY_IF_CHANGED(debug, properties, Textures, textures, ""); + DEBUG_PROPERTY_IF_CHANGED(debug, properties, UserData, userData, ""); + DEBUG_PROPERTY_IF_CHANGED(debug, properties, Text, text, ""); + DEBUG_PROPERTY_IF_CHANGED(debug, properties, LineHeight, lineHeight, ""); + DEBUG_PROPERTY_IF_CHANGED(debug, properties, TextColor, textColor, ""); + DEBUG_PROPERTY_IF_CHANGED(debug, properties, BackgroundColor, backgroundColor, ""); + DEBUG_PROPERTY_IF_CHANGED(debug, properties, ShapeType, shapeType, ""); + + debug << " last edited:" << properties.getLastEdited() << "\n"; + debug << " edited ago:" << properties.getEditedAgo() << "\n"; + debug << "]"; return debug; } diff --git a/libraries/entities/src/EntityItemPropertiesMacros.h b/libraries/entities/src/EntityItemPropertiesMacros.h index 518035c0d3..592f808e1a 100644 --- a/libraries/entities/src/EntityItemPropertiesMacros.h +++ b/libraries/entities/src/EntityItemPropertiesMacros.h @@ -321,6 +321,10 @@ T _##n; \ bool _##n##Changed; +#define DEBUG_PROPERTY_IF_CHANGED(D, P, N, n, x) \ + if (P.n##Changed()) { \ + D << " " << #n << ":" << P.get##N() << x << "\n"; \ + } #endif // hifi_EntityItemPropertiesMacros_h diff --git a/libraries/entities/src/EntityTree.cpp b/libraries/entities/src/EntityTree.cpp index 95617b4944..8bb759c1b4 100644 --- a/libraries/entities/src/EntityTree.cpp +++ b/libraries/entities/src/EntityTree.cpp @@ -592,6 +592,10 @@ int EntityTree::processEditPacketData(PacketType packetType, const unsigned char // if the EntityItem exists, then update it if (existingEntity) { + if (wantEditLogging()) { + qDebug() << "User [" << senderNode->getUUID() << "] editing entity. ID:" << entityItemID; + qDebug() << " properties:" << properties; + } updateEntity(entityItemID, properties, senderNode->getCanAdjustLocks()); existingEntity->markAsChangedOnServer(); } else { diff --git a/libraries/entities/src/EntityTree.h b/libraries/entities/src/EntityTree.h index 3bc0986799..d8b9b9f38f 100644 --- a/libraries/entities/src/EntityTree.h +++ b/libraries/entities/src/EntityTree.h @@ -151,6 +151,9 @@ public: void emitEntityScriptChanging(const EntityItemID& entityItemID); void setSimulation(EntitySimulation* simulation); + + bool wantEditLogging() const { return _wantEditLogging; } + void setWantEditLogging(bool value) { _wantEditLogging = value; } signals: void deletingEntity(const EntityItemID& entityID); @@ -180,6 +183,8 @@ private: QHash _entityToElementMap; EntitySimulation* _simulation; + + bool _wantEditLogging = false; }; #endif // hifi_EntityTree_h From 0495833ca6eb13b41373e67c9d4739541ada5d94 Mon Sep 17 00:00:00 2001 From: Ryan Huffman Date: Fri, 13 Feb 2015 15:00:37 -0800 Subject: [PATCH 06/11] Disallow entity models to be reset to natural dimensions if unknown --- examples/editEntities.js | 15 ++++++++++++--- 1 file changed, 12 insertions(+), 3 deletions(-) diff --git a/examples/editEntities.js b/examples/editEntities.js index a9b5bfeb16..f0bb123e96 100644 --- a/examples/editEntities.js +++ b/examples/editEntities.js @@ -957,9 +957,18 @@ PropertiesTool = function(opts) { selectionManager.saveProperties(); for (var i = 0; i < selectionManager.selections.length; i++) { var properties = selectionManager.savedProperties[selectionManager.selections[i].id]; - Entities.editEntity(selectionManager.selections[i], { - dimensions: properties.naturalDimensions, - }); + var naturalDimensions = properties.naturalDimensions; + + // If any of the natural dimensions are not 0, resize + if (properties.type == "Model" && naturalDimensions.x == 0 + && naturalDimensions.y == 0 || naturalDimensions.z == 0) { + Window.alert("Cannot reset entity to its natural dimensions: Model URL" + + " is invalid or the model has not yet been loaded."); + } else { + Entities.editEntity(selectionManager.selections[i], { + dimensions: properties.naturalDimensions, + }); + } } pushCommandForSelections(); selectionManager._update(); From 2df850eb8d75bd88aed5eec157a41618566cb437 Mon Sep 17 00:00:00 2001 From: Ryan Huffman Date: Fri, 13 Feb 2015 15:02:16 -0800 Subject: [PATCH 07/11] Fix natural dimensions check --- examples/editEntities.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/examples/editEntities.js b/examples/editEntities.js index f0bb123e96..b9e594a1c1 100644 --- a/examples/editEntities.js +++ b/examples/editEntities.js @@ -961,7 +961,7 @@ PropertiesTool = function(opts) { // If any of the natural dimensions are not 0, resize if (properties.type == "Model" && naturalDimensions.x == 0 - && naturalDimensions.y == 0 || naturalDimensions.z == 0) { + && naturalDimensions.y == 0 && naturalDimensions.z == 0) { Window.alert("Cannot reset entity to its natural dimensions: Model URL" + " is invalid or the model has not yet been loaded."); } else { From 98b445b22f9cac6e5a6e0ff86c3d8ad5d0a5e7e8 Mon Sep 17 00:00:00 2001 From: Seth Alves Date: Fri, 13 Feb 2015 15:21:03 -0800 Subject: [PATCH 08/11] the geometryCacheID for Rectangle3DOverlay wasn't being initialized (so was randomish). if they overlapped, some would be drawn looking like others --- interface/src/ui/overlays/Rectangle3DOverlay.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/interface/src/ui/overlays/Rectangle3DOverlay.cpp b/interface/src/ui/overlays/Rectangle3DOverlay.cpp index 6ee90b11cc..99023d389b 100644 --- a/interface/src/ui/overlays/Rectangle3DOverlay.cpp +++ b/interface/src/ui/overlays/Rectangle3DOverlay.cpp @@ -20,6 +20,7 @@ #include "Rectangle3DOverlay.h" Rectangle3DOverlay::Rectangle3DOverlay() { + _geometryCacheID(DependencyManager::get()->allocateID()) } Rectangle3DOverlay::Rectangle3DOverlay(const Rectangle3DOverlay* rectangle3DOverlay) : From 42511f3b7f1ad65d997e23f3e77c147dd5d933e6 Mon Sep 17 00:00:00 2001 From: Seth Alves Date: Fri, 13 Feb 2015 15:23:22 -0800 Subject: [PATCH 09/11] M-x mangle buffer --- interface/src/ui/overlays/Rectangle3DOverlay.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/interface/src/ui/overlays/Rectangle3DOverlay.cpp b/interface/src/ui/overlays/Rectangle3DOverlay.cpp index 99023d389b..7a88b327d1 100644 --- a/interface/src/ui/overlays/Rectangle3DOverlay.cpp +++ b/interface/src/ui/overlays/Rectangle3DOverlay.cpp @@ -19,8 +19,9 @@ #include "Rectangle3DOverlay.h" -Rectangle3DOverlay::Rectangle3DOverlay() { +Rectangle3DOverlay::Rectangle3DOverlay() : _geometryCacheID(DependencyManager::get()->allocateID()) +{ } Rectangle3DOverlay::Rectangle3DOverlay(const Rectangle3DOverlay* rectangle3DOverlay) : From 1fc0225939fa516333a17febfa8335922440bd1e Mon Sep 17 00:00:00 2001 From: ZappoMan Date: Fri, 13 Feb 2015 15:33:41 -0800 Subject: [PATCH 10/11] change ScriptCache and SoundCache to derive from Dependency --- assignment-client/src/Agent.cpp | 2 +- assignment-client/src/AssignmentClient.cpp | 2 +- interface/src/Application.cpp | 7 ++- interface/src/ui/CachesSizeDialog.cpp | 8 ++-- libraries/audio/src/SoundCache.cpp | 5 -- libraries/audio/src/SoundCache.h | 6 +-- libraries/metavoxels/src/Bitstream.cpp | 54 +++++++++++----------- libraries/metavoxels/src/MetavoxelUtil.cpp | 6 +-- libraries/metavoxels/src/ScriptCache.cpp | 9 +--- libraries/metavoxels/src/ScriptCache.h | 6 +-- tests/metavoxels/src/MetavoxelTests.cpp | 14 +++--- 11 files changed, 56 insertions(+), 63 deletions(-) diff --git a/assignment-client/src/Agent.cpp b/assignment-client/src/Agent.cpp index 08a510f32c..4755d9137a 100644 --- a/assignment-client/src/Agent.cpp +++ b/assignment-client/src/Agent.cpp @@ -208,7 +208,7 @@ void Agent::run() { _scriptEngine.init(); // must be done before we set up the viewers - _scriptEngine.registerGlobalObject("SoundCache", &SoundCache::getInstance()); + _scriptEngine.registerGlobalObject("SoundCache", DependencyManager::get().data()); _scriptEngine.registerGlobalObject("EntityViewer", &_entityViewer); _entityViewer.setJurisdictionListener(_scriptEngine.getEntityScriptingInterface()->getJurisdictionListener()); diff --git a/assignment-client/src/AssignmentClient.cpp b/assignment-client/src/AssignmentClient.cpp index 9eb2fad739..80f3cbab5e 100644 --- a/assignment-client/src/AssignmentClient.cpp +++ b/assignment-client/src/AssignmentClient.cpp @@ -136,7 +136,7 @@ AssignmentClient::AssignmentClient(int &argc, char **argv) : // Create Singleton objects on main thread NetworkAccessManager::getInstance(); - SoundCache::getInstance(); + auto soundCache = DependencyManager::get(); } void AssignmentClient::sendAssignmentRequest() { diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index 2011f9b82e..903cae413e 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -211,6 +211,8 @@ bool setupEssentials(int& argc, char** argv) { auto addressManager = DependencyManager::set(); auto nodeList = DependencyManager::set(NodeType::Agent, listenPort); auto geometryCache = DependencyManager::set(); + auto scriptCache = DependencyManager::set(); + auto soundCache = DependencyManager::set(); auto glowEffect = DependencyManager::set(); auto faceshift = DependencyManager::set(); auto audio = DependencyManager::set(); @@ -563,11 +565,14 @@ Application::~Application() { _myAvatar = NULL; DependencyManager::destroy(); + + qDebug() << "start destroying ResourceCaches Application::~Application() line:" << __LINE__; DependencyManager::destroy(); DependencyManager::destroy(); DependencyManager::destroy(); DependencyManager::destroy(); DependencyManager::destroy(); + qDebug() << "done destroying ResourceCaches Application::~Application() line:" << __LINE__; } void Application::initializeGL() { @@ -3466,7 +3471,7 @@ void Application::registerScriptEngineWithApplicationServices(ScriptEngine* scri scriptEngine->registerGlobalObject("Settings", SettingsScriptingInterface::getInstance()); scriptEngine->registerGlobalObject("AudioDevice", AudioDeviceScriptingInterface::getInstance()); scriptEngine->registerGlobalObject("AnimationCache", DependencyManager::get().data()); - scriptEngine->registerGlobalObject("SoundCache", &SoundCache::getInstance()); + scriptEngine->registerGlobalObject("SoundCache", DependencyManager::get().data()); scriptEngine->registerGlobalObject("Account", AccountScriptingInterface::getInstance()); scriptEngine->registerGlobalObject("Metavoxels", &_metavoxels); diff --git a/interface/src/ui/CachesSizeDialog.cpp b/interface/src/ui/CachesSizeDialog.cpp index 4d4457c922..d21d1c2db8 100644 --- a/interface/src/ui/CachesSizeDialog.cpp +++ b/interface/src/ui/CachesSizeDialog.cpp @@ -59,8 +59,8 @@ CachesSizeDialog::CachesSizeDialog(QWidget* parent) : void CachesSizeDialog::confirmClicked(bool checked) { DependencyManager::get()->setUnusedResourceCacheSize(_animations->value() * BYTES_PER_MEGABYTES); DependencyManager::get()->setUnusedResourceCacheSize(_geometries->value() * BYTES_PER_MEGABYTES); - ScriptCache::getInstance()->setUnusedResourceCacheSize(_scripts->value() * BYTES_PER_MEGABYTES); - SoundCache::getInstance().setUnusedResourceCacheSize(_sounds->value() * BYTES_PER_MEGABYTES); + DependencyManager::get()->setUnusedResourceCacheSize(_scripts->value() * BYTES_PER_MEGABYTES); + DependencyManager::get()->setUnusedResourceCacheSize(_sounds->value() * BYTES_PER_MEGABYTES); DependencyManager::get()->setUnusedResourceCacheSize(_textures->value() * BYTES_PER_MEGABYTES); QDialog::close(); @@ -69,8 +69,8 @@ void CachesSizeDialog::confirmClicked(bool checked) { void CachesSizeDialog::resetClicked(bool checked) { _animations->setValue(DependencyManager::get()->getUnusedResourceCacheSize() / BYTES_PER_MEGABYTES); _geometries->setValue(DependencyManager::get()->getUnusedResourceCacheSize() / BYTES_PER_MEGABYTES); - _scripts->setValue(ScriptCache::getInstance()->getUnusedResourceCacheSize() / BYTES_PER_MEGABYTES); - _sounds->setValue(SoundCache::getInstance().getUnusedResourceCacheSize() / BYTES_PER_MEGABYTES); + _scripts->setValue(DependencyManager::get()->getUnusedResourceCacheSize() / BYTES_PER_MEGABYTES); + _sounds->setValue(DependencyManager::get()->getUnusedResourceCacheSize() / BYTES_PER_MEGABYTES); _textures->setValue(DependencyManager::get()->getUnusedResourceCacheSize() / BYTES_PER_MEGABYTES); } diff --git a/libraries/audio/src/SoundCache.cpp b/libraries/audio/src/SoundCache.cpp index fe05372ce5..2949a6c70a 100644 --- a/libraries/audio/src/SoundCache.cpp +++ b/libraries/audio/src/SoundCache.cpp @@ -15,11 +15,6 @@ static int soundPointerMetaTypeId = qRegisterMetaType(); -SoundCache& SoundCache::getInstance() { - static SoundCache staticInstance; - return staticInstance; -} - SoundCache::SoundCache(QObject* parent) : ResourceCache(parent) { diff --git a/libraries/audio/src/SoundCache.h b/libraries/audio/src/SoundCache.h index f9fbf51c10..7942e16010 100644 --- a/libraries/audio/src/SoundCache.h +++ b/libraries/audio/src/SoundCache.h @@ -17,11 +17,11 @@ #include "Sound.h" /// Scriptable interface for sound loading. -class SoundCache : public ResourceCache { +class SoundCache : public ResourceCache, public Dependency { Q_OBJECT + SINGLETON_DEPENDENCY + public: - static SoundCache& getInstance(); - Q_INVOKABLE SharedSoundPointer getSound(const QUrl& url); protected: diff --git a/libraries/metavoxels/src/Bitstream.cpp b/libraries/metavoxels/src/Bitstream.cpp index 642562bfb5..9c672a415e 100644 --- a/libraries/metavoxels/src/Bitstream.cpp +++ b/libraries/metavoxels/src/Bitstream.cpp @@ -465,9 +465,9 @@ void Bitstream::writeRawDelta(const QScriptValue& value, const QScriptValue& ref } else if (reference.isArray()) { if (value.isArray()) { *this << false; - int length = value.property(ScriptCache::getInstance()->getLengthString()).toInt32(); + int length = value.property(DependencyManager::get()->getLengthString()).toInt32(); *this << length; - int referenceLength = reference.property(ScriptCache::getInstance()->getLengthString()).toInt32(); + int referenceLength = reference.property(DependencyManager::get()->getLengthString()).toInt32(); for (int i = 0; i < length; i++) { if (i < referenceLength) { writeDelta(value.property(i), reference.property(i)); @@ -555,7 +555,7 @@ void Bitstream::readRawDelta(QScriptValue& value, const QScriptValue& reference) } else { QVariant variant; readRawDelta(variant, reference.toVariant()); - value = ScriptCache::getInstance()->getEngine()->newVariant(variant); + value = DependencyManager::get()->getEngine()->newVariant(variant); } } else if (reference.isQObject()) { bool typeChanged; @@ -566,7 +566,7 @@ void Bitstream::readRawDelta(QScriptValue& value, const QScriptValue& reference) } else { QObject* object; readRawDelta(object, reference.toQObject()); - value = ScriptCache::getInstance()->getEngine()->newQObject(object, QScriptEngine::ScriptOwnership); + value = DependencyManager::get()->getEngine()->newQObject(object, QScriptEngine::ScriptOwnership); } } else if (reference.isQMetaObject()) { bool typeChanged; @@ -577,7 +577,7 @@ void Bitstream::readRawDelta(QScriptValue& value, const QScriptValue& reference) } else { const QMetaObject* metaObject; *this >> metaObject; - value = ScriptCache::getInstance()->getEngine()->newQMetaObject(metaObject); + value = DependencyManager::get()->getEngine()->newQMetaObject(metaObject); } } else if (reference.isDate()) { bool typeChanged; @@ -588,7 +588,7 @@ void Bitstream::readRawDelta(QScriptValue& value, const QScriptValue& reference) } else { QDateTime dateTime; *this >> dateTime; - value = ScriptCache::getInstance()->getEngine()->newDate(dateTime); + value = DependencyManager::get()->getEngine()->newDate(dateTime); } } else if (reference.isRegExp()) { bool typeChanged; @@ -599,7 +599,7 @@ void Bitstream::readRawDelta(QScriptValue& value, const QScriptValue& reference) } else { QRegExp regExp; *this >> regExp; - value = ScriptCache::getInstance()->getEngine()->newRegExp(regExp); + value = DependencyManager::get()->getEngine()->newRegExp(regExp); } } else if (reference.isArray()) { bool typeChanged; @@ -610,8 +610,8 @@ void Bitstream::readRawDelta(QScriptValue& value, const QScriptValue& reference) } else { int length; *this >> length; - value = ScriptCache::getInstance()->getEngine()->newArray(length); - int referenceLength = reference.property(ScriptCache::getInstance()->getLengthString()).toInt32(); + value = DependencyManager::get()->getEngine()->newArray(length); + int referenceLength = reference.property(DependencyManager::get()->getLengthString()).toInt32(); for (int i = 0; i < length; i++) { QScriptValue element; if (i < referenceLength) { @@ -630,7 +630,7 @@ void Bitstream::readRawDelta(QScriptValue& value, const QScriptValue& reference) } else { // start by shallow-copying the reference - value = ScriptCache::getInstance()->getEngine()->newObject(); + value = DependencyManager::get()->getEngine()->newObject(); for (QScriptValueIterator it(reference); it.hasNext(); ) { it.next(); value.setProperty(it.scriptName(), it.value()); @@ -1036,7 +1036,7 @@ Bitstream& Bitstream::operator<<(const QScriptValue& value) { } else if (value.isArray()) { writeScriptValueType(*this, ARRAY_SCRIPT_VALUE); - int length = value.property(ScriptCache::getInstance()->getLengthString()).toInt32(); + int length = value.property(DependencyManager::get()->getLengthString()).toInt32(); *this << length; for (int i = 0; i < length; i++) { *this << value.property(i); @@ -1087,37 +1087,37 @@ Bitstream& Bitstream::operator>>(QScriptValue& value) { case VARIANT_SCRIPT_VALUE: { QVariant variantValue; *this >> variantValue; - value = ScriptCache::getInstance()->getEngine()->newVariant(variantValue); + value = DependencyManager::get()->getEngine()->newVariant(variantValue); break; } case QOBJECT_SCRIPT_VALUE: { QObject* object; *this >> object; - ScriptCache::getInstance()->getEngine()->newQObject(object, QScriptEngine::ScriptOwnership); + DependencyManager::get()->getEngine()->newQObject(object, QScriptEngine::ScriptOwnership); break; } case QMETAOBJECT_SCRIPT_VALUE: { const QMetaObject* metaObject; *this >> metaObject; - ScriptCache::getInstance()->getEngine()->newQMetaObject(metaObject); + DependencyManager::get()->getEngine()->newQMetaObject(metaObject); break; } case DATE_SCRIPT_VALUE: { QDateTime dateTime; *this >> dateTime; - value = ScriptCache::getInstance()->getEngine()->newDate(dateTime); + value = DependencyManager::get()->getEngine()->newDate(dateTime); break; } case REGEXP_SCRIPT_VALUE: { QRegExp regExp; *this >> regExp; - value = ScriptCache::getInstance()->getEngine()->newRegExp(regExp); + value = DependencyManager::get()->getEngine()->newRegExp(regExp); break; } case ARRAY_SCRIPT_VALUE: { int length; *this >> length; - value = ScriptCache::getInstance()->getEngine()->newArray(length); + value = DependencyManager::get()->getEngine()->newArray(length); for (int i = 0; i < length; i++) { QScriptValue element; *this >> element; @@ -1126,7 +1126,7 @@ Bitstream& Bitstream::operator>>(QScriptValue& value) { break; } case OBJECT_SCRIPT_VALUE: { - value = ScriptCache::getInstance()->getEngine()->newObject(); + value = DependencyManager::get()->getEngine()->newObject(); forever { QScriptString name; *this >> name; @@ -1477,7 +1477,7 @@ Bitstream& Bitstream::operator>(QScriptString& string) { QString rawString; *this >> rawString; string = (rawString == INVALID_STRING) ? QScriptString() : - ScriptCache::getInstance()->getEngine()->toStringHandle(rawString); + DependencyManager::get()->getEngine()->toStringHandle(rawString); return *this; } @@ -1828,7 +1828,7 @@ QJsonValue JSONWriter::getData(const QScriptValue& value) { } else if (value.isArray()) { object.insert("type", QString("ARRAY")); QJsonArray array; - int length = value.property(ScriptCache::getInstance()->getLengthString()).toInt32(); + int length = value.property(DependencyManager::get()->getLengthString()).toInt32(); for (int i = 0; i < length; i++) { array.append(getData(value.property(i))); } @@ -2209,31 +2209,31 @@ void JSONReader::putData(const QJsonValue& data, QScriptValue& value) { } else if (type == "VARIANT") { QVariant variant; putData(object.value("value"), variant); - value = ScriptCache::getInstance()->getEngine()->newVariant(variant); + value = DependencyManager::get()->getEngine()->newVariant(variant); } else if (type == "QOBJECT") { QObject* qObject; putData(object.value("value"), qObject); - value = ScriptCache::getInstance()->getEngine()->newQObject(qObject, QScriptEngine::ScriptOwnership); + value = DependencyManager::get()->getEngine()->newQObject(qObject, QScriptEngine::ScriptOwnership); } else if (type == "QMETAOBJECT") { const QMetaObject* metaObject; putData(object.value("value"), metaObject); - value = ScriptCache::getInstance()->getEngine()->newQMetaObject(metaObject); + value = DependencyManager::get()->getEngine()->newQMetaObject(metaObject); } else if (type == "DATE") { QDateTime dateTime; putData(object.value("value"), dateTime); - value = ScriptCache::getInstance()->getEngine()->newDate(dateTime); + value = DependencyManager::get()->getEngine()->newDate(dateTime); } else if (type == "REGEXP") { QRegExp regExp; putData(object.value("value"), regExp); - value = ScriptCache::getInstance()->getEngine()->newRegExp(regExp); + value = DependencyManager::get()->getEngine()->newRegExp(regExp); } else if (type == "ARRAY") { QJsonArray array = object.value("value").toArray(); - value = ScriptCache::getInstance()->getEngine()->newArray(array.size()); + value = DependencyManager::get()->getEngine()->newArray(array.size()); for (int i = 0; i < array.size(); i++) { QScriptValue element; putData(array.at(i), element); @@ -2241,7 +2241,7 @@ void JSONReader::putData(const QJsonValue& data, QScriptValue& value) { } } else if (type == "OBJECT") { QJsonObject jsonObject = object.value("value").toObject(); - value = ScriptCache::getInstance()->getEngine()->newObject(); + value = DependencyManager::get()->getEngine()->newObject(); for (QJsonObject::const_iterator it = jsonObject.constBegin(); it != jsonObject.constEnd(); it++) { QScriptValue element; putData(it.value(), element); diff --git a/libraries/metavoxels/src/MetavoxelUtil.cpp b/libraries/metavoxels/src/MetavoxelUtil.cpp index 73900fdcbc..4e86e1c636 100644 --- a/libraries/metavoxels/src/MetavoxelUtil.cpp +++ b/libraries/metavoxels/src/MetavoxelUtil.cpp @@ -663,7 +663,7 @@ void ParameterizedURLEditor::updateURL() { QByteArray valuePropertyName = widget->property("valuePropertyName").toByteArray(); const QMetaObject* widgetMetaObject = widget->metaObject(); QMetaProperty widgetProperty = widgetMetaObject->property(widgetMetaObject->indexOfProperty(valuePropertyName)); - parameters.insert(ScriptCache::getInstance()->getEngine()->toStringHandle( + parameters.insert(DependencyManager::get()->getEngine()->toStringHandle( widget->property("parameterName").toString()), widgetProperty.read(widget)); } } @@ -677,7 +677,7 @@ void ParameterizedURLEditor::updateParameters() { if (_program) { _program->disconnect(this); } - _program = ScriptCache::getInstance()->getProgram(_url.getURL()); + _program = DependencyManager::get()->getProgram(_url.getURL()); if (_program->isLoaded()) { continueUpdatingParameters(); } else { @@ -698,7 +698,7 @@ void ParameterizedURLEditor::continueUpdatingParameters() { } delete form; } - QSharedPointer value = ScriptCache::getInstance()->getValue(_url.getURL()); + QSharedPointer value = DependencyManager::get()->getValue(_url.getURL()); const QList& parameters = static_cast(value.data())->getParameterInfo(); if (parameters.isEmpty()) { return; diff --git a/libraries/metavoxels/src/ScriptCache.cpp b/libraries/metavoxels/src/ScriptCache.cpp index 7e8dbc4bae..b7e81b5381 100644 --- a/libraries/metavoxels/src/ScriptCache.cpp +++ b/libraries/metavoxels/src/ScriptCache.cpp @@ -57,8 +57,8 @@ bool operator==(const QScriptValue& first, const QScriptValue& second) { if (!second.isArray()) { return false; } - int length = first.property(ScriptCache::getInstance()->getLengthString()).toInt32(); - if (second.property(ScriptCache::getInstance()->getLengthString()).toInt32() != length) { + int length = first.property(DependencyManager::get()->getLengthString()).toInt32(); + if (second.property(DependencyManager::get()->getLengthString()).toInt32() != length) { return false; } for (int i = 0; i < length; i++) { @@ -103,11 +103,6 @@ bool operator<(const QScriptValue& first, const QScriptValue& second) { return first.lessThan(second); } -ScriptCache* ScriptCache::getInstance() { - static ScriptCache cache; - return &cache; -} - ScriptCache::ScriptCache() : _engine(NULL) { diff --git a/libraries/metavoxels/src/ScriptCache.h b/libraries/metavoxels/src/ScriptCache.h index 5d29157b3d..b9294a7504 100644 --- a/libraries/metavoxels/src/ScriptCache.h +++ b/libraries/metavoxels/src/ScriptCache.h @@ -25,13 +25,11 @@ class NetworkProgram; class NetworkValue; /// Maintains a cache of loaded scripts. -class ScriptCache : public ResourceCache { +class ScriptCache : public ResourceCache, public Dependency { Q_OBJECT + SINGLETON_DEPENDENCY public: - - static ScriptCache* getInstance(); - ScriptCache(); void setEngine(QScriptEngine* engine); diff --git a/tests/metavoxels/src/MetavoxelTests.cpp b/tests/metavoxels/src/MetavoxelTests.cpp index 106c56b0fe..938b5470e8 100644 --- a/tests/metavoxels/src/MetavoxelTests.cpp +++ b/tests/metavoxels/src/MetavoxelTests.cpp @@ -219,14 +219,14 @@ static QScriptValue createRandomScriptValue(bool complex = false, bool ensureHas case 4: { int length = randIntInRange(2, 6); - QScriptValue value = ScriptCache::getInstance()->getEngine()->newArray(length); + QScriptValue value = DependencyManager::get()->getEngine()->newArray(length); for (int i = 0; i < length; i++) { value.setProperty(i, createRandomScriptValue()); } return value; } default: { - QScriptValue value = ScriptCache::getInstance()->getEngine()->newObject(); + QScriptValue value = DependencyManager::get()->getEngine()->newObject(); if (ensureHashOrder) { // we can't depend on the iteration order, so if we need it to be the same (as when comparing bytes), we // can only have one property @@ -747,7 +747,7 @@ static SharedObjectPointer mutate(const SharedObjectPointer& state) { case 3: { SharedObjectPointer newState = state->clone(true); QScriptValue oldValue = static_cast(newState.data())->getBizzle(); - QScriptValue newValue = ScriptCache::getInstance()->getEngine()->newObject(); + QScriptValue newValue = DependencyManager::get()->getEngine()->newObject(); for (QScriptValueIterator it(oldValue); it.hasNext(); ) { it.next(); newValue.setProperty(it.scriptName(), it.value()); @@ -755,8 +755,8 @@ static SharedObjectPointer mutate(const SharedObjectPointer& state) { switch (randIntInRange(0, 2)) { case 0: { QScriptValue oldArray = oldValue.property("foo"); - int oldLength = oldArray.property(ScriptCache::getInstance()->getLengthString()).toInt32(); - QScriptValue newArray = ScriptCache::getInstance()->getEngine()->newArray(oldLength); + int oldLength = oldArray.property(DependencyManager::get()->getLengthString()).toInt32(); + QScriptValue newArray = DependencyManager::get()->getEngine()->newArray(oldLength); for (int i = 0; i < oldLength; i++) { newArray.setProperty(i, oldArray.property(i)); } @@ -1203,8 +1203,8 @@ TestSharedObjectA::TestSharedObjectA(float foo, TestEnum baz, TestFlags bong) : _bong(bong) { sharedObjectsCreated++; - _bizzle = ScriptCache::getInstance()->getEngine()->newObject(); - _bizzle.setProperty("foo", ScriptCache::getInstance()->getEngine()->newArray(4)); + _bizzle = DependencyManager::get()->getEngine()->newObject(); + _bizzle.setProperty("foo", DependencyManager::get()->getEngine()->newArray(4)); } TestSharedObjectA::~TestSharedObjectA() { From cfbf8fdca763d812eb4bd52e121f7fcf03122c33 Mon Sep 17 00:00:00 2001 From: Andrew Meadows Date: Fri, 13 Feb 2015 16:19:10 -0800 Subject: [PATCH 11/11] explicit cleanup of loaded model animations in Application dtor --- interface/src/Application.cpp | 3 +++ libraries/entities/src/ModelEntityItem.cpp | 10 ---------- 2 files changed, 3 insertions(+), 10 deletions(-) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index 1e94d79457..cee5404287 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -65,6 +65,7 @@ #include #include #include +#include #include #include #include @@ -565,6 +566,8 @@ Application::~Application() { Menu::getInstance()->deleteLater(); _myAvatar = NULL; + + ModelEntityItem::cleanupLoadedAnimations() ; DependencyManager::destroy(); DependencyManager::destroy(); diff --git a/libraries/entities/src/ModelEntityItem.cpp b/libraries/entities/src/ModelEntityItem.cpp index 4d8e741cc6..ed76b8c99f 100644 --- a/libraries/entities/src/ModelEntityItem.cpp +++ b/libraries/entities/src/ModelEntityItem.cpp @@ -163,16 +163,6 @@ void ModelEntityItem::appendSubclassData(OctreePacketData* packetData, EncodeBit QMap ModelEntityItem::_loadedAnimations; // TODO: improve cleanup by leveraging the AnimationPointer(s) -// This class/instance will cleanup the animations once unloaded. -class EntityAnimationsBookkeeper { -public: - ~EntityAnimationsBookkeeper() { - ModelEntityItem::cleanupLoadedAnimations(); - } -}; - -EntityAnimationsBookkeeper modelAnimationsBookkeeperInstance; - void ModelEntityItem::cleanupLoadedAnimations() { foreach(AnimationPointer animation, _loadedAnimations) { animation.clear();