Update the structure of the renderable sky browser to inherit fronm renderable plane and wwtcommuicator

This commit is contained in:
sylvass
2021-11-23 09:48:07 -05:00
parent d5cdf4b3f8
commit 27d68556ec
6 changed files with 65 additions and 278 deletions

View File

@@ -39,12 +39,11 @@ local browser = {
asset.onInitialize(function ()
openspace.addSceneGraphNode(browser)
openspace.skybrowser.addToSkyBrowserModule(browserId)
openspace.skybrowser.add3dBrowserToSkyBrowserModule(browserId)
end)
asset.onDeinitialize(function ()
openspace.removeScreenSpaceRenderable(browserId)
openspace.removeScreenSpaceRenderable(targetId)
openspace.removeSceneGraphNode(browserId)
end)
asset.export("browser", {browser})

View File

@@ -30,11 +30,11 @@ set(HEADER_FILES
include/screenspaceskytarget.h
include/wwtdatahandler.h
include/utility.h
include/renderableskybrowser.h
include/pair.h
include/wwtcommunicator.h
include/browser.h
include/screenspaceskybrowser.h
include/renderableskybrowser.h
ext/tinyxml2/tinyxml2.h
)

View File

@@ -2,9 +2,7 @@
#define __OPENSPACE_MODULE_SKYBROWSER___RENDERABLESKYBROWSER___H__
#include <modules/skybrowser/include/wwtdatahandler.h>
#include <modules/webbrowser/include/webrenderhandler.h>
#include <modules/webbrowser/include/browserinstance.h>
#include <modules/webbrowser/include/webkeyboardhandler.h>
#include <modules/skybrowser/include/wwtcommunicator.h>
#include <modules/base/rendering/renderableplane.h>
#include <openspace/documentation/documentation.h>
#include <openspace/properties/vector/vec2property.h>
@@ -35,72 +33,32 @@ namespace ghoul::opengl { class Texture; }
namespace openspace::documentation { struct Documentation; }
#pragma optimize("", off)
namespace openspace {
class RenderableSkyBrowser : public RenderablePlane
class RenderableSkyBrowser : public RenderablePlane, public WwtCommunicator
{
public:
static constexpr const char* KeyIdentifier = "Identifier";
RenderableSkyBrowser(const ghoul::Dictionary& dictionary);
virtual ~RenderableSkyBrowser() = default;
~RenderableSkyBrowser();
// Inherited from RenderablePlane
void initializeGL() override;
void deinitializeGL() override;
void update(const UpdateData& data) override;
// Web page communication
void executeJavascript(std::string script) const;
void setIdInBrowser(std::string id);
// WorldWide Telescope communication
void displayImage(const ImageData& image, const int i);
void removeSelectedImage(const ImageData& image, const int i);
void sendMessageToWwt(const ghoul::Dictionary& msg);
void syncWwtView();
// Set up initialization with wwt
void stopSyncingWwtView();
void setIdInBrowser();
// Place
void placeAt3dPosition(const ImageData& image);
// Getters
float verticalFov() const;
std::deque<int>& getSelectedImages();
// Setters
void setImageLayerOrder(int i, int order);
private:
// Properties
properties::Vec2Property _dimensions;
properties::StringProperty _url;
properties::TriggerProperty _reload;
class ScreenSpaceRenderHandler : public WebRenderHandler {
public:
void draw() override;
void render() override;
void setTexture(GLuint t);
};
void bindTexture() override;
// Browser variables
std::unique_ptr<BrowserInstance> _browserInstance;
std::unique_ptr<ghoul::opengl::Texture> _texture;
CefRefPtr<ScreenSpaceRenderHandler> _renderHandler;
CefRefPtr<WebKeyboardHandler> _keyboardHandler;
// Flags
bool _isUrlDirty = false;
bool _isDimensionsDirty = false;
bool _isSyncedWithWwt;
float _verticalFov;
std::thread _threadWwtMessages;
std::deque<int> _selectedImages;
};
}

View File

@@ -470,15 +470,15 @@ void SkyBrowserModule::setSelectedObject()
// Find and save what mouse is currently hovering on
auto it = std::find_if(std::begin(_targetsBrowsers), std::end(_targetsBrowsers),
[&] (Pair &pair) {
bool onBrowser = pair.getBrowser()->coordIsInsideCornersScreenSpace(
[&] (const std::unique_ptr<Pair> &pair) {
bool onBrowser = pair->getBrowser()->coordIsInsideCornersScreenSpace(
_mousePosition
);
bool onTarget = pair.getTarget()->coordIsInsideCornersScreenSpace(
bool onTarget = pair->getTarget()->coordIsInsideCornersScreenSpace(
_mousePosition
);
if (onBrowser) {
_selectedBrowser = pair.getBrowser()->identifier();
_selectedBrowser = pair->getBrowser()->identifier();
}
_isBrowser = onBrowser;
@@ -489,7 +489,7 @@ void SkyBrowserModule::setSelectedObject()
_mouseOnPair = nullptr;
}
else {
_mouseOnPair = &(*it);
_mouseOnPair = it->get();
}
// Selection has changed
@@ -518,8 +518,7 @@ void SkyBrowserModule::addTargetBrowserPair(std::string targetId, std::string br
// Assert pair to have both target and browser
if (browser && target) {
Pair newPair(browser, target);
_targetsBrowsers.push_back(newPair);
_targetsBrowsers.push_back(std::make_unique<Pair>(browser, target));
}
}
@@ -584,9 +583,11 @@ void SkyBrowserModule::removeTargetBrowserPair(std::string& id) {
if (!found) {
return;
}
auto it = std::remove(std::begin(_targetsBrowsers), std::end(_targetsBrowsers),
*found);
auto it = std::remove_if(std::begin(_targetsBrowsers), std::end(_targetsBrowsers),
[&](const std::unique_ptr<Pair>& pair) {
return *found == *(pair.get());
});
std::string targetId = found->getTarget()->identifier();
// Remove from engine
openspace::global::scriptEngine->queueScript(
@@ -644,7 +645,7 @@ void SkyBrowserModule::selectImage3dBrowser(int i)
_browser3dNode->renderable());
if (renderable) {
const ImageData& image = _dataHandler->getImage(i);
renderable->displayImage(image, i);
renderable->displayImage(image.imageUrl, i);
}
}
@@ -698,13 +699,11 @@ void SkyBrowserModule::add2dSelectedImagesTo3d(const std::string& pairId)
if (pair && get3dBrowser()) {
// Empty 3D browser selection
get3dBrowser()->getSelectedImages().clear();
// Copy 2D selection of images to 3D browser
const std::deque<int> images = pair->getSelectedImages();
std::for_each(std::begin(images), std::end(images), [&](const int i) {
const ImageData& image = _dataHandler->getImage(i);
get3dBrowser()->displayImage(image, i);
get3dBrowser()->displayImage(image.imageUrl, i);
});
}
}
@@ -713,7 +712,7 @@ const std::unique_ptr<WwtDataHandler>& SkyBrowserModule::getWWTDataHandler() {
return _dataHandler;
}
std::vector<Pair>& SkyBrowserModule::getPairs()
std::vector<std::unique_ptr<Pair>>& SkyBrowserModule::getPairs()
{
return _targetsBrowsers;
}
@@ -721,12 +720,17 @@ std::vector<Pair>& SkyBrowserModule::getPairs()
Pair* SkyBrowserModule::getPair(const std::string& id)
{
auto it = std::find_if(std::begin(_targetsBrowsers), std::end(_targetsBrowsers),
[&](Pair& pair) {
bool foundBrowser = pair.browserId() == id;
bool foundTarget = pair.targetId() == id;
[&](const std::unique_ptr<Pair>& pair) {
bool foundBrowser = pair->browserId() == id;
bool foundTarget = pair->targetId() == id;
return foundBrowser || foundTarget;
});
return &(*it);
if (it == std::end(_targetsBrowsers)) {
return nullptr;
}
else {
return it->get();
}
}
SceneGraphNode* SkyBrowserModule::get3dBrowserNode() {
@@ -776,7 +780,7 @@ void SkyBrowserModule::place3dBrowser(const ImageData& image, const int i)
{
// If the image has a 3D position, add it to the scene graph
if (image.has3dCoords && get3dBrowser()) {
get3dBrowser()->displayImage(image, i);
get3dBrowser()->displayImage(image.imageUrl, i);
get3dBrowser()->placeAt3dPosition(image);
}
else {
@@ -829,14 +833,14 @@ void SkyBrowserModule::incrementallyFadeBrowserTargets(Transparency goal, float
}(goal);
bool isAllFinished{ false };
for (Pair& pair : _targetsBrowsers) {
if (pair.isEnabled()) {
bool isPairFinished = pair.hasFinishedFading(transparency);
for (std::unique_ptr<Pair>& pair : _targetsBrowsers) {
if (pair->isEnabled()) {
bool isPairFinished = pair->hasFinishedFading(transparency);
if (!isPairFinished) {
pair.incrementallyFade(transparency, _fadingTime, deltaTime);
pair->incrementallyFade(transparency, _fadingTime, deltaTime);
}
else if (isPairFinished && goal == Transparency::Transparent) {
pair.disable();
pair->disable();
}
isAllFinished &= isPairFinished;
}
@@ -850,9 +854,9 @@ void SkyBrowserModule::incrementallyFadeBrowserTargets(Transparency goal, float
void SkyBrowserModule::incrementallyAnimateTargets(double deltaTime)
{
for (Pair& pair : _targetsBrowsers) {
if (pair.isEnabled()) {
pair.incrementallyAnimateToCoordinate(deltaTime);
for (std::unique_ptr<Pair>& pair : _targetsBrowsers) {
if (pair->isEnabled()) {
pair->incrementallyAnimateToCoordinate(deltaTime);
}
}
}

View File

@@ -56,7 +56,7 @@ public:
virtual ~SkyBrowserModule();
// Getters
std::vector<Pair>& getPairs();
std::vector<std::unique_ptr<Pair>>& getPairs();
Pair* getPair(const std::string& id);
SceneGraphNode* get3dBrowserNode();
RenderableSkyBrowser* get3dBrowser();
@@ -108,7 +108,7 @@ private:
void startRotatingCamera(glm::dvec3 endAnimation); // Pass in galactic coordinate
// The browsers and targets
std::vector<Pair> _targetsBrowsers;
std::vector<std::unique_ptr<Pair>> _targetsBrowsers;
Pair* _mouseOnPair{ nullptr };
Pair* _selectedPair{ nullptr };
bool _isBrowser{ false };

View File

@@ -1,8 +1,6 @@
#include <modules/skybrowser/include/renderableskybrowser.h>
#include <modules/skybrowser/include/utility.h>
#include <modules/webbrowser/webbrowsermodule.h>
#include <openspace/engine/moduleengine.h>
#include <openspace/engine/windowdelegate.h>
#include <openspace/engine/globals.h>
#include <openspace/util/distanceconstants.h>
@@ -49,27 +47,11 @@ namespace {
namespace openspace {
void RenderableSkyBrowser::ScreenSpaceRenderHandler::draw() {}
void RenderableSkyBrowser::ScreenSpaceRenderHandler::render() {}
void RenderableSkyBrowser::ScreenSpaceRenderHandler::setTexture(GLuint t) {
_texture = t;
}
RenderableSkyBrowser::RenderableSkyBrowser(const ghoul::Dictionary& dictionary)
: RenderablePlane(dictionary)
, _url(UrlInfo)
, _dimensions(DimensionsInfo, glm::vec2(0.f), glm::vec2(0.f), glm::vec2(3000.f))
, _reload(ReloadInfo)
, _verticalFov(70.f)
, _isSyncedWithWwt(false)
: RenderablePlane(dictionary),
WwtCommunicator(dictionary)
{
// Handle target dimension property
const Parameters p = codegen::bake<Parameters>(dictionary);
_url = p.url.value_or(_url);
std::string identifier;
if (dictionary.hasValue<std::string>(KeyIdentifier)) {
identifier = dictionary.value<std::string>(KeyIdentifier);
@@ -79,179 +61,51 @@ namespace openspace {
}
setIdentifier(identifier);
const Parameters p = codegen::bake<Parameters>(dictionary);
_url = p.url.value_or(_url);
// Ensure the texture is a square for now
// Maybe change later
glm::vec2 windowDimensions = global::windowDelegate->currentSubwindowSize();
float maxDimension = std::max(windowDimensions.x, windowDimensions.y);
_dimensions = { maxDimension, maxDimension };
// Create browser and render handler
_renderHandler = new ScreenSpaceRenderHandler();
_keyboardHandler = new WebKeyboardHandler();
_browserInstance = std::make_unique<BrowserInstance>(
_renderHandler,
_keyboardHandler
);
_url.onChange([this]() { _isUrlDirty = true; });
_dimensions.onChange([this]() { _isDimensionsDirty = true; });
_reload.onChange([this]() { _browserInstance->reloadBrowser(); });
addProperty(_url);
addProperty(_dimensions);
addProperty(_reload);
addProperty(_verticalFov);
addProperty(_borderColor);
addProperty(_equatorialAim);
}
RenderableSkyBrowser::~RenderableSkyBrowser() {
WebBrowserModule* webBrowser = global::moduleEngine->module<WebBrowserModule>();
if (webBrowser) {
webBrowser->addBrowser(_browserInstance.get());
}
}
void RenderableSkyBrowser::initializeGL() {
Browser::initializeGL();
RenderablePlane::initializeGL();
_texture = std::make_unique<ghoul::opengl::Texture>(
glm::uvec3(_dimensions.value(), 1.0f)
);
_texture->setDimensions(glm::ivec3(_dimensions.value(), 1));
_renderHandler->setTexture(*_texture);
// The browser gets by default the size of the OpenSpace window, so it needs to
// be resized
_browserInstance->initialize();
_browserInstance->loadUrl(_url);
_browserInstance->reshape(_dimensions.value());
}
void RenderableSkyBrowser::deinitializeGL() {
RenderablePlane::deinitializeGL();
_renderHandler->setTexture(0);
_texture = nullptr;
std::string urlString;
_url.getStringValue(urlString);
LDEBUG(fmt::format("Deinitializing RenderableSkyBrowser: {}", urlString));
_browserInstance->close(true);
WebBrowserModule* webBrowser = global::moduleEngine->module<WebBrowserModule>();
if (webBrowser) {
webBrowser->removeBrowser(_browserInstance.get());
_browserInstance.reset();
}
else {
LWARNING("Could not find WebBrowserModule");
}
RenderablePlane::deinitializeGL();
Browser::deinitializeGL();
}
void RenderableSkyBrowser::update(const UpdateData& data) {
Browser::update();
RenderablePlane::update(data);
_renderHandler->updateTexture();
if (_isUrlDirty) {
_browserInstance->loadUrl(_url);
_isUrlDirty = false;
}
if (_isDimensionsDirty) {
_browserInstance->reshape(_dimensions.value());
_isDimensionsDirty = false;
}
}
void RenderableSkyBrowser::bindTexture() {
if (_texture) {
_texture->bind();
}
else {
glBindTexture(GL_TEXTURE_2D, 0);
}
void RenderableSkyBrowser::stopSyncingWwtView()
{
}
void RenderableSkyBrowser::executeJavascript(std::string script) const {
//LINFOC(_loggerCat, "Executing javascript " + script);
const bool isBrowserReady = _browserInstance && _browserInstance->getBrowser();
const bool isMainFrameReady = _browserInstance->getBrowser()->GetMainFrame();
if (isBrowserReady && isMainFrameReady) {
CefRefPtr<CefFrame> frame = _browserInstance->getBrowser()->GetMainFrame();
frame->ExecuteJavaScript(script, frame->GetURL(), 0);
}
}
void RenderableSkyBrowser::sendMessageToWwt(const ghoul::Dictionary& msg) {
std::string script = "sendMessageToWWT(" + ghoul::formatJson(msg) + ");";
executeJavascript(script);
}
void RenderableSkyBrowser::displayImage(const ImageData& image, const int i) {
ghoul::Dictionary msg = wwtmessage::moveCamera(
image.equatorialSpherical,
image.fov,
0.0
);
sendMessageToWwt(msg);
_verticalFov = image.fov;
// Add to selected images if 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);
// Create image layer and center WWT app on the image
sendMessageToWwt(wwtmessage::addImage(std::to_string(i), image.imageUrl));
LINFO("Image has been loaded to " + identifier());
}
}
void RenderableSkyBrowser::removeSelectedImage(const ImageData& image, 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 RenderableSkyBrowser::setIdInBrowser(std::string id) {
// Send ID to it's browser
executeJavascript("setId('" + id + "')");
}
float RenderableSkyBrowser::verticalFov() const {
return _verticalFov;
}
void RenderableSkyBrowser::syncWwtView() {
// If the camera is already synced, the browser is already initialized
if (!_isSyncedWithWwt) {
_isSyncedWithWwt = true;
// Start a thread to enable user interaction while sending the calls to WWT
_threadWwtMessages = std::thread([&] {
while (_isSyncedWithWwt) {
glm::dvec2 aim{ 0.0 };
// Send a message just to establish contact
ghoul::Dictionary msg = wwtmessage::moveCamera(
aim,
_verticalFov,
0.0
);
sendMessageToWwt(msg);
// Sleep so we don't bombard WWT with too many messages
std::this_thread::sleep_for(std::chrono::milliseconds(500));
}
});
}
}
void RenderableSkyBrowser::stopSyncingWwtView() {
_isSyncedWithWwt = false;
if (_threadWwtMessages.joinable()) {
_threadWwtMessages.join();
}
void RenderableSkyBrowser::setIdInBrowser()
{
WwtCommunicator::setIdInBrowser(identifier());
}
void RenderableSkyBrowser::placeAt3dPosition(const ImageData& image)
@@ -301,32 +155,4 @@ namespace openspace {
scripting::ScriptEngine::RemoteScripting::Yes
);
}
std::deque<int>& RenderableSkyBrowser::getSelectedImages() {
return _selectedImages;
}
void RenderableSkyBrowser::setImageLayerOrder(int i, int order) {
// Remove from selected 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);
}
} // namespace