mirror of
https://github.com/OpenSpace/OpenSpace.git
synced 2026-05-04 18:11:01 -05:00
Merge branch 'master' into project/b612-asteroid-uncertainty
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;
|
||||
};
|
||||
|
||||
|
||||
@@ -30,10 +30,10 @@
|
||||
#include <openspace/scene/profile.h>
|
||||
|
||||
class QCheckBox;
|
||||
class QComboBox;
|
||||
class QDateTimeEdit;
|
||||
class QLabel;
|
||||
class QLineEdit;
|
||||
class QTabWidget;
|
||||
|
||||
class TimeDialog final : public QDialog {
|
||||
Q_OBJECT
|
||||
@@ -48,18 +48,15 @@ public:
|
||||
TimeDialog(QWidget* parent, std::optional<openspace::Profile::Time>* time);
|
||||
|
||||
private slots:
|
||||
void enableAccordingToType(int);
|
||||
void approved();
|
||||
|
||||
private:
|
||||
void createWidgets();
|
||||
void enableFormatForAbsolute(bool enableAbs);
|
||||
|
||||
std::optional<openspace::Profile::Time>* _time = nullptr;
|
||||
openspace::Profile::Time _timeData;
|
||||
bool _initializedAsAbsolute = true;
|
||||
|
||||
QComboBox* _typeCombo = nullptr;
|
||||
QTabWidget* _tabWidget = nullptr;
|
||||
QLabel* _absoluteLabel = nullptr;
|
||||
QDateTimeEdit* _absoluteEdit = nullptr;
|
||||
QLabel* _relativeLabel = nullptr;
|
||||
|
||||
@@ -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"));
|
||||
|
||||
@@ -32,6 +32,7 @@
|
||||
#include <QKeyEvent>
|
||||
#include <QLabel>
|
||||
#include <QLineEdit>
|
||||
#include <QTabWidget>
|
||||
#include <QVBoxLayout>
|
||||
#include <format>
|
||||
#include <algorithm>
|
||||
@@ -45,8 +46,6 @@ TimeDialog::TimeDialog(QWidget* parent, std::optional<openspace::Profile::Time>*
|
||||
setWindowTitle("Time");
|
||||
createWidgets();
|
||||
|
||||
const QStringList types = { "Absolute", "Relative" };
|
||||
_typeCombo->addItems(types);
|
||||
if (_time->has_value()) {
|
||||
_timeData = **_time;
|
||||
if (_timeData.type == Profile::Time::Type::Relative) {
|
||||
@@ -66,44 +65,75 @@ TimeDialog::TimeDialog(QWidget* parent, std::optional<openspace::Profile::Time>*
|
||||
}
|
||||
_startPaused->setChecked(_timeData.startPaused);
|
||||
|
||||
_initializedAsAbsolute = (_timeData.type == Profile::Time::Type::Absolute);
|
||||
enableAccordingToType(static_cast<int>(_timeData.type));
|
||||
if (_timeData.type == Profile::Time::Type::Relative) {
|
||||
_relativeEdit->setText(QString::fromStdString(_timeData.value));
|
||||
_relativeEdit->setFocus(Qt::OtherFocusReason);
|
||||
}
|
||||
else {
|
||||
const size_t tIdx = _timeData.value.find_first_of('T', 0);
|
||||
const QString importDate = QString::fromStdString(
|
||||
_timeData.value.substr(0, tIdx)
|
||||
);
|
||||
const QString importTime = QString::fromStdString(
|
||||
_timeData.value.substr(tIdx + 1)
|
||||
);
|
||||
_absoluteEdit->setDate(QDate::fromString(importDate, Qt::DateFormat::ISODate));
|
||||
_absoluteEdit->setTime(QTime::fromString(importTime));
|
||||
_relativeEdit->clear();
|
||||
_absoluteEdit->setFocus(Qt::OtherFocusReason);
|
||||
}
|
||||
|
||||
_tabWidget->setCurrentIndex(static_cast<int>(_timeData.type));
|
||||
}
|
||||
|
||||
void TimeDialog::createWidgets() {
|
||||
QBoxLayout* layout = new QVBoxLayout(this);
|
||||
|
||||
_tabWidget = new QTabWidget;
|
||||
|
||||
{
|
||||
layout->addWidget(new QLabel("Time Type"));
|
||||
_typeCombo = new QComboBox;
|
||||
_typeCombo->setAccessibleName("Time type");
|
||||
_typeCombo->setToolTip("Types: Absolute defined time or Relative to actual time");
|
||||
connect(
|
||||
_typeCombo, QOverload<int>::of(&QComboBox::currentIndexChanged),
|
||||
this, &TimeDialog::enableAccordingToType
|
||||
);
|
||||
layout->addWidget(_typeCombo);
|
||||
}
|
||||
{
|
||||
QWidget* container = new QWidget;
|
||||
QBoxLayout* l = new QVBoxLayout(container);
|
||||
_absoluteLabel = new QLabel("Absolute UTC:");
|
||||
layout->addWidget(_absoluteLabel);
|
||||
l->addWidget(_absoluteLabel);
|
||||
|
||||
_absoluteEdit = new QDateTimeEdit;
|
||||
_absoluteEdit->setDisplayFormat("yyyy-MM-dd T hh:mm:ss");
|
||||
_absoluteEdit->setDateTime(QDateTime::currentDateTime());
|
||||
_absoluteEdit->setAccessibleName("Set absolute time");
|
||||
layout->addWidget(_absoluteEdit);
|
||||
l->addWidget(_absoluteEdit);
|
||||
|
||||
l->addStretch();
|
||||
|
||||
_tabWidget->addTab(container, "Absolute");
|
||||
}
|
||||
{
|
||||
QWidget* container = new QWidget;
|
||||
QBoxLayout* l = new QVBoxLayout(container);
|
||||
_relativeLabel = new QLabel("Relative Time:");
|
||||
layout->addWidget(_relativeLabel);
|
||||
l->addWidget(_relativeLabel);
|
||||
|
||||
_relativeEdit = new QLineEdit;
|
||||
_relativeEdit->setAccessibleName("Set relative time");
|
||||
_relativeEdit->setToolTip(
|
||||
"String for relative time to actual (e.g. \"-1d\" for back 1 day)"
|
||||
);
|
||||
layout->addWidget(_relativeEdit);
|
||||
l->addWidget(_relativeEdit);
|
||||
|
||||
QLabel* desc = new QLabel(
|
||||
"This field modifies the default start time. It has to be of the form "
|
||||
"[-]XX(s,m,h,d,M,y). For example '-1d' will cause the profile to start at "
|
||||
"yesterday's date."
|
||||
);
|
||||
desc->setObjectName("information");
|
||||
desc->setWordWrap(true);
|
||||
l->addWidget(desc);
|
||||
|
||||
_tabWidget->addTab(container, "Relative");
|
||||
}
|
||||
|
||||
layout->addWidget(_tabWidget);
|
||||
|
||||
{
|
||||
_startPaused = new QCheckBox("Start with time paused");
|
||||
_startPaused->setChecked(false);
|
||||
@@ -123,47 +153,9 @@ void TimeDialog::createWidgets() {
|
||||
}
|
||||
}
|
||||
|
||||
void TimeDialog::enableAccordingToType(int idx) {
|
||||
const Profile::Time::Type comboIdx = static_cast<Profile::Time::Type>(idx);
|
||||
const bool setFormatForAbsolute = (comboIdx == Profile::Time::Type::Absolute);
|
||||
enableFormatForAbsolute(setFormatForAbsolute);
|
||||
_typeCombo->setCurrentIndex(idx);
|
||||
if (comboIdx == Profile::Time::Type::Relative) {
|
||||
_relativeEdit->setText("<font color='black'>Relative Time:</font>");
|
||||
if (_initializedAsAbsolute) {
|
||||
_relativeEdit->setText("0d");
|
||||
}
|
||||
else {
|
||||
_relativeEdit->setText(QString::fromStdString(_timeData.value));
|
||||
}
|
||||
_relativeEdit->setFocus(Qt::OtherFocusReason);
|
||||
}
|
||||
else {
|
||||
_relativeEdit->setText("<font color='gray'>Relative Time:</font>");
|
||||
const size_t tIdx = _timeData.value.find_first_of('T', 0);
|
||||
const QString importDate = QString::fromStdString(
|
||||
_timeData.value.substr(0, tIdx)
|
||||
);
|
||||
const QString importTime = QString::fromStdString(
|
||||
_timeData.value.substr(tIdx + 1)
|
||||
);
|
||||
_absoluteEdit->setDate(QDate::fromString(importDate, Qt::DateFormat::ISODate));
|
||||
_absoluteEdit->setTime(QTime::fromString(importTime));
|
||||
_relativeEdit->clear();
|
||||
_absoluteEdit->setFocus(Qt::OtherFocusReason);
|
||||
}
|
||||
}
|
||||
|
||||
void TimeDialog::enableFormatForAbsolute(bool enableAbs) {
|
||||
_absoluteLabel->setEnabled(enableAbs);
|
||||
_absoluteEdit->setEnabled(enableAbs);
|
||||
_relativeLabel->setEnabled(!enableAbs);
|
||||
_relativeEdit->setEnabled(!enableAbs);
|
||||
}
|
||||
|
||||
void TimeDialog::approved() {
|
||||
constexpr int Relative = static_cast<int>(Profile::Time::Type::Relative);
|
||||
if (_typeCombo->currentIndex() == Relative) {
|
||||
if (_tabWidget->currentIndex() == Relative) {
|
||||
if (_relativeEdit->text().isEmpty()) {
|
||||
*_time = std::nullopt;
|
||||
}
|
||||
|
||||
@@ -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() {
|
||||
|
||||
+1
-1
Submodule apps/OpenSpace/ext/sgct updated: 0afa47198a...7ac1bd4891
+34
-3
@@ -37,6 +37,7 @@
|
||||
#include <ghoul/cmdparser/multiplecommand.h>
|
||||
#include <ghoul/cmdparser/singlecommand.h>
|
||||
#include <ghoul/filesystem/filesystem.h>
|
||||
#include <ghoul/logging/logmanager.h>
|
||||
#include <ghoul/logging/visualstudiooutputlog.h>
|
||||
#include <ghoul/misc/stacktrace.h>
|
||||
#ifdef WIN32
|
||||
@@ -1414,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;
|
||||
|
||||
@@ -1,7 +1,9 @@
|
||||
local Item = {
|
||||
Type = "DashboardItemDistance",
|
||||
Identifier = "Distance",
|
||||
GuiName = "Distance"
|
||||
GuiName = "Distance",
|
||||
SourceType = "Camera",
|
||||
DestinationType = "Focus"
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -0,0 +1,61 @@
|
||||
-- Three nodes
|
||||
-- This example adds three invisible scene graph nodes and then shows the angle between
|
||||
-- those three nodes.
|
||||
|
||||
local Node1 = {
|
||||
Identifier = "DashboardItemAngle_Example_ThreeNodes_Node1",
|
||||
GUI = {
|
||||
Name = "DashboardItemAngle - Three Nodes (Node 1)"
|
||||
}
|
||||
}
|
||||
|
||||
local Node2 = {
|
||||
Identifier = "DashboardItemAngle_Example_ThreeNodes_Node2",
|
||||
Transform = {
|
||||
Translation = {
|
||||
Type = "StaticTranslation",
|
||||
Position = { 2.0, 1.0, 0.0 }
|
||||
}
|
||||
},
|
||||
GUI = {
|
||||
Name = "DashboardItemAngle - Three Nodes (Node 2)"
|
||||
}
|
||||
}
|
||||
|
||||
local Node3 = {
|
||||
Identifier = "DashboardItemAngle_Example_ThreeNodes_Node3",
|
||||
Transform = {
|
||||
Translation = {
|
||||
Type = "StaticTranslation",
|
||||
Position = { -2.0, 1.0, 0.0 }
|
||||
}
|
||||
},
|
||||
GUI = {
|
||||
Name = "DashboardItemAngle - Three Nodes (Node 3)"
|
||||
}
|
||||
}
|
||||
|
||||
local Item = {
|
||||
Identifier = "DashboardItemAngle_Example_ThreeNodes",
|
||||
Type = "DashboardItemAngle",
|
||||
SourceType = "Node",
|
||||
SourceNodeIdentifier = Node1.Identifier,
|
||||
ReferenceType = "Node",
|
||||
ReferenceNodeIdentifier = Node2.Identifier,
|
||||
DestinationType = "Node",
|
||||
DestinationNodeIdentifier = Node3.Identifier
|
||||
}
|
||||
|
||||
asset.onInitialize(function()
|
||||
openspace.addSceneGraphNode(Node1)
|
||||
openspace.addSceneGraphNode(Node2)
|
||||
openspace.addSceneGraphNode(Node3)
|
||||
openspace.dashboard.addDashboardItem(Item)
|
||||
end)
|
||||
|
||||
asset.onDeinitialize(function()
|
||||
openspace.dashboard.removeDashboardItem(Item)
|
||||
openspace.removeSceneGraphNode(Node3)
|
||||
openspace.removeSceneGraphNode(Node2)
|
||||
openspace.removeSceneGraphNode(Node1)
|
||||
end)
|
||||
@@ -0,0 +1,45 @@
|
||||
-- Two nodes and camera
|
||||
-- This example adds two invisible scene graph nodes and then shows the angle between the
|
||||
-- camera and those two nodes.
|
||||
|
||||
local Node1 = {
|
||||
Identifier = "DashboardItemAngle_Example_TwoNodesCamera_Node1",
|
||||
GUI = {
|
||||
Name = "DashboardItemAngle - Two Nodes & Camera (Node 1)"
|
||||
}
|
||||
}
|
||||
|
||||
local Node2 = {
|
||||
Identifier = "DashboardItemAngle_Example_TwoNodesCamera_Node2",
|
||||
Transform = {
|
||||
Translation = {
|
||||
Type = "StaticTranslation",
|
||||
Position = { 20.0, 1.0, 0.0 }
|
||||
}
|
||||
},
|
||||
GUI = {
|
||||
Name = "DashboardItemAngle - Two Nodes & Camera (Node 2)"
|
||||
}
|
||||
}
|
||||
|
||||
local Item = {
|
||||
Identifier = "DashboardItemAngle_Example_TwoNodesCamera",
|
||||
Type = "DashboardItemAngle",
|
||||
SourceType = "Camera",
|
||||
ReferenceType = "Node",
|
||||
ReferenceNodeIdentifier = Node1.Identifier,
|
||||
DestinationType = "Node",
|
||||
DestinationNodeIdentifier = Node2.Identifier
|
||||
}
|
||||
|
||||
asset.onInitialize(function()
|
||||
openspace.addSceneGraphNode(Node1)
|
||||
openspace.addSceneGraphNode(Node2)
|
||||
openspace.dashboard.addDashboardItem(Item)
|
||||
end)
|
||||
|
||||
asset.onDeinitialize(function()
|
||||
openspace.dashboard.removeDashboardItem(Item)
|
||||
openspace.removeSceneGraphNode(Node2)
|
||||
openspace.removeSceneGraphNode(Node1)
|
||||
end)
|
||||
@@ -0,0 +1,45 @@
|
||||
-- Two nodes and focus
|
||||
-- This example adds two invisible scene graph nodes and then shows the angle between the
|
||||
-- current focus node and those two nodes.
|
||||
|
||||
local Node1 = {
|
||||
Identifier = "DashboardItemAngle_Example_TwoNodesFocus_Node1",
|
||||
GUI = {
|
||||
Name = "DashboardItemAngle - Two Nodes & Focus (Node 1)"
|
||||
}
|
||||
}
|
||||
|
||||
local Node2 = {
|
||||
Identifier = "DashboardItemAngle_Example_TwoNodesFocus_Node2",
|
||||
Transform = {
|
||||
Translation = {
|
||||
Type = "StaticTranslation",
|
||||
Position = { 20.0, 1.0, 0.0 }
|
||||
}
|
||||
},
|
||||
GUI = {
|
||||
Name = "DashboardItemAngle - Two Nodes & Focus (Node 2)"
|
||||
}
|
||||
}
|
||||
|
||||
local Item = {
|
||||
Identifier = "DashboardItemAngle_Example_TwoNodesFocus",
|
||||
Type = "DashboardItemAngle",
|
||||
SourceType = "Focus",
|
||||
ReferenceType = "Node",
|
||||
ReferenceNodeIdentifier = Node1.Identifier,
|
||||
DestinationType = "Node",
|
||||
DestinationNodeIdentifier = Node2.Identifier
|
||||
}
|
||||
|
||||
asset.onInitialize(function()
|
||||
openspace.addSceneGraphNode(Node1)
|
||||
openspace.addSceneGraphNode(Node2)
|
||||
openspace.dashboard.addDashboardItem(Item)
|
||||
end)
|
||||
|
||||
asset.onDeinitialize(function()
|
||||
openspace.dashboard.removeDashboardItem(Item)
|
||||
openspace.removeSceneGraphNode(Node2)
|
||||
openspace.removeSceneGraphNode(Node1)
|
||||
end)
|
||||
@@ -0,0 +1,15 @@
|
||||
-- Basic
|
||||
-- This example adds a new DashboardItem that shows the current in-game simulation date.
|
||||
|
||||
local Item = {
|
||||
Identifier = "DashboardItemDate_Example",
|
||||
Type = "DashboardItemDate"
|
||||
}
|
||||
|
||||
asset.onInitialize(function()
|
||||
openspace.dashboard.addDashboardItem(Item)
|
||||
end)
|
||||
|
||||
asset.onDeinitialize(function()
|
||||
openspace.dashboard.removeDashboardItem(Item)
|
||||
end)
|
||||
@@ -0,0 +1,17 @@
|
||||
-- Day of Year
|
||||
-- This example adds a new DashboardItem that shows the current in-game simulation date
|
||||
-- showing the current year and the number of days that have passed in the year.
|
||||
|
||||
local Item = {
|
||||
Identifier = "DashboardItemDate_Example_DayOfYear",
|
||||
Type = "DashboardItemDate",
|
||||
TimeFormat = "YYYY DOY"
|
||||
}
|
||||
|
||||
asset.onInitialize(function()
|
||||
openspace.dashboard.addDashboardItem(Item)
|
||||
end)
|
||||
|
||||
asset.onDeinitialize(function()
|
||||
openspace.dashboard.removeDashboardItem(Item)
|
||||
end)
|
||||
@@ -0,0 +1,17 @@
|
||||
-- No Decorations
|
||||
-- This example adds a new DashboardItem that shows the current in-game simulation date
|
||||
-- without any additional text surrounding the current date
|
||||
|
||||
local Item = {
|
||||
Identifier = "DashboardItemDate_Example_NoDecoration",
|
||||
Type = "DashboardItemDate",
|
||||
FormatString = "{}"
|
||||
}
|
||||
|
||||
asset.onInitialize(function()
|
||||
openspace.dashboard.addDashboardItem(Item)
|
||||
end)
|
||||
|
||||
asset.onDeinitialize(function()
|
||||
openspace.dashboard.removeDashboardItem(Item)
|
||||
end)
|
||||
@@ -0,0 +1,17 @@
|
||||
-- Timezone
|
||||
-- This example adds a new DashboardItem that shows the current in-game simulation date
|
||||
-- with a timezone of UTC-7 (=PDT)
|
||||
|
||||
local Item = {
|
||||
Identifier = "DashboardItemDate_Example_Timezone",
|
||||
Type = "DashboardItemDate",
|
||||
TimeFormat = "YYYY MON DD HR:MN:SC.### PDT ::UTC-7"
|
||||
}
|
||||
|
||||
asset.onInitialize(function()
|
||||
openspace.dashboard.addDashboardItem(Item)
|
||||
end)
|
||||
|
||||
asset.onDeinitialize(function()
|
||||
openspace.dashboard.removeDashboardItem(Item)
|
||||
end)
|
||||
@@ -0,0 +1,17 @@
|
||||
-- Year Month Day
|
||||
-- This example adds a new DashboardItem that shows the current in-game simulation date
|
||||
-- with a resolution of days.
|
||||
|
||||
local Item = {
|
||||
Identifier = "DashboardItemDate_Example_YearMonthDay",
|
||||
Type = "DashboardItemDate",
|
||||
TimeFormat = "YYYY MON DD"
|
||||
}
|
||||
|
||||
asset.onInitialize(function()
|
||||
openspace.dashboard.addDashboardItem(Item)
|
||||
end)
|
||||
|
||||
asset.onDeinitialize(function()
|
||||
openspace.dashboard.removeDashboardItem(Item)
|
||||
end)
|
||||
@@ -0,0 +1,28 @@
|
||||
-- Node-Camera
|
||||
-- This example adds an invisible node and a dashboard item that shows the distance
|
||||
-- between this node and the current focus node.
|
||||
|
||||
local Node = {
|
||||
Identifier = "DashboardItemDistance_Example_NodeCamera_Node",
|
||||
GUI = {
|
||||
Name = "DashboardItemDistance - Node-Camera"
|
||||
}
|
||||
}
|
||||
|
||||
local Item = {
|
||||
Identifier = "DashboardItemDistance_Example_NodeCamera",
|
||||
Type = "DashboardItemDistance",
|
||||
SourceType = "Node",
|
||||
SourceNodeIdentifier = Node.Identifier,
|
||||
DestinationType = "Camera"
|
||||
}
|
||||
|
||||
asset.onInitialize(function()
|
||||
openspace.addSceneGraphNode(Node)
|
||||
openspace.dashboard.addDashboardItem(Item)
|
||||
end)
|
||||
|
||||
asset.onDeinitialize(function()
|
||||
openspace.dashboard.removeDashboardItem(Item)
|
||||
openspace.removeSceneGraphNode(Node)
|
||||
end)
|
||||
@@ -0,0 +1,28 @@
|
||||
-- Node-Focus
|
||||
-- This example adds an invisible node and a dashboard item that shows the distance
|
||||
-- between this node and the current focus node.
|
||||
|
||||
local Node = {
|
||||
Identifier = "DashboardItemDistance_Example_NodeFocus_Node",
|
||||
GUI = {
|
||||
Name = "DashboardItemDistance - Node-Focus"
|
||||
}
|
||||
}
|
||||
|
||||
local Item = {
|
||||
Identifier = "DashboardItemDistance_Example_NodeFocus",
|
||||
Type = "DashboardItemDistance",
|
||||
SourceType = "Node",
|
||||
SourceNodeIdentifier = Node.Identifier,
|
||||
DestinationType = "Focus"
|
||||
}
|
||||
|
||||
asset.onInitialize(function()
|
||||
openspace.addSceneGraphNode(Node)
|
||||
openspace.dashboard.addDashboardItem(Item)
|
||||
end)
|
||||
|
||||
asset.onDeinitialize(function()
|
||||
openspace.dashboard.removeDashboardItem(Item)
|
||||
openspace.removeSceneGraphNode(Node1)
|
||||
end)
|
||||
@@ -0,0 +1,44 @@
|
||||
-- Node-Node
|
||||
-- This example adds two invisible nodes and a dashboard item that shows the distance
|
||||
-- between those two nodes.
|
||||
|
||||
local Node1 = {
|
||||
Identifier = "DashboardItemDistance_Example_NodeNode_Node1",
|
||||
GUI = {
|
||||
Name = "DashboardItemDistance - Node-Node (Node 1)"
|
||||
}
|
||||
}
|
||||
|
||||
local Node2 = {
|
||||
Identifier = "DashboardItemDistance_Example_NodeNode_Node2",
|
||||
Transform = {
|
||||
Translation = {
|
||||
Type = "StaticTranslation",
|
||||
Position = { 2.0, 0.0, 0.0 }
|
||||
}
|
||||
},
|
||||
GUI = {
|
||||
Name = "DashboardItemDistance - Node-Node (Node 2)"
|
||||
}
|
||||
}
|
||||
|
||||
local Item = {
|
||||
Identifier = "DashboardItemDistance_Example_NodeNode",
|
||||
Type = "DashboardItemDistance",
|
||||
SourceType = "Node",
|
||||
SourceNodeIdentifier = Node1.Identifier,
|
||||
DestinationType = "Node",
|
||||
DestinationNodeIdentifier = Node2.Identifier
|
||||
}
|
||||
|
||||
asset.onInitialize(function()
|
||||
openspace.addSceneGraphNode(Node1)
|
||||
openspace.addSceneGraphNode(Node2)
|
||||
openspace.dashboard.addDashboardItem(Item)
|
||||
end)
|
||||
|
||||
asset.onDeinitialize(function()
|
||||
openspace.dashboard.removeDashboardItem(Item)
|
||||
openspace.removeSceneGraphNode(Node2)
|
||||
openspace.removeSceneGraphNode(Node1)
|
||||
end)
|
||||
+29
@@ -0,0 +1,29 @@
|
||||
-- NodeSurface-Camera
|
||||
-- This example adds two invisible nodes and a dashboard item that shows the distance
|
||||
-- between those two nodes
|
||||
|
||||
local Node = {
|
||||
Identifier = "DashboardItemDistance_Example_NodeSurfaceCamera_Node",
|
||||
BoundingSphere = 200.0,
|
||||
GUI = {
|
||||
Name = "DashboardItemDistance - NodeSurface-Camera"
|
||||
}
|
||||
}
|
||||
|
||||
local Item = {
|
||||
Identifier = "DashboardItemDistance_Example_NodeSurfaceCamera",
|
||||
Type = "DashboardItemDistance",
|
||||
SourceType = "Node Surface",
|
||||
SourceNodeIdentifier = Node.Identifier,
|
||||
DestinationType = "Camera"
|
||||
}
|
||||
|
||||
asset.onInitialize(function()
|
||||
openspace.addSceneGraphNode(Node)
|
||||
openspace.dashboard.addDashboardItem(Item)
|
||||
end)
|
||||
|
||||
asset.onDeinitialize(function()
|
||||
openspace.dashboard.removeDashboardItem(Item)
|
||||
openspace.removeSceneGraphNode(Node)
|
||||
end)
|
||||
@@ -0,0 +1,17 @@
|
||||
-- Basic
|
||||
-- This example adds a dashboard item that shows the remaining time or the elapsed time
|
||||
-- since midday 2000 JAN 01.
|
||||
|
||||
local Item = {
|
||||
Identifier = "DashboardItemElapsedTime_Example",
|
||||
Type = "DashboardItemElapsedTime",
|
||||
ReferenceTime = "2000 JAN 01 12:00:00"
|
||||
}
|
||||
|
||||
asset.onInitialize(function()
|
||||
openspace.dashboard.addDashboardItem(Item)
|
||||
end)
|
||||
|
||||
asset.onDeinitialize(function()
|
||||
openspace.dashboard.removeDashboardItem(Item)
|
||||
end)
|
||||
@@ -0,0 +1,18 @@
|
||||
-- Fixed Time
|
||||
-- This example adds a dashboard item that shows the remaining time or the elapsed time
|
||||
-- since 2000 JAN 01 but ignoring any unit smaller than days.
|
||||
|
||||
local Item = {
|
||||
Identifier = "DashboardItemElapsedTime_Example_FixedTime",
|
||||
Type = "DashboardItemElapsedTime",
|
||||
ReferenceTime = "2000 JAN 01 12:00:00",
|
||||
LowestTimeUnit = "Day"
|
||||
}
|
||||
|
||||
asset.onInitialize(function()
|
||||
openspace.dashboard.addDashboardItem(Item)
|
||||
end)
|
||||
|
||||
asset.onDeinitialize(function()
|
||||
openspace.dashboard.removeDashboardItem(Item)
|
||||
end)
|
||||
@@ -0,0 +1,19 @@
|
||||
-- No Decorations
|
||||
-- This example adds a dashboard item that shows the remaining time or the elapsed time
|
||||
-- since midday 2000 JAN 01 without any additional text decoration and only printing the
|
||||
-- remaining time.
|
||||
|
||||
local Item = {
|
||||
Identifier = "DashboardItemElapsedTime_Example_NoDecorations",
|
||||
Type = "DashboardItemElapsedTime",
|
||||
ReferenceTime = "2000 JAN 01 12:00:00",
|
||||
FormatString = "{}"
|
||||
}
|
||||
|
||||
asset.onInitialize(function()
|
||||
openspace.dashboard.addDashboardItem(Item)
|
||||
end)
|
||||
|
||||
asset.onDeinitialize(function()
|
||||
openspace.dashboard.removeDashboardItem(Item)
|
||||
end)
|
||||
@@ -0,0 +1,16 @@
|
||||
-- Basic
|
||||
-- This example adds a dashboard item that shows the average number of frames per second,
|
||||
-- which is the default value for the frame time type setting.
|
||||
|
||||
local Item = {
|
||||
Identifier = "DashboardItemFramerate_Example",
|
||||
Type = "DashboardItemFramerate"
|
||||
}
|
||||
|
||||
asset.onInitialize(function()
|
||||
openspace.dashboard.addDashboardItem(Item)
|
||||
end)
|
||||
|
||||
asset.onDeinitialize(function()
|
||||
openspace.dashboard.removeDashboardItem(Item)
|
||||
end)
|
||||
@@ -0,0 +1,17 @@
|
||||
-- Delta Time
|
||||
-- This example adds a dashboard item that shows the frame rate of the last frame in
|
||||
-- milliseconds.
|
||||
|
||||
local Item = {
|
||||
Identifier = "DashboardItemFramerate_Example_DeltaTime",
|
||||
Type = "DashboardItemFramerate",
|
||||
FrametimeType = "Deltatime"
|
||||
}
|
||||
|
||||
asset.onInitialize(function()
|
||||
openspace.dashboard.addDashboardItem(Item)
|
||||
end)
|
||||
|
||||
asset.onDeinitialize(function()
|
||||
openspace.dashboard.removeDashboardItem(Item)
|
||||
end)
|
||||
@@ -0,0 +1,16 @@
|
||||
-- Basic
|
||||
-- This example adds a dashboard item that shows the position of the camera relative to
|
||||
-- the focus node, if that focus node is a globe.
|
||||
|
||||
local Item = {
|
||||
Identifier = "DashboardItemGlobeLocation_Example",
|
||||
Type = "DashboardItemGlobeLocation"
|
||||
}
|
||||
|
||||
asset.onInitialize(function()
|
||||
openspace.dashboard.addDashboardItem(Item)
|
||||
end)
|
||||
|
||||
asset.onDeinitialize(function()
|
||||
openspace.dashboard.removeDashboardItem(Item)
|
||||
end)
|
||||
@@ -0,0 +1,18 @@
|
||||
-- Degree/Minute/Seconds
|
||||
-- This example adds a dashboard item that shows the position of the camera relative to
|
||||
-- the focus node, if that focus node is a globe. The longitude and latitude of the camera
|
||||
-- is provided in the sexagesimal system (degrees, minutes, seconds).
|
||||
|
||||
local Item = {
|
||||
Identifier = "DashboardItemGlobeLocation_Example",
|
||||
Type = "DashboardItemGlobeLocation",
|
||||
DisplayFormat = "DegreeMinuteSeconds"
|
||||
}
|
||||
|
||||
asset.onInitialize(function()
|
||||
openspace.dashboard.addDashboardItem(Item)
|
||||
end)
|
||||
|
||||
asset.onDeinitialize(function()
|
||||
openspace.dashboard.removeDashboardItem(Item)
|
||||
end)
|
||||
@@ -0,0 +1,16 @@
|
||||
-- Basic
|
||||
-- This example adds a dashboard item that shows the input state of the mouse, keyboard,
|
||||
-- and joystick input devices.
|
||||
|
||||
local Item = {
|
||||
Identifier = "DashboardItemInputState_Example",
|
||||
Type = "DashboardItemInputState"
|
||||
}
|
||||
|
||||
asset.onInitialize(function()
|
||||
openspace.dashboard.addDashboardItem(Item)
|
||||
end)
|
||||
|
||||
asset.onDeinitialize(function()
|
||||
openspace.dashboard.removeDashboardItem(Item)
|
||||
end)
|
||||
@@ -0,0 +1,17 @@
|
||||
-- Mouse Only
|
||||
-- This example adds a dashboard item that only shows the input state of the mouse inputs.
|
||||
|
||||
local Item = {
|
||||
Identifier = "DashboardItemInputState_Example_MouseOnly",
|
||||
Type = "DashboardItemInputState",
|
||||
ShowKeyboard = false,
|
||||
ShowJoystick = false
|
||||
}
|
||||
|
||||
asset.onInitialize(function()
|
||||
openspace.dashboard.addDashboardItem(Item)
|
||||
end)
|
||||
|
||||
asset.onDeinitialize(function()
|
||||
openspace.dashboard.removeDashboardItem(Item)
|
||||
end)
|
||||
+17
@@ -0,0 +1,17 @@
|
||||
-- Only disabled
|
||||
-- This example adds a dashboard item that shows the input state of the mouse, keyboard,
|
||||
-- and joystick input devices but only when they are disabled.
|
||||
|
||||
local Item = {
|
||||
Identifier = "DashboardItemInputState_Example_OnlyDisabled",
|
||||
Type = "DashboardItemInputState",
|
||||
ShowWhenDisabled = true
|
||||
}
|
||||
|
||||
asset.onInitialize(function()
|
||||
openspace.dashboard.addDashboardItem(Item)
|
||||
end)
|
||||
|
||||
asset.onDeinitialize(function()
|
||||
openspace.dashboard.removeDashboardItem(Item)
|
||||
end)
|
||||
@@ -0,0 +1,16 @@
|
||||
-- Basic
|
||||
-- This example adds a dashboard item that shows the status of the currently active
|
||||
-- mission.
|
||||
|
||||
local Item = {
|
||||
Identifier = "DashboardItemMission_Example",
|
||||
Type = "DashboardItemMission"
|
||||
}
|
||||
|
||||
asset.onInitialize(function()
|
||||
openspace.dashboard.addDashboardItem(Item)
|
||||
end)
|
||||
|
||||
asset.onDeinitialize(function()
|
||||
openspace.dashboard.removeDashboardItem(Item)
|
||||
end)
|
||||
+15
@@ -0,0 +1,15 @@
|
||||
-- Basic
|
||||
-- This example adds a dashboard item that shows the status of the parallel connection.
|
||||
|
||||
local Item = {
|
||||
Identifier = "DashboardItemParallelConnection_Example",
|
||||
Type = "DashboardItemParallelConnection"
|
||||
}
|
||||
|
||||
asset.onInitialize(function()
|
||||
openspace.dashboard.addDashboardItem(Item)
|
||||
end)
|
||||
|
||||
asset.onDeinitialize(function()
|
||||
openspace.dashboard.removeDashboardItem(Item)
|
||||
end)
|
||||
+17
@@ -0,0 +1,17 @@
|
||||
-- Bool
|
||||
-- This example adds a dashboard item that shows the state of a boolean property.
|
||||
|
||||
local Item = {
|
||||
Identifier = "DashboardItemPropertyValue_Example_Bool",
|
||||
Type = "DashboardItemPropertyValue",
|
||||
URI = "NavigationHandler.OrbitalNavigator.Friction.RotationalFriction",
|
||||
DisplayString = "Rotational Friction is: {}"
|
||||
}
|
||||
|
||||
asset.onInitialize(function()
|
||||
openspace.dashboard.addDashboardItem(Item)
|
||||
end)
|
||||
|
||||
asset.onDeinitialize(function()
|
||||
openspace.dashboard.removeDashboardItem(Item)
|
||||
end)
|
||||
+18
@@ -0,0 +1,18 @@
|
||||
-- Float
|
||||
-- This example adds a dashboard item that shows the state of a floating point value
|
||||
-- property.
|
||||
|
||||
local Item = {
|
||||
Identifier = "DashboardItemPropertyValue_Example_Float",
|
||||
Type = "DashboardItemPropertyValue",
|
||||
URI = "RenderEngine.Gamma",
|
||||
DisplayString = "Gamma Correction: {}"
|
||||
}
|
||||
|
||||
asset.onInitialize(function()
|
||||
openspace.dashboard.addDashboardItem(Item)
|
||||
end)
|
||||
|
||||
asset.onDeinitialize(function()
|
||||
openspace.dashboard.removeDashboardItem(Item)
|
||||
end)
|
||||
@@ -0,0 +1,18 @@
|
||||
-- Int
|
||||
-- This example adds a dashboard item that shows the state of a integer point value
|
||||
-- property.
|
||||
|
||||
local Item = {
|
||||
Identifier = "DashboardItemPropertyValue_Example_Int",
|
||||
Type = "DashboardItemPropertyValue",
|
||||
URI = "LuaConsole.HistoryLength",
|
||||
DisplayString = "Lua Console History Length: {}"
|
||||
}
|
||||
|
||||
asset.onInitialize(function()
|
||||
openspace.dashboard.addDashboardItem(Item)
|
||||
end)
|
||||
|
||||
asset.onDeinitialize(function()
|
||||
openspace.dashboard.removeDashboardItem(Item)
|
||||
end)
|
||||
+17
@@ -0,0 +1,17 @@
|
||||
-- Vec3
|
||||
-- This example adds a dashboard item that shows the state of a 3-vector value property.
|
||||
|
||||
local Item = {
|
||||
Identifier = "DashboardItemPropertyValue_Example_Vec3",
|
||||
Type = "DashboardItemPropertyValue",
|
||||
URI = "RenderEngine.GlobalRotation",
|
||||
DisplayString = "Global Rotation: ({}, {}, {})"
|
||||
}
|
||||
|
||||
asset.onInitialize(function()
|
||||
openspace.dashboard.addDashboardItem(Item)
|
||||
end)
|
||||
|
||||
asset.onDeinitialize(function()
|
||||
openspace.dashboard.removeDashboardItem(Item)
|
||||
end)
|
||||
+17
@@ -0,0 +1,17 @@
|
||||
-- Vec4
|
||||
-- This example adds a dashboard item that shows the state of a 4-vector value property.
|
||||
|
||||
local Item = {
|
||||
Identifier = "DashboardItemPropertyValue_Example_Vec4",
|
||||
Type = "DashboardItemPropertyValue",
|
||||
URI = "RenderEngine.EnabledFontColor",
|
||||
DisplayString = "Font Color (enabled): ({}, {}, {}, {})"
|
||||
}
|
||||
|
||||
asset.onInitialize(function()
|
||||
openspace.dashboard.addDashboardItem(Item)
|
||||
end)
|
||||
|
||||
asset.onDeinitialize(function()
|
||||
openspace.dashboard.removeDashboardItem(Item)
|
||||
end)
|
||||
+15
@@ -0,0 +1,15 @@
|
||||
-- Basic
|
||||
-- This example adds a dashboard item that shows the current simulation increment.
|
||||
|
||||
local Item = {
|
||||
Identifier = "DashboardItemSimulationIncrement_Example",
|
||||
Type = "DashboardItemSimulationIncrement"
|
||||
}
|
||||
|
||||
asset.onInitialize(function()
|
||||
openspace.dashboard.addDashboardItem(Item)
|
||||
end)
|
||||
|
||||
asset.onDeinitialize(function()
|
||||
openspace.dashboard.removeDashboardItem(Item)
|
||||
end)
|
||||
+17
@@ -0,0 +1,17 @@
|
||||
-- Nanoseconds
|
||||
-- This example adds a dashboard item that shows the current simulation increment always
|
||||
-- expressed in nanoseconds.
|
||||
|
||||
local Item = {
|
||||
Identifier = "DashboardItemSimulationIncrement_Example_NoDecoration",
|
||||
Type = "DashboardItemSimulationIncrement",
|
||||
RequestedUnit = "Nanosecond"
|
||||
}
|
||||
|
||||
asset.onInitialize(function()
|
||||
openspace.dashboard.addDashboardItem(Item)
|
||||
end)
|
||||
|
||||
asset.onDeinitialize(function()
|
||||
openspace.dashboard.removeDashboardItem(Item)
|
||||
end)
|
||||
+22
@@ -0,0 +1,22 @@
|
||||
-- No Decoration
|
||||
-- This example adds a dashboard item that shows the current simulation increment without
|
||||
-- any textual decorations. This example also shows how to ignore the first two parameters
|
||||
-- the `TransitionFormat` format string. Both the `TransitionFormat` and the
|
||||
-- `RegularFormat` string replacement markers allow the setting of numbers to determine
|
||||
-- which argument should be placed in here. The `TransitionFormat` in this example omits
|
||||
-- the numbers 0 and 1, thus ignoring the first two arguments to the string.
|
||||
|
||||
local Item = {
|
||||
Identifier = "DashboardItemSimulationIncrement_Example_NoDecoration",
|
||||
Type = "DashboardItemSimulationIncrement",
|
||||
TransitionFormat = "{3:.1f} {4:s} / second{2:s}",
|
||||
RegularFormat = "{:.1f} {:s} / second{:s}"
|
||||
}
|
||||
|
||||
asset.onInitialize(function()
|
||||
openspace.dashboard.addDashboardItem(Item)
|
||||
end)
|
||||
|
||||
asset.onDeinitialize(function()
|
||||
openspace.dashboard.removeDashboardItem(Item)
|
||||
end)
|
||||
@@ -0,0 +1,16 @@
|
||||
-- Basic
|
||||
-- This example adds a dashboard item that adds a spacing to the dashboard. This example
|
||||
-- will not show anything by itself.
|
||||
|
||||
local Item = {
|
||||
Identifier = "DashboardItemSpacing_Example",
|
||||
Type = "DashboardItemSpacing"
|
||||
}
|
||||
|
||||
asset.onInitialize(function()
|
||||
openspace.dashboard.addDashboardItem(Item)
|
||||
end)
|
||||
|
||||
asset.onDeinitialize(function()
|
||||
openspace.dashboard.removeDashboardItem(Item)
|
||||
end)
|
||||
@@ -0,0 +1,15 @@
|
||||
-- Basic
|
||||
-- This example adds a dashboard item that shows the speed of the camera.
|
||||
|
||||
local Item = {
|
||||
Identifier = "DashboardItemVelocity_Example",
|
||||
Type = "DashboardItemVelocity"
|
||||
}
|
||||
|
||||
asset.onInitialize(function()
|
||||
openspace.dashboard.addDashboardItem(Item)
|
||||
end)
|
||||
|
||||
asset.onDeinitialize(function()
|
||||
openspace.dashboard.removeDashboardItem(Item)
|
||||
end)
|
||||
@@ -0,0 +1,17 @@
|
||||
-- Nautical Miles
|
||||
-- This example adds a dashboard item that shows the speed of the camera, but always
|
||||
-- displayed in nautical miles per second (or knots).
|
||||
|
||||
local Item = {
|
||||
Identifier = "DashboardItemVelocity_Example_NauticalMiles",
|
||||
Type = "DashboardItemVelocity",
|
||||
RequestedUnit = "Nautical Mile"
|
||||
}
|
||||
|
||||
asset.onInitialize(function()
|
||||
openspace.dashboard.addDashboardItem(Item)
|
||||
end)
|
||||
|
||||
asset.onDeinitialize(function()
|
||||
openspace.dashboard.removeDashboardItem(Item)
|
||||
end)
|
||||
@@ -1,201 +0,0 @@
|
||||
asset.require("scene/solarsystem/planets/earth/earth")
|
||||
asset.require("scene/solarsystem/planets/earth/moon/moon")
|
||||
|
||||
local Angle = {
|
||||
Type = "DashboardItemAngle",
|
||||
Identifier = "Angle",
|
||||
ReferenceType = "Node",
|
||||
ReferenceNodeName = "Earth",
|
||||
DestinationType = "Node",
|
||||
DestinationNodeName = "Moon"
|
||||
}
|
||||
|
||||
local Date = {
|
||||
Type = "DashboardItemDate",
|
||||
Identifier = "Date"
|
||||
}
|
||||
|
||||
local SimulationIncrement = {
|
||||
Type = "DashboardItemSimulationIncrement",
|
||||
Identifier = "SimulationIncrement",
|
||||
GuiName = "Simulation Increment"
|
||||
}
|
||||
|
||||
local Distance = {
|
||||
Type = "DashboardItemDistance",
|
||||
Identifier = "Distance"
|
||||
}
|
||||
|
||||
local Framerate = {
|
||||
Type = "DashboardItemFramerate",
|
||||
Identifier = "Framerate"
|
||||
}
|
||||
|
||||
local ParallelConnection = {
|
||||
Type = "DashboardItemParallelConnection",
|
||||
Identifier = "ParallelConnection",
|
||||
GuiName = "Parallel Connection"
|
||||
}
|
||||
|
||||
local Mission = {
|
||||
Type = "DashboardItemMission",
|
||||
Identifier = "Mission"
|
||||
}
|
||||
|
||||
local PropertyValue = {
|
||||
Type = "DashboardItemPropertyValue",
|
||||
Identifier = "DashbaordItemPropertyValue",
|
||||
URI = "Scene.Earth.Renderable.Enabled",
|
||||
DisplayString = "Earth is enabled: {}"
|
||||
}
|
||||
|
||||
local PropertyValueFloat = {
|
||||
Type = "DashboardItemPropertyValue",
|
||||
Identifier = "DashbaordItemPropertyValue_Float",
|
||||
URI = "Scene.Earth.Renderable.TargetLodScaleFactor",
|
||||
DisplayString = "Earth LOD is {:.5f}"
|
||||
}
|
||||
|
||||
local PropertyValueDouble = {
|
||||
Type = "DashboardItemPropertyValue",
|
||||
Identifier = "DashbaordItemPropertyValue_Double",
|
||||
URI = "NavigationHandler.PathNavigator.ArrivalDistanceFactor",
|
||||
DisplayString = "Arrival Distance Factor is {:.8f}"
|
||||
}
|
||||
|
||||
local PropertyValueInt = {
|
||||
Type = "DashboardItemPropertyValue",
|
||||
Identifier = "DashbaordItemPropertyValue_Int",
|
||||
URI = "LuaConsole.HistoryLength",
|
||||
DisplayString = "History length is {}"
|
||||
}
|
||||
|
||||
local PropertyValueUInt = {
|
||||
Type = "DashboardItemPropertyValue",
|
||||
Identifier = "DashboardItemPropertyValue_UInt",
|
||||
URI = "Modules.Globebrowsing.TileCacheSize",
|
||||
DisplayString = "Tile Cache Size is {}"
|
||||
}
|
||||
|
||||
local PropertyValueDVec3 = {
|
||||
Type = "DashboardItemPropertyValue",
|
||||
Identifier = "DashboardItemPropertyValue_DVec3",
|
||||
URI = "Scene.SolarSystemBarycenter.Transform.Transform",
|
||||
DisplayString = "SSB Transform is: ({}, {}, {})"
|
||||
}
|
||||
|
||||
local PropertyValueIVec2 = {
|
||||
Type = "DashboardItemPropertyValue",
|
||||
Identifier = "DashboardItemPropertyValue_IVec2",
|
||||
URI = "Scene.SolarSystemBarycenter.Renderable.ScreenSpacePosition",
|
||||
DisplayString = "Random ScreenSpace Position: ({}, {})"
|
||||
}
|
||||
|
||||
local PropertyValueVec2 = {
|
||||
Type = "DashboardItemPropertyValue",
|
||||
Identifier = "DashboardItemPropertyValue_Vec2",
|
||||
URI = "Scene.EarthAtmosphere.Renderable.AtmosphereDimmingSunsetAngle",
|
||||
DisplayString = "Sunset Angle is ({}, {})"
|
||||
}
|
||||
|
||||
local PropertyValueVec3 = {
|
||||
Type = "DashboardItemPropertyValue",
|
||||
Identifier = "DashboardItemPropertyValue_Vec3",
|
||||
URI = "RenderEngine.GlobalRotation",
|
||||
DisplayString = "Global Rotation is ({}, {}, {})"
|
||||
}
|
||||
|
||||
local PropertyValueVec4 = {
|
||||
Type = "DashboardItemPropertyValue",
|
||||
Identifier = "DashboardItemPropertyValue_Vec4",
|
||||
URI = "LuaConsole.BackgroundColor",
|
||||
DisplayString = "Background Coolor is ({}, {}, {}, {})"
|
||||
}
|
||||
|
||||
local ElapsedTime = {
|
||||
Type = "DashboardItemElapsedTime",
|
||||
Identifier = "ElapsedTime",
|
||||
ReferenceTime = "2022-10-12 12:00:00"
|
||||
}
|
||||
|
||||
local InputState = {
|
||||
Type = "DashboardItemInputState",
|
||||
Identifier = "InputState"
|
||||
}
|
||||
|
||||
|
||||
asset.onInitialize(function()
|
||||
openspace.dashboard.addDashboardItem(Angle)
|
||||
openspace.dashboard.addDashboardItem(Date)
|
||||
openspace.dashboard.addDashboardItem(SimulationIncrement)
|
||||
openspace.dashboard.addDashboardItem(Distance)
|
||||
openspace.dashboard.addDashboardItem(Framerate)
|
||||
openspace.dashboard.addDashboardItem(ParallelConnection)
|
||||
openspace.dashboard.addDashboardItem(Mission)
|
||||
openspace.dashboard.addDashboardItem(PropertyValue)
|
||||
openspace.dashboard.addDashboardItem(PropertyValueFloat)
|
||||
openspace.dashboard.addDashboardItem(PropertyValueDouble)
|
||||
openspace.dashboard.addDashboardItem(PropertyValueInt)
|
||||
openspace.dashboard.addDashboardItem(PropertyValueUInt)
|
||||
openspace.dashboard.addDashboardItem(PropertyValueDVec3)
|
||||
openspace.dashboard.addDashboardItem(PropertyValueIVec2)
|
||||
openspace.dashboard.addDashboardItem(PropertyValueVec2)
|
||||
openspace.dashboard.addDashboardItem(PropertyValueVec3)
|
||||
openspace.dashboard.addDashboardItem(PropertyValueVec4)
|
||||
openspace.dashboard.addDashboardItem(ElapsedTime)
|
||||
openspace.dashboard.addDashboardItem(InputState)
|
||||
end)
|
||||
|
||||
asset.onDeinitialize(function()
|
||||
openspace.dashboard.removeDashboardItem(InputState)
|
||||
openspace.dashboard.removeDashboardItem(ElapsedTime)
|
||||
openspace.dashboard.removeDashboardItem(PropertyValueVec4)
|
||||
openspace.dashboard.removeDashboardItem(PropertyValueVec3)
|
||||
openspace.dashboard.removeDashboardItem(PropertyValueVec2)
|
||||
openspace.dashboard.removeDashboardItem(PropertyValueIVec2)
|
||||
openspace.dashboard.removeDashboardItem(PropertyValueDVec3)
|
||||
openspace.dashboard.removeDashboardItem(PropertyValueUInt)
|
||||
openspace.dashboard.removeDashboardItem(PropertyValueInt)
|
||||
openspace.dashboard.removeDashboardItem(PropertyValueDouble)
|
||||
openspace.dashboard.removeDashboardItem(PropertyValueFloat)
|
||||
openspace.dashboard.removeDashboardItem(PropertyValue)
|
||||
openspace.dashboard.removeDashboardItem(Mission)
|
||||
openspace.dashboard.removeDashboardItem(ParallelConnection)
|
||||
openspace.dashboard.removeDashboardItem(Framerate)
|
||||
openspace.dashboard.removeDashboardItem(Distance)
|
||||
openspace.dashboard.removeDashboardItem(SimulationIncrement)
|
||||
openspace.dashboard.removeDashboardItem(Date)
|
||||
openspace.dashboard.removeDashboardItem(Angle)
|
||||
end)
|
||||
|
||||
asset.export(Angle)
|
||||
asset.export(Date)
|
||||
asset.export(SimulationIncrement)
|
||||
asset.export(Distance)
|
||||
asset.export(Framerate)
|
||||
asset.export(ParallelConnection)
|
||||
asset.export(Mission)
|
||||
asset.export(PropertyValue)
|
||||
asset.export(PropertyValueFloat)
|
||||
asset.export(PropertyValueDouble)
|
||||
asset.export(PropertyValueInt)
|
||||
asset.export(PropertyValueUInt)
|
||||
asset.export(PropertyValueDVec3)
|
||||
asset.export(PropertyValueIVec2)
|
||||
asset.export(PropertyValueVec2)
|
||||
asset.export(PropertyValueVec3)
|
||||
asset.export(PropertyValueVec4)
|
||||
asset.export(ElapsedTime)
|
||||
asset.export(InputState)
|
||||
|
||||
|
||||
|
||||
asset.meta = {
|
||||
Name = "Dashboard Items Example",
|
||||
Description = [[Examples of different types of dashboard items. These are dynamic
|
||||
information texts that will be shown over the rendering (per default in the top
|
||||
left corner, on flat screens).]],
|
||||
Author = "OpenSpace Team",
|
||||
URL = "http://openspaceproject.com",
|
||||
License = "MIT license"
|
||||
}
|
||||
@@ -1,6 +1,6 @@
|
||||
-- Basic
|
||||
-- This example creates a SceneGraphNode that only displays coordinate axes. The
|
||||
-- parent is not set which defaults to placing the axes at the center of the Sun.
|
||||
-- This example creates a scene graph node that only displays coordinate axes. The parent
|
||||
-- is not set which defaults to placing the axes at the center of the Sun.
|
||||
|
||||
local Node = {
|
||||
Identifier = "RenderableCartesianAxes_Example",
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
-- With Parent
|
||||
-- This example creates a SceneGraphNode that displays coordinate axes of the given parent
|
||||
-- node, in this case Earth.
|
||||
-- This example creates a scene graph node that displays coordinate axes of the given
|
||||
-- parent node, in this case Earth.
|
||||
|
||||
local earth = asset.require("scene/solarsystem/planets/earth/earth")
|
||||
|
||||
|
||||
@@ -0,0 +1,24 @@
|
||||
-- Basic
|
||||
-- This example shows how to create a textured plane in 3D space, where the texture is
|
||||
-- loaded from a local file on disk.
|
||||
|
||||
local Node = {
|
||||
Identifier = "RenderablePlaneImageLocal_Example",
|
||||
Renderable = {
|
||||
Type = "RenderablePlaneImageLocal",
|
||||
Size = 3.0E11,
|
||||
Texture = openspace.absPath("${DATA}/test2.jpg")
|
||||
},
|
||||
GUI = {
|
||||
Name = "RenderablePlaneImageLocal - Basic",
|
||||
Path = "/Examples"
|
||||
}
|
||||
}
|
||||
|
||||
asset.onInitialize(function()
|
||||
openspace.addSceneGraphNode(Node)
|
||||
end)
|
||||
|
||||
asset.onDeinitialize(function()
|
||||
openspace.removeSceneGraphNode(Node)
|
||||
end)
|
||||
+26
@@ -0,0 +1,26 @@
|
||||
-- Billboard Image
|
||||
-- This example shows how to create a textured plane in 3D space, where the texture is
|
||||
-- loaded from a local file on disk and the plane is billboarded to always face the
|
||||
-- camera.
|
||||
|
||||
local Node = {
|
||||
Identifier = "RenderablePlaneImageLocal_Example_Billboard",
|
||||
Renderable = {
|
||||
Type = "RenderablePlaneImageLocal",
|
||||
Size = 3.0E11,
|
||||
Texture = openspace.absPath("${DATA}/test2.jpg"),
|
||||
Billboard = true
|
||||
},
|
||||
GUI = {
|
||||
Name = "RenderablePlaneImageLocal - Billboard",
|
||||
Path = "/Examples"
|
||||
}
|
||||
}
|
||||
|
||||
asset.onInitialize(function()
|
||||
openspace.addSceneGraphNode(Node)
|
||||
end)
|
||||
|
||||
asset.onDeinitialize(function()
|
||||
openspace.removeSceneGraphNode(Node)
|
||||
end)
|
||||
+4
-4
@@ -1,18 +1,18 @@
|
||||
-- Billboarded Image
|
||||
-- Billboard Image
|
||||
-- This example shows how to create a textured plane in 3D space, where the texture is
|
||||
-- loaded from the internet though a web URL and the plane is billboarded to always
|
||||
-- face the camera.
|
||||
|
||||
local Node = {
|
||||
Identifier = "RenderablePlaneImageOnline_Example_Billboarded",
|
||||
Identifier = "RenderablePlaneImageOnline_Example_Billboard",
|
||||
Renderable = {
|
||||
Type = "RenderablePlaneImageOnline",
|
||||
Size = 3.0E11,
|
||||
URL = "http://data.openspaceproject.com/examples/renderableplaneimageonline.jpg",
|
||||
Billboarded = true
|
||||
Billboard = true
|
||||
},
|
||||
GUI = {
|
||||
Name = "RenderablePlaneImageOnline - Billboarded",
|
||||
Name = "RenderablePlaneImageOnline - Billboard",
|
||||
Path = "/Examples"
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,56 @@
|
||||
-- Basic
|
||||
-- This asset creates a rotation that places coordinate axes close to a sphere with the
|
||||
-- z axis pointing towards the sphere. The coordinate axes are translated away from the
|
||||
-- sphere to make that orientation more obvious.
|
||||
--
|
||||
-- Making the `YAxis` `{ 0.0, 1.0, 0.0 }` and actually using the orthogonal projection of
|
||||
-- that direction means that the y axis of the new coordinate system will point in the
|
||||
-- hemisphere in which the old y-axis was pointing, albeit being orthogonal to the other
|
||||
-- specified axis. That axis is pointing towards the scene graph node holding the sphere.
|
||||
|
||||
local Sphere = {
|
||||
Identifier = "FixedRotation_Example_Sphere",
|
||||
Transform = {
|
||||
Translation = {
|
||||
Type = "StaticTranslation",
|
||||
Position = { 2.0, 1.5, 1.0 }
|
||||
}
|
||||
},
|
||||
Renderable = {
|
||||
Type = "RenderableSphericalGrid"
|
||||
},
|
||||
GUI = {
|
||||
Name = "FixedRotation - Basic (Sphere)",
|
||||
Path = "/Examples"
|
||||
}
|
||||
}
|
||||
|
||||
local Node = {
|
||||
Identifier = "FixedRotation_Example",
|
||||
Transform = {
|
||||
Rotation = {
|
||||
Type = "FixedRotation",
|
||||
Attached = "FixedRotation_Example",
|
||||
YAxis = { 0.0, 1.0, 0.0 },
|
||||
YAxisOrthogonal = true,
|
||||
ZAxis = "FixedRotation_Example_Sphere"
|
||||
}
|
||||
},
|
||||
Renderable = {
|
||||
Type = "RenderableCartesianAxes"
|
||||
},
|
||||
GUI = {
|
||||
Name = "FixedRotation - Basic",
|
||||
Path = "/Examples"
|
||||
}
|
||||
}
|
||||
|
||||
asset.onInitialize(function()
|
||||
openspace.addSceneGraphNode(Sphere)
|
||||
openspace.addSceneGraphNode(Node)
|
||||
end)
|
||||
|
||||
asset.onDeinitialize(function()
|
||||
openspace.removeSceneGraphNode(Node)
|
||||
openspace.removeSceneGraphNode(Sphere)
|
||||
end)
|
||||
@@ -0,0 +1,33 @@
|
||||
-- Axis Mapping
|
||||
-- This asset creates a rotation that shows coordinate axes in which the x and the y axes
|
||||
-- are flipped. While this could also be achieved with a
|
||||
-- [ConstantRotation](#base_transform_rotation_constant) class, this serves as an example
|
||||
-- for more elaborate coordinate system mappings, such as converting to a coordinate
|
||||
-- system with a known coordinate axes.
|
||||
|
||||
local Node = {
|
||||
Identifier = "FixedRotation_Example_Mapping",
|
||||
Transform = {
|
||||
Rotation = {
|
||||
Type = "FixedRotation",
|
||||
XAxis = { 0.0, 1.0, 0.0 },
|
||||
YAxis = { 1.0, 0.0, 0.0 },
|
||||
ZAxis = { 0.0, 0.0, 1.0 }
|
||||
}
|
||||
},
|
||||
Renderable = {
|
||||
Type = "RenderableCartesianAxes"
|
||||
},
|
||||
GUI = {
|
||||
Name = "FixedRotation - Mapping",
|
||||
Path = "/Examples"
|
||||
}
|
||||
}
|
||||
|
||||
asset.onInitialize(function()
|
||||
openspace.addSceneGraphNode(Node)
|
||||
end)
|
||||
|
||||
asset.onDeinitialize(function()
|
||||
openspace.removeSceneGraphNode(Node)
|
||||
end)
|
||||
@@ -0,0 +1,56 @@
|
||||
-- Inverted Axis
|
||||
-- This asset creates a rotation that places coordinate axes close to a sphere with the z
|
||||
-- axis pointing away from the sphere. The coordinate axes are translated away from the
|
||||
-- sphere to make that orientation more obvious.
|
||||
--
|
||||
-- Making the `YAxis` { 0.0, 1.0, 0.0 } and actually using the orthogonal projection of
|
||||
-- that direction means that the y axis of the new coordinate system will point in the
|
||||
-- hemisphere in which the old y-axis was pointing, albeit being orthogonal to the other
|
||||
-- specified axis. That axis is pointing towards the scene graph node holding the sphere.
|
||||
local Sphere = {
|
||||
Identifier = "FixedRotation_Example_InvertedAxis_Sphere",
|
||||
Transform = {
|
||||
Translation = {
|
||||
Type = "StaticTranslation",
|
||||
Position = { 2.0, 1.5, 1.0 }
|
||||
}
|
||||
},
|
||||
Renderable = {
|
||||
Type = "RenderableSphericalGrid"
|
||||
},
|
||||
GUI = {
|
||||
Name = "FixedRotation - Inverted Axis (Sphere)",
|
||||
Path = "/Examples"
|
||||
}
|
||||
}
|
||||
|
||||
local Node = {
|
||||
Identifier = "FixedRotation_Example_InvertedAxis",
|
||||
Transform = {
|
||||
Rotation = {
|
||||
Type = "FixedRotation",
|
||||
Attached = "FixedRotation_Example_InvertedAxis",
|
||||
YAxis = { 0.0, 1.0, 0.0 },
|
||||
YAxisOrthogonal = true,
|
||||
ZAxis = Sphere.Identifier,
|
||||
ZAxisInvert = true
|
||||
}
|
||||
},
|
||||
Renderable = {
|
||||
Type = "RenderableCartesianAxes"
|
||||
},
|
||||
GUI = {
|
||||
Name = "FixedRotation - Inverted Axis",
|
||||
Path = "/Examples"
|
||||
}
|
||||
}
|
||||
|
||||
asset.onInitialize(function()
|
||||
openspace.addSceneGraphNode(Sphere)
|
||||
openspace.addSceneGraphNode(Node)
|
||||
end)
|
||||
|
||||
asset.onDeinitialize(function()
|
||||
openspace.removeSceneGraphNode(Node)
|
||||
openspace.removeSceneGraphNode(Sphere)
|
||||
end)
|
||||
@@ -0,0 +1,87 @@
|
||||
-- Rotation Following Two Moving Objects
|
||||
-- This asset creates a rotation that places coordinate axes orbiting close to two spheres
|
||||
-- with the y axis always pointing towards the first sphere and the z axis always pointing
|
||||
-- towards the second sphere as the coordinate system moves around. The set of coordinate
|
||||
-- axes are orbiting using a [KeplerTranslation](#space_transform_kepler) that provides a
|
||||
-- configurable orbital motion. The use of the
|
||||
-- [KeplerTranslation](#space_transform_kepler) in this example is arbitrary and the
|
||||
-- FixedRotation does not depend on the use of that class. We use it in this example as we
|
||||
-- want a moving object to show that the `FixedRotation` will always point at the object,
|
||||
-- even as it is moving.
|
||||
--
|
||||
-- Note that in this example the coordinate system will be skewed as, in general, it is
|
||||
-- not guaranteed that the direction from the node to the two spheres will be an
|
||||
-- orthogonal vector.
|
||||
|
||||
local Sphere1 = {
|
||||
Identifier = "FixedRotation_Example_Moving_TwoObjects_Sphere1",
|
||||
Transform = {
|
||||
Translation = {
|
||||
Type = "StaticTranslation",
|
||||
Position = { 3.0, -2.0, 0.0 }
|
||||
}
|
||||
},
|
||||
Renderable = {
|
||||
Type = "RenderableSphericalGrid"
|
||||
},
|
||||
GUI = {
|
||||
Name = "FixedRotation - Moving Two Objects (Sphere 1)",
|
||||
Path = "/Examples"
|
||||
}
|
||||
}
|
||||
|
||||
local Sphere2 = {
|
||||
Identifier = "FixedRotation_Example_Moving_TwoObjects_Sphere2",
|
||||
Transform = {
|
||||
Translation = {
|
||||
Type = "KeplerTranslation",
|
||||
Eccentricity = 0.5,
|
||||
SemiMajorAxis = 0.0025,
|
||||
Inclination = 0.0,
|
||||
AscendingNode = 0.0,
|
||||
ArgumentOfPeriapsis = 0.0,
|
||||
MeanAnomaly = 0.0,
|
||||
Epoch = "2000 JAN 01 12:00:00",
|
||||
Period = 10.0
|
||||
}
|
||||
},
|
||||
Renderable = {
|
||||
Type = "RenderableSphericalGrid"
|
||||
},
|
||||
GUI = {
|
||||
Name = "FixedRotation - Moving Two Objects (Sphere 2)",
|
||||
Path = "/Examples"
|
||||
}
|
||||
}
|
||||
|
||||
local Node = {
|
||||
Identifier = "FixedRotation_Example_Moving_TwoObjects",
|
||||
Transform = {
|
||||
Rotation = {
|
||||
Type = "FixedRotation",
|
||||
Attached = "FixedRotation_Example_Moving_TwoObjects",
|
||||
YAxis = Sphere1.Identifier,
|
||||
YAxisOrthogonal = true,
|
||||
ZAxis = Sphere2.Identifier
|
||||
}
|
||||
},
|
||||
Renderable = {
|
||||
Type = "RenderableCartesianAxes"
|
||||
},
|
||||
GUI = {
|
||||
Name = "FixedRotation - Moving Two Objects",
|
||||
Path = "/Examples"
|
||||
}
|
||||
}
|
||||
|
||||
asset.onInitialize(function()
|
||||
openspace.addSceneGraphNode(Sphere1)
|
||||
openspace.addSceneGraphNode(Sphere2)
|
||||
openspace.addSceneGraphNode(Node)
|
||||
end)
|
||||
|
||||
asset.onDeinitialize(function()
|
||||
openspace.removeSceneGraphNode(Node)
|
||||
openspace.removeSceneGraphNode(Sphere2)
|
||||
openspace.removeSceneGraphNode(Sphere1)
|
||||
end)
|
||||
@@ -0,0 +1,63 @@
|
||||
-- Rotation Following One Moving Object
|
||||
-- This asset creates a rotation that places coordinate axes orbiting close to a sphere
|
||||
-- with the z axis always pointing towards the sphere as it orbits around the sphere. The
|
||||
-- coordinate axes are translated away from the sphere to make that orientation more
|
||||
-- obvious.
|
||||
--
|
||||
-- Making the `YAxis` { 0.0, 1.0, 0.0 } and actually using the orthogonal projection of
|
||||
-- that direction means that the y axis of the new coordinate system will point in the
|
||||
-- hemisphere in which the old y-axis was pointing, albeit being orthogonal to the other
|
||||
-- specified axis. That axis is pointing towards the scene graph node holding the sphere.
|
||||
local Sphere = {
|
||||
Identifier = "FixedRotation_Example_Moving_Sphere",
|
||||
Transform = {
|
||||
Translation = {
|
||||
Type = "KeplerTranslation",
|
||||
Eccentricity = 0.5,
|
||||
SemiMajorAxis = 0.0025,
|
||||
Inclination = 0.0,
|
||||
AscendingNode = 0.0,
|
||||
ArgumentOfPeriapsis = 0.0,
|
||||
MeanAnomaly = 0.0,
|
||||
Epoch = "2000 JAN 01 12:00:00",
|
||||
Period = 10.0
|
||||
}
|
||||
},
|
||||
Renderable = {
|
||||
Type = "RenderableSphericalGrid"
|
||||
},
|
||||
GUI = {
|
||||
Name = "FixedRotation - Moving (Sphere)",
|
||||
Path = "/Examples"
|
||||
}
|
||||
}
|
||||
|
||||
local Node = {
|
||||
Identifier = "FixedRotation_Example_Moving",
|
||||
Transform = {
|
||||
Rotation = {
|
||||
Type = "FixedRotation",
|
||||
Attached = "FixedRotation_Example_Moving",
|
||||
YAxis = { 0.0, 1.0, 0.0 },
|
||||
YAxisOrthogonal = true,
|
||||
ZAxis = Sphere.Identifier
|
||||
}
|
||||
},
|
||||
Renderable = {
|
||||
Type = "RenderableCartesianAxes"
|
||||
},
|
||||
GUI = {
|
||||
Name = "FixedRotation - Moving",
|
||||
Path = "/Examples"
|
||||
}
|
||||
}
|
||||
|
||||
asset.onInitialize(function()
|
||||
openspace.addSceneGraphNode(Sphere)
|
||||
openspace.addSceneGraphNode(Node)
|
||||
end)
|
||||
|
||||
asset.onDeinitialize(function()
|
||||
openspace.removeSceneGraphNode(Node)
|
||||
openspace.removeSceneGraphNode(Sphere)
|
||||
end)
|
||||
@@ -1,7 +1,7 @@
|
||||
-- Basic
|
||||
-- This asset creates a SceneGraphNode that only displays coordinate axes. The rotation of
|
||||
-- coordinate axes are determined by executing a Lua file that returns the rotation matrix
|
||||
-- to be used.
|
||||
-- This asset creates a scene graph node that only displays coordinate axes. The rotation
|
||||
-- of coordinate axes are determined by executing a Lua file that returns the rotation
|
||||
-- matrix to be used.
|
||||
--
|
||||
-- ```{literalinclude} example.lua
|
||||
-- :language: lua
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
-- Basic
|
||||
-- This asset creates a SceneGraphNode that only displays coordinate axes. The rotation of
|
||||
-- the coordinate axes are determined by a combination of individual rotations. The
|
||||
-- This asset creates a scene graph node that only displays coordinate axes. The rotation
|
||||
-- of the coordinate axes are determined by a combination of individual rotations. The
|
||||
-- rotations are applied in the order in which they are specified
|
||||
|
||||
local Node = {
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
-- Basic
|
||||
-- This asset creates a rotation provided by a SPICE kernel and applies it to a
|
||||
-- SceneGraphNode that only displays coordinate axes. The rotation of the coordinate axes
|
||||
-- are determined by SPICE, in this case pretending that the coordinate axes are rotating
|
||||
-- at the same rate as Earth.
|
||||
-- This asset creates a rotation provided by a SPICE kernel and applies it to a scene
|
||||
-- graph node that only displays coordinate axes. The rotation of the coordinate axes are
|
||||
-- determined by SPICE, in this case pretending that the coordinate axes are rotating at
|
||||
-- the same rate as Earth.
|
||||
-- For more information about SPICE see: https://naif.jpl.nasa.gov/naif/
|
||||
|
||||
-- Load the default SPICE kernels, which are the planetary constants and the DE430 kernel
|
||||
|
||||
+5
-5
@@ -1,9 +1,9 @@
|
||||
-- Fixed Date
|
||||
-- This asset creates a rotation provided by a SPICE kernel and applies it to a
|
||||
-- SceneGraphNode that only displays coordinate axes. The rotation of the coordinate axes
|
||||
-- are determined by SPICE, in this case pretending that the coordinate axes are rotating
|
||||
-- at the same rate as Earth. In this specific example, the orientation is independent of
|
||||
-- the actual in-game time in OpenSpace and only uses a fixed date of 2000 JAN 01 instead.
|
||||
-- This asset creates a rotation provided by a SPICE kernel and applies it to a scene
|
||||
-- graph node that only displays coordinate axes. The rotation of the coordinate axes are
|
||||
-- determined by SPICE, in this case pretending that the coordinate axes are rotating at
|
||||
-- the same rate as Earth. In this specific example, the orientation is independent of the
|
||||
-- actual in-game time in OpenSpace and only uses a fixed date of 2000 JAN 01 instead.
|
||||
|
||||
-- Load the default SPICE kernels, which is the planetary constants and the DE430 kernel
|
||||
asset.require("spice/core")
|
||||
+6
-6
@@ -1,10 +1,10 @@
|
||||
-- TimeFrame
|
||||
-- This asset creates a rotation provided by a SPICE kernel and applies it to a
|
||||
-- SceneGraphNode that only displays coordinate axes. The rotation of the coordinate axes
|
||||
-- are determined by SPICE, in this case pretending that the coordinate axes are rotating
|
||||
-- at the same rate as Earth. In this example, the rotation is only calculated between
|
||||
-- 2000 JAN 01 and 2002 JAN 01 to exemplify a use-case in which the data from the SPICE
|
||||
-- kernel is not available for the whole duration.
|
||||
-- This asset creates a rotation provided by a SPICE kernel and applies it to a scene
|
||||
-- graph node that only displays coordinate axes. The rotation of the coordinate axes are
|
||||
-- determined by SPICE, in this case pretending that the coordinate axes are rotating at
|
||||
-- the same rate as Earth. In this example, the rotation is only calculated between 2000
|
||||
-- JAN 01 and 2002 JAN 01 to exemplify a use-case in which the data from the SPICE kernel
|
||||
-- is not available for the whole duration.
|
||||
|
||||
-- Load the default SPICE kernels, which is the planetary constants and the DE430 kernel
|
||||
asset.require("spice/core")
|
||||
@@ -1,8 +1,8 @@
|
||||
-- Time offset
|
||||
-- This asset creates a rotation provided by a SPICE kernel and applies it to a
|
||||
-- SceneGraphNode that only displays coordinate axes. The rotation of the coordinate axes
|
||||
-- are determined by SPICE, in this case pretending that the coordinate axes are rotating
|
||||
-- at the same rate as Earth. In this specific example, the orientation is offset 8h back
|
||||
-- This asset creates a rotation provided by a SPICE kernel and applies it to a scene
|
||||
-- graph node that only displays coordinate axes. The rotation of the coordinate axes are
|
||||
-- determined by SPICE, in this case pretending that the coordinate axes are rotating at
|
||||
-- the same rate as Earth. In this specific example, the orientation is offset 8h back
|
||||
-- compared to the actual in-game time in OpenSpace.
|
||||
|
||||
-- Load the default SPICE kernels, which is the planetary constants and the DE430 kernel
|
||||
|
||||
+3
-3
@@ -1,7 +1,7 @@
|
||||
-- Euler Angles
|
||||
-- This asset creates a rotation provided by Euler angles and applies it to a
|
||||
-- SceneGraphNode that only displays coordinate axes. The rotation of the coordinate axes
|
||||
-- are determined by a constant and unchanging static rotation.
|
||||
-- This asset creates a rotation provided by Euler angles and applies it to a scene graph
|
||||
-- node that only displays coordinate axes. The rotation of the coordinate axes are
|
||||
-- determined by a constant and unchanging static rotation.
|
||||
|
||||
local Node = {
|
||||
Identifier = "StaticRotation_Example_Euler",
|
||||
+3
-3
@@ -1,7 +1,7 @@
|
||||
-- Matrix
|
||||
-- This asset creates a SceneGraphNode that only displays coordinate axes. The rotation of
|
||||
-- the coordinate axes are determined by a constant and unchanging static rotation that is
|
||||
-- provided by a 3-by-3 rotation matrix in column-major order.
|
||||
-- This asset creates a scene graph node that only displays coordinate axes. The rotation
|
||||
-- of the coordinate axes are determined by a constant and unchanging static rotation that
|
||||
-- is provided by a 3-by-3 rotation matrix in column-major order.
|
||||
|
||||
local Node = {
|
||||
Identifier = "StaticRotation_Example_Matrix",
|
||||
+3
-3
@@ -1,7 +1,7 @@
|
||||
-- Quaternion
|
||||
-- This asset creates a SceneGraphNode that only displays coordinate axes. The rotation of
|
||||
-- the coordinate axes are determined by a constant and unchanging static rotation that is
|
||||
-- provided by a four-dimensional quaternion.
|
||||
-- This asset creates a scene graph node that only displays coordinate axes. The rotation
|
||||
-- of the coordinate axes are determined by a constant and unchanging static rotation that
|
||||
-- is provided by a four-dimensional quaternion.
|
||||
|
||||
local Node = {
|
||||
Identifier = "StaticRotation_Example_Quaternion",
|
||||
@@ -1,9 +1,9 @@
|
||||
-- Basic
|
||||
-- This asset creates a SceneGraphNode that only displays coordinate axes. The rotation of
|
||||
-- the coordinate axes are determined by a timeline of individual rotations. These rotations
|
||||
-- are keyframes that are used to seamlessly change between different orientations. This
|
||||
-- example transitions between three rotations over a long time span. This example will
|
||||
-- only work if the in-game time is set to January 1st, 2000.
|
||||
-- This asset creates a scene graph node that only displays coordinate axes. The rotation
|
||||
-- of the coordinate axes are determined by a timeline of individual rotations. These
|
||||
-- rotations are keyframes that are used to seamlessly change between different
|
||||
-- orientations. This example transitions between three rotations over a long time span.
|
||||
-- This example will only work if the in-game time is set to January 1st, 2000.
|
||||
|
||||
local Node = {
|
||||
Identifier = "TimelineRotation_Example",
|
||||
|
||||
+9
-9
@@ -1,13 +1,13 @@
|
||||
-- No Interpolation
|
||||
-- This asset creates a SceneGraphNode that only displays coordinate axes. The rotation of
|
||||
-- the coordinate axes are determined by a timeline of individual rotations that are used
|
||||
-- without interpolating between the timeline entries. These rotations are keyframes that
|
||||
-- are used to change between different orientations. This example transitions between
|
||||
-- three rotations. In this example, the interpolation between entries is disabled, which
|
||||
-- will cause the coordinate axes to change their orientation abruptly when the rotation
|
||||
-- changes. If the interpolation were enabled, the orientation of the coordinate axes
|
||||
-- would transition seamlessly instead at the provided times. This example will only work
|
||||
-- if the in-game time is set to January 1st, 2000.
|
||||
-- This asset creates a scene graph node that only displays coordinate axes. The rotation
|
||||
-- of the coordinate axes are determined by a timeline of individual rotations that are
|
||||
-- used without interpolating between the timeline entries. These rotations are keyframes
|
||||
-- that are used to change between different orientations. This example transitions
|
||||
-- between three rotations. In this example, the interpolation between entries is
|
||||
-- disabled, which will cause the coordinate axes to change their orientation abruptly
|
||||
-- when the rotation changes. If the interpolation were enabled, the orientation of the
|
||||
-- coordinate axes would transition seamlessly instead at the provided times. This example
|
||||
-- will only work if the in-game time is set to January 1st, 2000.
|
||||
|
||||
local Node = {
|
||||
Identifier = "TimelineRotation_Example_NoInterpolation",
|
||||
@@ -1,5 +1,5 @@
|
||||
-- Basic
|
||||
-- This asset creates a SceneGraphNode that only displays coordinate axes. The sizes of
|
||||
-- This asset creates a scene graph node that only displays coordinate axes. The sizes of
|
||||
-- coordinate axes are determined by executing a Lua file that returns the scaling
|
||||
-- parameters to be used as a table.
|
||||
--
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
-- Basic
|
||||
-- This asset creates a SceneGraphNode that only displays coordinate axes, with a set of
|
||||
-- This asset creates a scene graph node that only displays coordinate axes, with a set of
|
||||
-- multiple scales that are applied one after the other.
|
||||
|
||||
local Node = {
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
-- Basic
|
||||
-- This asset creates a SceneGraphNode that only displays coordinate axes. The coordinate
|
||||
-- axis normally have a length of 1 meter and are scaled in this example by different
|
||||
-- values for each axis. The x axis is scaled by a factor of 149597870700, which means
|
||||
-- they will be 149597870700 m (1 AU) long and thus reaching the same distance as Earth's
|
||||
-- orbit around the Sun. The y-axis stays at its original size, and the z-axis will be
|
||||
-- hidden entirely by setting the scale value close to 0.
|
||||
-- This asset creates a scene graph node that only displays coordinate axes. The
|
||||
-- coordinate axis normally have a length of 1 meter and are scaled in this example by
|
||||
-- different values for each axis. The x axis is scaled by a factor of 149597870700, which
|
||||
-- means they will be 149597870700 m (1 AU) long and thus reaching the same distance as
|
||||
-- Earth's orbit around the Sun. The y-axis stays at its original size, and the z-axis
|
||||
-- will be hidden entirely by setting the scale value close to 0.
|
||||
|
||||
local Node = {
|
||||
Identifier = "NonUniformStaticScale_Example",
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
-- Ellipsoid
|
||||
-- This asset creates a SceneGraphNode that is rendering a sphere which is adjust to an
|
||||
-- This asset creates a scene graph node that is rendering a sphere which is adjust to an
|
||||
-- ellipsoidal shape by using a non-uniform scaling. In particular, the second axis is
|
||||
-- half as long as the first, and the third axis is a third as long.
|
||||
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
-- Basic
|
||||
-- This asset creates a SceneGraphNode that only displays coordinate axes. The coordinate
|
||||
-- axis normally have a length of 1 meter and are scaled in this example by a factor of
|
||||
-- 149597870700, which means they will be 149597870700 m (1 AU) long, thus reaching the
|
||||
-- same distance as Earth's orbit around the Sun.
|
||||
-- This asset creates a scene graph node that only displays coordinate axes. The
|
||||
-- coordinate axis normally have a length of 1 meter and are scaled in this example by a
|
||||
-- factor of 149597870700, which means they will be 149597870700 m (1 AU) long, thus
|
||||
-- reaching the same distance as Earth's orbit around the Sun.
|
||||
|
||||
local Node = {
|
||||
Identifier = "StaticScale_Example",
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
-- Basic
|
||||
-- This asset creates a SceneGraphNode that only displays coordinate axes, which grow at
|
||||
-- This asset creates a scene graph node that only displays coordinate axes, which grow at
|
||||
-- a speed of 1 m/s starting on January 1st, 2000 00:00:00. This means that on
|
||||
-- that date, the coordinate axes will disappear and, for example, on January 1st, 2000
|
||||
-- 12:00:00, the coordinate axes will be 43200 meters long.
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
-- with Speed
|
||||
-- This asset creates a SceneGraphNode that only displays coordinate axes, which grow at
|
||||
-- This asset creates a scene graph node that only displays coordinate axes, which grow at
|
||||
-- a speed of 12 km/s starting on August 8th, 1969 12:00:00. This means that on
|
||||
-- that date, the coordinate axes will disappear and, for example, on August 8th, 1969
|
||||
-- 23:00:00, the coordinate axes will be 475200 km long.
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
-- No Interpolation
|
||||
-- This asset creates a SceneGraphNode that only displays coordinate axes. The scale of
|
||||
-- This asset creates a scene graph node that only displays coordinate axes. The scale of
|
||||
-- the coordinate axes are determined by a timeline of individual scales that are used
|
||||
-- without interpolating between the timeline entries. These scales are keyframes that are
|
||||
-- used to change between different sizes. This example transitions between three sizes.
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
-- Basic
|
||||
-- This asset creates a SceneGraphNode that only displays coordinate axes. The scale of
|
||||
-- This asset creates a scene graph node that only displays coordinate axes. The scale of
|
||||
-- the coordinate axes are determined by a timeline of individual scales. These scales
|
||||
-- are keyframes that are used to seamlessly change between different sizes. This example
|
||||
-- transitions between three scales over a long time span. This example will only work if
|
||||
|
||||
@@ -0,0 +1,53 @@
|
||||
-- No Interpolation
|
||||
-- This asset creates a scene graph node that only displays coordinate axes whose scale is
|
||||
-- determined by a timeline of individual scales that are used without interpolating
|
||||
-- between the timeline entries. These scales are keyframes that are used to change
|
||||
-- between different sizes.
|
||||
--
|
||||
-- This example transitions between three sizes, but as the interpolation between entries
|
||||
-- is disabled, it will cause the coordinate axes to change their size abruptly when the
|
||||
-- scale changes. If the interpolation were enabled, the orientation of the coordinate
|
||||
-- axes would transition seamlessly instead at the provided times. This example will only
|
||||
-- work if the in-game time is set to January 1st, 2000.
|
||||
|
||||
local Node = {
|
||||
Identifier = "TimelineScale_Example_NoInterpolation",
|
||||
Transform = {
|
||||
Scale = {
|
||||
Type = "TimelineScale",
|
||||
Keyframes = {
|
||||
-- The first timeline entry
|
||||
["2000 JAN 01 00:00:00"] = {
|
||||
Type = "StaticScale",
|
||||
Scale = 10.0
|
||||
},
|
||||
-- The second timeline entry
|
||||
["2000 JAN 01 12:00:00"] = {
|
||||
Type = "StaticScale",
|
||||
Scale = 0.0
|
||||
},
|
||||
-- The third timeline entry
|
||||
["2000 JAN 01 23:59:59"] = {
|
||||
Type = "StaticScale",
|
||||
Scale = -10.0
|
||||
}
|
||||
},
|
||||
ShouldInterpolate = false
|
||||
}
|
||||
},
|
||||
Renderable = {
|
||||
Type = "RenderableCartesianAxes"
|
||||
},
|
||||
GUI = {
|
||||
Name = "TimelineScale - No Interpolation",
|
||||
Path = "/Examples"
|
||||
}
|
||||
}
|
||||
|
||||
asset.onInitialize(function()
|
||||
openspace.addSceneGraphNode(Node)
|
||||
end)
|
||||
|
||||
asset.onDeinitialize(function()
|
||||
openspace.removeSceneGraphNode(Node)
|
||||
end)
|
||||
@@ -16,7 +16,7 @@ local Dashboard = {
|
||||
FontSize = 40,
|
||||
SourceType = "Camera",
|
||||
DestinationType = "Node",
|
||||
DestinationNodeName = earth.Earth.Identifier,
|
||||
DestinationNodeIdentifier = earth.Earth.Identifier,
|
||||
-- Specify to use a specific unit, by disabling the automatic simplification of
|
||||
-- unit and instead use light-years
|
||||
Simplification = false,
|
||||
|
||||
+22
@@ -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)
|
||||
+24
@@ -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)
|
||||
+41
@@ -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)
|
||||
+47
@@ -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)
|
||||
@@ -0,0 +1,28 @@
|
||||
-- Basic
|
||||
-- This example creates time frame interval and uses it for a scene graph node displaying
|
||||
-- a set of coordinate axes. The time frame interval causes the scene graph node to only
|
||||
-- be valid between January 1st, 2000 and March 1st, 2002.
|
||||
|
||||
local Node = {
|
||||
Identifier = "TimeFrameInterval_Example",
|
||||
TimeFrame = {
|
||||
Type = "TimeFrameInterval",
|
||||
Start = "2000 JAN 01 00:00:00.000",
|
||||
End = "2002 MAR 02 00:00:00.00"
|
||||
},
|
||||
Renderable = {
|
||||
Type = "RenderableCartesianAxes"
|
||||
},
|
||||
GUI = {
|
||||
Name = "TimeFrameInterval - Basic",
|
||||
Path = "/Examples"
|
||||
}
|
||||
}
|
||||
|
||||
asset.onInitialize(function()
|
||||
openspace.addSceneGraphNode(Node)
|
||||
end)
|
||||
|
||||
asset.onDeinitialize(function()
|
||||
openspace.removeSceneGraphNode(Node)
|
||||
end)
|
||||
@@ -13,13 +13,13 @@ local Node = {
|
||||
{
|
||||
Type = "TimeFrameInterval",
|
||||
Start = "2000 JAN 01 00:00:00.000",
|
||||
End = "2000 JAN 01 23:59:59.999"
|
||||
End = "2000 JAN 02 00:00:00.000"
|
||||
},
|
||||
-- The second TimeFrameInterval for the second day
|
||||
{
|
||||
Type = "TimeFrameInterval",
|
||||
Start = "2002 MAR 01 00:00:00.000",
|
||||
End = "2002 MAR 01 23:59:59.999"
|
||||
End = "2002 MAR 02 00:00:00.000"
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
@@ -1,8 +1,9 @@
|
||||
-- Basic
|
||||
-- This asset creates a SceneGraphNode that only displays coordinate axes. The coordinate
|
||||
-- axes are translated by a value determined by executing a Lua file that returns the
|
||||
-- translation parameters to be used as a table. In order to see the translation, we need
|
||||
-- to also have a node that does not move so that we can see the relative movement.
|
||||
-- This asset creates a scene graph node that only displays coordinate axes. The
|
||||
-- coordinate axes are translated by a value determined by executing a Lua file that
|
||||
-- returns the translation parameters to be used as a table. In order to see the
|
||||
-- translation, we need to also have a node that does not move so that we can see the
|
||||
-- relative movement.
|
||||
--
|
||||
-- ```{literalinclude} example.lua
|
||||
-- :language: lua
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
-- Basic
|
||||
-- This asset creates a time-varying translation with information from a SPICE kernel and
|
||||
-- applies it to a SceneGraphNode that only displays coordinate axes. The position of the
|
||||
-- coordinate axes are determined by SPICE, in this case pretending that the axes are
|
||||
-- applies it to a scene graph node that only displays coordinate axes. The position of
|
||||
-- the coordinate axes are determined by SPICE, in this case pretending that the axes are
|
||||
-- orbiting the same way the Moon does around Earth.
|
||||
-- For more information about SPICE see: https://naif.jpl.nasa.gov/naif/
|
||||
|
||||
|
||||
+2
-2
@@ -1,7 +1,7 @@
|
||||
-- Fixed Date
|
||||
-- This asset creates a time-varying translation with information from a SPICE kernel and
|
||||
-- applies it to a SceneGraphNode that only displays coordinate axes. The position of the
|
||||
-- coordinate axes are determined by SPICE, in this case pretending that the axes are
|
||||
-- applies it to a scene graph node that only displays coordinate axes. The position of
|
||||
-- the coordinate axes are determined by SPICE, in this case pretending that the axes are
|
||||
-- orbiting the same way the Moon does around Earth. In this specific example, the
|
||||
-- position is independent of the actual in-game time in OpenSpace and only uses a fixed
|
||||
-- date of 2000 JAN 01 instead.
|
||||
+2
-2
@@ -1,7 +1,7 @@
|
||||
-- Reference Frame
|
||||
-- This asset creates a time-varying translation with information from a SPICE kernel and
|
||||
-- applies it to a SceneGraphNode that only displays coordinate axes. The position of the
|
||||
-- coordinate axes are determined by SPICE, in this case pretending that the axes are
|
||||
-- applies it to a scene graph node that only displays coordinate axes. The position of
|
||||
-- the coordinate axes are determined by SPICE, in this case pretending that the axes are
|
||||
-- orbiting the same way the Moon does around Earth. The calculated position will be
|
||||
-- provided in the rotating coordinate system of Earth itself.
|
||||
-- For more information about SPICE see: https://naif.jpl.nasa.gov/naif/
|
||||
@@ -1,7 +1,7 @@
|
||||
-- Fixed Date
|
||||
-- This asset creates a time-varying translation with information from a SPICE kernel and
|
||||
-- applies it to a SceneGraphNode that only displays coordinate axes. The position of the
|
||||
-- coordinate axes are determined by SPICE, in this case pretending that the axes are
|
||||
-- applies it to a scene graph node that only displays coordinate axes. The position of
|
||||
-- the coordinate axes are determined by SPICE, in this case pretending that the axes are
|
||||
-- orbiting the same way the Moon does around Earth. In this specific example, the position
|
||||
-- is offset 8h back compared to the actual in-game time in OpenSpace.
|
||||
-- For more information about SPICE see: https://naif.jpl.nasa.gov/naif/
|
||||
|
||||
@@ -0,0 +1,48 @@
|
||||
-- Basic
|
||||
-- This asset creates a scene graph node that only displays coordinate axes whose
|
||||
-- translation of the coordinate axes is determined by a timeline of individual
|
||||
-- translations. These translations are provided as keyframes that interpolate seamlessly
|
||||
-- between different positions.
|
||||
--
|
||||
-- This example will only work if the in-game time is set to January 1st, 2000.
|
||||
|
||||
local Node = {
|
||||
Identifier = "TimelineTranslation_Example",
|
||||
Transform = {
|
||||
Translation = {
|
||||
Type = "TimelineTranslation",
|
||||
Keyframes = {
|
||||
-- The first timeline entry
|
||||
["2000 JAN 01 00:00:00"] = {
|
||||
Type = "StaticTranslation",
|
||||
Position = { -10.0, 0.0, 0.0 }
|
||||
},
|
||||
-- The second timeline entry
|
||||
["2000 JAN 01 12:00:00"] = {
|
||||
Type = "StaticTranslation",
|
||||
Position = { 0.0, 0.0, 0.0 }
|
||||
},
|
||||
-- The third timeline entry
|
||||
["2000 JAN 01 23:59:59"] = {
|
||||
Type = "StaticTranslation",
|
||||
Position = { 10.0, 0.0, 0.0 }
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
Renderable = {
|
||||
Type = "RenderableCartesianAxes"
|
||||
},
|
||||
GUI = {
|
||||
Name = "TimelineTranslation - Basic",
|
||||
Path = "/Examples"
|
||||
}
|
||||
}
|
||||
|
||||
asset.onInitialize(function()
|
||||
openspace.addSceneGraphNode(Node)
|
||||
end)
|
||||
|
||||
asset.onDeinitialize(function()
|
||||
openspace.removeSceneGraphNode(Node)
|
||||
end)
|
||||
@@ -0,0 +1,55 @@
|
||||
-- No Interpolation
|
||||
-- This asset creates a scene graph node that only displays coordinate axes whose
|
||||
-- translation of the coordinate axes is determined by a timeline of individual
|
||||
-- translations that are used without interpolating between the timeline entries. These
|
||||
-- translations are keyframes that are used to change between different positions.
|
||||
--
|
||||
-- This example transitions between three positions. In this example, the interpolation
|
||||
-- between entries is disabled, which will cause the coordinate axes to change their
|
||||
-- position abruptly when the translation changes. If the interpolation were enabled, the
|
||||
-- orientation of the coordinate axes would transition seamlessly instead at the provided
|
||||
-- times.
|
||||
--
|
||||
-- This example will only work if the in-game time is set to January 1st, 2000.
|
||||
|
||||
local Node = {
|
||||
Identifier = "TimelineTranslation_Example_NoInterpolation",
|
||||
Transform = {
|
||||
Translation = {
|
||||
Type = "TimelineTranslation",
|
||||
Keyframes = {
|
||||
-- The first timeline entry
|
||||
["2000 JAN 01 00:00:00"] = {
|
||||
Type = "StaticTranslation",
|
||||
Position = { -10.0, 0.0, 0.0 }
|
||||
},
|
||||
-- The second timeline entry
|
||||
["2000 JAN 01 12:00:00"] = {
|
||||
Type = "StaticTranslation",
|
||||
Position = { 0.0, 0.0, 0.0 }
|
||||
},
|
||||
-- The third timeline entry
|
||||
["2000 JAN 01 23:59:59"] = {
|
||||
Type = "StaticTranslation",
|
||||
Position = { 10.0, 0.0, 0.0 }
|
||||
}
|
||||
},
|
||||
ShouldInterpolate = false
|
||||
}
|
||||
},
|
||||
Renderable = {
|
||||
Type = "RenderableCartesianAxes"
|
||||
},
|
||||
GUI = {
|
||||
Name = "TimelineTranslation - No Interpolation",
|
||||
Path = "/Examples"
|
||||
}
|
||||
}
|
||||
|
||||
asset.onInitialize(function()
|
||||
openspace.addSceneGraphNode(Node)
|
||||
end)
|
||||
|
||||
asset.onDeinitialize(function()
|
||||
openspace.removeSceneGraphNode(Node)
|
||||
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",
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user