mirror of
https://github.com/OpenSpace/OpenSpace.git
synced 2026-01-05 11:09:37 -06:00
Merge branch 'master' into project/infravis-2025-visA
This commit is contained in:
@@ -27,6 +27,12 @@ cmake_policy(VERSION 3.25)
|
||||
|
||||
project(OpenSpace)
|
||||
|
||||
# CMake 4.0 will no longer allow minimum required version below 3.5 and some of our
|
||||
# dependencies have not been updated to reflect this. To make things work, we blanked
|
||||
# require to 3.10 here to remove those issues. Once CMake configures and generates
|
||||
# successfully without this next line, it can be removed
|
||||
set(CMAKE_POLICY_VERSION_MINIMUM 3.10)
|
||||
|
||||
set(OPENSPACE_RELEASE_BUILD OFF)
|
||||
set(OPENSPACE_VERSION_MAJOR)
|
||||
set(OPENSPACE_VERSION_MINOR)
|
||||
|
||||
@@ -48,6 +48,7 @@ set(HEADER_FILES
|
||||
include/profile/timedialog.h
|
||||
include/profile/profileedit.h
|
||||
include/profile/propertiesdialog.h
|
||||
include/profile/uipanelsdialog.h
|
||||
include/sgctedit/displaywindowunion.h
|
||||
include/sgctedit/monitorbox.h
|
||||
include/sgctedit/sgctedit.h
|
||||
@@ -78,6 +79,7 @@ set(SOURCE_FILES
|
||||
src/profile/timedialog.cpp
|
||||
src/profile/profileedit.cpp
|
||||
src/profile/propertiesdialog.cpp
|
||||
src/profile/uipanelsdialog.cpp
|
||||
src/sgctedit/sgctedit.cpp
|
||||
src/sgctedit/displaywindowunion.cpp
|
||||
src/sgctedit/monitorbox.cpp
|
||||
|
||||
@@ -62,18 +62,16 @@ public:
|
||||
bool wasLaunchSelected() const;
|
||||
|
||||
/**
|
||||
* Returns the selected profile name when launcher window closed.
|
||||
* Returns the selected profile name when the launcher window closed.
|
||||
*
|
||||
* \return The name of selected profile (this is only the name without file extension
|
||||
* and without path)
|
||||
* \return The path to the selected profile
|
||||
*/
|
||||
std::string selectedProfile() const;
|
||||
|
||||
/**
|
||||
* Returns the selected sgct window configuration when launcher window closed.
|
||||
* Returns the selected SGCT window configuration when the launcher window closed.
|
||||
*
|
||||
* \return The name of selected profile (this is only the name without file extension
|
||||
* and without path)
|
||||
* \return The path to the selected profile
|
||||
*/
|
||||
std::string selectedWindowConfig() const;
|
||||
|
||||
|
||||
@@ -86,16 +86,17 @@ signals:
|
||||
void raiseExitWindow();
|
||||
|
||||
private slots:
|
||||
void openMeta();
|
||||
void openProperties();
|
||||
void openModules();
|
||||
void openKeybindings();
|
||||
void openAssets();
|
||||
void openTime();
|
||||
void openAddedScripts();
|
||||
void openKeybindings();
|
||||
void openMeta();
|
||||
void openMarkNodes();
|
||||
void openDeltaTimes();
|
||||
void openCamera();
|
||||
void openMarkNodes();
|
||||
void openTime();
|
||||
void openModules();
|
||||
void openUiPanels();
|
||||
void openAddedScripts();
|
||||
void approved();
|
||||
|
||||
private:
|
||||
@@ -112,18 +113,19 @@ private:
|
||||
std::string _profileFilename;
|
||||
|
||||
QLineEdit* _profileEdit = nullptr;
|
||||
QLabel* _modulesLabel = nullptr;
|
||||
QLabel* _assetsLabel = nullptr;
|
||||
QTextEdit* _assetsEdit = nullptr;
|
||||
QLabel* _propertiesLabel = nullptr;
|
||||
QTextEdit* _propertiesEdit = nullptr;
|
||||
QLabel* _assetsLabel = nullptr;
|
||||
QTextEdit* _assetsEdit = nullptr;
|
||||
QLabel* _keybindingsLabel = nullptr;
|
||||
QTextEdit* _keybindingsEdit = nullptr;
|
||||
QLabel* _deltaTimesLabel = nullptr;
|
||||
QLabel* _metaLabel = nullptr;
|
||||
QLabel* _interestingNodesLabel = nullptr;
|
||||
QLabel* _deltaTimesLabel = nullptr;
|
||||
QLabel* _cameraLabel = nullptr;
|
||||
QLabel* _timeLabel = nullptr;
|
||||
QLabel* _metaLabel = nullptr;
|
||||
QLabel* _modulesLabel = nullptr;
|
||||
QLabel* _uiPanelVisibilityLabel = nullptr;
|
||||
QLabel* _additionalScriptsLabel = nullptr;
|
||||
};
|
||||
|
||||
|
||||
51
apps/OpenSpace/ext/launcher/include/profile/uipanelsdialog.h
Normal file
51
apps/OpenSpace/ext/launcher/include/profile/uipanelsdialog.h
Normal file
@@ -0,0 +1,51 @@
|
||||
/*****************************************************************************************
|
||||
* *
|
||||
* OpenSpace *
|
||||
* *
|
||||
* Copyright (c) 2014-2025 *
|
||||
* *
|
||||
* 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_UI_LAUNCHER___UIPANELSDIALOG___H__
|
||||
#define __OPENSPACE_UI_LAUNCHER___UIPANELSDIALOG___H__
|
||||
|
||||
#include <QDialog>
|
||||
|
||||
class QCheckBox;
|
||||
|
||||
class UiPanelsDialog final : public QDialog {
|
||||
Q_OBJECT
|
||||
public:
|
||||
/**
|
||||
* Constructor for UiPanelsDialog class.
|
||||
*
|
||||
* \param parent Pointer to parent Qt widget
|
||||
* \param uiPanels The list of ui panels and their visibility
|
||||
*/
|
||||
UiPanelsDialog(QWidget* parent, std::map<std::string, bool>* uiPanels);
|
||||
|
||||
private slots:
|
||||
void parseSelections();
|
||||
|
||||
private:
|
||||
std::map<std::string, bool>* _uiPanels;
|
||||
std::map<QCheckBox*, std::string> _checkboxToId;
|
||||
};
|
||||
|
||||
#endif // __OPENSPACE_UI_LAUNCHER___UIPANELSDIALOG___H__
|
||||
@@ -127,9 +127,10 @@ public:
|
||||
*
|
||||
* \param quality The value for number of vertical lines of resolution. This will be
|
||||
* compared against the QualityValues array in order to set the correct
|
||||
* combobox index
|
||||
* combobox index
|
||||
* \tilt The tilt of the fisheye in degrees
|
||||
*/
|
||||
void setProjectionFisheye(int quality);
|
||||
void setProjectionFisheye(int quality, float tilt);
|
||||
|
||||
/**
|
||||
* Sets the window's projection type to spherical mirror, with the accompanying
|
||||
@@ -162,6 +163,21 @@ public:
|
||||
*/
|
||||
void setProjectionEquirectangular(int quality);
|
||||
|
||||
/**
|
||||
* Sets the window's projection type to blitting the contents of another window.
|
||||
*
|
||||
* \param windowBlitId The id of the window from which to blit
|
||||
*/
|
||||
void setProjectionBlit(int windowBlitId);
|
||||
|
||||
/**
|
||||
* This function must be called by users of this class whenever the total number of
|
||||
* windows has changed.
|
||||
*
|
||||
* \param newWindowCount the number of windows after the change
|
||||
*/
|
||||
void updateWindowCount(int newWindowCount);
|
||||
|
||||
signals:
|
||||
void windowChanged(int monitorIndex, int windowIndex, const QRectF& newDimensions);
|
||||
|
||||
@@ -171,6 +187,7 @@ private:
|
||||
QWidget* createSphericalMirrorWidget();
|
||||
QWidget* createCylindricalWidget();
|
||||
QWidget* createEquirectangularWidget();
|
||||
QWidget* createBlitWidget();
|
||||
|
||||
void onSizeXChanged(int newValue);
|
||||
void onSizeYChanged(int newValue);
|
||||
@@ -209,44 +226,39 @@ private:
|
||||
|
||||
struct {
|
||||
QWidget* widget = nullptr;
|
||||
QLabel* labelInfo = nullptr;
|
||||
QDoubleSpinBox* fovH = nullptr;
|
||||
QDoubleSpinBox* fovV = nullptr;
|
||||
QLabel* labelFovH = nullptr;
|
||||
QLabel* labelFovV = nullptr;
|
||||
QPushButton* buttonLockFov = nullptr;
|
||||
} _planar;
|
||||
|
||||
struct {
|
||||
QWidget* widget = nullptr;
|
||||
QLabel* labelInfo = nullptr;
|
||||
QComboBox* quality = nullptr;
|
||||
QLabel* labelQuality = nullptr;
|
||||
QDoubleSpinBox* tilt = nullptr;
|
||||
} _fisheye;
|
||||
|
||||
struct {
|
||||
QWidget* widget = nullptr;
|
||||
QLabel* labelInfo = nullptr;
|
||||
QComboBox* quality = nullptr;
|
||||
QLabel* labelQuality = nullptr;
|
||||
} _sphericalMirror;
|
||||
|
||||
struct {
|
||||
QWidget* widget = nullptr;
|
||||
QLabel* labelInfo = nullptr;
|
||||
QComboBox* quality = nullptr;
|
||||
QLabel* labelQuality = nullptr;
|
||||
QDoubleSpinBox* heightOffset = nullptr;
|
||||
QLabel* labelHeightOffset = nullptr;
|
||||
} _cylindrical;
|
||||
|
||||
struct {
|
||||
QWidget* widget = nullptr;
|
||||
QLabel* labelInfo = nullptr;
|
||||
QComboBox* quality = nullptr;
|
||||
QLabel* labelQuality = nullptr;
|
||||
} _equirectangular;
|
||||
|
||||
struct {
|
||||
QWidget* widget = nullptr;
|
||||
QComboBox* windowId = nullptr;
|
||||
QLabel* unavailable = nullptr;
|
||||
} _blit;
|
||||
|
||||
const QIcon _lockIcon;
|
||||
const QIcon _unlockIcon;
|
||||
};
|
||||
|
||||
@@ -35,6 +35,7 @@
|
||||
#include "profile/modulesdialog.h"
|
||||
#include "profile/propertiesdialog.h"
|
||||
#include "profile/timedialog.h"
|
||||
#include "profile/uipanelsdialog.h"
|
||||
#include <openspace/scene/profile.h>
|
||||
#include <ghoul/format.h>
|
||||
#include <QDialogButtonBox>
|
||||
@@ -305,6 +306,21 @@ void ProfileEdit::createWidgets() {
|
||||
rightLayout->addLayout(container);
|
||||
}
|
||||
rightLayout->addWidget(new Line);
|
||||
{
|
||||
QBoxLayout* container = new QVBoxLayout;
|
||||
_uiPanelVisibilityLabel = new QLabel("User Interface Panels");
|
||||
_uiPanelVisibilityLabel->setObjectName("heading");
|
||||
_uiPanelVisibilityLabel->setWordWrap(true);
|
||||
container->addWidget(_uiPanelVisibilityLabel);
|
||||
|
||||
QPushButton* uiPanelEdit = new QPushButton("Edit");
|
||||
connect(uiPanelEdit, &QPushButton::clicked, this, &ProfileEdit::openUiPanels);
|
||||
uiPanelEdit->setLayoutDirection(Qt::RightToLeft);
|
||||
uiPanelEdit->setAccessibleName("Edit user interface panels");
|
||||
container->addWidget(uiPanelEdit);
|
||||
rightLayout->addLayout(container);
|
||||
}
|
||||
rightLayout->addWidget(new Line);
|
||||
{
|
||||
QBoxLayout* container = new QVBoxLayout;
|
||||
_additionalScriptsLabel = new QLabel("Additional Scripts");
|
||||
@@ -375,6 +391,10 @@ void ProfileEdit::openModules() {
|
||||
_modulesLabel->setText(labelText(_profile.modules.size(), "Modules"));
|
||||
}
|
||||
|
||||
void ProfileEdit::openUiPanels() {
|
||||
UiPanelsDialog(this, &_profile.uiPanelVisibility).exec();
|
||||
}
|
||||
|
||||
void ProfileEdit::openProperties() {
|
||||
PropertiesDialog(this, &_profile.properties).exec();
|
||||
_propertiesLabel->setText(labelText(_profile.properties.size(), "Properties"));
|
||||
|
||||
130
apps/OpenSpace/ext/launcher/src/profile/uipanelsdialog.cpp
Normal file
130
apps/OpenSpace/ext/launcher/src/profile/uipanelsdialog.cpp
Normal file
@@ -0,0 +1,130 @@
|
||||
/*****************************************************************************************
|
||||
* *
|
||||
* OpenSpace *
|
||||
* *
|
||||
* Copyright (c) 2014-2025 *
|
||||
* *
|
||||
* 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 "profile/uipanelsdialog.h"
|
||||
|
||||
#include "profile/line.h"
|
||||
#include <openspace/json.h>
|
||||
#include <ghoul/filesystem/filesystem.h>
|
||||
#include <QCheckBox>
|
||||
#include <QDialogButtonBox>
|
||||
#include <QLabel>
|
||||
#include <QVBoxLayout>
|
||||
#include <fstream>
|
||||
#include <string_view>
|
||||
|
||||
namespace {
|
||||
constexpr std::string_view DefaultPanelPath = "${DATA}/web/default_ui_panels.json";
|
||||
|
||||
struct Panel {
|
||||
std::string id;
|
||||
std::string name;
|
||||
bool isVisible;
|
||||
};
|
||||
|
||||
void from_json(const nlohmann::json& j, Panel& layout) {
|
||||
j["id"].get_to(layout.id);
|
||||
j["name"].get_to(layout.name);
|
||||
j["visible"].get_to(layout.isVisible);
|
||||
}
|
||||
|
||||
std::vector<Panel> loadPanels() {
|
||||
std::ifstream panelFile = std::ifstream(absPath(DefaultPanelPath));
|
||||
const std::string panelContent = std::string(
|
||||
std::istreambuf_iterator<char>(panelFile),
|
||||
std::istreambuf_iterator<char>()
|
||||
);
|
||||
const nlohmann::json panel = nlohmann::json::parse(panelContent);
|
||||
std::map<std::string, Panel> panels = panel.get<std::map<std::string, Panel>>();
|
||||
|
||||
std::vector<Panel> result;
|
||||
for (const auto& [key, value] : panels) {
|
||||
result.push_back(value);
|
||||
}
|
||||
|
||||
std::sort(
|
||||
result.begin(),
|
||||
result.end(),
|
||||
[](const Panel& lhs, const Panel& rhs) { return lhs.name < rhs.name; }
|
||||
);
|
||||
|
||||
return result;
|
||||
}
|
||||
} // namespace
|
||||
|
||||
UiPanelsDialog::UiPanelsDialog(QWidget* parent, std::map<std::string, bool>* uiPanels)
|
||||
: QDialog(parent)
|
||||
, _uiPanels(uiPanels)
|
||||
{
|
||||
setWindowTitle("User Interface Panels");
|
||||
|
||||
std::vector<Panel> panels = loadPanels();
|
||||
|
||||
QBoxLayout* layout = new QVBoxLayout(this);
|
||||
|
||||
QLabel* info = new QLabel(
|
||||
"Select the user interface panels that should be visible by default in the "
|
||||
"current profile."
|
||||
);
|
||||
info->setWordWrap(true);
|
||||
layout->addWidget(info);
|
||||
|
||||
for (const Panel& panel : panels) {
|
||||
QCheckBox* box = new QCheckBox(QString::fromStdString(panel.name));
|
||||
|
||||
// If the profile already has a desired value for the checkbox, use it. Otherwise
|
||||
// use the default values
|
||||
auto it = _uiPanels->find(panel.id);
|
||||
if (it != _uiPanels->end()) {
|
||||
box->setChecked(it->second);
|
||||
}
|
||||
else {
|
||||
box->setChecked(panel.isVisible);
|
||||
}
|
||||
|
||||
layout->addWidget(box);
|
||||
_checkboxToId[box] = panel.id;
|
||||
}
|
||||
|
||||
layout->addWidget(new Line);
|
||||
|
||||
{
|
||||
QDialogButtonBox* buttons = new QDialogButtonBox;
|
||||
buttons->setStandardButtons(QDialogButtonBox::Save | QDialogButtonBox::Cancel);
|
||||
connect(
|
||||
buttons, &QDialogButtonBox::accepted,
|
||||
this, &UiPanelsDialog::parseSelections
|
||||
);
|
||||
connect(buttons, &QDialogButtonBox::rejected, this, &UiPanelsDialog::reject);
|
||||
layout->addWidget(buttons);
|
||||
}
|
||||
}
|
||||
|
||||
void UiPanelsDialog::parseSelections() {
|
||||
_uiPanels->clear();
|
||||
for (const auto& [key, value] : _checkboxToId) {
|
||||
_uiPanels->emplace(value, key->isChecked());
|
||||
}
|
||||
accept();
|
||||
}
|
||||
@@ -194,7 +194,7 @@ void DisplayWindowUnion::initialize(const std::vector<QRect>& monitorSizeList,
|
||||
},
|
||||
[&](const sgct::config::FisheyeProjection& p) {
|
||||
if (p.quality.has_value()) {
|
||||
wCtrl->setProjectionFisheye(*p.quality);
|
||||
wCtrl->setProjectionFisheye(*p.quality, p.tilt.value_or(0.f));
|
||||
}
|
||||
},
|
||||
[&](const sgct::config::PlanarProjection& p) {
|
||||
@@ -208,7 +208,12 @@ void DisplayWindowUnion::initialize(const std::vector<QRect>& monitorSizeList,
|
||||
wCtrl->setProjectionSphericalMirror(*p.quality);
|
||||
}
|
||||
},
|
||||
[&](const sgct::config::NoProjection&) {},
|
||||
[&](const sgct::config::NoProjection&) {
|
||||
// We can only generate blitting when there is no projection selected.
|
||||
if (w.blitWindowId.has_value()) {
|
||||
wCtrl->setProjectionBlit(*w.blitWindowId);
|
||||
}
|
||||
},
|
||||
[&](const sgct::config::ProjectionPlane&) {},
|
||||
[&](const sgct::config::CubemapProjection&) {},
|
||||
},
|
||||
@@ -251,6 +256,7 @@ void DisplayWindowUnion::updateWindows() {
|
||||
_addWindowButton->setEnabled(_nWindowsDisplayed != _windowControls.size());
|
||||
for (WindowControl* w : _windowControls) {
|
||||
w->showWindowLabel(_nWindowsDisplayed > 1);
|
||||
w->updateWindowCount(_nWindowsDisplayed);
|
||||
}
|
||||
|
||||
emit nWindowsChanged(_nWindowsDisplayed);
|
||||
|
||||
@@ -64,7 +64,8 @@ namespace {
|
||||
Fisheye,
|
||||
SphericalMirror,
|
||||
Cylindrical,
|
||||
Equirectangular
|
||||
Equirectangular,
|
||||
Blit
|
||||
};
|
||||
|
||||
constexpr int LineEditWidthFixedWindowSize = 95;
|
||||
@@ -378,7 +379,7 @@ WindowControl::WindowControl(int monitorIndex, int windowIndex,
|
||||
_projectionType = new QComboBox;
|
||||
_projectionType->addItems({
|
||||
"Planar Projection", "Fisheye", "Spherical Mirror Projection",
|
||||
"Cylindrical Projection", "Equirectangular Projection"
|
||||
"Cylindrical Projection", "Equirectangular Projection", "Copy Window Contents"
|
||||
});
|
||||
_projectionType->setToolTip("Select from the supported window projection types");
|
||||
_projectionType->setCurrentIndex(0);
|
||||
@@ -403,6 +404,9 @@ WindowControl::WindowControl(int monitorIndex, int windowIndex,
|
||||
_equirectangular.widget = createEquirectangularWidget();
|
||||
projectionLayout->addWidget(_equirectangular.widget);
|
||||
|
||||
_blit.widget = createBlitWidget();
|
||||
projectionLayout->addWidget(_blit.widget);
|
||||
|
||||
// We need to trigger this once to ensure that all of the defaults are correct
|
||||
onProjectionChanged(0);
|
||||
|
||||
@@ -424,21 +428,21 @@ QWidget* WindowControl::createPlanarWidget() {
|
||||
QGridLayout* layout = new QGridLayout(widget);
|
||||
layout->setColumnStretch(1, 1);
|
||||
|
||||
_planar.labelInfo = new QLabel(
|
||||
QLabel* labelInfo = new QLabel(
|
||||
"This projection type is the 'regular' projection with a horizontal and a "
|
||||
"vertical field of view, given in degrees. The wider the field of view, the "
|
||||
"more content is shown at the same time, but everything becomes smaller. Very "
|
||||
"large values will introduce distortions on the corners."
|
||||
);
|
||||
_planar.labelInfo->setObjectName("info");
|
||||
_planar.labelInfo->setWordWrap(true);
|
||||
layout->addWidget(_planar.labelInfo, 0, 0, 1, 3);
|
||||
labelInfo->setObjectName("info");
|
||||
labelInfo->setWordWrap(true);
|
||||
layout->addWidget(labelInfo, 0, 0, 1, 3);
|
||||
|
||||
_planar.labelFovH = new QLabel("Horizontal FOV");
|
||||
QLabel* labelFovH = new QLabel("Horizontal FOV");
|
||||
const QString hfovTip =
|
||||
"The total horizontal field of view of the viewport (degrees)";
|
||||
_planar.labelFovH->setToolTip(hfovTip);
|
||||
layout->addWidget(_planar.labelFovH, 1, 0);
|
||||
labelFovH->setToolTip(hfovTip);
|
||||
layout->addWidget(labelFovH, 1, 0);
|
||||
|
||||
_planar.fovH = new QDoubleSpinBox;
|
||||
_planar.fovH->setMinimum(FovEpsilon);
|
||||
@@ -452,11 +456,11 @@ QWidget* WindowControl::createPlanarWidget() {
|
||||
);
|
||||
layout->addWidget(_planar.fovH, 1, 1);
|
||||
|
||||
_planar.labelFovV = new QLabel("Vertical FOV");
|
||||
QLabel* labelFovV = new QLabel("Vertical FOV");
|
||||
const QString vfovTip = "The total vertical field of view of the viewport (degrees). "
|
||||
"Internally,\nthe values for 'up' & 'down' will each be half this value";
|
||||
_planar.labelFovV->setToolTip(vfovTip);
|
||||
layout->addWidget(_planar.labelFovV, 2, 0);
|
||||
labelFovV->setToolTip(vfovTip);
|
||||
layout->addWidget(labelFovV, 2, 0);
|
||||
|
||||
_planar.fovV = new QDoubleSpinBox;
|
||||
_planar.fovV->setMinimum(FovEpsilon);
|
||||
@@ -493,29 +497,29 @@ QWidget* WindowControl::createFisheyeWidget() {
|
||||
// *------------*-----------*
|
||||
// | { Informational text } | Row 0
|
||||
// | Quality * [DDDDD>] | Row 1
|
||||
// | [] Spout Output | Row 2
|
||||
// | Tilt * [oooooo] | Row 2
|
||||
// *------------*-----------*
|
||||
|
||||
QWidget* widget = new QWidget;
|
||||
QGridLayout* layout = new QGridLayout(widget);
|
||||
layout->setColumnStretch(1, 1);
|
||||
|
||||
_fisheye.labelInfo = new QLabel(
|
||||
QLabel* labelInfo = new QLabel(
|
||||
"This projection provides a rendering in a format that is suitable for "
|
||||
"planetariums and other immersive environments. A field-of-view of 180 degrees "
|
||||
"is presented as a circular image in the center of the screen. For this "
|
||||
"projection a square window is suggested, but not necessary."
|
||||
);
|
||||
_fisheye.labelInfo->setObjectName("info");
|
||||
_fisheye.labelInfo->setWordWrap(true);
|
||||
layout->addWidget(_fisheye.labelInfo, 0, 0, 1, 2);
|
||||
labelInfo->setObjectName("info");
|
||||
labelInfo->setWordWrap(true);
|
||||
layout->addWidget(labelInfo, 0, 0, 1, 2);
|
||||
|
||||
_fisheye.labelQuality = new QLabel("Quality");
|
||||
QLabel* labelQuality = new QLabel("Quality");
|
||||
const QString qualityTip = "Determines the pixel resolution of the projection "
|
||||
"rendering. The higher resolution,\nthe better the rendering quality, but at the "
|
||||
"expense of increased rendering times";
|
||||
_fisheye.labelQuality->setToolTip(qualityTip);
|
||||
layout->addWidget(_fisheye.labelQuality, 1, 0);
|
||||
"expense of increased rendering times.";
|
||||
labelQuality->setToolTip(qualityTip);
|
||||
layout->addWidget(labelQuality, 1, 0);
|
||||
|
||||
_fisheye.quality = new QComboBox;
|
||||
_fisheye.quality->addItems(qualityList());
|
||||
@@ -523,6 +527,19 @@ QWidget* WindowControl::createFisheyeWidget() {
|
||||
_fisheye.quality->setCurrentIndex(2);
|
||||
layout->addWidget(_fisheye.quality, 1, 1);
|
||||
|
||||
QLabel* labelTilt = new QLabel("Tilt");
|
||||
const QString tiltTip = "Determines the tilt (in degrees) of the fisheye rendering. "
|
||||
"Changing this value will cause the entire rendering to be tilted by the set "
|
||||
"number of degrees.";
|
||||
labelTilt->setToolTip(tiltTip);
|
||||
layout->addWidget(labelTilt, 2, 0);
|
||||
|
||||
_fisheye.tilt = new QDoubleSpinBox;
|
||||
_fisheye.tilt->setToolTip(tiltTip);
|
||||
_fisheye.tilt->setMinimum(-180.0);
|
||||
_fisheye.tilt->setMaximum(180.0);
|
||||
layout->addWidget(_fisheye.tilt, 2, 1);
|
||||
|
||||
return widget;
|
||||
}
|
||||
|
||||
@@ -536,22 +553,22 @@ QWidget* WindowControl::createSphericalMirrorWidget() {
|
||||
QGridLayout* layout = new QGridLayout(widget);
|
||||
layout->setColumnStretch(1, 1);
|
||||
|
||||
_sphericalMirror.labelInfo = new QLabel(
|
||||
QLabel* labelInfo = new QLabel(
|
||||
"This projection is rendering a image suite for use with a spherical mirror "
|
||||
"projection as described by Paul Bourke (http://paulbourke.net/dome/mirrordome/) "
|
||||
"and which is a low-cost yet effective way to provide content for a sphericalal "
|
||||
"display surface using a regular projector."
|
||||
);
|
||||
_sphericalMirror.labelInfo->setObjectName("info");
|
||||
_sphericalMirror.labelInfo->setWordWrap(true);
|
||||
layout->addWidget(_sphericalMirror.labelInfo, 0, 0, 1, 2);
|
||||
labelInfo->setObjectName("info");
|
||||
labelInfo->setWordWrap(true);
|
||||
layout->addWidget(labelInfo, 0, 0, 1, 2);
|
||||
|
||||
_sphericalMirror.labelQuality = new QLabel("Quality");
|
||||
QLabel* labelQuality = new QLabel("Quality");
|
||||
const QString qualityTip = "Determines the pixel resolution of the projection "
|
||||
"rendering. The higher resolution,\nthe better the rendering quality, but at the "
|
||||
"expense of increased rendering times";
|
||||
_sphericalMirror.labelQuality->setToolTip(qualityTip);
|
||||
layout->addWidget(_sphericalMirror.labelQuality, 1, 0);
|
||||
labelQuality->setToolTip(qualityTip);
|
||||
layout->addWidget(labelQuality, 1, 0);
|
||||
|
||||
_sphericalMirror.quality = new QComboBox;
|
||||
_sphericalMirror.quality->addItems(qualityList());
|
||||
@@ -573,22 +590,22 @@ QWidget* WindowControl::createCylindricalWidget() {
|
||||
QGridLayout* layout = new QGridLayout(widget);
|
||||
layout->setColumnStretch(1, 1);
|
||||
|
||||
_cylindrical.labelInfo = new QLabel(
|
||||
QLabel* labelInfo = new QLabel(
|
||||
"This projection type provides a cylindrical rendering that covers 360 degrees "
|
||||
"around the camera, which can be useful in immersive environments that are not "
|
||||
"spherical, but where, for example, all walls of a room are covered with "
|
||||
"projectors."
|
||||
);
|
||||
_cylindrical.labelInfo->setObjectName("info");
|
||||
_cylindrical.labelInfo->setWordWrap(true);
|
||||
layout->addWidget(_cylindrical.labelInfo, 0, 0, 1, 2);
|
||||
labelInfo->setObjectName("info");
|
||||
labelInfo->setWordWrap(true);
|
||||
layout->addWidget(labelInfo, 0, 0, 1, 2);
|
||||
|
||||
_cylindrical.labelQuality = new QLabel("Quality");
|
||||
QLabel* labelQuality = new QLabel("Quality");
|
||||
const QString qualityTip = "Determines the pixel resolution of the projection "
|
||||
"rendering. The higher resolution,\nthe better the rendering quality, but at the "
|
||||
"expense of increased rendering times";
|
||||
_cylindrical.labelQuality->setToolTip(qualityTip);
|
||||
layout->addWidget(_cylindrical.labelQuality, 1, 0);
|
||||
labelQuality->setToolTip(qualityTip);
|
||||
layout->addWidget(labelQuality, 1, 0);
|
||||
|
||||
_cylindrical.quality = new QComboBox;
|
||||
_cylindrical.quality->addItems(qualityList());
|
||||
@@ -596,13 +613,13 @@ QWidget* WindowControl::createCylindricalWidget() {
|
||||
_cylindrical.quality->setCurrentIndex(2);
|
||||
layout->addWidget(_cylindrical.quality, 1, 1);
|
||||
|
||||
_cylindrical.labelHeightOffset = new QLabel("Height Offset");
|
||||
QLabel* labelHeightOffset = new QLabel("Height Offset");
|
||||
const QString heightTip = "Offsets the height from which the cylindrical projection "
|
||||
"is generated.\nThis is, in general, only necessary if the user position is "
|
||||
"offset and\ncountering that offset is desired in order to continue producing\n"
|
||||
"a 'standard' cylindrical projection";
|
||||
_cylindrical.labelHeightOffset->setToolTip(heightTip);
|
||||
layout->addWidget(_cylindrical.labelHeightOffset, 2, 0);
|
||||
labelHeightOffset->setToolTip(heightTip);
|
||||
layout->addWidget(labelHeightOffset, 2, 0);
|
||||
|
||||
_cylindrical.heightOffset = new QDoubleSpinBox;
|
||||
_cylindrical.heightOffset->setMinimum(-1000000.0);
|
||||
@@ -611,7 +628,6 @@ QWidget* WindowControl::createCylindricalWidget() {
|
||||
_cylindrical.heightOffset->setToolTip(heightTip);
|
||||
layout->addWidget(_cylindrical.heightOffset, 2, 1);
|
||||
|
||||
|
||||
return widget;
|
||||
}
|
||||
|
||||
@@ -620,28 +636,27 @@ QWidget* WindowControl::createEquirectangularWidget() {
|
||||
// *------------*-----------*
|
||||
// | { Informational text } | Row 0
|
||||
// | Quality * [DDDDD>] | Row 1
|
||||
// | [] Spout Output | Row 2
|
||||
// *------------*-----------*
|
||||
QWidget* widget = new QWidget;
|
||||
QGridLayout* layout = new QGridLayout(widget);
|
||||
layout->setColumnStretch(1, 1);
|
||||
|
||||
_equirectangular.labelInfo = new QLabel(
|
||||
QLabel* labelInfo = new QLabel(
|
||||
"This projection provides the rendering as an image in equirectangular "
|
||||
"projection, which is a common display type for 360 surround video. When "
|
||||
"uploading a video in equirectangular projection to YouTube, for example, it "
|
||||
"will use it as a 360 video."
|
||||
);
|
||||
_equirectangular.labelInfo->setObjectName("info");
|
||||
_equirectangular.labelInfo->setWordWrap(true);
|
||||
layout->addWidget(_equirectangular.labelInfo, 0, 0, 1, 2);
|
||||
labelInfo->setObjectName("info");
|
||||
labelInfo->setWordWrap(true);
|
||||
layout->addWidget(labelInfo, 0, 0, 1, 2);
|
||||
|
||||
_equirectangular.labelQuality = new QLabel("Quality");
|
||||
QLabel* labelQuality = new QLabel("Quality");
|
||||
const QString qualityTip = "Determines the pixel resolution of the projection "
|
||||
"rendering. The higher resolution,\nthe better the rendering quality, but at the "
|
||||
"expense of increased rendering times";
|
||||
_equirectangular.labelQuality->setToolTip(qualityTip);
|
||||
layout->addWidget(_equirectangular.labelQuality, 1, 0);
|
||||
labelQuality->setToolTip(qualityTip);
|
||||
layout->addWidget(labelQuality, 1, 0);
|
||||
|
||||
_equirectangular.quality = new QComboBox;
|
||||
_equirectangular.quality->addItems(qualityList());
|
||||
@@ -652,6 +667,49 @@ QWidget* WindowControl::createEquirectangularWidget() {
|
||||
return widget;
|
||||
}
|
||||
|
||||
QWidget* WindowControl::createBlitWidget() {
|
||||
// Column 0 Column 1
|
||||
// *------------*-----------*
|
||||
// | { Informational text } | Row 0
|
||||
// | Window ID * [DDDDD>] | Row 1
|
||||
// | { Unavailability } | Row 2
|
||||
// *------------*-----------*
|
||||
|
||||
QWidget* widget = new QWidget;
|
||||
QGridLayout* layout = new QGridLayout(widget);
|
||||
layout->setColumnStretch(1, 1);
|
||||
|
||||
QLabel* labelInfo = new QLabel(
|
||||
"This projection type will reuse the contents of another window. This can be "
|
||||
"useful for GUI windows that should show the 3D scene, but not incur the cost of "
|
||||
"rendering the scene twice. Note that the contents of the rendering will be "
|
||||
"copied in their entirety, which means that if the rendering windows have "
|
||||
"different aspect ratios, the image in the receiving window will be stretched."
|
||||
);
|
||||
labelInfo->setObjectName("info");
|
||||
labelInfo->setWordWrap(true);
|
||||
layout->addWidget(labelInfo, 0, 0, 1, 2);
|
||||
|
||||
QLabel* labelBlitId = new QLabel("Window ID");
|
||||
const QString blitTip = "Determines the window from which to copy the contents.";
|
||||
labelBlitId->setToolTip(blitTip);
|
||||
layout->addWidget(labelBlitId, 1, 0);
|
||||
|
||||
_blit.windowId = new QComboBox;
|
||||
_blit.windowId->setToolTip(blitTip);
|
||||
layout->addWidget(_blit.windowId, 1, 1);
|
||||
|
||||
_blit.unavailable = new QLabel(
|
||||
"It is only possible to copy the contents of another window if at least two "
|
||||
"windows have been created. Add a second window before selecting this projection "
|
||||
"type."
|
||||
);
|
||||
_blit.unavailable->setWordWrap(true);
|
||||
layout->addWidget(_blit.unavailable, 2, 0, 1, 2);
|
||||
|
||||
return widget;
|
||||
}
|
||||
|
||||
void WindowControl::resetToDefaults() {
|
||||
//
|
||||
// Determine ideal window sizes
|
||||
@@ -684,9 +742,11 @@ void WindowControl::resetToDefaults() {
|
||||
_planar.fovV->setValue(DefaultFovShortEdge);
|
||||
_cylindrical.heightOffset->setValue(DefaultHeightOffset);
|
||||
_fisheye.quality->setCurrentIndex(2);
|
||||
_fisheye.tilt->setValue(0.0);
|
||||
_sphericalMirror.quality->setCurrentIndex(2);
|
||||
_cylindrical.quality->setCurrentIndex(2);
|
||||
_equirectangular.quality->setCurrentIndex(2);
|
||||
_blit.windowId->setCurrentIndex(0);
|
||||
emit windowChanged(_monitorIndexDefault, _windowIndex, _windowDimensions);
|
||||
}
|
||||
|
||||
@@ -736,6 +796,7 @@ void WindowControl::generateWindowInformation(sgct::config::Window& window) cons
|
||||
);
|
||||
window.draw2D = _render2D->isChecked();
|
||||
window.draw3D = _render3D->isChecked();
|
||||
|
||||
window.isDecorated = _windowDecoration->isChecked();
|
||||
if (_spoutOutput->isChecked()) {
|
||||
window.spout = sgct::config::Window::Spout{
|
||||
@@ -746,6 +807,8 @@ void WindowControl::generateWindowInformation(sgct::config::Window& window) cons
|
||||
window.name = _windowName->text().toStdString();
|
||||
}
|
||||
|
||||
window.viewports.clear();
|
||||
|
||||
// The rest of this function is just specifying the rendering, which we can skip if we
|
||||
// don't want to render 3D anyway
|
||||
if (!window.draw3D) {
|
||||
@@ -762,7 +825,7 @@ void WindowControl::generateWindowInformation(sgct::config::Window& window) cons
|
||||
vp.projection = sgct::config::FisheyeProjection {
|
||||
.fov = 180.f,
|
||||
.quality = Quality[_fisheye.quality->currentIndex()].first,
|
||||
.tilt = 0.f
|
||||
.tilt = static_cast<float>(_fisheye.tilt->value())
|
||||
};
|
||||
break;
|
||||
case ProjectionIndices::SphericalMirror:
|
||||
@@ -781,6 +844,16 @@ void WindowControl::generateWindowInformation(sgct::config::Window& window) cons
|
||||
.quality = Quality[_equirectangular.quality->currentIndex()].first
|
||||
};
|
||||
break;
|
||||
case ProjectionIndices::Blit:
|
||||
// We have to subtract here as SGCT uses 0-indexing, but we present it to the
|
||||
// user as 1-indexing
|
||||
window.blitWindowId = _blit.windowId->currentText().toInt() - 1;
|
||||
window.draw3D = false;
|
||||
|
||||
// We are falling through the planar value on purpose as for a variety of
|
||||
// reasons requires a projection to be defined even when we are blitting the
|
||||
// contents of another window.
|
||||
[[fallthrough]];
|
||||
case ProjectionIndices::Planar:
|
||||
{
|
||||
double fovH = _planar.fovH->value();
|
||||
@@ -799,8 +872,6 @@ void WindowControl::generateWindowInformation(sgct::config::Window& window) cons
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
window.viewports.clear();
|
||||
window.viewports.push_back(vp);
|
||||
}
|
||||
|
||||
@@ -810,8 +881,9 @@ void WindowControl::setProjectionPlanar(float hfov, float vfov) {
|
||||
_projectionType->setCurrentIndex(static_cast<int>(ProjectionIndices::Planar));
|
||||
}
|
||||
|
||||
void WindowControl::setProjectionFisheye(int quality) {
|
||||
void WindowControl::setProjectionFisheye(int quality, float tilt) {
|
||||
_fisheye.quality->setCurrentIndex(indexForQuality(quality));
|
||||
_fisheye.tilt->setValue(tilt);
|
||||
_projectionType->setCurrentIndex(static_cast<int>(ProjectionIndices::Fisheye));
|
||||
}
|
||||
|
||||
@@ -835,6 +907,32 @@ void WindowControl::setProjectionEquirectangular(int quality) {
|
||||
);
|
||||
}
|
||||
|
||||
void WindowControl::setProjectionBlit(int windowBlitId) {
|
||||
// We add 1 here as SGCT uses a 0-indexing for the window idx, but we present it to
|
||||
// the user as a 1-indexing
|
||||
int idx = _blit.windowId->findText(QString::number(windowBlitId + 1));
|
||||
ghoul_assert(idx != -1, "Could not find window blit id");
|
||||
_blit.windowId->setCurrentIndex(idx);
|
||||
_projectionType->setCurrentIndex(
|
||||
static_cast<int>(ProjectionIndices::Blit)
|
||||
);
|
||||
}
|
||||
|
||||
void WindowControl::updateWindowCount(int newWindowCount) {
|
||||
QString currentIdx = _blit.windowId->currentText();
|
||||
_blit.windowId->clear();
|
||||
for (int idx = 0; idx < newWindowCount; idx++) {
|
||||
if (idx == _windowIndex) {
|
||||
continue;
|
||||
}
|
||||
_blit.windowId->addItem(QString::number(idx + 1));
|
||||
}
|
||||
_blit.windowId->setCurrentText(currentIdx);
|
||||
|
||||
// Set the correct visibility
|
||||
_blit.unavailable->setVisible(newWindowCount == 1);
|
||||
}
|
||||
|
||||
void WindowControl::onSizeXChanged(int newValue) {
|
||||
_windowDimensions.setWidth(newValue);
|
||||
if (_aspectRatioLocked) {
|
||||
@@ -896,6 +994,7 @@ void WindowControl::onProjectionChanged(int newSelection) const {
|
||||
_sphericalMirror.widget->setVisible(selected == ProjectionIndices::SphericalMirror);
|
||||
_cylindrical.widget->setVisible(selected == ProjectionIndices::Cylindrical);
|
||||
_equirectangular.widget->setVisible(selected == ProjectionIndices::Equirectangular);
|
||||
_blit.widget->setVisible(selected == ProjectionIndices::Blit);
|
||||
}
|
||||
|
||||
void WindowControl::onAspectRatioLockClicked() {
|
||||
|
||||
Submodule apps/OpenSpace/ext/sgct updated: 1418d9beb2...7ac1bd4891
@@ -1415,9 +1415,39 @@ int main(int argc, char* argv[]) {
|
||||
openspace::Settings settings = loadSettings();
|
||||
settings.hasStartedBefore = true;
|
||||
|
||||
const std::filesystem::path p = global::configuration->profile;
|
||||
const std::filesystem::path reducedName = p.filename().replace_extension();
|
||||
settings.profile = reducedName.string();
|
||||
const std::filesystem::path profile = global::configuration->profile;
|
||||
|
||||
const bool isDefaultProfile = ghoul::filesystem::isSubdirectory(
|
||||
profile,
|
||||
absPath("${PROFILES}")
|
||||
);
|
||||
const bool isUserProfile = ghoul::filesystem::isSubdirectory(
|
||||
profile,
|
||||
absPath("${USER_PROFILES}")
|
||||
);
|
||||
|
||||
if (isDefaultProfile) {
|
||||
std::filesystem::path p = std::filesystem::relative(
|
||||
profile,
|
||||
absPath("${PROFILES}")
|
||||
);
|
||||
p.replace_extension();
|
||||
settings.profile = p.string();
|
||||
}
|
||||
else if (isUserProfile) {
|
||||
std::filesystem::path p = std::filesystem::relative(
|
||||
profile,
|
||||
absPath("${USER_PROFILES}")
|
||||
);
|
||||
p.replace_extension();
|
||||
settings.profile = p.string();
|
||||
}
|
||||
else {
|
||||
LWARNING(
|
||||
"Cannot save remembered profile when starting a profile that is not in "
|
||||
"the data/profiles or user/data/profiles folder."
|
||||
);
|
||||
}
|
||||
|
||||
settings.configuration =
|
||||
isGeneratedWindowConfig ? "" : global::configuration->windowConfiguration;
|
||||
|
||||
@@ -0,0 +1,22 @@
|
||||
-- Basic
|
||||
-- Creates a screenspace image that shows a spherical grid as an example for any
|
||||
-- [Renderable](#renderable) that can be displayed.
|
||||
|
||||
local Object = {
|
||||
Type = "ScreenSpaceRenderableRenderable",
|
||||
Identifier = "ScreenSpaceRenderableRenderable_Example",
|
||||
Renderable = {
|
||||
Type = "RenderableSphericalGrid",
|
||||
Opacity = 1.0,
|
||||
Color = { 0.3, 0.84, 1.0 },
|
||||
LineWidth = 2.0
|
||||
}
|
||||
}
|
||||
|
||||
asset.onInitialize(function()
|
||||
openspace.addScreenSpaceRenderable(Object)
|
||||
end)
|
||||
|
||||
asset.onDeinitialize(function()
|
||||
openspace.removeScreenSpaceRenderable(Object)
|
||||
end)
|
||||
@@ -0,0 +1,24 @@
|
||||
-- Axes
|
||||
-- Creates a screenspace image that renders three Cartesian axes into the screen space
|
||||
-- window. This example also modifies the original camera position to give an oblique view
|
||||
-- onto the axes and increases the field of view of the camera to a wider degree. We also
|
||||
-- set the background color to be fully opaque to make it easier to see the axes.
|
||||
|
||||
local Object = {
|
||||
Type = "ScreenSpaceRenderableRenderable",
|
||||
Identifier = "ScreenSpaceRenderableRenderable_Example_Axes",
|
||||
Renderable = {
|
||||
Type = "RenderableCartesianAxes"
|
||||
},
|
||||
BackgroundColor = { 0.0, 0.0, 0.0, 1.0 },
|
||||
CameraPosition = { 1.0, 1.0, 1.0 },
|
||||
CameraFov = 80.0
|
||||
}
|
||||
|
||||
asset.onInitialize(function()
|
||||
openspace.addScreenSpaceRenderable(Object)
|
||||
end)
|
||||
|
||||
asset.onDeinitialize(function()
|
||||
openspace.removeScreenSpaceRenderable(Object)
|
||||
end)
|
||||
@@ -0,0 +1,41 @@
|
||||
-- Model Distance
|
||||
-- Creates a screen space window into which 3D model of the Eiffel tower is rendered. As
|
||||
-- the objects are rendered in meter scale, and the Eiffel tower is about 300m tall, we
|
||||
-- place the camera at a great distance to be able to see the entire Eiffel tower at the
|
||||
-- same time.
|
||||
|
||||
-- Download the model file for the Eiffel tower
|
||||
local modelFolder = asset.resource({
|
||||
Name = "Scale Eiffel Tower",
|
||||
Type = "HttpSynchronization",
|
||||
Identifier = "scale_model_eiffel_tower",
|
||||
Version = 1
|
||||
})
|
||||
|
||||
local Object = {
|
||||
Type = "ScreenSpaceRenderableRenderable",
|
||||
Identifier = "ScreenSpaceRenderableRenderable_Example_ModelDistance",
|
||||
Renderable = {
|
||||
Type = "RenderableModel",
|
||||
GeometryFile = modelFolder .. "eiffeltower.osmodel",
|
||||
RotationVector = { 0.0, 45.0, 0.0 },
|
||||
LightSources = {
|
||||
{
|
||||
Identifier = "Camera",
|
||||
Type = "CameraLightSource",
|
||||
Intensity = 5.0
|
||||
}
|
||||
}
|
||||
},
|
||||
Scale = 1.25,
|
||||
CameraPosition = { 0.0, 3500.0, 9000.0 },
|
||||
CameraCenter = { 0.0, 2750.0, 0.0 }
|
||||
}
|
||||
|
||||
asset.onInitialize(function()
|
||||
openspace.addScreenSpaceRenderable(Object)
|
||||
end)
|
||||
|
||||
asset.onDeinitialize(function()
|
||||
openspace.removeScreenSpaceRenderable(Object)
|
||||
end)
|
||||
@@ -0,0 +1,47 @@
|
||||
-- Model
|
||||
-- Creates a screen space window into which 3D model of the Eiffel tower is rendered. As
|
||||
-- the objects are rendered in meter scale, and the Eiffel tower is about 300m tall, we
|
||||
-- both shrink the rendering to make the entire model fit into the view and also modify
|
||||
-- the position of the camera.
|
||||
|
||||
-- Download the model file for the Eiffel tower
|
||||
local modelFolder = asset.resource({
|
||||
Name = "Scale Eiffel Tower",
|
||||
Type = "HttpSynchronization",
|
||||
Identifier = "scale_model_eiffel_tower",
|
||||
Version = 1
|
||||
})
|
||||
|
||||
local Object = {
|
||||
Type = "ScreenSpaceRenderableRenderable",
|
||||
Identifier = "ScreenSpaceRenderableRenderable_Example_Model",
|
||||
Transform = {
|
||||
Scale = {
|
||||
Type = "StaticScale",
|
||||
Scale = 0.0002
|
||||
}
|
||||
},
|
||||
Renderable = {
|
||||
Type = "RenderableModel",
|
||||
GeometryFile = modelFolder .. "eiffeltower.osmodel",
|
||||
RotationVector = { 0.0, 45.0, 0.0 },
|
||||
LightSources = {
|
||||
{
|
||||
Identifier = "Camera",
|
||||
Type = "CameraLightSource",
|
||||
Intensity = 5.0
|
||||
}
|
||||
}
|
||||
},
|
||||
Scale = 1.25,
|
||||
CameraPosition = { 0.0, 1.0, 2.0 },
|
||||
CameraCenter = { 0.0, 0.5, 0.0 }
|
||||
}
|
||||
|
||||
asset.onInitialize(function()
|
||||
openspace.addScreenSpaceRenderable(Object)
|
||||
end)
|
||||
|
||||
asset.onDeinitialize(function()
|
||||
openspace.removeScreenSpaceRenderable(Object)
|
||||
end)
|
||||
@@ -42,8 +42,7 @@ local LightPollutionSphere = {
|
||||
Orientation = "Inside",
|
||||
MirrorTexture = true,
|
||||
FadeOutThreshold = 1.00,
|
||||
RenderBinMode = "PostDeferredTransparent",
|
||||
Enabled = asset.enabled
|
||||
RenderBinMode = "PostDeferredTransparent"
|
||||
},
|
||||
GUI = {
|
||||
Name = "Light Pollution Sphere",
|
||||
|
||||
@@ -23,7 +23,9 @@ local Object = {
|
||||
Texture = textures .. "mwHalpha-f.png",
|
||||
Orientation = "Inside",
|
||||
MirrorTexture = true,
|
||||
FadeOutThreshold = 0.025
|
||||
FadeOutThreshold = 0.025,
|
||||
BlendingOption = "Additive",
|
||||
DisableDepth = true
|
||||
},
|
||||
GUI = {
|
||||
Name = "Hydrogen Alpha",
|
||||
|
||||
@@ -30,7 +30,9 @@ local COBE = {
|
||||
Texture = textures .. "COBErect.png",
|
||||
Orientation = "Both",
|
||||
MirrorTexture = true,
|
||||
FadeInThreshold = 0.4
|
||||
FadeInThreshold = 0.4,
|
||||
BlendingOption = "Additive",
|
||||
DisableDepth = true
|
||||
},
|
||||
GUI = {
|
||||
Name = "1990 COBE CMB",
|
||||
@@ -62,7 +64,9 @@ local WMAP = {
|
||||
Texture = textures .. "wmap_ilc_7yr_v4_200uK_RGB_sos.png",
|
||||
Orientation = "Both",
|
||||
MirrorTexture = true,
|
||||
FadeInThreshold = 0.4
|
||||
FadeInThreshold = 0.4,
|
||||
BlendingOption = "Additive",
|
||||
DisableDepth = true
|
||||
},
|
||||
GUI = {
|
||||
Name = "2003 WMAP CMB",
|
||||
@@ -93,7 +97,9 @@ local Planck = {
|
||||
Texture = textures .. "cmb4k.jpg",
|
||||
Orientation = "Both",
|
||||
MirrorTexture = true,
|
||||
FadeInThreshold = 0.4
|
||||
FadeInThreshold = 0.4,
|
||||
BlendingOption = "Additive",
|
||||
DisableDepth = true
|
||||
},
|
||||
GUI = {
|
||||
Name = "2013 Planck CMB",
|
||||
|
||||
@@ -27,7 +27,9 @@ local PlanckMultiverse1 = {
|
||||
Texture = textures .. "cmb4k.jpg",
|
||||
Orientation = "Both",
|
||||
MirrorTexture = true,
|
||||
FadeInThreshold = 0.4
|
||||
FadeInThreshold = 0.4,
|
||||
BlendingOption = "Additive",
|
||||
DisableDepth = true
|
||||
},
|
||||
GUI = {
|
||||
Name = "Planck Multiverse 1",
|
||||
@@ -56,7 +58,9 @@ local PlanckMultiverse2 = {
|
||||
Texture = textures .. "cmb4k.jpg",
|
||||
Orientation = "Both",
|
||||
MirrorTexture = true,
|
||||
FadeInThreshold = 0.4
|
||||
FadeInThreshold = 0.4,
|
||||
BlendingOption = "Additive",
|
||||
DisableDepth = true
|
||||
},
|
||||
GUI = {
|
||||
Name = "Planck Multiverse 2",
|
||||
@@ -85,7 +89,9 @@ local PlanckMultiverse3 = {
|
||||
Texture = textures .. "cmb4k.jpg",
|
||||
Orientation = "Both",
|
||||
MirrorTexture = true,
|
||||
FadeInThreshold = 0.4
|
||||
FadeInThreshold = 0.4,
|
||||
BlendingOption = "Additive",
|
||||
DisableDepth = true
|
||||
},
|
||||
GUI = {
|
||||
Name = "Planck Multiverse 3",
|
||||
@@ -114,7 +120,9 @@ local PlanckMultiverse4 = {
|
||||
Texture = textures .. "cmb4k.jpg",
|
||||
Orientation = "Both",
|
||||
MirrorTexture = true,
|
||||
FadeInThreshold = 0.4
|
||||
FadeInThreshold = 0.4,
|
||||
BlendingOption = "Additive",
|
||||
DisableDepth = true
|
||||
},
|
||||
GUI = {
|
||||
Name = "Planck Multiverse 4",
|
||||
|
||||
@@ -22,7 +22,9 @@ local Object = {
|
||||
Texture = textures .. "eso0932a_blend.png",
|
||||
Orientation = "Inside",
|
||||
MirrorTexture = true,
|
||||
FadeOutThreshold = 0.01
|
||||
FadeOutThreshold = 0.01,
|
||||
BlendingOption = "Additive",
|
||||
DisableDepth = true
|
||||
},
|
||||
GUI = {
|
||||
Name = "Milky Way (ESO)",
|
||||
|
||||
@@ -0,0 +1,36 @@
|
||||
local globe = asset.require("../../titan")
|
||||
|
||||
|
||||
|
||||
local Layer = {
|
||||
Identifier = "Cassini_SAR_HiSAR_Global_Mosaic_351m",
|
||||
Name = "Cassini SAR - HiSAR Global Mosaic (351m)",
|
||||
Enabled = asset.enabled,
|
||||
ZIndex = 20,
|
||||
FilePath = asset.resource("cassini_sar_hisar_global_mosaic_351m_sweden.wms"),
|
||||
Description = [[This global map of Titan is a preliminary product showing coverage from
|
||||
Synthetic Aperture Radar (SAR) and High Altitude Synthetic Aperture Radar (HiSAR)
|
||||
images at a pixel resolution of 351 meters per pixel (m). This mosaic merges Cassini
|
||||
swaths through flyby T104 into a single mosaic. (Description from URL)]]
|
||||
}
|
||||
|
||||
|
||||
asset.onInitialize(function()
|
||||
openspace.globebrowsing.addLayer(globe.Titan.Identifier, "ColorLayers", Layer)
|
||||
end)
|
||||
|
||||
asset.onDeinitialize(function()
|
||||
openspace.globebrowsing.deleteLayer(globe.Titan.Identifier, "ColorLayers", Layer)
|
||||
end)
|
||||
|
||||
asset.export("layer", Layer)
|
||||
|
||||
|
||||
|
||||
asset.meta = {
|
||||
Name = "Titan Cassini SAR - HiSAR Global Mosaic 351m",
|
||||
Description = "Cassini global synthetic aperture radar image layer for Titan",
|
||||
Author = "USGS",
|
||||
URL = "https://astrogeology.usgs.gov/search/map/titan_cassini_sar_hisar_global_mosaic_351m",
|
||||
License = "NASA/PDS"
|
||||
}
|
||||
@@ -0,0 +1,20 @@
|
||||
<GDAL_WMS>
|
||||
<Service name="TMS">
|
||||
<ServerUrl>http://wms.itn.liu.se/Titan/HiSAR_Global_Mosaic_351m/tile/${z}/${y}/${x}</ServerUrl>
|
||||
</Service>
|
||||
<DataWindow>
|
||||
<UpperLeftX>-180.0</UpperLeftX>
|
||||
<UpperLeftY>90.0</UpperLeftY>
|
||||
<LowerRightX>180.0</LowerRightX>
|
||||
<LowerRightY>-90.0</LowerRightY>
|
||||
<SizeX>46080</SizeX>
|
||||
<SizeY>23040</SizeY>
|
||||
<TileLevel>7</TileLevel>
|
||||
<YOrigin>top</YOrigin>
|
||||
</DataWindow>
|
||||
<Projection>EPSG:4326</Projection>
|
||||
<BlockSizeX>512</BlockSizeX>
|
||||
<BlockSizeY>512</BlockSizeY>
|
||||
<BandsCount>1</BandsCount>
|
||||
<MaxConnections>10</MaxConnections>
|
||||
</GDAL_WMS>
|
||||
221
data/assets/util/calibration.asset
Normal file
221
data/assets/util/calibration.asset
Normal file
@@ -0,0 +1,221 @@
|
||||
local textures = asset.resource({
|
||||
Name = "Calibration Images",
|
||||
Type = "HttpSynchronization",
|
||||
Identifier = "calibration_images",
|
||||
Version = 1
|
||||
})
|
||||
|
||||
local Distance = 1000
|
||||
local Size = 1000
|
||||
|
||||
|
||||
local Center = {
|
||||
Identifier = "Calibration",
|
||||
GUI = {
|
||||
Name = "Calibration",
|
||||
Description = "The centerpoint of the calibration cube",
|
||||
Path = "/Calibration"
|
||||
}
|
||||
}
|
||||
|
||||
local Front = {
|
||||
Identifier = "Calibration_Front",
|
||||
Parent = Center.Identifier,
|
||||
Transform = {
|
||||
Translation = {
|
||||
Type = "StaticTranslation",
|
||||
Position = { 0, Distance, 0 }
|
||||
},
|
||||
Rotation = {
|
||||
Type = "StaticRotation",
|
||||
Rotation = { math.pi / 2.0, 0.0, 0.0 }
|
||||
}
|
||||
},
|
||||
Renderable = {
|
||||
Type = "RenderablePlaneImageLocal",
|
||||
Enabled = asset.enabled,
|
||||
Size = Size,
|
||||
Origin = "Center",
|
||||
Texture = textures .. "test-pattern-0.png"
|
||||
},
|
||||
GUI = {
|
||||
Name = "Calibration (Front)",
|
||||
Description = "The front face of the calibration cube",
|
||||
Path = "/Calibration"
|
||||
}
|
||||
}
|
||||
|
||||
local Right = {
|
||||
Identifier = "Calibration_Right",
|
||||
Parent = Center.Identifier,
|
||||
Transform = {
|
||||
Translation = {
|
||||
Type = "StaticTranslation",
|
||||
Position = { Distance, 0, 0 }
|
||||
},
|
||||
Rotation = {
|
||||
Type = "StaticRotation",
|
||||
Rotation = { math.pi / 2.0, 0.0, -math.pi / 2.0 }
|
||||
}
|
||||
},
|
||||
Renderable = {
|
||||
Type = "RenderablePlaneImageLocal",
|
||||
Enabled = asset.enabled,
|
||||
Size = Size,
|
||||
Origin = "Center",
|
||||
Texture = textures .. "test-pattern-1.png"
|
||||
},
|
||||
GUI = {
|
||||
Name = "Calibration (Right)",
|
||||
Description = "The right face of the calibration cube",
|
||||
Path = "/Calibration"
|
||||
}
|
||||
}
|
||||
|
||||
local Back = {
|
||||
Identifier = "Calibration_Back",
|
||||
Parent = Center.Identifier,
|
||||
Transform = {
|
||||
Translation = {
|
||||
Type = "StaticTranslation",
|
||||
Position = { 0, -Distance, 0 }
|
||||
},
|
||||
Rotation = {
|
||||
Type = "StaticRotation",
|
||||
Rotation = { -math.pi / 2.0, math.pi, 0.0 }
|
||||
}
|
||||
},
|
||||
Renderable = {
|
||||
Type = "RenderablePlaneImageLocal",
|
||||
Enabled = asset.enabled,
|
||||
Size = Size,
|
||||
Origin = "Center",
|
||||
Texture = textures .. "test-pattern-2.png"
|
||||
},
|
||||
GUI = {
|
||||
Name = "Calibration (Back)",
|
||||
Description = "The back face of the calibration cube",
|
||||
Path = "/Calibration"
|
||||
}
|
||||
}
|
||||
|
||||
local Left = {
|
||||
Identifier = "Calibration_Left",
|
||||
Parent = Center.Identifier,
|
||||
Transform = {
|
||||
Translation = {
|
||||
Type = "StaticTranslation",
|
||||
Position = { -Distance, 0, 0 }
|
||||
},
|
||||
Rotation = {
|
||||
Type = "StaticRotation",
|
||||
Rotation = { math.pi / 2.0, 0.0, math.pi / 2.0 }
|
||||
}
|
||||
},
|
||||
Renderable = {
|
||||
Type = "RenderablePlaneImageLocal",
|
||||
Enabled = asset.enabled,
|
||||
Size = Size,
|
||||
Origin = "Center",
|
||||
Texture = textures .. "test-pattern-3.png"
|
||||
},
|
||||
GUI = {
|
||||
Name = "Calibration (Left)",
|
||||
Description = "The left face of the calibration cube",
|
||||
Path = "/Calibration"
|
||||
}
|
||||
}
|
||||
|
||||
local Top = {
|
||||
Identifier = "Calibration_Top",
|
||||
Parent = Center.Identifier,
|
||||
Transform = {
|
||||
Translation = {
|
||||
Type = "StaticTranslation",
|
||||
Position = { 0, 0, Distance }
|
||||
},
|
||||
Rotation = {
|
||||
Type = "StaticRotation",
|
||||
Rotation = { 0.0, math.pi, -math.pi }
|
||||
}
|
||||
},
|
||||
Renderable = {
|
||||
Type = "RenderablePlaneImageLocal",
|
||||
Enabled = asset.enabled,
|
||||
Size = Size,
|
||||
Origin = "Center",
|
||||
Texture = textures .. "test-pattern-4.png"
|
||||
},
|
||||
GUI = {
|
||||
Name = "Calibration (Top)",
|
||||
Description = "The top face of the calibration cube",
|
||||
Path = "/Calibration"
|
||||
}
|
||||
}
|
||||
|
||||
local Bottom = {
|
||||
Identifier = "Calibration_Bottom",
|
||||
Parent = Center.Identifier,
|
||||
Transform = {
|
||||
Translation = {
|
||||
Type = "StaticTranslation",
|
||||
Position = { 0, 0, -Distance }
|
||||
},
|
||||
Rotation = {
|
||||
Type = "StaticRotation",
|
||||
Rotation = { 0.0, 0.0, 0.0 }
|
||||
}
|
||||
},
|
||||
Renderable = {
|
||||
Type = "RenderablePlaneImageLocal",
|
||||
Enabled = asset.enabled,
|
||||
Size = Size,
|
||||
Origin = "Center",
|
||||
Texture = textures .. "test-pattern-5.png"
|
||||
},
|
||||
GUI = {
|
||||
Name = "Calibration (Bottom)",
|
||||
Description = "The bottom face of the calibration cube",
|
||||
Path = "/Calibration"
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
asset.onInitialize(function()
|
||||
openspace.addSceneGraphNode(Center)
|
||||
openspace.addSceneGraphNode(Left)
|
||||
openspace.addSceneGraphNode(Right)
|
||||
openspace.addSceneGraphNode(Front)
|
||||
openspace.addSceneGraphNode(Back)
|
||||
openspace.addSceneGraphNode(Top)
|
||||
openspace.addSceneGraphNode(Bottom)
|
||||
end)
|
||||
|
||||
asset.onDeinitialize(function()
|
||||
openspace.removeSceneGraphNode(Bottom)
|
||||
openspace.removeSceneGraphNode(Top)
|
||||
openspace.removeSceneGraphNode(Back)
|
||||
openspace.removeSceneGraphNode(Front)
|
||||
openspace.removeSceneGraphNode(Right)
|
||||
openspace.removeSceneGraphNode(Left)
|
||||
openspace.removeSceneGraphNode(Center)
|
||||
end)
|
||||
|
||||
asset.export(Center)
|
||||
asset.export(Left)
|
||||
asset.export(Right)
|
||||
asset.export(Front)
|
||||
asset.export(Back)
|
||||
asset.export(Top)
|
||||
asset.export(Bottom)
|
||||
|
||||
|
||||
|
||||
asset.meta = {
|
||||
Name = "Calibrator",
|
||||
Description = [[A cube that can be used to verify calibration in a complicated display
|
||||
environment]],
|
||||
Author = "OpenSpace Team",
|
||||
URL = "http://openspaceproject.com",
|
||||
License = "MIT license"
|
||||
}
|
||||
36
data/profiles/calibrator.profile
Normal file
36
data/profiles/calibrator.profile
Normal file
@@ -0,0 +1,36 @@
|
||||
{
|
||||
"assets": [
|
||||
"base_blank",
|
||||
"util/calibration"
|
||||
],
|
||||
"camera": {
|
||||
"aim": "Calibration_Front",
|
||||
"anchor": "Calibration",
|
||||
"frame": "Calibration",
|
||||
"position": {
|
||||
"x": 0.5,
|
||||
"y": 0.5,
|
||||
"z": 0.5
|
||||
},
|
||||
"type": "setNavigationState"
|
||||
},
|
||||
"meta": {
|
||||
"author": "OpenSpace Team",
|
||||
"description": "This profile places the camera in the inside of a calibration cube. This profile can be used to verify that a display environment is set up correctly. If a setup is correct, the different windows/viewports should show the correct parts of the surrounding cube accurately and withou any unwanted distortion.",
|
||||
"license": "MIT license",
|
||||
"name": "Calibration",
|
||||
"url": "https://openspaceproject.com",
|
||||
"version": "1.0"
|
||||
},
|
||||
"properties": [
|
||||
{
|
||||
"name": "NavigationHandler.OrbitalNavigator.LimitZoom.EnabledMinimumAllowedDistance",
|
||||
"type": "setPropertyValueSingle",
|
||||
"value": "false"
|
||||
}
|
||||
],
|
||||
"version": {
|
||||
"major": 1,
|
||||
"minor": 4
|
||||
}
|
||||
}
|
||||
17
data/web/default_ui_panels.json
Normal file
17
data/web/default_ui_panels.json
Normal file
@@ -0,0 +1,17 @@
|
||||
{
|
||||
"0": { "id": "scene", "name": "Scene", "visible": true, "enabled": true },
|
||||
"1": { "id": "settings", "name": "Settings", "visible": false, "enabled": true },
|
||||
"2": { "id": "navigation", "name": "Navigation", "visible": true, "enabled": true },
|
||||
"3": { "id": "timePanel", "name": "Date & Time", "visible": true, "enabled": true },
|
||||
"4": { "id": "sessionRecording", "name": "Session Recording", "visible": true, "enabled": true },
|
||||
"5": { "id": "geoLocation", "name": "Geo Location", "visible": true, "enabled": true },
|
||||
"6": { "id": "screenSpaceRenderables", "name": "ScreenSpace Renderables", "visible": true, "enabled": true },
|
||||
"7": { "id": "exoplanets", "name": "Exoplanets", "visible": true, "enabled": true },
|
||||
"8": { "id": "userPanels", "name": "User Panels", "visible": true, "enabled": true },
|
||||
"9": { "id": "actions", "name": "Actions", "visible": true, "enabled": true },
|
||||
"10": { "id": "skyBrowser", "name": "SkyBrowser", "visible": true, "enabled": true },
|
||||
"11": { "id": "mission", "name": "Mission", "visible": false, "enabled": false },
|
||||
"12": { "id": "flightControl", "name": "Flight Control", "visible": false, "enabled": true },
|
||||
"13": { "id": "keybindingsLayout", "name": "Keybindings", "visible": true, "enabled": true },
|
||||
"14": { "id": "gettingStartedTour", "name": "Getting Started Tour", "visible": true, "enabled": true }
|
||||
}
|
||||
2
ext/date
2
ext/date
Submodule ext/date updated: 569b2d6785...5bdb7e6f31
Submodule ext/ghoul updated: 1ee8a47a1c...8d73afb420
@@ -48,11 +48,6 @@ public:
|
||||
std::string description;
|
||||
};
|
||||
|
||||
enum class DisplayType {
|
||||
Radio,
|
||||
Dropdown
|
||||
};
|
||||
|
||||
/**
|
||||
* The constructor delegating the `identifier` and the `guiName` to its super class.
|
||||
*
|
||||
@@ -64,18 +59,6 @@ public:
|
||||
*/
|
||||
OptionProperty(Property::PropertyInfo info);
|
||||
|
||||
/**
|
||||
* The constructor delegating the `identifier` and the `guiName` to its super class.
|
||||
*
|
||||
* \param info The PropertyInfo structure that contains all the required static
|
||||
* information for initializing this Property
|
||||
* \param displayType Optional DisplayType for GUI (default RADIO)
|
||||
*
|
||||
* \pre \p info.identifier must not be empty
|
||||
* \pre \p info.guiName must not be empty
|
||||
*/
|
||||
OptionProperty(PropertyInfo info, DisplayType displayType);
|
||||
|
||||
/**
|
||||
* Returns the name of the class for reflection purposes.
|
||||
*
|
||||
@@ -86,21 +69,14 @@ public:
|
||||
|
||||
using TemplateProperty<int>::operator=;
|
||||
|
||||
/**
|
||||
* Returns the type for GUI display.
|
||||
*
|
||||
* \return OptionType for display purposes
|
||||
*/
|
||||
DisplayType displayType() const;
|
||||
|
||||
/**
|
||||
* Adds the passed option to the list of available options. The `value` of the
|
||||
* `option` must not have been registered previously, or a warning will be logged.
|
||||
*
|
||||
* \param value The option that will be added to the list of available options
|
||||
* \param desc The description of the value that will be added
|
||||
* \param description The description of the value that will be added
|
||||
*/
|
||||
void addOption(int value, std::string desc);
|
||||
void addOption(int value, std::string description);
|
||||
|
||||
/**
|
||||
* Adds multiple options to the OptionProperty. Each value in the vector consists of
|
||||
@@ -171,7 +147,6 @@ private:
|
||||
|
||||
/// The list of options which have been registered with this OptionProperty
|
||||
std::vector<Option> _options;
|
||||
DisplayType _displayType;
|
||||
};
|
||||
|
||||
} // namespace openspace::properties
|
||||
|
||||
@@ -178,7 +178,7 @@ public:
|
||||
/// Removes an asset unless the `ignoreUpdates` member is set to `true`
|
||||
void removeAsset(const std::string& path);
|
||||
|
||||
static constexpr Version CurrentVersion = Version{ 1, 3 };
|
||||
static constexpr Version CurrentVersion = Version{ 1, 4 };
|
||||
|
||||
Version version = CurrentVersion;
|
||||
std::vector<Module> modules;
|
||||
@@ -192,6 +192,7 @@ public:
|
||||
std::optional<CameraType> camera;
|
||||
std::vector<std::string> markNodes;
|
||||
std::vector<std::string> additionalScripts;
|
||||
std::map<std::string, bool> uiPanelVisibility;
|
||||
|
||||
bool ignoreUpdates = false;
|
||||
|
||||
|
||||
Submodule modules/audio/ext/soloud updated: 1157475881...e82fd32c1f
@@ -72,6 +72,7 @@ set(HEADER_FILES
|
||||
rendering/screenspaceframebuffer.h
|
||||
rendering/screenspaceimagelocal.h
|
||||
rendering/screenspaceimageonline.h
|
||||
rendering/screenspacerenderablerenderable.h
|
||||
rotation/timelinerotation.h
|
||||
rotation/constantrotation.h
|
||||
rotation/fixedrotation.h
|
||||
@@ -142,6 +143,7 @@ set(SOURCE_FILES
|
||||
rendering/screenspaceframebuffer.cpp
|
||||
rendering/screenspaceimagelocal.cpp
|
||||
rendering/screenspaceimageonline.cpp
|
||||
rendering/screenspacerenderablerenderable.cpp
|
||||
rotation/timelinerotation.cpp
|
||||
rotation/constantrotation.cpp
|
||||
rotation/fixedrotation.cpp
|
||||
|
||||
@@ -68,6 +68,7 @@
|
||||
#include <modules/base/rendering/screenspaceimagelocal.h>
|
||||
#include <modules/base/rendering/screenspaceimageonline.h>
|
||||
#include <modules/base/rendering/screenspaceframebuffer.h>
|
||||
#include <modules/base/rendering/screenspacerenderablerenderable.h>
|
||||
#include <modules/base/rotation/constantrotation.h>
|
||||
#include <modules/base/rotation/fixedrotation.h>
|
||||
#include <modules/base/rotation/luarotation.h>
|
||||
@@ -110,6 +111,9 @@ void BaseModule::internalInitialize(const ghoul::Dictionary&) {
|
||||
fSsRenderable->registerClass<ScreenSpaceImageLocal>("ScreenSpaceImageLocal");
|
||||
fSsRenderable->registerClass<ScreenSpaceImageOnline>("ScreenSpaceImageOnline");
|
||||
fSsRenderable->registerClass<ScreenSpaceFramebuffer>("ScreenSpaceFramebuffer");
|
||||
fSsRenderable->registerClass<ScreenSpaceRenderableRenderable>(
|
||||
"ScreenSpaceRenderableRenderable"
|
||||
);
|
||||
|
||||
|
||||
ghoul::TemplateFactory<DashboardItem>* fDashboard =
|
||||
@@ -281,6 +285,7 @@ std::vector<documentation::Documentation> BaseModule::documentations() const {
|
||||
ScreenSpaceFramebuffer::Documentation(),
|
||||
ScreenSpaceImageLocal::Documentation(),
|
||||
ScreenSpaceImageOnline::Documentation(),
|
||||
ScreenSpaceRenderableRenderable::Documentation(),
|
||||
|
||||
ConstantRotation::Documentation(),
|
||||
FixedRotation::Documentation(),
|
||||
|
||||
@@ -143,26 +143,17 @@ documentation::Documentation DashboardItemAngle::Documentation() {
|
||||
DashboardItemAngle::DashboardItemAngle(const ghoul::Dictionary& dictionary)
|
||||
: DashboardTextItem(dictionary)
|
||||
, _source{
|
||||
properties::OptionProperty(
|
||||
SourceTypeInfo,
|
||||
properties::OptionProperty::DisplayType::Dropdown
|
||||
),
|
||||
properties::OptionProperty(SourceTypeInfo),
|
||||
properties::StringProperty(SourceNodeIdentifierInfo),
|
||||
nullptr
|
||||
}
|
||||
, _reference{
|
||||
properties::OptionProperty(
|
||||
ReferenceTypeInfo,
|
||||
properties::OptionProperty::DisplayType::Dropdown
|
||||
),
|
||||
properties::OptionProperty(ReferenceTypeInfo),
|
||||
properties::StringProperty(ReferenceNodeIdentifierInfo),
|
||||
nullptr
|
||||
}
|
||||
, _destination{
|
||||
properties::OptionProperty(
|
||||
DestinationTypeInfo,
|
||||
properties::OptionProperty::DisplayType::Dropdown
|
||||
),
|
||||
properties::OptionProperty(DestinationTypeInfo),
|
||||
properties::StringProperty(DestinationNodeIdentifierInfo),
|
||||
nullptr
|
||||
}
|
||||
|
||||
@@ -159,21 +159,15 @@ documentation::Documentation DashboardItemDistance::Documentation() {
|
||||
DashboardItemDistance::DashboardItemDistance(const ghoul::Dictionary& dictionary)
|
||||
: DashboardTextItem(dictionary)
|
||||
, _doSimplification(SimplificationInfo, true)
|
||||
, _requestedUnit(RequestedUnitInfo, properties::OptionProperty::DisplayType::Dropdown)
|
||||
, _requestedUnit(RequestedUnitInfo)
|
||||
, _formatString(FormatStringInfo, "Distance from {} to {}: {:f} {}")
|
||||
, _source{
|
||||
properties::OptionProperty(
|
||||
SourceTypeInfo,
|
||||
properties::OptionProperty::DisplayType::Dropdown
|
||||
),
|
||||
properties::OptionProperty(SourceTypeInfo),
|
||||
properties::StringProperty(SourceNodeIdentifierInfo),
|
||||
nullptr
|
||||
}
|
||||
, _destination{
|
||||
properties::OptionProperty(
|
||||
DestinationTypeInfo,
|
||||
properties::OptionProperty::DisplayType::Dropdown
|
||||
),
|
||||
properties::OptionProperty(DestinationTypeInfo),
|
||||
properties::StringProperty(DestinationNodeIdentifierInfo),
|
||||
nullptr
|
||||
}
|
||||
|
||||
@@ -197,7 +197,7 @@ documentation::Documentation DashboardItemFramerate::Documentation() {
|
||||
|
||||
DashboardItemFramerate::DashboardItemFramerate(const ghoul::Dictionary& dictionary)
|
||||
: DashboardTextItem(dictionary)
|
||||
, _frametimeType(FrametimeInfo, properties::OptionProperty::DisplayType::Dropdown)
|
||||
, _frametimeType(FrametimeInfo)
|
||||
, _clearCache(ClearCacheInfo)
|
||||
{
|
||||
const Parameters p = codegen::bake<Parameters>(dictionary);
|
||||
|
||||
@@ -125,7 +125,7 @@ DashboardItemSimulationIncrement::DashboardItemSimulationIncrement(
|
||||
const ghoul::Dictionary& dictionary)
|
||||
: DashboardTextItem(dictionary)
|
||||
, _doSimplification(SimplificationInfo, true)
|
||||
, _requestedUnit(RequestedUnitInfo, properties::OptionProperty::DisplayType::Dropdown)
|
||||
, _requestedUnit(RequestedUnitInfo)
|
||||
, _transitionFormat(
|
||||
TransitionFormatInfo,
|
||||
"Simulation increment: {:.1f} {:s} / second{:s} (current: {:.1f} {:s})"
|
||||
|
||||
@@ -84,7 +84,7 @@ documentation::Documentation DashboardItemVelocity::Documentation() {
|
||||
DashboardItemVelocity::DashboardItemVelocity(const ghoul::Dictionary& dictionary)
|
||||
: DashboardTextItem(dictionary)
|
||||
, _doSimplification(SimplificationInfo, true)
|
||||
, _requestedUnit(RequestedUnitInfo, properties::OptionProperty::DisplayType::Dropdown)
|
||||
, _requestedUnit(RequestedUnitInfo)
|
||||
{
|
||||
const Parameters p = codegen::bake<Parameters>(dictionary);
|
||||
_doSimplification.onChange([this]() {
|
||||
|
||||
@@ -37,6 +37,9 @@ namespace {
|
||||
openspace::properties::Property::Visibility::NoviceUser
|
||||
};
|
||||
|
||||
// This `LightSource` type represents a light source placed at the position of the
|
||||
// camera. An object with this light source will always be illuminated from the
|
||||
// current view direction.
|
||||
struct [[codegen::Dictionary(CameraLightSource)]] Parameters {
|
||||
// [[codegen::verbatim(IntensityInfo.description)]]
|
||||
std::optional<float> intensity;
|
||||
|
||||
@@ -41,18 +41,26 @@ namespace {
|
||||
openspace::properties::Property::Visibility::NoviceUser
|
||||
};
|
||||
|
||||
constexpr openspace::properties::Property::PropertyInfo NodeCameraStateInfo = {
|
||||
constexpr openspace::properties::Property::PropertyInfo NodeInfo = {
|
||||
"Node",
|
||||
"Node",
|
||||
"The identifier of the scene graph node to follow.",
|
||||
openspace::properties::Property::Visibility::AdvancedUser
|
||||
};
|
||||
|
||||
// This `LightSource` type represents a light source placed at the position of a
|
||||
// scene graph node. That is, the direction of the light will follow the position
|
||||
// of an existing object in the scene. It will also update dynamically as the
|
||||
// object moves.
|
||||
//
|
||||
// Note that the brightness of the light from the light source does not depend on
|
||||
// the distance between the two scene graph nodes. Only the `Intensity` value has
|
||||
// an impact on the brightness.
|
||||
struct [[codegen::Dictionary(SceneGraphLightSource)]] Parameters {
|
||||
// [[codegen::verbatim(IntensityInfo.description)]]
|
||||
std::optional<float> intensity;
|
||||
|
||||
// [[codegen::verbatim(NodeCameraStateInfo.description)]]
|
||||
// [[codegen::verbatim(NodeInfo.description)]]
|
||||
std::string node [[codegen::identifier()]];
|
||||
};
|
||||
#include "scenegraphlightsource_codegen.cpp"
|
||||
@@ -67,7 +75,7 @@ documentation::Documentation SceneGraphLightSource::Documentation() {
|
||||
SceneGraphLightSource::SceneGraphLightSource(const ghoul::Dictionary& dictionary)
|
||||
: LightSource(dictionary)
|
||||
, _intensity(IntensityInfo, 1.f, 0.f, 1.f)
|
||||
, _sceneGraphNodeReference(NodeCameraStateInfo, "")
|
||||
, _sceneGraphNodeReference(NodeInfo, "")
|
||||
{
|
||||
const Parameters p = codegen::bake<Parameters>(dictionary);
|
||||
|
||||
|
||||
@@ -637,10 +637,7 @@ RenderablePointCloud::RenderablePointCloud(const ghoul::Dictionary& dictionary)
|
||||
, _useAdditiveBlending(UseAdditiveBlendingInfo, true)
|
||||
, _useRotation(UseOrientationDataInfo, false)
|
||||
, _drawElements(DrawElementsInfo, true)
|
||||
, _renderOption(
|
||||
OrientationRenderOptionInfo,
|
||||
properties::OptionProperty::DisplayType::Dropdown
|
||||
)
|
||||
, _renderOption(OrientationRenderOptionInfo)
|
||||
, _nDataPoints(NumShownDataPointsInfo, 0)
|
||||
, _hasOrientationData(HasOrientationDataInfo, false)
|
||||
{
|
||||
|
||||
@@ -121,10 +121,7 @@ documentation::Documentation SizeMappingComponent::Documentation() {
|
||||
SizeMappingComponent::SizeMappingComponent()
|
||||
: properties::PropertyOwner({ "SizeMapping", "Size Mapping", "" })
|
||||
, enabled(EnabledInfo, true)
|
||||
, parameterOption(
|
||||
OptionInfo,
|
||||
properties::OptionProperty::DisplayType::Dropdown
|
||||
)
|
||||
, parameterOption(OptionInfo)
|
||||
, scaleFactor(ScaleFactorInfo, 1.f, 0.f, 1000.f)
|
||||
, isRadius(IsRadiusInfo, false)
|
||||
{
|
||||
|
||||
@@ -106,7 +106,7 @@ documentation::Documentation RenderableDistanceLabel::Documentation() {
|
||||
RenderableDistanceLabel::RenderableDistanceLabel(const ghoul::Dictionary& dictionary)
|
||||
: RenderableLabel(dictionary)
|
||||
, _nodelineId(NodeLineInfo)
|
||||
, _distanceUnit(DistanceUnitInfo, properties::OptionProperty::DisplayType::Dropdown)
|
||||
, _distanceUnit(DistanceUnitInfo)
|
||||
, _customUnitDescriptor(CustomUnitDescriptorInfo)
|
||||
, _precision(PrecisionInfo, 0, 0, 10)
|
||||
{
|
||||
|
||||
@@ -252,7 +252,7 @@ documentation::Documentation RenderableLabel::Documentation() {
|
||||
|
||||
RenderableLabel::RenderableLabel(const ghoul::Dictionary& dictionary)
|
||||
: Renderable(dictionary, { .automaticallyUpdateRenderBin = false })
|
||||
, _blendMode(BlendModeInfo, properties::OptionProperty::DisplayType::Dropdown)
|
||||
, _blendMode(BlendModeInfo)
|
||||
, _text(TextInfo, "")
|
||||
, _color(ColorInfo, glm::vec3(1.f), glm::vec3(0.f), glm::vec3(1.f))
|
||||
, _fontSize(FontSizeInfo, 50.f, 1.f, 100.f)
|
||||
@@ -261,14 +261,8 @@ RenderableLabel::RenderableLabel(const ghoul::Dictionary& dictionary)
|
||||
, _enableFadingEffect(EnableFadingEffectInfo, false)
|
||||
, _fadeWidths(FadeWidthsInfo, glm::vec2(1.f), glm::vec2(0.f), glm::vec2(100.f))
|
||||
, _fadeDistances(FadeDistancesInfo, glm::vec2(1.f), glm::vec2(0.f), glm::vec2(100.f))
|
||||
, _fadeUnitOption(
|
||||
FadeUnitOptionInfo,
|
||||
properties::OptionProperty::DisplayType::Dropdown
|
||||
)
|
||||
, _orientationOption(
|
||||
OrientationOptionInfo,
|
||||
properties::OptionProperty::DisplayType::Dropdown
|
||||
)
|
||||
, _fadeUnitOption(FadeUnitOptionInfo)
|
||||
, _orientationOption(OrientationOptionInfo)
|
||||
{
|
||||
const Parameters p = codegen::bake<Parameters>(dictionary);
|
||||
|
||||
|
||||
@@ -295,10 +295,7 @@ RenderableModel::RenderableModel(const ghoul::Dictionary& dictionary)
|
||||
, _modelScale(ModelScaleInfo, 1.0, std::numeric_limits<double>::epsilon(), 4e+27)
|
||||
, _rotationVec(RotationVecInfo, glm::dvec3(0.0), glm::dvec3(0.0), glm::dvec3(360.0))
|
||||
, _enableDepthTest(EnableDepthTestInfo, true)
|
||||
, _blendingFuncOption(
|
||||
BlendingOptionInfo,
|
||||
properties::OptionProperty::DisplayType::Dropdown
|
||||
)
|
||||
, _blendingFuncOption(BlendingOptionInfo)
|
||||
, _lightSourcePropertyOwner({ "LightSources", "Light Sources" })
|
||||
{
|
||||
const Parameters p = codegen::bake<Parameters>(dictionary);
|
||||
|
||||
@@ -131,7 +131,7 @@ documentation::Documentation RenderablePlane::Documentation() {
|
||||
|
||||
RenderablePlane::RenderablePlane(const ghoul::Dictionary& dictionary)
|
||||
: Renderable(dictionary, { .automaticallyUpdateRenderBin = false })
|
||||
, _blendMode(BlendModeInfo, properties::OptionProperty::DisplayType::Dropdown)
|
||||
, _blendMode(BlendModeInfo)
|
||||
, _billboard(BillboardInfo, false)
|
||||
, _mirrorBackside(MirrorBacksideInfo, false)
|
||||
, _size(SizeInfo, glm::vec2(10.f), glm::vec2(0.f), glm::vec2(1e25f))
|
||||
|
||||
@@ -180,15 +180,12 @@ RenderableSphere::RenderableSphere(const ghoul::Dictionary& dictionary)
|
||||
: Renderable(dictionary)
|
||||
, _size(SizeInfo, 1.f, 0.f, 1e25f)
|
||||
, _segments(SegmentsInfo, 16, 4, 1000)
|
||||
, _orientation(OrientationInfo, properties::OptionProperty::DisplayType::Dropdown)
|
||||
, _orientation(OrientationInfo)
|
||||
, _mirrorTexture(MirrorTextureInfo, false)
|
||||
, _disableFadeInDistance(DisableFadeInOutInfo, false)
|
||||
, _fadeInThreshold(FadeInThresholdInfo, 0.f, 0.f, 1.f, 0.001f)
|
||||
, _fadeOutThreshold(FadeOutThresholdInfo, 0.f, 0.f, 1.f, 0.001f)
|
||||
, _blendingFuncOption(
|
||||
BlendingOptionInfo,
|
||||
properties::OptionProperty::DisplayType::Dropdown
|
||||
)
|
||||
, _blendingFuncOption(BlendingOptionInfo)
|
||||
, _disableDepth(DisableDepthInfo, false)
|
||||
{
|
||||
const Parameters p = codegen::bake<Parameters>(dictionary);
|
||||
|
||||
@@ -188,10 +188,7 @@ RenderableTrail::Appearance::Appearance()
|
||||
, useLineFade(EnableFadeInfo, true)
|
||||
, lineWidth(LineWidthInfo, 10.f, 1.f, 20.f)
|
||||
, pointSize(PointSizeInfo, 1, 1, 64)
|
||||
, renderingModes(
|
||||
RenderingModeInfo,
|
||||
properties::OptionProperty::DisplayType::Dropdown
|
||||
)
|
||||
, renderingModes(RenderingModeInfo)
|
||||
, lineLength(LineLengthInfo, 1.f, 0.f, 1.f)
|
||||
, lineFadeAmount(LineFadeAmountInfo, 1.f, 0.f, 1.f)
|
||||
{
|
||||
|
||||
@@ -101,7 +101,7 @@ bool ScreenSpaceDashboard::initializeGL() {
|
||||
ScreenSpaceFramebuffer::initializeGL();
|
||||
|
||||
addRenderFunction([this]() {
|
||||
glm::vec2 penPosition = glm::vec2(0.f, _size.value().w);
|
||||
glm::vec2 penPosition = glm::vec2(0.f, _size.value().x);
|
||||
|
||||
if (_useMainDashboard) {
|
||||
global::dashboard->render(penPosition);
|
||||
|
||||
@@ -40,7 +40,7 @@ namespace openspace {
|
||||
namespace documentation { struct Documentation; }
|
||||
namespace scripting { struct LuaLibrary; }
|
||||
|
||||
class ScreenSpaceDashboard: public ScreenSpaceFramebuffer {
|
||||
class ScreenSpaceDashboard : public ScreenSpaceFramebuffer {
|
||||
public:
|
||||
explicit ScreenSpaceDashboard(const ghoul::Dictionary& dictionary);
|
||||
virtual ~ScreenSpaceDashboard() override = default;
|
||||
|
||||
@@ -55,7 +55,7 @@ documentation::Documentation ScreenSpaceFramebuffer::Documentation() {
|
||||
|
||||
ScreenSpaceFramebuffer::ScreenSpaceFramebuffer(const ghoul::Dictionary& dictionary)
|
||||
: ScreenSpaceRenderable(dictionary)
|
||||
, _size(SizeInfo, glm::vec4(0), glm::vec4(0), glm::vec4(16384))
|
||||
, _size(SizeInfo, glm::vec2(16), glm::vec2(16), glm::vec2(16384))
|
||||
{
|
||||
documentation::testSpecificationAndThrow(
|
||||
Documentation(),
|
||||
@@ -75,14 +75,8 @@ ScreenSpaceFramebuffer::ScreenSpaceFramebuffer(const ghoul::Dictionary& dictiona
|
||||
}
|
||||
}
|
||||
|
||||
if (_guiName.empty()) {
|
||||
// Adding an extra space to the user-facing name as it looks nicer
|
||||
setGuiName("ScreenSpaceFramebuffer " + std::to_string(iIdentifier));
|
||||
}
|
||||
|
||||
const glm::vec2 resolution = global::windowDelegate->currentDrawBufferResolution();
|
||||
_size = global::windowDelegate->currentDrawBufferResolution();
|
||||
addProperty(_size);
|
||||
_size = glm::vec4(0.f, 0.f, resolution.x, resolution.y);
|
||||
}
|
||||
|
||||
ScreenSpaceFramebuffer::~ScreenSpaceFramebuffer() {}
|
||||
@@ -107,22 +101,13 @@ bool ScreenSpaceFramebuffer::deinitializeGL() {
|
||||
|
||||
void ScreenSpaceFramebuffer::render(const RenderData& renderData) {
|
||||
const glm::vec2& resolution = global::windowDelegate->currentDrawBufferResolution();
|
||||
const glm::vec4& size = _size.value();
|
||||
|
||||
const float xratio = resolution.x / (size.z - size.x);
|
||||
const float yratio = resolution.y / (size.w - size.y);
|
||||
const glm::vec2& size = _size.value();
|
||||
const glm::vec2 ratio = resolution / size;
|
||||
|
||||
if (!_renderFunctions.empty()) {
|
||||
std::array<GLint, 4> viewport;
|
||||
//glGetIntegerv(GL_VIEWPORT, viewport);
|
||||
global::renderEngine->openglStateCache().viewport(viewport.data());
|
||||
glViewport(
|
||||
static_cast<GLint>(-size.x * xratio),
|
||||
static_cast<GLint>(-size.y * yratio),
|
||||
static_cast<GLsizei>(resolution.x * xratio),
|
||||
static_cast<GLsizei>(resolution.y * yratio)
|
||||
);
|
||||
global::renderEngine->openglStateCache().setViewportState(viewport.data());
|
||||
glGetIntegerv(GL_VIEWPORT, viewport.data());
|
||||
glViewport(0, 0, static_cast<GLint>(size.x), static_cast<GLint>(size.y));
|
||||
|
||||
const GLint defaultFBO = ghoul::opengl::FramebufferObject::getActiveObject();
|
||||
_framebuffer->activate();
|
||||
@@ -142,7 +127,7 @@ void ScreenSpaceFramebuffer::render(const RenderData& renderData) {
|
||||
const glm::mat4 localRotation = localRotationMatrix();
|
||||
const glm::mat4 scale = glm::scale(
|
||||
scaleMatrix(),
|
||||
glm::vec3((1.f / xratio), (1.f / yratio), 1.f)
|
||||
glm::vec3((1.f / ratio.x), (1.f / ratio.y), 1.f)
|
||||
);
|
||||
const glm::mat4 modelTransform = globalRotation*translation*localRotation*scale;
|
||||
draw(modelTransform, renderData);
|
||||
@@ -153,7 +138,7 @@ bool ScreenSpaceFramebuffer::isReady() const {
|
||||
return _shader && _texture;
|
||||
}
|
||||
|
||||
void ScreenSpaceFramebuffer::setSize(glm::vec4 size) {
|
||||
void ScreenSpaceFramebuffer::setSize(glm::vec2 size) {
|
||||
_size = std::move(size);
|
||||
}
|
||||
|
||||
|
||||
@@ -27,7 +27,7 @@
|
||||
|
||||
#include <openspace/rendering/screenspacerenderable.h>
|
||||
|
||||
#include <openspace/properties/vector/vec4property.h>
|
||||
#include <openspace/properties/vector/vec2property.h>
|
||||
|
||||
namespace ghoul::opengl {
|
||||
class FramebufferObject;
|
||||
@@ -56,7 +56,7 @@ public:
|
||||
void render(const RenderData& renderData) override;
|
||||
bool isReady() const override;
|
||||
|
||||
void setSize(glm::vec4 size);
|
||||
void setSize(glm::vec2 size);
|
||||
void addRenderFunction(RenderFunction renderFunction);
|
||||
void removeAllRenderFunctions();
|
||||
|
||||
@@ -64,7 +64,7 @@ public:
|
||||
|
||||
protected:
|
||||
void createFramebuffer();
|
||||
properties::Vec4Property _size;
|
||||
properties::Vec2Property _size;
|
||||
|
||||
private:
|
||||
void bindTexture() override;
|
||||
|
||||
307
modules/base/rendering/screenspacerenderablerenderable.cpp
Normal file
307
modules/base/rendering/screenspacerenderablerenderable.cpp
Normal file
@@ -0,0 +1,307 @@
|
||||
/*****************************************************************************************
|
||||
* *
|
||||
* OpenSpace *
|
||||
* *
|
||||
* Copyright (c) 2014-2025 *
|
||||
* *
|
||||
* 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/base/rendering/screenspacerenderablerenderable.h>
|
||||
|
||||
#include <openspace/camera/camera.h>
|
||||
#include <openspace/rendering/renderable.h>
|
||||
#include <openspace/scene/rotation.h>
|
||||
#include <openspace/scene/scale.h>
|
||||
#include <openspace/scene/translation.h>
|
||||
#include <openspace/util/updatestructures.h>
|
||||
|
||||
namespace {
|
||||
constexpr openspace::properties::Property::PropertyInfo TimeInfo = {
|
||||
"Time",
|
||||
"Time",
|
||||
"The time (in J2000 seconds) that is used to calculate transformations and the "
|
||||
"renderable's data."
|
||||
};
|
||||
|
||||
constexpr openspace::properties::Property::PropertyInfo CameraPositionInfo = {
|
||||
"CameraPosition",
|
||||
"Camera Position",
|
||||
"Specifies the location of the virtual camera that is showing the renderable "
|
||||
"class. This position is provided in meters."
|
||||
};
|
||||
|
||||
constexpr openspace::properties::Property::PropertyInfo CameraCenterInfo = {
|
||||
"CameraCenter",
|
||||
"Camera Center",
|
||||
"The location of the camera's focal point. The camera's view direction will "
|
||||
"always be pointing at the provided center location. This position is provided "
|
||||
"in meters."
|
||||
};
|
||||
|
||||
constexpr openspace::properties::Property::PropertyInfo CameraUpInfo = {
|
||||
"CameraUp",
|
||||
"Camera Up",
|
||||
"The direction that is 'up' for the provided camera. This value does not have "
|
||||
"any units."
|
||||
};
|
||||
|
||||
constexpr openspace::properties::Property::PropertyInfo CameraFovInfo = {
|
||||
"CameraFov",
|
||||
"Camera Field of view",
|
||||
"The camera's field of view in degrees."
|
||||
};
|
||||
|
||||
const openspace::properties::PropertyOwner::PropertyOwnerInfo TransformInfo = {
|
||||
"Transform",
|
||||
"Transform",
|
||||
"The Translation, Rotation, and Scale that are applied to the rendered "
|
||||
"Renderable."
|
||||
};
|
||||
|
||||
// This [ScreenSpaceRenderable](#core_screenspacerenderable) object can render any
|
||||
// [Renderable](#renderable) type into an image that is shown in screen space. This
|
||||
// can be used to display a rendered object as an overlay in front of the regular 3D
|
||||
// rendering of the scene.
|
||||
//
|
||||
// Note that to use this `ScreenSpaceRenderable`, it might be necessary to specify the
|
||||
// `size` parameter, which determines the resolution of the inset window into which
|
||||
// the Renderable is rendered. For many use cases, the default should suffice,
|
||||
// however.
|
||||
//
|
||||
// A possible use-case for the ScreenSpaceRenderable would be to show a 3D model of a
|
||||
// spacecraft without the need to place it at a position in the 3D scene with the need
|
||||
// to fly to that object to talk about it.
|
||||
struct [[codegen::Dictionary(ScreenSpaceRenderableRenderable)]] Parameters {
|
||||
std::optional<std::string> identifier [[codegen::private()]];
|
||||
|
||||
// The [Renderable](#renderable) object that is shown in this ScreenSpace object.
|
||||
// See the list of creatable renderable objects for options that can be used for
|
||||
// this type.
|
||||
ghoul::Dictionary renderable [[codegen::reference("renderable")]];
|
||||
|
||||
struct Transform {
|
||||
// The [Translation](#core_transform_translation) object that is used for the
|
||||
// provided [Renderable](#renderable). If no value is specified, a
|
||||
// [StaticTranslation](#base_transform_translation_static) is created instead.
|
||||
std::optional<ghoul::Dictionary> translation
|
||||
[[codegen::reference("core_transform_translation")]];
|
||||
|
||||
// The [Rotation](#core_transform_rotation) object that is used for the
|
||||
// provided [Renderable](#renderable). If no value is specified, a
|
||||
// [StaticRotation](#base_transform_rotation_static) is created instead.
|
||||
std::optional<ghoul::Dictionary> rotation
|
||||
[[codegen::reference("core_transform_rotation")]];
|
||||
|
||||
// The [Scale](#core_transform_scale) object that is used for the provided
|
||||
// [Renderable](#renderable). If no value is specified, a
|
||||
// [StaticScale](#base_transform_scale_static) is created instead.
|
||||
std::optional<ghoul::Dictionary> scale
|
||||
[[codegen::reference("core_transform_scale")]];
|
||||
};
|
||||
// The collection of transformations that are applied to the
|
||||
// [Renderable](#renderable) before it is shown on screen.
|
||||
std::optional<Transform> transform;
|
||||
|
||||
// Specifies the start date that is used to control the renderable and the
|
||||
// transforms. If no value is specified the date of 2000 JAN 01 12:00:00 is used
|
||||
// instead.
|
||||
std::optional<std::string> time [[codegen::datetime()]];
|
||||
|
||||
// [[codegen::verbatim(CameraPositionInfo.description)]]
|
||||
std::optional<glm::vec3> cameraPosition;
|
||||
|
||||
// [[codegen::verbatim(CameraCenterInfo.description)]]
|
||||
std::optional<glm::vec3> cameraCenter;
|
||||
|
||||
// [[codegen::verbatim(CameraUpInfo.description)]]
|
||||
std::optional<glm::vec3> cameraUp;
|
||||
|
||||
// [[codegen::verbatim(CameraFovInfo.description)]]
|
||||
std::optional<float> cameraFov;
|
||||
};
|
||||
#include "screenspacerenderablerenderable_codegen.cpp"
|
||||
} // namespace
|
||||
|
||||
namespace openspace {
|
||||
|
||||
documentation::Documentation ScreenSpaceRenderableRenderable::Documentation() {
|
||||
return codegen::doc<Parameters>(
|
||||
"base_screenspace_renderable",
|
||||
ScreenSpaceFramebuffer::Documentation()
|
||||
);
|
||||
}
|
||||
|
||||
ScreenSpaceRenderableRenderable::ScreenSpaceRenderableRenderable(
|
||||
const ghoul::Dictionary& dictionary)
|
||||
: ScreenSpaceFramebuffer(dictionary)
|
||||
, _time(
|
||||
TimeInfo,
|
||||
0.0,
|
||||
-std::numeric_limits<double>::max(),
|
||||
std::numeric_limits<double>::max()
|
||||
)
|
||||
, _cameraPosition(
|
||||
CameraPositionInfo,
|
||||
glm::vec3(0.f, 2.f, 2.f),
|
||||
glm::vec3(-10.f, -10.f, -10.f),
|
||||
glm::vec3(10.f, 10.f, 10.f)
|
||||
)
|
||||
, _cameraCenter(CameraCenterInfo, glm::vec3(0.f), glm::vec3(-1.f), glm::vec3(1.f))
|
||||
, _cameraUp(CameraUpInfo, glm::vec3(0.f, 1.f, 0.f), glm::vec3(-1.f), glm::vec3(1.f))
|
||||
, _cameraFov(CameraFovInfo, 45.f, 5.f, 90.f)
|
||||
{
|
||||
const Parameters p = codegen::bake<Parameters>(dictionary);
|
||||
|
||||
std::string identifier = p.identifier.value_or("ScreenSpaceRenderableRenderable");
|
||||
setIdentifier(makeUniqueIdentifier(std::move(identifier)));
|
||||
|
||||
if (p.time.has_value()) {
|
||||
_time = Time(*p.time).j2000Seconds();
|
||||
}
|
||||
_time.onChange([this]() { _previousTime = _time; });
|
||||
addProperty(_time);
|
||||
|
||||
_cameraPosition = p.cameraPosition.value_or(_cameraPosition);
|
||||
addProperty(_cameraPosition);
|
||||
_cameraCenter = p.cameraCenter.value_or(_cameraCenter);
|
||||
addProperty(_cameraCenter);
|
||||
_cameraUp = p.cameraUp.value_or(_cameraUp);
|
||||
addProperty(_cameraUp);
|
||||
_cameraFov = p.cameraFov.value_or(_cameraFov);
|
||||
addProperty(_cameraFov);
|
||||
|
||||
_renderable = Renderable::createFromDictionary(p.renderable);
|
||||
_renderable->initialize();
|
||||
addPropertySubOwner(_renderable.get());
|
||||
|
||||
_transform = ghoul::mm_unique_ptr<properties::PropertyOwner>(
|
||||
new properties::PropertyOwner(TransformInfo)
|
||||
);
|
||||
addPropertySubOwner(_transform.get());
|
||||
|
||||
if (p.transform.has_value() && p.transform->translation.has_value()) {
|
||||
_translation = Translation::createFromDictionary(*p.transform->translation);
|
||||
}
|
||||
else {
|
||||
ghoul::Dictionary translation;
|
||||
translation.setValue("Type", std::string("StaticTranslation"));
|
||||
translation.setValue("Position", glm::dvec3(0.0));
|
||||
_translation = Translation::createFromDictionary(translation);
|
||||
}
|
||||
_translation->initialize();
|
||||
_transform->addPropertySubOwner(_translation.get());
|
||||
|
||||
if (p.transform.has_value() && p.transform->rotation.has_value()) {
|
||||
_rotation = Rotation::createFromDictionary(*p.transform->rotation);
|
||||
}
|
||||
else {
|
||||
ghoul::Dictionary rotation;
|
||||
rotation.setValue("Type", std::string("StaticRotation"));
|
||||
rotation.setValue("Rotation", glm::dvec3(0.0));
|
||||
_rotation = Rotation::createFromDictionary(rotation);
|
||||
}
|
||||
_rotation->initialize();
|
||||
_transform->addPropertySubOwner(_rotation.get());
|
||||
|
||||
if (p.transform.has_value() && p.transform->scale.has_value()) {
|
||||
_scale = Scale::createFromDictionary(*p.transform->scale);
|
||||
}
|
||||
else {
|
||||
ghoul::Dictionary scale;
|
||||
scale.setValue("Type", std::string("StaticScale"));
|
||||
scale.setValue("Scale", 1.0);
|
||||
_scale = Scale::createFromDictionary(scale);
|
||||
}
|
||||
_scale->initialize();
|
||||
_transform->addPropertySubOwner(_scale.get());
|
||||
}
|
||||
|
||||
ScreenSpaceRenderableRenderable::~ScreenSpaceRenderableRenderable() {}
|
||||
|
||||
bool ScreenSpaceRenderableRenderable::initializeGL() {
|
||||
ScreenSpaceFramebuffer::initializeGL();
|
||||
|
||||
_renderable->initializeGL();
|
||||
|
||||
addRenderFunction([this]() {
|
||||
glm::vec4 bg = _backgroundColor;
|
||||
glClearColor(bg.r, bg.g, bg.b, bg.a);
|
||||
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
|
||||
|
||||
Camera camera;
|
||||
// @TODO (2025-03-24, abock): These two lines can be removed once #3573 is fixed
|
||||
camera.setPositionVec3(glm::dvec3(0.0, 0.0, 0.0));
|
||||
camera.setRotation(glm::dvec3(0.0, 0.0, 0.0));
|
||||
|
||||
glm::mat4 view = glm::lookAt(
|
||||
_cameraPosition.value(),
|
||||
_cameraCenter.value(),
|
||||
glm::normalize(_cameraUp.value())
|
||||
);
|
||||
camera.sgctInternal.setViewMatrix(view);
|
||||
|
||||
glm::mat4 proj = glm::perspectiveFov(
|
||||
glm::radians(_cameraFov.value()),
|
||||
_size.value().x,
|
||||
_size.value().y,
|
||||
0.1f,
|
||||
20.f
|
||||
);
|
||||
camera.sgctInternal.setProjectionMatrix(proj);
|
||||
|
||||
openspace::RenderData renderData = {
|
||||
.camera = camera,
|
||||
.time = Time(_time),
|
||||
.modelTransform = {
|
||||
.translation = _translation->position(),
|
||||
.rotation = _rotation->matrix(),
|
||||
.scale = _scale->scaleValue()
|
||||
}
|
||||
};
|
||||
RendererTasks tasks;
|
||||
_renderable->render(renderData, tasks);
|
||||
});
|
||||
return true;
|
||||
}
|
||||
|
||||
bool ScreenSpaceRenderableRenderable::deinitializeGL() {
|
||||
_renderable->deinitializeGL();
|
||||
_renderable->deinitialize();
|
||||
return ScreenSpaceFramebuffer::deinitializeGL();
|
||||
}
|
||||
|
||||
void ScreenSpaceRenderableRenderable::update() {
|
||||
UpdateData updateData = {
|
||||
.time = Time(_time),
|
||||
.previousFrameTime = Time(_previousTime)
|
||||
};
|
||||
|
||||
_translation->update(updateData);
|
||||
updateData.modelTransform.translation = _translation->position();
|
||||
|
||||
_rotation->update(updateData);
|
||||
updateData.modelTransform.rotation = _rotation->matrix();
|
||||
|
||||
_scale->update(updateData);
|
||||
updateData.modelTransform.scale = _scale->scaleValue();
|
||||
|
||||
_renderable->update(updateData);
|
||||
}
|
||||
|
||||
} // namespace openspace
|
||||
76
modules/base/rendering/screenspacerenderablerenderable.h
Normal file
76
modules/base/rendering/screenspacerenderablerenderable.h
Normal file
@@ -0,0 +1,76 @@
|
||||
/*****************************************************************************************
|
||||
* *
|
||||
* OpenSpace *
|
||||
* *
|
||||
* Copyright (c) 2014-2025 *
|
||||
* *
|
||||
* 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_BASE___SCREENSPACERENDERABLERENDERABLE___H__
|
||||
#define __OPENSPACE_MODULE_BASE___SCREENSPACERENDERABLERENDERABLE___H__
|
||||
|
||||
#include <modules/base//rendering/screenspaceframebuffer.h>
|
||||
|
||||
#include <openspace/properties/scalar/boolproperty.h>
|
||||
#include <openspace/properties/scalar/doubleproperty.h>
|
||||
#include <openspace/properties/scalar/floatproperty.h>
|
||||
#include <openspace/properties/vector/vec3property.h>
|
||||
|
||||
namespace openspace {
|
||||
|
||||
namespace properties { class PropertyOwner; }
|
||||
|
||||
class Renderable;
|
||||
class Rotation;
|
||||
class Scale;
|
||||
class Translation;
|
||||
|
||||
namespace documentation { struct Documentation; }
|
||||
|
||||
class ScreenSpaceRenderableRenderable : public ScreenSpaceFramebuffer {
|
||||
public:
|
||||
using RenderFunction = std::function<void()>;
|
||||
|
||||
explicit ScreenSpaceRenderableRenderable(const ghoul::Dictionary& dictionary);
|
||||
virtual ~ScreenSpaceRenderableRenderable() override;
|
||||
|
||||
bool initializeGL() override;
|
||||
bool deinitializeGL() override;
|
||||
void update() override;
|
||||
|
||||
static documentation::Documentation Documentation();
|
||||
|
||||
private:
|
||||
ghoul::mm_unique_ptr<Translation> _translation = nullptr;
|
||||
ghoul::mm_unique_ptr<properties::PropertyOwner> _transform = nullptr;
|
||||
ghoul::mm_unique_ptr<Rotation> _rotation = nullptr;
|
||||
ghoul::mm_unique_ptr<Scale> _scale = nullptr;
|
||||
ghoul::mm_unique_ptr<Renderable> _renderable = nullptr;
|
||||
|
||||
double _previousTime = 0.0;
|
||||
properties::DoubleProperty _time;
|
||||
properties::Vec3Property _cameraPosition;
|
||||
properties::Vec3Property _cameraCenter;
|
||||
properties::Vec3Property _cameraUp;
|
||||
properties::FloatProperty _cameraFov;
|
||||
};
|
||||
|
||||
} //namespace openspace
|
||||
|
||||
#endif // __OPENSPACE_MODULE_BASE___SCREENSPACERENDERABLERENDERABLE___H__
|
||||
@@ -284,10 +284,7 @@ FixedRotation::FixedRotation(const ghoul::Dictionary& dictionary)
|
||||
: Rotation(dictionary)
|
||||
, _enabled(EnableInfo, true)
|
||||
, _xAxis{
|
||||
properties::OptionProperty(
|
||||
XAxisTypeInfo,
|
||||
properties::OptionProperty::DisplayType::Dropdown
|
||||
),
|
||||
properties::OptionProperty(XAxisTypeInfo),
|
||||
properties::StringProperty(XAxisObjectInfo, ""),
|
||||
properties::BoolProperty(XAxisInvertObjectInfo, false),
|
||||
properties::Vec3Property(
|
||||
@@ -300,10 +297,7 @@ FixedRotation::FixedRotation(const ghoul::Dictionary& dictionary)
|
||||
nullptr
|
||||
}
|
||||
, _yAxis{
|
||||
properties::OptionProperty(
|
||||
YAxisTypeInfo,
|
||||
properties::OptionProperty::DisplayType::Dropdown
|
||||
),
|
||||
properties::OptionProperty(YAxisTypeInfo),
|
||||
properties::StringProperty(YAxisObjectInfo, ""),
|
||||
properties::BoolProperty(YAxisInvertObjectInfo, false),
|
||||
properties::Vec3Property(
|
||||
@@ -316,10 +310,7 @@ FixedRotation::FixedRotation(const ghoul::Dictionary& dictionary)
|
||||
nullptr
|
||||
}
|
||||
, _zAxis{
|
||||
properties::OptionProperty(
|
||||
ZAxisTypeInfo,
|
||||
properties::OptionProperty::DisplayType::Dropdown
|
||||
),
|
||||
properties::OptionProperty(ZAxisTypeInfo),
|
||||
properties::StringProperty(ZAxisObjectInfo, ""),
|
||||
properties::BoolProperty(ZAxisInvertObjectInfo, false),
|
||||
properties::Vec3Property(
|
||||
|
||||
@@ -192,7 +192,7 @@ RenderableDUMeshes::RenderableDUMeshes(const ghoul::Dictionary& dictionary)
|
||||
glm::ivec2(1000)
|
||||
)
|
||||
, _lineWidth(LineWidthInfo, 2.f, 1.f, 16.f)
|
||||
, _renderOption(RenderOptionInfo, properties::OptionProperty::DisplayType::Dropdown)
|
||||
, _renderOption(RenderOptionInfo)
|
||||
{
|
||||
const Parameters p = codegen::bake<Parameters>(dictionary);
|
||||
|
||||
|
||||
@@ -300,8 +300,8 @@ RenderableFieldlinesSequence::RenderableFieldlinesSequence(
|
||||
const ghoul::Dictionary& dictionary)
|
||||
: Renderable(dictionary)
|
||||
, _colorGroup({ "Color" })
|
||||
, _colorMethod(ColorMethodInfo, properties::OptionProperty::DisplayType::Radio)
|
||||
, _colorQuantity(ColorQuantityInfo, properties::OptionProperty::DisplayType::Dropdown)
|
||||
, _colorMethod(ColorMethodInfo)
|
||||
, _colorQuantity(ColorQuantityInfo)
|
||||
, _colorQuantityMinMax(
|
||||
ColorMinMaxInfo,
|
||||
glm::vec2(-0.f, 100.f),
|
||||
@@ -342,10 +342,7 @@ RenderableFieldlinesSequence::RenderableFieldlinesSequence(
|
||||
glm::vec2(-5000.f),
|
||||
glm::vec2(5000.f)
|
||||
)
|
||||
, _maskingQuantity(
|
||||
MaskingQuantityInfo,
|
||||
properties::OptionProperty::DisplayType::Dropdown
|
||||
)
|
||||
, _maskingQuantity(MaskingQuantityInfo)
|
||||
, _lineWidth(LineWidthInfo, 1.f, 1.f, 20.f)
|
||||
, _jumpToStartBtn(TimeJumpButtonInfo)
|
||||
{
|
||||
|
||||
Submodule modules/fitsfilereader/ext/CCfits updated: 15e78f599d...d9f9811b3e
Submodule modules/fitsfilereader/ext/cfitsio updated: 8d98f1495b...49258f81de
@@ -472,12 +472,9 @@ RenderableGaiaStars::RenderableGaiaStars(const ghoul::Dictionary& dictionary)
|
||||
, _firstRow(FirstRowInfo, 0, 0, 2539913) // DR1-max: 2539913
|
||||
, _lastRow(LastRowInfo, 0, 0, 2539913)
|
||||
, _columnNamesList(ColumnNamesInfo)
|
||||
, _fileReaderOption(
|
||||
FileReaderOptionInfo,
|
||||
properties::OptionProperty::DisplayType::Dropdown
|
||||
)
|
||||
, _renderMode(RenderModeInfo, properties::OptionProperty::DisplayType::Dropdown)
|
||||
, _shaderOption(ShaderOptionInfo, properties::OptionProperty::DisplayType::Dropdown)
|
||||
, _fileReaderOption(FileReaderOptionInfo)
|
||||
, _renderMode(RenderModeInfo)
|
||||
, _shaderOption(ShaderOptionInfo)
|
||||
, _nRenderedStars(NumRenderedStarsInfo, 0, 0, 2000000000) // 2 Billion stars
|
||||
, _cpuRamBudgetProperty(CpuRamBudgetInfo, 0.f, 0.f, 1.f)
|
||||
, _gpuStreamBudgetProperty(GpuStreamBudgetInfo, 0.f, 0.f, 1.f)
|
||||
|
||||
@@ -146,7 +146,7 @@ namespace {
|
||||
"The number of integration steps used during the raycasting procedure.",
|
||||
openspace::properties::Property::Visibility::AdvancedUser
|
||||
};
|
||||
|
||||
|
||||
void saveCachedFile(const std::filesystem::path& file,
|
||||
const std::vector<glm::vec3>& positions,
|
||||
const std::vector<glm::vec3>& colors, int64_t nPoints,
|
||||
@@ -254,10 +254,7 @@ RenderableGalaxy::RenderableGalaxy(const ghoul::Dictionary& dictionary)
|
||||
, _stepSize(StepSizeInfo, 0.01f, 0.001f, 0.05f, 0.001f)
|
||||
, _absorptionMultiply(AbsorptionMultiplyInfo, 40.f, 0.f, 200.f)
|
||||
, _emissionMultiply(EmissionMultiplyInfo, 200.f, 0.f, 1000.f)
|
||||
, _starRenderingMethod(
|
||||
StarRenderingMethodInfo,
|
||||
properties::OptionProperty::DisplayType::Dropdown
|
||||
)
|
||||
, _starRenderingMethod(StarRenderingMethodInfo)
|
||||
, _enabledPointsRatio(EnabledPointsRatioInfo, 0.5f, 0.01f, 1.f)
|
||||
, _rotation(
|
||||
RotationInfo,
|
||||
|
||||
@@ -300,10 +300,7 @@ GeoJsonComponent::GeoJsonComponent(const ghoul::Dictionary& dictionary,
|
||||
)
|
||||
, _pointSizeScale(PointSizeScaleInfo, 1.f, 0.01f, 100.f)
|
||||
, _lineWidthScale(LineWidthScaleInfo, 1.f, 0.01f, 10.f)
|
||||
, _pointRenderModeOption(
|
||||
PointRenderModeInfo,
|
||||
properties::OptionProperty::DisplayType::Dropdown
|
||||
)
|
||||
, _pointRenderModeOption(PointRenderModeInfo)
|
||||
, _drawWireframe(DrawWireframeInfo, false)
|
||||
, _preventUpdatesFromHeightMap(PreventHeightUpdateInfo, false)
|
||||
, _forceUpdateHeightData(ForceUpdateHeightDataInfo)
|
||||
|
||||
@@ -37,7 +37,7 @@ namespace {
|
||||
namespace openspace::globebrowsing {
|
||||
|
||||
GeoJsonManager::GeoJsonManager()
|
||||
: properties::PropertyOwner({ "GeoJson", "Geometry Overlays" })
|
||||
: properties::PropertyOwner({ "GeographicOverlays", "Geographic Overlays" })
|
||||
{}
|
||||
|
||||
void GeoJsonManager::initialize(RenderableGlobe* globe) {
|
||||
|
||||
@@ -380,16 +380,10 @@ GeoJsonProperties::GeoJsonProperties()
|
||||
, lineWidth(LineWidthInfo, 2.f, 0.01f, 10.f)
|
||||
, pointSize(PointSizeInfo, 10.f, 0.01f, 100.f)
|
||||
, pointTexture(PointTextureInfo)
|
||||
, pointAnchorOption(
|
||||
PointAnchorOptionInfo,
|
||||
properties::OptionProperty::DisplayType::Dropdown
|
||||
)
|
||||
, pointAnchorOption(PointAnchorOptionInfo)
|
||||
, extrude(ExtrudeInfo, false)
|
||||
, performShading(PerformShadingInfo, false)
|
||||
, altitudeModeOption(
|
||||
AltitudeModeInfo,
|
||||
properties::OptionProperty::DisplayType::Dropdown
|
||||
)
|
||||
, altitudeModeOption(AltitudeModeInfo)
|
||||
{
|
||||
addProperty(opacity);
|
||||
color.setViewOption(properties::Property::ViewOptions::Color);
|
||||
|
||||
@@ -280,10 +280,7 @@ GlobeLabelsComponent::GlobeLabelsComponent()
|
||||
, _fadeOutEnabled(FadeOutEnabledInfo, false)
|
||||
, _disableCulling(DisableCullingInfo, false)
|
||||
, _distanceEPS(DistanceEPSInfo, 100000.f, 1000.f, 10000000.f)
|
||||
, _alignmentOption(
|
||||
AlignmentOptionInfo,
|
||||
properties::OptionProperty::DisplayType::Dropdown
|
||||
)
|
||||
, _alignmentOption(AlignmentOptionInfo)
|
||||
{
|
||||
addProperty(_enabled);
|
||||
addProperty(_color);
|
||||
|
||||
@@ -186,8 +186,8 @@ Layer::Layer(layers::Group::ID id, const ghoul::Dictionary& layerDict, LayerGrou
|
||||
layerDict.hasKey(KeyDesc) ? layerDict.value<std::string>(KeyDesc) : ""
|
||||
})
|
||||
, _parent(parent)
|
||||
, _typeOption(TypeInfo, properties::OptionProperty::DisplayType::Dropdown)
|
||||
, _blendModeOption(BlendModeInfo, properties::OptionProperty::DisplayType::Dropdown)
|
||||
, _typeOption(TypeInfo)
|
||||
, _blendModeOption(BlendModeInfo)
|
||||
, _enabled(EnabledInfo, false)
|
||||
, _reset(ResetInfo)
|
||||
, _remove(RemoveInfo)
|
||||
|
||||
@@ -80,7 +80,7 @@ LayerAdjustment::LayerAdjustment()
|
||||
: properties::PropertyOwner({ "Adjustment" })
|
||||
, _chromaKeyColor(ChromaKeyColorInfo, glm::vec3(0.f), glm::vec3(0.f), glm::vec3(1.f))
|
||||
, _chromaKeyTolerance(ChromaKeyToleranceInfo, 0.f, 0.f, 1.f)
|
||||
, _typeOption(TypeInfo, properties::OptionProperty::DisplayType::Dropdown)
|
||||
, _typeOption(TypeInfo)
|
||||
, _typeId(static_cast<layers::Adjustment::ID>(_typeOption.value()))
|
||||
{
|
||||
// Add options to option properties
|
||||
|
||||
@@ -110,48 +110,33 @@ void renderOptionProperty(Property* prop, const std::string& ownerName,
|
||||
|
||||
int value = *p;
|
||||
const std::vector<OptionProperty::Option>& options = p->options();
|
||||
switch (p->displayType()) {
|
||||
case OptionProperty::DisplayType::Radio:
|
||||
ImGui::Text("%s", name.c_str());
|
||||
ImGui::Separator();
|
||||
for (const OptionProperty::Option& o : options) {
|
||||
ImGui::RadioButton(o.description.c_str(), &value, o.value);
|
||||
if (showTooltip) {
|
||||
renderTooltip(prop, tooltipDelay);
|
||||
}
|
||||
}
|
||||
ImGui::Separator();
|
||||
break;
|
||||
case OptionProperty::DisplayType::Dropdown: {
|
||||
// The order of the options does not have to correspond with the value of the
|
||||
// option
|
||||
std::string nodeNames;
|
||||
for (const OptionProperty::Option& o : options) {
|
||||
nodeNames += o.description + '\0';
|
||||
}
|
||||
nodeNames += '\0';
|
||||
|
||||
int idx = static_cast<int>(std::distance(
|
||||
options.begin(),
|
||||
std::find_if(
|
||||
options.begin(),
|
||||
options.end(),
|
||||
[value](const OptionProperty::Option& o) { return o.value == value; }
|
||||
)
|
||||
));
|
||||
|
||||
const bool hasChanged = ImGui::Combo(name.c_str(), &idx, nodeNames.c_str());
|
||||
if (showTooltip) {
|
||||
renderTooltip(prop, tooltipDelay);
|
||||
}
|
||||
|
||||
if (hasChanged) {
|
||||
value = options[idx].value;
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
// The order of the options does not have to correspond with the value of the
|
||||
// option
|
||||
std::string nodeNames;
|
||||
for (const OptionProperty::Option& o : options) {
|
||||
nodeNames += o.description + '\0';
|
||||
}
|
||||
nodeNames += '\0';
|
||||
|
||||
int idx = static_cast<int>(std::distance(
|
||||
options.begin(),
|
||||
std::find_if(
|
||||
options.begin(),
|
||||
options.end(),
|
||||
[value](const OptionProperty::Option& o) { return o.value == value; }
|
||||
)
|
||||
));
|
||||
|
||||
const bool hasChanged = ImGui::Combo(name.c_str(), &idx, nodeNames.c_str());
|
||||
if (showTooltip) {
|
||||
renderTooltip(prop, tooltipDelay);
|
||||
}
|
||||
|
||||
if (hasChanged) {
|
||||
value = options[idx].value;
|
||||
}
|
||||
|
||||
if (value != p->value() && !isReadOnly) {
|
||||
executeSetPropertyScript(p->uri(), std::to_string(value));
|
||||
}
|
||||
|
||||
Submodule modules/kameleon/ext/kameleon updated: eee25cf7f4...91485053e1
@@ -191,7 +191,7 @@ RenderableKameleonVolume::RenderableKameleonVolume(const ghoul::Dictionary& dict
|
||||
, _domainScale(DomainScaleInfo, glm::vec3(1.f))
|
||||
, _lowerValueBound(LowerValueBoundInfo, 0.f, 0.f, 1.f)
|
||||
, _upperValueBound(UpperValueBoundInfo, 1.f, 0.01f, 1.f)
|
||||
, _gridType(GridTypeInfo, properties::OptionProperty::DisplayType::Dropdown)
|
||||
, _gridType(GridTypeInfo)
|
||||
, _stepSize(StepSizeInfo, 0.02f, 0.01f, 1.f)
|
||||
, _sourcePath(SourcePathInfo)
|
||||
, _transferFunctionPath(TransferFunctionInfo)
|
||||
|
||||
@@ -43,6 +43,7 @@ set(HEADER_FILES
|
||||
include/topics/getpropertytopic.h
|
||||
include/topics/luascripttopic.h
|
||||
include/topics/missiontopic.h
|
||||
include/topics/profiletopic.h
|
||||
include/topics/sessionrecordingtopic.h
|
||||
include/topics/setpropertytopic.h
|
||||
include/topics/shortcuttopic.h
|
||||
@@ -73,6 +74,7 @@ set(SOURCE_FILES
|
||||
src/topics/getpropertytopic.cpp
|
||||
src/topics/luascripttopic.cpp
|
||||
src/topics/missiontopic.cpp
|
||||
src/topics/profiletopic.cpp
|
||||
src/topics/sessionrecordingtopic.cpp
|
||||
src/topics/setpropertytopic.cpp
|
||||
src/topics/shortcuttopic.cpp
|
||||
|
||||
45
modules/server/include/topics/profiletopic.h
Normal file
45
modules/server/include/topics/profiletopic.h
Normal file
@@ -0,0 +1,45 @@
|
||||
/*****************************************************************************************
|
||||
* *
|
||||
* OpenSpace *
|
||||
* *
|
||||
* Copyright (c) 2014-2025 *
|
||||
* *
|
||||
* 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_SERVER___PROFILETOPIC___H__
|
||||
#define __OPENSPACE_MODULE_SERVER___PROFILETOPIC___H__
|
||||
|
||||
#include <modules/server/include/topics/topic.h>
|
||||
|
||||
using nlohmann::json;
|
||||
|
||||
namespace openspace {
|
||||
|
||||
class ProfileTopic : public Topic {
|
||||
public:
|
||||
ProfileTopic() = default;
|
||||
~ProfileTopic() override = default;
|
||||
|
||||
void handleJson(const nlohmann::json& json) override;
|
||||
bool isDone() const override;
|
||||
};
|
||||
|
||||
} // namespace openspace
|
||||
|
||||
#endif // __OPENSPACE_MODULE_SERVER___PROFILETOPIC___H__
|
||||
@@ -53,6 +53,7 @@
|
||||
#include <ghoul/io/socket/tcpsocketserver.h>
|
||||
#include <ghoul/io/socket/websocketserver.h>
|
||||
#include <ghoul/misc/profiling.h>
|
||||
#include <include/topics/profiletopic.h>
|
||||
|
||||
namespace {
|
||||
constexpr std::string_view _loggerCat = "ServerModule: Connection";
|
||||
@@ -97,6 +98,7 @@ Connection::Connection(std::unique_ptr<ghoul::io::Socket> s, std::string address
|
||||
_topicFactory.registerClass<GetPropertyTopic>("get");
|
||||
_topicFactory.registerClass<LuaScriptTopic>("luascript");
|
||||
_topicFactory.registerClass<MissionTopic>("missions");
|
||||
_topicFactory.registerClass<ProfileTopic>("profile");
|
||||
_topicFactory.registerClass<SessionRecordingTopic>("sessionRecording");
|
||||
_topicFactory.registerClass<SetPropertyTopic>("set");
|
||||
_topicFactory.registerClass<ShortcutTopic>("shortcuts");
|
||||
|
||||
46
modules/server/src/topics/profiletopic.cpp
Normal file
46
modules/server/src/topics/profiletopic.cpp
Normal file
@@ -0,0 +1,46 @@
|
||||
/*****************************************************************************************
|
||||
* *
|
||||
* OpenSpace *
|
||||
* *
|
||||
* Copyright (c) 2014-2025 *
|
||||
* *
|
||||
* 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/server/include/topics/profiletopic.h>
|
||||
|
||||
#include <modules/server/include/connection.h>
|
||||
#include <modules/server/include/jsonconverters.h>
|
||||
#include <openspace/engine/globals.h>
|
||||
#include <openspace/scene/profile.h>
|
||||
|
||||
namespace openspace {
|
||||
|
||||
bool ProfileTopic::isDone() const {
|
||||
return true;
|
||||
}
|
||||
|
||||
void ProfileTopic::handleJson(const nlohmann::json&) {
|
||||
const nlohmann::json data = {
|
||||
{ "uiPanelVisibility", global::profile->uiPanelVisibility },
|
||||
{ "markNodes", global::profile->markNodes }
|
||||
};
|
||||
_connection->sendJson(wrappedPayload(data));
|
||||
}
|
||||
|
||||
} // namespace openspace
|
||||
@@ -208,12 +208,25 @@ namespace {
|
||||
if (e.find('.') == std::string::npos) {
|
||||
e += ".0";
|
||||
}
|
||||
// @TODO(abock, 2024-05-20) 'd' suffix is needed until scnlib updates to v3
|
||||
auto res = scn::scan<int, double>(e, "{:2d}{}");
|
||||
if (!res) {
|
||||
if (e.size() <= 2) {
|
||||
throw ghoul::RuntimeError(
|
||||
std::format("Error parsing epoch '{}'. Invalid date string", epoch)
|
||||
);
|
||||
}
|
||||
|
||||
std::string_view yearStr = std::string_view(e).substr(0, 2);
|
||||
std::string_view daysInYearStr = std::string_view(e).substr(2);
|
||||
auto resYear = scn::scan<int>(yearStr, "{}");
|
||||
if (!resYear) {
|
||||
throw ghoul::RuntimeError(std::format("Error parsing epoch '{}'", epoch));
|
||||
}
|
||||
auto [year, daysInYear] = res->values();
|
||||
int year = resYear->value();
|
||||
|
||||
auto resDaysInYear = scn::scan<double>(daysInYearStr, "{}");
|
||||
if (!resDaysInYear) {
|
||||
throw ghoul::RuntimeError(std::format("Error parsing epoch '{}'", epoch));
|
||||
}
|
||||
double daysInYear = resDaysInYear->value();
|
||||
year += year > 57 ? 1900 : 2000;
|
||||
const int daysSince2000 = countDays(year);
|
||||
|
||||
@@ -336,9 +349,8 @@ namespace {
|
||||
// We have the first form
|
||||
int month = 0;
|
||||
int days = 0;
|
||||
// @TODO(abock, 2024-05-20) 'd' suffix is needed until scnlib updates to v3
|
||||
auto res = scn::scan<int, int, int, int, int, double>(
|
||||
epoch, "{:4d}-{:2d}-{:2d}T{:2d}:{:2d}:{}"
|
||||
epoch, "{:4}-{:2}-{:2}T{:2}:{:2}:{}"
|
||||
);
|
||||
if (!res) {
|
||||
throw ghoul::RuntimeError(std::format("Error parsing epoch '{}'", epoch));
|
||||
@@ -350,9 +362,8 @@ namespace {
|
||||
else if (pos == 8) {
|
||||
// We have the second form
|
||||
|
||||
// @TODO(abock, 2024-05-20) 'd' suffix is needed until scnlib updates to v3
|
||||
auto res = scn::scan<int, int, int, int, double>(
|
||||
epoch, "{:4d}-{:3d}T{:2d}:{:2d}:{}"
|
||||
epoch, "{:4}-{:3}T{:2}:{:2}:{}"
|
||||
//date.year, date.nDays, date.hours, date.minutes, date.seconds
|
||||
);
|
||||
if (!res) {
|
||||
|
||||
@@ -298,9 +298,9 @@ documentation::Documentation RenderableFluxNodes::Documentation() {
|
||||
RenderableFluxNodes::RenderableFluxNodes(const ghoul::Dictionary& dictionary)
|
||||
: Renderable(dictionary)
|
||||
, _earthdistGroup({ "Earthfocus" })
|
||||
, _goesEnergyBins(GoesEnergyBinsInfo, properties::OptionProperty::DisplayType::Radio)
|
||||
, _goesEnergyBins(GoesEnergyBinsInfo)
|
||||
, _styleGroup({ "Style" })
|
||||
, _colorMode(ColorModeInfo, properties::OptionProperty::DisplayType::Radio)
|
||||
, _colorMode(ColorModeInfo)
|
||||
, _streamColor(
|
||||
StreamColorInfo,
|
||||
glm::vec4(0.96f, 0.88f, 0.8f, 1.f),
|
||||
@@ -311,7 +311,7 @@ RenderableFluxNodes::RenderableFluxNodes(const ghoul::Dictionary& dictionary)
|
||||
, _colorTableRange(colorTableRangeInfo, { -2.f, 4.f }, { -8.f, -8.f }, { 8.f, 8.f })
|
||||
, _fluxColorAlpha(FluxColorAlphaInfo, 1.f, 0.f, 1.f)
|
||||
, _streamGroup({ "Streams" })
|
||||
, _scalingMethod(ScalingmethodInfo, properties::OptionProperty::DisplayType::Radio)
|
||||
, _scalingMethod(ScalingmethodInfo)
|
||||
, _nodesAmountGroup({ "NodeGroup" })
|
||||
, _nodeSize(NodeSizeInfo, 2.f, 1.f, 10.f)
|
||||
, _distanceThreshold(DistanceThresholdInfo, 0.f, 0.f, 1.f)
|
||||
@@ -323,7 +323,7 @@ RenderableFluxNodes::RenderableFluxNodes(const ghoul::Dictionary& dictionary)
|
||||
, _filteringLower(FilteringInfo, 0.f, 0.f, 5.f)
|
||||
, _filteringUpper(FilteringUpperInfo, 5.f, 0.f, 5.f)
|
||||
, _amountofNodes(AmountofNodesInfo, 1, 1, 100)
|
||||
, _nodeskipMethod(NodeskipMethodInfo, properties::OptionProperty::DisplayType::Radio)
|
||||
, _nodeskipMethod(NodeskipMethodInfo)
|
||||
, _defaultNodeSkip(DefaultNodeSkipInfo, 1, 1, 100)
|
||||
, _fluxNodeskipThreshold(FluxNodeskipThresholdInfo, 0, -20, 10)
|
||||
, _earthNodeSkip(EarthNodeSkipInfo, 1, 1, 100)
|
||||
|
||||
@@ -258,10 +258,7 @@ RenderableOrbitalKepler::Appearance::Appearance()
|
||||
, pointSizeExponent(PointSizeExponentInfo, 1.0f, 0.f, 11.f)
|
||||
, enableMaxSize(EnableMaxSizeInfo, true)
|
||||
, maxSize(MaxSizeInfo, 5.f, 0.f, 45.f)
|
||||
, renderingModes(
|
||||
RenderingModeInfo,
|
||||
properties::OptionProperty::DisplayType::Dropdown
|
||||
)
|
||||
, renderingModes(RenderingModeInfo)
|
||||
, trailFade(TrailFadeInfo, 20.f, 0.f, 30.f)
|
||||
, enableOutline(EnableOutlineInfo, true)
|
||||
, outlineColor(OutlineColorInfo, glm::vec3(0.f), glm::vec3(0.f), glm::vec3(1.f))
|
||||
|
||||
@@ -450,11 +450,8 @@ RenderableStars::RenderableStars(const ghoul::Dictionary& dictionary)
|
||||
properties::StringProperty(MappingVzInfo),
|
||||
properties::StringProperty(MappingSpeedInfo)
|
||||
}
|
||||
, _colorOption(ColorOptionInfo, properties::OptionProperty::DisplayType::Dropdown)
|
||||
, _otherDataOption(
|
||||
OtherDataOptionInfo,
|
||||
properties::OptionProperty::DisplayType::Dropdown
|
||||
)
|
||||
, _colorOption(ColorOptionInfo)
|
||||
, _otherDataOption(OtherDataOptionInfo)
|
||||
, _otherDataColorMapPath(OtherDataColorMapInfo)
|
||||
, _otherDataRange(
|
||||
OtherDataValueRangeInfo,
|
||||
@@ -484,10 +481,7 @@ RenderableStars::RenderableStars(const ghoul::Dictionary& dictionary)
|
||||
}
|
||||
, _parameters {
|
||||
properties::PropertyOwner(SizeCompositionInfo),
|
||||
properties::OptionProperty(
|
||||
SizeCompositionMethodInfo,
|
||||
properties::OptionProperty::DisplayType::Dropdown
|
||||
),
|
||||
properties::OptionProperty(SizeCompositionMethodInfo),
|
||||
properties::FloatProperty(LumPercentInfo, 0.5f, 0.f, 3.f),
|
||||
properties::FloatProperty(RadiusPercentInfo, 0.5f, 0.f, 3.f)
|
||||
}
|
||||
@@ -614,7 +608,7 @@ RenderableStars::RenderableStars(const ghoul::Dictionary& dictionary)
|
||||
_useProperMotion = p.useProperMotion.value_or(_useProperMotion);
|
||||
addProperty(_useProperMotion);
|
||||
|
||||
|
||||
|
||||
_properMotionEpoch = p.properMotionEpoch.value_or(_properMotionEpoch);
|
||||
addProperty(_properMotionEpoch);
|
||||
|
||||
|
||||
@@ -157,10 +157,7 @@ RenderableShadowCylinder::RenderableShadowCylinder(const ghoul::Dictionary& dict
|
||||
, _numberOfPoints(NumberPointsInfo, 190, 1, 300)
|
||||
, _shadowLength(ShadowLengthInfo, 0.1f, 0.f, 0.5f)
|
||||
, _shadowColor(ShadowColorInfo, glm::vec3(1.f), glm::vec3(0.f), glm::vec3(1.f))
|
||||
, _terminatorType(
|
||||
TerminatorTypeInfo,
|
||||
properties::OptionProperty::DisplayType::Dropdown
|
||||
)
|
||||
, _terminatorType(TerminatorTypeInfo)
|
||||
, _lightSource(LightSourceInfo)
|
||||
, _observer(ObserverInfo)
|
||||
, _body(BodyInfo)
|
||||
|
||||
@@ -173,7 +173,7 @@ documentation::Documentation RenderableTimeVaryingVolume::Documentation() {
|
||||
RenderableTimeVaryingVolume::RenderableTimeVaryingVolume(
|
||||
const ghoul::Dictionary& dictionary)
|
||||
: Renderable(dictionary)
|
||||
, _gridType(GridTypeInfo, properties::OptionProperty::DisplayType::Dropdown)
|
||||
, _gridType(GridTypeInfo)
|
||||
, _stepSize(StepSizeInfo, 0.02f, 0.001f, 0.1f)
|
||||
, _brightness(BrightnessInfo, 0.33f, 0.f, 1.f)
|
||||
, _rNormalization(rNormalizationInfo, 0.f, 0.f, 2.f)
|
||||
|
||||
@@ -38,7 +38,7 @@ set(PROJECT_ARCH "x86_64")
|
||||
# reserved. Use of this source code is governed by a BSD-style license that
|
||||
# can be found in the LICENSE file.
|
||||
|
||||
cmake_minimum_required(VERSION 2.8.12.1)
|
||||
cmake_minimum_required(VERSION 3.10)
|
||||
|
||||
# Use folders in the resulting project files.
|
||||
set_property(GLOBAL PROPERTY OS_FOLDERS ON)
|
||||
|
||||
@@ -128,10 +128,7 @@ namespace openspace::interaction {
|
||||
|
||||
PathNavigator::PathNavigator()
|
||||
: properties::PropertyOwner({ "PathNavigator", "Path Navigator" })
|
||||
, _defaultPathType(
|
||||
DefaultCurveOptionInfo,
|
||||
properties::OptionProperty::DisplayType::Dropdown
|
||||
)
|
||||
, _defaultPathType(DefaultCurveOptionInfo)
|
||||
, _includeRoll(IncludeRollInfo, false)
|
||||
, _speedScale(SpeedScaleInfo, 1.f, 0.01f, 2.f)
|
||||
, _applyIdleBehaviorOnFinish(IdleBehaviorOnFinishInfo, false)
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
/*****************************************************************************************
|
||||
|
||||
* *
|
||||
* OpenSpace *
|
||||
* *
|
||||
@@ -32,6 +31,26 @@
|
||||
|
||||
namespace {
|
||||
constexpr std::string_view _loggerCat = "OptionProperty";
|
||||
|
||||
using Option = openspace::properties::OptionProperty::Option;
|
||||
|
||||
bool addOptionInternal(int value, std::string desc, std::vector<Option>& options) {
|
||||
Option option = { .value = value, .description = std::move(desc) };
|
||||
|
||||
for (const Option& o : options) {
|
||||
if (o.value == option.value) {
|
||||
LWARNING(std::format(
|
||||
"The value of option {{ {} -> {} }} was already registered when "
|
||||
"trying to add option {{ {} -> {} }}",
|
||||
o.value, o.description, option.value, option.description
|
||||
|
||||
));
|
||||
return false;
|
||||
}
|
||||
}
|
||||
options.push_back(std::move(option));
|
||||
return true;
|
||||
}
|
||||
} // namespace
|
||||
|
||||
namespace openspace::properties {
|
||||
@@ -46,18 +65,6 @@ OptionProperty::OptionProperty(PropertyInfo info)
|
||||
std::numeric_limits<int>::max(),
|
||||
1
|
||||
)
|
||||
, _displayType(DisplayType::Radio)
|
||||
{}
|
||||
|
||||
OptionProperty::OptionProperty(PropertyInfo info, DisplayType displayType)
|
||||
: NumericalProperty<int>(
|
||||
std::move(info),
|
||||
0,
|
||||
std::numeric_limits<int>::lowest(),
|
||||
std::numeric_limits<int>::max(),
|
||||
1
|
||||
)
|
||||
, _displayType(displayType)
|
||||
{}
|
||||
|
||||
std::string_view OptionProperty::className() const {
|
||||
@@ -70,48 +77,37 @@ ghoul::lua::LuaTypes OptionProperty::typeLua() const {
|
||||
);
|
||||
}
|
||||
|
||||
OptionProperty::DisplayType OptionProperty::displayType() const {
|
||||
return _displayType;
|
||||
}
|
||||
|
||||
const std::vector<OptionProperty::Option>& OptionProperty::options() const {
|
||||
return _options;
|
||||
}
|
||||
|
||||
void OptionProperty::addOption(int value, std::string desc) {
|
||||
Option option = { .value = value, .description = std::move(desc) };
|
||||
|
||||
for (const Option& o : _options) {
|
||||
if (o.value == option.value) {
|
||||
LWARNING(std::format(
|
||||
"The value of option {{ {} -> {} }} was already registered when trying "
|
||||
"to add option {{ {} -> {} }}",
|
||||
o.value, o.description, option.value, option.description
|
||||
|
||||
));
|
||||
return;
|
||||
}
|
||||
void OptionProperty::addOption(int value, std::string description) {
|
||||
bool success = addOptionInternal(value, description, _options);
|
||||
if (success) {
|
||||
// Set default value to option added first
|
||||
NumericalProperty::setValue(_options[0].value);
|
||||
}
|
||||
_options.push_back(std::move(option));
|
||||
// Set default value to option added first
|
||||
NumericalProperty::setValue(_options[0].value);
|
||||
}
|
||||
|
||||
void OptionProperty::addOptions(std::vector<std::pair<int, std::string>> options) {
|
||||
for (std::pair<int, std::string>& p : options) {
|
||||
addOption(p.first, std::move(p.second));
|
||||
addOptionInternal(p.first, std::move(p.second), _options);
|
||||
}
|
||||
// Set default value to option added first
|
||||
NumericalProperty::setValue(_options[0].value);
|
||||
}
|
||||
|
||||
void OptionProperty::addOptions(std::vector<std::string> options) {
|
||||
for (int i = 0; i < static_cast<int>(options.size()); i++) {
|
||||
addOption(i, std::move(options[i]));
|
||||
addOptionInternal(i, std::move(options[i]), _options);
|
||||
}
|
||||
// Set default value to option added first
|
||||
NumericalProperty::setValue(_options[0].value);
|
||||
}
|
||||
|
||||
void OptionProperty::clearOptions() {
|
||||
NumericalProperty::setValue(0);
|
||||
_options.clear();
|
||||
_value = 0;
|
||||
}
|
||||
|
||||
void OptionProperty::setValue(int value) {
|
||||
|
||||
@@ -302,7 +302,8 @@ void PropertyOwner::addPropertySubOwner(openspace::properties::PropertyOwner* ow
|
||||
const bool hasProp = hasProperty(owner->identifier());
|
||||
if (hasProp) {
|
||||
LERROR(std::format(
|
||||
"PropertyOwner '{}'s name already names a Property", owner->identifier()
|
||||
"PropertyOwner '{}'s identifier is already in use for a Property",
|
||||
owner->identifier()
|
||||
));
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -35,34 +35,30 @@ namespace {
|
||||
constexpr openspace::properties::Property::PropertyInfo EnabledInfo = {
|
||||
"Enabled",
|
||||
"Color Map Enabled",
|
||||
"If this value is set to 'true', the provided color map is used (if one was "
|
||||
"provided in the configuration). If no color map was provided, changing this "
|
||||
"setting does not do anything.",
|
||||
"Decides if the color mapping should be used or not.",
|
||||
openspace::properties::Property::Visibility::NoviceUser
|
||||
};
|
||||
|
||||
constexpr openspace::properties::Property::PropertyInfo FileInfo = {
|
||||
"File",
|
||||
"Color Map File",
|
||||
"The path to the color map file to use for coloring the points.",
|
||||
"The path to the color map file to use. Should be a .cmap file",
|
||||
openspace::properties::Property::Visibility::AdvancedUser
|
||||
};
|
||||
|
||||
constexpr openspace::properties::Property::PropertyInfo ParameterInfo = {
|
||||
"Parameter",
|
||||
"Parameter",
|
||||
"This value determines which paramenter is used for coloring the points based "
|
||||
"on the color map. The property is set based on predefined options specified in "
|
||||
"the asset file. When changing the parameter, the value range to used for the"
|
||||
"mapping will also be changed. Per default, it is set to the last parameter in "
|
||||
"the list of options.",
|
||||
"The paramenter in the dataset to use for the color mapping. On change, the "
|
||||
"value range to used for the mapping will also be changed.",
|
||||
openspace::properties::Property::Visibility::User
|
||||
};
|
||||
|
||||
constexpr openspace::properties::Property::PropertyInfo RangeInfo = {
|
||||
"ValueRange",
|
||||
"Value Range",
|
||||
"This value changes the range of values to be mapped with the current color map.",
|
||||
"The range of values to use in the color mapping. The lowest value will be "
|
||||
"mapped to the first color in the color map.",
|
||||
openspace::properties::Property::Visibility::User
|
||||
};
|
||||
|
||||
@@ -150,30 +146,55 @@ namespace {
|
||||
openspace::properties::Property::Visibility::AdvancedUser
|
||||
};
|
||||
|
||||
// This component handles settings for dynamic color mapping of data points based on
|
||||
// the columns in a dataset. It is for example utilized by the
|
||||
// [RenderablePointCloud](#base_renderablepointcloud) renderable type.
|
||||
//
|
||||
// The option for the parameters will be initialized based on the dataset used for
|
||||
// the specific renderable. The value range will be set based on the min and max
|
||||
// values for the respective column in the dataset, but can be manually adjusted.
|
||||
// Per default, all columns will be loaded, but this can also be adjusted.
|
||||
//
|
||||
// In addition to specifying a color map (.cmap) file and changing the parameter used
|
||||
// for determining the color, this component includes features such as:
|
||||
//
|
||||
// - Inverting the color map
|
||||
//
|
||||
// - Handling colors for missing data values (or hiding these data points)
|
||||
//
|
||||
// - Handling colors for values outside the provided range
|
||||
//
|
||||
// - Predefining which parameters to load from the dataset, and the range of values
|
||||
// to use for color mapping
|
||||
struct [[codegen::Dictionary(ColorMappingComponent)]] Parameters {
|
||||
// [[codegen::verbatim(EnabledInfo.description)]]
|
||||
std::optional<bool> enabled;
|
||||
|
||||
// [[codegen::verbatim(FileInfo.description)]]
|
||||
std::optional<std::filesystem::path> file;
|
||||
std::filesystem::path file;
|
||||
|
||||
struct ColorMapParameter {
|
||||
// The key for the data variable to use for color
|
||||
// The key for the data variable to use for color.
|
||||
std::string key;
|
||||
|
||||
// An optional value range to use for coloring when this option is selected.
|
||||
// If not included, the range will be set from the min and max value in the
|
||||
// dataset
|
||||
// dataset.
|
||||
std::optional<glm::vec2> range;
|
||||
};
|
||||
// A list of options for color parameters to use for color mapping, that will
|
||||
// appear as options in the drop-down menu in the user interface. Per default,
|
||||
// the first option in the list is selected. Each option is a table in the form
|
||||
// { Key = \"theKey\", Range = {min, max} }, where the value range is optional.
|
||||
// If added, this range will automatically be set when the option is selected
|
||||
// A list of options for parameters to use for color mapping that will appear
|
||||
// as options in the drop-down menu in the user interface. Per default, the
|
||||
// first option in the list is selected.
|
||||
//
|
||||
// Each option is a table in the form
|
||||
// `{ Key = \"dataColumn\", Range = {min, max} }`, where the `Range` is optional.
|
||||
// The specified range (or the min/max values for this data column) will be used
|
||||
// for color mapping when the option is selected.
|
||||
std::optional<std::vector<ColorMapParameter>> parameterOptions;
|
||||
|
||||
// [[codegen::verbatim(ParameterInfo.description)]]
|
||||
// The default parameter to use for the color map. The options for this parameter
|
||||
// are either loaded from the dataset or provided in the `ParameterOptions` list.
|
||||
// This value can be changed dynamically in the user interface.
|
||||
std::optional<std::string> parameter;
|
||||
|
||||
// [[codegen::verbatim(RangeInfo.description)]]
|
||||
@@ -216,7 +237,7 @@ ColorMappingComponent::ColorMappingComponent()
|
||||
: properties::PropertyOwner({ "ColorMapping", "Color Mapping", "" })
|
||||
, enabled(EnabledInfo, true)
|
||||
, invert(InvertColorMapInfo, false)
|
||||
, dataColumn(ParameterInfo, properties::OptionProperty::DisplayType::Dropdown)
|
||||
, dataColumn(ParameterInfo)
|
||||
, colorMapFile(FileInfo)
|
||||
, valueRange(RangeInfo, glm::vec2(0.f))
|
||||
, setRangeFromData(SetRangeFromDataInfo)
|
||||
@@ -318,9 +339,7 @@ ColorMappingComponent::ColorMappingComponent(const ghoul::Dictionary& dictionary
|
||||
_hasBelowRangeColorInAsset = true;
|
||||
}
|
||||
|
||||
if (p.file.has_value()) {
|
||||
colorMapFile = p.file->string();
|
||||
}
|
||||
colorMapFile = p.file.string();
|
||||
|
||||
invert = p.invert.value_or(invert);
|
||||
}
|
||||
|
||||
@@ -42,13 +42,20 @@ namespace {
|
||||
openspace::properties::Property::Visibility::AdvancedUser
|
||||
};
|
||||
|
||||
// This is the base class of all `LightSource` types, which are components that can be
|
||||
// added to certain `Renderable` types to add lighting effects.
|
||||
//
|
||||
// A `LightSource`, in this case, is just a table that describes properties such as
|
||||
// the location of the light. It _does not physically exist in the scene_, and the
|
||||
// table of parameters have to be added to each `Renderable` that should be affected
|
||||
// by the light source. This is commonly done by exporting a light source table from
|
||||
// an Asset file that represents an illuminating object in the scene, such as the Sun
|
||||
// in our solar system.
|
||||
struct [[codegen::Dictionary(LightSource)]] Parameters {
|
||||
// The type of the light source that is described in this element. The available
|
||||
// types of light sources depend on the configuration of the application and can
|
||||
// be written to disk on application startup into the FactoryDocumentation
|
||||
std::string type [[codegen::annotation("Must name a valid LightSource type")]];
|
||||
// The type of light source that is described in this element.
|
||||
std::string type [[codegen::annotation("Must name a valid `LightSource` type")]];
|
||||
|
||||
// The identifier of the light source
|
||||
// The identifier of the light source.
|
||||
std::string identifier [[codegen::identifier()]];
|
||||
|
||||
// [[codegen::verbatim(EnabledInfo.description)]]
|
||||
|
||||
@@ -623,6 +623,15 @@ void convertVersion12to13(nlohmann::json& profile) {
|
||||
|
||||
} // namespace version12
|
||||
|
||||
namespace version13 {
|
||||
|
||||
void convertVersion13to14(nlohmann::json& profile) {
|
||||
// Version 1.4 introduced the ui panel view
|
||||
profile["version"] = Profile::Version{ 1, 4 };
|
||||
}
|
||||
|
||||
} // namespace version13
|
||||
|
||||
Profile::ParsingError::ParsingError(Severity severity_, std::string msg)
|
||||
: ghoul::RuntimeError(std::move(msg), "profile")
|
||||
, severity(severity_)
|
||||
@@ -737,6 +746,9 @@ std::string Profile::serialize() const {
|
||||
if (!additionalScripts.empty()) {
|
||||
r["additional_scripts"] = additionalScripts;
|
||||
}
|
||||
if (!uiPanelVisibility.empty()) {
|
||||
r["panel_visibility"] = uiPanelVisibility;
|
||||
}
|
||||
|
||||
return r.dump(2);
|
||||
}
|
||||
@@ -779,6 +791,11 @@ Profile::Profile(const std::filesystem::path& path) {
|
||||
profile["version"].get_to(version);
|
||||
}
|
||||
|
||||
if (version.major == 1 && version.minor == 3) {
|
||||
version13::convertVersion13to14(profile);
|
||||
profile["version"].get_to(version);
|
||||
}
|
||||
|
||||
|
||||
if (profile.find("modules") != profile.end()) {
|
||||
profile["modules"].get_to(modules);
|
||||
@@ -827,6 +844,9 @@ Profile::Profile(const std::filesystem::path& path) {
|
||||
if (profile.find("additional_scripts") != profile.end()) {
|
||||
profile["additional_scripts"].get_to(additionalScripts);
|
||||
}
|
||||
if (profile.find("panel_visibility") != profile.end()) {
|
||||
profile["panel_visibility"].get_to(uiPanelVisibility);
|
||||
}
|
||||
}
|
||||
catch (const nlohmann::json::exception& e) {
|
||||
std::string err = e.what();
|
||||
|
||||
@@ -32,6 +32,7 @@
|
||||
#include <openspace/scene/profile.h>
|
||||
#include <openspace/scene/sceneinitializer.h>
|
||||
#include <openspace/scripting/scriptengine.h>
|
||||
#include <openspace/util/updatestructures.h>
|
||||
#include <ghoul/lua/lua_helper.h>
|
||||
#include <stack>
|
||||
|
||||
|
||||
@@ -195,7 +195,7 @@ namespace {
|
||||
};
|
||||
|
||||
constexpr openspace::properties::Property::PropertyInfo GuiFocusableInfo = {
|
||||
"IsFocusable",
|
||||
"Focusable",
|
||||
"Focusable Hint",
|
||||
"This value serves as a hint to determine if it makes sense to focus the camera "
|
||||
"on this scene graph node. It only serves as a hint and does not actually "
|
||||
@@ -924,7 +924,7 @@ void SceneGraphNode::renderDebugSphere(const Camera& camera, double size,
|
||||
void SceneGraphNode::setParent(SceneGraphNode& parent) {
|
||||
ghoul_assert(_parent != nullptr, "Node must be attached to a parent");
|
||||
|
||||
parent.attachChild(_parent->detachChild(*this));
|
||||
_parent = &parent;
|
||||
}
|
||||
|
||||
void SceneGraphNode::attachChild(ghoul::mm_unique_ptr<SceneGraphNode> child) {
|
||||
|
||||
116
tests/profile/conversion/version_10.profile
Normal file
116
tests/profile/conversion/version_10.profile
Normal file
@@ -0,0 +1,116 @@
|
||||
{
|
||||
"version": { "major": 1, "minor": 0 },
|
||||
"meta": {
|
||||
"name": "name",
|
||||
"version": "version",
|
||||
"description": "description",
|
||||
"author": "author",
|
||||
"url": "url",
|
||||
"license": "license"
|
||||
},
|
||||
"modules": [
|
||||
{ "name": "abs-module" },
|
||||
{
|
||||
"name": "def-module",
|
||||
"loadedInstruction": "instr"
|
||||
},
|
||||
{
|
||||
"name": "ghi-module",
|
||||
"notLoadedInstruction": "not_instr"
|
||||
},
|
||||
{
|
||||
"name": "jkl-module",
|
||||
"loadedInstruction": "instr",
|
||||
"notLoadedInstruction": "not_instr"
|
||||
}
|
||||
],
|
||||
"assets": [
|
||||
"scene/solarsystem/planets/earth/earth",
|
||||
"scene/solarsystem/planets/earth/satellites/satellites",
|
||||
"folder1/folder2/asset",
|
||||
"folder3/folder4/asset2",
|
||||
"folder5/folder6/asset3"
|
||||
],
|
||||
"properties": [
|
||||
{
|
||||
"type": "setPropertyValue",
|
||||
"name": "{earth_satellites}.Renderable.Enabled",
|
||||
"value": "false"
|
||||
},
|
||||
{
|
||||
"type": "setPropertyValue",
|
||||
"name": "property_name_1",
|
||||
"value": "property_value_1"
|
||||
},
|
||||
{
|
||||
"type": "setPropertyValue",
|
||||
"name": "property_name_2",
|
||||
"value": "property_value_2"
|
||||
},
|
||||
{
|
||||
"type": "setPropertyValue",
|
||||
"name": "property_name_3",
|
||||
"value": "property_value_3"
|
||||
},
|
||||
{
|
||||
"type": "setPropertyValueSingle",
|
||||
"name": "property_name_4",
|
||||
"value": "property_value_4"
|
||||
},
|
||||
{
|
||||
"type": "setPropertyValueSingle",
|
||||
"name": "property_name_5",
|
||||
"value": "property_value_5"
|
||||
},
|
||||
{
|
||||
"type": "setPropertyValueSingle",
|
||||
"name": "property_name_6",
|
||||
"value": "property_value_6"
|
||||
}
|
||||
],
|
||||
"keybindings": [
|
||||
{
|
||||
"key": "T",
|
||||
"documentation": "T documentation",
|
||||
"name": "T name",
|
||||
"gui_path": "T Gui-Path",
|
||||
"is_local": true,
|
||||
"script": "T script"
|
||||
},
|
||||
{
|
||||
"key": "U",
|
||||
"documentation": "U documentation",
|
||||
"name": "U name",
|
||||
"gui_path": "U Gui-Path",
|
||||
"is_local": false,
|
||||
"script": "U script"
|
||||
},
|
||||
{
|
||||
"key": "CTRL+V",
|
||||
"documentation": "CTRL+V documentation",
|
||||
"name": "CTRL+V name",
|
||||
"gui_path": "CTRL+V Gui-Path",
|
||||
"is_local": false,
|
||||
"script": "CTRL+V script"
|
||||
}
|
||||
],
|
||||
"time": {
|
||||
"type": "relative",
|
||||
"value": "-1d"
|
||||
},
|
||||
"camera": {
|
||||
"type": "goToGeo",
|
||||
"anchor": "Earth",
|
||||
"latitude": 58.5877,
|
||||
"longitude": 16.1924,
|
||||
"altitude": 2.0e+07
|
||||
},
|
||||
"mark_nodes": [
|
||||
"Earth", "Mars", "Moon", "Sun"
|
||||
],
|
||||
"additional_scripts": [
|
||||
"script-1",
|
||||
"script-2",
|
||||
"script-3"
|
||||
]
|
||||
}
|
||||
130
tests/profile/conversion/version_11.profile
Normal file
130
tests/profile/conversion/version_11.profile
Normal file
@@ -0,0 +1,130 @@
|
||||
{
|
||||
"version": { "major": 1, "minor": 1 },
|
||||
"meta": {
|
||||
"name": "name",
|
||||
"version": "version",
|
||||
"description": "description",
|
||||
"author": "author",
|
||||
"url": "url",
|
||||
"license": "license"
|
||||
},
|
||||
"modules": [
|
||||
{ "name": "abs-module" },
|
||||
{
|
||||
"name": "def-module",
|
||||
"loadedInstruction": "instr"
|
||||
},
|
||||
{
|
||||
"name": "ghi-module",
|
||||
"notLoadedInstruction": "not_instr"
|
||||
},
|
||||
{
|
||||
"name": "jkl-module",
|
||||
"loadedInstruction": "instr",
|
||||
"notLoadedInstruction": "not_instr"
|
||||
}
|
||||
],
|
||||
"assets": [
|
||||
"scene/solarsystem/planets/earth/earth",
|
||||
"scene/solarsystem/planets/earth/satellites/satellites",
|
||||
"folder1/folder2/asset",
|
||||
"folder3/folder4/asset2",
|
||||
"folder5/folder6/asset3"
|
||||
],
|
||||
"properties": [
|
||||
{
|
||||
"type": "setPropertyValue",
|
||||
"name": "{earth_satellites}.Renderable.Enabled",
|
||||
"value": "false"
|
||||
},
|
||||
{
|
||||
"type": "setPropertyValue",
|
||||
"name": "property_name_1",
|
||||
"value": "property_value_1"
|
||||
},
|
||||
{
|
||||
"type": "setPropertyValue",
|
||||
"name": "property_name_2",
|
||||
"value": "property_value_2"
|
||||
},
|
||||
{
|
||||
"type": "setPropertyValue",
|
||||
"name": "property_name_3",
|
||||
"value": "property_value_3"
|
||||
},
|
||||
{
|
||||
"type": "setPropertyValueSingle",
|
||||
"name": "property_name_4",
|
||||
"value": "property_value_4"
|
||||
},
|
||||
{
|
||||
"type": "setPropertyValueSingle",
|
||||
"name": "property_name_5",
|
||||
"value": "property_value_5"
|
||||
},
|
||||
{
|
||||
"type": "setPropertyValueSingle",
|
||||
"name": "property_name_6",
|
||||
"value": "property_value_6"
|
||||
}
|
||||
],
|
||||
"actions": [
|
||||
{
|
||||
"identifier": "profile.keybind.0",
|
||||
"documentation": "T documentation",
|
||||
"name": "T name",
|
||||
"gui_path": "T Gui-Path",
|
||||
"is_local": true,
|
||||
"script": "T script"
|
||||
},
|
||||
{
|
||||
"identifier": "profile.keybind.1",
|
||||
"documentation": "U documentation",
|
||||
"name": "U name",
|
||||
"gui_path": "U Gui-Path",
|
||||
"is_local": false,
|
||||
"script": "U script"
|
||||
},
|
||||
{
|
||||
"identifier": "profile.keybind.2",
|
||||
"documentation": "CTRL+V documentation",
|
||||
"name": "CTRL+V name",
|
||||
"gui_path": "CTRL+V Gui-Path",
|
||||
"is_local": false,
|
||||
"script": "CTRL+V script"
|
||||
}
|
||||
],
|
||||
"keybindings": [
|
||||
{
|
||||
"action": "profile.keybind.0",
|
||||
"key": "T"
|
||||
},
|
||||
{
|
||||
"action": "profile.keybind.1",
|
||||
"key": "U"
|
||||
},
|
||||
{
|
||||
"action": "profile.keybind.2",
|
||||
"key": "CTRL+V"
|
||||
}
|
||||
],
|
||||
"time": {
|
||||
"type": "relative",
|
||||
"value": "-1d"
|
||||
},
|
||||
"camera": {
|
||||
"type": "goToGeo",
|
||||
"anchor": "Earth",
|
||||
"latitude": 58.5877,
|
||||
"longitude": 16.1924,
|
||||
"altitude": 2.0e+07
|
||||
},
|
||||
"mark_nodes": [
|
||||
"Earth", "Mars", "Moon", "Sun"
|
||||
],
|
||||
"additional_scripts": [
|
||||
"script-1",
|
||||
"script-2",
|
||||
"script-3"
|
||||
]
|
||||
}
|
||||
131
tests/profile/conversion/version_12.profile
Normal file
131
tests/profile/conversion/version_12.profile
Normal file
@@ -0,0 +1,131 @@
|
||||
{
|
||||
"version": { "major": 1, "minor": 2 },
|
||||
"meta": {
|
||||
"name": "name",
|
||||
"version": "version",
|
||||
"description": "description",
|
||||
"author": "author",
|
||||
"url": "url",
|
||||
"license": "license"
|
||||
},
|
||||
"modules": [
|
||||
{ "name": "abs-module" },
|
||||
{
|
||||
"name": "def-module",
|
||||
"loadedInstruction": "instr"
|
||||
},
|
||||
{
|
||||
"name": "ghi-module",
|
||||
"notLoadedInstruction": "not_instr"
|
||||
},
|
||||
{
|
||||
"name": "jkl-module",
|
||||
"loadedInstruction": "instr",
|
||||
"notLoadedInstruction": "not_instr"
|
||||
}
|
||||
],
|
||||
"assets": [
|
||||
"scene/solarsystem/planets/earth/earth",
|
||||
"scene/solarsystem/planets/earth/satellites/satellites",
|
||||
"folder1/folder2/asset",
|
||||
"folder3/folder4/asset2",
|
||||
"folder5/folder6/asset3"
|
||||
],
|
||||
"properties": [
|
||||
{
|
||||
"type": "setPropertyValue",
|
||||
"name": "{earth_satellites}.Renderable.Enabled",
|
||||
"value": "false"
|
||||
},
|
||||
{
|
||||
"type": "setPropertyValue",
|
||||
"name": "property_name_1",
|
||||
"value": "property_value_1"
|
||||
},
|
||||
{
|
||||
"type": "setPropertyValue",
|
||||
"name": "property_name_2",
|
||||
"value": "property_value_2"
|
||||
},
|
||||
{
|
||||
"type": "setPropertyValue",
|
||||
"name": "property_name_3",
|
||||
"value": "property_value_3"
|
||||
},
|
||||
{
|
||||
"type": "setPropertyValueSingle",
|
||||
"name": "property_name_4",
|
||||
"value": "property_value_4"
|
||||
},
|
||||
{
|
||||
"type": "setPropertyValueSingle",
|
||||
"name": "property_name_5",
|
||||
"value": "property_value_5"
|
||||
},
|
||||
{
|
||||
"type": "setPropertyValueSingle",
|
||||
"name": "property_name_6",
|
||||
"value": "property_value_6"
|
||||
}
|
||||
],
|
||||
"actions": [
|
||||
{
|
||||
"identifier": "profile.keybind.0",
|
||||
"documentation": "T documentation",
|
||||
"name": "T name",
|
||||
"gui_path": "T Gui-Path",
|
||||
"is_local": true,
|
||||
"script": "T script"
|
||||
},
|
||||
{
|
||||
"identifier": "profile.keybind.1",
|
||||
"documentation": "U documentation",
|
||||
"name": "U name",
|
||||
"gui_path": "U Gui-Path",
|
||||
"is_local": false,
|
||||
"script": "U script"
|
||||
},
|
||||
{
|
||||
"identifier": "profile.keybind.2",
|
||||
"documentation": "CTRL+V documentation",
|
||||
"name": "CTRL+V name",
|
||||
"gui_path": "CTRL+V Gui-Path",
|
||||
"is_local": false,
|
||||
"script": "CTRL+V script"
|
||||
}
|
||||
],
|
||||
"keybindings": [
|
||||
{
|
||||
"action": "profile.keybind.0",
|
||||
"key": "T"
|
||||
},
|
||||
{
|
||||
"action": "profile.keybind.1",
|
||||
"key": "U"
|
||||
},
|
||||
{
|
||||
"action": "profile.keybind.2",
|
||||
"key": "CTRL+V"
|
||||
}
|
||||
],
|
||||
"time": {
|
||||
"type": "relative",
|
||||
"value": "-1d",
|
||||
"is_paused": false
|
||||
},
|
||||
"camera": {
|
||||
"type": "goToGeo",
|
||||
"anchor": "Earth",
|
||||
"latitude": 58.5877,
|
||||
"longitude": 16.1924,
|
||||
"altitude": 2.0e+07
|
||||
},
|
||||
"mark_nodes": [
|
||||
"Earth", "Mars", "Moon", "Sun"
|
||||
],
|
||||
"additional_scripts": [
|
||||
"script-1",
|
||||
"script-2",
|
||||
"script-3"
|
||||
]
|
||||
}
|
||||
131
tests/profile/conversion/version_13.profile
Normal file
131
tests/profile/conversion/version_13.profile
Normal file
@@ -0,0 +1,131 @@
|
||||
{
|
||||
"version": { "major": 1, "minor": 3 },
|
||||
"meta": {
|
||||
"name": "name",
|
||||
"version": "version",
|
||||
"description": "description",
|
||||
"author": "author",
|
||||
"url": "url",
|
||||
"license": "license"
|
||||
},
|
||||
"modules": [
|
||||
{ "name": "abs-module" },
|
||||
{
|
||||
"name": "def-module",
|
||||
"loadedInstruction": "instr"
|
||||
},
|
||||
{
|
||||
"name": "ghi-module",
|
||||
"notLoadedInstruction": "not_instr"
|
||||
},
|
||||
{
|
||||
"name": "jkl-module",
|
||||
"loadedInstruction": "instr",
|
||||
"notLoadedInstruction": "not_instr"
|
||||
}
|
||||
],
|
||||
"assets": [
|
||||
"scene/solarsystem/planets/earth/earth",
|
||||
"scene/solarsystem/planets/earth/satellites/satellites",
|
||||
"folder1/folder2/asset",
|
||||
"folder3/folder4/asset2",
|
||||
"folder5/folder6/asset3"
|
||||
],
|
||||
"properties": [
|
||||
{
|
||||
"type": "setPropertyValue",
|
||||
"name": "{earth_satellites}.Renderable.Enabled",
|
||||
"value": "false"
|
||||
},
|
||||
{
|
||||
"type": "setPropertyValue",
|
||||
"name": "property_name_1",
|
||||
"value": "property_value_1"
|
||||
},
|
||||
{
|
||||
"type": "setPropertyValue",
|
||||
"name": "property_name_2",
|
||||
"value": "property_value_2"
|
||||
},
|
||||
{
|
||||
"type": "setPropertyValue",
|
||||
"name": "property_name_3",
|
||||
"value": "property_value_3"
|
||||
},
|
||||
{
|
||||
"type": "setPropertyValueSingle",
|
||||
"name": "property_name_4",
|
||||
"value": "property_value_4"
|
||||
},
|
||||
{
|
||||
"type": "setPropertyValueSingle",
|
||||
"name": "property_name_5",
|
||||
"value": "property_value_5"
|
||||
},
|
||||
{
|
||||
"type": "setPropertyValueSingle",
|
||||
"name": "property_name_6",
|
||||
"value": "property_value_6"
|
||||
}
|
||||
],
|
||||
"actions": [
|
||||
{
|
||||
"identifier": "profile.keybind.0",
|
||||
"documentation": "T documentation",
|
||||
"name": "T name",
|
||||
"gui_path": "T Gui-Path",
|
||||
"is_local": true,
|
||||
"script": "T script"
|
||||
},
|
||||
{
|
||||
"identifier": "profile.keybind.1",
|
||||
"documentation": "U documentation",
|
||||
"name": "U name",
|
||||
"gui_path": "U Gui-Path",
|
||||
"is_local": false,
|
||||
"script": "U script"
|
||||
},
|
||||
{
|
||||
"identifier": "profile.keybind.2",
|
||||
"documentation": "CTRL+V documentation",
|
||||
"name": "CTRL+V name",
|
||||
"gui_path": "CTRL+V Gui-Path",
|
||||
"is_local": false,
|
||||
"script": "CTRL+V script"
|
||||
}
|
||||
],
|
||||
"keybindings": [
|
||||
{
|
||||
"action": "profile.keybind.0",
|
||||
"key": "T"
|
||||
},
|
||||
{
|
||||
"action": "profile.keybind.1",
|
||||
"key": "U"
|
||||
},
|
||||
{
|
||||
"action": "profile.keybind.2",
|
||||
"key": "CTRL+V"
|
||||
}
|
||||
],
|
||||
"time": {
|
||||
"type": "relative",
|
||||
"value": "-1d",
|
||||
"is_paused": false
|
||||
},
|
||||
"camera": {
|
||||
"type": "goToGeo",
|
||||
"anchor": "Earth",
|
||||
"latitude": 58.5877,
|
||||
"longitude": 16.1924,
|
||||
"altitude": 2.0e+07
|
||||
},
|
||||
"mark_nodes": [
|
||||
"Earth", "Mars", "Moon", "Sun"
|
||||
],
|
||||
"additional_scripts": [
|
||||
"script-1",
|
||||
"script-2",
|
||||
"script-3"
|
||||
]
|
||||
}
|
||||
131
tests/profile/conversion/version_14.profile
Normal file
131
tests/profile/conversion/version_14.profile
Normal file
@@ -0,0 +1,131 @@
|
||||
{
|
||||
"version": { "major": 1, "minor": 4 },
|
||||
"meta": {
|
||||
"name": "name",
|
||||
"version": "version",
|
||||
"description": "description",
|
||||
"author": "author",
|
||||
"url": "url",
|
||||
"license": "license"
|
||||
},
|
||||
"modules": [
|
||||
{ "name": "abs-module" },
|
||||
{
|
||||
"name": "def-module",
|
||||
"loadedInstruction": "instr"
|
||||
},
|
||||
{
|
||||
"name": "ghi-module",
|
||||
"notLoadedInstruction": "not_instr"
|
||||
},
|
||||
{
|
||||
"name": "jkl-module",
|
||||
"loadedInstruction": "instr",
|
||||
"notLoadedInstruction": "not_instr"
|
||||
}
|
||||
],
|
||||
"assets": [
|
||||
"scene/solarsystem/planets/earth/earth",
|
||||
"scene/solarsystem/planets/earth/satellites/satellites",
|
||||
"folder1/folder2/asset",
|
||||
"folder3/folder4/asset2",
|
||||
"folder5/folder6/asset3"
|
||||
],
|
||||
"properties": [
|
||||
{
|
||||
"type": "setPropertyValue",
|
||||
"name": "{earth_satellites}.Renderable.Enabled",
|
||||
"value": "false"
|
||||
},
|
||||
{
|
||||
"type": "setPropertyValue",
|
||||
"name": "property_name_1",
|
||||
"value": "property_value_1"
|
||||
},
|
||||
{
|
||||
"type": "setPropertyValue",
|
||||
"name": "property_name_2",
|
||||
"value": "property_value_2"
|
||||
},
|
||||
{
|
||||
"type": "setPropertyValue",
|
||||
"name": "property_name_3",
|
||||
"value": "property_value_3"
|
||||
},
|
||||
{
|
||||
"type": "setPropertyValueSingle",
|
||||
"name": "property_name_4",
|
||||
"value": "property_value_4"
|
||||
},
|
||||
{
|
||||
"type": "setPropertyValueSingle",
|
||||
"name": "property_name_5",
|
||||
"value": "property_value_5"
|
||||
},
|
||||
{
|
||||
"type": "setPropertyValueSingle",
|
||||
"name": "property_name_6",
|
||||
"value": "property_value_6"
|
||||
}
|
||||
],
|
||||
"actions": [
|
||||
{
|
||||
"identifier": "profile.keybind.0",
|
||||
"documentation": "T documentation",
|
||||
"name": "T name",
|
||||
"gui_path": "T Gui-Path",
|
||||
"is_local": true,
|
||||
"script": "T script"
|
||||
},
|
||||
{
|
||||
"identifier": "profile.keybind.1",
|
||||
"documentation": "U documentation",
|
||||
"name": "U name",
|
||||
"gui_path": "U Gui-Path",
|
||||
"is_local": false,
|
||||
"script": "U script"
|
||||
},
|
||||
{
|
||||
"identifier": "profile.keybind.2",
|
||||
"documentation": "CTRL+V documentation",
|
||||
"name": "CTRL+V name",
|
||||
"gui_path": "CTRL+V Gui-Path",
|
||||
"is_local": false,
|
||||
"script": "CTRL+V script"
|
||||
}
|
||||
],
|
||||
"keybindings": [
|
||||
{
|
||||
"action": "profile.keybind.0",
|
||||
"key": "T"
|
||||
},
|
||||
{
|
||||
"action": "profile.keybind.1",
|
||||
"key": "U"
|
||||
},
|
||||
{
|
||||
"action": "profile.keybind.2",
|
||||
"key": "CTRL+V"
|
||||
}
|
||||
],
|
||||
"time": {
|
||||
"type": "relative",
|
||||
"value": "-1d",
|
||||
"is_paused": false
|
||||
},
|
||||
"camera": {
|
||||
"type": "goToGeo",
|
||||
"anchor": "Earth",
|
||||
"latitude": 58.5877,
|
||||
"longitude": 16.1924,
|
||||
"altitude": 2.0e+07
|
||||
},
|
||||
"mark_nodes": [
|
||||
"Earth", "Mars", "Moon", "Sun"
|
||||
],
|
||||
"additional_scripts": [
|
||||
"script-1",
|
||||
"script-2",
|
||||
"script-3"
|
||||
]
|
||||
}
|
||||
@@ -861,6 +861,98 @@ TEST_CASE("Save settings to profile", "[profile]") {
|
||||
CHECK(profile.time->value == "current-time");
|
||||
}
|
||||
|
||||
TEST_CASE("Version 1.0 -> 1.1", "[profile]") {
|
||||
constexpr std::string_view Src = "${TESTDIR}/profile/conversion/version_10.profile";
|
||||
constexpr std::string_view Dest = "${TESTDIR}/profile/conversion/version_11.profile";
|
||||
|
||||
Profile src = Profile(absPath(Src));
|
||||
Profile dst = Profile(absPath(Dest));
|
||||
CHECK(src == dst);
|
||||
}
|
||||
|
||||
TEST_CASE("Version 1.0 -> 1.2", "[profile]") {
|
||||
constexpr std::string_view Src = "${TESTDIR}/profile/conversion/version_10.profile";
|
||||
constexpr std::string_view Dest = "${TESTDIR}/profile/conversion/version_12.profile";
|
||||
|
||||
Profile src = Profile(absPath(Src));
|
||||
Profile dst = Profile(absPath(Dest));
|
||||
CHECK(src == dst);
|
||||
}
|
||||
|
||||
TEST_CASE("Version 1.0 -> 1.3", "[profile]") {
|
||||
constexpr std::string_view Src = "${TESTDIR}/profile/conversion/version_10.profile";
|
||||
constexpr std::string_view Dest = "${TESTDIR}/profile/conversion/version_13.profile";
|
||||
|
||||
Profile src = Profile(absPath(Src));
|
||||
Profile dst = Profile(absPath(Dest));
|
||||
CHECK(src == dst);
|
||||
}
|
||||
|
||||
TEST_CASE("Version 1.0 -> 1.4", "[profile]") {
|
||||
constexpr std::string_view Src = "${TESTDIR}/profile/conversion/version_10.profile";
|
||||
constexpr std::string_view Dest = "${TESTDIR}/profile/conversion/version_14.profile";
|
||||
|
||||
Profile src = Profile(absPath(Src));
|
||||
Profile dst = Profile(absPath(Dest));
|
||||
CHECK(src == dst);
|
||||
}
|
||||
|
||||
TEST_CASE("Version 1.1 -> 1.2", "[profile]") {
|
||||
constexpr std::string_view Src = "${TESTDIR}/profile/conversion/version_11.profile";
|
||||
constexpr std::string_view Dest = "${TESTDIR}/profile/conversion/version_12.profile";
|
||||
|
||||
Profile src = Profile(absPath(Src));
|
||||
Profile dst = Profile(absPath(Dest));
|
||||
CHECK(src == dst);
|
||||
}
|
||||
|
||||
TEST_CASE("Version 1.1 -> 1.3", "[profile]") {
|
||||
constexpr std::string_view Src = "${TESTDIR}/profile/conversion/version_11.profile";
|
||||
constexpr std::string_view Dest = "${TESTDIR}/profile/conversion/version_13.profile";
|
||||
|
||||
Profile src = Profile(absPath(Src));
|
||||
Profile dst = Profile(absPath(Dest));
|
||||
CHECK(src == dst);
|
||||
}
|
||||
|
||||
TEST_CASE("Version 1.1 -> 1.4", "[profile]") {
|
||||
constexpr std::string_view Src = "${TESTDIR}/profile/conversion/version_11.profile";
|
||||
constexpr std::string_view Dest = "${TESTDIR}/profile/conversion/version_14.profile";
|
||||
|
||||
Profile src = Profile(absPath(Src));
|
||||
Profile dst = Profile(absPath(Dest));
|
||||
CHECK(src == dst);
|
||||
}
|
||||
|
||||
TEST_CASE("Version 1.2 -> 1.3", "[profile]") {
|
||||
constexpr std::string_view Src = "${TESTDIR}/profile/conversion/version_12.profile";
|
||||
constexpr std::string_view Dest = "${TESTDIR}/profile/conversion/version_13.profile";
|
||||
|
||||
Profile src = Profile(absPath(Src));
|
||||
Profile dst = Profile(absPath(Dest));
|
||||
CHECK(src == dst);
|
||||
}
|
||||
|
||||
TEST_CASE("Version 1.2 -> 1.4", "[profile]") {
|
||||
constexpr std::string_view Src = "${TESTDIR}/profile/conversion/version_12.profile";
|
||||
constexpr std::string_view Dest = "${TESTDIR}/profile/conversion/version_14.profile";
|
||||
|
||||
Profile src = Profile(absPath(Src));
|
||||
Profile dst = Profile(absPath(Dest));
|
||||
CHECK(src == dst);
|
||||
}
|
||||
|
||||
TEST_CASE("Version 1.3 -> 1.4", "[profile]") {
|
||||
constexpr std::string_view Src = "${TESTDIR}/profile/conversion/version_13.profile";
|
||||
constexpr std::string_view Dest = "${TESTDIR}/profile/conversion/version_14.profile";
|
||||
|
||||
Profile src = Profile(absPath(Src));
|
||||
Profile dst = Profile(absPath(Dest));
|
||||
CHECK(src == dst);
|
||||
}
|
||||
|
||||
|
||||
|
||||
//
|
||||
// Error states
|
||||
//
|
||||
|
||||
Reference in New Issue
Block a user