From 8449575fa231cfe504cbfcecc395d2f447f59f16 Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Mon, 1 Dec 2014 09:25:21 -0800 Subject: [PATCH 01/14] fix for ice-server heartbeat without an access token --- domain-server/src/DomainServer.cpp | 45 ++++++++++++++++-------------- 1 file changed, 24 insertions(+), 21 deletions(-) diff --git a/domain-server/src/DomainServer.cpp b/domain-server/src/DomainServer.cpp index ddc06c8015..80777ce529 100644 --- a/domain-server/src/DomainServer.cpp +++ b/domain-server/src/DomainServer.cpp @@ -337,9 +337,31 @@ bool DomainServer::optionallySetupAssignmentPayment() { void DomainServer::setupAutomaticNetworking() { + LimitedNodeList* nodeList = LimitedNodeList::getInstance(); + + const int STUN_REFLEXIVE_KEEPALIVE_INTERVAL_MSECS = 10 * 1000; + const int STUN_IP_ADDRESS_CHECK_INTERVAL_MSECS = 30 * 1000; + + // setup our timer to check our IP via stun every X seconds + QTimer* dynamicIPTimer = new QTimer(this); + connect(dynamicIPTimer, &QTimer::timeout, this, &DomainServer::requestCurrentPublicSocketViaSTUN); + + if (_automaticNetworkingSetting == FULL_AUTOMATIC_NETWORKING_VALUE) { + dynamicIPTimer->start(STUN_REFLEXIVE_KEEPALIVE_INTERVAL_MSECS); + + // setup a timer to heartbeat with the ice-server every so often + QTimer* iceHeartbeatTimer = new QTimer(this); + connect(iceHeartbeatTimer, &QTimer::timeout, this, &DomainServer::performICEUpdates); + iceHeartbeatTimer->start(ICE_HEARBEAT_INTERVAL_MSECS); + + // call our sendHeartbeaToIceServer immediately anytime a local or public socket changes + connect(nodeList, &LimitedNodeList::localSockAddrChanged, this, &DomainServer::sendHeartbeatToIceServer); + connect(nodeList, &LimitedNodeList::publicSockAddrChanged, this, &DomainServer::sendHeartbeatToIceServer); + } + if (!didSetupAccountManagerWithAccessToken()) { - qDebug() << "Cannot setup domain-server automatic networking without an access token."; - qDebug() << "Please add an access token to your config file or via the web interface."; + qDebug() << "Cannot send heartbeat to data server without an access token."; + qDebug() << "Add an access token to your config file or via the web interface."; return; } @@ -350,37 +372,18 @@ void DomainServer::setupAutomaticNetworking() { if (_automaticNetworkingSetting == IP_ONLY_AUTOMATIC_NETWORKING_VALUE || _automaticNetworkingSetting == FULL_AUTOMATIC_NETWORKING_VALUE) { - LimitedNodeList* nodeList = LimitedNodeList::getInstance(); const QUuid& domainID = nodeList->getSessionUUID(); if (!domainID.isNull()) { qDebug() << "domain-server" << _automaticNetworkingSetting << "automatic networking enabled for ID" << uuidStringWithoutCurlyBraces(domainID) << "via" << _oauthProviderURL.toString(); - const int STUN_IP_ADDRESS_CHECK_INTERVAL_MSECS = 30 * 1000; - const int STUN_REFLEXIVE_KEEPALIVE_INTERVAL_MSECS = 10 * 1000; - - // setup our timer to check our IP via stun every X seconds - QTimer* dynamicIPTimer = new QTimer(this); - connect(dynamicIPTimer, &QTimer::timeout, this, &DomainServer::requestCurrentPublicSocketViaSTUN); - if (_automaticNetworkingSetting == IP_ONLY_AUTOMATIC_NETWORKING_VALUE) { dynamicIPTimer->start(STUN_IP_ADDRESS_CHECK_INTERVAL_MSECS); // send public socket changes to the data server so nodes can find us at our new IP connect(nodeList, &LimitedNodeList::publicSockAddrChanged, this, &DomainServer::performIPAddressUpdate); } else { - dynamicIPTimer->start(STUN_REFLEXIVE_KEEPALIVE_INTERVAL_MSECS); - - // setup a timer to heartbeat with the ice-server every so often - QTimer* iceHeartbeatTimer = new QTimer(this); - connect(iceHeartbeatTimer, &QTimer::timeout, this, &DomainServer::performICEUpdates); - iceHeartbeatTimer->start(ICE_HEARBEAT_INTERVAL_MSECS); - - // call our sendHeartbeaToIceServer immediately anytime a local or public socket changes - connect(nodeList, &LimitedNodeList::localSockAddrChanged, this, &DomainServer::sendHeartbeatToIceServer); - connect(nodeList, &LimitedNodeList::publicSockAddrChanged, this, &DomainServer::sendHeartbeatToIceServer); - // send our heartbeat to data server so it knows what our network settings are sendHeartbeatToDataServer(); } From 40db44e4bd708831694cc283cccb03e5174c23e3 Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Mon, 1 Dec 2014 09:59:51 -0800 Subject: [PATCH 02/14] fix for custom hifi URL lookup --- interface/src/Application.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index 20ae07b0c9..31b73274fc 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -842,7 +842,7 @@ bool Application::event(QEvent* event) { QFileOpenEvent* fileEvent = static_cast(event); if (!fileEvent->url().isEmpty()) { - AddressManager::getInstance().handleLookupString(fileEvent->url().toLocalFile()); + AddressManager::getInstance().handleLookupString(fileEvent->url().toString()); } return false; From 7f36a11f3539ec07ca807ea097d813d48acd2627 Mon Sep 17 00:00:00 2001 From: David Rowe Date: Mon, 1 Dec 2014 10:40:37 -0800 Subject: [PATCH 03/14] Find Oculus libraries when using Visual Studio 2013 --- cmake/modules/FindLibOVR.cmake | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/cmake/modules/FindLibOVR.cmake b/cmake/modules/FindLibOVR.cmake index a1d75add3f..6ffb3ed309 100644 --- a/cmake/modules/FindLibOVR.cmake +++ b/cmake/modules/FindLibOVR.cmake @@ -48,8 +48,13 @@ elseif (UNIX) select_library_configurations(XINERAMA) elseif (WIN32) - find_library(LIBOVR_LIBRARY_DEBUG NAMES libovrd PATH_SUFFIXES Lib/Win32/VS2010 HINTS ${LIBOVR_SEARCH_DIRS}) - find_library(LIBOVR_LIBRARY_RELEASE NAMES libovr PATH_SUFFIXES Lib/Win32/VS2010 HINTS ${LIBOVR_SEARCH_DIRS}) + if (MSVC10) + find_library(LIBOVR_LIBRARY_DEBUG NAMES libovrd PATH_SUFFIXES Lib/Win32/VS2010 HINTS ${LIBOVR_SEARCH_DIRS}) + find_library(LIBOVR_LIBRARY_RELEASE NAMES libovr PATH_SUFFIXES Lib/Win32/VS2010 HINTS ${LIBOVR_SEARCH_DIRS}) + elseif (MSVC12) + find_library(LIBOVR_LIBRARY_DEBUG NAMES libovrd PATH_SUFFIXES Lib/Win32/VS2013 HINTS ${LIBOVR_SEARCH_DIRS}) + find_library(LIBOVR_LIBRARY_RELEASE NAMES libovr PATH_SUFFIXES Lib/Win32/VS2013 HINTS ${LIBOVR_SEARCH_DIRS}) + endif () find_package(ATL) endif () From 09eb150edc9adb0e06ac9931633ce00115e99240 Mon Sep 17 00:00:00 2001 From: David Rowe Date: Mon, 1 Dec 2014 11:40:35 -0800 Subject: [PATCH 04/14] Update build instructions for VS2013 Community and Professional --- BUILD.md | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-) diff --git a/BUILD.md b/BUILD.md index d6e1603f37..e1d920b8df 100644 --- a/BUILD.md +++ b/BUILD.md @@ -96,12 +96,13 @@ Currently building on Windows has been tested using the following compilers: #####Windows SDK 7.1 -Whichever version of Visual Studio you use, you will need [Microsoft Windows SDK for Windows 7 and .NET Framework 4](http://www.microsoft.com/en-us/download/details.aspx?id=8279). +If using Visual Studio 2010, or using Visual Studio 2013 but building as a Visual Studio 2010 project, you need [Microsoft Windows SDK for Windows 7 and .NET Framework 4](http://www.microsoft.com/en-us/download/details.aspx?id=8279). NOTE: If using Visual Studio C++ 2010 Express, you need to follow a specific install order. See below before installing the Windows SDK. -######Windows 8.1 -You may have already downloaded the Windows 8 SDK (e.g. if you have previously installed Visual Studio 2013). If so, change CMAKE_PREFIX_PATH in %HIFI_DIR%\CMakeLists.txt to point to the Windows 8 SDK binaries. The default path is `C:\Program Files (x86)\Windows Kits\8.1\Lib\winv6.3\um\x86` +######Windows SDK 8.1 + +If using Visual Studio 2013 and building as a Visual Studio 2013 project you need the Windows 8 SDK which you should already have as part of installing Visual Studio 2013. You should be able to see it at `C:\Program Files (x86)\Windows Kits\8.1\Lib\winv6.3\um\x86`. #####Visual Studio C++ 2010 Express @@ -123,9 +124,11 @@ Some of the build instructions will ask you to start a Visual Studio Command Pro #####Visual Studio 2013 -This product must be purchased separately. +You can use the Community or Professional editions of Visual Studio 2013. -Visual Studio 2013 doesn't have a shortcut to start a Visual Studio Command Prompt. Instead, start a regular command prompt and then run: +You can start a Visual Studio 2013 command prompt using the shortcut provided in the Visual Studio Tools folder installed as part of Visual Studio 2013. + +Or you can start a regular command prompt and then run: "%VS120COMNTOOLS%\vsvars32.bat" @@ -146,6 +149,8 @@ Once Qt is installed, you need to manually configure the following: * Make sure the Qt runtime DLLs are loadable. You must do this before you attempt to build because some tools for the build depend on Qt. E.g., add to the PATH: `Qt\5.2.0\msvc2010_opengl\bin\`. * Set the QT_CMAKE_PREFIX_PATH environment variable to your `Qt\5.2.0\msvc2010_opengl` directory. +If building as a Visual Studio 2013 project, download and configure the msvc2013 version of Qt instead. + ####External Libraries CMake will need to know where the headers and libraries for required external dependencies are. From 845e687fc579add8016dd593d41f94f9a956dad2 Mon Sep 17 00:00:00 2001 From: Sam Gateau Date: Mon, 1 Dec 2014 11:45:07 -0800 Subject: [PATCH 05/14] Adding a Hack for the apaartment model to boost the lightmaps --- interface/src/renderer/GeometryCache.cpp | 5 ++++- libraries/fbx/src/FBXReader.cpp | 7 ++++--- libraries/fbx/src/FBXReader.h | 2 +- 3 files changed, 9 insertions(+), 5 deletions(-) diff --git a/interface/src/renderer/GeometryCache.cpp b/interface/src/renderer/GeometryCache.cpp index 04b59e7ea1..e2517613df 100644 --- a/interface/src/renderer/GeometryCache.cpp +++ b/interface/src/renderer/GeometryCache.cpp @@ -835,11 +835,14 @@ void GeometryReader::run() { fbxgeo = readSVO(_reply->readAll()); } else { bool grabLightmaps = true; + float lightmapLevel = 1.0f; // HACK: For monday 12/01/2014 we need to kill lighmaps loading in starchamber... if (_url.path().toLower().endsWith("loungev4_11-18.fbx")) { grabLightmaps = false; + } else if (_url.path().toLower().endsWith("apt8_reboot.fbx")) { + lightmapLevel = 4.0f; } - fbxgeo = readFBX(_reply->readAll(), _mapping, grabLightmaps); + fbxgeo = readFBX(_reply->readAll(), _mapping, grabLightmaps, lightmapLevel); } QMetaObject::invokeMethod(geometry.data(), "setGeometry", Q_ARG(const FBXGeometry&, fbxgeo)); diff --git a/libraries/fbx/src/FBXReader.cpp b/libraries/fbx/src/FBXReader.cpp index d77cbbd0a1..5f215ac4d0 100644 --- a/libraries/fbx/src/FBXReader.cpp +++ b/libraries/fbx/src/FBXReader.cpp @@ -1194,7 +1194,7 @@ int matchTextureUVSetToAttributeChannel(const std::string& texUVSetName, const Q } } -FBXGeometry extractFBXGeometry(const FBXNode& node, const QVariantHash& mapping, bool loadLightmaps) { +FBXGeometry extractFBXGeometry(const FBXNode& node, const QVariantHash& mapping, bool loadLightmaps, float lightmapLevel) { QHash meshes; QHash modelIDsToNames; QHash meshIDsToMeshIndices; @@ -1954,6 +1954,7 @@ FBXGeometry extractFBXGeometry(const FBXNode& node, const QVariantHash& mapping, FBXTexture emissiveTexture; glm::vec2 emissiveParams(0.f, 1.f); + emissiveParams.y = lightmapLevel; QString emissiveTextureID = emissiveTextures.value(childID); QString ambientTextureID = ambientTextures.value(childID); if (!emissiveTextureID.isNull() || !ambientTextureID.isNull()) { @@ -2372,10 +2373,10 @@ QByteArray writeMapping(const QVariantHash& mapping) { return buffer.data(); } -FBXGeometry readFBX(const QByteArray& model, const QVariantHash& mapping, bool loadLightmaps) { +FBXGeometry readFBX(const QByteArray& model, const QVariantHash& mapping, bool loadLightmaps, float lightmapLevel) { QBuffer buffer(const_cast(&model)); buffer.open(QIODevice::ReadOnly); - return extractFBXGeometry(parseFBX(&buffer), mapping, loadLightmaps); + return extractFBXGeometry(parseFBX(&buffer), mapping, loadLightmaps, lightmapLevel); } bool addMeshVoxelsOperation(OctreeElement* element, void* extraData) { diff --git a/libraries/fbx/src/FBXReader.h b/libraries/fbx/src/FBXReader.h index 3adf5b5ffb..a5df7ccc0c 100644 --- a/libraries/fbx/src/FBXReader.h +++ b/libraries/fbx/src/FBXReader.h @@ -253,7 +253,7 @@ QByteArray writeMapping(const QVariantHash& mapping); /// Reads FBX geometry from the supplied model and mapping data. /// \exception QString if an error occurs in parsing -FBXGeometry readFBX(const QByteArray& model, const QVariantHash& mapping, bool loadLightmaps = true); +FBXGeometry readFBX(const QByteArray& model, const QVariantHash& mapping, bool loadLightmaps = true, float lightmapLevel = 1.0f); /// Reads SVO geometry from the supplied model data. FBXGeometry readSVO(const QByteArray& model); From 36f716cd6165e846a4bb475a08c217de20a37001 Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Tue, 2 Dec 2014 10:13:43 -0800 Subject: [PATCH 06/14] have script loading be separate from ScriptEngine constructor --- libraries/script-engine/src/ScriptEngine.cpp | 114 ++++++++----------- libraries/script-engine/src/ScriptEngine.h | 8 +- 2 files changed, 54 insertions(+), 68 deletions(-) diff --git a/libraries/script-engine/src/ScriptEngine.cpp b/libraries/script-engine/src/ScriptEngine.cpp index e6002d7c10..fefe8e2103 100644 --- a/libraries/script-engine/src/ScriptEngine.cpp +++ b/libraries/script-engine/src/ScriptEngine.cpp @@ -100,71 +100,6 @@ ScriptEngine::ScriptEngine(const QString& scriptContents, const QString& fileNam { } -ScriptEngine::ScriptEngine(const QUrl& scriptURL, - AbstractControllerScriptingInterface* controllerScriptingInterface) : - _scriptContents(), - _isFinished(false), - _isRunning(false), - _isInitialized(false), - _isAvatar(false), - _avatarIdentityTimer(NULL), - _avatarBillboardTimer(NULL), - _timerFunctionMap(), - _isListeningToAudioStream(false), - _avatarSound(NULL), - _numAvatarSoundSentBytes(0), - _controllerScriptingInterface(controllerScriptingInterface), - _avatarData(NULL), - _scriptName(), - _fileNameString(), - _quatLibrary(), - _vec3Library(), - _uuidLibrary(), - _animationCache(this), - _isUserLoaded(false), - _arrayBufferClass(new ArrayBufferClass(this)) -{ - QString scriptURLString = scriptURL.toString(); - _fileNameString = scriptURLString; - - QUrl url(scriptURL); - - // if the scheme length is one or lower, maybe they typed in a file, let's try - const int WINDOWS_DRIVE_LETTER_SIZE = 1; - if (url.scheme().size() <= WINDOWS_DRIVE_LETTER_SIZE) { - url = QUrl::fromLocalFile(scriptURLString); - } - - // ok, let's see if it's valid... and if so, load it - if (url.isValid()) { - if (url.scheme() == "file") { - QString fileName = url.toLocalFile(); - QFile scriptFile(fileName); - if (scriptFile.open(QFile::ReadOnly | QFile::Text)) { - qDebug() << "Loading file:" << fileName; - QTextStream in(&scriptFile); - _scriptContents = in.readAll(); - } else { - qDebug() << "ERROR Loading file:" << fileName; - emit errorMessage("ERROR Loading file:" + fileName); - } - } else { - QNetworkAccessManager& networkAccessManager = NetworkAccessManager::getInstance(); - QNetworkReply* reply = networkAccessManager.get(QNetworkRequest(url)); - qDebug() << "Downloading script at" << url; - QEventLoop loop; - QObject::connect(reply, SIGNAL(finished()), &loop, SLOT(quit())); - loop.exec(); - if (reply->error() == QNetworkReply::NoError && reply->attribute(QNetworkRequest::HttpStatusCodeAttribute) == 200) { - _scriptContents = reply->readAll(); - } else { - qDebug() << "ERROR Loading file:" << url.toString(); - emit errorMessage("ERROR Loading file:" + url.toString()); - } - } - } -} - void ScriptEngine::setIsAvatar(bool isAvatar) { _isAvatar = isAvatar; @@ -217,6 +152,55 @@ bool ScriptEngine::setScriptContents(const QString& scriptContents, const QStrin return true; } +void ScriptEngine::loadURL(const QUrl& scriptURL) { + if (_isRunning) { + return; + } + + QString scriptURLString = scriptURL.toString(); + _fileNameString = scriptURLString; + + QUrl url(scriptURL); + + // if the scheme length is one or lower, maybe they typed in a file, let's try + const int WINDOWS_DRIVE_LETTER_SIZE = 1; + if (url.scheme().size() <= WINDOWS_DRIVE_LETTER_SIZE) { + url = QUrl::fromLocalFile(scriptURLString); + } + + // ok, let's see if it's valid... and if so, load it + if (url.isValid()) { + if (url.scheme() == "file") { + QString fileName = url.toLocalFile(); + QFile scriptFile(fileName); + if (scriptFile.open(QFile::ReadOnly | QFile::Text)) { + qDebug() << "Loading file:" << fileName; + QTextStream in(&scriptFile); + _scriptContents = in.readAll(); + emit scriptLoaded(); + } else { + qDebug() << "ERROR Loading file:" << fileName; + emit errorLoadingScript(); + } + } else { + QNetworkAccessManager& networkAccessManager = NetworkAccessManager::getInstance(); + QNetworkReply* reply = networkAccessManager.get(QNetworkRequest(url)); + connect(reply, &QNetworkReply::finished, this, &ScriptEngine::handleScriptDownload); + } + } +} + +void ScriptEngine::handleScriptDownload() { + QNetworkReply* reply = qobject_cast(sender()); + + if (reply->error() == QNetworkReply::NoError && reply->attribute(QNetworkRequest::HttpStatusCodeAttribute) == 200) { + _scriptContents = reply->readAll(); + } else { + qDebug() << "ERROR Loading file:" << reply->url().toString(); + emit errorLoadingScript(); + } +} + Q_SCRIPT_DECLARE_QMETAOBJECT(LocalVoxels, QString) void ScriptEngine::init() { diff --git a/libraries/script-engine/src/ScriptEngine.h b/libraries/script-engine/src/ScriptEngine.h index bb279b8887..ee952d9d35 100644 --- a/libraries/script-engine/src/ScriptEngine.h +++ b/libraries/script-engine/src/ScriptEngine.h @@ -40,9 +40,6 @@ const unsigned int SCRIPT_DATA_CALLBACK_USECS = floor(((1.0 / 60.0f) * 1000 * 10 class ScriptEngine : public QScriptEngine { Q_OBJECT public: - ScriptEngine(const QUrl& scriptURL, - AbstractControllerScriptingInterface* controllerScriptingInterface = NULL); - ScriptEngine(const QString& scriptContents = NO_SCRIPT, const QString& fileNameString = QString(""), AbstractControllerScriptingInterface* controllerScriptingInterface = NULL); @@ -94,6 +91,7 @@ public: bool isUserLoaded() const { return _isUserLoaded; } public slots: + void loadURL(const QUrl& scriptURL); void stop(); QScriptValue evaluate(const QString& program, const QString& fileName = QString(), int lineNumber = 1); @@ -109,6 +107,8 @@ public slots: void nodeKilled(SharedNodePointer node); signals: + void scriptLoaded(); + void errorLoadingScript(); void update(float deltaTime); void scriptEnding(); void finished(const QString& fileNameString); @@ -155,6 +155,8 @@ private: ArrayBufferClass* _arrayBufferClass; QHash _outgoingScriptAudioSequenceNumbers; +private slots: + void handleScriptDownload(); }; #endif // hifi_ScriptEngine_h From d7f168999d1de69951942d02fa4fa6a39a3d65b1 Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Tue, 2 Dec 2014 10:30:23 -0800 Subject: [PATCH 07/14] don't block main thread for a script load --- interface/src/Application.cpp | 49 +++++++++++++------- interface/src/Application.h | 3 ++ libraries/script-engine/src/ScriptEngine.cpp | 7 +-- libraries/script-engine/src/ScriptEngine.h | 4 +- 4 files changed, 40 insertions(+), 23 deletions(-) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index 20ae07b0c9..35b13cbec7 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -4013,26 +4013,23 @@ ScriptEngine* Application::loadScript(const QString& scriptFilename, bool isUser return _scriptEnginesHash[scriptURLString]; } - ScriptEngine* scriptEngine; - if (scriptFilename.isNull()) { - scriptEngine = new ScriptEngine(NO_SCRIPT, "", &_controllerScriptingInterface); - } else { - // start the script on a new thread... - scriptEngine = new ScriptEngine(scriptUrl, &_controllerScriptingInterface); - - if (!scriptEngine->hasScript()) { - qDebug() << "Application::loadScript(), script failed to load..."; - QMessageBox::warning(getWindow(), "Error Loading Script", scriptURLString + " failed to load."); - return NULL; - } - - _scriptEnginesHash.insertMulti(scriptURLString, scriptEngine); - _runningScriptsWidget->setRunningScripts(getRunningScripts()); - UserActivityLogger::getInstance().loadedScript(scriptURLString); - } + ScriptEngine* scriptEngine = new ScriptEngine(NO_SCRIPT, "", &_controllerScriptingInterface); scriptEngine->setUserLoaded(isUserLoaded); - registerScriptEngineWithApplicationServices(scriptEngine); + if (scriptFilename.isNull()) { + // this had better be the script editor (we should de-couple so somebody who thinks they are loading a script + // doesn't just get an empty script engine) + + // we can complete setup now since there isn't a script we have to load + registerScriptEngineWithApplicationServices(scriptEngine); + } else { + // connect to the appropriate signals of this script engine + connect(scriptEngine, &ScriptEngine::scriptLoaded, this, &Application::handleScriptEngineLoaded); + connect(scriptEngine, &ScriptEngine::scriptLoaded, this, &Application::handleScriptLoadError); + + // get the script engine object to load the script at the designated script URL + scriptEngine->loadURL(scriptUrl); + } // restore the main window's active state if (activateMainWindow && !loadScriptFromEditor) { @@ -4043,6 +4040,22 @@ ScriptEngine* Application::loadScript(const QString& scriptFilename, bool isUser return scriptEngine; } +void Application::handleScriptEngineLoaded(const QUrl& scriptURL) { + ScriptEngine* scriptEngine = qobject_cast(sender()); + + _scriptEnginesHash.insertMulti(scriptURL.toString(), scriptEngine); + _runningScriptsWidget->setRunningScripts(getRunningScripts()); + UserActivityLogger::getInstance().loadedScript(scriptURL.toString()); + + // register our application services and set it off on its own thread + registerScriptEngineWithApplicationServices(scriptEngine); +} + +void Application::handleScriptLoadError(const QUrl& scriptURL) { + qDebug() << "Application::loadScript(), script failed to load..."; + QMessageBox::warning(getWindow(), "Error Loading Script", scriptURL.toString() + " failed to load."); +} + void Application::scriptFinished(const QString& scriptName) { const QString& scriptURLString = QUrl(scriptName).toString(); QHash::iterator it = _scriptEnginesHash.find(scriptURLString); diff --git a/interface/src/Application.h b/interface/src/Application.h index 9f2cdbd520..caaebea876 100644 --- a/interface/src/Application.h +++ b/interface/src/Application.h @@ -393,6 +393,9 @@ private slots: void timer(); void idle(); void aboutToQuit(); + + void handleScriptEngineLoaded(const QUrl& scriptURL); + void handleScriptLoadError(const QUrl& scriptURL); void connectedToDomain(const QString& hostname); diff --git a/libraries/script-engine/src/ScriptEngine.cpp b/libraries/script-engine/src/ScriptEngine.cpp index fefe8e2103..6cef69d23f 100644 --- a/libraries/script-engine/src/ScriptEngine.cpp +++ b/libraries/script-engine/src/ScriptEngine.cpp @@ -177,10 +177,10 @@ void ScriptEngine::loadURL(const QUrl& scriptURL) { qDebug() << "Loading file:" << fileName; QTextStream in(&scriptFile); _scriptContents = in.readAll(); - emit scriptLoaded(); + emit scriptLoaded(url); } else { qDebug() << "ERROR Loading file:" << fileName; - emit errorLoadingScript(); + emit errorLoadingScript(url); } } else { QNetworkAccessManager& networkAccessManager = NetworkAccessManager::getInstance(); @@ -195,9 +195,10 @@ void ScriptEngine::handleScriptDownload() { if (reply->error() == QNetworkReply::NoError && reply->attribute(QNetworkRequest::HttpStatusCodeAttribute) == 200) { _scriptContents = reply->readAll(); + emit scriptLoaded(reply->url()); } else { qDebug() << "ERROR Loading file:" << reply->url().toString(); - emit errorLoadingScript(); + emit errorLoadingScript(reply->url()); } } diff --git a/libraries/script-engine/src/ScriptEngine.h b/libraries/script-engine/src/ScriptEngine.h index ee952d9d35..4b6b3e48ab 100644 --- a/libraries/script-engine/src/ScriptEngine.h +++ b/libraries/script-engine/src/ScriptEngine.h @@ -107,8 +107,8 @@ public slots: void nodeKilled(SharedNodePointer node); signals: - void scriptLoaded(); - void errorLoadingScript(); + void scriptLoaded(const QUrl& scriptURL); + void errorLoadingScript(const QUrl& scriptURL); void update(float deltaTime); void scriptEnding(); void finished(const QString& fileNameString); From 0a92374ca6df9172e031999f2f58600ed5d1aec9 Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Tue, 2 Dec 2014 10:39:20 -0800 Subject: [PATCH 08/14] fix an incorrect connection to script load error --- interface/src/Application.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index 35b13cbec7..f499d04cfa 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -4025,7 +4025,7 @@ ScriptEngine* Application::loadScript(const QString& scriptFilename, bool isUser } else { // connect to the appropriate signals of this script engine connect(scriptEngine, &ScriptEngine::scriptLoaded, this, &Application::handleScriptEngineLoaded); - connect(scriptEngine, &ScriptEngine::scriptLoaded, this, &Application::handleScriptLoadError); + connect(scriptEngine, &ScriptEngine::errorLoadingScript, this, &Application::handleScriptLoadError); // get the script engine object to load the script at the designated script URL scriptEngine->loadURL(scriptUrl); From 4d233c09a36003a968bed277dabfad83dfd3559e Mon Sep 17 00:00:00 2001 From: Andrzej Kapolka Date: Tue, 2 Dec 2014 13:19:39 -0800 Subject: [PATCH 09/14] At least on Linux, fixes an annoying issue where closing the application window causes it to disappear and reappear briefly before exiting. --- interface/src/Application.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index 22a221c3a8..9561115478 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -1574,7 +1574,9 @@ void Application::setFullscreen(bool fullscreen) { } _window->setWindowState(fullscreen ? (_window->windowState() | Qt::WindowFullScreen) : (_window->windowState() & ~Qt::WindowFullScreen)); - _window->show(); + if (!_aboutToQuit) { + _window->show(); + } } void Application::setEnable3DTVMode(bool enable3DTVMode) { From 40df4973745655ff5d2af1c42d6705300cd89cc9 Mon Sep 17 00:00:00 2001 From: Sam Gateau Date: Tue, 2 Dec 2014 13:48:59 -0800 Subject: [PATCH 10/14] Hack for the Viking Palace scene before demo for good looking lightmaps --- interface/src/renderer/GeometryCache.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/interface/src/renderer/GeometryCache.cpp b/interface/src/renderer/GeometryCache.cpp index e2517613df..e523d7e608 100644 --- a/interface/src/renderer/GeometryCache.cpp +++ b/interface/src/renderer/GeometryCache.cpp @@ -841,6 +841,8 @@ void GeometryReader::run() { grabLightmaps = false; } else if (_url.path().toLower().endsWith("apt8_reboot.fbx")) { lightmapLevel = 4.0f; + } else if (_url.path().toLower().endsWith("palaceoforinthilian4.fbx")) { + lightmapLevel = 3.5f; } fbxgeo = readFBX(_reply->readAll(), _mapping, grabLightmaps, lightmapLevel); } From 2f11501e5b8f3fa5ff8049e8fbd8948f51fcb3c3 Mon Sep 17 00:00:00 2001 From: Philip Rosedale Date: Tue, 2 Dec 2014 14:28:46 -0800 Subject: [PATCH 11/14] Fix constant movement with hydra by adding null zone for thrust --- examples/hydraMove.js | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/examples/hydraMove.js b/examples/hydraMove.js index 236cecab18..f469fbbe74 100644 --- a/examples/hydraMove.js +++ b/examples/hydraMove.js @@ -245,10 +245,15 @@ function handleGrabBehavior(deltaTime) { } // Update for joysticks and move button +var THRUST_DEAD_ZONE = 0.1; function flyWithHydra(deltaTime) { var thrustJoystickPosition = Controller.getJoystickPosition(THRUST_CONTROLLER); - if (thrustJoystickPosition.x != 0 || thrustJoystickPosition.y != 0) { + if (debug) { + print("thrust X: " + thrustJoystickPosition.x + " Y: " + thrustJoystickPosition.y); + } + + if (Math.abs(thrustJoystickPosition.x) > THRUST_DEAD_ZONE || Math.abs(thrustJoystickPosition.y) > THRUST_DEAD_ZONE) { if (thrustMultiplier < MAX_THRUST_MULTIPLIER) { thrustMultiplier *= 1 + (deltaTime * THRUST_INCREASE_RATE); } From 1ce201c04f9b93a17dc43ee6464dbbac809997a8 Mon Sep 17 00:00:00 2001 From: Philip Rosedale Date: Tue, 2 Dec 2014 14:33:19 -0800 Subject: [PATCH 12/14] add same for rotation --- examples/hydraMove.js | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/examples/hydraMove.js b/examples/hydraMove.js index f469fbbe74..46715839c3 100644 --- a/examples/hydraMove.js +++ b/examples/hydraMove.js @@ -246,13 +246,10 @@ function handleGrabBehavior(deltaTime) { // Update for joysticks and move button var THRUST_DEAD_ZONE = 0.1; +var ROTATE_DEAD_ZONE = 0.1; function flyWithHydra(deltaTime) { var thrustJoystickPosition = Controller.getJoystickPosition(THRUST_CONTROLLER); - if (debug) { - print("thrust X: " + thrustJoystickPosition.x + " Y: " + thrustJoystickPosition.y); - } - if (Math.abs(thrustJoystickPosition.x) > THRUST_DEAD_ZONE || Math.abs(thrustJoystickPosition.y) > THRUST_DEAD_ZONE) { if (thrustMultiplier < MAX_THRUST_MULTIPLIER) { thrustMultiplier *= 1 + (deltaTime * THRUST_INCREASE_RATE); @@ -275,7 +272,7 @@ function flyWithHydra(deltaTime) { // View Controller var viewJoystickPosition = Controller.getJoystickPosition(VIEW_CONTROLLER); - if (viewJoystickPosition.x != 0 || viewJoystickPosition.y != 0) { + if (Math.abs(viewJoystickPosition.x) > ROTATE_DEAD_ZONE || Math.abs(viewJoystickPosition.y) > ROTATE_DEAD_ZONE) { // change the body yaw based on our x controller var orientation = MyAvatar.orientation; From 06b22cf6057c54aa326c88ac474780c766c85445 Mon Sep 17 00:00:00 2001 From: Philip Rosedale Date: Tue, 2 Dec 2014 14:50:25 -0800 Subject: [PATCH 13/14] ...and don't turn on/off UI from hydra --- interface/src/ui/ApplicationOverlay.cpp | 26 ------------------------- 1 file changed, 26 deletions(-) diff --git a/interface/src/ui/ApplicationOverlay.cpp b/interface/src/ui/ApplicationOverlay.cpp index 1307672ad1..305119a019 100644 --- a/interface/src/ui/ApplicationOverlay.cpp +++ b/interface/src/ui/ApplicationOverlay.cpp @@ -571,8 +571,6 @@ void ApplicationOverlay::renderControllerPointers() { static quint64 pressedTime[NUMBER_OF_MAGNIFIERS] = { 0ULL, 0ULL, 0ULL }; static bool isPressed[NUMBER_OF_MAGNIFIERS] = { false, false, false }; static bool stateWhenPressed[NUMBER_OF_MAGNIFIERS] = { false, false, false }; - static bool triggerPressed[NUMBER_OF_MAGNIFIERS] = { false, false, false }; - static bool bumperPressed[NUMBER_OF_MAGNIFIERS] = { false, false, false }; const HandData* handData = Application::getInstance()->getAvatar()->getHandData(); @@ -613,30 +611,6 @@ void ApplicationOverlay::renderControllerPointers() { } } - //Check for UI active toggle - if (palmData->getTrigger() == 1.0f) { - if (!triggerPressed[index]) { - if (bumperPressed[index]) { - Menu::getInstance()->setIsOptionChecked(MenuOption::UserInterface, - !Menu::getInstance()->isOptionChecked(MenuOption::UserInterface)); - } - triggerPressed[index] = true; - } - } else { - triggerPressed[index] = false; - } - if ((controllerButtons & BUTTON_FWD)) { - if (!bumperPressed[index]) { - if (triggerPressed[index]) { - Menu::getInstance()->setIsOptionChecked(MenuOption::UserInterface, - !Menu::getInstance()->isOptionChecked(MenuOption::UserInterface)); - } - bumperPressed[index] = true; - } - } else { - bumperPressed[index] = false; - } - //if we have the oculus, we should make the cursor smaller since it will be //magnified if (OculusManager::isConnected()) { From 49a087018f0a8d48c14f5634f91fc8f62407ca17 Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Wed, 3 Dec 2014 08:22:50 -0800 Subject: [PATCH 14/14] fix for delayed heartbeats, late socket lookup --- domain-server/src/DomainServer.cpp | 31 ++++++++++++++-------- domain-server/src/DomainServer.h | 2 ++ libraries/networking/src/HifiSockAddr.cpp | 2 ++ libraries/networking/src/HifiSockAddr.h | 3 +++ libraries/networking/src/LimitedNodeList.h | 1 + 5 files changed, 28 insertions(+), 11 deletions(-) diff --git a/domain-server/src/DomainServer.cpp b/domain-server/src/DomainServer.cpp index 80777ce529..75db0b8022 100644 --- a/domain-server/src/DomainServer.cpp +++ b/domain-server/src/DomainServer.cpp @@ -37,6 +37,8 @@ int const DomainServer::EXIT_CODE_REBOOT = 234923; +const QString ICE_SERVER_DEFAULT_HOSTNAME = "ice.highfidelity.io"; + DomainServer::DomainServer(int argc, char* argv[]) : QCoreApplication(argc, argv), _shutdownEventListener(this), @@ -52,7 +54,8 @@ DomainServer::DomainServer(int argc, char* argv[]) : _webAuthenticationStateSet(), _cookieSessionHash(), _automaticNetworkingSetting(), - _settingsManager() + _settingsManager(), + _iceServerSocket(ICE_SERVER_DEFAULT_HOSTNAME, ICE_SERVER_DEFAULT_PORT) { LogUtils::init(); @@ -346,6 +349,9 @@ void DomainServer::setupAutomaticNetworking() { QTimer* dynamicIPTimer = new QTimer(this); connect(dynamicIPTimer, &QTimer::timeout, this, &DomainServer::requestCurrentPublicSocketViaSTUN); + _automaticNetworkingSetting = + _settingsManager.valueOrDefaultValueForKeyPath(METAVERSE_AUTOMATIC_NETWORKING_KEY_PATH).toString(); + if (_automaticNetworkingSetting == FULL_AUTOMATIC_NETWORKING_VALUE) { dynamicIPTimer->start(STUN_REFLEXIVE_KEEPALIVE_INTERVAL_MSECS); @@ -354,9 +360,17 @@ void DomainServer::setupAutomaticNetworking() { connect(iceHeartbeatTimer, &QTimer::timeout, this, &DomainServer::performICEUpdates); iceHeartbeatTimer->start(ICE_HEARBEAT_INTERVAL_MSECS); - // call our sendHeartbeaToIceServer immediately anytime a local or public socket changes + // call our sendHeartbeatToIceServer immediately anytime a local or public socket changes connect(nodeList, &LimitedNodeList::localSockAddrChanged, this, &DomainServer::sendHeartbeatToIceServer); connect(nodeList, &LimitedNodeList::publicSockAddrChanged, this, &DomainServer::sendHeartbeatToIceServer); + + // attempt to update our public socket now, this will send a heartbeat once we get public socket + requestCurrentPublicSocketViaSTUN(); + + // in case the STUN lookup is still happening we should re-request a public socket once we get that address + connect(&nodeList->getSTUNSockAddr(), &HifiSockAddr::lookupCompleted, + this, &DomainServer::requestCurrentPublicSocketViaSTUN); + } if (!didSetupAccountManagerWithAccessToken()) { @@ -366,9 +380,6 @@ void DomainServer::setupAutomaticNetworking() { return; } - _automaticNetworkingSetting = - _settingsManager.valueOrDefaultValueForKeyPath(METAVERSE_AUTOMATIC_NETWORKING_KEY_PATH).toString(); - if (_automaticNetworkingSetting == IP_ONLY_AUTOMATIC_NETWORKING_VALUE || _automaticNetworkingSetting == FULL_AUTOMATIC_NETWORKING_VALUE) { @@ -383,14 +394,13 @@ void DomainServer::setupAutomaticNetworking() { // send public socket changes to the data server so nodes can find us at our new IP connect(nodeList, &LimitedNodeList::publicSockAddrChanged, this, &DomainServer::performIPAddressUpdate); + + // attempt to update our sockets now + requestCurrentPublicSocketViaSTUN(); } else { // send our heartbeat to data server so it knows what our network settings are sendHeartbeatToDataServer(); } - - // attempt to update our sockets now - requestCurrentPublicSocketViaSTUN(); - } else { qDebug() << "Cannot enable domain-server automatic networking without a domain ID." << "Please add an ID to your config file or via the web interface."; @@ -1167,8 +1177,7 @@ void DomainServer::performICEUpdates() { } void DomainServer::sendHeartbeatToIceServer() { - static HifiSockAddr ICE_SERVER_SOCK_ADDR = HifiSockAddr("ice.highfidelity.io", ICE_SERVER_DEFAULT_PORT); - LimitedNodeList::getInstance()->sendHeartbeatToIceServer(ICE_SERVER_SOCK_ADDR); + LimitedNodeList::getInstance()->sendHeartbeatToIceServer(_iceServerSocket); } void DomainServer::sendICEPingPackets() { diff --git a/domain-server/src/DomainServer.h b/domain-server/src/DomainServer.h index de485da5e7..2a92c63923 100644 --- a/domain-server/src/DomainServer.h +++ b/domain-server/src/DomainServer.h @@ -154,6 +154,8 @@ private: QString _automaticNetworkingSetting; DomainServerSettingsManager _settingsManager; + + HifiSockAddr _iceServerSocket; }; diff --git a/libraries/networking/src/HifiSockAddr.cpp b/libraries/networking/src/HifiSockAddr.cpp index f2419f5124..425dffefe9 100644 --- a/libraries/networking/src/HifiSockAddr.cpp +++ b/libraries/networking/src/HifiSockAddr.cpp @@ -86,6 +86,7 @@ bool HifiSockAddr::operator==(const HifiSockAddr& rhsSockAddr) const { void HifiSockAddr::handleLookupResult(const QHostInfo& hostInfo) { if (hostInfo.error() != QHostInfo::NoError) { qDebug() << "Lookup failed for" << hostInfo.lookupId() << ":" << hostInfo.errorString(); + emit lookupFailed(); } foreach(const QHostAddress& address, hostInfo.addresses()) { @@ -94,6 +95,7 @@ void HifiSockAddr::handleLookupResult(const QHostInfo& hostInfo) { _address = address; qDebug() << "QHostInfo lookup result for" << hostInfo.hostName() << "with lookup ID" << hostInfo.lookupId() << "is" << address.toString(); + emit lookupCompleted(); break; } } diff --git a/libraries/networking/src/HifiSockAddr.h b/libraries/networking/src/HifiSockAddr.h index 064f8032ca..4d3944012e 100644 --- a/libraries/networking/src/HifiSockAddr.h +++ b/libraries/networking/src/HifiSockAddr.h @@ -54,6 +54,9 @@ public: friend QDataStream& operator>>(QDataStream& dataStream, HifiSockAddr& sockAddr); private slots: void handleLookupResult(const QHostInfo& hostInfo); +signals: + void lookupCompleted(); + void lookupFailed(); private: QHostAddress _address; quint16 _port; diff --git a/libraries/networking/src/LimitedNodeList.h b/libraries/networking/src/LimitedNodeList.h index ad8c1688bb..2fc8751e3f 100644 --- a/libraries/networking/src/LimitedNodeList.h +++ b/libraries/networking/src/LimitedNodeList.h @@ -105,6 +105,7 @@ public: const HifiSockAddr& publicSocket, const HifiSockAddr& localSocket); const HifiSockAddr& getLocalSockAddr() const { return _localSockAddr; } + const HifiSockAddr& getSTUNSockAddr() const { return _stunSockAddr; } void processNodeData(const HifiSockAddr& senderSockAddr, const QByteArray& packet); void processKillNode(const QByteArray& datagram);