From 056365932be7cad76bc454ea1351448ea2f3f148 Mon Sep 17 00:00:00 2001 From: David Rowe Date: Thu, 5 Feb 2015 09:37:08 -0800 Subject: [PATCH 1/6] Make circle3d dimension property specify overall size not half size --- interface/src/ui/overlays/Circle3DOverlay.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/interface/src/ui/overlays/Circle3DOverlay.cpp b/interface/src/ui/overlays/Circle3DOverlay.cpp index f890999174..463e63a187 100644 --- a/interface/src/ui/overlays/Circle3DOverlay.cpp +++ b/interface/src/ui/overlays/Circle3DOverlay.cpp @@ -119,7 +119,7 @@ void Circle3DOverlay::render(RenderArgs* args) { glPushMatrix(); glm::vec3 positionToCenter = center - position; glTranslatef(positionToCenter.x, positionToCenter.y, positionToCenter.z); - glScalef(dimensions.x, dimensions.y, 1.0f); + glScalef(dimensions.x / 2.0f, dimensions.y / 2.0f, 1.0f); glLineWidth(_lineWidth); From 2f6749ff691c8e4e072df804a3ca400a74bd008e Mon Sep 17 00:00:00 2001 From: David Rowe Date: Thu, 5 Feb 2015 09:38:45 -0800 Subject: [PATCH 2/6] Implement dimensions test for 3D planar overlay intersection --- interface/src/ui/overlays/Planar3DOverlay.cpp | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/interface/src/ui/overlays/Planar3DOverlay.cpp b/interface/src/ui/overlays/Planar3DOverlay.cpp index 628ff6a7dc..508b5c4227 100644 --- a/interface/src/ui/overlays/Planar3DOverlay.cpp +++ b/interface/src/ui/overlays/Planar3DOverlay.cpp @@ -93,7 +93,6 @@ QScriptValue Planar3DOverlay::getProperty(const QString& property) { bool Planar3DOverlay::findRayIntersection(const glm::vec3& origin, const glm::vec3& direction, float& distance, BoxFace& face) { - RayIntersectionInfo rayInfo; rayInfo._rayStart = origin; rayInfo._rayDirection = direction; @@ -110,9 +109,13 @@ bool Planar3DOverlay::findRayIntersection(const glm::vec3& origin, const glm::ve if (intersects) { distance = rayInfo._hitDistance; - // TODO: if it intersects, we want to check to see if the intersection point is within our dimensions - // glm::vec3 hitAt = origin + direction * distance; - // _dimensions + + glm::vec3 hitPosition = origin + (distance * direction); + glm::vec3 localHitPosition = glm::inverse(_rotation) * (hitPosition - _position); + glm::vec2 halfDimensions = _dimensions / 2.0f; + + intersects = -halfDimensions.x <= localHitPosition.x && localHitPosition.x <= halfDimensions.x + && -halfDimensions.y <= localHitPosition.y && localHitPosition.y <= halfDimensions.y; } return intersects; } From 3ceb1123b357c5d218f30a6d439a04dd1a892173 Mon Sep 17 00:00:00 2001 From: David Rowe Date: Thu, 5 Feb 2015 09:39:16 -0800 Subject: [PATCH 3/6] Cater for ellipses in circle3d overlay intersection --- interface/src/ui/overlays/Circle3DOverlay.cpp | 22 +++++++++---------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/interface/src/ui/overlays/Circle3DOverlay.cpp b/interface/src/ui/overlays/Circle3DOverlay.cpp index 463e63a187..e68f1bfb37 100644 --- a/interface/src/ui/overlays/Circle3DOverlay.cpp +++ b/interface/src/ui/overlays/Circle3DOverlay.cpp @@ -417,19 +417,19 @@ bool Circle3DOverlay::findRayIntersection(const glm::vec3& origin, const glm::vec3& direction, float& distance, BoxFace& face) { bool intersects = Planar3DOverlay::findRayIntersection(origin, direction, distance, face); - if (intersects) { - glm::vec3 hitAt = origin + (direction * distance); - float distanceToHit = glm::distance(hitAt, _position); - float maxDimension = glm::max(_dimensions.x, _dimensions.y); - float innerRadius = maxDimension * getInnerRadius(); - float outerRadius = maxDimension * getOuterRadius(); - - // TODO: this really only works for circles, we should be handling the ellipse case as well... - if (distanceToHit < innerRadius || distanceToHit > outerRadius) { - intersects = false; - } + if (intersects) { + glm::vec3 hitPosition = origin + (distance * direction); + glm::vec3 localHitPosition = glm::inverse(_rotation) * (hitPosition - _position); + localHitPosition.y = localHitPosition.y * _dimensions.x / _dimensions.y; // Scale to make circular + + float distanceToHit = glm::length(localHitPosition); + float innerRadius = _dimensions.x / 2.0f * _innerRadius; + float outerRadius = _dimensions.x / 2.0f * _outerRadius; + + intersects = innerRadius <= distanceToHit && distanceToHit <= outerRadius; } + return intersects; } From 1fa50fa54d76982a14634857a138cbcb0cab9c1f Mon Sep 17 00:00:00 2001 From: David Rowe Date: Thu, 5 Feb 2015 13:09:06 -0800 Subject: [PATCH 4/6] Run only one instance of Windows Interface at a time OSX automatically does this. --- interface/src/main.cpp | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/interface/src/main.cpp b/interface/src/main.cpp index dae32b67c6..ae2ba7f576 100644 --- a/interface/src/main.cpp +++ b/interface/src/main.cpp @@ -18,6 +18,17 @@ #include "Application.h" int main(int argc, const char * argv[]) { + +#ifdef Q_OS_WIN + // Run only one instance of Interface at a time. + HANDLE mutex = CreateMutex(NULL, FALSE, "High Fidelity Interface"); + DWORD result = GetLastError(); + if (result == ERROR_ALREADY_EXISTS || result == ERROR_ACCESS_DENIED) { + // Interface is already running. + return 0; + } +#endif + QElapsedTimer startupTime; startupTime.start(); @@ -44,6 +55,11 @@ int main(int argc, const char * argv[]) { qDebug( "Created QT Application."); exitCode = app.exec(); } + +#ifdef Q_OS_WIN + ReleaseMutex(mutex); +#endif + qDebug("Normal exit."); return exitCode; } From ab758648c78b0592ac07a211beea74d5adf749ae Mon Sep 17 00:00:00 2001 From: David Rowe Date: Thu, 5 Feb 2015 16:44:26 -0800 Subject: [PATCH 5/6] Show and focus on the other Interface instance --- interface/src/Application.cpp | 29 +++++++++++++++++++++++++++++ interface/src/Application.h | 5 +++++ interface/src/main.cpp | 24 ++++++++++++++++++++++++ 3 files changed, 58 insertions(+) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index 3c1806b00b..03921ec689 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -23,6 +23,7 @@ // include this before QGLWidget, which includes an earlier version of OpenGL #include "InterfaceConfig.h" +#include #include #include #include @@ -147,6 +148,30 @@ const QString SKIP_FILENAME = QStandardPaths::writableLocation(QStandardPaths::D const QString DEFAULT_SCRIPTS_JS_URL = "http://s3.amazonaws.com/hifi-public/scripts/defaultScripts.js"; +#ifdef Q_OS_WIN +class MyNativeEventFilter : public QAbstractNativeEventFilter { +public: + static MyNativeEventFilter& getInstance() { + static MyNativeEventFilter staticInstance; + return staticInstance; + } + + bool nativeEventFilter(const QByteArray &eventType, void* msg, long* result) Q_DECL_OVERRIDE { + if (eventType == "windows_generic_MSG") { + MSG* message = (MSG*)msg; + if (message->message == UWM_IDENTIFY_INSTANCES) { + *result = UWM_IDENTIFY_INSTANCES; + return true; + } + if (message->message == WM_SHOWWINDOW) { + Application::getInstance()->getWindow()->showNormal(); + } + } + return false; + } +}; +#endif + void messageHandler(QtMsgType type, const QMessageLogContext& context, const QString& message) { QString logMessage = LogHandler::getInstance().printMessage((LogMsgType) type, context, message); @@ -244,6 +269,10 @@ Application::Application(int& argc, char** argv, QElapsedTimer &startup_time) : _aboutToQuit(false), _notifiedPacketVersionMismatchThisDomain(false) { +#ifdef Q_OS_WIN + installNativeEventFilter(&MyNativeEventFilter::getInstance()); +#endif + _logger = new FileLogger(this); // After setting organization name in order to get correct directory qInstallMessageHandler(messageHandler); diff --git a/interface/src/Application.h b/interface/src/Application.h index 113a09e874..86fe4f1411 100644 --- a/interface/src/Application.h +++ b/interface/src/Application.h @@ -118,6 +118,11 @@ static const quint64 TOO_LONG_SINCE_LAST_SEND_DOWNSTREAM_AUDIO_STATS = 1 * USECS static const QString INFO_HELP_PATH = "html/interface-welcome-allsvg.html"; static const QString INFO_EDIT_ENTITIES_PATH = "html/edit-entities-commands.html"; +#ifdef Q_OS_WIN +static const UINT UWM_IDENTIFY_INSTANCES = + RegisterWindowMessage("UWM_IDENTIFY_INSTANCES_{8AB82783-B74A-4258-955B-8188C22AA0D6}"); +#endif + class Application; #if defined(qApp) #undef qApp diff --git a/interface/src/main.cpp b/interface/src/main.cpp index ae2ba7f576..0f20f09e25 100644 --- a/interface/src/main.cpp +++ b/interface/src/main.cpp @@ -17,6 +17,24 @@ #include "Application.h" +#ifdef Q_OS_WIN +static BOOL CALLBACK enumWindowsCallback(HWND hWnd, LPARAM lParam) { + const UINT TIMEOUT = 200; // ms + DWORD response; + LRESULT result = SendMessageTimeout(hWnd, UWM_IDENTIFY_INSTANCES, 0, 0, SMTO_BLOCK | SMTO_ABORTIFHUNG, TIMEOUT, &response); + if (result == 0) { // Timeout; continue search. + return TRUE; + } + if (response == UWM_IDENTIFY_INSTANCES) { + HWND* target = (HWND*)lParam; + *target = hWnd; + return FALSE; // Found; terminate search. + } + return TRUE; // Not found; continue search. +} +#endif + + int main(int argc, const char * argv[]) { #ifdef Q_OS_WIN @@ -25,6 +43,12 @@ int main(int argc, const char * argv[]) { DWORD result = GetLastError(); if (result == ERROR_ALREADY_EXISTS || result == ERROR_ACCESS_DENIED) { // Interface is already running. + HWND otherInstance = NULL; + EnumWindows(enumWindowsCallback, (LPARAM)&otherInstance); + if (otherInstance) { + ShowWindow(otherInstance, SW_RESTORE); + SetForegroundWindow(otherInstance); + } return 0; } #endif From 9e34b3683980c24f9452cd9e29746417c56dc201 Mon Sep 17 00:00:00 2001 From: David Rowe Date: Thu, 5 Feb 2015 17:17:31 -0800 Subject: [PATCH 6/6] Send hifi command line url to other instance --- interface/src/Application.cpp | 7 +++++++ interface/src/main.cpp | 9 +++++++++ 2 files changed, 16 insertions(+) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index 03921ec689..ed8ad8c4d6 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -166,6 +166,13 @@ public: if (message->message == WM_SHOWWINDOW) { Application::getInstance()->getWindow()->showNormal(); } + if (message->message == WM_COPYDATA) { + COPYDATASTRUCT* pcds = (COPYDATASTRUCT*)(message->lParam); + QUrl url = QUrl((const char*)(pcds->lpData)); + if (url.isValid() && url.scheme() == HIFI_URL_SCHEME) { + DependencyManager::get()->handleLookupString(url.toString()); + } + } } return false; } diff --git a/interface/src/main.cpp b/interface/src/main.cpp index 0f20f09e25..d12a2761ed 100644 --- a/interface/src/main.cpp +++ b/interface/src/main.cpp @@ -15,6 +15,7 @@ #include +#include "AddressManager.h" #include "Application.h" #ifdef Q_OS_WIN @@ -48,6 +49,14 @@ int main(int argc, const char * argv[]) { if (otherInstance) { ShowWindow(otherInstance, SW_RESTORE); SetForegroundWindow(otherInstance); + + QUrl url = QUrl(argv[1]); + if (url.isValid() && url.scheme() == HIFI_URL_SCHEME) { + COPYDATASTRUCT cds; + cds.cbData = strlen(argv[1]) + 1; + cds.lpData = (PVOID)argv[1]; + SendMessage(otherInstance, WM_COPYDATA, 0, (LPARAM)&cds); + } } return 0; }