diff --git a/modules/skybrowser/include/pair.h b/modules/skybrowser/include/pair.h index 2465c6587e..bbf7c7b4b2 100644 --- a/modules/skybrowser/include/pair.h +++ b/modules/skybrowser/include/pair.h @@ -58,7 +58,11 @@ public: // Mouse interaction bool checkMouseIntersection(glm::vec2 mousePosition); glm::vec2 selectedScreenSpacePosition(); - bool isSelectedBrowser(); + bool isBrowserSelected(); + bool isTargetSelected(); + void fineTuneTarget(const glm::vec2& start, const glm::vec2& translation); + void translateSelected(const glm::vec2& start, const glm::vec2& translation); + void resizeBrowser(const glm::vec2& start, const glm::vec2& translation); // Browser void sendIdToBrowser(); @@ -71,6 +75,7 @@ public: // Boolean functions bool hasFinishedFading(float goalState) const; + bool isOnResizeArea(glm::vec2 mouseScreenSpaceCoords); bool isEnabled() const; bool isLocked() const; diff --git a/modules/skybrowser/include/screenspaceskybrowser.h b/modules/skybrowser/include/screenspaceskybrowser.h index 066b7c8555..a56ef2ab29 100644 --- a/modules/skybrowser/include/screenspaceskybrowser.h +++ b/modules/skybrowser/include/screenspaceskybrowser.h @@ -47,12 +47,8 @@ namespace openspace { // Interaction. Resize void saveResizeStartSize(); - // Mouse interaction with the browser. Returns 1 or -1 at the coordinate in - // image if the mouse is on a side of the browser - // __1__ - // y| -1 |_____|1 - // |__x -1 - glm::ivec2 isOnResizeArea(glm::vec2 screenSpaceCoord); + bool isOnResizeArea(glm::vec2 screenSpaceCoord); + void resize(const glm::vec2& start, const glm::vec2& mouseDrag); glm::dvec2 fineTuneVector(glm::dvec2 drag); void setIdInBrowser(); @@ -69,13 +65,15 @@ namespace openspace { bool _isSyncedWithWwt{ false }; bool _isFovAnimated{ false }; - // Animation of browser + // Animation of fieldOfView float _endVfov{ 0.f }; - // Resizing of browser - glm::vec2 _originalDimensions; + // Resizing float _originalScale; float _resizeAreaPercentage{ 0.1f }; + glm::vec2 _originalDimensions; + glm::vec2 _originalScreenSpaceSize; + glm::ivec2 _resizeDirection; // Time variables // For capping the calls onchange properties from scrolling diff --git a/modules/skybrowser/skybrowsermodule.cpp b/modules/skybrowser/skybrowsermodule.cpp index 57c434196e..90d8bc5b33 100644 --- a/modules/skybrowser/skybrowsermodule.cpp +++ b/modules/skybrowser/skybrowsermodule.cpp @@ -50,7 +50,7 @@ namespace { } // namespace namespace openspace { - + scripting::LuaLibrary SkyBrowserModule::luaLibrary() const { scripting::LuaLibrary res; @@ -229,141 +229,77 @@ SkyBrowserModule::SkyBrowserModule() global::callback::mouseButton->emplace_back( [&](MouseButton button, MouseAction action, KeyModifier modifier) -> bool { - if (_mouseOnPair && action == MouseAction::Press) { - - // Get the currently selected browser - setSelectedBrowser(_mouseOnPair->browserId()); - - if (button == MouseButton::Left) { - _isCameraRotating = false; - _startMousePosition = _mousePosition; - _startDragPosition = _mouseOnPair->selectedScreenSpacePosition(); - - // If current object is browser, check for resizing - if (_mouseOnPair->isSelectedBrowser()) { - // Resize browser if mouse is over resize button - _resizeDirection = _mouseOnPair->getBrowser()->isOnResizeArea( - _mousePosition - ); - if (_resizeDirection != glm::ivec2{ 0 }) { - _mouseOnPair->getBrowser()->saveResizeStartSize(); - _startBrowserSize = _mouseOnPair->getBrowser()-> - screenSpaceDimensions(); - _isResizing = true; - return true; - } - } - // If you start dragging around the target, it should unlock - else { - _mouseOnPair->unlock(); - } - _isDragging = true; - - return true; - } - // Fine tuning mode of target - else if (_mouseOnPair->isSelectedBrowser() && - button == MouseButton::Right) { - // If you start dragging around on the browser, the target unlocks - _mouseOnPair->unlock(); - // Change view (by moving target) within browser if right mouse - // click on browser - _startMousePosition = _mousePosition; - _startDragPosition = _mouseOnPair->getTarget()->screenSpacePosition(); - _isFineTuneMode = true; - - return true; - } + if (!_isCameraInSolarSystem) { + return false; } - else if (action == MouseAction::Release) { - if (_isDragging) { - _isDragging = false; - return true; - } - if (_isFineTuneMode) { - _isFineTuneMode = false; - return true; - } - if (_isResizing) { - _isResizing = false; + if (action == MouseAction::Press && _mouseOnPair) { + handleMouseClick(button); + return true; + } + else if (_interactionMode != MouseInteraction::Hover && + action == MouseAction::Release) { + // Update browser size if it has been resized + if (_interactionMode == MouseInteraction::Resize) { _mouseOnPair->updateBrowserSize(); - return true; } - } - return false; + _interactionMode = MouseInteraction::Hover; + return true; + } + else { + return false; + } } ); global::callback::mousePosition->emplace_back( [&](double x, double y) { - if (_isCameraInSolarSystem) { - glm::vec2 pixel{ static_cast(x), static_cast(y) }; - _mousePosition = skybrowser::pixelToScreenSpace2d(pixel); - glm::vec2 translation = _mousePosition - _startMousePosition; - - if (_isResizing) { - // Calculate scaling factor - glm::vec2 mouseDragVector = (_mousePosition - _startMousePosition); - glm::vec2 scaling = mouseDragVector * glm::vec2(_resizeDirection); - glm::vec2 newSizeRelToOld = (_startBrowserSize + (scaling)) / - _startBrowserSize; - // Scale the browser - _mouseOnPair->getBrowser()->setScale(newSizeRelToOld); - - // For dragging functionality, translate so it looks like the - // browser isn't moving. Make sure the browser doesn't move in - // directions it's not supposed to - translation = 0.5f * mouseDragVector * abs( - glm::vec2(_resizeDirection) - ); - - } - if (_isDragging || _isResizing) { - - // Translate - if (_mouseOnPair->isSelectedBrowser()) { - _mouseOnPair->getBrowser()->translate( - translation, - _startDragPosition - ); - } - else { - _mouseOnPair->getTarget()->translate( - translation, - _startDragPosition - ); - } - } - else if (_isFineTuneMode) { - glm::vec2 fineTune = _mouseOnPair->getBrowser()->fineTuneVector( - translation - ); - _mouseOnPair->getTarget()->translate(fineTune, _startDragPosition); - } - // If there is no dragging or resizing, look for new objects - else { - setSelectedObject(); - } + if (!_isCameraInSolarSystem) { + return false; } - + + glm::vec2 pixel{ static_cast(x), static_cast(y) }; + _mousePosition = skybrowser::pixelToScreenSpace2d(pixel); + glm::vec2 translation = _mousePosition - _startMousePosition; + + switch (_interactionMode) { + case MouseInteraction::Hover: + setSelectedObject(); + break; + + case MouseInteraction::Resize: + _mouseOnPair->resizeBrowser(_startDragPosition, translation); + break; + + case MouseInteraction::Drag: + _mouseOnPair->translateSelected(_startDragPosition, translation); + break; + + case MouseInteraction::FineTune: + _mouseOnPair->fineTuneTarget(_startDragPosition, translation); + break; + + default: + setSelectedObject(); + break; + } + return false; } ); global::callback::mouseScrollWheel->emplace_back( [&](double, double scroll) -> bool { - // If mouse is on browser or target, apply zoom - if (_mouseOnPair) { - _mouseOnPair->getBrowser()->setVerticalFovWithScroll( - static_cast(scroll) - ); - return true; + if (!_isCameraInSolarSystem || !_mouseOnPair) { + return false; } - - return false; + // If mouse is on browser or target, apply zoom + _mouseOnPair->getBrowser()->setVerticalFovWithScroll( + static_cast(scroll) + ); + return true; } ); @@ -374,27 +310,28 @@ SkyBrowserModule::SkyBrowserModule() bool camWasInSolarSystem = _isCameraInSolarSystem; glm::dvec3 cameraPos = global::navigationHandler->camera()->positionVec3(); _isCameraInSolarSystem = glm::length(cameraPos) < SolarSystemRadius; + bool vizModeChanged = _isCameraInSolarSystem != camWasInSolarSystem; - // Fading flags - if (_isCameraInSolarSystem != camWasInSolarSystem) { - _isTransitioningVizMode = true; - - // Select the 3D browser when moving out of the solar system - if (!_isCameraInSolarSystem && _browser3dNode) { - _selectedBrowser = _browser3dNode->renderable()->identifier(); + // Visualization mode changed. Start fading + if (vizModeChanged) { + _isFading = true; + // Camera moved into the solar system + if (!_isCameraInSolarSystem) { + _goal = Transparency::Transparent; + // Select the 3D browser when moving out of the solar system + if (_browser3dNode) { + _selectedBrowser = _browser3dNode->renderable()->identifier(); + } + } + else { + _goal = Transparency::Opaque; } } double deltaTime = global::windowDelegate->deltaTime(); // Fade pairs if the camera moved in or out the solar system - if (_isTransitioningVizMode) { - if (_isCameraInSolarSystem) { - incrementallyFadeBrowserTargets(Transparency::Opaque, deltaTime); - } - else { - incrementallyFadeBrowserTargets(Transparency::Transparent, deltaTime); - } + if (_isFading) { + incrementallyFadeBrowserTargets(_goal, deltaTime); } - if (_isCameraInSolarSystem) { incrementallyAnimateTargets(deltaTime); } @@ -435,6 +372,9 @@ void SkyBrowserModule::internalInitialize(const ghoul::Dictionary& dict) { void SkyBrowserModule::setSelectedObject() { + if (_interactionMode != MouseInteraction::Hover) { + return; + } // Save old selection for removing highlight Pair* previousPair = _mouseOnPair; @@ -488,8 +428,8 @@ void SkyBrowserModule::createTargetBrowserPair() { std::string idTarget = "SkyTarget" + std::to_string(noOfPairs); glm::vec3 positionBrowser = { -1.0f, -0.5f, -2.1f }; std::string guiPath = "/SkyBrowser"; - std::string url = "https://data.openspaceproject.com/dist/skybrowser/page/"; - //std::string url = "http://localhost:8000"; + //std::string url = "https://data.openspaceproject.com/dist/skybrowser/page/"; + std::string url = "http://localhost:8000"; const std::string browser = "{" "Identifier = '" + idBrowser + "'," @@ -628,6 +568,45 @@ void SkyBrowserModule::add2dSelectedImagesTo3d(const std::string& pairId) } } +void SkyBrowserModule::handleMouseClick(const MouseButton& button) +{ + setSelectedBrowser(_mouseOnPair->browserId()); + + if (button == MouseButton::Left) { + _startMousePosition = _mousePosition; + _startDragPosition = _mouseOnPair->selectedScreenSpacePosition(); + + // If current object is browser, check for resizing + bool shouldResize = _mouseOnPair->isBrowserSelected() && + _mouseOnPair->isOnResizeArea(_mousePosition); + + if (shouldResize) { + _mouseOnPair->getBrowser()->saveResizeStartSize(); + _interactionMode = MouseInteraction::Resize; + return; + } + else { + // If it's not resize mode, it's drag mode + _interactionMode = MouseInteraction::Drag; + } + + // If target is clicked, it should unlock + if (_mouseOnPair->isTargetSelected()) { + _mouseOnPair->unlock(); + } + } + // Fine tuning mode of target + else if (button == MouseButton::Right && _mouseOnPair->isBrowserSelected()) { + // If you start dragging around on the browser, the target unlocks + _mouseOnPair->unlock(); + // Change view (by moving target) within browser if right mouse + // click on browser + _startMousePosition = _mousePosition; + _startDragPosition = _mouseOnPair->getTarget()->screenSpacePosition(); + _interactionMode = MouseInteraction::FineTune; + } +} + const std::unique_ptr& SkyBrowserModule::getWwtDataHandler() { return _dataHandler; } @@ -769,7 +748,7 @@ void SkyBrowserModule::incrementallyFadeBrowserTargets(Transparency goal, float // The transition is over when the fade is finished if (isAllFinished) { - _isTransitioningVizMode = false; + _isFading = false; } } diff --git a/modules/skybrowser/skybrowsermodule.h b/modules/skybrowser/skybrowsermodule.h index 85b9226ae7..c1027cd5a7 100644 --- a/modules/skybrowser/skybrowsermodule.h +++ b/modules/skybrowser/skybrowsermodule.h @@ -28,6 +28,7 @@ #include #include #include +#include #include namespace openspace { @@ -44,6 +45,13 @@ enum class Transparency { Opaque }; +enum class MouseInteraction { + Hover, + Resize, + Drag, + FineTune, +}; + class SkyBrowserModule : public OpenSpaceModule { public: @@ -96,6 +104,9 @@ public: int nLoadedImages(); void add2dSelectedImagesTo3d(const std::string& pairId); + // Mouse interaction + void handleMouseClick(const MouseButton& button); + scripting::LuaLibrary luaLibrary() const override; //std::vector documentations() const override; @@ -114,24 +125,21 @@ private: // Fading double _fadingTime = 2.0; + Transparency _goal; // Flags - bool _isFineTuneMode{ false }; - bool _isResizing{ false }; - bool _isDragging{ false }; - bool _isCameraInSolarSystem{ true }; + bool _isCameraInSolarSystem{ true }; // Visualization modes + bool _isFading{ false }; bool _isCameraRotating = false; - bool _isTransitioningVizMode{ false }; - // Mouse interaction - dragging and resizing - glm::ivec3 _highlightAddition{ 35 }; // Highlight object when mouse hovers + // Mouse interaction + MouseInteraction _interactionMode; glm::vec2 _mousePosition; // Current mouse position in screen space coordinates glm::vec2 _startMousePosition; glm::vec2 _startDragPosition; - glm::vec2 _startBrowserSize; - glm::ivec2 _resizeDirection{ 0 }; // Animation of rotation of camera to look at coordinate galactic coordinates + glm::ivec3 _highlightAddition{ 35 }; // Highlight object when mouse hovers glm::dvec3 _startAnimation; glm::dvec3 _endAnimation; double _stopAnimationThreshold{ 0.05 }; diff --git a/modules/skybrowser/src/pair.cpp b/modules/skybrowser/src/pair.cpp index b8d7baff52..b3bef60b1e 100644 --- a/modules/skybrowser/src/pair.cpp +++ b/modules/skybrowser/src/pair.cpp @@ -151,11 +151,32 @@ namespace openspace { return _selected->screenSpacePosition(); } - bool Pair::isSelectedBrowser() + bool Pair::isBrowserSelected() { return _isSelectedBrowser; } + bool Pair::isTargetSelected() + { + return _selected && !_isSelectedBrowser; + } + + void Pair::fineTuneTarget(const glm::vec2& start, const glm::vec2& translation) + { + glm::vec2 fineTune = _browser->fineTuneVector(translation); + _target->translate(fineTune, start); + } + + void Pair::translateSelected(const glm::vec2& start, const glm::vec2& translation) + { + _selected->translate(translation, start); + } + + void Pair::resizeBrowser(const glm::vec2& start, const glm::vec2& translation) + { + _browser->resize(start, translation); + } + void Pair::setEnabled(bool enable) { _browser->setEnabled(enable); @@ -297,6 +318,11 @@ namespace openspace { return isTargetFadeFinished(goalState) && isBrowserFadeFinished(goalState); } + bool Pair::isOnResizeArea(glm::vec2 mouseScreenSpaceCoords) + { + return _browser->isOnResizeArea(mouseScreenSpaceCoords); + } + ScreenSpaceSkyTarget* Pair::getTarget() { return _target; } diff --git a/modules/skybrowser/src/screenspaceskybrowser.cpp b/modules/skybrowser/src/screenspaceskybrowser.cpp index 2c52ef8ea8..251398c7af 100644 --- a/modules/skybrowser/src/screenspaceskybrowser.cpp +++ b/modules/skybrowser/src/screenspaceskybrowser.cpp @@ -242,10 +242,15 @@ namespace openspace { _texture->bind(); } - glm::ivec2 ScreenSpaceSkyBrowser::isOnResizeArea(glm::vec2 coord) { + // Mouse interaction with the browser. Returns 1 or -1 at the coordinate in + // image if the mouse is on a side of the browser + // __1__ + // y| -1 |_____|1 + // |__x -1 + bool ScreenSpaceSkyBrowser::isOnResizeArea(glm::vec2 coord) { glm::ivec2 resizePosition = glm::ivec2{ 0 }; // Make sure coordinate is on browser - if (!intersection(coord)) return resizePosition; + if (!intersection(coord)) return false; // TO DO: turn this into a vector and use prettier vector arithmetic float resizeAreaY = screenSpaceDimensions().y * _resizeAreaPercentage; @@ -259,7 +264,26 @@ namespace openspace { resizePosition.x = isOnRight ? 1 : isOnLeft ? -1 : 0; resizePosition.y = isOnTop ? 1 : isOnBottom ? -1 : 0; - return resizePosition; + _resizeDirection = resizePosition; + + return isOnRight || isOnLeft || isOnTop || isOnBottom; + } + + void ScreenSpaceSkyBrowser::resize(const glm::vec2& start, const glm::vec2& mouseDrag) + { + glm::vec2 scaling = mouseDrag * glm::vec2(_resizeDirection); + glm::vec2 newSizeRelToOld = (_originalScreenSpaceSize + (scaling)) / + _originalScreenSpaceSize; + // Scale the browser + setScale(newSizeRelToOld); + + // For dragging functionality, translate so it looks like the + // browser isn't moving. Make sure the browser doesn't move in + // directions it's not supposed to + glm::vec2 translation = 0.5f * mouseDrag * abs( + glm::vec2(_resizeDirection) + ); + translate(translation, start); } void ScreenSpaceSkyBrowser::setScale(float scalingFactor) { @@ -292,6 +316,7 @@ namespace openspace { } void ScreenSpaceSkyBrowser::saveResizeStartSize() { + _originalScreenSpaceSize = screenSpaceDimensions(); _originalDimensions = _dimensions; _originalScale = _scale; }