From 89e483c748ea1fca123f9d35b913c137f8c81f93 Mon Sep 17 00:00:00 2001 From: sylvass Date: Fri, 5 Nov 2021 12:03:38 -0400 Subject: [PATCH] Simplify fading functions --- modules/skybrowser/include/pair.h | 98 +++++++++ modules/skybrowser/skybrowsermodule.cpp | 56 ++--- modules/skybrowser/skybrowsermodule.h | 7 +- modules/skybrowser/src/pair.cpp | 276 ++++++++++++++++++++++++ 4 files changed, 401 insertions(+), 36 deletions(-) create mode 100644 modules/skybrowser/include/pair.h create mode 100644 modules/skybrowser/src/pair.cpp diff --git a/modules/skybrowser/include/pair.h b/modules/skybrowser/include/pair.h new file mode 100644 index 0000000000..2a025691bc --- /dev/null +++ b/modules/skybrowser/include/pair.h @@ -0,0 +1,98 @@ +/***************************************************************************************** + * * + * OpenSpace * + * * + * Copyright (c) 2014-2021 * + * * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this * + * software and associated documentation files (the "Software"), to deal in the Software * + * without restriction, including without limitation the rights to use, copy, modify, * + * merge, publish, distribute, sublicense, and/or sell copies of the Software, and to * + * permit persons to whom the Software is furnished to do so, subject to the following * + * conditions: * + * * + * The above copyright notice and this permission notice shall be included in all copies * + * or substantial portions of the Software. * + * * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, * + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A * + * PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT * + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF * + * CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE * + * OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. * + ****************************************************************************************/ + +#ifndef __OPENSPACE_MODULE_SKYBROWSER___PAIR___H__ +#define __OPENSPACE_MODULE_SKYBROWSER___PAIR___H__ + +#include +#include + +namespace openspace { + +class ScreenSpaceSkyBrowser; +class ScreenSpaceSkyTarget; +class ImageData; + +class Pair { +public: + + constexpr static const float AcceptableDiff = 0.01f; + + Pair(ScreenSpaceSkyBrowser* browser, ScreenSpaceSkyTarget* target); + Pair(Pair const&) = default; + + Pair& operator=(Pair other); + + void lock(); + void unlock(); + void setImageOrder(int i, int order); + void connectPair(); + void synchronizeWithWwt(); + void removeHighlight(glm::ivec3 color); + void highlight(glm::ivec3 color); + void enable(); + void disable(); + + void startAnimation(glm::dvec3 coordsEnd, float FOVEnd, bool shouldLockAfter = true); + void centerTargetOnScreen(); + void incrementallyAnimateToCoordinate(double deltaTime); + void incrementallyFade(float goalState, float fadeTime, float deltaTime); + bool isFinishedFading(float goalState); + bool isCoordOnPair(glm::vec2 mousePosition); + bool isEnabled(); + bool isLocked(); + + glm::ivec3 borderColor(); + glm::dvec3 targetDirectionEquatorial(); + glm::dvec3 targetDirectionGalactic(); + std::string browserGuiName(); + std::string browserId(); + std::string targetId(); + float verticalFov(); + const std::deque& getSelectedImages(); + void selectImage(const ImageData& image, const int i); + void removeSelectedImage(const int i); + void loadImages(std::string collection); + void setImageOpacity(const int i, float opacity); + void sendIdToBrowser(); + + ScreenSpaceSkyTarget* getTarget(); + ScreenSpaceSkyBrowser* getBrowser(); + + friend bool operator==(const Pair& lhs, const Pair& rhs); + friend bool operator!=(const Pair& lhs, const Pair& rhs); + +private: + + static std::string _selected; + bool isTargetFadeFinished(float goalState); + bool isBrowserFadeFinished(float goalState); + + ScreenSpaceSkyTarget* _target{ nullptr }; + ScreenSpaceSkyBrowser* _browser{ nullptr }; +}; + +} // namespace openspace + +#endif // __OPENSPACE_MODULE_SKYBROWSER___PAIR___H__ diff --git a/modules/skybrowser/skybrowsermodule.cpp b/modules/skybrowser/skybrowsermodule.cpp index 1e38c9bde5..a4e9b46fb1 100644 --- a/modules/skybrowser/skybrowsermodule.cpp +++ b/modules/skybrowser/skybrowsermodule.cpp @@ -416,7 +416,6 @@ SkyBrowserModule::SkyBrowserModule() _cameraInSolarSystem = glm::length(cameraPos) < _solarSystemRadius; // Fading flags - bool fadeIsFinished{ false }; if (_cameraInSolarSystem != camWasInSolarSystem) { _isTransitioningVizMode = true; @@ -429,20 +428,15 @@ SkyBrowserModule::SkyBrowserModule() // Fade pairs if the camera moved in or out the solar system if (_isTransitioningVizMode) { if (_cameraInSolarSystem) { - fadeIsFinished = fadeBrowserTargetsToOpaque(deltaTime); + incrementallyFadeBrowserTargets(Transparency::Opaque, deltaTime); } else { - fadeIsFinished = fadeBrowserTargetsToTransparent(deltaTime); - } - - // The transition is over when the fade is finished - if (fadeIsFinished) { - _isTransitioningVizMode = false; + incrementallyFadeBrowserTargets(Transparency::Transparent, deltaTime); } } if (_cameraInSolarSystem) { - animateTargets(deltaTime); + incrementallyAnimateTargets(deltaTime); } if (_cameraIsRotating) { incrementallyRotateCamera(deltaTime); @@ -776,33 +770,29 @@ void SkyBrowserModule::incrementallyRotateCamera(double deltaTime) { } } -bool SkyBrowserModule::fadeBrowserTargetsToTransparent(double deltaTime) +void SkyBrowserModule::incrementallyFadeBrowserTargets(Transparency goal, float deltaTime) { - bool fadeIsFinished{ false }; - for (Pair pair : _targetsBrowsers) { - if (pair.isEnabled()) { - bool finished = pair.fadeToTransparent(_fadingTime, deltaTime); - if (finished) { - pair.disable(); - } - fadeIsFinished &= finished; - } - } - return fadeIsFinished; -} - -bool SkyBrowserModule::fadeBrowserTargetsToOpaque(double deltaTime) -{ - bool fadeIsFinished{ false }; + float transparency = static_cast(goal); + bool isAllFinished{ false }; for (Pair pair : _targetsBrowsers) { - if (pair.isEnabled()) { - fadeIsFinished &= pair.fadeToOpaque(_fadingTime, deltaTime); - } - } - return fadeIsFinished; + if (pair.isEnabled()) { + pair.incrementallyFade(transparency, _fadingTime, deltaTime); + bool isPairFinished = pair.isFinishedFading(transparency); + + if (isPairFinished && goal == Transparency::Transparent) { + pair.disable(); + } + isAllFinished &= isPairFinished; + } + } + + // The transition is over when the fade is finished + if (isAllFinished) { + _isTransitioningVizMode = false; + } } -void SkyBrowserModule::animateTargets(double deltaTime) +void SkyBrowserModule::incrementallyAnimateTargets(double deltaTime) { for (Pair pair : _targetsBrowsers) { if (pair.isEnabled()) { @@ -825,8 +815,6 @@ std::string SkyBrowserModule::selectedBrowserId() { return _selectedBrowser; } - - bool SkyBrowserModule::cameraInSolarSystem() { return _cameraInSolarSystem; } diff --git a/modules/skybrowser/skybrowsermodule.h b/modules/skybrowser/skybrowsermodule.h index 3ed58e7fae..377b76d86a 100644 --- a/modules/skybrowser/skybrowsermodule.h +++ b/modules/skybrowser/skybrowsermodule.h @@ -49,6 +49,10 @@ class SceneGraphNode; class ImageData; class Pair; +enum class Transparency { + Transparent = 0, + Opaque = 1 +}; class SkyBrowserModule : public OpenSpaceModule { public: @@ -77,8 +81,7 @@ public: void lookAtTarget(std::string id); void incrementallyRotateCamera(double deltaTime); - bool fadeBrowserTargetsToTransparent(double deltaTime); - bool fadeBrowserTargetsToOpaque(double deltaTime); + void fadeBrowserTargets(Transparency goal, float deltaTime); void animateTargets(double deltaTime); void lookAt3dBrowser(); diff --git a/modules/skybrowser/src/pair.cpp b/modules/skybrowser/src/pair.cpp new file mode 100644 index 0000000000..7a568ff2a8 --- /dev/null +++ b/modules/skybrowser/src/pair.cpp @@ -0,0 +1,276 @@ +/***************************************************************************************** + * * + * OpenSpace * + * * + * Copyright (c) 2014-2021 * + * * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this * + * software and associated documentation files (the "Software"), to deal in the Software * + * without restriction, including without limitation the rights to use, copy, modify, * + * merge, publish, distribute, sublicense, and/or sell copies of the Software, and to * + * permit persons to whom the Software is furnished to do so, subject to the following * + * conditions: * + * * + * The above copyright notice and this permission notice shall be included in all copies * + * or substantial portions of the Software. * + * * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, * + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A * + * PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT * + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF * + * CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE * + * OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. * + ****************************************************************************************/ + +#include +#include +#include +#include +#include + +namespace openspace { + + std::string Pair::_selected = ""; // Define the static variable in the global scope + + Pair::Pair(ScreenSpaceSkyBrowser* browser, ScreenSpaceSkyTarget* target) + : _target(target), _browser(browser) + { + assert(browser != nullptr, "Sky browser is null pointer!"); + assert(target != nullptr, "Sky target is null pointer!"); + } + + Pair& Pair::operator=(Pair other) + { + std::swap(_target, other._target); + std::swap(_browser, other._browser); + return *this; + } + + void Pair::lock() { + _target->lock(); + } + + void Pair::unlock() { + _target->unlock(); + } + + void Pair::setImageOrder(int i, int order) { + _browser->setImageOrder(i, order); + } + + void Pair::connectPair() + { + _browser->connectToSkyTarget(); + _target->findSkyBrowser(); + } + + void Pair::synchronizeWithWwt() + { + _browser->startSyncingWithWwt(); + } + + void Pair::removeHighlight(glm::ivec3 color) + { + _target->removeHighlight(color); + _browser->removeHighlight(color); + } + + void Pair::highlight(glm::ivec3 color) + { + _browser->highlight(color); + _target->highlight(color); + } + + bool Pair::isTargetFadeFinished(float goalState) + { + // Is fading finished? + float targetDiff = abs(_target->opacity() - goalState); + + return targetDiff < AcceptableDiff; + } + + bool Pair::isBrowserFadeFinished(float goalState) + { + float browserDiff = abs(_browser->getOpacity().value() - goalState); + return browserDiff < AcceptableDiff; + } + + bool Pair::isCoordOnPair(glm::vec2 mousePosition) + { + bool onBrowser = _browser->coordIsInsideCornersScreenSpace(mousePosition); + bool onTarget = _target->coordIsInsideCornersScreenSpace(mousePosition); + if (onBrowser) { + _selected = _browser->identifier(); + } + else if (onTarget) { + _selected = _target->identifier(); + } + + return onBrowser || onTarget; + } + + void Pair::enable() + { + _browser->property("Enabled")->set(true); + _target->property("Enabled")->set(true); + } + + void Pair::disable() + { + _browser->property("Enabled")->set(false); + _target->property("Enabled")->set(false); + } + + bool Pair::isEnabled() + { + return _target->isEnabled() && _browser->isEnabled(); + } + + bool Pair::isLocked() + { + return _target->isLocked(); + } + + glm::ivec3 Pair::borderColor() + { + return _browser->borderColor(); + } + + glm::dvec3 Pair::targetDirectionEquatorial() + { + return _target->directionEquatorial(); + } + + glm::dvec3 Pair::targetDirectionGalactic() + { + return _target->directionGalactic(); + } + + std::string Pair::browserGuiName() + { + return _browser->guiName(); + } + + std::string Pair::browserId() + { + return _browser->identifier(); + } + + std::string Pair::targetId() + { + return _target->identifier(); + } + + float Pair::verticalFov() + { + return _browser->verticalFov(); + } + + const std::deque& Pair::getSelectedImages() + { + return _browser->getSelectedImages(); + } + + void Pair::selectImage(const ImageData& image, int i) + { + // Load image into browser + _browser->addSelectedImage(image, i); + + // If the image has coordinates, move the target + if (image.hasCelestialCoords) { + + // Animate the target to the image coordinate position + unlock(); + startAnimation(image.equatorialCartesian, image.fov); + } + } + + void Pair::removeSelectedImage(const int i) + { + _browser->removeSelectedImage(i); + } + + void Pair::loadImages(std::string collection) + { + _browser->sendMessageToWwt(wwtmessage::loadCollection(collection)); + _browser->setHasLoadedImages(true); + } + + void Pair::setImageOpacity(const int i, float opacity) + { + ghoul::Dictionary msg = wwtmessage::setImageOpacity(std::to_string(i), opacity); + _browser->sendMessageToWwt(msg); + } + + void Pair::sendIdToBrowser() + { + _browser->sendIdToBrowser(); + } + + void Pair::incrementallyAnimateToCoordinate(double deltaTime) + { + if (_target->isAnimated()) { + _target->animateToCoordinate(deltaTime); + } + else if (_browser->isAnimated()) { + _browser->incrementallyAnimateToFov(deltaTime); + } + } + + void Pair::startAnimation(glm::dvec3 coordsEnd, float FOVEnd, bool lockAfter) + { + _target->startAnimation(coordsEnd, lockAfter); + _browser->startFovAnimation(FOVEnd); + } + + void Pair::centerTargetOnScreen() + { + // Animate the target to the center of the screen + unlock(); + // Get camera direction in celestial spherical coordinates + glm::dvec3 viewDirection = skybrowser::cameraDirectionEquatorial(); + // Keep the current fov + float currentFov = verticalFov(); + startAnimation(viewDirection, currentFov, false); + } + + bool Pair::isFinishedFading(float goalState) + { + return isTargetFadeFinished(goalState) && isBrowserFadeFinished(goalState); + } + + ScreenSpaceSkyTarget* Pair::getTarget() { + return _target; + } + + ScreenSpaceSkyBrowser* Pair::getBrowser() { + return _browser; + } + + void Pair::incrementallyFade(float goalState, float fadeTime, float deltaTime) + { + float opacityDelta = static_cast(deltaTime / fadeTime); + + if (!isTargetFadeFinished(goalState)) { + _target->setOpacity(_target->opacity() + opacityDelta); + } + else { + _target->setOpacity(goalState); + } + + if (!isBrowserFadeFinished(goalState)) { + _browser->getOpacity() = _browser->getOpacity().value() + opacityDelta; + } + else { + _browser->getOpacity() = goalState; + } + } + + bool operator==(const Pair& lhs, const Pair& rhs) { + return lhs._target == rhs._target && lhs._browser == rhs._browser; + } + bool operator!=(const Pair & lhs, const Pair & rhs) { + return !(lhs == rhs); + } + +} // namespace openspace