mirror of
https://github.com/OpenSpace/OpenSpace.git
synced 2026-01-05 03:00:58 -06:00
Add new classes for browsers
This commit is contained in:
107
modules/skybrowser/include/browser.h
Normal file
107
modules/skybrowser/include/browser.h
Normal file
@@ -0,0 +1,107 @@
|
||||
/*****************************************************************************************
|
||||
* *
|
||||
* 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___BROWSER___H__
|
||||
#define __OPENSPACE_MODULE_SKYBROWSER___BROWSER___H__
|
||||
|
||||
#include <openspace/documentation/documentation.h>
|
||||
#include <modules/webbrowser/include/webrenderhandler.h>
|
||||
#include <openspace/properties/stringproperty.h>
|
||||
#include <openspace/properties/vector/vec2property.h>
|
||||
#include <openspace/properties/triggerproperty.h>
|
||||
|
||||
#ifdef _MSC_VER
|
||||
#pragma warning (push)
|
||||
#pragma warning (disable : 4100)
|
||||
#endif // _MSC_VER
|
||||
|
||||
#ifdef __clang__
|
||||
#pragma clang diagnostic push
|
||||
#pragma clang diagnostic ignored "-Wunused-parameter"
|
||||
#endif // __clang__
|
||||
|
||||
#include <include/cef_client.h>
|
||||
|
||||
#ifdef __clang__
|
||||
#pragma clang diagnostic pop
|
||||
#endif // __clang__
|
||||
|
||||
#ifdef _MSC_VER
|
||||
#pragma warning (pop)
|
||||
#endif // _MSC_VER
|
||||
|
||||
namespace ghoul::opengl { class Texture; }
|
||||
|
||||
namespace openspace {
|
||||
|
||||
class BrowserInstance;
|
||||
class RenderHandler;
|
||||
class WebKeyboardHandler;
|
||||
|
||||
class Browser {
|
||||
public:
|
||||
|
||||
Browser(const ghoul::Dictionary& dictionary);
|
||||
Browser(Browser const&) = default;
|
||||
~Browser();
|
||||
|
||||
bool initializeGL();
|
||||
bool deinitializeGL();
|
||||
|
||||
void render();
|
||||
void update();
|
||||
bool isReady() const;
|
||||
|
||||
glm::vec2 browserPixelDimensions() const;
|
||||
|
||||
|
||||
protected:
|
||||
properties::Vec2Property _dimensions;
|
||||
properties::StringProperty _url;
|
||||
properties::TriggerProperty _reload;
|
||||
std::unique_ptr<BrowserInstance> _browserInstance;
|
||||
std::unique_ptr<ghoul::opengl::Texture> _texture;
|
||||
|
||||
|
||||
class RenderHandler : public WebRenderHandler {
|
||||
public:
|
||||
void draw() override;
|
||||
void render() override;
|
||||
|
||||
void setTexture(GLuint t);
|
||||
};
|
||||
|
||||
private:
|
||||
void bindTexture();
|
||||
|
||||
CefRefPtr<RenderHandler> _renderHandler;
|
||||
CefRefPtr<WebKeyboardHandler> _keyboardHandler;
|
||||
|
||||
bool _isUrlDirty = false;
|
||||
bool _isDimensionsDirty = false;
|
||||
};
|
||||
|
||||
} // namespace openspace
|
||||
|
||||
#endif // __OPENSPACE_MODULE_SKYBROWSER___BROWSER___H__
|
||||
89
modules/skybrowser/include/screenspaceskybrowser2.h
Normal file
89
modules/skybrowser/include/screenspaceskybrowser2.h
Normal file
@@ -0,0 +1,89 @@
|
||||
#ifndef __OPENSPACE_MODULE_SKYBROWSER___SCREENSPACESKYBROWSER2___H__
|
||||
#define __OPENSPACE_MODULE_SKYBROWSER___SCREENSPACESKYBROWSER2___H__
|
||||
|
||||
#include <modules/skybrowser/include/wwtcommunicator.h>
|
||||
#include <openspace/rendering/screenspacerenderable.h>
|
||||
#include <openspace/documentation/documentation.h>
|
||||
#include <openspace/properties/stringproperty.h>
|
||||
#include <openspace/properties/scalar/floatproperty.h>
|
||||
#include <openspace/properties/vector/ivec3property.h>
|
||||
#include <deque>
|
||||
|
||||
namespace openspace {
|
||||
class ScreenSpaceSkyTarget;
|
||||
|
||||
class ScreenSpaceSkyBrowser2 : public ScreenSpaceRenderable, public WwtCommunicator
|
||||
{
|
||||
public:
|
||||
// Constructor and destructor
|
||||
ScreenSpaceSkyBrowser2(const ghoul::Dictionary& dictionary);
|
||||
virtual ~ScreenSpaceSkyBrowser2();
|
||||
|
||||
// Inherited functions
|
||||
bool initializeGL() override;
|
||||
bool deinitializeGL() override;
|
||||
glm::mat4 scaleMatrix() override;
|
||||
void render() override;
|
||||
void update() override;
|
||||
|
||||
// Target - browser connection
|
||||
bool connectToSkyTarget();
|
||||
bool isAnimated();
|
||||
void startFovAnimation(float fov);
|
||||
void incrementallyAnimateToFov(float deltaTime);
|
||||
glm::dvec2 fineTuneVector(glm::dvec2 drag);
|
||||
|
||||
// Getters returning references
|
||||
ScreenSpaceSkyTarget* getSkyTarget();
|
||||
properties::FloatProperty& getOpacity();
|
||||
|
||||
// Setters
|
||||
void setVerticalFovWithScroll(float scroll);
|
||||
void setScale(glm::vec2 scalingFactor);
|
||||
void setScale(float scalingFactor);
|
||||
|
||||
// Communication with WorldWide Telescope
|
||||
void startSyncingWithWwt();
|
||||
|
||||
|
||||
// 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);
|
||||
|
||||
private:
|
||||
void syncWwtView();
|
||||
void bindTexture() override;
|
||||
|
||||
// Resize functions
|
||||
void saveResizeStartSize();
|
||||
void updateBrowserSize();
|
||||
|
||||
// Properties
|
||||
properties::StringProperty _skyTargetId;
|
||||
|
||||
// Flags
|
||||
bool _isSyncedWithWwt{ false };
|
||||
bool _isFovAnimated{ false };
|
||||
float _endVfov{ 0.f };
|
||||
float _fovDiff{ 0.01f };
|
||||
|
||||
// Resizing of browser
|
||||
glm::vec2 _originalDimensions;
|
||||
float _originalScale;
|
||||
float _resizeAreaPercentage{ 0.1f };
|
||||
|
||||
// Target & images
|
||||
ScreenSpaceSkyTarget* _skyTarget{ nullptr };
|
||||
std::thread _wwtMessages;
|
||||
|
||||
// Time variables
|
||||
// For capping the calls to change the zoom from scrolling
|
||||
constexpr static const std::chrono::milliseconds _timeUpdateInterval{ 10 };
|
||||
std::chrono::system_clock::time_point _lastUpdateTime;
|
||||
};
|
||||
}
|
||||
|
||||
#endif // __OPENSPACE_MODULE_SKYBROWSER___SCREENSPACESKYBROWSER2___H__
|
||||
87
modules/skybrowser/include/wwtcommunicator.h
Normal file
87
modules/skybrowser/include/wwtcommunicator.h
Normal file
@@ -0,0 +1,87 @@
|
||||
/*****************************************************************************************
|
||||
* *
|
||||
* 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___WWTCOMMUNICATOR___H__
|
||||
#define __OPENSPACE_MODULE_SKYBROWSER___WWTCOMMUNICATOR___H__
|
||||
|
||||
#include <modules/skybrowser/include/browser.h>
|
||||
#include <openspace/properties/vector/ivec3property.h>
|
||||
#include <openspace/properties/scalar/floatproperty.h>
|
||||
#include <openspace/documentation/documentation.h>
|
||||
#include <deque>
|
||||
#include <thread>
|
||||
|
||||
namespace openspace {
|
||||
|
||||
class ImageData;
|
||||
|
||||
class WwtCommunicator : public Browser {
|
||||
|
||||
public:
|
||||
|
||||
WwtCommunicator(const ghoul::Dictionary& dictionary);
|
||||
WwtCommunicator(WwtCommunicator const&) = default;
|
||||
virtual ~WwtCommunicator();
|
||||
|
||||
// Web page communication
|
||||
|
||||
void setIdInBrowser(const std::string& id);
|
||||
|
||||
// WorldWide Telescope communication
|
||||
void displayImage(const std::string& url, const int i);
|
||||
void removeSelectedImage(const int i);
|
||||
void setImageLayerOrder(int i, int order);
|
||||
|
||||
// Getters
|
||||
const std::deque<int>& getSelectedImages();
|
||||
glm::ivec3 borderColor() const;
|
||||
float verticalFov() const;
|
||||
glm::dvec2 fieldsOfView();
|
||||
bool hasLoadedImages() const;
|
||||
|
||||
|
||||
// Setters
|
||||
void setHasLoadedImages(bool isLoaded);
|
||||
void setVerticalFov(float vfov);
|
||||
void setWebpageBorderColor(glm::ivec3 color);
|
||||
|
||||
// Display
|
||||
void highlight(glm::ivec3 addition);
|
||||
void removeHighlight(glm::ivec3 removal);
|
||||
|
||||
protected:
|
||||
void sendMessageToWwt(const ghoul::Dictionary& msg);
|
||||
properties::FloatProperty _verticalFov;
|
||||
properties::IVec3Property _borderColor;
|
||||
|
||||
std::deque<int> _selectedImages;
|
||||
bool _hasLoadedImages{ false };
|
||||
|
||||
private:
|
||||
void executeJavascript(const std::string& script) const;
|
||||
};
|
||||
|
||||
} // namespace openspace
|
||||
|
||||
#endif // __OPENSPACE_MODULE_SKYBROWSER___WWTCOMMUNICATOR___H__
|
||||
174
modules/skybrowser/src/browser.cpp
Normal file
174
modules/skybrowser/src/browser.cpp
Normal file
@@ -0,0 +1,174 @@
|
||||
/*****************************************************************************************
|
||||
* *
|
||||
* 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 <modules/skybrowser/include/browser.h>
|
||||
|
||||
#include <modules/webbrowser/webbrowsermodule.h>
|
||||
#include <modules/webbrowser/include/webkeyboardhandler.h>
|
||||
#include <modules/webbrowser/include/browserinstance.h>
|
||||
#include <openspace/engine/windowdelegate.h>
|
||||
#include <openspace/engine/globals.h>
|
||||
#include <openspace/engine/moduleengine.h>
|
||||
#include <ghoul/opengl/texture.h>
|
||||
#include <ghoul/logging/logmanager.h>
|
||||
#include <apps\OpenSpace\ext\sgct\include\sgct\utils\box.h>
|
||||
|
||||
namespace {
|
||||
constexpr const char* _loggerCat = "Browser";
|
||||
|
||||
const openspace::properties::Property::PropertyInfo DimensionsInfo = {
|
||||
"Dimensions",
|
||||
"Browser Dimensions",
|
||||
"Set the dimensions of the web browser window."
|
||||
};
|
||||
const openspace::properties::Property::PropertyInfo UrlInfo = {
|
||||
"Url",
|
||||
"URL",
|
||||
"The URL to load"
|
||||
};
|
||||
|
||||
const openspace::properties::Property::PropertyInfo ReloadInfo = {
|
||||
"Reload",
|
||||
"Reload",
|
||||
"Reload the web browser"
|
||||
};
|
||||
|
||||
} // namespace
|
||||
|
||||
namespace openspace {
|
||||
|
||||
void Browser::RenderHandler::draw() {}
|
||||
|
||||
void Browser::RenderHandler::render() {}
|
||||
|
||||
void Browser::RenderHandler::setTexture(GLuint t) {
|
||||
_texture = t;
|
||||
}
|
||||
|
||||
|
||||
Browser::Browser(const ghoul::Dictionary& dictionary)
|
||||
: _url(UrlInfo)
|
||||
, _dimensions(DimensionsInfo, glm::vec2(0.f), glm::vec2(0.f), glm::vec2(3000.f))
|
||||
, _reload(ReloadInfo)
|
||||
{
|
||||
if (dictionary.hasValue<std::string>(UrlInfo.identifier)) {
|
||||
_url = dictionary.value<std::string>(UrlInfo.identifier);
|
||||
}
|
||||
|
||||
glm::vec2 windowDimensions = global::windowDelegate->currentSubwindowSize();
|
||||
_dimensions = windowDimensions;
|
||||
|
||||
_url.onChange([this]() { _isUrlDirty = true; });
|
||||
_dimensions.onChange([this]() { _isDimensionsDirty = true; });
|
||||
_reload.onChange([this]() { _browserInstance->reloadBrowser(); });
|
||||
|
||||
// Create browser and render handler
|
||||
_renderHandler = new RenderHandler();
|
||||
_keyboardHandler = new WebKeyboardHandler();
|
||||
_browserInstance = std::make_unique<BrowserInstance>(
|
||||
_renderHandler,
|
||||
_keyboardHandler
|
||||
);
|
||||
|
||||
WebBrowserModule* webBrowser = global::moduleEngine->module<WebBrowserModule>();
|
||||
if (webBrowser) {
|
||||
webBrowser->addBrowser(_browserInstance.get());
|
||||
}
|
||||
}
|
||||
|
||||
Browser::~Browser() {
|
||||
// Delete
|
||||
_browserInstance.reset();
|
||||
_texture.reset();
|
||||
}
|
||||
|
||||
bool Browser::initializeGL() {
|
||||
_texture = std::make_unique<ghoul::opengl::Texture>(
|
||||
glm::uvec3(_dimensions.value(), 1.0f)
|
||||
);
|
||||
|
||||
_renderHandler->setTexture(*_texture);
|
||||
|
||||
_browserInstance->initialize();
|
||||
_browserInstance->loadUrl(_url);
|
||||
return isReady();
|
||||
}
|
||||
|
||||
|
||||
bool Browser::deinitializeGL() {
|
||||
_renderHandler->setTexture(0);
|
||||
_texture = nullptr;
|
||||
|
||||
std::string urlString;
|
||||
_url.getStringValue(urlString);
|
||||
LDEBUG(fmt::format("Deinitializing ScreenSpaceBrowser: {}", urlString));
|
||||
|
||||
_browserInstance->close(true);
|
||||
|
||||
WebBrowserModule* webBrowser = global::moduleEngine->module<WebBrowserModule>();
|
||||
if (webBrowser) {
|
||||
webBrowser->removeBrowser(_browserInstance.get());
|
||||
_browserInstance.reset();
|
||||
}
|
||||
else {
|
||||
LWARNING("Could not find WebBrowserModule");
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void Browser::render() {
|
||||
if (!_renderHandler->isTextureReady()) {
|
||||
return;
|
||||
}
|
||||
_renderHandler->updateTexture();
|
||||
|
||||
}
|
||||
|
||||
void Browser::update() {
|
||||
if (_isUrlDirty) {
|
||||
_browserInstance->loadUrl(_url);
|
||||
_isUrlDirty = false;
|
||||
}
|
||||
|
||||
if (_isDimensionsDirty) {
|
||||
_browserInstance->reshape(_dimensions.value());
|
||||
_isDimensionsDirty = false;
|
||||
}
|
||||
}
|
||||
|
||||
bool Browser::isReady() const {
|
||||
return _texture.get();
|
||||
}
|
||||
|
||||
void Browser::bindTexture() {
|
||||
_texture->bind();
|
||||
}
|
||||
|
||||
glm::vec2 Browser::browserPixelDimensions() const {
|
||||
return _dimensions.value();
|
||||
}
|
||||
|
||||
|
||||
} // namespace openspace
|
||||
335
modules/skybrowser/src/screenspaceskybrowser2.cpp
Normal file
335
modules/skybrowser/src/screenspaceskybrowser2.cpp
Normal file
@@ -0,0 +1,335 @@
|
||||
#include <modules/skybrowser/include/ScreenSpaceSkyBrowser2.h>
|
||||
|
||||
#include <modules/skybrowser/include/screenspaceskytarget.h>
|
||||
#include <modules/skybrowser/include/utility.h>
|
||||
#include <openspace/engine/globals.h>
|
||||
#include <openspace/rendering/renderengine.h>
|
||||
#include <ghoul/logging/logmanager.h>
|
||||
#include <ghoul/misc/dictionaryjsonformatter.h> // formatJson
|
||||
#include <ghoul/opengl/texture.h>
|
||||
#include <optional>
|
||||
|
||||
namespace {
|
||||
constexpr const char* _loggerCat = "ScreenSpaceSkyBrowser2";
|
||||
|
||||
constexpr const openspace::properties::Property::PropertyInfo BrowserDimensionInfo =
|
||||
{
|
||||
"BrowserDimensions",
|
||||
"Browser Dimensions",
|
||||
"The pixel dimensions of the sky browser."
|
||||
};
|
||||
constexpr const openspace::properties::Property::PropertyInfo TargetIdInfo =
|
||||
{
|
||||
"TargetId",
|
||||
"Target Id",
|
||||
"The identifier of the target. It is used to synchronize the sky browser and the"
|
||||
"sky target."
|
||||
};
|
||||
constexpr const openspace::properties::Property::PropertyInfo BorderColorInfo =
|
||||
{
|
||||
"BorderColor",
|
||||
"Border Color",
|
||||
"The color of the border of the sky browser."
|
||||
};
|
||||
constexpr const openspace::properties::Property::PropertyInfo VerticalFovInfo =
|
||||
{
|
||||
"VerticalFieldOfView",
|
||||
"Vertical Field Of View",
|
||||
"The vertical field of view in degrees."
|
||||
};
|
||||
|
||||
struct [[codegen::Dictionary(ScreenSpaceSkyBrowser2)]] Parameters {
|
||||
|
||||
// [[codegen::verbatim(BrowserDimensionInfo.description)]]
|
||||
std::optional<glm::vec2> browserDimensions;
|
||||
|
||||
// [[codegen::verbatim(VerticalFovInfo.description)]]
|
||||
std::optional<float> verticalFov;
|
||||
|
||||
// [[codegen::verbatim(TargetIdInfo.description)]]
|
||||
std::optional<std::string> targetId;
|
||||
|
||||
// [[codegen::verbatim(BorderColorInfo.description)]]
|
||||
std::optional<glm::ivec3> borderColor;
|
||||
};
|
||||
|
||||
#include "ScreenSpaceSkyBrowser2_codegen.cpp"
|
||||
} // namespace
|
||||
|
||||
namespace openspace {
|
||||
|
||||
ScreenSpaceSkyBrowser2::ScreenSpaceSkyBrowser2(const ghoul::Dictionary& dictionary)
|
||||
: ScreenSpaceRenderable(dictionary),
|
||||
WwtCommunicator(dictionary)
|
||||
, _skyTargetId(TargetIdInfo)
|
||||
{
|
||||
// Make the color property display a color picker in the GUI
|
||||
_borderColor.setViewOption("Color", true);
|
||||
|
||||
// Handle target dimension property
|
||||
const Parameters p = codegen::bake<Parameters>(dictionary);
|
||||
_verticalFov = p.verticalFov.value_or(_verticalFov);
|
||||
_borderColor = p.borderColor.value_or(_borderColor);
|
||||
_skyTargetId = p.targetId.value_or(_skyTargetId);
|
||||
|
||||
addProperty(_dimensions);
|
||||
addProperty(_verticalFov);
|
||||
addProperty(_borderColor);
|
||||
addProperty(_skyTargetId);
|
||||
|
||||
_verticalFov.onChange([&]() {
|
||||
if (_skyTarget) {
|
||||
_skyTarget->setScale(_verticalFov);
|
||||
}
|
||||
});
|
||||
_borderColor.onChange([&]() {
|
||||
setWebpageBorderColor(_borderColor.value());
|
||||
});
|
||||
_skyTargetId.onChange([&]() {
|
||||
connectToSkyTarget();
|
||||
});
|
||||
|
||||
// Set a unique identifier
|
||||
std::string identifier;
|
||||
if (dictionary.hasValue<std::string>(KeyIdentifier)) {
|
||||
identifier = dictionary.value<std::string>(KeyIdentifier);
|
||||
}
|
||||
else {
|
||||
identifier = "ScreenSpaceSkyBrowser22";
|
||||
}
|
||||
identifier = makeUniqueIdentifier(identifier);
|
||||
setIdentifier(identifier);
|
||||
|
||||
glm::vec2 screenPosition = _cartesianPosition.value();
|
||||
_cartesianPosition.setValue(glm::vec3(screenPosition, skybrowser::ScreenSpaceZ));
|
||||
|
||||
// Always make sure that the target and browser are visible together
|
||||
_enabled.onChange([&]() {
|
||||
if (_skyTarget) {
|
||||
_skyTarget->property("Enabled")->set(_enabled.value());
|
||||
}
|
||||
});
|
||||
|
||||
// Ensure the color of the border is bright enough.
|
||||
// Make sure the RGB color at least is 50% brightness
|
||||
// By making each channel 50% bright in general
|
||||
// 222 = sqrt(3*(0.5*256)^2)
|
||||
while (glm::length(glm::vec3(_borderColor.value())) < 222.f) {
|
||||
_borderColor = glm::vec3(rand() % 256, rand() % 256, rand() % 256);
|
||||
}
|
||||
}
|
||||
|
||||
ScreenSpaceSkyBrowser2::~ScreenSpaceSkyBrowser2() {
|
||||
// Set flag to false so the thread can exit
|
||||
_isSyncedWithWwt = false;
|
||||
if (_wwtMessages.joinable()) {
|
||||
_wwtMessages.join();
|
||||
LINFO("Joined thread");
|
||||
}
|
||||
}
|
||||
|
||||
bool ScreenSpaceSkyBrowser2::initializeGL() {
|
||||
|
||||
return Browser::initializeGL() && ScreenSpaceRenderable::initializeGL();
|
||||
}
|
||||
|
||||
|
||||
void ScreenSpaceSkyBrowser2::startSyncingWithWwt() {
|
||||
// If the camera is already synced, the browser is already syncing
|
||||
if (!_isSyncedWithWwt) {
|
||||
_isSyncedWithWwt = true;
|
||||
// Set border color
|
||||
setWebpageBorderColor(_borderColor.value());
|
||||
// Track target
|
||||
syncWwtView();
|
||||
}
|
||||
}
|
||||
|
||||
glm::dvec2 ScreenSpaceSkyBrowser2::fineTuneVector(glm::dvec2 drag) {
|
||||
// Fine tuning of target
|
||||
glm::dvec2 wwtFov = fieldsOfView();
|
||||
glm::dvec2 openSpaceFOV = skybrowser::fovWindow();
|
||||
|
||||
glm::dvec2 browserDim = screenSpaceDimensions();
|
||||
glm::dvec2 angleResult = wwtFov * (drag / browserDim);
|
||||
glm::dvec2 resultRelativeOs = angleResult / openSpaceFOV;
|
||||
|
||||
// Convert to screen space coordinate system
|
||||
glm::dvec2 convertToScreenSpace{ (2 * skybrowser::windowRatio()), 2.f };
|
||||
glm::dvec2 result = - convertToScreenSpace * resultRelativeOs;
|
||||
return result;
|
||||
}
|
||||
/*
|
||||
void ScreenSpaceBrowser::setXCallback(std::function<void()> callback) {
|
||||
_originalDimensions.onChange(std::move(callback));
|
||||
}
|
||||
*/
|
||||
bool ScreenSpaceSkyBrowser2::deinitializeGL() {
|
||||
// Set flag to false so the thread can exit
|
||||
_isSyncedWithWwt = false;
|
||||
if (_wwtMessages.joinable()) {
|
||||
_wwtMessages.join();
|
||||
LINFO("Joined thread");
|
||||
}
|
||||
return Browser::deinitializeGL() && ScreenSpaceRenderable::deinitializeGL();
|
||||
}
|
||||
|
||||
bool ScreenSpaceSkyBrowser2::connectToSkyTarget() {
|
||||
_skyTarget = dynamic_cast<ScreenSpaceSkyTarget*>(
|
||||
global::renderEngine->screenSpaceRenderable(_skyTargetId.value()));
|
||||
return _skyTarget;
|
||||
}
|
||||
|
||||
bool ScreenSpaceSkyBrowser2::isAnimated()
|
||||
{
|
||||
return _isFovAnimated;
|
||||
}
|
||||
|
||||
void ScreenSpaceSkyBrowser2::startFovAnimation(float fov)
|
||||
{
|
||||
_isFovAnimated = true;
|
||||
_endVfov = fov;
|
||||
}
|
||||
|
||||
void ScreenSpaceSkyBrowser2::incrementallyAnimateToFov(float deltaTime)
|
||||
{
|
||||
// If distance too large, keep animating. Else, stop animation
|
||||
float diff = verticalFov() - _endVfov;
|
||||
const bool shouldAnimate = abs(diff) > _fovDiff;
|
||||
|
||||
if (shouldAnimate) {
|
||||
setVerticalFovWithScroll(diff);
|
||||
}
|
||||
else {
|
||||
_isFovAnimated = false;
|
||||
}
|
||||
}
|
||||
|
||||
void ScreenSpaceSkyBrowser2::render() {
|
||||
Browser::render();
|
||||
|
||||
draw(
|
||||
globalRotationMatrix() *
|
||||
translationMatrix() *
|
||||
localRotationMatrix() *
|
||||
scaleMatrix()
|
||||
);
|
||||
}
|
||||
|
||||
void ScreenSpaceSkyBrowser2::update() {
|
||||
Browser::update();
|
||||
ScreenSpaceRenderable::update();
|
||||
}
|
||||
|
||||
ScreenSpaceSkyTarget* ScreenSpaceSkyBrowser2::getSkyTarget() {
|
||||
return _skyTarget;
|
||||
}
|
||||
|
||||
void ScreenSpaceSkyBrowser2::setVerticalFovWithScroll(float scroll) {
|
||||
// Cap how often the zoom is allowed to update
|
||||
std::chrono::system_clock::time_point now = std::chrono::system_clock::now();
|
||||
std::chrono::system_clock::duration timeSinceLastUpdate = now - _lastUpdateTime;
|
||||
|
||||
if (timeSinceLastUpdate > _timeUpdateInterval) {
|
||||
// Make scroll more sensitive the smaller the FOV
|
||||
float x = _verticalFov;
|
||||
float zoomFactor = atan(x / 50.0) + exp(x / 40) - 0.999999;
|
||||
float zoom = scroll > 0.0 ? -zoomFactor : zoomFactor;
|
||||
_verticalFov = std::clamp(_verticalFov + zoom, 0.001f, 70.0f);
|
||||
_lastUpdateTime = std::chrono::system_clock::now();
|
||||
}
|
||||
}
|
||||
|
||||
void ScreenSpaceSkyBrowser2::syncWwtView() {
|
||||
|
||||
// Start a thread to enable user interaction while sending the calls to WWT
|
||||
_wwtMessages = std::thread([&] {
|
||||
while (_isSyncedWithWwt) {
|
||||
if (_skyTarget) {
|
||||
// Message WorldWide Telescope current view
|
||||
glm::dvec3 cartesian = _skyTarget->directionEquatorial();
|
||||
|
||||
ghoul::Dictionary message = wwtmessage::moveCamera(
|
||||
skybrowser::cartesianToSpherical(cartesian),
|
||||
_verticalFov,
|
||||
skybrowser::cameraRoll()
|
||||
);
|
||||
sendMessageToWwt(message);
|
||||
}
|
||||
|
||||
// Sleep so we don't bombard WWT with too many messages
|
||||
std::this_thread::sleep_for(std::chrono::milliseconds(50));
|
||||
}
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
glm::ivec2 ScreenSpaceSkyBrowser2::isOnResizeArea(glm::vec2 coord) {
|
||||
glm::ivec2 resizePosition = glm::ivec2{ 0 };
|
||||
// Make sure coordinate is on browser
|
||||
if (!coordIsInsideCornersScreenSpace(coord)) return resizePosition;
|
||||
|
||||
// TO DO: turn this into a vector and use prettier vector arithmetic
|
||||
float resizeAreaY = screenSpaceDimensions().y * _resizeAreaPercentage;
|
||||
float resizeAreaX = screenSpaceDimensions().x * _resizeAreaPercentage;
|
||||
|
||||
const bool isOnTop = coord.y > upperRightCornerScreenSpace().y - resizeAreaY;
|
||||
const bool isOnBottom = coord.y < lowerLeftCornerScreenSpace().y + resizeAreaY;
|
||||
const bool isOnRight = coord.x > upperRightCornerScreenSpace().x - resizeAreaX;
|
||||
const bool isOnLeft = coord.x < lowerLeftCornerScreenSpace().x + resizeAreaX;
|
||||
|
||||
resizePosition.x = isOnRight ? 1 : isOnLeft ? -1 : 0;
|
||||
resizePosition.y = isOnTop ? 1 : isOnBottom ? -1 : 0;
|
||||
|
||||
return resizePosition;
|
||||
}
|
||||
// Scales the ScreenSpaceBrowser to a new ratio
|
||||
void ScreenSpaceSkyBrowser2::setScale(glm::vec2 scalingFactor) {
|
||||
|
||||
// Scale on the y axis, this is to ensure that _scale = 1 is
|
||||
// equal to the height of the window
|
||||
setScale(abs(scalingFactor.y));
|
||||
// Resize the dimensions of the texture on the x axis
|
||||
glm::vec2 newSize = abs(scalingFactor) * _originalDimensions;
|
||||
_texture->setDimensions(glm::ivec3(newSize, 1));
|
||||
_objectSize = _texture->dimensions();
|
||||
}
|
||||
|
||||
glm::mat4 ScreenSpaceSkyBrowser2::scaleMatrix() {
|
||||
// To ensure the plane has the right ratio
|
||||
// The _scale tells us how much of the windows height the
|
||||
// browser covers: e.g. a browser that covers 0.25 of the
|
||||
// height of the window will have scale = 0.25
|
||||
|
||||
float textureRatio = static_cast<float>(_texture->dimensions().x) /
|
||||
static_cast<float>(_texture->dimensions().y);
|
||||
|
||||
glm::mat4 scale = glm::scale(
|
||||
glm::mat4(1.f),
|
||||
glm::vec3(textureRatio * _scale, _scale, 1.f)
|
||||
);
|
||||
return scale;
|
||||
}
|
||||
|
||||
void ScreenSpaceSkyBrowser2::saveResizeStartSize() {
|
||||
_originalDimensions = _dimensions.value();
|
||||
_originalScale = _scale.value();
|
||||
}
|
||||
|
||||
// Updates the browser size to match the size of the texture
|
||||
void ScreenSpaceSkyBrowser2::updateBrowserSize() {
|
||||
_dimensions = _texture->dimensions();
|
||||
}
|
||||
|
||||
void ScreenSpaceSkyBrowser2::setScale(float scalingFactor) {
|
||||
_scale = _originalScale * scalingFactor;
|
||||
}
|
||||
|
||||
properties::FloatProperty& ScreenSpaceSkyBrowser2::getOpacity() {
|
||||
return _opacity;
|
||||
}
|
||||
|
||||
void ScreenSpaceSkyBrowser2::bindTexture() {
|
||||
_texture->bind();
|
||||
}
|
||||
}
|
||||
183
modules/skybrowser/src/wwtcommunicator.cpp
Normal file
183
modules/skybrowser/src/wwtcommunicator.cpp
Normal file
@@ -0,0 +1,183 @@
|
||||
/*****************************************************************************************
|
||||
* *
|
||||
* 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 <modules/skybrowser/include/wwtcommunicator.h>
|
||||
|
||||
#include <modules/webbrowser/webbrowsermodule.h>
|
||||
#include <modules/webbrowser/include/webkeyboardhandler.h>
|
||||
#include <modules/webbrowser/include/browserinstance.h>
|
||||
#include <ghoul/misc/dictionaryjsonformatter.h> // formatJson
|
||||
#include <modules/skybrowser/include/utility.h>
|
||||
|
||||
|
||||
namespace {
|
||||
constexpr const char* _loggerCat = "WwtCommunicator";
|
||||
|
||||
constexpr const openspace::properties::Property::PropertyInfo BorderColorInfo =
|
||||
{
|
||||
"BorderColor",
|
||||
"Border Color",
|
||||
"The color of the border of the sky browser."
|
||||
};
|
||||
constexpr const openspace::properties::Property::PropertyInfo VerticalFovInfo =
|
||||
{
|
||||
"VerticalFieldOfView",
|
||||
"Vertical Field Of View",
|
||||
"The vertical field of view in degrees."
|
||||
};
|
||||
|
||||
} // namespace
|
||||
|
||||
namespace openspace {
|
||||
|
||||
WwtCommunicator::WwtCommunicator(const ghoul::Dictionary& dictionary)
|
||||
: Browser(dictionary),
|
||||
_verticalFov(VerticalFovInfo, 10.f, 0.01f, 70.0f),
|
||||
_borderColor(BorderColorInfo, glm::ivec3(200), glm::ivec3(0), glm::ivec3(255))
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
WwtCommunicator::~WwtCommunicator() {
|
||||
|
||||
}
|
||||
|
||||
void WwtCommunicator::displayImage(const std::string& url, int i)
|
||||
{
|
||||
// Ensure there are no duplicates
|
||||
auto it = std::find(std::begin(_selectedImages), std::end(_selectedImages), i);
|
||||
if (it == std::end(_selectedImages)) {
|
||||
// Push newly selected image to front
|
||||
_selectedImages.push_front(i);
|
||||
// Index of image is used as layer ID as it is unique in the image data set
|
||||
sendMessageToWwt(wwtmessage::addImage(std::to_string(i), url));
|
||||
sendMessageToWwt(wwtmessage::setImageOpacity(std::to_string(i), 1.0));
|
||||
}
|
||||
}
|
||||
|
||||
void WwtCommunicator::removeSelectedImage(const int i) {
|
||||
// Remove from selected list
|
||||
auto it = std::find(std::begin(_selectedImages), std::end(_selectedImages), i);
|
||||
|
||||
if (it != std::end(_selectedImages)) {
|
||||
_selectedImages.erase(it);
|
||||
sendMessageToWwt(wwtmessage::removeImage(std::to_string(i)));
|
||||
}
|
||||
}
|
||||
|
||||
void WwtCommunicator::sendMessageToWwt(const ghoul::Dictionary& msg) {
|
||||
std::string script = "sendMessageToWWT(" + ghoul::formatJson(msg) + ");";
|
||||
executeJavascript(script);
|
||||
}
|
||||
|
||||
const std::deque<int>& WwtCommunicator::getSelectedImages() {
|
||||
return _selectedImages;
|
||||
}
|
||||
|
||||
void WwtCommunicator::setVerticalFov(float vfov) {
|
||||
_verticalFov = vfov;
|
||||
}
|
||||
|
||||
void WwtCommunicator::setWebpageBorderColor(glm::ivec3 color) {
|
||||
std::string stringColor = std::to_string(color.x) + ","
|
||||
+ std::to_string(color.y) + "," + std::to_string(color.z);
|
||||
std::string script = "document.body.style.backgroundColor = 'rgb("
|
||||
+ stringColor + ")';";
|
||||
executeJavascript(script);
|
||||
}
|
||||
|
||||
void WwtCommunicator::highlight(glm::ivec3 addition)
|
||||
{
|
||||
glm::ivec3 color = glm::ivec3(_borderColor.value());
|
||||
setWebpageBorderColor(color + addition);
|
||||
}
|
||||
|
||||
void WwtCommunicator::removeHighlight(glm::ivec3 removal)
|
||||
{
|
||||
glm::ivec3 color = glm::ivec3(_borderColor.value());
|
||||
setWebpageBorderColor(color - removal);
|
||||
}
|
||||
|
||||
glm::dvec2 WwtCommunicator::fieldsOfView() {
|
||||
float browserRatio = _dimensions.value().x / _dimensions.value().y;
|
||||
glm::dvec2 browserFov = glm::dvec2(verticalFov() * browserRatio, verticalFov());
|
||||
|
||||
return browserFov;
|
||||
}
|
||||
|
||||
bool WwtCommunicator::hasLoadedImages() const {
|
||||
return _hasLoadedImages;
|
||||
}
|
||||
|
||||
void WwtCommunicator::setImageLayerOrder(int i, int order) {
|
||||
// Find in selected images list
|
||||
auto current = std::find(
|
||||
std::begin(_selectedImages),
|
||||
std::end(_selectedImages),
|
||||
i
|
||||
);
|
||||
auto target = std::begin(_selectedImages) + order;
|
||||
|
||||
// Make sure the image was found in the list
|
||||
if (current != std::end(_selectedImages) && target != std::end(_selectedImages)) {
|
||||
// Swap the two images
|
||||
std::iter_swap(current, target);
|
||||
}
|
||||
|
||||
int reverseOrder = _selectedImages.size() - order - 1;
|
||||
ghoul::Dictionary message = wwtmessage::setLayerOrder(std::to_string(i),
|
||||
reverseOrder);
|
||||
sendMessageToWwt(message);
|
||||
}
|
||||
|
||||
void WwtCommunicator::setHasLoadedImages(bool isLoaded) {
|
||||
_hasLoadedImages = isLoaded;
|
||||
}
|
||||
|
||||
void WwtCommunicator::setIdInBrowser(const std::string& id) {
|
||||
// Send ID to it's browser
|
||||
executeJavascript("setId('" + id + "')");
|
||||
}
|
||||
|
||||
void WwtCommunicator::executeJavascript(const std::string& script) const {
|
||||
// Make sure that the browser has a main frame
|
||||
const bool browserExists = _browserInstance && _browserInstance->getBrowser();
|
||||
const bool frameIsLoaded = browserExists &&
|
||||
_browserInstance->getBrowser()->GetMainFrame();
|
||||
|
||||
if (frameIsLoaded) {
|
||||
CefRefPtr<CefFrame> frame = _browserInstance->getBrowser()->GetMainFrame();
|
||||
frame->ExecuteJavaScript(script, frame->GetURL(), 0);
|
||||
}
|
||||
}
|
||||
|
||||
glm::ivec3 WwtCommunicator::borderColor() const {
|
||||
return _borderColor.value();
|
||||
}
|
||||
|
||||
float WwtCommunicator::verticalFov() const {
|
||||
return _verticalFov.value();
|
||||
}
|
||||
|
||||
} // namespace openspace
|
||||
Reference in New Issue
Block a user