Merge branch 'master' into thesis/2020/radiation

This commit is contained in:
ElonOlsson
2021-09-13 18:23:33 -04:00
214 changed files with 9042 additions and 5664 deletions

View File

@@ -27,13 +27,13 @@ include(${OPENSPACE_CMAKE_EXT_DIR}/set_openspace_compile_settings.cmake)
set(HEADER_FILES
include/filesystemaccess.h
include/launcherwindow.h
include/profile/actiondialog.h
include/profile/additionalscriptsdialog.h
include/profile/assetsdialog.h
include/profile/assettreeitem.h
include/profile/assettreemodel.h
include/profile/cameradialog.h
include/profile/deltatimesdialog.h
include/profile/keybindingsdialog.h
include/profile/scriptlogdialog.h
include/profile/line.h
include/profile/marknodesdialog.h
@@ -47,13 +47,13 @@ set(HEADER_FILES
set(SOURCE_FILES
src/launcherwindow.cpp
src/filesystemaccess.cpp
src/profile/actiondialog.cpp
src/profile/additionalscriptsdialog.cpp
src/profile/assetsdialog.cpp
src/profile/assettreeitem.cpp
src/profile/assettreemodel.cpp
src/profile/cameradialog.cpp
src/profile/deltatimesdialog.cpp
src/profile/keybindingsdialog.cpp
src/profile/scriptlogdialog.cpp
src/profile/line.cpp
src/profile/marknodesdialog.cpp
@@ -64,18 +64,14 @@ set(SOURCE_FILES
src/profile/propertiesdialog.cpp
)
find_package(Qt5 COMPONENTS Widgets REQUIRED)
set(MOC_FILES "")
qt5_wrap_cpp(
MOC_FILES
set(HEADER_SOURCE
include/launcherwindow.h
include/profile/actiondialog.h
include/profile/additionalscriptsdialog.h
include/profile/assetsdialog.h
include/profile/assettreemodel.h
include/profile/cameradialog.h
include/profile/deltatimesdialog.h
include/profile/keybindingsdialog.h
include/profile/scriptlogdialog.h
include/profile/marknodesdialog.h
include/profile/metadialog.h
@@ -85,13 +81,42 @@ qt5_wrap_cpp(
include/profile/propertiesdialog.h
)
find_package(QT NAMES Qt6 Qt5 COMPONENTS Core Widgets REQUIRED)
set(MOC_FILES "")
set(RESOURCE_FILES "")
qt5_add_resources(RESOURCE_FILES resources/resources.qrc)
set(LIBRARIES "")
if (${QT_VERSION_MAJOR} EQUAL 5)
find_package(Qt5 COMPONENTS Widgets)
qt5_wrap_cpp(
MOC_FILES
${HEADER_SOURCE}
)
qt5_add_resources(RESOURCE_FILES resources/resources.qrc)
set(LIBRARIES )
elseif (${QT_VERSION_MAJOR} EQUAL 6)
find_package(Qt6 COMPONENTS Widgets REQUIRED)
qt6_wrap_cpp(
MOC_FILES
${HEADER_SOURCE}
)
qt6_add_resources(RESOURCE_FILES resources/resources.qrc)
elseif (NOT DEFINED QT_VERSION_MAJOR)
message(FATAL_ERROR "Unable to find Qt version")
else ()
message(FATAL_ERROR "Unsupported Qt version")
endif()
add_library(openspace-ui-launcher STATIC ${HEADER_FILES} ${SOURCE_FILES} ${MOC_FILES} ${RESOURCE_FILES})
set_openspace_compile_settings(openspace-ui-launcher)
target_include_directories(openspace-ui-launcher PUBLIC include)
target_link_libraries(openspace-ui-launcher PUBLIC Qt5::Core Qt5::Gui Qt5::Widgets openspace-core)
target_link_libraries(
openspace-ui-launcher
PUBLIC
openspace-core
Qt${QT_VERSION_MAJOR}::Core Qt${QT_VERSION_MAJOR}::Gui Qt${QT_VERSION_MAJOR}::Widgets
)
if (MSVC)
set(MSVC_WARNINGS

View File

@@ -0,0 +1,103 @@
/*****************************************************************************************
* *
* OpenSpace *
* *
* Copyright (c) 2014-2021 *
* *
* Permission is hereby granted, free of charge, to any person obtaining a copy of this *
* software and associated documentation files (the "Software"), to deal in the Software *
* without restriction, including without limitation the rights to use, copy, modify, *
* merge, publish, distribute, sublicense, and/or sell copies of the Software, and to *
* permit persons to whom the Software is furnished to do so, subject to the following *
* conditions: *
* *
* The above copyright notice and this permission notice shall be included in all copies *
* or substantial portions of the Software. *
* *
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, *
* INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A *
* PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT *
* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF *
* CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE *
* OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. *
****************************************************************************************/
#ifndef __OPENSPACE_UI_LAUNCHER___ACTIONDIALOG___H__
#define __OPENSPACE_UI_LAUNCHER___ACTIONDIALOG___H__
#include <QDialog>
#include <openspace/scene/profile.h>
class QCheckBox;
class QComboBox;
class QDialogButtonBox;
class QGridLayout;
class QLineEdit;
class QListWidget;
class QPushButton;
class QTextEdit;
class ActionDialog final : public QDialog {
Q_OBJECT
public:
ActionDialog(QWidget* parent,
std::vector<openspace::Profile::Action>* actions,
std::vector<openspace::Profile::Keybinding>* keybindings);
private:
void createWidgets();
void createActionWidgets(QGridLayout* layout);
void createKeyboardWidgets(QGridLayout* layout);
void applyChanges();
openspace::Profile::Action* selectedAction();
void actionAdd();
void actionRemove();
void actionSelected();
void actionSaved();
void clearActionFields();
void actionRejected();
openspace::Profile::Keybinding* selectedKeybinding();
void keybindingAdd();
void keybindingRemove();
void keybindingSelected();
void keybindingActionSelected(int);
void keybindingSaved();
void clearKeybindingFields();
void keybindingRejected();
std::vector<openspace::Profile::Action>* _actions = nullptr;
std::vector<openspace::Profile::Action> _actionData;
std::vector<openspace::Profile::Keybinding>* _keybindings = nullptr;
std::vector<openspace::Profile::Keybinding> _keybindingsData;
struct {
QListWidget* list = nullptr;
QLineEdit* identifier = nullptr;
QLineEdit* name = nullptr;
QLineEdit* guiPath = nullptr;
QLineEdit* documentation = nullptr;
QCheckBox* isLocal = nullptr;
QTextEdit* script = nullptr;
QPushButton* addButton = nullptr;
QPushButton* removeButton = nullptr;
QDialogButtonBox* saveButtons = nullptr;
} _actionWidgets;
struct {
QListWidget* list = nullptr;
QCheckBox* shiftModifier = nullptr;
QCheckBox* ctrlModifier = nullptr;
QCheckBox* altModifier = nullptr;
QComboBox* key = nullptr;
QComboBox* action = nullptr;
QLineEdit* actionText = nullptr;
QPushButton* addButton = nullptr;
QPushButton* removeButton = nullptr;
QDialogButtonBox* saveButtons = nullptr;
} _keybindingWidgets;
};
#endif // __OPENSPACE_UI_LAUNCHER___ACTIONDIALOG___H__

View File

@@ -27,11 +27,9 @@
#include <QDialog>
namespace openspace { class Profile; }
class QTextEdit;
class AdditionalScriptsDialog : public QDialog {
class AdditionalScriptsDialog final : public QDialog {
Q_OBJECT
public:
/**
@@ -41,7 +39,7 @@ public:
* new or imported profile.
* \param parent Pointer to parent Qt widget
*/
AdditionalScriptsDialog(openspace::Profile& profile, QWidget* parent);
AdditionalScriptsDialog(QWidget* parent, std::vector<std::string>* scripts);
private slots:
void parseScript();
@@ -57,7 +55,8 @@ private slots:
private:
void createWidgets();
openspace::Profile& _profile;
std::vector<std::string>* _scripts = nullptr;
std::vector<std::string> _scriptsData;
QTextEdit* _textScripts = nullptr;
QPushButton* _chooseScriptsButton = nullptr;
};

View File

@@ -29,12 +29,10 @@
#include "assettreemodel.h"
namespace openspace { class Profile; }
class QTextEdit;
class QTreeView;
class AssetsDialog : public QDialog {
class AssetsDialog final : public QDialog {
Q_OBJECT
public:
/**
@@ -43,11 +41,12 @@ public:
* \param profile The #openspace::Profile object containing all data of the
* new or imported profile.
* \param assetBasePath The path to the folder in which all of the assets are living
* \param userAssetBasePath The path to the folder in which the users' assets are living
* \param userAssetBasePath The path to the folder in which the users' assets are
* living
* \param parent Pointer to parent Qt widget
*/
AssetsDialog(openspace::Profile& profile, const std::string& assetBasePath,
const std::string& userAssetBasePath, QWidget* parent);
AssetsDialog(QWidget* parent, openspace::Profile* profile,
const std::string& assetBasePath, const std::string& userAssetBasePath);
private slots:
void parseSelections();
@@ -62,7 +61,7 @@ private:
*/
QString createTextSummary();
openspace::Profile& _profile;
openspace::Profile* _profile = nullptr;
AssetTreeModel _assetTreeModel;
QTreeView* _assetTree = nullptr;
QTextEdit* _summary = nullptr;

View File

@@ -31,7 +31,7 @@
#include "openspace/scene/profile.h"
#include <memory>
class AssetTreeModel : public QAbstractItemModel {
class AssetTreeModel final : public QAbstractItemModel {
Q_OBJECT
public:
@@ -45,7 +45,7 @@ public:
* function (can be multiple times)
* \return QVariant data object
*/
QVariant data(const QModelIndex& index, int role) const override;
QVariant data(const QModelIndex& index, int role) const final;
/**
* Returns the header data of the tree view
@@ -57,7 +57,7 @@ public:
* \return QVariant data object in the header
*/
QVariant headerData(int section, Qt::Orientation orientation,
int role = Qt::DisplayRole) const override;
int role = Qt::DisplayRole) const final;
/**
* Returns the index of item in #QModelIndex object form
@@ -68,7 +68,7 @@ public:
* \return #QModelIndex index of the item at specified position
*/
QModelIndex index(int row, int column,
const QModelIndex& parent = QModelIndex()) const override;
const QModelIndex& parent = QModelIndex()) const final;
/**
* Returns the index of the parent of the item specified by input param
@@ -76,7 +76,7 @@ public:
* \param index of item that is a child of the parent
* \return #QModelIndex index of the parent
*/
QModelIndex parent(const QModelIndex& index) const override;
QModelIndex parent(const QModelIndex& index) const final;
/**
* Returns the index of the parent of the item specified by the input params
@@ -103,7 +103,7 @@ public:
* \param parent #QModelIndex of the parent item
* \return number of children/rows of this parent
*/
int rowCount(const QModelIndex& parent = QModelIndex()) const override;
int rowCount(const QModelIndex& parent = QModelIndex()) const final;
/**
* Returns the number of columns of data in each item of the tree
@@ -111,7 +111,7 @@ public:
* \param parent specified by the #QModelIndex index
* \return the number of data columns
*/
int columnCount(const QModelIndex& parent = QModelIndex()) const override;
int columnCount(const QModelIndex& parent = QModelIndex()) const final;
/**
* Return the Qt flags of the item specified by index, which can include
@@ -120,7 +120,7 @@ public:
* \param index specified by the #QModelIndex index
* \return the Qt flags
*/
Qt::ItemFlags flags(const QModelIndex& index) const override;
Qt::ItemFlags flags(const QModelIndex& index) const final;
/**
* Set data at index \p index
@@ -131,7 +131,7 @@ public:
* \return true if the data set was successful
*/
bool setData(const QModelIndex& index, const QVariant& value,
int role = Qt::EditRole) override;
int role = Qt::EditRole) final;
/**
* Returns a vector of all #Assets selected in the tree view

View File

@@ -27,13 +27,14 @@
#include <QDialog>
namespace openspace { class Profile; }
#include <openspace/scene/profile.h>
#include <optional>
class QLabel;
class QLineEdit;
class QTabWidget;
class CameraDialog : public QDialog {
class CameraDialog final : public QDialog {
Q_OBJECT
public:
/**
@@ -43,7 +44,7 @@ public:
* new or imported profile.
* \param parent Pointer to parent Qt widget (optional)
*/
CameraDialog(openspace::Profile& profile, QWidget* parent);
CameraDialog(QWidget* parent, std::optional<openspace::Profile::CameraType>* camera);
private slots:
void approved();
@@ -57,7 +58,7 @@ private:
void addErrorMsg(QString errorDescription);
bool areRequiredFormsFilledAndValid();
openspace::Profile& _profile;
std::optional<openspace::Profile::CameraType>* _camera = nullptr;
QTabWidget* _tabWidget = nullptr;
struct {
QLineEdit* anchor = nullptr;

View File

@@ -27,15 +27,13 @@
#include <QDialog>
namespace openspace { class Profile; }
class QDialogButtonBox;
class QLabel;
class QListWidget;
class QLineEdit;
class QPushButton;
class DeltaTimesDialog : public QDialog {
class DeltaTimesDialog final : public QDialog {
Q_OBJECT
public:
/**
@@ -45,7 +43,7 @@ public:
* new or imported profile.
* \param parent Pointer to parent Qt widget
*/
DeltaTimesDialog(openspace::Profile& profile, QWidget* parent);
DeltaTimesDialog(QWidget* parent, std::vector<double>* deltaTimes);
/**
* Returns a text summary of the delta time list for display purposes
@@ -87,8 +85,8 @@ private:
void setLabelForKey(int index, bool editMode, std::string color);
bool isLineEmpty(int index);
openspace::Profile& _profile;
std::vector<double> _data;
std::vector<double>* _deltaTimes = nullptr;
std::vector<double> _deltaTimesData;
bool _editModeNewItem = false;
QListWidget* _listWidget = nullptr;

View File

@@ -1,124 +0,0 @@
/*****************************************************************************************
* *
* OpenSpace *
* *
* Copyright (c) 2014-2021 *
* *
* Permission is hereby granted, free of charge, to any person obtaining a copy of this *
* software and associated documentation files (the "Software"), to deal in the Software *
* without restriction, including without limitation the rights to use, copy, modify, *
* merge, publish, distribute, sublicense, and/or sell copies of the Software, and to *
* permit persons to whom the Software is furnished to do so, subject to the following *
* conditions: *
* *
* The above copyright notice and this permission notice shall be included in all copies *
* or substantial portions of the Software. *
* *
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, *
* INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A *
* PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT *
* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF *
* CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE *
* OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. *
****************************************************************************************/
#ifndef __OPENSPACE_UI_LAUNCHER___KEYBINDINGS___H__
#define __OPENSPACE_UI_LAUNCHER___KEYBINDINGS___H__
#include <QDialog>
#include <openspace/scene/profile.h>
#include <openspace/util/keys.h>
#include <QWidget>
#include <QListWidgetItem>
class QComboBox;
class QCheckBox;
class QTextEdit;
class QDialogButtonBox;
class QListWidget;
class QLabel;
class QPushButton;
class KeybindingsDialog : public QDialog {
Q_OBJECT
public:
/**
* Constructor for keybindings class
*
* \param profile The #openspace::Profile object containing all data of the
* new or imported profile.
* \param parent Pointer to parent Qt widget (optional)
*/
KeybindingsDialog(openspace::Profile& profile, QWidget* parent);
/**
* Handles keypress while the Qt dialog window is open
*
* \param evt #QKeyEvent object for the key press event
*/
virtual void keyPressEvent(QKeyEvent* evt) override;
private slots:
void listItemSelected();
void listItemAdded();
void listItemRemove();
void listItemSave();
void listItemCancelSave();
void transitionToEditMode();
void parseSelections();
void chooseScripts();
void keySelected(int index);
void keyModSelected(int index);
/**
* Adds scripts to the _scriptEdit from outside dialogs
*
* \param scripts #std::string scripts to be appended
*/
void appendScriptsToKeybind(std::string scripts);
private:
void createWidgets();
void transitionFromEditMode();
void editBoxDisabled(bool disabled);
int indexInKeyMapping(std::vector<int>& mapVector, int keyInt);
bool areRequiredFormsFilled();
bool isLineEmpty(int index);
void addStringToErrorDisplay(const QString& newString);
void checkForNumberKeyConflict(int key);
void checkForBindingConflict(int selectedModKey, int selectedKey);
openspace::Profile& _profile;
std::vector<openspace::Profile::Keybinding> _data;
std::vector<int> _mapModKeyComboBoxIndexToKeyValue;
std::vector<int> _mapKeyComboBoxIndexToKeyValue;
bool _editModeNewItem = false;
int _currentKeybindingSelection = 0;
QListWidget* _list = nullptr;
QLabel* _keyModLabel = nullptr;
QComboBox* _keyModCombo = nullptr;
QLabel* _keyLabel = nullptr;
QComboBox* _keyCombo = nullptr;
QLabel* _nameLabel = nullptr;
QLineEdit* _nameEdit = nullptr;
QLabel* _guiPathLabel = nullptr;
QLineEdit* _guiPathEdit = nullptr;
QLabel* _documentationLabel = nullptr;
QLineEdit* _documentationEdit = nullptr;
QCheckBox* _localCheck = nullptr;
QLabel* _scriptLabel = nullptr;
QTextEdit* _scriptEdit = nullptr;
QPushButton* _addButton = nullptr;
QPushButton* _removeButton = nullptr;
QPushButton* _chooseScriptsButton = nullptr;
QPushButton* _saveButton = nullptr;
QPushButton* _cancelButton = nullptr;
QDialogButtonBox* _buttonBox = nullptr;
QLabel* _errorMsg = nullptr;
};
#endif // __OPENSPACE_UI_LAUNCHER___KEYBINDINGS___H__

View File

@@ -27,14 +27,12 @@
#include <QDialog>
namespace openspace { class Profile; }
class QLineEdit;
class QListWidget;
class QListWidgetItem;
class QPushButton;
class MarkNodesDialog : public QDialog {
class MarkNodesDialog final : public QDialog {
Q_OBJECT
public:
/**
@@ -44,7 +42,7 @@ public:
* new or imported profile.
* \param parent Pointer to parent Qt widget
*/
MarkNodesDialog(openspace::Profile& profile, QWidget* parent);
MarkNodesDialog(QWidget* parent, std::vector<std::string>* markedNodes);
/**
* Handles keypress while the Qt dialog window is open
@@ -63,8 +61,8 @@ private:
void createWidgets();
std::vector<QListWidgetItem*> _markedNodesListItems;
openspace::Profile& _profile;
std::vector<std::string> _data;
std::vector<std::string>* _markedNodes;
std::vector<std::string> _markedNodesData;
QListWidget* _list = nullptr;
QPushButton* _removeButton = nullptr;

View File

@@ -27,12 +27,13 @@
#include <QDialog>
namespace openspace { class Profile; }
#include <openspace/scene/profile.h>
#include <optional>
class QLineEdit;
class QTextEdit;
class MetaDialog : public QDialog {
class MetaDialog final : public QDialog {
Q_OBJECT
public:
/**
@@ -42,7 +43,7 @@ public:
* new or imported profile.
* \param parent Pointer to parent Qt widget
*/
MetaDialog(openspace::Profile& profile, QWidget* parent);
MetaDialog(QWidget* parent, std::optional<openspace::Profile::Meta>* meta);
private slots:
void save();
@@ -50,7 +51,7 @@ private slots:
private:
void createWidgets();
openspace::Profile& _profile;
std::optional<openspace::Profile::Meta>* _meta = nullptr;
QLineEdit* _nameEdit = nullptr;
QLineEdit* _versionEdit = nullptr;

View File

@@ -35,7 +35,7 @@ class QLineEdit;
class QListWidget;
class QPushButton;
class ModulesDialog : public QDialog {
class ModulesDialog final : public QDialog {
Q_OBJECT
public:
/**
@@ -45,7 +45,7 @@ public:
* new or imported profile.
* \param parent Pointer to parent Qt widget
*/
ModulesDialog(openspace::Profile& profile, QWidget* parent);
ModulesDialog(QWidget* parent, std::vector<openspace::Profile::Module>* modules);
/**
* Handles keypress while the Qt dialog window is open
@@ -71,8 +71,8 @@ private:
void editBoxDisabled(bool disabled);
bool isLineEmpty(int index) const;
openspace::Profile& _profile;
std::vector<openspace::Profile::Module> _data;
std::vector<openspace::Profile::Module>* _modules = nullptr;
std::vector<openspace::Profile::Module> _moduleData;
bool _editModeNewItem = false;
QListWidget* _list = nullptr;

View File

@@ -36,7 +36,7 @@ class QLabel;
class QLineEdit;
class QTextEdit;
class ProfileEdit : public QDialog {
class ProfileEdit final : public QDialog {
Q_OBJECT
public:
/**

View File

@@ -36,7 +36,7 @@ class QLineEdit;
class QListWidget;
class QPushButton;
class PropertiesDialog : public QDialog {
class PropertiesDialog final : public QDialog {
Q_OBJECT
public:
/**
@@ -46,7 +46,8 @@ public:
* new or imported profile.
* \param parent Pointer to parent Qt widget
*/
PropertiesDialog(openspace::Profile& profile, QWidget* parent);
PropertiesDialog(QWidget* parent,
std::vector<openspace::Profile::Property>* properties);
/**
* Handles keypress while the Qt dialog window is open
@@ -73,8 +74,8 @@ private:
bool areRequiredFormsFilled();
bool isLineEmpty(int index);
openspace::Profile& _profile;
std::vector<openspace::Profile::Property> _data;
std::vector<openspace::Profile::Property>* _properties = nullptr;
std::vector<openspace::Profile::Property> _propertyData;
bool _editModeNewItem = false;
QListWidget* _list = nullptr;

View File

@@ -25,11 +25,10 @@
#ifndef __OPENSPACE_UI_LAUNCHER___SCRIPTLOG___H__
#define __OPENSPACE_UI_LAUNCHER___SCRIPTLOG___H__
#include "profile/keybindingsdialog.h"
#include <QDialog>
#include <QListWidget>
class ScriptlogDialog : public QDialog {
class ScriptlogDialog final : public QDialog {
Q_OBJECT
public:
/**

View File

@@ -34,7 +34,7 @@ class QDateTimeEdit;
class QLabel;
class QLineEdit;
class TimeDialog : public QDialog {
class TimeDialog final : public QDialog {
Q_OBJECT
public:
/**
@@ -44,7 +44,7 @@ public:
* new or imported profile.
* \param parent Pointer to parent Qt widget
*/
TimeDialog(openspace::Profile& profile, QWidget* parent);
TimeDialog(QWidget* parent, std::optional<openspace::Profile::Time>* time);
private slots:
void enableAccordingToType(int);
@@ -54,8 +54,8 @@ private:
void createWidgets();
void enableFormatForAbsolute(bool enableAbs);
openspace::Profile& _profile;
openspace::Profile::Time _data;
std::optional<openspace::Profile::Time>* _time = nullptr;
openspace::Profile::Time _timeData;
bool _initializedAsAbsolute = true;
QComboBox* _typeCombo = nullptr;

View File

@@ -6,7 +6,7 @@
}
QLabel#heading {
font-size: 12pt;
font-size: 12pt;
}
QLabel#error-message {
@@ -18,12 +18,12 @@ QLabel#error-message {
*/
LauncherWindow QLabel {
font-family: Segoe UI;
font-weight:600;
font-weight: 600;
}
LauncherWindow QLabel#label_choose, QLabel#label_options {
color: #ddd;
font-size:10pt;
color: #dddddd;
font-size: 10pt;
}
LauncherWindow QLabel#clear {
@@ -119,12 +119,22 @@ AssetsDialog QTreeView {
}
/*
* Keybindings
* ActionDialog
*/
KeybindingsDialog QListWidget {
ActionDialog QListWidget {
min-width: 40em;
}
ActionDialog QPushButton#add-button, QPushButton#remove-button {
font-weight: bold;
padding: 0px 0px 0px 0px;
min-width: 1.5em;
max-width: 1.5em;
min-height: 1.5em;
max-height: 1.5em;
}
/*
* DeltaTimes
*/

View File

@@ -28,16 +28,18 @@
#include <openspace/engine/configuration.h>
#include <ghoul/filesystem/filesystem.h>
#include <ghoul/fmt.h>
#include <ghoul/logging/logmanager.h>
#include <QComboBox>
#include <QFile>
#include <QLabel>
#include <QMessageBox>
#include <QPushButton>
#include <QStandardItemModel>
#include <filesystem>
#include <fstream>
#include <iostream>
#include <random>
#include <QStandardItemModel>
using namespace openspace;

View File

@@ -0,0 +1,698 @@
/*****************************************************************************************
* *
* OpenSpace *
* *
* Copyright (c) 2014-2021 *
* *
* Permission is hereby granted, free of charge, to any person obtaining a copy of this *
* software and associated documentation files (the "Software"), to deal in the Software *
* without restriction, including without limitation the rights to use, copy, modify, *
* merge, publish, distribute, sublicense, and/or sell copies of the Software, and to *
* permit persons to whom the Software is furnished to do so, subject to the following *
* conditions: *
* *
* The above copyright notice and this permission notice shall be included in all copies *
* or substantial portions of the Software. *
* *
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, *
* INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A *
* PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT *
* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF *
* CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE *
* OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. *
****************************************************************************************/
#include "profile/actiondialog.h"
#include "profile/line.h"
#include <openspace/util/keys.h>
#include <ghoul/fmt.h>
#include <ghoul/misc/assert.h>
#include <QCheckBox>
#include <QComboBox>
#include <QDialogButtonBox>
#include <QGridLayout>
#include <QHBoxLayout>
#include <QLabel>
#include <QLineEdit>
#include <QListWidget>
#include <QMessageBox>
#include <QPushButton>
#include <QTextEdit>
#include <QVBoxLayout>
using namespace openspace;
namespace {
void updateListItem(QListWidgetItem* item, const Profile::Action& action) {
ghoul_assert(item, "Item must exist at this point");
item->setText(
action.name.empty() ?
QString::fromStdString(action.identifier) :
QString::fromStdString(action.name)
);
}
void updateListItem(QListWidgetItem* item, const Profile::Keybinding& kb) {
ghoul_assert(item, "Item must exist at this point");
std::string name = fmt::format("{}\t{}", ghoul::to_string(kb.key), kb.action);
item->setText(QString::fromStdString(name));
}
} // namespace
ActionDialog::ActionDialog(QWidget* parent,
std::vector<openspace::Profile::Action>* actions,
std::vector<openspace::Profile::Keybinding>* keybindings)
: QDialog(parent)
, _actions(actions)
, _actionData(*_actions)
, _keybindings(keybindings)
, _keybindingsData(*_keybindings)
{
setWindowTitle("Actions and Keybindings");
createWidgets();
}
void ActionDialog::createWidgets() {
// Column 0 Column 1 Column 2
// *----------------------*---------------*----------------*
// | Actions | Row 0
// | | Identifier | [oooooooooooo] | Row 1
// | | Name | [oooooooooooo] | Row 2
// | | GUI Path | [oooooooooooo] | Row 3
// | | Documentation | [oooooooooooo] | Row 4
// | | Is Local | [] | Row 5
// | | Script | [oooooooooooo] | Row 6
// *----------------------*---------------*----------------*
// | [+] [-] | | [Save] [Cancel]| Row 7
// *----------------------*---------------*----------------*
// |=======================================================| Row 8
// | Keybindings | Row 9
// *----------------------*---------------*----------------|
// | | Modifier | []S []C []A | Row 10
// | | Key | DDDDDDDDDDDD> | Row 11
// | | Add actions | DDDDDDDDDDDD> | Row 12
// | | Action | [oooooooooooo] | Row 13
// *----------------------*---------------*----------------*
// | [+] [-] | | [Save] [Cancel]| Row 14
// *----------------------*---------------*----------------*
// |=======================================================| Row 14
// *----------------------*---------------*----------------*
// | | [Save] [Cancel]| Row 15
// *----------------------*---------------*----------------*
QGridLayout* layout = new QGridLayout(this);
createActionWidgets(layout);
clearActionFields();
layout->addWidget(new Line, 8, 0, 1, 3);
createKeyboardWidgets(layout);
clearKeybindingFields();
layout->addWidget(new Line, 16, 0, 1, 3);
QDialogButtonBox* buttonBox = new QDialogButtonBox;
buttonBox->setStandardButtons(QDialogButtonBox::Save | QDialogButtonBox::Cancel);
QObject::connect(
buttonBox, &QDialogButtonBox::accepted,
this, &ActionDialog::applyChanges
);
QObject::connect(
buttonBox, &QDialogButtonBox::rejected,
this, &ActionDialog::reject
);
layout->addWidget(buttonBox, 17, 2, Qt::AlignRight);
}
void ActionDialog::createActionWidgets(QGridLayout* layout) {
QLabel* title = new QLabel("Actions");
title->setObjectName("heading");
layout->addWidget(title, 0, 0, 1, 3);
_actionWidgets.list = new QListWidget;
_actionWidgets.list->setToolTip(
"The list of all actions currently defined in the profile. Select one to edit it "
"or use the + button below to create a new action"
);
_actionWidgets.list->setAlternatingRowColors(true);
_actionWidgets.list->setResizeMode(QListView::Adjust);
connect(
_actionWidgets.list, &QListWidget::itemSelectionChanged,
this, &ActionDialog::actionSelected
);
for (size_t i = 0; i < _actionData.size(); ++i) {
const Profile::Action& action = _actionData[i];
std::string name = action.name.empty() ? action.identifier : action.name;
_actionWidgets.list->addItem(new QListWidgetItem(QString::fromStdString(name)));
}
layout->addWidget(_actionWidgets.list, 1, 0, 6, 1);
layout->addWidget(new QLabel("Identifier"), 1, 1);
_actionWidgets.identifier = new QLineEdit;
_actionWidgets.identifier->setToolTip(
"The unique identifier for this action. The identifier name cannot be reused "
"between different actions and will lead to a failure to load the profile if it "
"happens. There are no restrictions on the name of the identifier, but a dot "
"separated hierarchical structure is suggested to prevent name clashes"
);
_actionWidgets.identifier->setEnabled(false);
layout->addWidget(_actionWidgets.identifier, 1, 2);
layout->addWidget(new QLabel("Name"), 2, 1);
_actionWidgets.name = new QLineEdit;
_actionWidgets.name->setToolTip(
"The user-facing name of this action. As it is displayed in user interfaces, the "
"name should be as concise and informative as possible"
);
_actionWidgets.name->setEnabled(false);
layout->addWidget(_actionWidgets.name, 2, 2);
layout->addWidget(new QLabel("GUI Path"), 3, 1);
_actionWidgets.guiPath = new QLineEdit;
_actionWidgets.guiPath->setToolTip(
"The path under which this action will be shown in user interfaces. The path "
"must use the '/' character as separators between folders and start with a '/' "
"character that denotes the root folder"
);
_actionWidgets.guiPath->setEnabled(false);
layout->addWidget(_actionWidgets.guiPath, 3, 2);
layout->addWidget(new QLabel("Documentation"), 4, 1);
_actionWidgets.documentation = new QLineEdit;
_actionWidgets.documentation->setToolTip(
"A longer user-facing documentation that describes the action in more detail. "
"The user can request the documentation on demand, so it might be longer and "
"more descriptive than the name itself and might also explain some optional "
"parameters that that action can consume"
);
_actionWidgets.documentation->setEnabled(false);
layout->addWidget(_actionWidgets.documentation, 4, 2);
layout->addWidget(new QLabel("Is Local"), 5, 1);
_actionWidgets.isLocal = new QCheckBox;
_actionWidgets.isLocal->setToolTip(
"If this value is checked, the action will only ever affect the OpenSpace "
"instance that is executing it. If running a 'regular' OpenSpace instance, this "
"setting will not make any difference, but it is necessary in a clustered "
"environment or when using a parallel connection, in which case it determines "
"whether a command should be executed only locally or send to all remote "
"instances as well"
);
_actionWidgets.isLocal->setEnabled(false);
layout->addWidget(_actionWidgets.isLocal, 5, 2);
layout->addWidget(new QLabel("Script"), 6, 1);
_actionWidgets.script = new QTextEdit;
_actionWidgets.script->setToolTip(
"This is the Lua script that gets executed when this action is triggered. "
"Actions can make use of optional arguments which are already defined as the "
"`args` variable when this script executes. If no arguments are passed, this "
"variable does not exist"
);
_actionWidgets.script->setEnabled(false);
layout->addWidget(_actionWidgets.script, 6, 2);
// + / - buttons
QWidget* container = new QWidget;
QBoxLayout* containerLayout = new QHBoxLayout(container);
_actionWidgets.addButton = new QPushButton("+");
_actionWidgets.addButton->setObjectName("add-button");
_actionWidgets.addButton->setToolTip("Adds a new action to the list of all actions");
QObject::connect(
_actionWidgets.addButton, &QPushButton::clicked,
this, &ActionDialog::actionAdd
);
containerLayout->addWidget(_actionWidgets.addButton);
_actionWidgets.removeButton = new QPushButton("-");
_actionWidgets.removeButton->setObjectName("remove-button");
_actionWidgets.removeButton->setToolTip("Removes the currently selected action");
_actionWidgets.removeButton->setEnabled(false);
QObject::connect(
_actionWidgets.removeButton, &QPushButton::clicked,
this, &ActionDialog::actionRemove
);
containerLayout->addWidget(_actionWidgets.removeButton);
layout->addWidget(container, 7, 0, Qt::AlignLeft);
// Save / Cancel buttons
_actionWidgets.saveButtons = new QDialogButtonBox;
_actionWidgets.saveButtons->setToolTip(
"Saves or discards all changes to the currently selected action"
);
_actionWidgets.saveButtons->setEnabled(false);
_actionWidgets.saveButtons->setStandardButtons(
QDialogButtonBox::Save | QDialogButtonBox::Cancel
);
QObject::connect(
_actionWidgets.saveButtons, &QDialogButtonBox::accepted,
this, &ActionDialog::actionSaved
);
QObject::connect(
_actionWidgets.saveButtons, &QDialogButtonBox::rejected,
this, &ActionDialog::actionRejected
);
layout->addWidget(_actionWidgets.saveButtons, 7, 2, Qt::AlignRight);
}
void ActionDialog::createKeyboardWidgets(QGridLayout* layout) {
QLabel* title = new QLabel("Keybindings");
title->setObjectName("heading");
layout->addWidget(title);
_keybindingWidgets.list = new QListWidget;
_keybindingWidgets.list->setToolTip(
"The list of all keybindings currently assigned in this profile"
);
_keybindingWidgets.list->setAlternatingRowColors(true);
_keybindingWidgets.list->setResizeMode(QListView::Adjust);
connect(
_keybindingWidgets.list, &QListWidget::itemSelectionChanged,
this, &ActionDialog::keybindingSelected
);
for (size_t i = 0; i < _keybindingsData.size(); ++i) {
const Profile::Keybinding& kv = _keybindingsData[i];
QListWidgetItem* item = new QListWidgetItem;
updateListItem(item, kv);
_keybindingWidgets.list->addItem(item);
}
layout->addWidget(_keybindingWidgets.list, 10, 0, 4, 1);
layout->addWidget(new QLabel("Modifier"), 10, 1);
{
QWidget* container = new QWidget;
QBoxLayout* containerLayout = new QHBoxLayout(container);
_keybindingWidgets.shiftModifier = new QCheckBox("Shift");
_keybindingWidgets.shiftModifier->setEnabled(false);
containerLayout->addWidget(_keybindingWidgets.shiftModifier);
_keybindingWidgets.ctrlModifier = new QCheckBox("Control");
_keybindingWidgets.ctrlModifier->setEnabled(false);
containerLayout->addWidget(_keybindingWidgets.ctrlModifier);
_keybindingWidgets.altModifier = new QCheckBox("Alt");
_keybindingWidgets.altModifier->setEnabled(false);
containerLayout->addWidget(_keybindingWidgets.altModifier);
layout->addWidget(container, 10, 2);
}
layout->addWidget(new QLabel("Key"), 11, 1);
_keybindingWidgets.key = new QComboBox;
QStringList keyList;
for (const KeyInfo& ki : KeyInfos) {
keyList += QString::fromStdString(std::string(ki.name));
}
_keybindingWidgets.key->addItems(keyList);
_keybindingWidgets.key->setCurrentIndex(-1);
_keybindingWidgets.key->setEnabled(false);
layout->addWidget(_keybindingWidgets.key, 11, 2);
layout->addWidget(new QLabel("Action chooser"), 12, 1);
_keybindingWidgets.action = new QComboBox;
_keybindingWidgets.action->setToolTip(
"You can select any of the actions defined above here to be associated with the "
"selected keybind. Selecting an action from this dropdown menu will "
"automatically enter it into the text field below and overwrite any value that "
"already is entered in there"
);
for (const Profile::Action& action : _actionData) {
_keybindingWidgets.action->addItem(QString::fromStdString(action.identifier));
}
connect(
_keybindingWidgets.action, QOverload<int>::of(&QComboBox::currentIndexChanged),
this, &ActionDialog::keybindingActionSelected
);
_keybindingWidgets.action->setEnabled(false);
layout->addWidget(_keybindingWidgets.action, 12, 2);
layout->addWidget(new QLabel("Action"), 13, 1);
_keybindingWidgets.actionText = new QLineEdit;
_keybindingWidgets.actionText->setToolTip(
"This is the action that will be triggered when the keybind is pressed. In the "
"majority of cases, you do not need to enter something here manually, but "
"instead select the action from the dropdown list above. However, if you know "
"that an action with a specific identifier will exist at runtime, for example if "
"it is defined in an asset included in this profile, you can enter the "
"identifier of that action manually here to associate a key with it. If the "
"identifer does not exist, an error will be logged when trying to bind the key "
"at startup."
);
_keybindingWidgets.actionText->setEnabled(false);
layout->addWidget(_keybindingWidgets.actionText, 13, 2);
// +/- buttons
QWidget* container = new QWidget;
QBoxLayout* containerLayout = new QHBoxLayout(container);
_keybindingWidgets.addButton = new QPushButton("+");
_keybindingWidgets.addButton->setObjectName("add-button");
_keybindingWidgets.addButton->setToolTip(
"Adds a new keybinding to the list of all keybindings"
);
QObject::connect(
_keybindingWidgets.addButton, &QPushButton::clicked,
this, &ActionDialog::keybindingAdd
);
containerLayout->addWidget(_keybindingWidgets.addButton);
_keybindingWidgets.removeButton = new QPushButton("-");
_keybindingWidgets.removeButton->setObjectName("remove-button");
_keybindingWidgets.removeButton->setToolTip(
"Removes the currently selected keybinding"
);
_keybindingWidgets.removeButton->setEnabled(false);
QObject::connect(
_keybindingWidgets.removeButton, &QPushButton::clicked,
this, &ActionDialog::keybindingRemove
);
containerLayout->addWidget(_keybindingWidgets.removeButton);
layout->addWidget(container, 14, 0, Qt::AlignLeft);
// Save/Cancel
_keybindingWidgets.saveButtons = new QDialogButtonBox;
_keybindingWidgets.saveButtons->setToolTip(
"Saves or discards all changes to the currently selected keybinding"
);
_keybindingWidgets.saveButtons->setEnabled(false);
_keybindingWidgets.saveButtons->setStandardButtons(
QDialogButtonBox::Save | QDialogButtonBox::Cancel
);
QObject::connect(
_keybindingWidgets.saveButtons, &QDialogButtonBox::accepted,
this, &ActionDialog::keybindingSaved
);
QObject::connect(
_keybindingWidgets.saveButtons, &QDialogButtonBox::rejected,
this, &ActionDialog::keybindingRejected
);
layout->addWidget(_keybindingWidgets.saveButtons, 14, 2, Qt::AlignRight);
}
void ActionDialog::applyChanges() {
*_actions = std::move(_actionData);
*_keybindings = std::move(_keybindingsData);
accept();
}
Profile::Action* ActionDialog::selectedAction() {
QListWidgetItem* item = _actionWidgets.list->currentItem();
const int idx = _actionWidgets.list->row(item);
return idx != -1 ? &_actionData[idx] : nullptr;
}
void ActionDialog::actionAdd() {
_actionWidgets.list->addItem("");
_actionData.push_back(Profile::Action());
_actionWidgets.list->setCurrentRow(_actionWidgets.list->count() - 1);
}
void ActionDialog::actionRemove() {
const openspace::Profile::Action* action = selectedAction();
ghoul_assert(action, "An action must exist at this point");
ghoul_assert(
_actionWidgets.list->count() == static_cast<int>(_actionData.size()),
"Action list and data has desynced"
);
// We can't remove an action if it has a keyboard shortcut attached to it
for (size_t i = 0; i < _keybindingsData.size(); ++i) {
const Profile::Keybinding& kb = _keybindingsData[i];
if (kb.action != action->identifier) {
continue;
}
QMessageBox::StandardButton button = QMessageBox::information(
this,
"Remove action",
QString::fromStdString(fmt::format(
"Action '{}' is used in the keybind '{}' and cannot be removed unless "
"the keybind is removed as well. Do you want to remove the keybind as "
"well?",
action->identifier, ghoul::to_string(kb.key)
)),
QMessageBox::StandardButton::Yes,
QMessageBox::StandardButton::No
);
if (button == QMessageBox::StandardButton::Yes) {
_keybindingsData.erase(_keybindingsData.begin() + i);
delete _keybindingWidgets.list->takeItem(static_cast<int>(i));
i--;
}
else {
// If the user chooses 'No' at least once, we have to bail
return;
}
}
for (size_t i = 0; i < _actionData.size(); ++i) {
if (_actionData[i].identifier == action->identifier) {
_actionData.erase(_actionData.begin() + i);
delete _actionWidgets.list->takeItem(static_cast<int>(i));
clearActionFields();
return;
}
}
ghoul_assert(false, "We shouldn't be able to get here");
}
void ActionDialog::actionSelected() {
const Profile::Action* action = selectedAction();
if (action) {
// Action selected
_actionWidgets.identifier->setText(QString::fromStdString(action->identifier));
_actionWidgets.identifier->setEnabled(true);
_actionWidgets.name->setText(QString::fromStdString(action->name));
_actionWidgets.name->setEnabled(true);
_actionWidgets.guiPath->setText(QString::fromStdString(action->guiPath));
_actionWidgets.guiPath->setEnabled(true);
_actionWidgets.documentation->setText(
QString::fromStdString(action->documentation)
);
_actionWidgets.documentation->setEnabled(true);
_actionWidgets.isLocal->setChecked(action->isLocal);
_actionWidgets.isLocal->setEnabled(true);
_actionWidgets.script->setText(QString::fromStdString(action->script));
_actionWidgets.script->setEnabled(true);
_actionWidgets.addButton->setEnabled(false);
_actionWidgets.removeButton->setEnabled(true);
_actionWidgets.saveButtons->setEnabled(true);
}
else {
// No action selected
_actionWidgets.addButton->setEnabled(true);
_actionWidgets.removeButton->setEnabled(false);
_actionWidgets.saveButtons->setEnabled(false);
}
}
void ActionDialog::actionSaved() {
std::string newIdentifier = _actionWidgets.identifier->text().toStdString();
if (newIdentifier.empty()) {
QMessageBox::critical(this, "Empty identifier", "Identifier must not be empty");
return;
}
Profile::Action* action = selectedAction();
std::string oldIdentifier = action->identifier;
if (oldIdentifier != newIdentifier) {
// The identifier is a bit special as we need to make sure that we didn't
// accidentally create a duplicate while renaming the currently selected action.
// Also if we didn't create a duplicate, meaning that we renamed an action to a
// new valid identifier, we need to make sure that we update all keybinds that
// referenced the old value are updated to use the new name instead
const auto it = std::find_if(
_actionData.begin(), _actionData.end(),
[id = newIdentifier](const Profile::Action& a) { return a.identifier == id; }
);
if (it != _actionData.end()) {
QMessageBox::critical(
this,
"Duplicate identifier",
"The chosen identifier was already used in another action. Identifiers "
"have to be unique. Please choose a different identfier."
);
return;
}
// If we got this far, we have a new identifier and it is a new one, so we need to
// update other keybinds now
ghoul_assert(
_keybindingWidgets.list->count() == _keybindingsData.size(),
"The list and data got out of sync"
);
for (int i = 0; i < _keybindingWidgets.list->count(); ++i) {
if (_keybindingsData[i].action == oldIdentifier) {
_keybindingsData[i].action = newIdentifier;
updateListItem(_keybindingWidgets.list->item(i), _keybindingsData[i]);
}
}
for (int i = 0; i < _keybindingWidgets.action->count(); ++i) {
if (_keybindingWidgets.action->itemText(i).toStdString() == oldIdentifier) {
_keybindingWidgets.action->setItemText(
i,
QString::fromStdString(newIdentifier)
);
}
}
action->identifier = newIdentifier;
}
action->name = _actionWidgets.name->text().toStdString();
action->guiPath = _actionWidgets.guiPath->text().toStdString();
action->documentation = _actionWidgets.documentation->text().toStdString();
action->isLocal = _actionWidgets.isLocal->isChecked();
action->script = _actionWidgets.script->toPlainText().toStdString();
updateListItem(_actionWidgets.list->currentItem(), *action);
clearActionFields();
}
void ActionDialog::clearActionFields() {
_actionWidgets.list->setCurrentRow(-1);
_actionWidgets.identifier->clear();
_actionWidgets.identifier->setEnabled(false);
_actionWidgets.name->clear();
_actionWidgets.name->setEnabled(false);
_actionWidgets.guiPath->clear();
_actionWidgets.guiPath->setEnabled(false);
_actionWidgets.documentation->clear();
_actionWidgets.documentation->setEnabled(false);
_actionWidgets.isLocal->setChecked(false);
_actionWidgets.isLocal->setEnabled(false);
_actionWidgets.script->clear();
_actionWidgets.script->setEnabled(false);
_actionWidgets.saveButtons->setEnabled(false);
}
void ActionDialog::actionRejected() {
if (_actionData.back().identifier.empty()) {
// This happens if someone creates a new action and never gave an identifier
delete _actionWidgets.list->takeItem(_actionWidgets.list->count() - 1);
_actionData.erase(_actionData.begin() + _actionData.size() - 1);
}
clearActionFields();
}
Profile::Keybinding* ActionDialog::selectedKeybinding() {
QListWidgetItem* item = _keybindingWidgets.list->currentItem();
const int idx = _keybindingWidgets.list->row(item);
return idx != -1 ? &_keybindingsData[idx] : nullptr;
}
void ActionDialog::keybindingAdd() {
_keybindingWidgets.list->addItem("");
_keybindingsData.push_back(Profile::Keybinding());
_keybindingWidgets.list->setCurrentRow(_keybindingWidgets.list->count() - 1);
}
void ActionDialog::keybindingRemove() {
const Profile::Keybinding* keybinding = selectedKeybinding();
ghoul_assert(keybinding, "A keybinding must be selected at this point");
for (size_t i = 0; i < _keybindingsData.size(); ++i) {
if (_keybindingsData[i].key == keybinding->key &&
_keybindingsData[i].action == keybinding->action)
{
_keybindingsData.erase(_keybindingsData.begin() + i);
delete _keybindingWidgets.list->takeItem(static_cast<int>(i));
clearKeybindingFields();
return;
}
}
}
void ActionDialog::keybindingSelected() {
const Profile::Keybinding* keybinding = selectedKeybinding();
if (keybinding) {
_keybindingWidgets.shiftModifier->setEnabled(true);
_keybindingWidgets.shiftModifier->setChecked(
hasKeyModifier(keybinding->key.modifier, KeyModifier::Shift)
);
_keybindingWidgets.ctrlModifier->setEnabled(true);
_keybindingWidgets.ctrlModifier->setChecked(
hasKeyModifier(keybinding->key.modifier, KeyModifier::Control)
);
_keybindingWidgets.altModifier->setEnabled(true);
_keybindingWidgets.altModifier->setChecked(
hasKeyModifier(keybinding->key.modifier, KeyModifier::Alt)
);
std::string key = ghoul::to_string(keybinding->key.key);
_keybindingWidgets.key->setCurrentText(QString::fromStdString(key));
_keybindingWidgets.key->setEnabled(true);
_keybindingWidgets.action->setCurrentText(QString::fromStdString(keybinding->action));
_keybindingWidgets.action->setEnabled(true);
_keybindingWidgets.actionText->setText(
QString::fromStdString(keybinding->action)
);
_keybindingWidgets.actionText->setEnabled(true);
_keybindingWidgets.addButton->setEnabled(false);
_keybindingWidgets.removeButton->setEnabled(true);
_keybindingWidgets.saveButtons->setEnabled(true);
}
else {
// No keybinding selected
_keybindingWidgets.addButton->setEnabled(true);
_keybindingWidgets.removeButton->setEnabled(false);
_keybindingWidgets.saveButtons->setEnabled(false);
}
}
void ActionDialog::keybindingActionSelected(int) {
_keybindingWidgets.actionText->setText(_keybindingWidgets.action->currentText());
}
void ActionDialog::keybindingSaved() {
Profile::Keybinding* keybinding = selectedKeybinding();
ghoul_assert(keybinding, "There must be a selected action at this point");
KeyModifier km = KeyModifier::None;
if (_keybindingWidgets.shiftModifier->isChecked()) {
km |= KeyModifier::Shift;
}
if (_keybindingWidgets.altModifier->isChecked()) {
km |= KeyModifier::Alt;
}
if (_keybindingWidgets.ctrlModifier->isChecked()) {
km |= KeyModifier::Control;
}
keybinding->key = stringToKey(_keybindingWidgets.key->currentText().toStdString());
keybinding->key.modifier = km;
keybinding->action = _keybindingWidgets.actionText->text().toStdString();
updateListItem(_keybindingWidgets.list->currentItem(), *keybinding);
clearKeybindingFields();
}
void ActionDialog::clearKeybindingFields() {
_keybindingWidgets.list->setCurrentRow(-1);
_keybindingWidgets.shiftModifier->setChecked(false);
_keybindingWidgets.shiftModifier->setEnabled(false);
_keybindingWidgets.ctrlModifier->setChecked(false);
_keybindingWidgets.ctrlModifier->setEnabled(false);
_keybindingWidgets.altModifier->setChecked(false);
_keybindingWidgets.altModifier->setEnabled(false);
_keybindingWidgets.key->setCurrentIndex(-1);
_keybindingWidgets.key->setEnabled(false);
_keybindingWidgets.action->setCurrentIndex(-1);
_keybindingWidgets.action->setEnabled(false);
_keybindingWidgets.actionText->clear();
_keybindingWidgets.actionText->setEnabled(false);
}
void ActionDialog::keybindingRejected() {
clearKeybindingFields();
}

View File

@@ -33,18 +33,19 @@
#include <QPushButton>
#include <QTextEdit>
#include <QVBoxLayout>
#include <sstream>
AdditionalScriptsDialog::AdditionalScriptsDialog(openspace::Profile& profile,
QWidget* parent)
AdditionalScriptsDialog::AdditionalScriptsDialog(QWidget* parent,
std::vector<std::string>* scripts)
: QDialog(parent)
, _profile(profile)
, _scripts(scripts)
, _scriptsData(*_scripts)
{
setWindowTitle("Additional Scripts");
createWidgets();
std::vector<std::string> scripts = _profile.additionalScripts();
std::string scriptText = std::accumulate(
scripts.begin(), scripts.end(),
_scriptsData.begin(), _scriptsData.end(),
std::string(), [](std::string lhs, std::string rhs) { return lhs + rhs + '\n'; }
);
_textScripts->setText(QString::fromStdString(std::move(scriptText)));
@@ -95,7 +96,7 @@ void AdditionalScriptsDialog::parseScript() {
std::getline(iss, s);
additionalScripts.push_back(std::move(s));
}
_profile.setAdditionalScripts(additionalScripts);
*_scripts = std::move(additionalScripts);
accept();
}

View File

@@ -26,6 +26,7 @@
#include "profile/line.h"
#include <openspace/scene/profile.h>
#include <ghoul/fmt.h>
#include <QDialogButtonBox>
#include <QHeaderView>
#include <QLabel>
@@ -122,8 +123,9 @@ namespace {
}
} // namespace
AssetsDialog::AssetsDialog(openspace::Profile& profile, const std::string& assetBasePath,
const std::string& userAssetBasePath, QWidget* parent)
AssetsDialog::AssetsDialog(QWidget* parent, openspace::Profile* profile,
const std::string& assetBasePath,
const std::string& userAssetBasePath)
: QDialog(parent)
, _profile(profile)
{
@@ -157,10 +159,10 @@ AssetsDialog::AssetsDialog(openspace::Profile& profile, const std::string& asset
connect(_assetTree, &QTreeView::clicked, this, &AssetsDialog::selected);
for (const std::string& a : _profile.assets()) {
QModelIndex parent = _assetTreeModel.index(-1, 0);
int nRows = _assetTreeModel.rowCount(parent);
traverseToFindFilesystemMatch(_assetTreeModel, parent, nRows, a);
for (const std::string& a : _profile->assets) {
QModelIndex p = _assetTreeModel.index(-1, 0);
int nRows = _assetTreeModel.rowCount(p);
traverseToFindFilesystemMatch(_assetTreeModel, p, nRows, a);
}
int nRows = _assetTreeModel.rowCount(_assetTreeModel.index(-1, 0));
@@ -223,13 +225,13 @@ QString AssetsDialog::createTextSummary() {
}
void AssetsDialog::parseSelections() {
_profile.clearAssets();
_profile->assets.clear();
std::vector<std::string> summaryPaths;
std::vector<AssetTreeItem*> summaryItems;
_assetTreeModel.getSelectedAssets(summaryPaths, summaryItems);
for (const std::string& sel : summaryPaths) {
_profile.addAsset(sel);
_profile->addAsset(sel);
}
accept();
}

View File

@@ -25,7 +25,6 @@
#include "profile/cameradialog.h"
#include "profile/line.h"
#include <openspace/scene/profile.h>
#include <QDialogButtonBox>
#include <QDoubleValidator>
#include <QFrame>
@@ -56,15 +55,16 @@ namespace {
}
} // namespace
CameraDialog::CameraDialog(openspace::Profile& profile, QWidget *parent)
CameraDialog::CameraDialog(QWidget* parent,
std::optional<openspace::Profile::CameraType>* camera)
: QDialog(parent)
, _profile(profile)
, _camera(camera)
{
setWindowTitle("Set Camera Position");
createWidgets();
if (_profile.camera().has_value()) {
openspace::Profile::CameraType type = *_profile.camera();
if (_camera->has_value()) {
const openspace::Profile::CameraType& type = **_camera;
std::visit(overloaded {
[this](const openspace::Profile::CameraNavState& nav) {
_tabWidget->setCurrentIndex(CameraTypeNav);
@@ -406,7 +406,7 @@ void CameraDialog::approved() {
else {
nav.pitch = std::nullopt;
}
_profile.setCamera(nav);
*_camera = std::move(nav);
}
else if (_tabWidget->currentIndex() == CameraTypeGeo) {
openspace::Profile::CameraGoToGeo geo;
@@ -416,7 +416,7 @@ void CameraDialog::approved() {
if (!_geoState.altitude->text().isEmpty()) {
geo.altitude = _geoState.altitude->text().toDouble();
}
_profile.setCamera(geo);
*_camera = std::move(geo);
}
accept();

View File

@@ -26,6 +26,7 @@
#include "profile/line.h"
#include <openspace/scene/profile.h>
#include <ghoul/fmt.h>
#include <QDialogButtonBox>
#include <QDoubleValidator>
#include <QEvent>
@@ -79,16 +80,15 @@ namespace {
}
} // namespace
DeltaTimesDialog::DeltaTimesDialog(openspace::Profile& profile, QWidget *parent)
DeltaTimesDialog::DeltaTimesDialog(QWidget* parent, std::vector<double>* deltaTimes)
: QDialog(parent)
, _profile(profile)
, _deltaTimes(deltaTimes)
, _deltaTimesData(*_deltaTimes)
{
setWindowTitle("Simulation Time Increments");
createWidgets();
_data = _profile.deltaTimes();
for (size_t d = 0; d < _data.size(); ++d) {
for (size_t d = 0; d < _deltaTimesData.size(); ++d) {
std::string summary = createSummaryForDeltaTime(d, true);
_listWidget->addItem(new QListWidgetItem(QString::fromStdString(summary)));
}
@@ -203,7 +203,11 @@ std::string DeltaTimesDialog::createSummaryForDeltaTime(size_t idx, bool forList
}
if (forListView) {
s += '\t' + std::to_string(_data.at(idx)) + '\t' + timeDescription(_data.at(idx));
s += fmt::format(
"\t{}\t{}",
std::to_string(_deltaTimesData.at(idx)),
timeDescription(_deltaTimesData.at(idx))
);
}
return s;
}
@@ -212,16 +216,16 @@ void DeltaTimesDialog::listItemSelected() {
QListWidgetItem *item = _listWidget->currentItem();
int index = _listWidget->row(item);
if (index < (static_cast<int>(_data.size()) - 1)) {
if (index < (static_cast<int>(_deltaTimesData.size()) - 1)) {
_listWidget->setCurrentRow(index);
}
if (!_data.empty()) {
if (_data.at(index) == 0) {
if (!_deltaTimesData.empty()) {
if (_deltaTimesData.at(index) == 0) {
_seconds->clear();
}
else {
_seconds->setText(QString::number(_data.at(index)));
_seconds->setText(QString::number(_deltaTimesData.at(index)));
}
}
_editModeNewItem = true;
@@ -230,8 +234,8 @@ void DeltaTimesDialog::listItemSelected() {
void DeltaTimesDialog::setLabelForKey(int index, bool editMode, std::string color) {
std::string labelS = "Set Simulation Time Increment for key";
if (index >= static_cast<int>(_data.size())) {
index = static_cast<int>(_data.size()) - 1;
if (index >= static_cast<int>(_deltaTimesData.size())) {
index = static_cast<int>(_deltaTimesData.size()) - 1;
}
if (editMode) {
labelS += " '" + createSummaryForDeltaTime(index, false) + "':";
@@ -261,7 +265,7 @@ bool DeltaTimesDialog::isLineEmpty(int index) {
if (!_listWidget->item(index)->text().isEmpty()) {
isEmpty = false;
}
if (!_data.empty() && (_data.at(0) != 0)) {
if (!_deltaTimesData.empty() && (_deltaTimesData.at(0) != 0)) {
isEmpty = false;
}
return isEmpty;
@@ -275,11 +279,11 @@ void DeltaTimesDialog::addDeltaTimeValue() {
// Special case where list is "empty" but really has one line that is blank.
// This is done because QListWidget does not seem to like having its sole
// remaining item being removed.
_data.at(0) = 0;
_deltaTimesData.at(0) = 0;
_listWidget->item(0)->setText(messageAddValue);
}
else if (_data.size() < MaxNumberOfKeys) {
_data.push_back(0);
else if (_deltaTimesData.size() < MaxNumberOfKeys) {
_deltaTimesData.push_back(0);
_listWidget->addItem(new QListWidgetItem(messageAddValue));
}
else {
@@ -294,8 +298,8 @@ void DeltaTimesDialog::saveDeltaTimeValue() {
QListWidgetItem* item = _listWidget->currentItem();
if (item != nullptr) {
int index = _listWidget->row(item);
if (_data.size() > 0) {
_data.at(index) = _seconds->text().toDouble();
if (_deltaTimesData.size() > 0) {
_deltaTimesData.at(index) = _seconds->text().toDouble();
std::string summary = createSummaryForDeltaTime(index, true);
_listWidget->item(index)->setText(QString::fromStdString(summary));
transitionEditMode(index, false);
@@ -307,7 +311,7 @@ void DeltaTimesDialog::saveDeltaTimeValue() {
void DeltaTimesDialog::discardDeltaTimeValue() {
listItemSelected();
transitionEditMode(_listWidget->count() - 1, false);
if (_editModeNewItem && !_data.empty() && _data.back() == 0) {
if (_editModeNewItem && !_deltaTimesData.empty() && _deltaTimesData.back() == 0) {
removeDeltaTimeValue();
}
_editModeNewItem = false;
@@ -316,13 +320,13 @@ void DeltaTimesDialog::discardDeltaTimeValue() {
void DeltaTimesDialog::removeDeltaTimeValue() {
if (_listWidget->count() > 0) {
if (_listWidget->count() == 1) {
_data.at(0) = 0;
_deltaTimesData.at(0) = 0;
_listWidget->item(0)->setText("");
}
else {
delete _listWidget->takeItem(_listWidget->count() - 1);
if (!_data.empty()) {
_data.pop_back();
if (!_deltaTimesData.empty()) {
_deltaTimesData.pop_back();
}
}
}
@@ -355,20 +359,20 @@ void DeltaTimesDialog::transitionEditMode(int index, bool state) {
}
void DeltaTimesDialog::parseSelections() {
if ((_data.size() == 1) && (_data.at(0) == 0)) {
_data.clear();
if ((_deltaTimesData.size() == 1) && (_deltaTimesData.at(0) == 0)) {
_deltaTimesData.clear();
}
int finalNonzeroIndex = static_cast<int>(_data.size()) - 1;
int finalNonzeroIndex = static_cast<int>(_deltaTimesData.size()) - 1;
for (; finalNonzeroIndex >= 0; --finalNonzeroIndex) {
if (_data.at(finalNonzeroIndex) != 0) {
if (_deltaTimesData.at(finalNonzeroIndex) != 0) {
break;
}
}
std::vector<double> tempDt;
for (int i = 0; i < (finalNonzeroIndex + 1); ++i) {
tempDt.push_back(_data[i]);
tempDt.push_back(_deltaTimesData[i]);
}
_profile.setDeltaTimes(tempDt);
*_deltaTimes = std::move(_deltaTimesData);
accept();
}

View File

@@ -1,577 +0,0 @@
/*****************************************************************************************
* *
* OpenSpace *
* *
* Copyright (c) 2014-2021 *
* *
* Permission is hereby granted, free of charge, to any person obtaining a copy of this *
* software and associated documentation files (the "Software"), to deal in the Software *
* without restriction, including without limitation the rights to use, copy, modify, *
* merge, publish, distribute, sublicense, and/or sell copies of the Software, and to *
* permit persons to whom the Software is furnished to do so, subject to the following *
* conditions: *
* *
* The above copyright notice and this permission notice shall be included in all copies *
* or substantial portions of the Software. *
* *
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, *
* INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A *
* PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT *
* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF *
* CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE *
* OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. *
****************************************************************************************/
#include "profile/keybindingsdialog.h"
#include "profile/line.h"
#include "profile/scriptlogdialog.h"
#include <openspace/scene/profile.h>
#include <qevent.h>
#include <algorithm>
#include <QKeyEvent>
#include <QCheckBox>
#include <QVBoxLayout>
#include <QPushButton>
#include <QLabel>
#include <QComboBox>
#include <QLineEdit>
#include <QTextEdit>
#include <QDialogButtonBox>
using namespace openspace;
namespace {
const Profile::Keybinding BlankKey= {
{ Key::Unknown, KeyModifier::NoModifier },
"",
"",
"",
true,
""
};
void replaceChars(std::string& src, const std::string& from, const std::string& to) {
std::string newString;
std::string::size_type found, last = 0;
while ((found = src.find(from, last)) != std::string::npos) {
newString.append(src, last, (found - last));
newString += to;
last = found + from.length();
}
newString += src.substr(last);
src.swap(newString);
}
std::string truncateString(std::string& s) {
const size_t maxLength = 50;
replaceChars(s, "\n", ";");
if (s.length() > maxLength) {
s.resize(maxLength);
s += "...";
}
return s;
}
std::string createOneLineSummary(Profile::Keybinding k) {
std::string summary;
int keymod = static_cast<int>(k.key.modifier);
if (keymod != static_cast<int>(KeyModifier::NoModifier)) {
summary += KeyModifierNames.at(keymod) + " ";
}
int keyname = static_cast<int>(k.key.key);
summary += KeyNames.at(keyname) + " ";
summary += truncateString(k.name) + " (";
summary += truncateString(k.documentation) + ") @ ";
summary += truncateString(k.guiPath) + " ";
summary += (k.isLocal) ? "local" : "remote";
summary += " `" + truncateString(k.script) + "`";
return summary;
}
} // namespace
KeybindingsDialog::KeybindingsDialog(Profile& profile, QWidget *parent)
: QDialog(parent)
, _profile(profile)
, _data(_profile.keybindings())
{
setWindowTitle("Assign Keybindings");
createWidgets();
transitionFromEditMode();
}
void KeybindingsDialog::appendScriptsToKeybind(std::string scripts) {
_scriptEdit->append(QString::fromStdString(std::move(scripts)));
}
void KeybindingsDialog::createWidgets() {
QBoxLayout* layout = new QVBoxLayout(this);
{
_list = new QListWidget;
connect(
_list, &QListWidget::itemSelectionChanged,
this, &KeybindingsDialog::listItemSelected
);
_list->setAlternatingRowColors(true);
_list->setMovement(QListView::Free);
_list->setResizeMode(QListView::Adjust);
for (size_t i = 0; i < _data.size(); ++i) {
std::string summary = createOneLineSummary(_data[i]);
_list->addItem(new QListWidgetItem(QString::fromStdString(summary)));
}
layout->addWidget(_list);
}
{
QBoxLayout* box = new QHBoxLayout;
_addButton = new QPushButton("Add new");
connect(
_addButton, &QPushButton::clicked,
this, &KeybindingsDialog::listItemAdded
);
box->addWidget(_addButton);
_removeButton = new QPushButton("Remove");
connect(
_removeButton, &QPushButton::clicked,
this, &KeybindingsDialog::listItemRemove
);
box->addWidget(_removeButton);
box->addStretch();
layout->addLayout(box);
}
layout->addWidget(new Line);
{
QGridLayout* box = new QGridLayout;
_keyModLabel = new QLabel("Key Modifier");
box->addWidget(_keyModLabel, 0, 0);
_keyModCombo = new QComboBox;
_keyModCombo->setToolTip(
"Modifier keys to hold while key is pressed (blank means none)"
);
QStringList comboModKeysStringList;
int modIdx = 0;
for (const std::pair<const int, std::string>& m : KeyModifierNames) {
comboModKeysStringList += QString::fromStdString(m.second);
_mapModKeyComboBoxIndexToKeyValue.push_back(modIdx++);
}
_keyModCombo->addItems(comboModKeysStringList);
connect(
_keyModCombo, QOverload<int>::of(&QComboBox::currentIndexChanged),
this, &KeybindingsDialog::keyModSelected
);
box->addWidget(_keyModCombo, 0, 1);
_keyLabel = new QLabel("Key");
box->addWidget(_keyLabel, 1, 0);
_keyCombo = new QComboBox;
_keyCombo->setToolTip("Key to press for this keybinding");
QStringList comboKeysStringList;
for (int i = 0; i < static_cast<int>(Key::Last); ++i) {
if (KeyNames.find(i) != KeyNames.end()) {
comboKeysStringList += QString::fromStdString(KeyNames.at(i));
// Create map to relate key combo box to integer value defined in Key
_mapKeyComboBoxIndexToKeyValue.push_back(i);
}
}
_keyCombo->addItems(comboKeysStringList);
connect(
_keyCombo, QOverload<int>::of(&QComboBox::currentIndexChanged),
this, &KeybindingsDialog::keySelected
);
box->addWidget(_keyCombo, 1, 1);
_nameLabel = new QLabel("Name:");
box->addWidget(_nameLabel, 2, 0);
_nameEdit = new QLineEdit;
_nameEdit->setToolTip("Name assigned to this keybinding");
box->addWidget(_nameEdit, 2, 1);
_guiPathLabel = new QLabel("GUI Path:");
box->addWidget(_guiPathLabel, 3, 0);
_guiPathEdit = new QLineEdit;
_guiPathEdit->setToolTip(
"[OPTIONAL] Path for where this keybinding appears in GUI menu"
);
box->addWidget(_guiPathEdit, 3, 1);
_documentationLabel = new QLabel("Documentation:");
box->addWidget(_documentationLabel, 4, 0);
_documentationEdit = new QLineEdit;
_documentationEdit->setToolTip(
"[OPTIONAL] Documentation entry for keybinding"
);
box->addWidget(_documentationEdit, 4, 1);
_localCheck = new QCheckBox("Local");
_localCheck->setToolTip(
"Determines whether the command, when executed, should be shared with "
"connected instances or only executed locally"
);
box->addWidget(_localCheck, 5, 0, 1, 2);
_scriptLabel = new QLabel("Script");
box->addWidget(_scriptLabel, 6, 0, 1, 2);
_chooseScriptsButton = new QPushButton("Choose Scripts");
connect(
_chooseScriptsButton, &QPushButton::clicked,
this, &KeybindingsDialog::chooseScripts
);
box->addWidget(_chooseScriptsButton, 6, 1, 1, 1);
_scriptEdit = new QTextEdit;
_scriptEdit->setAcceptRichText(false);
_scriptEdit->setToolTip("Command(s) to execute at keypress event");
_scriptEdit->setTabChangesFocus(true);
box->addWidget(_scriptEdit, 7, 0, 1, 2);
box->setRowStretch(7, 1);
QBoxLayout* buttonBox = new QHBoxLayout;
_saveButton = new QPushButton("Save");
connect(
_saveButton, &QPushButton::clicked,
this, &KeybindingsDialog::listItemSave
);
buttonBox->addWidget(_saveButton);
_cancelButton = new QPushButton("Cancel");
connect(
_cancelButton, &QPushButton::clicked,
this, &KeybindingsDialog::listItemCancelSave
);
buttonBox->addWidget(_cancelButton);
buttonBox->addStretch();
box->addLayout(buttonBox, 8, 1, 1, 2);
layout->addLayout(box);
}
layout->addWidget(new Line);
{
QBoxLayout* footerLayout = new QHBoxLayout;
_errorMsg = new QLabel;
_errorMsg->setObjectName("error-message");
_errorMsg->setWordWrap(true);
footerLayout->addWidget(_errorMsg);
_buttonBox = new QDialogButtonBox;
_buttonBox->setStandardButtons(QDialogButtonBox::Save | QDialogButtonBox::Cancel);
QObject::connect(
_buttonBox, &QDialogButtonBox::accepted,
this, &KeybindingsDialog::parseSelections
);
QObject::connect(
_buttonBox, &QDialogButtonBox::rejected,
this, &KeybindingsDialog::reject
);
footerLayout->addWidget(_buttonBox);
layout->addLayout(footerLayout);
}
}
void KeybindingsDialog::listItemSelected() {
QListWidgetItem *item = _list->currentItem();
int index = _list->row(item);
_currentKeybindingSelection = index;
if (_data.size() > 0) {
Profile::Keybinding& k = _data[index];
const int modifierKey = indexInKeyMapping(
_mapModKeyComboBoxIndexToKeyValue,
static_cast<int>(k.key.modifier)
);
_keyModCombo->setCurrentIndex(modifierKey);
if (k.key.key == Key::Unknown) {
_keyCombo->setCurrentIndex(0);
}
else {
const int key = indexInKeyMapping(
_mapKeyComboBoxIndexToKeyValue,
static_cast<int>(k.key.key)
);
_keyCombo->setCurrentIndex(key);
}
// Do key here
_nameEdit->setText(QString::fromStdString(k.name));
_guiPathEdit->setText(QString::fromStdString(k.guiPath));
_documentationEdit->setText(QString::fromStdString(k.documentation));
_localCheck->setChecked(k.isLocal);
_scriptEdit->setText(QString::fromStdString(k.script));
}
transitionToEditMode();
}
void KeybindingsDialog::keySelected(int index) {
_errorMsg->clear();
int selectedKey = _mapKeyComboBoxIndexToKeyValue[index];
checkForNumberKeyConflict(selectedKey);
checkForBindingConflict(_keyModCombo->currentIndex(), selectedKey);
}
void KeybindingsDialog::keyModSelected(int index) {
_errorMsg->clear();
int selectedKey = _mapModKeyComboBoxIndexToKeyValue[index];
checkForBindingConflict(selectedKey,
_mapKeyComboBoxIndexToKeyValue.at(_keyCombo->currentIndex()));
}
void KeybindingsDialog::addStringToErrorDisplay(const QString& newString) {
QString errorContents = _errorMsg->text();
bool alreadyContainsString = (errorContents.indexOf(newString, 0) != -1);
if (!alreadyContainsString) {
errorContents = newString + errorContents;
_errorMsg->setText(errorContents);
}
}
int KeybindingsDialog::indexInKeyMapping(std::vector<int>& mapVector, int keyInt) {
const auto it = std::find(mapVector.cbegin(), mapVector.cend(), keyInt);
return static_cast<int>(std::distance(mapVector.cbegin(), it));
}
bool KeybindingsDialog::isLineEmpty(int index) {
bool isEmpty = true;
if (!_list->item(index)->text().isEmpty()) {
isEmpty = false;
}
if (!_data.empty() && !_data.at(0).name.empty()) {
isEmpty = false;
}
return isEmpty;
}
void KeybindingsDialog::listItemAdded() {
_data.push_back(BlankKey);
_list->addItem(new QListWidgetItem(" (Enter details below & click 'Save')"));
// Scroll down to that blank line highlighted
_list->setCurrentRow(_list->count() - 1);
// Blank-out the 2 text fields, set combo box to index 0
_keyModCombo->setCurrentIndex(static_cast<int>(_data.back().key.modifier));
if (_data.back().key.key == Key::Unknown) {
_keyCombo->setCurrentIndex(0);
}
else {
_keyCombo->setCurrentIndex(static_cast<int>(_data.back().key.key));
}
_keyModCombo->setFocus(Qt::OtherFocusReason);
_nameEdit->setText(QString::fromStdString(_data.back().name));
_guiPathEdit->setText("/");
_documentationEdit->setText(QString::fromStdString(_data.back().documentation));
_localCheck->setChecked(false);
_scriptEdit->setText(QString::fromStdString(_data.back().script));
_currentKeybindingSelection = static_cast<int>(_data.size() - 1);
_editModeNewItem = true;
}
void KeybindingsDialog::checkForNumberKeyConflict(int key) {
const QString numKeyWarning = "Warning: Using a number key may conflict with the "
"keybindings for simulation time increments.\n";
if (key >= static_cast<int>(Key::Num0) && key <= static_cast<int>(Key::Num9)) {
addStringToErrorDisplay(numKeyWarning);
}
}
void KeybindingsDialog::checkForBindingConflict(int selectedModKey, int selectedKey) {
const QString localWarn = "Warning: New selection conflicts with binding '";
if (_currentKeybindingSelection >= static_cast<int>(_data.size())) {
return;
}
KeyModifier newModifier = static_cast<KeyModifier>(selectedModKey);
Key newKey = static_cast<Key>(selectedKey);
for (int i = 0; i < static_cast<int>(_data.size()); ++i) {
if (i == _currentKeybindingSelection) {
continue;
}
openspace::Profile::Keybinding k = _data[i];
if ((k.key.key == newKey) && (k.key.modifier == newModifier)) {
addStringToErrorDisplay(localWarn + QString::fromStdString(k.name) + "'.\n");
break;
}
}
}
void KeybindingsDialog::listItemSave() {
if (!areRequiredFormsFilled()) {
return;
}
QListWidgetItem* item = _list->currentItem();
int index = _list->row(item);
if (!_data.empty()) {
int keyModIdx = _mapModKeyComboBoxIndexToKeyValue.at(
_keyModCombo->currentIndex());
_data[index].key.modifier = static_cast<KeyModifier>(keyModIdx);
int keyIdx = _mapKeyComboBoxIndexToKeyValue.at(_keyCombo->currentIndex());
_data[index].key.key = static_cast<Key>(keyIdx);
_data[index].name = _nameEdit->text().toStdString();
_data[index].guiPath = _guiPathEdit->text().toStdString();
_data[index].documentation = _documentationEdit->text().toStdString();
_data[index].script = _scriptEdit->toPlainText().toStdString();
_data[index].isLocal = (_localCheck->isChecked());
std::string summary = createOneLineSummary(_data[index]);
_list->item(index)->setText(QString::fromStdString(summary));
}
transitionFromEditMode();
}
bool KeybindingsDialog::areRequiredFormsFilled() {
bool requiredFormsFilled = true;
std::string errors;
if (_keyCombo->currentIndex() < 0) {
errors += "Missing key";
requiredFormsFilled = false;
}
if (_nameEdit->text().length() == 0) {
if (!errors.empty()) {
errors += ", ";
}
errors += "Missing keybinding name";
requiredFormsFilled = false;
}
if (_scriptEdit->toPlainText().isEmpty()) {
if (!errors.empty()) {
errors += ", ";
}
errors += "Missing script";
requiredFormsFilled = false;
}
_errorMsg->setText(QString::fromStdString(errors));
return requiredFormsFilled;
}
void KeybindingsDialog::listItemCancelSave() {
listItemSelected();
transitionFromEditMode();
if (_editModeNewItem && !_data.empty() &&
(_data.back().name.length() == 0 || _data.back().script.length() == 0 ||
_data.back().key.key == Key::Unknown))
{
listItemRemove();
}
_editModeNewItem = false;
}
void KeybindingsDialog::listItemRemove() {
if (_list->count() > 0) {
if (_list->count() == 1) {
// Special case where last remaining item is being removed (QListWidget does
// not like the final item being removed so instead clear it & leave it)
_data.at(0) = BlankKey;
_list->item(0)->setText("");
}
else {
int index = _list->currentRow();
if (index >= 0 && index < _list->count()) {
_list->takeItem(index);
if (!_data.empty()) {
_data.erase(_data.begin() + index);
}
}
}
}
_list->clearSelection();
transitionFromEditMode();
}
void KeybindingsDialog::transitionToEditMode() {
_saveButton->setDisabled(true);
_cancelButton->setDisabled(true);
_buttonBox->setDisabled(true);
_keyLabel->setText("<font color='black'>Key</font>");
_keyModLabel->setText("<font color='black'>Key Modifier</font>");
_nameLabel->setText("<font color='black'>Name</font>");
_scriptLabel->setText("<font color='black'>Script</font>");
_guiPathLabel->setText("<font color='black'>GUI Path</font>");
_documentationLabel->setText("<font color='black'>Documentation</font>");
editBoxDisabled(false);
_errorMsg->setText("");
}
void KeybindingsDialog::transitionFromEditMode() {
_list->setDisabled(false);
_addButton->setDisabled(false);
_removeButton->setDisabled(false);
_saveButton->setDisabled(false);
_cancelButton->setDisabled(false);
_buttonBox->setDisabled(false);
_keyLabel->setText("<font color='light gray'>Key</font>");
_keyModLabel->setText("<font color='light gray'>Key Modifier</font>");
_nameLabel->setText("<font color='light gray'>Name</font>");
_scriptLabel->setText("<font color='light gray'>Script</font>");
_guiPathLabel->setText("<font color='light gray'>GUI Path</font>");
_documentationLabel->setText("<font color='light gray'>Documentation</font>");
editBoxDisabled(true);
_errorMsg->setText("");
}
void KeybindingsDialog::editBoxDisabled(bool disabled) {
_keyLabel->setDisabled(disabled);
_keyCombo->setDisabled(disabled);
_keyModLabel->setDisabled(disabled);
_keyModCombo->setDisabled(disabled);
_nameLabel->setDisabled(disabled);
_nameEdit->setDisabled(disabled);
_guiPathLabel->setDisabled(disabled);
_guiPathEdit->setDisabled(disabled);
_documentationLabel->setDisabled(disabled);
_documentationEdit->setDisabled(disabled);
_localCheck->setDisabled(disabled);
_scriptLabel->setDisabled(disabled);
_scriptEdit->setDisabled(disabled);
_cancelButton->setDisabled(disabled);
_saveButton->setDisabled(disabled);
_chooseScriptsButton->setDisabled(disabled);
}
void KeybindingsDialog::parseSelections() {
// Handle case with only one remaining but empty line
if ((_data.size() == 1) && (_data.at(0).name.empty())) {
_data.clear();
}
_profile.setKeybindings(_data);
accept();
}
void KeybindingsDialog::chooseScripts() {
_errorMsg->clear();
ScriptlogDialog d(this);
connect(&d, &ScriptlogDialog::scriptsSelected, this, &KeybindingsDialog::appendScriptsToKeybind);
d.exec();
}
void KeybindingsDialog::keyPressEvent(QKeyEvent* evt) {
if (evt->key() == Qt::Key_Enter || evt->key() == Qt::Key_Return) {
return;
}
else if (evt->key() == Qt::Key_Escape) {
if (_editModeNewItem) {
listItemCancelSave();
return;
}
}
QDialog::keyPressEvent(evt);
}

View File

@@ -35,10 +35,10 @@
#include <QPushButton>
#include <QVBoxLayout>
MarkNodesDialog::MarkNodesDialog(openspace::Profile& profile, QWidget* parent)
MarkNodesDialog::MarkNodesDialog(QWidget* parent, std::vector<std::string>* markedNodes)
: QDialog(parent)
, _profile(profile)
, _data(_profile.markNodes())
, _markedNodes(markedNodes)
, _markedNodesData(*_markedNodes)
{
setWindowTitle("Mark Interesting Nodes");
createWidgets();
@@ -55,9 +55,9 @@ void MarkNodesDialog::createWidgets() {
_list->setMovement(QListView::Free);
_list->setResizeMode(QListView::Adjust);
for (size_t i = 0; i < _data.size(); ++i) {
for (size_t i = 0; i < _markedNodesData.size(); ++i) {
_markedNodesListItems.push_back(
new QListWidgetItem(QString::fromStdString(_data[i]))
new QListWidgetItem(QString::fromStdString(_markedNodesData[i]))
);
_list->addItem(_markedNodesListItems[i]);
}
@@ -110,12 +110,17 @@ void MarkNodesDialog::listItemAdded() {
}
std::string itemToAdd = _newNode->text().toStdString();
const auto it = std::find(_data.cbegin(), _data.cend(), itemToAdd);
if (it != _data.end()) {
_list->setCurrentRow(static_cast<int>(std::distance(_data.cbegin(), it)));
const auto it = std::find(
_markedNodesData.cbegin(), _markedNodesData.cend(),
itemToAdd
);
if (it != _markedNodesData.end()) {
_list->setCurrentRow(
static_cast<int>(std::distance(_markedNodesData.cbegin(), it))
);
}
else {
_data.push_back(itemToAdd);
_markedNodesData.push_back(itemToAdd);
_markedNodesListItems.push_back(new QListWidgetItem(_newNode->text()));
_list->addItem(_markedNodesListItems.back());
@@ -136,12 +141,12 @@ void MarkNodesDialog::listItemRemove() {
}
_list->takeItem(index);
_data.erase(_data.begin() + index);
_markedNodesData.erase(_markedNodesData.begin() + index);
_markedNodesListItems.erase(_markedNodesListItems.begin() + index);
}
void MarkNodesDialog::parseSelections() {
_profile.setMarkNodes(_data);
*_markedNodes = std::move(_markedNodesData);
accept();
}

View File

@@ -34,32 +34,32 @@
#include <QVBoxLayout>
#include <algorithm>
MetaDialog::MetaDialog(openspace::Profile& profile, QWidget *parent)
MetaDialog::MetaDialog(QWidget* parent, std::optional<openspace::Profile::Meta>* meta)
: QDialog(parent)
, _profile(profile)
, _meta(meta)
{
setWindowTitle("Meta");
createWidgets();
if (_profile.meta().has_value()) {
openspace::Profile::Meta meta = *_profile.meta();
if (meta.name.has_value()) {
_nameEdit->setText(QString::fromStdString(*meta.name));
if (_meta->has_value()) {
const openspace::Profile::Meta& m = **_meta;
if (m.name.has_value()) {
_nameEdit->setText(QString::fromStdString(*m.name));
}
if (meta.version.has_value()) {
_versionEdit->setText(QString::fromStdString(*meta.version));
if (m.version.has_value()) {
_versionEdit->setText(QString::fromStdString(*m.version));
}
if (meta.description.has_value()) {
_descriptionEdit->setText(QString::fromStdString(*meta.description));
if (m.description.has_value()) {
_descriptionEdit->setText(QString::fromStdString(*m.description));
}
if (meta.author.has_value()) {
_authorEdit->setText(QString::fromStdString(*meta.author));
if (m.author.has_value()) {
_authorEdit->setText(QString::fromStdString(*m.author));
}
if (meta.url.has_value()) {
_urlEdit->setText(QString::fromStdString(*meta.url));
if (m.url.has_value()) {
_urlEdit->setText(QString::fromStdString(*m.url));
}
if (meta.license.has_value()) {
_licenseEdit->setText(QString::fromStdString(*meta.license));
if (m.license.has_value()) {
_licenseEdit->setText(QString::fromStdString(*m.license));
}
}
}
@@ -127,10 +127,10 @@ void MetaDialog::save() {
if (!_licenseEdit->text().isEmpty()) {
m.license = _licenseEdit->text().toStdString();
}
_profile.setMeta(m);
*_meta = std::move(m);
}
else {
_profile.clearMeta();
*_meta = std::nullopt;
}
accept();
}

View File

@@ -40,10 +40,11 @@ namespace {
const Profile::Module Blank = { "", "", "" };
} // namespace
ModulesDialog::ModulesDialog(Profile& profile, QWidget *parent)
ModulesDialog::ModulesDialog(QWidget* parent,
std::vector<openspace::Profile::Module>* modules)
: QDialog(parent)
, _profile(profile)
, _data(_profile.modules())
, _modules(modules)
, _moduleData(*_modules)
{
setWindowTitle("Modules");
createWidgets();
@@ -63,7 +64,7 @@ void ModulesDialog::createWidgets() {
_list->setMovement(QListView::Free);
_list->setResizeMode(QListView::Adjust);
for (const Profile::Module& m : _data) {
for (const Profile::Module& m : _moduleData) {
_list->addItem(new QListWidgetItem(createOneLineSummary(m)));
}
layout->addWidget(_list);
@@ -176,8 +177,8 @@ void ModulesDialog::listItemSelected() {
QListWidgetItem* item = _list->currentItem();
int index = _list->row(item);
if (!_data.empty()) {
const Profile::Module& m = _data[index];
if (!_moduleData.empty()) {
const Profile::Module& m = _moduleData[index];
_moduleEdit->setText(QString::fromStdString(m.name));
if (m.loadedInstruction.has_value()) {
_loadedEdit->setText(QString::fromStdString(*m.loadedInstruction));
@@ -200,7 +201,7 @@ bool ModulesDialog::isLineEmpty(int index) const {
if (!_list->item(index)->text().isEmpty()) {
isEmpty = false;
}
if (!_data.empty() && !_data.at(0).name.empty()) {
if (!_moduleData.empty() && !_moduleData.at(0).name.empty()) {
isEmpty = false;
}
return isEmpty;
@@ -213,13 +214,13 @@ void ModulesDialog::listItemAdded() {
// Special case where list is "empty" but really has one line that is blank.
// This is done because QListWidget does not seem to like having its sole
// remaining item being removed.
_data.at(0) = Blank;
_moduleData.at(0) = Blank;
_list->item(0)->setText(" (Enter details below & click 'Save')");
_list->setCurrentRow(0);
transitionToEditMode();
}
else {
_data.push_back(Blank);
_moduleData.push_back(Blank);
_list->addItem(new QListWidgetItem(" (Enter details below & click 'Save')"));
//Scroll down to that blank line highlighted
_list->setCurrentRow(_list->count() - 1);
@@ -227,16 +228,18 @@ void ModulesDialog::listItemAdded() {
}
// Blank-out the 2 text fields, set combo box to index 0
_moduleEdit->setText(QString::fromStdString(_data.back().name));
if (_data.back().loadedInstruction.has_value()) {
_loadedEdit->setText(QString::fromStdString(*_data.back().loadedInstruction));
_moduleEdit->setText(QString::fromStdString(_moduleData.back().name));
if (_moduleData.back().loadedInstruction.has_value()) {
_loadedEdit->setText(QString::fromStdString(
*_moduleData.back().loadedInstruction
));
}
else {
_loadedEdit->clear();
}
if (_data.back().notLoadedInstruction.has_value()) {
if (_moduleData.back().notLoadedInstruction.has_value()) {
_notLoadedEdit->setText(
QString::fromStdString(*_data.back().notLoadedInstruction)
QString::fromStdString(*_moduleData.back().notLoadedInstruction)
);
}
else {
@@ -255,11 +258,11 @@ void ModulesDialog::listItemSave() {
QListWidgetItem* item = _list->currentItem();
int index = _list->row(item);
if ( _data.size() > 0) {
_data[index].name = _moduleEdit->text().toStdString();
_data[index].loadedInstruction = _loadedEdit->text().toStdString();
_data[index].notLoadedInstruction = _notLoadedEdit->text().toStdString();
_list->item(index)->setText(createOneLineSummary(_data[index]));
if (_moduleData.size() > 0) {
_moduleData[index].name = _moduleEdit->text().toStdString();
_moduleData[index].loadedInstruction = _loadedEdit->text().toStdString();
_moduleData[index].notLoadedInstruction = _notLoadedEdit->text().toStdString();
_list->item(index)->setText(createOneLineSummary(_moduleData[index]));
}
transitionFromEditMode();
_editModeNewItem = false;
@@ -267,7 +270,7 @@ void ModulesDialog::listItemSave() {
void ModulesDialog::listItemCancelSave() {
transitionFromEditMode();
if (_editModeNewItem && !_data.empty() && _data.back().name.empty()) {
if (_editModeNewItem && !_moduleData.empty() && _moduleData.back().name.empty()) {
listItemRemove();
}
_editModeNewItem = false;
@@ -279,15 +282,15 @@ void ModulesDialog::listItemRemove() {
if (_list->count() == 1) {
// Special case where last remaining item is being removed (QListWidget
// doesn't like the final item being removed so instead clear it)
_data.at(0) = Blank;
_moduleData.at(0) = Blank;
_list->item(0)->setText("");
}
else {
int index = _list->currentRow();
if (index >= 0 && index < _list->count()) {
delete _list->takeItem(index);
if (!_data.empty()) {
_data.erase(_data.begin() + index);
if (!_moduleData.empty()) {
_moduleData.erase(_moduleData.begin() + index);
}
}
}
@@ -336,10 +339,10 @@ void ModulesDialog::editBoxDisabled(bool disabled) {
void ModulesDialog::parseSelections() {
// Handle case with only one remaining but empty line
if ((_data.size() == 1) && (_data.at(0).name.empty())) {
_data.clear();
if ((_moduleData.size() == 1) && (_moduleData.at(0).name.empty())) {
_moduleData.clear();
}
_profile.setModules(_data);
*_modules = std::move(_moduleData);
accept();
}

View File

@@ -24,11 +24,11 @@
#include "profile/profileedit.h"
#include "profile/actiondialog.h"
#include "profile/additionalscriptsdialog.h"
#include "profile/assetsdialog.h"
#include "profile/cameradialog.h"
#include "profile/deltatimesdialog.h"
#include "profile/keybindingsdialog.h"
#include "profile/line.h"
#include "profile/marknodesdialog.h"
#include "profile/metadialog.h"
@@ -36,6 +36,7 @@
#include "profile/propertiesdialog.h"
#include "profile/timedialog.h"
#include <openspace/scene/profile.h>
#include <ghoul/fmt.h>
#include <QDialogButtonBox>
#include <QKeyEvent>
#include <QLabel>
@@ -69,17 +70,18 @@ namespace {
return results;
}
std::string summarizeKeybindings(const std::vector<Profile::Keybinding>& keybindings)
std::string summarizeKeybindings(const std::vector<Profile::Keybinding>& keybindings,
const std::vector<Profile::Action>& actions)
{
std::string results;
for (Profile::Keybinding k : keybindings) {
results += k.name + " (";
int keymod = static_cast<int>(k.key.modifier);
if (keymod != static_cast<int>(openspace::KeyModifier::NoModifier)) {
results += openspace::KeyModifierNames.at(keymod) + "+";
}
results += openspace::KeyNames.at(static_cast<int>(k.key.key));
results += ")\n";
const auto it = std::find_if(
actions.cbegin(), actions.cend(),
[id = k.action](const Profile::Action& a) { return a.identifier == id; }
);
std::string name = it != actions.end() ? it->name : "Unknown action";
results += fmt::format("{} ({})\n", name, ghoul::to_string(k.key));
}
return results;
}
@@ -87,7 +89,7 @@ namespace {
std::string summarizeProperties(const std::vector<Profile::Property>& properties) {
std::string results;
for (openspace::Profile::Property p : properties) {
results += p.name + " = " + p.value + '\n';
results += fmt::format("{} = {}\n", p.name, p.value);
}
return results;
}
@@ -333,26 +335,26 @@ void ProfileEdit::createWidgets(const std::string& profileName) {
}
void ProfileEdit::initSummaryTextForEachCategory() {
_modulesLabel->setText(labelText(_profile.modules().size(), "Modules"));
_modulesLabel->setText(labelText(_profile.modules.size(), "Modules"));
_assetsLabel->setText(labelText(_profile.assets().size(), "Assets"));
_assetsEdit->setText(QString::fromStdString(summarizeAssets(_profile.assets())));
_assetsLabel->setText(labelText(_profile.assets.size(), "Assets"));
_assetsEdit->setText(QString::fromStdString(summarizeAssets(_profile.assets)));
_propertiesLabel->setText(labelText(_profile.properties().size(), "Properties"));
_propertiesLabel->setText(labelText(_profile.properties.size(), "Properties"));
_propertiesEdit->setText(
QString::fromStdString(summarizeProperties(_profile.properties()))
QString::fromStdString(summarizeProperties(_profile.properties))
);
_keybindingsLabel->setText(labelText(_profile.keybindings().size(), "Keybindings"));
_keybindingsEdit->setText(
QString::fromStdString(summarizeKeybindings(_profile.keybindings()))
);
_keybindingsLabel->setText(labelText(_profile.keybindings.size(), "Keybindings"));
_keybindingsEdit->setText(QString::fromStdString(
summarizeKeybindings(_profile.keybindings, _profile.actions)
));
_deltaTimesLabel->setText(
labelText(_profile.deltaTimes().size(), "Simulation Time Increments")
labelText(_profile.deltaTimes.size(), "Simulation Time Increments")
);
_interestingNodesLabel->setText(
labelText(_profile.markNodes().size(), "Mark Interesting Nodes")
labelText(_profile.markNodes.size(), "Mark Interesting Nodes")
);
}
@@ -401,68 +403,68 @@ void ProfileEdit::duplicateProfile() {
void ProfileEdit::openMeta() {
_errorMsg->clear();
MetaDialog(_profile, this).exec();
MetaDialog(this, &_profile.meta).exec();
}
void ProfileEdit::openModules() {
_errorMsg->clear();
ModulesDialog(_profile, this).exec();
_modulesLabel->setText(labelText(_profile.modules().size(), "Modules"));
ModulesDialog(this, &_profile.modules).exec();
_modulesLabel->setText(labelText(_profile.modules.size(), "Modules"));
}
void ProfileEdit::openProperties() {
_errorMsg->clear();
PropertiesDialog(_profile, this).exec();
_propertiesLabel->setText(labelText(_profile.properties().size(), "Properties"));
PropertiesDialog(this, &_profile.properties).exec();
_propertiesLabel->setText(labelText(_profile.properties.size(), "Properties"));
_propertiesEdit->setText(
QString::fromStdString(summarizeProperties(_profile.properties()))
QString::fromStdString(summarizeProperties(_profile.properties))
);
}
void ProfileEdit::openKeybindings() {
_errorMsg->clear();
KeybindingsDialog(_profile, this).exec();
_keybindingsLabel->setText(labelText(_profile.keybindings().size(), "Keybindings"));
_keybindingsEdit->setText(
QString::fromStdString(summarizeKeybindings(_profile.keybindings()))
);
ActionDialog(this, &_profile.actions, &_profile.keybindings).exec();
_keybindingsLabel->setText(labelText(_profile.keybindings.size(), "Keybindings"));
_keybindingsEdit->setText(QString::fromStdString(
summarizeKeybindings(_profile.keybindings, _profile.actions)
));
}
void ProfileEdit::openAssets() {
_errorMsg->clear();
AssetsDialog(_profile, _assetBasePath, _userAssetBasePath, this).exec();
_assetsLabel->setText(labelText(_profile.assets().size(), "Assets"));
_assetsEdit->setText(QString::fromStdString(summarizeAssets(_profile.assets())));
AssetsDialog(this, &_profile, _assetBasePath, _userAssetBasePath).exec();
_assetsLabel->setText(labelText(_profile.assets.size(), "Assets"));
_assetsEdit->setText(QString::fromStdString(summarizeAssets(_profile.assets)));
}
void ProfileEdit::openTime() {
_errorMsg->clear();
TimeDialog(_profile, this).exec();
TimeDialog(this, &_profile.time).exec();
}
void ProfileEdit::openDeltaTimes() {
_errorMsg->clear();
DeltaTimesDialog(_profile, this).exec();
DeltaTimesDialog(this, &_profile.deltaTimes).exec();
_deltaTimesLabel->setText(
labelText(_profile.deltaTimes().size(), "Simulation Time Increments")
labelText(_profile.deltaTimes.size(), "Simulation Time Increments")
);
}
void ProfileEdit::openAddedScripts() {
_errorMsg->clear();
AdditionalScriptsDialog(_profile, this).exec();
AdditionalScriptsDialog(this, &_profile.additionalScripts).exec();
}
void ProfileEdit::openCamera() {
_errorMsg->clear();
CameraDialog(_profile, this).exec();
CameraDialog(this, &_profile.camera).exec();
}
void ProfileEdit::openMarkNodes() {
_errorMsg->clear();
MarkNodesDialog(_profile, this).exec();
MarkNodesDialog(this, &_profile.markNodes).exec();
_interestingNodesLabel->setText(
labelText(_profile.markNodes().size(), "Mark Interesting Nodes")
labelText(_profile.markNodes.size(), "Mark Interesting Nodes")
);
}

View File

@@ -46,10 +46,11 @@ namespace {
};
} // namespace
PropertiesDialog::PropertiesDialog(Profile& profile, QWidget *parent)
PropertiesDialog::PropertiesDialog(QWidget* parent,
std::vector<openspace::Profile::Property>* properties)
: QDialog(parent)
, _profile(profile)
, _data(_profile.properties())
, _properties(properties)
, _propertyData(*_properties)
{
setWindowTitle("Set Property Values");
createWidgets();
@@ -65,8 +66,8 @@ void PropertiesDialog::createWidgets() {
_list, &QListWidget::itemSelectionChanged,
this, &PropertiesDialog::listItemSelected
);
for (size_t i = 0; i < _data.size(); ++i) {
_list->addItem(new QListWidgetItem(createOneLineSummary(_data[i])));
for (size_t i = 0; i < _propertyData.size(); ++i) {
_list->addItem(new QListWidgetItem(createOneLineSummary(_propertyData[i])));
}
layout->addWidget(_list);
}
@@ -172,8 +173,8 @@ void PropertiesDialog::listItemSelected() {
QListWidgetItem* item = _list->currentItem();
int index = _list->row(item);
if (_data.size() > 0) {
Profile::Property& p = _data[index];
if (_propertyData.size() > 0) {
Profile::Property& p = _propertyData[index];
if (p.setType == Profile::Property::SetType::SetPropertyValueSingle) {
_commandCombo->setCurrentIndex(0);
}
@@ -191,7 +192,7 @@ bool PropertiesDialog::isLineEmpty(int index) {
if (!_list->item(index)->text().isEmpty()) {
isEmpty = false;
}
if (!_data.empty() && !_data.at(0).name.empty()) {
if (!_propertyData.empty() && !_propertyData.at(0).name.empty()) {
isEmpty = false;
}
return isEmpty;
@@ -204,13 +205,13 @@ void PropertiesDialog::listItemAdded() {
// Special case where list is "empty" but really has one line that is blank.
// This is done because QListWidget does not seem to like having its sole
// remaining item being removed.
_data.at(0) = Blank;
_propertyData.at(0) = Blank;
_list->item(0)->setText(" (Enter details below & click 'Save')");
_list->setCurrentRow(0);
transitionToEditMode();
}
else {
_data.push_back(Blank);
_propertyData.push_back(Blank);
_list->addItem(new QListWidgetItem(" (Enter details below & click 'Save')"));
//Scroll down to that blank line highlighted
_list->setCurrentRow(_list->count() - 1);
@@ -218,8 +219,8 @@ void PropertiesDialog::listItemAdded() {
// Blank-out the 2 text fields, set combo box to index 0
_commandCombo->setCurrentIndex(0);
_propertyEdit->setText(QString::fromStdString(_data.back().name));
_valueEdit->setText(QString::fromStdString(_data.back().value));
_propertyEdit->setText(QString::fromStdString(_propertyData.back().name));
_valueEdit->setText(QString::fromStdString(_propertyData.back().value));
_commandCombo->setFocus(Qt::OtherFocusReason);
_editModeNewItem = true;
}
@@ -232,16 +233,17 @@ void PropertiesDialog::listItemSave() {
QListWidgetItem* item = _list->currentItem();
int index = _list->row(item);
if ( _data.size() > 0) {
if (_propertyData.size() > 0) {
if (_commandCombo->currentIndex() == 0) {
_data[index].setType = Profile::Property::SetType::SetPropertyValueSingle;
_propertyData[index].setType =
Profile::Property::SetType::SetPropertyValueSingle;
}
else {
_data[index].setType = Profile::Property::SetType::SetPropertyValue;
_propertyData[index].setType = Profile::Property::SetType::SetPropertyValue;
}
_data[index].name = _propertyEdit->text().toStdString();
_data[index].value = _valueEdit->text().toStdString();
_list->item(index)->setText(createOneLineSummary(_data[index]));
_propertyData[index].name = _propertyEdit->text().toStdString();
_propertyData[index].value = _valueEdit->text().toStdString();
_list->item(index)->setText(createOneLineSummary(_propertyData[index]));
}
transitionFromEditMode();
_editModeNewItem = false;
@@ -269,8 +271,10 @@ void PropertiesDialog::listItemCancelSave() {
listItemSelected();
transitionFromEditMode();
if (_editModeNewItem) {
if (_data.size() > 0) {
if (_data.back().name.length() == 0 || _data.back().value.length() == 0) {
if (_propertyData.size() > 0) {
if (_propertyData.back().name.length() == 0 ||
_propertyData.back().value.length() == 0)
{
listItemRemove();
}
}
@@ -284,15 +288,15 @@ void PropertiesDialog::listItemRemove() {
if (_list->count() == 1) {
//Special case where last remaining item is being removed (QListWidget
// doesn't like the final item being removed so instead clear it)
_data.at(0) = Blank;
_propertyData.at(0) = Blank;
_list->item(0)->setText("");
}
else {
int index = _list->currentRow();
if (index >= 0 && index < _list->count()) {
delete _list->takeItem(index);
if (_data.size() > 0) {
_data.erase(_data.begin() + index);
if (_propertyData.size() > 0) {
_propertyData.erase(_propertyData.begin() + index);
}
}
}
@@ -341,10 +345,10 @@ void PropertiesDialog::editBoxDisabled(bool disabled) {
void PropertiesDialog::parseSelections() {
// Handle case with only one remaining but empty line
if ((_data.size() == 1) && (_data.at(0).name.compare("") == 0)) {
_data.clear();
if ((_propertyData.size() == 1) && (_propertyData.at(0).name.compare("") == 0)) {
_propertyData.clear();
}
_profile.setProperties(_data);
*_properties = std::move(_propertyData);
accept();
}

View File

@@ -37,20 +37,20 @@
using namespace openspace;
TimeDialog::TimeDialog(openspace::Profile& profile, QWidget* parent)
TimeDialog::TimeDialog(QWidget* parent, std::optional<openspace::Profile::Time>* time)
: QDialog(parent)
, _profile(profile)
, _time(time)
{
setWindowTitle("Time");
createWidgets();
QStringList types = { "Absolute", "Relative" };
_typeCombo->addItems(types);
if (_profile.time().has_value()) {
_data = *_profile.time();
if (_data.type == Profile::Time::Type::Relative) {
if (_data.value == "") {
_data.value = "now";
if (_time->has_value()) {
_timeData = **_time;
if (_timeData.type == Profile::Time::Type::Relative) {
if (_timeData.value == "") {
_timeData.value = "now";
}
_relativeEdit->setSelection(0, _relativeEdit->text().length());
}
@@ -59,11 +59,11 @@ TimeDialog::TimeDialog(openspace::Profile& profile, QWidget* parent)
}
}
else {
_data.type = Profile::Time::Type::Relative;
_data.value = "now";
_timeData.type = Profile::Time::Type::Relative;
_timeData.value = "now";
}
_initializedAsAbsolute = (_data.type == Profile::Time::Type::Absolute);
enableAccordingToType(static_cast<int>(_data.type));
_initializedAsAbsolute = (_timeData.type == Profile::Time::Type::Absolute);
enableAccordingToType(static_cast<int>(_timeData.type));
}
void TimeDialog::createWidgets() {
@@ -117,15 +117,15 @@ void TimeDialog::enableAccordingToType(int idx) {
_relativeEdit->setText("now");
}
else {
_relativeEdit->setText(QString::fromStdString(_data.value));
_relativeEdit->setText(QString::fromStdString(_timeData.value));
}
_relativeEdit->setFocus(Qt::OtherFocusReason);
}
else {
_relativeEdit->setText("<font color='gray'>Relative Time:</font>");
size_t tIdx = _data.value.find_first_of('T', 0);
QString importDate = QString::fromStdString(_data.value.substr(0, tIdx));
QString importTime = QString::fromStdString(_data.value.substr(tIdx + 1));
size_t tIdx = _timeData.value.find_first_of('T', 0);
QString importDate = QString::fromStdString(_timeData.value.substr(0, tIdx));
QString importTime = QString::fromStdString(_timeData.value.substr(tIdx + 1));
_absoluteEdit->setDate(QDate::fromString(importDate, Qt::DateFormat::ISODate));
_absoluteEdit->setTime(QTime::fromString(importTime));
_relativeEdit->clear();
@@ -144,13 +144,13 @@ void TimeDialog::approved() {
constexpr const int Relative = static_cast<int>(Profile::Time::Type::Relative);
if (_typeCombo->currentIndex() == Relative) {
if (_relativeEdit->text().isEmpty()) {
_profile.clearTime();
*_time = std::nullopt;
}
else {
Profile::Time t;
t.type = Profile::Time::Type::Relative;
t.value = _relativeEdit->text().toStdString();
_profile.setTime(t);
*_time = t;
}
}
else {
@@ -161,7 +161,7 @@ void TimeDialog::approved() {
_absoluteEdit->date().toString("yyyy-MM-dd").toStdString(),
_absoluteEdit->time().toString().toStdString()
);
_profile.setTime(t);
*_time = t;
}
accept();
}

View File

@@ -960,7 +960,7 @@ void checkCommandLineForSettings(int& argc, char** argv, bool& hasSGCT, bool& ha
}
std::string setWindowConfigPresetForGui(const std::string labelFromCfgFile,
const std::string xmlExt, bool haveCliSGCTConfig,
bool haveCliSGCTConfig,
const std::string& sgctFunctionName)
{
configuration::Configuration& config = *global::configuration;
@@ -1046,8 +1046,9 @@ int main(int argc, char* argv[]) {
//
// Parse commandline arguments
//
char* prgName = argv[0];
ghoul::cmdparser::CommandlineParser parser(
std::string(argv[0]),
std::string(prgName),
ghoul::cmdparser::CommandlineParser::AllowUnknownCommands::Yes
);
@@ -1159,7 +1160,6 @@ int main(int argc, char* argv[]) {
const std::string xmlExt = ".xml";
std::string windowCfgPreset = setWindowConfigPresetForGui(
labelFromCfgFile,
xmlExt,
hasSGCTConfig,
sgctFunctionName
);

View File

@@ -129,4 +129,4 @@ int main(int argc, char** argv) {
LINFO("Server stopped");
return 0;
};
}

View File

@@ -1,7 +1,6 @@
-- This is a blank scene that that just sets up the default menus/dasboard/keys, etc.
local assetHelper = asset.require('util/asset_helper')
local sceneHelper = asset.require('util/scene_helper')
local propertyHelper = asset.require('util/property_helper')
-- Specifying which other assets should be loaded in this scene
@@ -14,36 +13,47 @@ asset.require('util/default_keybindings')
-- Load web gui
local webGui = asset.require('util/webgui')
-- Keybindings that are specific for this scene
local Keybindings = {
{
Key = "h",
Name="Toggle Trails",
Command = "local list = openspace.getProperty('{planetTrail_solarSystem}.Renderable.Enabled'); for _,v in pairs(list) do openspace.setPropertyValueSingle(v, not openspace.getPropertyValue(v)) end\n" ..
"local moonlist = openspace.getProperty('{moonTrail_solarSystem}.Renderable.Enabled'); for _,v in pairs(moonlist) do openspace.setPropertyValueSingle(v, not openspace.getPropertyValue(v)) end",
Documentation = "Toggles the visibility of planet and moon trails",
GuiPath = "/Rendering",
Local = false
},
{
Key = "l",
Name = "Toggle planet labels",
Command = "local list = openspace.getProperty('{solarsystem_labels}.Renderable.Enabled'); for _,v in pairs(list) do openspace.setPropertyValueSingle(v, not openspace.getPropertyValue(v)) end",
Documentation = "Turns on visibility for all solar system labels",
GuiPath = "/Rendering",
Local = false
}
local toggle_trails = {
Identifier = "os_default.toggle_trails",
Name = "Toggle Trails",
Command = "local list = openspace.getProperty('{planetTrail_solarSystem}.Renderable.Enabled'); for _,v in pairs(list) do openspace.setPropertyValueSingle(v, not openspace.getPropertyValue(v)) end\n" ..
"local moonlist = openspace.getProperty('{moonTrail_solarSystem}.Renderable.Enabled'); for _,v in pairs(moonlist) do openspace.setPropertyValueSingle(v, not openspace.getPropertyValue(v)) end",
Documentation = "Toggles the visibility of planet and moon trails",
GuiPath = "/Rendering",
IsLocal = false,
Key = "h"
}
local toggle_planet_labels = {
Identifier = "os_default.toggle_planet_labels",
Name = "Toggle planet labels",
Command = "local list = openspace.getProperty('{solarsystem_labels}.Renderable.Enabled'); for _,v in pairs(list) do openspace.setPropertyValueSingle(v, not openspace.getPropertyValue(v)) end",
Documentation = "Turns on visibility for all solar system labels",
GuiPath = "/Rendering",
IsLocal = false,
Key = "l"
}
asset.onInitialize(function ()
webGui.setCefRoute("onscreen")
sceneHelper.bindKeys(Keybindings)
openspace.action.registerAction(toggle_trails)
openspace.bindKey(toggle_trails.Key, toggle_trails.Identifier)
openspace.action.registerAction(toggle_planet_labels)
openspace.bindKey(toggle_planet_labels.Key, toggle_planet_labels.Identifier)
openspace.setDefaultGuiSorting()
openspace.setPropertyValueSingle("RenderEngine.VerticalLogOffset", 0.100000)
end)
asset.onDeinitialize(function ()
sceneHelper.unbindKeys(Keybindings)
openspace.action.removeAction(toggle_trails.Identifier)
openspace.clearKey(toggle_trails.Key)
openspace.action.removeAction(toggle_planet_labels.Identifier)
openspace.clearKey(toggle_planet_labels.Key)
end)

View File

@@ -1,5 +1,4 @@
local assetHelper = asset.require('util/asset_helper')
local sceneHelper = asset.require('util/scene_helper')
local propertyHelper = asset.require('util/property_helper')
local debugHelper = asset.require('util/debug_helper')

View File

@@ -0,0 +1,47 @@
local assetHelper = asset.require('util/asset_helper')
local earth = asset.require('scene/solarsystem/planets/earth/earth')
local sunTransforms = asset.require('scene/solarsystem/sun/transforms')
local models = asset.syncedResource({
Name = "New Horizons Model",
Type = "HttpSynchronization",
Identifier = "newhorizons_model",
Version = 2
})
local lat = 40.7306
local long = -73.9352
local Example_GlobeRotation = {
Identifier = "Example_GlobeRotation",
Parent = earth.Earth.Identifier,
Transform = {
Translation = {
Type = "GlobeTranslation",
Globe = earth.Earth.Identifier,
Latitude = lat,
Longitude = long,
Altitude = 6,
UseHeightmap = true
},
Rotation = {
Type = "GlobeRotation",
Globe = earth.Earth.Identifier,
Latitude = lat,
Longitude = long
-- Can be used to to put flat on leaning surfaces, but also leads to updating
-- the rotation every frame
--UseHeightmap = true
}
},
Renderable = {
Type = "RenderableModel",
Body = "NEW HORIZONS",
GeometryFile = models .. "/NewHorizonsCleanModel.obj"
},
GUI = {
Path = "/Example"
}
}
assetHelper.registerSceneGraphNodesAndExport(asset, { Example_GlobeRotation })

View File

@@ -16,8 +16,8 @@ local Example_Fixed_Height = {
Translation = {
Type = "GlobeTranslation",
Globe = earth.Earth.Identifier,
Longitude = -74.006,
Latitude = 40.7128,
Longitude = -74.006,
Altitude = 100000.0
}
},
@@ -38,8 +38,8 @@ local Example_Adaptive_Height = {
Translation = {
Type = "GlobeTranslation",
Globe = earth.Earth.Identifier,
Longitude = -74.006,
Latitude = 40.7128,
Longitude = -74.006,
UseHeightmap = true
}
},

View File

@@ -0,0 +1,75 @@
/*****************************************************************************************
* *
* OpenSpace *
* *
* Copyright (c) 2014-2021 *
* *
* Permission is hereby granted, free of charge, to any person obtaining a copy of this *
* software and associated documentation files (the "Software"), to deal in the Software *
* without restriction, including without limitation the rights to use, copy, modify, *
* merge, publish, distribute, sublicense, and/or sell copies of the Software, and to *
* permit persons to whom the Software is furnished to do so, subject to the following *
* conditions: *
* *
* The above copyright notice and this permission notice shall be included in all copies *
* or substantial portions of the Software. *
* *
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, *
* INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A *
* PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT *
* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF *
* CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE *
* OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. *
****************************************************************************************/
#include "fragment.glsl"
in vec2 vs_st;
in vec3 vs_normalViewSpace;
in vec4 vs_positionCameraSpace;
in float vs_screenSpaceDepth;
in mat3 TBN;
uniform float ambientIntensity = 0.2;
uniform float diffuseIntensity = 1.0;
uniform float specularIntensity = 1.0;
uniform bool performShading = true;
uniform bool use_forced_color = false;
uniform bool has_texture_diffuse;
uniform bool has_texture_normal;
uniform bool has_texture_specular;
uniform bool has_color_specular;
uniform bool opacityBlending = false;
uniform sampler2D texture_diffuse;
uniform sampler2D texture_normal;
uniform sampler2D texture_specular;
uniform vec3 color_diffuse;
uniform vec3 color_specular;
uniform int nLightSources;
uniform vec3 lightDirectionsViewSpace[8];
uniform float lightIntensities[8];
uniform float opacity = 1.0;
Fragment getFragment() {
Fragment frag;
if (has_texture_normal) {
vec3 normalAlbedo = texture(texture_normal, vs_st).rgb;
normalAlbedo = normalize(normalAlbedo * 2.0 - 1.0);
frag.color.rgb = normalize(TBN * normalAlbedo);
}
else {
frag.color.rgb = normalize(vs_normalViewSpace);
}
frag.color.a = 1.0;
frag.gPosition = vs_positionCameraSpace;
frag.gNormal = vec4(vs_normalViewSpace, 0.0);
frag.disableLDR2HDR = true;
return frag;
}

View File

@@ -0,0 +1,68 @@
/*****************************************************************************************
* *
* OpenSpace *
* *
* Copyright (c) 2014-2021 *
* *
* Permission is hereby granted, free of charge, to any person obtaining a copy of this *
* software and associated documentation files (the "Software"), to deal in the Software *
* without restriction, including without limitation the rights to use, copy, modify, *
* merge, publish, distribute, sublicense, and/or sell copies of the Software, and to *
* permit persons to whom the Software is furnished to do so, subject to the following *
* conditions: *
* *
* The above copyright notice and this permission notice shall be included in all copies *
* or substantial portions of the Software. *
* *
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, *
* INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A *
* PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT *
* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF *
* CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE *
* OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. *
****************************************************************************************/
#version __CONTEXT__
#include "PowerScaling/powerScaling_vs.hglsl"
layout(location = 0) in vec4 in_position;
layout(location = 1) in vec2 in_st;
layout(location = 2) in vec3 in_normal;
layout(location = 3) in vec3 in_tangent;
out vec2 vs_st;
out vec3 vs_normalViewSpace;
out float vs_screenSpaceDepth;
out vec4 vs_positionCameraSpace;
out mat3 TBN;
uniform mat4 modelViewTransform;
uniform mat4 projectionTransform;
uniform mat4 normalTransform;
uniform mat4 meshTransform;
uniform mat4 meshNormalTransform;
void main() {
vs_positionCameraSpace = modelViewTransform * (meshTransform * in_position);
vec4 positionClipSpace = projectionTransform * vs_positionCameraSpace;
vec4 positionScreenSpace = z_normalization(positionClipSpace);
gl_Position = positionScreenSpace;
vs_st = in_st;
vs_screenSpaceDepth = positionScreenSpace.w;
vs_normalViewSpace = normalize(mat3(normalTransform) * (mat3(meshNormalTransform) * in_normal));
// TBN matrix for normal mapping
vec3 T = normalize(mat3(normalTransform) * (mat3(meshNormalTransform) * in_tangent));
vec3 N = normalize(mat3(normalTransform) * (mat3(meshNormalTransform) * in_normal));
// Re-orthogonalize T with respect to N
T = normalize(T - dot(T, N) * N);
// Retrieve perpendicular vector B with cross product of T and N
vec3 B = normalize(cross(N, T));
TBN = mat3(T, B, N);
}

View File

@@ -0,0 +1,45 @@
local assetHelper = asset.require('util/asset_helper')
local sunTransforms = asset.require('scene/solarsystem/sun/transforms')
local transforms = asset.require('scene/solarsystem/planets/earth/transforms')
local model = asset.syncedResource({
Name = "Animated Box",
Type = "HttpSynchronization",
Identifier = "animated_box",
Version = 1
})
local model = {
Identifier = "modelshader",
Parent = transforms.EarthCenter.Identifier,
Transform = {
Translation = {
Type = "StaticTranslation",
Position = { 11E7, 0.0, 0.0 }
}
},
Renderable = {
Type = "RenderableModel",
GeometryFile = model .. "/BoxAnimated.glb",
ModelScale = 3E7,
LightSources = {
{
Type = "SceneGraphLightSource",
Identifier = "Sun",
Node = sunTransforms.SolarSystemBarycenter.Identifier,
Intensity = 1.0
}
},
PerformShading = true,
DisableFaceCulling = true,
VertexShader = asset.localResource("model_vs.glsl"),
FragmentShader = asset.localResource("model_fs.glsl"),
},
GUI = {
Name = "Model Shader",
Path = "/Example",
Description = "Simple box model with a custom shader",
}
}
assetHelper.registerSceneGraphNodesAndExport(asset, { model })

View File

@@ -28,9 +28,7 @@ local states = {
Exit = "openspace.setPropertyValueSingle('Scene.EarthLabel.Renderable.Enabled', false)"
},
{
Identifier = "Moon",
Enter = "",
Exit = ""
Identifier = "Moon"
}
}
@@ -48,7 +46,6 @@ local transitions = {
{
From = "Earth",
To = "Constellations",
-- action is optional
},
{
From = "Constellations",
@@ -67,7 +64,7 @@ local transitions = {
}
asset.onInitialize(function()
-- Setup
-- Setup (could be done in the profile)
openspace.setPropertyValueSingle('Scene.Constellations.Renderable.Enabled', true)
openspace.setPropertyValueSingle('Scene.Constellations.Renderable.Opacity', 0.0)

View File

@@ -78,7 +78,7 @@ local sunstar = {
}
},
GUI = {
Name = "Sun",
Name = "Sun Star",
Path = "/Milky Way/Stars",
Description = [[Individual star to represent the sun when outside of the solar
system]]

View File

@@ -78,6 +78,60 @@ local createConstellations = function (baseIdentifier, guiPath, constellationfil
end
local show_art = {
Identifier = "constellation_art.show_art",
Name = "Show Constellation Art",
Command = "openspace.setPropertyValue('Scene.ConstellationArt*.Renderable.Opacity', 0);" ..
"openspace.setPropertyValue('Scene.ConstellationArt*.Renderable.Enabled', true);" ..
"openspace.setPropertyValue('Scene.ConstellationArt*.Renderable.Opacity', 0.2, 2);",
Documentation = "Enables and fades up constellation art work",
GuiPath = "/Rendering",
IsLocal = false
}
asset.export("ShowArtAction", show_art)
local hide_art = {
Identifier = "constellation_art.hide_art",
Name = "Hide Constellation Art",
Command = "openspace.setPropertyValue('Scene.ConstellationArt*.Renderable.Opacity', 0, 2);",
Documentation = "Fades out constellation artwork",
GuiPath = "/Rendering",
IsLocal = false
}
asset.export("HideArtAction", hide_art)
local disable_art = {
Identifier = "constellation_art.disable_art",
Name = "Disable Constellation Art",
Command = "openspace.setPropertyValue('Scene.ConstellationArt*.Renderable.Enabled', false);",
Documentation = "Disable constellation artwork",
GuiPath = "/Rendering",
IsLocal = false
}
asset.export("DisableArtAction", disable_art)
local show_zodiac_art = {
Identifier = "constellation_art.show_zodiac_art",
Name = "Show Zodiac Art",
Command = "openspace.setPropertyValue('Scene.ConstellationArt*.Renderable.Opacity', 0);" ..
"openspace.setPropertyValue('{zodiac}.Renderable.Enabled',true);" ..
"openspace.setPropertyValue('{zodiac}.Renderable.Opacity', 1, 2);",
Documentation = "Enables and fades up zodiac art work",
GuiPath = "/Rendering",
IsLocal = false
}
asset.export("ShowZodiacArt", show_zodiac_art)
local hide_zodiac_art = {
Identifier = "constellation_art.hide_zodiac_art",
Name = "Hide Zodiac Art",
Command = "openspace.setPropertyValue('{zodiac}.Renderable.Opacity', 0, 2);",
Documentation = "fades down zodiac art work",
GuiPath = "/Rendering",
IsLocal = false
}
asset.export("HideZodiacArt", hide_zodiac_art)
local nodes = {}
asset.onInitialize(function ()
@@ -87,12 +141,20 @@ asset.onInitialize(function ()
for _, n in ipairs(nodes) do
openspace.addSceneGraphNode(n);
end
openspace.action.registerAction(show_art)
openspace.action.registerAction(hide_art)
openspace.action.registerAction(disable_art)
end)
asset.onDeinitialize(function ()
for _, n in ipairs(nodes) do
openspace.removeSceneGraphNode(n.Identifier);
end
openspace.action.removeAction(show_art.Identifier)
openspace.action.removeAction(hide_art.Identifier)
openspace.action.removeAction(disable_art.Identifier)
end)

View File

@@ -1,32 +1,13 @@
local scene_helper = asset.require('util/scene_helper')
local Keybindings = {
{
Key = "v",
Name = "Show Constellation Art",
Command = "openspace.setPropertyValue('Scene.ConstellationArt*.Renderable.Opacity', 0);" ..
"openspace.setPropertyValue('{zodiac}.Renderable.Enabled',true);" ..
"openspace.setPropertyValue('{zodiac}.Renderable.Opacity', 1, 2);",
Documentation = "Enables and fades up zodiac art work",
GuiPath = "/Rendering",
Local = false
},
{
Key = "Shift+v",
Name = "Show Constellation Art",
Command = "openspace.setPropertyValue('{zodiac}.Renderable.Opacity', 0, 2);",
Documentation = "fades down zodiac art work",
GuiPath = "/Rendering",
Local = false
},
}
local mainAsset = asset.require('./constellation_art')
asset.onInitialize(function ()
scene_helper.bindKeys(Keybindings)
openspace.bindKey("v", mainAsset.ShowZodiacArt.Identifier)
openspace.bindKey("Shift+v", mainAsset.HideZodiacArt.Identifier)
end)
asset.onDeinitialize(function ()
scene_helper.unbindKeys(Keybindings)
openspace.clearKey("v")
openspace.clearKey("Shift+v")
end)
asset.meta = {

View File

@@ -1,40 +1,15 @@
local scene_helper = asset.require('util/scene_helper')
local Keybindings = {
{
Key = "c",
Name = "Show Constellation Art",
Command = "openspace.setPropertyValue('Scene.ConstellationArt*.Renderable.Opacity', 0);" ..
"openspace.setPropertyValue('Scene.ConstellationArt*.Renderable.Enabled', true);" ..
"openspace.setPropertyValue('Scene.ConstellationArt*.Renderable.Opacity', 0.2, 2);",
Documentation = "Enables and fades up constellation art work",
GuiPath = "/Rendering",
Local = false
},
{
Key = "SHIFT+c",
Name = "Hide Constellation Art",
Command = "openspace.setPropertyValue('Scene.ConstellationArt*.Renderable.Opacity', 0, 2);",
Documentation = "Fades out constellation artwork",
GuiPath = "/Rendering",
Local = false
},
{
Key = "CTRL+c",
Name = "Disable Constellation Art",
Command = "openspace.setPropertyValue('Scene.ConstellationArt*.Renderable.Enabled', false);",
Documentation = "Disable constellation artwork",
GuiPath = "/Rendering",
Local = false
}
}
local mainAsset = asset.require('./constellation_art')
asset.onInitialize(function ()
scene_helper.bindKeys(Keybindings)
openspace.bindKey("c", mainAsset.ShowArtAction.Identifier)
openspace.bindKey("SHIFT+c", mainAsset.HideArtAction.Identifier)
openspace.bindKey("CTRL+c", mainAsset.DisableArtAction.Identifier)
end)
asset.onDeinitialize(function ()
scene_helper.unbindKeys(Keybindings)
openspace.clearKey("c")
openspace.clearKey("SHIFT+c")
openspace.clearKey("CTRL+c")
end)

View File

@@ -14,21 +14,42 @@ local vrts = asset.syncedResource({
Version = 1
})
asset.onInitialize(function ()
openspace.globebrowsing.addBlendingLayersFromDirectory(vrts, assetGlobe);
flipbook = helper.createFlipbook(assetPrefix, assetGlobe, 19);
rawset(_G, "nextFlip", function() helper.nextFlipbookPage(flipbook) end)
rawset(_G, "previousFlip", function() helper.previousFlipbookPage(flipbook) end)
openspace.action.registerAction({
Identifier = "lem_flipbook.next_flip",
Name = "Next A11 flip",
Command = "nextFlip()",
Documentation = "Show the next Apollo 11 flipbook image",
GuiPath = "/Missions/Apollo/11",
IsLocal = false
})
openspace.bindKey("p", "nextFlip()", "Show the next Apollo 11 flipbook image.", "Next A11 flip", "/Missions/Apollo/11")
openspace.bindKey("o", "previousFlip()","Show the previous Apollo 11 flipbook image.", "Prev A11 flip", "/Missions/Apollo/11")
rawset(_G, "previousFlip", function() helper.previousFlipbookPage(flipbook) end)
openspace.action.registerAction({
Identifier = "lem_flipbook.prev_flip",
Name = "Prev A11 flip",
Command = "previousFlip()",
Documentation = "Show the previous Apollo 11 flipbook image",
GuiPath = "/Missions/Apollo/11",
IsLocal = false
})
openspace.bindKey("p", "lem_flipbook.next_flip")
openspace.bindKey("o", "lem_flipbook.prev_flip")
end)
asset.onDeinitialize(function ()
flipbook = nil;
openspace.action.removeAction("lem_flipbook.next_flip")
openspace.action.removeAction("lem_flipbook.prev_flip")
openspace.clearKey("o")
openspace.clearKey("p")
end)

View File

@@ -50,6 +50,7 @@ local Apollo15 = {
Renderable = {
Type = "RenderableModel",
GeometryFile = models .. "/ApolloCSM.osmodel",
ModelScale = 0.0001,
LightSources = {
{
Type = "SceneGraphLightSource",

View File

@@ -38,11 +38,6 @@ local Apollo8LaunchModel = {
End = "1968 DEC 22"
},
Transform = {
Scale = {
Type = "StaticScale",
-- The scale of the model is in cm; OpenSpace is in m
Scale = 0.01
},
Rotation = {
Type = "StaticRotation",
Rotation = {0.0, 0.0, -3.1415 / 2}
@@ -51,6 +46,7 @@ local Apollo8LaunchModel = {
Renderable = {
Type = "RenderableModel",
GeometryFile = models .. "/ApolloCSM.osmodel",
ModelScale = 0.0001,
LightSources = {
{
Type = "SceneGraphLightSource",

View File

@@ -50,11 +50,6 @@ local Apollo8Model = {
End = "1968 DEC 28"
},
Transform = {
Scale = {
Type = "StaticScale",
-- The scale of the model is in cm; OpenSpace is in m
Scale = 0.01
},
Rotation = {
Type = "StaticRotation",
Rotation = {0.0, 0.0, -3.1415 / 2}
@@ -63,6 +58,7 @@ local Apollo8Model = {
Renderable = {
Type = "RenderableModel",
GeometryFile = models .. "/ApolloCSM.osmodel",
ModelScale = 0.0001,
LightSources = {
{
Type = "SceneGraphLightSource",

View File

@@ -85,20 +85,32 @@ for i = 1, #landingData do
}
end
asset.onInitialize(function ()
openspace.bindShortcut(
'Show Apollo Landing Labels',
'openspace.setPropertyValue("Scene.Apollo*Insignia.Renderable.Opacity", 1, 0.5)',
'Show patches of the Apollo missions on their respective landing sites',
'/Missions/Apollo'
)
local show_apollo_labels = {
Identifier = "apollo_insignias.show_insignias",
Name = "Show Apollo Landing Labels",
Command = "openspace.setPropertyValue('Scene.Apollo*Insignia.Renderable.Opacity', 1, 0.5)",
Documentation = "Show patches of the Apollo missions on their respective landing sites",
GuiPath = "/Missions/Apollo",
IsLocal = true
}
openspace.bindShortcut(
'Hide Apollo Landing Labels',
'openspace.setPropertyValue("Scene.Apollo*Insignia.Renderable.Opacity", 0, 0.5)',
'Hide patches of the Apollo missions on their respective landing sites',
'/Missions/Apollo'
)
local hide_apollo_labels = {
Identifier = "apollo_insignias.hide_insignias",
Name = "Hide Apollo Landing Labels",
Command = "openspace.setPropertyValue('Scene.Apollo*Insignia.Renderable.Opacity', 0, 0.5)",
Documentation = "Hide patches of the Apollo missions on their respective landing sites",
GuiPath = "/Missions/Apollo",
IsLocal = true
}
asset.onInitialize(function ()
openspace.action.registerAction(show_apollo_labels)
openspace.action.registerAction(hide_apollo_labels)
end)
asset.onDeinitialize(function ()
openspace.action.removeAction(show_apollo_labels.Identifier)
openspace.action.removeAction(hide_apollo_labels.Identifier)
end)
asset.export('showInsignia', function (missinNumber, interpolationDuration)

View File

@@ -1,8 +1,17 @@
<GDAL_WMS>
<Service name="TiledWMS">
<ServerUrl>http://198.102.45.23/arcgis/rest/services/worldelevation3d/terrain3d?</ServerUrl>
<TiledGroupName>GCS_Elevation</TiledGroupName>
<Service name="TMS">
<ServerUrl>http://earthlive.maptiles.arcgis.com/arcgis/rest/services/GCS_Elevation3D/ImageServer/tile/${z}/${y}/${x}</ServerUrl>
</Service>
<Timeout>2</Timeout>
<DataWindow>
<UpperLeftX>-180</UpperLeftX> <UpperLeftY>90</UpperLeftY>
<LowerRightX>180</LowerRightX> <LowerRightY>-90</LowerRightY>
<SizeX>16777216</SizeX> <SizeY>8388608</SizeY>
<TileLevel>14</TileLevel> <YOrigin>top</YOrigin>
</DataWindow>
<Projection>EPSG:4326</Projection>
<BlockSizeX>512</BlockSizeX> <BlockSizeY>512</BlockSizeY>
<BandsCount>1</BandsCount> <DataType>Float32</DataType>
<DataValues NoData="0" Min="-11000" Max="8500"/>
<MaxConnections>5</MaxConnections>
<ZeroBlockHttpCodes>404,400</ZeroBlockHttpCodes>
</GDAL_WMS>

View File

@@ -1,155 +1,202 @@
local sceneHelper = asset.require('./scene_helper')
local propertyHelper = asset.require('./property_helper')
local Keybindings = {
{
Key = "F1",
Name = "Show Native GUI",
Command = propertyHelper.invert('Modules.ImGUI.Main.Enabled'),
Documentation = "Shows or hides the native UI",
GuiPath = "/Native GUI",
Local = true
},
{
Key = "ESC",
Name = "Toggle Shutdown",
Command = "openspace.toggleShutdown()",
Documentation = "Toggles the shutdown that will stop OpenSpace after a grace period. Press again to cancel the shutdown during this period.",
Local = true
},
{
Key = "PRINT_SCREEN",
Name = "Take Screenshot",
Command = "openspace.takeScreenshot()",
Documentation = "Saves the contents of the screen to a file in the ${SCREENSHOTS} directory.",
GuiPath = "/Rendering",
Local = true
},
{
Key = "F12",
Name = "Take Screenshot",
Command = "openspace.takeScreenshot()",
Documentation = "Saves the contents of the screen to a file in the ${SCREENSHOTS} directory.",
GuiPath = "/Rendering",
Local = true
},
{
Key = "SPACE",
Name = "Toggle Pause (Interpolated)",
Command = "openspace.time.pauseToggleViaKeyboard()",
Documentation = "Smoothly starts and stops the simulation time.",
GuiPath = "/Simulation Speed",
Local = true
},
{
Key = "Shift+SPACE",
Name = "Toggle Pause (Immediate)",
Command = "openspace.time.togglePause()",
Documentation = "Immediately starts and stops the simulation time.",
GuiPath = "/Simulation Speed",
Local = true
},
{
Key = "f",
Name = "Toggle Rotation friction",
Command = propertyHelper.invert('NavigationHandler.OrbitalNavigator.Friction.RotationalFriction'),
Documentation = "Toggles the rotational friction of the camera. If it is disabled, the camera rotates around the focus object indefinitely.",
GuiPath = "/Navigation",
Local = false
},
{
Key = "Shift+f",
Name = "Toggle Zoom Friction",
Command = propertyHelper.invert('NavigationHandler.OrbitalNavigator.Friction.ZoomFriction'),
Documentation = "Toggles the zoom friction of the camera. If it is disabled, the camera rises up from or closes in towards the focus object indefinitely.",
GuiPath = "/Navigation",
Local = false
},
{
Key = "Ctrl+f",
Name = "Toggle Roll Friction",
Command = propertyHelper.invert('NavigationHandler.OrbitalNavigator.Friction.RollFriction'),
Documentation = "Toggles the roll friction of the camera. If it is disabled, the camera rolls around its own axis indefinitely.",
GuiPath = "/Navigation",
Local = false
},
{
Key = "w",
Name = "Fade to/from black",
Command = "if openspace.getPropertyValue('RenderEngine.BlackoutFactor') > 0.5 then openspace.setPropertyValueSingle('RenderEngine.BlackoutFactor', 0.0, 3) else openspace.setPropertyValueSingle('RenderEngine.BlackoutFactor', 1.0, 3) end",
Documentation = "Toggles the fade to black within 3 seconds or shows the rendering after 3 seconds.",
GuiPath = "/Rendering",
Local = false
},
{
Key = "Tab",
Name = "Toggle main GUI",
Command = propertyHelper.invert('Modules.CefWebGui.Visible'),
Documentation = "Toggles the main GUI",
GuiPath = "/GUI",
Local = true
},
{
Key = "Shift+Tab",
Name = "Toggle dashboard and overlays",
Command =
local toggle_native_ui = {
Identifier = "os_default.toggle_native_ui",
Name = "Show Native GUI",
Command = propertyHelper.invert('Modules.ImGUI.Main.Enabled'),
Documentation = "Shows or hides the native UI",
GuiPath = "/Native GUI",
IsLocal = true,
Key = "F1"
}
local toggle_shutdown = {
Identifier = "os_default.toggle_shutdown",
Name = "Toggle Shutdown",
Command = "openspace.toggleShutdown()",
Documentation = "Toggles the shutdown that will stop OpenSpace after a grace period. Press again to cancel the shutdown during this period.",
IsLocal = true,
Key = "ESC"
}
local take_screenshot = {
Identifier = "os_default.take_screenshot",
Name = "Take Screenshot",
Command = "openspace.takeScreenshot()",
Documentation = "Saves the contents of the screen to a file in the ${SCREENSHOTS} directory.",
GuiPath = "/Rendering",
IsLocal = true,
Key = "F12"
}
local toggle_pause_interpolated = {
Identifier = "os_default.toggle_pause_interpolated",
Name = "Toggle Pause (Interpolated)",
Command = "openspace.time.pauseToggleViaKeyboard()",
Documentation = "Smoothly starts and stops the simulation time.",
GuiPath = "/Simulation Speed",
IsLocal = true,
Key = "SPACE"
}
local toggle_pause_immediate = {
Identifier = "os_default.toggle_pause_immediate",
Name = "Toggle Pause (Immediate)",
Command = "openspace.time.togglePause()",
Documentation = "Immediately starts and stops the simulation time.",
GuiPath = "/Simulation Speed",
IsLocal = true,
Key = "Shift+SPACE"
}
local toggle_rotation_friction = {
Identifier = "os_default.toggle_rotation_friction",
Name = "Toggle Rotation friction",
Command = propertyHelper.invert('NavigationHandler.OrbitalNavigator.Friction.RotationalFriction'),
Documentation = "Toggles the rotational friction of the camera. If it is disabled, the camera rotates around the focus object indefinitely.",
GuiPath = "/Navigation",
IsLocal = false,
Key = "f"
}
local toggle_zoom_friction = {
Identifier = "os_default.toggle_zoom_friction",
Name = "Toggle Zoom Friction",
Command = propertyHelper.invert('NavigationHandler.OrbitalNavigator.Friction.ZoomFriction'),
Documentation = "Toggles the zoom friction of the camera. If it is disabled, the camera rises up from or closes in towards the focus object indefinitely.",
GuiPath = "/Navigation",
IsLocal = false,
Key = "Shift+f"
}
local toggle_roll_friction = {
Identifier = "os_default.toggle_roll_friction",
Name = "Toggle Roll Friction",
Command = propertyHelper.invert('NavigationHandler.OrbitalNavigator.Friction.RollFriction'),
Documentation = "Toggles the roll friction of the camera. If it is disabled, the camera rolls around its own axis indefinitely.",
GuiPath = "/Navigation",
IsLocal = false,
Key = "Ctrl+f"
}
local fade_to_black = {
Identifier = "os_default.fade_to_black",
Name = "Fade to/from black",
Command = "if openspace.getPropertyValue('RenderEngine.BlackoutFactor') > 0.5 then openspace.setPropertyValueSingle('RenderEngine.BlackoutFactor', 0.0, 3) else openspace.setPropertyValueSingle('RenderEngine.BlackoutFactor', 1.0, 3) end",
Documentation = "Toggles the fade to black within 3 seconds or shows the rendering after 3 seconds.",
GuiPath = "/Rendering",
IsLocal = false,
Key = "w"
}
local toggle_main_gui = {
Identifier = "os_default.toggle_main_gui",
Name = "Toggle main GUI",
Command = propertyHelper.invert('Modules.CefWebGui.Visible'),
Documentation = "Toggles the main GUI",
GuiPath = "/GUI",
IsLocal = true,
Key = "Tab"
}
local toggle_overlays = {
Identifier = "os_default.toggle_overlays",
Name = "Toggle dashboard and overlays",
Command =
[[local isEnabled = openspace.getPropertyValue('Dashboard.IsEnabled');
openspace.setPropertyValueSingle('Dashboard.IsEnabled', not isEnabled);
openspace.setPropertyValueSingle("RenderEngine.ShowLog", not isEnabled);
openspace.setPropertyValueSingle("RenderEngine.ShowVersion", not isEnabled);
openspace.setPropertyValueSingle("RenderEngine.ShowCamera", not isEnabled)]],
Documentation = "Toggles the dashboard and overlays",
GuiPath = "/GUI",
Local = true
},
{
Key = "Alt+R",
Name = "Toggle rendering on master",
Command = propertyHelper.invert('RenderEngine.DisableMasterRendering'),
Documentation = "Toggles the rendering on master",
GuiPath = "/Rendering",
Local = true
},
{
Key = "Right",
Name = "Next Delta Time Step (Interpolate)",
Command = "openspace.time.interpolateNextDeltaTimeStep()",
Documentation = "Smoothly interpolates the simulation speed to the next delta time step, if one exists.",
GuiPath = "/Simulation Speed",
Local = true
},
{
Key = "Shift+Right",
Name = "Next Delta Time Step (Immediate)",
Command = "openspace.time.setNextDeltaTimeStep()",
Documentation = "Immediately set the simulation speed to the next delta time step, if one exists.",
GuiPath = "/Simulation Speed",
Local = true
},
{
Key = "Left",
Name = "Previous Delta Time Step (Interpolate)",
Command = "openspace.time.interpolatePreviousDeltaTimeStep()",
Documentation = "Smoothly interpolates the simulation speed to the previous delta time step, if one exists.",
GuiPath = "/Simulation Speed",
Local = true
},
{
Key = "Shift+Left",
Name = "Previous Delta Time Step (Immediate)",
Command = "openspace.time.setPreviousDeltaTimeStep()",
Documentation = "Immediately set the simulation speed to the previous delta time step, if one exists.",
GuiPath = "/Simulation Speed",
Local = true
}
Documentation = "Toggles the dashboard and overlays",
GuiPath = "/GUI",
IsLocal = true,
Key = "Shift+Tab"
}
local toggle_master_rendering = {
Identifier = "os_default.toggle_master_rendering",
Name = "Toggle rendering on master",
Command = propertyHelper.invert('RenderEngine.DisableMasterRendering'),
Documentation = "Toggles the rendering on master",
GuiPath = "/Rendering",
IsLocal = true,
Key = "Alt+R"
}
local next_delta_step_interpolate = {
Identifier = "os_default.next_delta_step_interpolate",
Name = "Next Delta Time Step (Interpolate)",
Command = "openspace.time.interpolateNextDeltaTimeStep()",
Documentation = "Smoothly interpolates the simulation speed to the next delta time step, if one exists.",
GuiPath = "/Simulation Speed",
IsLocal = true,
Key = "Right"
}
local next_delta_step_immediate = {
Identifier = "os_default.next_delta_step_immediate",
Name = "Next Delta Time Step (Immediate)",
Command = "openspace.time.setNextDeltaTimeStep()",
Documentation = "Immediately set the simulation speed to the next delta time step, if one exists.",
GuiPath = "/Simulation Speed",
IsLocal = true,
Key = "Shift+Right"
}
local previous_delta_step_interpolate = {
Identifier = "os_default.previous_delta_step_interpolate",
Name = "Previous Delta Time Step (Interpolate)",
Command = "openspace.time.interpolatePreviousDeltaTimeStep()",
Documentation = "Smoothly interpolates the simulation speed to the previous delta time step, if one exists.",
GuiPath = "/Simulation Speed",
IsLocal = true,
Key = "Left"
}
local previous_delta_step_immediate = {
Identifier = "os_default.previous_delta_step_immediate",
Name = "Previous Delta Time Step (Immediate)",
Command = "openspace.time.setPreviousDeltaTimeStep()",
Documentation = "Immediately set the simulation speed to the previous delta time step, if one exists.",
GuiPath = "/Simulation Speed",
IsLocal = true,
Key = "Shift+Left"
}
local Actions = {
toggle_native_ui,toggle_shutdown,take_screenshot,toggle_pause_interpolated,toggle_pause_immediate,
toggle_rotation_friction,toggle_zoom_friction,toggle_roll_friction,fade_to_black,
toggle_main_gui,toggle_overlays,toggle_master_rendering,next_delta_step_interpolate,
next_delta_step_immediate,previous_delta_step_interpolate,previous_delta_step_immediate
}
asset.onInitialize(function()
sceneHelper.bindKeys(Keybindings)
for _, action in ipairs(Actions) do
openspace.action.registerAction(action)
openspace.bindKey(action.Key, action.Identifier)
end
end)
asset.onDeinitialize(function ()
sceneHelper.unbindKeys(Keybindings)
for _, action in ipairs(Actions) do
openspace.action.removeAction(action.Identifier)
openspace.clearKey(action.Key)
end
end)
asset.export("DefaultKeybindings", Keybindings)

View File

@@ -1,108 +0,0 @@
local bindKeys = function(t, ignoreWarning)
ignoreWarning = ignoreWarning or false
for _, k in ipairs(t) do
assert(k.Key, 'No key provided')
assert(k.Command, 'No command provided for key ' .. k.Key)
k.Name = k.Name or k.Key
k.GuiPath = k.GuiPath or ''
local currentKey = openspace.getKeyBinding(k.Key)
if (next(currentKey) ~= nil) and (not ignoreWarning) then
openspace.printWarning('New keybind for "' .. k.Key .. '" is added, but a previous keybind already existed. If you want to silence this warning, pass "true", to this call to bindKeys')
end
if k.Local then
openspace.bindKeyLocal(k.Key, k.Command, k.Documentation, k.Name, k.GuiPath)
else
openspace.bindKey(k.Key, k.Command, k.Documentation, k.Name, k.GuiPath)
end
end
end
asset.export("bindKeys", bindKeys)
local unbindKeys = function(keys)
-- We check against k and k.Key to provide compatability
-- for both calls with the same table that goes to bindKeys
-- as well as the return values from setDeltaTimeKeys
for _, k in ipairs(keys) do
openspace.clearKey(k.Key or k)
end
end
asset.export("unbindKeys", unbindKeys)
--shortcut function
local function has_value (tab, val)
for index, value in ipairs(tab) do
-- We grab the first index of our sub-table instead
if value[1] == val then
return true
end
end
return false
end
local extractShortcuts = function(names, shortcuts)
local foundShortcuts = {};
if type(names) ~= "table" then
openspace.printWarning("scene_helper.extractShortcuts invalid paramater names (not Table)")
end
if type(shortcuts) ~= "table" then
openspace.printWarning("scene_helper.extractShortcuts invalid paramater shortcuts (not Table)")
end
for _, shortcut in ipairs(shortcuts) do
for _, name in ipairs(names ) do
if (shortcut.Name == name) then
foundShortcuts[#foundShortcuts+1] = shortcut
end
end
end
return foundShortcuts
end
asset.export("extractShortcuts", extractShortcuts)
local createKeyBindFromShortcuts = function(key, shortcuts, guipath, title, documentation)
if type(key) ~= "string" then
openspace.printWarning("scene_helper.createKeyBindFromShortcuts invalid paramater key (not String)")
end
if type(shortcuts) ~= "table" or #shortcuts == 0 then
openspace.printWarning("scene_helper.createKeyBindFromShortcuts invalid paramater shortcuts (not Table or empty)")
end
-- if type(guipath) ~= "string" then
-- guipath = shortcuts[0].GuiPath
-- end
local concatTitle = type(title) ~= "string"
local concatDocumentation = type(documentation) ~= "string"
local keybind = {
Key = key,
Command = "",
Name = name or "",
Documentation = documentation or "",
GuiPath = guipath or "",
Local = false
}
for _, shortcut in ipairs(shortcuts) do
keybind.Command = keybind.Command .. shortcut.Command
if concatTitle then
keybind.Name = keybind.Name .. "/" .. shortcut.Name
end
if concatDocumentation then
keybind.Documentation = keybind.Documentation .. "," .. shortcut.Documentation
end
keybind.Local = keybind.Local and shortcut.Local
end
return keybind
end
asset.export("createKeyBindFromShortcuts", createKeyBindFromShortcuts)

View File

@@ -1,23 +1,22 @@
--testing_keybindings.asset
local sceneHelper = asset.require('./scene_helper')
local propertyHelper = asset.require('./property_helper')
local Keybindings = {
{
Key = "F7",
Name = "Take Screenshot",
Command = "openspace.takeScreenshot()",
Documentation = "Saves the contents of the screen to a file in the ${SCREENSHOTS} directory.",
GuiPath = "/Rendering",
Local = true
}
local take_screenshot = {
Identifier = "testing_keyboard.take_screenshot",
Name = "Take Screenshot",
Command = "openspace.takeScreenshot()",
Documentation = "Saves the contents of the screen to a file in the ${SCREENSHOTS} directory.",
GuiPath = "/Rendering",
IsLocal = true
}
asset.onInitialize(function()
Keys = sceneHelper.bindKeys(Keybindings)
openspace.action.registerAction(take_screenshot)
openspace.bindKey("F7", take_screenshot.Identifier)
end)
asset.onDeinitialize(function ()
sceneHelper.unbindKeys(Keybindings)
openspace.action.removeAction(take_screenshot.Identifier)
openspace.clearKey("F7")
end)

View File

@@ -3,7 +3,7 @@ asset.require('./static_server')
local guiCustomization = asset.require('customization/gui')
-- Select which commit hashes to use for the frontend and backend
local frontendHash = "829260614bb95e236d23cb500f6ec0fb2e3bdf51"
local frontendHash = "b777c48280801e3b54cf77c1231f949fe6e69ace"
local dataProvider = "data.openspaceproject.com/files/webgui"
local frontend = asset.syncedResource({

View File

@@ -1,4 +1,78 @@
{
"actions": [
{
"documentation": "Jump to right before the earthrise photo",
"gui_path": "/Missions/Apollo/8",
"identifier": "profile.setup.earthrise",
"is_local": false,
"name": "Set Earthrise time",
"script": "openspace.time.setPause(true); openspace.time.setDeltaTime(1); openspace.time.setTime('1968 DEC 24 16:37:31'); openspace.navigation.setNavigationState({Anchor = 'Apollo8', Position = { 1.494592E1, 3.236777E1, -4.171296E1 }, ReferenceFrame = 'Root', Up = { 0.960608E0, -0.212013E0, 0.179675E0 }}); openspace.setPropertyValue('*Trail.Renderable.Enabled', false);"
},
{
"documentation": "Jump to time right before Apollo 8 liftoff, with its trail enabled",
"gui_path": "/Missions/Apollo/8",
"identifier": "profile.setup.apollo8",
"is_local": false,
"name": "Set Apollo 8 launch time",
"script": "openspace.time.setTime('1968-12-21T12:51:37.00'); openspace.setPropertyValueSingle('Scene.Apollo8LaunchTrail.Renderable.Enabled', true);"
},
{
"documentation": "Toggles Moon Kaguya color layer",
"gui_path": "/Missions/Apollo",
"identifier": "profile.moon.kaguyalayer",
"is_local": false,
"name": "Toggle Kaguya layer",
"script": "openspace.setPropertyValueSingle('Scene.Moon.Renderable.Layers.ColorLayers.Kaguya_Utah.Enabled', not openspace.getPropertyValue('Scene.Moon.Renderable.Layers.ColorLayers.Kaguya_Utah.Enabled'));"
},
{
"documentation": "Toggles shading for the Moon",
"gui_path": "/Missions/Apollo",
"identifier": "profile.moon.shading",
"is_local": false,
"name": "Toggle Moon shading",
"script": "openspace.setPropertyValueSingle('Scene.Moon.Renderable.PerformShading', not openspace.getPropertyValue('Scene.Moon.Renderable.PerformShading'));"
},
{
"documentation": "Set camera focus to the Earth",
"gui_path": "/Missions/Apollo",
"identifier": "profile.focus.earth",
"is_local": false,
"name": "Focus on Earth",
"script": "openspace.setPropertyValueSingle('NavigationHandler.OrbitalNavigator.Aim', ''); openspace.setPropertyValueSingle('NavigationHandler.OrbitalNavigator.Anchor', 'Earth'); openspace.setPropertyValueSingle('NavigationHandler.OrbitalNavigator.RetargetAnchor', nil);"
},
{
"documentation": "Set camera focus to the Moon",
"gui_path": "/Missions/Apollo",
"identifier": "profile.focus.moon",
"is_local": false,
"name": "Focus on Moon",
"script": "openspace.setPropertyValueSingle('NavigationHandler.OrbitalNavigator.Aim', ''); openspace.setPropertyValueSingle('NavigationHandler.OrbitalNavigator.Anchor', 'Moon'); openspace.setPropertyValueSingle('NavigationHandler.OrbitalNavigator.RetargetAnchor', nil);"
},
{
"documentation": "Disable apollo site on moon when leaving",
"gui_path": "/Missions/Apollo",
"identifier": "profile.moon.disableapollosites",
"is_local": false,
"name": "Disable Apollo sites",
"script": "openspace.setPropertyValue('Scene.Moon.Renderable.Layers.ColorLayers.A17_*.Enabled', false); openspace.setPropertyValueSingle('Scene.Moon.Renderable.Layers.HeightLayers.LRO_NAC_Apollo_11.Enabled', false); openspace.setPropertyValueSingle('Scene.Moon.Renderable.Layers.ColorLayers.A11_M177481212_p_longlat.Enabled', false); openspace.setPropertyValueSingle('Scene.Apollo11MoonTrail.Renderable.Enabled', false); openspace.setPropertyValueSingle('Scene.Apollo11LemTrail.Renderable.Enabled', false); openspace.setPropertyValueSingle('Scene.Moon.Renderable.Layers.HeightLayers.LRO_NAC_Apollo_17.Enabled', false);"
},
{
"documentation": "Setup for Apollo 11 landing site",
"gui_path": "/Missions/Apollo/11",
"identifier": "profile.setup.apollo11",
"is_local": false,
"name": "Setup A11 site",
"script": "openspace.time.setTime('1969 JUL 20 20:17:40'); openspace.setPropertyValueSingle('Scene.Moon.Renderable.Layers.HeightLayers.LRO_NAC_Apollo_11.Enabled', true); openspace.setPropertyValueSingle('Scene.Moon.Renderable.Layers.ColorLayers.A11_M177481212_p_longlat.Enabled', true); openspace.setPropertyValueSingle('Scene.Moon.Renderable.TargetLodScaleFactor', 20.11); openspace.setPropertyValue('NavigationHandler.OrbitalNavigator.Anchor', 'Apollo11LemPosition'); openspace.setPropertyValue('NavigationHandler.OrbitalNavigator.RetargetAnchor', nil); openspace.setPropertyValueSingle('Scene.Apollo11MoonTrail.Renderable.Enabled', true); openspace.setPropertyValueSingle('Scene.Apollo11LemTrail.Renderable.Enabled', true);"
},
{
"documentation": "Setup for Apollo 17 landing site",
"gui_path": "/Missions/Apollo/17",
"identifier": "profile.setup.apollo17",
"is_local": false,
"name": "Setup A17 site",
"script": "openspace.time.setTime('1972 DEC 12 19:47:11'); openspace.setPropertyValueSingle('Scene.Moon.Renderable.Layers.ColorLayers.A17_travmap.BlendMode', 0.000000); openspace.setPropertyValueSingle('Scene.Moon.Renderable.Layers.ColorLayers.A17_travmap.Enabled', true); openspace.setPropertyValueSingle('Scene.Moon.Renderable.Layers.HeightLayers.LRO_NAC_Apollo_17.Enabled', true); openspace.setPropertyValueSingle('Scene.Moon.Renderable.Layers.ColorLayers.A17_LEM.Enabled', true); openspace.setPropertyValueSingle('Scene.Moon.Renderable.Layers.ColorLayers.A17_LEM.BlendMode', 0.000000); openspace.setPropertyValueSingle('Scene.Moon.Renderable.Layers.ColorLayers.A17_NAC_Alt_p.Enabled', true); openspace.setPropertyValueSingle('Scene.Moon.Renderable.Layers.ColorLayers.A17_NAC_Alt_p.BlendMode', 0.000000); openspace.setPropertyValueSingle('Scene.Moon.Renderable.TargetLodScaleFactor', 20.17); openspace.setPropertyValue('NavigationHandler.OrbitalNavigator.Anchor', 'Apollo17LemModel'); openspace.setPropertyValue('NavigationHandler.OrbitalNavigator.RetargetAnchor', nil); openspace.setPropertyValueSingle('Scene.Moon.Renderable.Layers.ColorLayers.A17_station7.BlendMode', 0.000000);"
}
],
"assets": [
"base",
"scene/solarsystem/missions/apollo/11/apollo11",
@@ -39,76 +113,40 @@
],
"keybindings": [
{
"documentation": "Jump to right before the earthrise photo",
"gui_path": "/Missions/Apollo/8",
"is_local": false,
"key": "E",
"name": "Set Earthrise time",
"script": "openspace.time.setPause(true); openspace.time.setDeltaTime(1); openspace.time.setTime('1968 DEC 24 16:37:31'); openspace.navigation.setNavigationState({Anchor = 'Apollo8', Position = { 1.494592E1, 3.236777E1, -4.171296E1 }, ReferenceFrame = 'Root', Up = { 0.960608E0, -0.212013E0, 0.179675E0 }}); openspace.setPropertyValue('*Trail.Renderable.Enabled', false);"
"action": "profile.setup.earthrise",
"key": "E"
},
{
"documentation": "Jump to time right before Apollo 8 liftoff, with its trail enabled",
"gui_path": "/Missions/Apollo/8",
"is_local": false,
"key": "U",
"name": "Set Apollo 8 launch time",
"script": "openspace.time.setTime('1968-12-21T12:51:37.00'); openspace.setPropertyValueSingle('Scene.Apollo8LaunchTrail.Renderable.Enabled', true);"
"action": "profile.setup.apollo8",
"key": "U"
},
{
"documentation": "Toggles Moon Kaguya color layer",
"gui_path": "/Missions/Apollo",
"is_local": false,
"key": "K",
"name": "Toggle Kaguya layer",
"script": "openspace.setPropertyValueSingle('Scene.Moon.Renderable.Layers.ColorLayers.Kaguya_Utah.Enabled', not openspace.getPropertyValue('Scene.Moon.Renderable.Layers.ColorLayers.Kaguya_Utah.Enabled'));"
"action": "profile.moon.kaguyalayer",
"key": "K"
},
{
"documentation": "Toggles shading for the Moon",
"gui_path": "/Missions/Apollo",
"is_local": false,
"key": "S",
"name": "Toggle Moon shading",
"script": "openspace.setPropertyValueSingle('Scene.Moon.Renderable.PerformShading', not openspace.getPropertyValue('Scene.Moon.Renderable.PerformShading'));"
"action": "profile.moon.shading",
"key": "S"
},
{
"documentation": "Set camera focus to the Earth",
"gui_path": "/Missions/Apollo",
"is_local": false,
"key": "HOME",
"name": "Focus on Earth",
"script": "openspace.setPropertyValueSingle('NavigationHandler.OrbitalNavigator.Aim', ''); openspace.setPropertyValueSingle('NavigationHandler.OrbitalNavigator.Anchor', 'Earth'); openspace.setPropertyValueSingle('NavigationHandler.OrbitalNavigator.RetargetAnchor', nil);"
"action": "profile.focus.earth",
"key": "Home"
},
{
"documentation": "Set camera focus to the Moon",
"gui_path": "/Missions/Apollo",
"is_local": false,
"key": "M",
"name": "Focus on Moon",
"script": "openspace.setPropertyValueSingle('NavigationHandler.OrbitalNavigator.Aim', ''); openspace.setPropertyValueSingle('NavigationHandler.OrbitalNavigator.Anchor', 'Moon'); openspace.setPropertyValueSingle('NavigationHandler.OrbitalNavigator.RetargetAnchor', nil);"
"action": "profile.focus.moon",
"key": "M"
},
{
"documentation": "Disable apollo site on moon when leaving",
"gui_path": "/Missions/Apollo",
"is_local": false,
"key": "F9",
"name": "Disable Apollo sites",
"script": "openspace.setPropertyValue('Scene.Moon.Renderable.Layers.ColorLayers.A17_*.Enabled', false); openspace.setPropertyValueSingle('Scene.Moon.Renderable.Layers.HeightLayers.LRO_NAC_Apollo_11.Enabled', false); openspace.setPropertyValueSingle('Scene.Moon.Renderable.Layers.ColorLayers.A11_M177481212_p_longlat.Enabled', false); openspace.setPropertyValueSingle('Scene.Apollo11MoonTrail.Renderable.Enabled', false); openspace.setPropertyValueSingle('Scene.Apollo11LemTrail.Renderable.Enabled', false); openspace.setPropertyValueSingle('Scene.Moon.Renderable.Layers.HeightLayers.LRO_NAC_Apollo_17.Enabled', false);"
"action": "profile.moon.disableapollosites",
"key": "F9"
},
{
"documentation": "Setup for Apollo 11 landing site",
"gui_path": "/Missions/Apollo/11",
"is_local": false,
"key": "F11",
"name": "Setup A11 site",
"script": "openspace.time.setTime('1969 JUL 20 20:17:40'); openspace.setPropertyValueSingle('Scene.Moon.Renderable.Layers.HeightLayers.LRO_NAC_Apollo_11.Enabled', true); openspace.setPropertyValueSingle('Scene.Moon.Renderable.Layers.ColorLayers.A11_M177481212_p_longlat.Enabled', true); openspace.setPropertyValueSingle('Scene.Moon.Renderable.TargetLodScaleFactor', 20.11); openspace.setPropertyValue('NavigationHandler.OrbitalNavigator.Anchor', 'Apollo11LemPosition'); openspace.setPropertyValue('NavigationHandler.OrbitalNavigator.RetargetAnchor', nil); openspace.setPropertyValueSingle('Scene.Apollo11MoonTrail.Renderable.Enabled', true); openspace.setPropertyValueSingle('Scene.Apollo11LemTrail.Renderable.Enabled', true);"
"action": "profile.setup.apollo11",
"key": "F11"
},
{
"documentation": "Setup for Apollo 17 landing site",
"gui_path": "/Missions/Apollo/17",
"is_local": false,
"key": "F7",
"name": "Setup A17 site",
"script": "openspace.time.setTime('1972 DEC 12 19:47:11'); openspace.setPropertyValueSingle('Scene.Moon.Renderable.Layers.ColorLayers.A17_travmap.BlendMode', 0.000000); openspace.setPropertyValueSingle('Scene.Moon.Renderable.Layers.ColorLayers.A17_travmap.Enabled', true); openspace.setPropertyValueSingle('Scene.Moon.Renderable.Layers.HeightLayers.LRO_NAC_Apollo_17.Enabled', true); openspace.setPropertyValueSingle('Scene.Moon.Renderable.Layers.ColorLayers.A17_LEM.Enabled', true); openspace.setPropertyValueSingle('Scene.Moon.Renderable.Layers.ColorLayers.A17_LEM.BlendMode', 0.000000); openspace.setPropertyValueSingle('Scene.Moon.Renderable.Layers.ColorLayers.A17_NAC_Alt_p.Enabled', true); openspace.setPropertyValueSingle('Scene.Moon.Renderable.Layers.ColorLayers.A17_NAC_Alt_p.BlendMode', 0.000000); openspace.setPropertyValueSingle('Scene.Moon.Renderable.TargetLodScaleFactor', 20.17); openspace.setPropertyValue('NavigationHandler.OrbitalNavigator.Anchor', 'Apollo17LemModel'); openspace.setPropertyValue('NavigationHandler.OrbitalNavigator.RetargetAnchor', nil); openspace.setPropertyValueSingle('Scene.Moon.Renderable.Layers.ColorLayers.A17_station7.BlendMode', 0.000000);"
"action": "profile.setup.apollo17",
"key": "F7"
}
],
"mark_nodes": [
@@ -145,6 +183,6 @@
},
"version": {
"major": 1,
"minor": 0
"minor": 1
}
}

View File

@@ -1,4 +1,30 @@
{
"actions": [
{
"documentation": "Toggle trails on or off for satellites around Earth",
"gui_path": "/Earth",
"identifier": "profile.toggle.satellite",
"is_local": false,
"name": "Toggle satellite trails",
"script": "local list = openspace.getProperty('{earth_satellites}.Renderable.Enabled'); for _,v in pairs(list) do openspace.setPropertyValueSingle(v, not openspace.getPropertyValue(v)) end"
},
{
"documentation": "Refocuses the camera on the ISS",
"gui_path": "/Earth",
"identifier": "profile.focus.iss",
"is_local": false,
"name": "Focus ISS",
"script": "openspace.setPropertyValueSingle('NavigationHandler.OrbitalNavigator.Aim', '');openspace.setPropertyValueSingle('NavigationHandler.OrbitalNavigator.Anchor', 'ISS');openspace.setPropertyValueSingle('NavigationHandler.OrbitalNavigator.RetargetAnchor', nil);"
},
{
"documentation": "Retargets the camera on Earth",
"gui_path": "/Earth",
"identifier": "profile.focus.earth",
"is_local": false,
"name": "Focus on Earth",
"script": "openspace.setPropertyValueSingle('NavigationHandler.OrbitalNavigator.Aim', '');openspace.setPropertyValueSingle('NavigationHandler.OrbitalNavigator.Anchor', 'Earth')openspace.setPropertyValueSingle('NavigationHandler.OrbitalNavigator.RetargetAnchor', nil);"
}
],
"assets": [
"base",
"scene/solarsystem/planets/earth/earth",
@@ -35,28 +61,16 @@
],
"keybindings": [
{
"documentation": "Toggle trails on or off for satellites around Earth",
"gui_path": "/Earth",
"is_local": false,
"key": "S",
"name": "Toggle satellite trails",
"script": "local list = openspace.getProperty('{earth_satellites}.Renderable.Enabled'); for _,v in pairs(list) do openspace.setPropertyValueSingle(v, not openspace.getPropertyValue(v)) end"
"action": "profile.toggle.satellite",
"key": "S"
},
{
"documentation": "Refocuses the camera on the ISS",
"gui_path": "/Earth",
"is_local": false,
"key": "I",
"name": "Focus ISS",
"script": "openspace.setPropertyValueSingle('NavigationHandler.OrbitalNavigator.Aim', '');openspace.setPropertyValueSingle('NavigationHandler.OrbitalNavigator.Anchor', 'ISS');openspace.setPropertyValueSingle('NavigationHandler.OrbitalNavigator.RetargetAnchor', nil);"
"action": "profile.focus.iss",
"key": "I"
},
{
"documentation": "Retargets the camera on Earth",
"gui_path": "/Earth",
"is_local": false,
"key": "HOME",
"name": "Focus on Earth",
"script": "openspace.setPropertyValueSingle('NavigationHandler.OrbitalNavigator.Aim', '');openspace.setPropertyValueSingle('NavigationHandler.OrbitalNavigator.Anchor', 'Earth')openspace.setPropertyValueSingle('NavigationHandler.OrbitalNavigator.RetargetAnchor', nil);"
"action": "profile.focus.earth",
"key": "HOME"
}
],
"mark_nodes": [
@@ -88,6 +102,6 @@
},
"version": {
"major": 1,
"minor": 0
"minor": 1
}
}

View File

@@ -1,4 +1,38 @@
{
"actions": [
{
"documentation": "Toggle trails on or off for satellites around Earth",
"gui_path": "/Earth",
"identifier": "profile.toggle.satellite",
"is_local": false,
"name": "Toggle satellite trails",
"script": "local list = openspace.getProperty('{earth_satellites}.Renderable.Enabled'); for _,v in pairs(list) do openspace.setPropertyValueSingle(v, not openspace.getPropertyValue(v)) end"
},
{
"documentation": "Refocuses the camera on the ISS",
"gui_path": "/Earth",
"identifier": "profile.focus.iss",
"is_local": false,
"name": "Focus ISS",
"script": "openspace.setPropertyValueSingle('NavigationHandler.OrbitalNavigator.Aim', '');openspace.setPropertyValueSingle('NavigationHandler.OrbitalNavigator.Anchor', 'ISS');openspace.setPropertyValueSingle('NavigationHandler.OrbitalNavigator.RetargetAnchor', nil);"
},
{
"documentation": "Retargets the camera on Earth",
"gui_path": "/Earth",
"identifier": "profile.focus.earth",
"is_local": false,
"name": "Focus on Earth",
"script": "openspace.setPropertyValueSingle('NavigationHandler.OrbitalNavigator.Aim', '');openspace.setPropertyValueSingle('NavigationHandler.OrbitalNavigator.Anchor', 'Earth')openspace.setPropertyValueSingle('NavigationHandler.OrbitalNavigator.RetargetAnchor', nil);"
},
{
"documentation": "Toggle on/off minor moon trails for all planets in the solar system",
"gui_path": "/Solar System",
"identifier": "profile.toggle.minormoons",
"is_local": false,
"name": "Toggle Minor Moon Trails",
"script": "local list = openspace.getProperty('{moonTrail_minor}.Renderable.Enabled'); for _,v in pairs(list) do openspace.setPropertyValueSingle(v, not openspace.getPropertyValue(v)) end"
}
],
"assets": [
"base",
"scene/solarsystem/planets/earth/earth",
@@ -43,36 +77,20 @@
],
"keybindings": [
{
"documentation": "Toggle trails on or off for satellites around Earth",
"gui_path": "/Earth",
"is_local": false,
"key": "S",
"name": "Toggle satellite trails",
"script": "local list = openspace.getProperty('{earth_satellites}.Renderable.Enabled'); for _,v in pairs(list) do openspace.setPropertyValueSingle(v, not openspace.getPropertyValue(v)) end"
"action": "profile.toggle.satellite",
"key": "S"
},
{
"documentation": "Refocuses the camera on the ISS",
"gui_path": "/Earth",
"is_local": false,
"key": "I",
"name": "Focus ISS",
"script": "openspace.setPropertyValueSingle('NavigationHandler.OrbitalNavigator.Aim', '');openspace.setPropertyValueSingle('NavigationHandler.OrbitalNavigator.Anchor', 'ISS');openspace.setPropertyValueSingle('NavigationHandler.OrbitalNavigator.RetargetAnchor', nil);"
"action": "profile.focus.iss",
"key": "I"
},
{
"documentation": "Retargets the camera on Earth",
"gui_path": "/Earth",
"is_local": false,
"key": "HOME",
"name": "Focus on Earth",
"script": "openspace.setPropertyValueSingle('NavigationHandler.OrbitalNavigator.Aim', '');openspace.setPropertyValueSingle('NavigationHandler.OrbitalNavigator.Anchor', 'Earth')openspace.setPropertyValueSingle('NavigationHandler.OrbitalNavigator.RetargetAnchor', nil);"
"action": "profile.focus.earth",
"key": "HOME"
},
{
"documentation": "Toggle on/off minor moon trails for all planets in the solar system",
"gui_path": "/Solar System",
"is_local": false,
"key": "SHIFT+H",
"name": "Toggle Minor Moon Trails",
"script": "local list = openspace.getProperty('{moonTrail_minor}.Renderable.Enabled'); for _,v in pairs(list) do openspace.setPropertyValueSingle(v, not openspace.getPropertyValue(v)) end"
"action": "profile.toggle.minormoons",
"key": "SHIFT+H"
}
],
"mark_nodes": [
@@ -110,6 +128,6 @@
},
"version": {
"major": 1,
"minor": 0
"minor": 1
}
}

View File

@@ -1,4 +1,46 @@
{
"actions": [
{
"documentation": "Toggle trails on or off for satellites around Earth",
"gui_path": "/Earth",
"identifier": "profile.toggle.satellitetrails",
"is_local": false,
"name": "Toggle satellite trails",
"script": "local list = openspace.getProperty('{earth_satellites}.Renderable.Enabled'); for _,v in pairs(list) do openspace.setPropertyValueSingle(v, not openspace.getPropertyValue(v)) end"
},
{
"documentation": "Toggle points and labels for the Lagrangian points for Earth Sun system",
"gui_path": "/JWST",
"identifier": "profile.toggle.lagrangianpoints",
"is_local": false,
"name": "Toggle Lagrangian points",
"script": "local list = openspace.getProperty('{lagrange_points_earth}.Renderable.Enabled'); for _,v in pairs(list) do openspace.setPropertyValueSingle(v, not openspace.getPropertyValue(v)) end"
},
{
"documentation": "Toggle Hubble Ultra Deep Field image and line towards its coordinate",
"gui_path": "/JWST",
"identifier": "profile.toggle.hudf",
"is_local": false,
"name": "Toggle Hubble Ultra Deep Field",
"script": "local list = openspace.getProperty('{mission_jwst_hudf}.*.Enabled'); for _,v in pairs(list) do openspace.setPropertyValueSingle(v, not openspace.getPropertyValue(v)) end"
},
{
"documentation": "Toggle L2 label, point and line",
"gui_path": "/JWST",
"identifier": "profile.toggle.l2",
"is_local": false,
"name": "Toggle L2",
"script": "local list = openspace.getProperty('{lagrange_points_earth_l2_small}.*.Enabled'); for _,v in pairs(list) do openspace.setPropertyValueSingle(v, not openspace.getPropertyValue(v)) end"
},
{
"documentation": "Toggle James Webb Space Telecope field of view and view band",
"gui_path": "/JWST",
"identifier": "profile.toggle.jwst_fov",
"is_local": false,
"name": "Toggle JWST field of view and view band",
"script": "local list = openspace.getProperty('{mission_jwst_fov}.*.Enabled'); for _,v in pairs(list) do openspace.setPropertyValueSingle(v, not openspace.getPropertyValue(v)) end"
}
],
"assets": [
"base",
"scene/solarsystem/planets/earth/earth",
@@ -38,44 +80,24 @@
],
"keybindings": [
{
"documentation": "Toggle trails on or off for satellites around Earth",
"gui_path": "/Earth",
"is_local": false,
"key": "S",
"name": "Toggle satellite trails",
"script": "local list = openspace.getProperty('{earth_satellites}.Renderable.Enabled'); for _,v in pairs(list) do openspace.setPropertyValueSingle(v, not openspace.getPropertyValue(v)) end"
"action": "profile.toggle.satellitetrails",
"key": "S"
},
{
"documentation": "Toggle points and labels for the Lagrangian points for Earth Sun system",
"gui_path": "/JWST",
"is_local": false,
"key": "P",
"name": "Toggle Lagrangian points",
"script": "local list = openspace.getProperty('{lagrange_points_earth}.Renderable.Enabled'); for _,v in pairs(list) do openspace.setPropertyValueSingle(v, not openspace.getPropertyValue(v)) end"
"action": "profile.toggle.lagrangianpoints",
"key": "P"
},
{
"documentation": "Toggle Hubble Ultra Deep Field image and line towards its coordinate",
"gui_path": "/JWST",
"is_local": false,
"key": "U",
"name": "Toggle Hubble Ultra Deep Field",
"script": "local list = openspace.getProperty('{mission_jwst_hudf}.*.Enabled'); for _,v in pairs(list) do openspace.setPropertyValueSingle(v, not openspace.getPropertyValue(v)) end"
"action": "profile.toggle.hudf",
"key": "U"
},
{
"documentation": "Toggle L2 label, point and line",
"gui_path": "/JWST",
"is_local": false,
"key": "O",
"name": "Toggle L2",
"script": "local list = openspace.getProperty('{lagrange_points_earth_l2_small}.*.Enabled'); for _,v in pairs(list) do openspace.setPropertyValueSingle(v, not openspace.getPropertyValue(v)) end"
"action": "profile.toggle.l2",
"key": "O"
},
{
"documentation": "Toggle James Webb Space Telecope field of view and view band",
"gui_path": "/JWST",
"is_local": false,
"key": "V",
"name": "Toggle JWST field of view and view band",
"script": "local list = openspace.getProperty('{mission_jwst_fov}.*.Enabled'); for _,v in pairs(list) do openspace.setPropertyValueSingle(v, not openspace.getPropertyValue(v)) end"
"action": "profile.toggle.jwst_fov",
"key": "V"
}
],
"mark_nodes": [
@@ -107,6 +129,6 @@
},
"version": {
"major": 1,
"minor": 0
"minor": 1
}
}
}

View File

@@ -1,4 +1,30 @@
{
"actions": [
{
"documentation": "Set and goto Insight Landing",
"gui_path": "/Missions/Insight",
"identifier": "profile.setup.insight",
"is_local": false,
"name": "Setup scene for insight EDL",
"script": "openspace.setPropertyValueSingle('Scene.Mars.Renderable.Layers.HeightLayers.Mola_Utah.Settings.Offset', -469.300000);openspace.setPropertyValueSingle('Scene.Mars.Renderable.Layers.HeightLayers.HiRISE-LS-DEM.Settings.Offset', -470.800006);openspace.setPropertyValueSingle('Scene.Mars.Renderable.Layers.HeightLayers.HiRISE-LS-DEM.Enabled', true);openspace.setPropertyValueSingle('Scene.Mars.Renderable.Layers.ColorLayers.HiRISE-LS.Enabled', true);openspace.time.setPause(true);openspace.time.setTime('2018 NOV 26 19:39:01.68');openspace.navigation.setNavigationState({Anchor = 'Insight',Pitch = 0.567457E-4,Position = { 1.240506E1,-1.369270E1,-2.423553E0 },ReferenceFrame = 'Root',Up = { 0.441211E0,0.247019E0,0.862737E0 },Yaw = -0.446853E-4});"
},
{
"documentation": "Disable Mars layer settings used for insight EDL",
"gui_path": "/Missions/Insight",
"identifier": "profile.unsetup.insight",
"is_local": false,
"name": "Unset Insight Landing",
"script": "openspace.setPropertyValueSingle('Scene.Mars.Renderable.Layers.HeightLayers.Mola_Utah.Settings.Offset', 0);openspace.setPropertyValueSingle('Scene.Mars.Renderable.Layers.HeightLayers.HiRISE-LS-DEM.Settings.Offset', 0);openspace.setPropertyValueSingle('Scene.Mars.Renderable.Layers.HeightLayers.HiRISE-LS-DEM.Enabled', false);openspace.setPropertyValueSingle('Scene.Mars.Renderable.Layers.ColorLayers.HiRISE-LS.Enabled', false);"
},
{
"documentation": "Sets time and layers for Perseverance landing",
"gui_path": "/Missions/Perseverance",
"identifier": "profile.setup.perseverance",
"is_local": false,
"name": "Setup and Goto Perseverance",
"script": "openspace.setPropertyValueSingle('Scene.Mars.Renderable.Layers.HeightLayers.Mola_Utah.Settings.Offset', -1674.0);openspace.setPropertyValueSingle('Scene.Mars.Renderable.Layers.HeightLayers.HiRISE-LS-DEM.Settings.Offset', -1674.0);openspace.time.setPause(true);openspace.time.setTime('2021 FEB 18 20:32:16');openspace.setPropertyValueSingle('Scene.Mars.Renderable.Layers.HeightLayers.HiRISE-LS-DEM.Enabled', true);openspace.setPropertyValueSingle('Scene.Mars.Renderable.Layers.ColorLayers.HiRISE-LS.Enabled', true);openspace.navigation.setNavigationState({Anchor = 'Perseverance',Pitch = 0.567457E-4,Position = { 1.240506E1,-1.369270E1,-2.423553E0 },ReferenceFrame = 'Root',Up = { 0.441211E0,0.247019E0,0.862737E0 },Yaw = -0.446853E-4});"
}
],
"assets": [
"base",
"scene/solarsystem/missions/insight/edl",
@@ -34,28 +60,16 @@
],
"keybindings": [
{
"documentation": "Set and goto Insight Landing",
"gui_path": "/Missions/Insight",
"is_local": false,
"key": "I",
"name": "Setup scene for insight EDL",
"script": "openspace.setPropertyValueSingle('Scene.Mars.Renderable.Layers.HeightLayers.Mola_Utah.Settings.Offset', -469.300000);openspace.setPropertyValueSingle('Scene.Mars.Renderable.Layers.HeightLayers.HiRISE-LS-DEM.Settings.Offset', -470.800006);openspace.setPropertyValueSingle('Scene.Mars.Renderable.Layers.HeightLayers.HiRISE-LS-DEM.Enabled', true);openspace.setPropertyValueSingle('Scene.Mars.Renderable.Layers.ColorLayers.HiRISE-LS.Enabled', true);openspace.time.setPause(true);openspace.time.setTime('2018 NOV 26 19:39:01.68');openspace.navigation.setNavigationState({Anchor = 'Insight',Pitch = 0.567457E-4,Position = { 1.240506E1,-1.369270E1,-2.423553E0 },ReferenceFrame = 'Root',Up = { 0.441211E0,0.247019E0,0.862737E0 },Yaw = -0.446853E-4});"
"action": "profile.setup.insight",
"key": "I"
},
{
"documentation": "Disable Mars layer settings used for insight EDL",
"gui_path": "/Missions/Insight",
"is_local": false,
"key": "SHIFT+I",
"name": "Unset Insight Landing",
"script": "openspace.setPropertyValueSingle('Scene.Mars.Renderable.Layers.HeightLayers.Mola_Utah.Settings.Offset', 0);openspace.setPropertyValueSingle('Scene.Mars.Renderable.Layers.HeightLayers.HiRISE-LS-DEM.Settings.Offset', 0);openspace.setPropertyValueSingle('Scene.Mars.Renderable.Layers.HeightLayers.HiRISE-LS-DEM.Enabled', false);openspace.setPropertyValueSingle('Scene.Mars.Renderable.Layers.ColorLayers.HiRISE-LS.Enabled', false);"
"action": "profile.unsetup.insight",
"key": "SHIFT+I"
},
{
"documentation": "Sets time and layers for Perseverance landing",
"gui_path": "/Missions/Perseverance",
"is_local": false,
"key": "P",
"name": "Setup and Goto Perseverance",
"script": "openspace.setPropertyValueSingle('Scene.Mars.Renderable.Layers.HeightLayers.Mola_Utah.Settings.Offset', -1674.0);openspace.setPropertyValueSingle('Scene.Mars.Renderable.Layers.HeightLayers.HiRISE-LS-DEM.Settings.Offset', -1674.0);openspace.time.setPause(true);openspace.time.setTime('2021 FEB 18 20:32:16');openspace.setPropertyValueSingle('Scene.Mars.Renderable.Layers.HeightLayers.HiRISE-LS-DEM.Enabled', true);openspace.setPropertyValueSingle('Scene.Mars.Renderable.Layers.ColorLayers.HiRISE-LS.Enabled', true);openspace.navigation.setNavigationState({Anchor = 'Perseverance',Pitch = 0.567457E-4,Position = { 1.240506E1,-1.369270E1,-2.423553E0 },ReferenceFrame = 'Root',Up = { 0.441211E0,0.247019E0,0.862737E0 },Yaw = -0.446853E-4});"
"action": "profile.setup.perseverance",
"key": "P"
}
],
"mark_nodes": [
@@ -77,6 +91,6 @@
},
"version": {
"major": 1,
"minor": 2
"minor": 1
}
}

View File

@@ -1,4 +1,134 @@
{
"actions": [
{
"documentation": "Sets the focus of the camera on 'NewHorizons'.",
"gui_path": "/Missions/New Horizons",
"identifier": "profile.focus.newhorizons",
"is_local": false,
"name": "Focus on New Horizons",
"script": "openspace.setPropertyValue('NavigationHandler.OrbitalNavigator.Anchor', 'NewHorizons');openspace.setPropertyValue('NavigationHandler.OrbitalNavigator.Aim', '');openspace.setPropertyValue('NavigationHandler.OrbitalNavigator.RetargetAnchor', nil);"
},
{
"documentation": "Anchor at New Horizons, Aim at Pluto",
"gui_path": "/Missions/New Horizons",
"identifier": "profile.focus.anchor_nh|aim_pluto",
"is_local": false,
"name": "Anchor NH, Aim Pluto",
"script": "openspace.setPropertyValue('NavigationHandler.OrbitalNavigator.Anchor', 'NewHorizons');openspace.setPropertyValue('NavigationHandler.OrbitalNavigator.Aim', 'Pluto');openspace.setPropertyValue('NavigationHandler.OrbitalNavigator.RetargetAnchor', nil)"
},
{
"documentation": "Sets the focus of the camera on 'Pluto'",
"gui_path": "/Missions/New Horizons",
"identifier": "profile.focus.pluto",
"is_local": false,
"name": "Focus on Pluto",
"script": "openspace.setPropertyValue('NavigationHandler.OrbitalNavigator.Anchor', 'PlutoProjection') ;openspace.setPropertyValue('NavigationHandler.OrbitalNavigator.Aim', ''); openspace.setPropertyValue('NavigationHandler.OrbitalNavigator.RetargetAnchor', nil);"
},
{
"documentation": "Sets the focus of the camera on 'Charon'.",
"gui_path": "/Missions/New Horizons",
"identifier": "profile.focus.charon",
"is_local": false,
"name": "Focus on Charon",
"script": "openspace.setPropertyValue('NavigationHandler.OrbitalNavigator.Anchor', 'Charon');openspace.setPropertyValue('NavigationHandler.OrbitalNavigator.Aim', '');openspace.setPropertyValue('NavigationHandler.OrbitalNavigator.RetargetAnchor', nil);"
},
{
"documentation": "Toggles New Horizons image projection",
"gui_path": "/Missions/New Horizons",
"identifier": "profile.toggle_nh_image_projections",
"is_local": false,
"name": "Toggle NH Image Projection",
"script": "local enabled = openspace.getPropertyValue('Scene.PlutoProjection.Renderable.ProjectionComponent.PerformProjection'); openspace.setPropertyValue('Scene.PlutoProjection.Renderable.ProjectionComponent.PerformProjection', not enabled); openspace.setPropertyValue('Scene.CharonProjection.Renderable.ProjectionComponent.PerformProjection', not enabled);"
},
{
"documentation": "Removes all image projections from Pluto and Charon.",
"gui_path": "/Missions/New Horizons",
"identifier": "profile.clear_image_projections",
"is_local": false,
"name": "Clear image projections",
"script": "openspace.setPropertyValue('Scene.PlutoProjection.Renderable.ProjectionComponent.ClearAllProjections', true); openspace.setPropertyValue('Scene.CharonProjection.Renderable.ProjectionComponent.ClearAllProjections', true);"
},
{
"documentation": "Jumps to the 14th of July 2015 at 0900 UTC and clears all projections.",
"gui_path": "/Missions/New Horizons",
"identifier": "profile.setup.approach",
"is_local": false,
"name": "Reset time and projections",
"script": "openspace.time.setTime('2015-07-14T09:00:00.00');openspace.setPropertyValue('Scene.PlutoProjection.Renderable.ProjectionComponent.ClearAllProjections', true);openspace.setPropertyValue('Scene.CharonProjection.Renderable.ProjectionComponent.ClearAllProjections', true);"
},
{
"documentation": "Increases the height map exaggeration on Pluto.",
"gui_path": "/Missions/New Horizons",
"identifier": "profile.pluto.increase_height_exaggeration",
"is_local": false,
"name": "Pluto HeightExaggeration +",
"script": "openspace.setPropertyValueSingle(\"Scene.PlutoProjection.Renderable.HeightExaggeration\", openspace.getPropertyValue(\"Scene.PlutoProjection.Renderable.HeightExaggeration\") + 5000);"
},
{
"documentation": "Decreases the height map exaggeration on Pluto.",
"gui_path": "/Missions/New Horizons",
"identifier": "profile.pluto.decrease_height_exaggeration",
"is_local": false,
"name": "Pluto HeightExaggeration -",
"script": "openspace.setPropertyValueSingle(\"Scene.PlutoProjection.Renderable.HeightExaggeration\", openspace.getPropertyValue(\"Scene.PlutoProjection.Renderable.HeightExaggeration\") - 5000);"
},
{
"documentation": "Increases the height map exaggeration on Charon.",
"gui_path": "/Missions/New Horizons",
"identifier": "profile.charon.increase_height_exaggeration",
"is_local": false,
"name": "Charon HeightExaggeration +",
"script": "openspace.setPropertyValueSingle(\"Scene.CharonProjection.Renderable.HeightExaggeration\", openspace.getPropertyValue(\"Scene.CharonProjection.Renderable.HeightExaggeration\") + 5000);"
},
{
"documentation": "Decreases the height map exaggeration on Charon.",
"gui_path": "/Missions/New Horizons",
"identifier": "profile.charon.decrease_height_exaggeration",
"is_local": false,
"name": "Charon HeightExaggeration -",
"script": "openspace.setPropertyValueSingle(\"Scene.CharonProjection.Renderable.HeightExaggeration\", openspace.getPropertyValue(\"Scene.CharonProjection.Renderable.HeightExaggeration\") - 5000);"
},
{
"documentation": "Toggles the visibility of the trail behind Pluto.",
"gui_path": "/Missions/New Horizons",
"identifier": "profile.toggle.pluto_trail",
"is_local": false,
"name": "Toggle Pluto Trail",
"script": "openspace.setPropertyValueSingle('Scene.PlutoBarycentricTrail.Renderable.Enabled', not openspace.getPropertyValue('Scene.PlutoBarycentricTrail.Renderable.Enabled'));"
},
{
"documentation": "Toggles the visibility of the text labels of Pluto, Charon, Hydra, Nix, Kerberos, and Styx.",
"gui_path": "/Missions/New Horizons",
"identifier": "profile.toggle.pluto_labels",
"is_local": false,
"name": "Toggle Pluto Labels",
"script": "local list = {\"Scene.PlutoText.Renderable.Enabled\", \"Scene.CharonText.Renderable.Enabled\", \"Scene.HydraText.Renderable.Enabled\", \"Scene.NixText.Renderable.Enabled\", \"Scene.KerberosText.Renderable.Enabled\", \"Scene.StyxText.Renderable.Enabled\"}; for _,v in pairs(list) do openspace.setPropertyValueSingle(v, not openspace.getPropertyValue(v)) end"
},
{
"documentation": "Toggles the visibility of the labels for the New Horizons instruments.",
"gui_path": "/Missions/New Horizons",
"identifier": "profile.toggle_nh_labels",
"is_local": false,
"name": "Toggle New Horizons Labels",
"script": "local v = openspace.getPropertyValue(\"Scene.Labels.Renderable.Opacity\"); if v <= 0.5 then openspace.setPropertyValueSingle(\"Scene.Labels.Renderable.Opacity\",1.0,2.0) else openspace.setPropertyValueSingle(\"Scene.Labels.Renderable.Opacity\",0.0,2.0) end"
},
{
"documentation": "Toggles the visibility of the shadow visualization of Pluto and Charon.",
"gui_path": "/Missions/New Horizons",
"identifier": "profile.toggle_shadows",
"is_local": false,
"name": "Toggle Shadows",
"script": "openspace.setPropertyValueSingle('Scene.PlutoShadow.Renderable.Enabled', not openspace.getPropertyValue('Scene.PlutoShadow.Renderable.Enabled'));openspace.setPropertyValueSingle('Scene.CharonShadow.Renderable.Enabled', not openspace.getPropertyValue('Scene.CharonShadow.Renderable.Enabled'));"
},
{
"documentation": "Toggles the trail of New Horizons",
"gui_path": "/Missions/New Horizons",
"identifier": "profile.toggle.nh_trail",
"is_local": false,
"name": "Toggle NH Trail",
"script": "openspace.setPropertyValueSingle('Scene.NewHorizonsTrailPluto.Renderable.Enabled', not openspace.getPropertyValue('Scene.NewHorizonsTrailPluto.Renderable.Enabled'));"
}
],
"assets": [
"base",
"scene/solarsystem/missions/newhorizons/dashboard",
@@ -37,172 +167,84 @@
],
"keybindings": [
{
"documentation": "Sets the focus of the camera on 'NewHorizons'.",
"gui_path": "/Missions/New Horizons",
"is_local": false,
"key": "A",
"name": "Focus on New Horizons",
"script": "openspace.setPropertyValue('NavigationHandler.OrbitalNavigator.Anchor', 'NewHorizons');openspace.setPropertyValue('NavigationHandler.OrbitalNavigator.Aim', '');openspace.setPropertyValue('NavigationHandler.OrbitalNavigator.RetargetAnchor', nil);"
"action": "profile.focus.newhorizons",
"key": "A"
},
{
"documentation": "Anchor at New Horizons, Aim at Pluto",
"gui_path": "/Missions/New Horizons",
"is_local": false,
"key": "SHIFT+A",
"name": "Anchor NH, Aim Pluto",
"script": "openspace.setPropertyValue('NavigationHandler.OrbitalNavigator.Anchor', 'NewHorizons');openspace.setPropertyValue('NavigationHandler.OrbitalNavigator.Aim', 'Pluto');openspace.setPropertyValue('NavigationHandler.OrbitalNavigator.RetargetAnchor', nil)"
"action": "profile.focus.anchor_nh|aim_pluto",
"key": "SHIFT+A"
},
{
"documentation": "Sets the focus of the camera on 'Pluto'",
"gui_path": "/Missions/New Horizons",
"is_local": false,
"key": "S",
"name": "Focus on Pluto",
"script": "openspace.setPropertyValue('NavigationHandler.OrbitalNavigator.Anchor', 'PlutoProjection') ;openspace.setPropertyValue('NavigationHandler.OrbitalNavigator.Aim', ''); openspace.setPropertyValue('NavigationHandler.OrbitalNavigator.RetargetAnchor', nil);"
"action": "profile.focus.pluto",
"key": "S"
},
{
"documentation": "Sets the focus of the camera on 'Charon'.",
"gui_path": "/Missions/New Horizons",
"is_local": false,
"key": "D",
"name": "Focus on Charon",
"script": "openspace.setPropertyValue('NavigationHandler.OrbitalNavigator.Anchor', 'Charon');openspace.setPropertyValue('NavigationHandler.OrbitalNavigator.Aim', '');openspace.setPropertyValue('NavigationHandler.OrbitalNavigator.RetargetAnchor', nil);"
"action": "profile.focus.charon",
"key": "D"
},
{
"documentation": "Toggles New Horizons image projection",
"gui_path": "/Missions/New Horizons",
"is_local": false,
"key": "F7",
"name": "Toggle NH Image Projection",
"script": "local enabled = openspace.getPropertyValue('Scene.PlutoProjection.Renderable.ProjectionComponent.PerformProjection'); openspace.setPropertyValue('Scene.PlutoProjection.Renderable.ProjectionComponent.PerformProjection', not enabled); openspace.setPropertyValue('Scene.CharonProjection.Renderable.ProjectionComponent.PerformProjection', not enabled);"
"action": "profile.toggle_nh_image_projections",
"key": "F7"
},
{
"documentation": "Removes all image projections from Pluto and Charon.",
"gui_path": "/Missions/New Horizons",
"is_local": false,
"key": "F8",
"name": "Clear image projections",
"script": "openspace.setPropertyValue('Scene.PlutoProjection.Renderable.ProjectionComponent.ClearAllProjections', true); openspace.setPropertyValue('Scene.CharonProjection.Renderable.ProjectionComponent.ClearAllProjections', true);"
"action": "profile.clear_image_projections",
"key": "F8"
},
{
"documentation": "Jumps to the 14th of July 2015 at 0900 UTC and clears all projections.",
"gui_path": "/Missions/New Horizons",
"is_local": false,
"key": "F9",
"name": "Reset time and projections",
"script": "openspace.time.setTime('2015-07-14T09:00:00.00');openspace.setPropertyValue('Scene.PlutoProjection.Renderable.ProjectionComponent.ClearAllProjections', true);openspace.setPropertyValue('Scene.CharonProjection.Renderable.ProjectionComponent.ClearAllProjections', true);"
"action": "profile.setup.approach",
"key": "F9"
},
{
"documentation": "Increases the height map exaggeration on Pluto.",
"gui_path": "/Missions/New Horizons",
"is_local": false,
"key": "KP8",
"name": "Pluto HeightExaggeration + (KP)",
"script": "openspace.setPropertyValueSingle(\"Scene.PlutoProjection.Renderable.HeightExaggeration\", openspace.getPropertyValue(\"Scene.PlutoProjection.Renderable.HeightExaggeration\") + 5000);"
"action": "profile.pluto.increase_height_exaggeration",
"key": "KP_8"
},
{
"documentation": "Increases the height map exaggeration on Pluto.",
"gui_path": "/Missions/New Horizons",
"is_local": false,
"key": "CTRL+I",
"name": "Pluto HeightExaggeration +",
"script": "openspace.setPropertyValueSingle(\"Scene.PlutoProjection.Renderable.HeightExaggeration\", openspace.getPropertyValue(\"Scene.PlutoProjection.Renderable.HeightExaggeration\") + 5000);"
"action": "profile.pluto.increase_height_exaggeration",
"key": "CTRL+I"
},
{
"documentation": "Decreases the height map exaggeration on Pluto.",
"gui_path": "/Missions/New Horizons",
"is_local": false,
"key": "CTRL+K",
"name": "Pluto HeightExaggeration -",
"script": "openspace.setPropertyValueSingle(\"Scene.PlutoProjection.Renderable.HeightExaggeration\", openspace.getPropertyValue(\"Scene.PlutoProjection.Renderable.HeightExaggeration\") - 5000);"
"action": "profile.pluto.decrease_height_exaggeration",
"key": "CTRL+K"
},
{
"documentation": "Decreases the height map exaggeration on Pluto.",
"gui_path": "/Missions/New Horizons",
"is_local": false,
"key": "KP2",
"name": "Pluto HeightExaggeration - (KP)",
"script": "openspace.setPropertyValueSingle(\"Scene.PlutoProjection.Renderable.HeightExaggeration\", openspace.getPropertyValue(\"Scene.PlutoProjection.Renderable.HeightExaggeration\") - 5000);"
"action": "profile.pluto.decrease_height_exaggeration",
"key": "KP_2"
},
{
"documentation": "Increases the height map exaggeration on Charon.",
"gui_path": "/Missions/New Horizons",
"is_local": false,
"key": "KP9",
"name": "Charon HeightExaggeration + (KP)",
"script": "openspace.setPropertyValueSingle(\"Scene.CharonProjection.Renderable.HeightExaggeration\", openspace.getPropertyValue(\"Scene.CharonProjection.Renderable.HeightExaggeration\") + 5000);"
"action": "profile.charon.increase_height_exaggeration",
"key": "KP_9"
},
{
"documentation": "Increases the height map exaggeration on Charon.",
"gui_path": "/Missions/New Horizons",
"is_local": false,
"key": "CTRL+O",
"name": "Charon HeightExaggeration +",
"script": "openspace.setPropertyValueSingle(\"Scene.CharonProjection.Renderable.HeightExaggeration\", openspace.getPropertyValue(\"Scene.CharonProjection.Renderable.HeightExaggeration\") + 5000);"
"action": "profile.charon.increase_height_exaggeration",
"key": "CTRL+O"
},
{
"documentation": "Decreases the height map exaggeration on Charon.",
"gui_path": "/Missions/New Horizons",
"is_local": false,
"key": "KP3",
"name": "Charon HeightExaggeration - (KP)",
"script": "openspace.setPropertyValueSingle(\"Scene.CharonProjection.Renderable.HeightExaggeration\", openspace.getPropertyValue(\"Scene.CharonProjection.Renderable.HeightExaggeration\") - 5000);"
"action": "profile.charon.decrease_height_exaggeration",
"key": "KP_3"
},
{
"documentation": "Decreases the height map exaggeration on Charon.",
"gui_path": "/Missions/New Horizons",
"is_local": false,
"key": "CTRL+L",
"name": "Charon HeightExaggeration -",
"script": "openspace.setPropertyValueSingle(\"Scene.CharonProjection.Renderable.HeightExaggeration\", openspace.getPropertyValue(\"Scene.CharonProjection.Renderable.HeightExaggeration\") - 5000);"
"action": "profile.charon.decrease_height_exaggeration",
"key": "CTRL+L"
},
{
"documentation": "Toggles the visibility of the trail behind Pluto.",
"gui_path": "/Missions/New Horizons",
"is_local": false,
"key": "O",
"name": "Toggle Pluto Trail",
"script": "openspace.setPropertyValueSingle('Scene.PlutoBarycentricTrail.Renderable.Enabled', not openspace.getPropertyValue('Scene.PlutoBarycentricTrail.Renderable.Enabled'));"
"action": "profile.toggle.pluto_trail",
"key": "O"
},
{
"documentation": "Toggles the visibility of the text labels of Pluto, Charon, Hydra, Nix, Kerberos, and Styx.",
"gui_path": "/Missions/New Horizons",
"is_local": false,
"key": "J",
"name": "Toggle Pluto Labels",
"script": "local list = {\"Scene.PlutoText.Enabled\", \"Scene.CharonText.Enabled\", \"Scene.HydraText.Enabled\", \"Scene.NixText.Enabled\", \"Scene.KerberosText.Enabled\", \"Scene.StyxText.Enabled\"}; for _,v in pairs(list) do openspace.setPropertyValueSingle(v, not openspace.getPropertyValue(v)) end"
"action": "profile.toggle.pluto_labels",
"key": "J"
},
{
"documentation": "Toggles the visibility of the labels for the New Horizons instruments.",
"gui_path": "/Missions/New Horizons",
"is_local": false,
"key": "I",
"name": "Toggle New Horizons Labels",
"script": "local v = openspace.getPropertyValue(\"Scene.Labels.Renderable.Opacity\"); if v <= 0.5 then openspace.setPropertyValueSingle(\"Scene.Labels.Renderable.Opacity\",1.0,2.0) else openspace.setPropertyValueSingle(\"Scene.Labels.Renderable.Opacity\",0.0,2.0) end"
"action": "profile.toggle_nh_labels",
"key": "I"
},
{
"documentation": "Draws the instrument field of views in a solid color or as lines.",
"gui_path": "/Missions/New Horizons",
"is_local": false,
"key": "M",
"name": "Toggle instrument FOVs",
"script": "local list = {\"Scene.PlutoText.Enabled\", \"Scene.NH_LORRI.Renderable.SolidDraw\", \"Scene.NH_RALPH_LEISA.Renderable.SolidDraw\", \"Scene.NH_RALPH_MVIC_PAN1.Renderable.SolidDraw\", \"Scene.NH_RALPH_MVIC_PAN2.Renderable.SolidDraw\", \"Scene.NH_RALPH_MVIC_RED.Renderable.SolidDraw\", \"Scene.NH_RALPH_MVIC_BLUE.Renderable.SolidDraw\", \"Scene.NH_RALPH_MVIC_FT.Renderable.SolidDraw\", \"Scene.NH_RALPH_MVIC_METHANE.Renderable.SolidDraw\", \"Scene.NH_RALPH_MVIC_NIR.Renderable.SolidDraw\", \"Scene.NH_ALICE_AIRGLOW.Renderable.SolidDraw\", \"Scene.NH_ALICE_SOC.Renderable.SolidDraw\"}; for _,v in pairs(list) do openspace.setPropertyValueSingle(v, not openspace.getPropertyValue(v)) end"
"action": "profile.toggle_shadows",
"key": "SHIFT+T"
},
{
"documentation": "Toggles the visibility of the shadow visualization of Pluto and Charon.",
"gui_path": "/Missions/New Horizons",
"is_local": false,
"key": "SHIFT+T",
"name": "Toggle Shadows",
"script": "openspace.setPropertyValueSingle('Scene.PlutoShadow.Renderable.Enabled', not openspace.getPropertyValue('Scene.PlutoShadow.Renderable.Enabled'));openspace.setPropertyValueSingle('Scene.CharonShadow.Renderable.Enabled', not openspace.getPropertyValue('Scene.CharonShadow.Renderable.Enabled'));"
},
{
"documentation": "Toggles the trail of New Horizons",
"gui_path": "/Missions/New Horizons",
"is_local": false,
"key": "T",
"name": "Toggle NH Trail",
"script": "openspace.setPropertyValueSingle('Scene.NewHorizonsTrailPluto.Renderable.Enabled', not openspace.getPropertyValue('Scene.NewHorizonsTrailPluto.Renderable.Enabled'));"
"action": "profile.toggle.nh_trail",
"key": "T"
}
],
"mark_nodes": [
@@ -246,6 +288,6 @@
},
"version": {
"major": 1,
"minor": 0
"minor": 1
}
}
}

View File

@@ -1,4 +1,62 @@
{
"actions": [
{
"documentation": "Sets the focus of the camera on 'OsirisRex'",
"gui_path": "/Missions/Osiris Rex",
"identifier": "profile.focus.osirisrex",
"is_local": false,
"name": "Focus on OsirisRex",
"script": "openspace.setPropertyValue('NavigationHandler.OrbitalNavigator.Anchor', 'OsirisRex'); openspace.setPropertyValue('NavigationHandler.OrbitalNavigator.Aim', ''); openspace.setPropertyValue('NavigationHandler.OrbitalNavigator.RetargetAnchor', nil);"
},
{
"documentation": "Sets the focus of the camera on 'Bennu'",
"gui_path": "/Missions/Osiris Rex",
"identifier": "profile.focus.bennu",
"is_local": false,
"name": "Focus on Bennu",
"script": "openspace.setPropertyValue('NavigationHandler.OrbitalNavigator.Anchor', 'BennuBarycenter'); openspace.setPropertyValue('NavigationHandler.OrbitalNavigator.Aim', ''); openspace.setPropertyValue('NavigationHandler.OrbitalNavigator.RetargetAnchor', nil);"
},
{
"documentation": "Sets the time to the approach at Bennu",
"gui_path": "/Missions/Osiris Rex",
"identifier": "profile.setup.bennu_approach",
"is_local": false,
"name": "Set Bennu approach time",
"script": "openspace.printInfo('Set time: Approach');openspace.time.setTime('2018-SEP-11 21:31:01.183');"
},
{
"documentation": "Sets the time to the preliminary survey of Bennu",
"gui_path": "/Missions/Osiris Rex",
"identifier": "profile.setup.bennu_survey",
"is_local": false,
"name": "Set Bennu survey time",
"script": "openspace.printInfo('Set time: Preliminary Survey'); openspace.time.setTime('2018-NOV-20 01:13:12.183');"
},
{
"documentation": "Sets the time to the orbital B event",
"gui_path": "/Missions/Osiris Rex",
"identifier": "profile.setup.orbital_b_event",
"is_local": false,
"name": "Set orbital B event time",
"script": "openspace.printInfo('Set time: Orbital B'); openspace.time.setTime('2019-APR-08 10:35:27.186');"
},
{
"documentation": "Sets the time to the recon event",
"gui_path": "/Missions/Osiris Rex",
"identifier": "profile.setup.recon_event",
"is_local": false,
"name": "Set recon event time",
"script": "openspace.printInfo('Set time: Recon'); openspace.time.setTime('2019-MAY-25 03:50:31.195');"
},
{
"documentation": "Toggles the visibility of the text marking the location of the Sun",
"gui_path": "/Missions/Osiris Rex",
"identifier": "profile.toggle.sun_marker",
"is_local": false,
"name": "Toggle Sun marker",
"script": "openspace.setPropertyValueSingle('Scene.SunMarker.Renderable.Enabled', not openspace.getPropertyValue('Scene.SunMarker.Renderable.Enabled'));"
}
],
"assets": [
"base",
"scene/solarsystem/missions/osirisrex/dashboard",
@@ -41,60 +99,32 @@
],
"keybindings": [
{
"documentation": "Sets the focus of the camera on 'OsirisRex'",
"gui_path": "/Missions/Osiris Rex",
"is_local": false,
"key": "A",
"name": "Focus on OsirisRex",
"script": "openspace.setPropertyValue('NavigationHandler.OrbitalNavigator.Anchor', 'OsirisRex'); openspace.setPropertyValue('NavigationHandler.OrbitalNavigator.Aim', ''); openspace.setPropertyValue('NavigationHandler.OrbitalNavigator.RetargetAnchor', nil);"
"action": "profile.focus.osirisrex",
"key": "A"
},
{
"documentation": "Sets the focus of the camera on 'Bennu'",
"gui_path": "/Missions/Osiris Rex",
"is_local": false,
"key": "S",
"name": "Focus on Bennu",
"script": "openspace.setPropertyValue('NavigationHandler.OrbitalNavigator.Anchor', 'BennuBarycenter'); openspace.setPropertyValue('NavigationHandler.OrbitalNavigator.Aim', ''); openspace.setPropertyValue('NavigationHandler.OrbitalNavigator.RetargetAnchor', nil);"
"action": "profile.focus.bennu",
"key": "S"
},
{
"documentation": "Sets the time to the approach at Bennu",
"gui_path": "/Missions/Osiris Rex",
"is_local": false,
"key": "F8",
"name": "Set Bennu approach time",
"script": "openspace.printInfo('Set time: Approach');openspace.time.setTime('2018-SEP-11 21:31:01.183');"
"action": "profile.setup.bennu_approach",
"key": "F8"
},
{
"documentation": "Sets the time to the preliminary survey of Bennu",
"gui_path": "/Missions/Osiris Rex",
"is_local": false,
"key": "F9",
"name": "Set Bennu survey time",
"script": "openspace.printInfo('Set time: Preliminary Survey'); openspace.time.setTime('2018-NOV-20 01:13:12.183');"
"action": "profile.setup.bennu_survey",
"key": "F9"
},
{
"documentation": "Sets the time to the orbital B event",
"gui_path": "/Missions/Osiris Rex",
"is_local": false,
"key": "F10",
"name": "Set orbital B event time",
"script": "openspace.printInfo('Set time: Orbital B'); openspace.time.setTime('2019-APR-08 10:35:27.186');"
"action": "profile.setup.orbital_b_event",
"key": "F10"
},
{
"documentation": "Sets the time to the recon event",
"gui_path": "/Missions/Osiris Rex",
"is_local": false,
"key": "F11",
"name": "Set recon event time",
"script": "openspace.printInfo('Set time: Recon'); openspace.time.setTime('2019-MAY-25 03:50:31.195');"
"action": "profile.setup.recon_event",
"key": "F11"
},
{
"documentation": "Toggles the visibility of the text marking the location of the Sun",
"gui_path": "/Missions/Osiris Rex",
"is_local": false,
"key": "Q",
"name": "Toggle Sun marker",
"script": "openspace.setPropertyValueSingle('Scene.SunMarker.Renderable.Enabled', not openspace.getPropertyValue('Scene.SunMarker.Renderable.Enabled'));"
"action": "profile.toggle.sun_marker",
"key": "Q"
}
],
"mark_nodes": [
@@ -123,6 +153,6 @@
},
"version": {
"major": 1,
"minor": 0
"minor": 1
}
}

View File

@@ -1,4 +1,70 @@
{
"actions": [
{
"documentation": "Sets the focus of the camera on 67P",
"gui_path": "/Missions/Rosetta",
"identifier": "profile.focus.67P",
"is_local": false,
"name": "Focus on 67P",
"script": "openspace.setPropertyValue('NavigationHandler.OrbitalNavigator.Anchor', '67P'); openspace.setPropertyValue('NavigationHandler.OrbitalNavigator.Aim', ''); openspace.setPropertyValue('NavigationHandler.OrbitalNavigator.RetargetAnchor', nil);"
},
{
"documentation": "Sets the focus of the camera on Rosetta",
"gui_path": "/Missions/Rosetta",
"identifier": "profile.focus.rosetta",
"is_local": false,
"name": "Focus on Rosetta",
"script": "openspace.setPropertyValue('NavigationHandler.OrbitalNavigator.Anchor', 'Rosetta'); openspace.setPropertyValue('NavigationHandler.OrbitalNavigator.Aim', ''); openspace.setPropertyValue('NavigationHandler.OrbitalNavigator.RetargetAnchor', nil);"
},
{
"documentation": "Jumps to the time when the Philae lander is released.",
"gui_path": "/Missions/Rosetta",
"identifier": "profile.setup.lander_release",
"is_local": false,
"name": "Set lander release time",
"script": "openspace.time.setTime('2014-11-12T08:20:00.00');"
},
{
"documentation": "Removes all image projections from 67P.",
"gui_path": "/Missions/Rosetta",
"identifier": "profile.67p.clear_projections",
"is_local": false,
"name": "Clear 67P projections",
"script": "openspace.setPropertyValue('Scene.67P.Renderable.ProjectionComponent.ClearAllProjections', true);"
},
{
"documentation": "Toggles the visibility of all trails further from the Sun than 67P.",
"gui_path": "/Missions/Rosetta",
"identifier": "profile.toggle.outerplanet_trails",
"is_local": false,
"name": "Toggle outer planetary trails",
"script": "local list = openspace.getProperty('{planetTrail_giants}.Renderable.Enabled'); for _,v in pairs(list) do openspace.setPropertyValueSingle(v, not openspace.getPropertyValue(v)) end"
},
{
"documentation": "Toggles the visibility of the free floating image plane.",
"gui_path": "/Missions/Rosetta",
"identifier": "profile.toggle.image_plane",
"is_local": false,
"name": "Toggle image plane",
"script": "openspace.setPropertyValueSingle('Scene.ImagePlaneRosetta.Renderable.Enabled', not openspace.getPropertyValue('Scene.ImagePlaneRosetta.Renderable.Enabled'));"
},
{
"documentation": "Toggles the visibility of Philae's trail.",
"gui_path": "/Missions/Rosetta",
"identifier": "profile.toggle.philae_trail",
"is_local": false,
"name": "Toggle Philae trail",
"script": "openspace.setPropertyValueSingle('Scene.PhilaeTrail.Renderable.Enabled', not openspace.getPropertyValue('Scene.PhilaeTrail.Renderable.Enabled'));"
},
{
"documentation": "Enables or disables the image projection on 67P.",
"gui_path": "/Missions/Rosetta",
"identifier": "profile.toggle.67p_projection",
"is_local": false,
"name": "Toggle 67P projection",
"script": "openspace.setPropertyValueSingle('Scene.67P.Renderable.ProjectionComponent.PerformProjection', not openspace.getPropertyValue('Scene.67P.Renderable.ProjectionComponent.PerformProjection'));"
}
],
"assets": [
"base",
"scene/solarsystem/missions/rosetta/67p",
@@ -45,68 +111,36 @@
],
"keybindings": [
{
"documentation": "Sets the focus of the camera on 67P",
"gui_path": "/Missions/Rosetta",
"is_local": false,
"key": "A",
"name": "Focus on 67P",
"script": "openspace.setPropertyValue('NavigationHandler.OrbitalNavigator.Anchor', '67P'); openspace.setPropertyValue('NavigationHandler.OrbitalNavigator.Aim', ''); openspace.setPropertyValue('NavigationHandler.OrbitalNavigator.RetargetAnchor', nil);"
"action": "profile.focus.67P",
"key": "A"
},
{
"documentation": "Sets the focus of the camera on Rosetta",
"gui_path": "/Missions/Rosetta",
"is_local": false,
"key": "S",
"name": "Focus on Rosetta",
"script": "openspace.setPropertyValue('NavigationHandler.OrbitalNavigator.Anchor', 'Rosetta'); openspace.setPropertyValue('NavigationHandler.OrbitalNavigator.Aim', ''); openspace.setPropertyValue('NavigationHandler.OrbitalNavigator.RetargetAnchor', nil);"
"action": "profile.focus.rosetta",
"key": "S"
},
{
"documentation": "Jumps to the time when the Philae lander is released.",
"gui_path": "/Missions/Rosetta",
"is_local": false,
"key": "F6",
"name": "Set lander release time",
"script": "openspace.time.setTime('2014-11-12T08:20:00.00');"
"action": "profile.setup.lander_release",
"key": "F6"
},
{
"documentation": "Removes all image projections from 67P.",
"gui_path": "/Missions/Rosetta",
"is_local": false,
"key": "F8",
"name": "Clear 67P projections",
"script": "openspace.setPropertyValue('Scene.67P.Renderable.ProjectionComponent.ClearAllProjections', true);"
"action": "profile.67p.clear_projections",
"key": "F8"
},
{
"documentation": "Toggles the visibility of all trails further from the Sun than 67P.",
"gui_path": "/Missions/Rosetta",
"is_local": false,
"key": "E",
"name": "Toggle outer planetary trails",
"script": "local list = openspace.getProperty('{planetTrail_giants}.Renderable.Enabled'); for _,v in pairs(list) do openspace.setPropertyValueSingle(v, not openspace.getPropertyValue(v)) end"
"action": "profile.toggle.outerplanet_trails",
"key": "E"
},
{
"documentation": "Toggles the visibility of the free floating image plane.",
"gui_path": "/Missions/Rosetta",
"is_local": false,
"key": "I",
"name": "Toggle image plane",
"script": "openspace.setPropertyValueSingle('Scene.ImagePlaneRosetta.Renderable.Enabled', not openspace.getPropertyValue('Scene.ImagePlaneRosetta.Renderable.Enabled'));"
"action": "profile.toggle.image_plane",
"key": "I"
},
{
"documentation": "Toggles the visibility of Philae's trail.",
"gui_path": "/Missions/Rosetta",
"is_local": false,
"key": "O",
"name": "Toggle Philae trail",
"script": "openspace.setPropertyValueSingle('Scene.PhilaeTrail.Renderable.Enabled', not openspace.getPropertyValue('Scene.PhilaeTrail.Renderable.Enabled'));"
"action": "profile.toggle.philae_trail",
"key": "O"
},
{
"documentation": "Enables or disables the image projection on 67P.",
"gui_path": "/Missions/Rosetta",
"is_local": false,
"key": "P",
"name": "Toggle 67P projection",
"script": "openspace.setPropertyValueSingle('Scene.67P.Renderable.ProjectionComponent.PerformProjection', not openspace.getPropertyValue('Scene.67P.Renderable.ProjectionComponent.PerformProjection'));"
"action": "profile.toggle.67p_projection",
"key": "P"
}
],
"mark_nodes": [
@@ -140,6 +174,6 @@
},
"version": {
"major": 1,
"minor": 0
"minor": 1
}
}

View File

@@ -1,4 +1,62 @@
{
"actions": [
{
"documentation": "Set camera focus to Voyager 1",
"gui_path": "/Missions/Voyager",
"identifier": "profile.focus.voyager1",
"is_local": false,
"name": "Focus on Voyager",
"script": "openspace.setPropertyValueSingle(\"NavigationHandler.OrbitalNavigator.RetargetAnchor\", nil);openspace.setPropertyValueSingle(\"NavigationHandler.OrbitalNavigator.Anchor\", 'Voyager_1');openspace.setPropertyValueSingle(\"NavigationHandler.OrbitalNavigator.Aim\", '')"
},
{
"documentation": "Sets the camera focus on Voyager 2",
"gui_path": "/Missions/Voyager",
"identifier": "profile.focus.voyager2",
"is_local": false,
"name": "Focus on Voyager2",
"script": "openspace.setPropertyValueSingle(\"NavigationHandler.OrbitalNavigator.RetargetAnchor\", nil);openspace.setPropertyValueSingle(\"NavigationHandler.OrbitalNavigator.Anchor\", 'Voyager_2');openspace.setPropertyValueSingle(\"NavigationHandler.OrbitalNavigator.Aim\", '');"
},
{
"documentation": "Sets the time for Voyager's approach to Jupiter",
"gui_path": "/",
"identifier": "profile.setup.jupiter_approach",
"is_local": false,
"name": "Set Jupiter Approach",
"script": "openspace.time.setTime(\"1979-01-20T01:32:07.914\")"
},
{
"documentation": "Sets the time for Voyager's approach to Saturn",
"gui_path": "/Missions/Voyager",
"identifier": "profile.setup.saturn_approach",
"is_local": false,
"name": "Set Saturn Approach",
"script": "openspace.time.setTime(\"1980-10-20T07:43:42.645\");"
},
{
"documentation": "Set the camera focus to Jupiter",
"gui_path": "/Missions/Voyager",
"identifier": "profile.focus.jupiter",
"is_local": false,
"name": "Focus on Jupiter",
"script": "openspace.setPropertyValueSingle(\"NavigationHandler.OrbitalNavigator.RetargetAnchor\", nil);openspace.setPropertyValueSingle(\"NavigationHandler.OrbitalNavigator.Anchor\", 'Jupiter');openspace.setPropertyValueSingle(\"NavigationHandler.OrbitalNavigator.Aim\", '');"
},
{
"documentation": "Sets the camera focus on Saturn",
"gui_path": "/Missions/Voyager",
"identifier": "profile.focus.saturn",
"is_local": false,
"name": "Focus on Saturn",
"script": "openspace.setPropertyValueSingle(\"NavigationHandler.OrbitalNavigator.RetargetAnchor\", nil);openspace.setPropertyValueSingle(\"NavigationHandler.OrbitalNavigator.Anchor\", 'Saturn');openspace.setPropertyValueSingle(\"NavigationHandler.OrbitalNavigator.Aim\", '');"
},
{
"documentation": "Toggles the trails of the minor moons",
"gui_path": "/Solar System",
"identifier": "profile.toggle.minor_trails",
"is_local": false,
"name": "Toggle minor trails",
"script": "local list = openspace.getProperty('{moonTrail_minor}.Renderable.Enabled'); for _,v in pairs(list) do openspace.setPropertyValueSingle(v, not openspace.getPropertyValue(v)) end"
}
],
"assets": [
"base",
"scene/solarsystem/missions/voyager/dashboard",
@@ -37,60 +95,32 @@
],
"keybindings": [
{
"documentation": "Set camera focus to Voyager 1",
"gui_path": "/Missions/Voyager",
"is_local": false,
"key": "V",
"name": "Focvus on Voyager",
"script": "openspace.setPropertyValueSingle(\"NavigationHandler.OrbitalNavigator.RetargetAnchor\", nil);openspace.setPropertyValueSingle(\"NavigationHandler.OrbitalNavigator.Anchor\", 'Voyager_1');openspace.setPropertyValueSingle(\"NavigationHandler.OrbitalNavigator.Aim\", '')"
"action": "profile.focus.voyager1",
"key": "V"
},
{
"documentation": "Sets the camera focus on Voyager 2",
"gui_path": "/Missions/Voyager",
"is_local": false,
"key": "SHIFT+V",
"name": "Focus on Voyager2",
"script": "openspace.setPropertyValueSingle(\"NavigationHandler.OrbitalNavigator.RetargetAnchor\", nil);openspace.setPropertyValueSingle(\"NavigationHandler.OrbitalNavigator.Anchor\", 'Voyager_2');openspace.setPropertyValueSingle(\"NavigationHandler.OrbitalNavigator.Aim\", '');"
"action": "profile.focus.voyager2",
"key": "SHIFT+V"
},
{
"documentation": "Sets the time for Voyager's approach to Jupiter",
"gui_path": "/",
"is_local": false,
"key": "SHIFT+J",
"name": "Set Jupiter Approach",
"script": "openspace.time.setTime(\"1979-01-20T01:32:07.914\")"
"action": "profile.setup.jupiter_approach",
"key": "SHIFT+J"
},
{
"documentation": "Sets the time for Voyager's approach to Saturn",
"gui_path": "/Missions/Voyager",
"is_local": false,
"key": "SHIFT+S",
"name": "Set Saturn Approach",
"script": "openspace.time.setTime(\"1980-10-20T07:43:42.645\");"
"action": "profile.setup.saturn_approach",
"key": "SHIFT+S"
},
{
"documentation": "Set the camera focus to Jupiter",
"gui_path": "/Missions/Voyager",
"is_local": false,
"key": "J",
"name": "Focus on Jupiter",
"script": "openspace.setPropertyValueSingle(\"NavigationHandler.OrbitalNavigator.RetargetAnchor\", nil);openspace.setPropertyValueSingle(\"NavigationHandler.OrbitalNavigator.Anchor\", 'Jupiter');openspace.setPropertyValueSingle(\"NavigationHandler.OrbitalNavigator.Aim\", '');"
"action": "profile.focus.jupiter",
"key": "J"
},
{
"documentation": "Sets the camera focus on Saturn",
"gui_path": "/Missions/Voyager",
"is_local": false,
"key": "S",
"name": "Focus on Saturn",
"script": "openspace.setPropertyValueSingle(\"NavigationHandler.OrbitalNavigator.RetargetAnchor\", nil);openspace.setPropertyValueSingle(\"NavigationHandler.OrbitalNavigator.Anchor\", 'Saturn');openspace.setPropertyValueSingle(\"NavigationHandler.OrbitalNavigator.Aim\", '');"
"action": "profile.focus.saturn",
"key": "S"
},
{
"documentation": "Toggles the trails of the minor moons",
"gui_path": "/Solar System",
"is_local": false,
"key": "SHIFT+H",
"name": "Toggle minor trails",
"script": "local list = openspace.getProperty('{moonTrail_minor}.Renderable.Enabled'); for _,v in pairs(list) do openspace.setPropertyValueSingle(v, not openspace.getPropertyValue(v)) end"
"action": "profile.toggle.minor_trails",
"key": "SHIFT+H"
}
],
"mark_nodes": [
@@ -123,6 +153,6 @@
},
"version": {
"major": 1,
"minor": 0
"minor": 1
}
}

View File

@@ -0,0 +1,39 @@
/*****************************************************************************************
* *
* OpenSpace *
* *
* Copyright (c) 2014-2021 *
* *
* Permission is hereby granted, free of charge, to any person obtaining a copy of this *
* software and associated documentation files (the "Software"), to deal in the Software *
* without restriction, including without limitation the rights to use, copy, modify, *
* merge, publish, distribute, sublicense, and/or sell copies of the Software, and to *
* permit persons to whom the Software is furnished to do so, subject to the following *
* conditions: *
* *
* The above copyright notice and this permission notice shall be included in all copies *
* or substantial portions of the Software. *
* *
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, *
* INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A *
* PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT *
* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF *
* CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE *
* OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. *
****************************************************************************************/
#ifndef __OPENSPACE_CORE___CAMERAPOSE___H__
#define __OPENSPACE_CORE___CAMERAPOSE___H__
#include <ghoul/glm.h>
namespace openspace {
struct CameraPose {
glm::dvec3 position = glm::dvec3(0.0);
glm::dquat rotation = glm::dquat(1.0, 0.0, 0.0, 0.0);
};
} // namespace openspace
#endif // __OPENSPACE_CORE___CAMERAPOSE___H__

View File

@@ -54,6 +54,7 @@ namespace configuration { struct Configuration; }
namespace interaction {
struct JoystickInputStates;
struct WebsocketInputStates;
class ActionManager;
class InteractionMonitor;
class KeybindingManager;
class NavigationHandler;
@@ -88,6 +89,7 @@ inline VersionChecker* versionChecker;
inline VirtualPropertyManager* virtualPropertyManager;
inline WindowDelegate* windowDelegate;
inline configuration::Configuration* configuration;
inline interaction::ActionManager* actionManager;
inline interaction::InteractionMonitor* interactionMonitor;
inline interaction::JoystickInputStates* joystickInputStates;
inline interaction::WebsocketInputStates* websocketInputStates;

View File

@@ -0,0 +1,70 @@
/*****************************************************************************************
* *
* OpenSpace *
* *
* Copyright (c) 2014-2021 *
* *
* Permission is hereby granted, free of charge, to any person obtaining a copy of this *
* software and associated documentation files (the "Software"), to deal in the Software *
* without restriction, including without limitation the rights to use, copy, modify, *
* merge, publish, distribute, sublicense, and/or sell copies of the Software, and to *
* permit persons to whom the Software is furnished to do so, subject to the following *
* conditions: *
* *
* The above copyright notice and this permission notice shall be included in all copies *
* or substantial portions of the Software. *
* *
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, *
* INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A *
* PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT *
* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF *
* CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE *
* OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. *
****************************************************************************************/
#ifndef __OPENSPACE_CORE___ACTION___H__
#define __OPENSPACE_CORE___ACTION___H__
#include <ghoul/misc/boolean.h>
#include <string>
namespace openspace::interaction {
struct Action {
BooleanType(IsSynchronized);
/// Unique identifier that identifies this action. There is no special naming scheme
/// that we enforce, we are trying to stick to the same . separated structure that
/// hopefully provides some protection against accidentally reusing identifiers
std::string identifier;
/// The Lua script that gets executed whenever this action is triggered. Optional
/// parameters can be passed to actions which are accessible through an `args`
/// variable that contains all of the arguments passed into the action. This means
/// that the provided script must not use this variable name itself or the script will
/// not successfully execute
std::string command;
/// The human-readable name of this action. This name must not be unique, but it is
/// recommended that the combination of GuiPath + name should be unique to prevent
/// user confusion
std::string name;
/// A user-facing description of what the action does when it gets triggered. If the
/// action uses optional arguments, they should be described in here, too
std::string documentation;
/// This variable defines a subdivision of where this action is placed in a user
/// interface. The individual path components are separated by '/' with a leading '/'
/// for the root path
std::string guiPath;
/// If this value is set to `Yes`, the execution of this action is synchronized to
/// other OpenSpace instances, for example other nodes in a cluster environment, or
/// to other OpenSpace instances using a parallel connection
IsSynchronized synchronization = IsSynchronized::Yes;
};
} // namespace openspace::interaction
#endif // __OPENSPACE_CORE___ACTION___H__

View File

@@ -22,39 +22,34 @@
* OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. *
****************************************************************************************/
#ifndef __OPENSPACE_CORE___SHORTCUTMANAGER___H__
#define __OPENSPACE_CORE___SHORTCUTMANAGER___H__
#ifndef __OPENSPACE_CORE___ACTIONMANAGER___H__
#define __OPENSPACE_CORE___ACTIONMANAGER___H__
#include <ghoul/misc/boolean.h>
#include <string>
#include <vector>
#include <openspace/interaction/action.h>
#include <unordered_map>
namespace ghoul { class Dictionary; }
namespace openspace::scripting { struct LuaLibrary; }
namespace openspace::interaction {
class ShortcutManager {
class ActionManager {
public:
BooleanType(IsSynchronized);
bool hasAction(const std::string& identifier) const;
void registerAction(Action action);
void removeAction(const std::string& identifier);
const Action& action(const std::string& identifier) const;
std::vector<Action> actions() const;
struct ShortcutInformation {
std::string name;
std::string script;
IsSynchronized synchronization;
std::string documentation;
std::string guiPath;
};
void resetShortcuts();
void addShortcut(ShortcutInformation info);
const std::vector<ShortcutInformation>& shortcuts() const;
void triggerAction(const std::string& identifier,
const ghoul::Dictionary& arguments) const;
static scripting::LuaLibrary luaLibrary();
private:
std::vector<ShortcutInformation> _shortcuts;
std::unordered_map<unsigned int, Action> _actions;
};
} // namespace openspace::interaction
#endif // __OPENSPACE_CORE___SHORTCUTMANAGER___H__
#endif // __OPENSPACE_CORE___ACTIONMANAGER___H__

View File

@@ -58,6 +58,12 @@ public:
void resetVelocities();
/*
* Returns true if any of the velocities are larger than zero,
* i.e. wether an interaction happened
*/
bool hasNonZeroVelocities();
protected:
struct InteractionState {
InteractionState(double scaleFactor);

View File

@@ -28,6 +28,7 @@
#include <ghoul/misc/assert.h>
#include <ghoul/misc/exception.h>
#include <ghoul/misc/stringconversion.h>
#include <ghoul/fmt.h>
#include <array>
#include <memory>
#include <string>
@@ -126,18 +127,18 @@ inline std::string to_string(const openspace::interaction::JoystickAction& value
case openspace::interaction::JoystickAction::Press: return "Press";
case openspace::interaction::JoystickAction::Repeat: return "Repeat";
case openspace::interaction::JoystickAction::Release: return "Release";
default: throw MissingCaseException();
default: throw MissingCaseException();
}
}
template <>
constexpr openspace::interaction::JoystickAction from_string(std::string_view string) {
if (string == "Idle") { return openspace::interaction::JoystickAction::Idle; }
if (string == "Press") { return openspace::interaction::JoystickAction::Press; }
if (string == "Repeat") { return openspace::interaction::JoystickAction::Repeat; }
if (string == "Idle") { return openspace::interaction::JoystickAction::Idle; }
if (string == "Press") { return openspace::interaction::JoystickAction::Press; }
if (string == "Repeat") { return openspace::interaction::JoystickAction::Repeat; }
if (string == "Release") { return openspace::interaction::JoystickAction::Release; }
throw RuntimeError("Unknown action '" + std::string(string) + "'");
throw RuntimeError(fmt::format("Unknown action '{}'", string));
}
} // namespace ghoul

View File

@@ -28,7 +28,6 @@
#include <openspace/documentation/documentationgenerator.h>
#include <openspace/util/keys.h>
#include <ghoul/misc/boolean.h>
namespace openspace {
class Camera;
@@ -41,33 +40,15 @@ namespace openspace::interaction {
class KeybindingManager : public DocumentationGenerator {
public:
BooleanType(IsSynchronized);
struct KeyInformation {
std::string command;
IsSynchronized synchronization;
std::string documentation;
std::string name;
std::string guiPath;
};
KeybindingManager();
void resetKeyBindings();
void bindKeyLocal(Key key, KeyModifier modifier, std::string luaCommand,
std::string documentation = "", std::string name = "", std::string guiPath = "");
void bindKey(Key key, KeyModifier modifier, std::string action);
void bindKey(Key key, KeyModifier modifier, std::string luaCommand,
std::string documentation = "", std::string name = "", std::string guiPath = "");
void removeKeyBinding(const std::string& key);
void removeKeyBinding(const KeyWithModifier& key);
std::vector<std::pair<KeyWithModifier, KeyInformation>> keyBinding(
const std::string& key) const;
std::vector<std::pair<KeyWithModifier, KeyInformation>> keyBinding(
std::vector<std::pair<KeyWithModifier, std::string>> keyBinding(
const KeyWithModifier& key) const;
static scripting::LuaLibrary luaLibrary();
@@ -76,10 +57,10 @@ public:
std::string generateJson() const override;
const std::multimap<KeyWithModifier, KeyInformation>& keyBindings() const;
const std::multimap<KeyWithModifier, std::string>& keyBindings() const;
private:
std::multimap<KeyWithModifier, KeyInformation> _keyLua;
std::multimap<KeyWithModifier, std::string> _keyLua;
};
} // namespace openspace::interaction

View File

@@ -26,7 +26,7 @@
#define __OPENSPACE_CORE___SESSIONRECORDING___H__
#include <openspace/interaction/externinteraction.h>
#include <openspace/interaction/keyframenavigator.h>
#include <openspace/navigation/keyframenavigator.h>
#include <openspace/properties/scalar/boolproperty.h>
#include <openspace/scripting/lualibrary.h>
#include <vector>

View File

@@ -25,8 +25,8 @@
#ifndef __OPENSPACE_CORE___KEYFRAMENAVIGATOR___H__
#define __OPENSPACE_CORE___KEYFRAMENAVIGATOR___H__
#include <openspace/util/timeline.h>
#include <openspace/network/messagestructures.h>
#include <openspace/util/timeline.h>
#include <ghoul/glm.h>
#include <ghoul/misc/boolean.h>
#include <glm/gtx/quaternion.hpp>

View File

@@ -28,10 +28,12 @@
#include <openspace/documentation/documentation.h>
#include <openspace/interaction/inputstate.h>
#include <openspace/interaction/joystickcamerastates.h>
#include <openspace/interaction/orbitalnavigator.h>
#include <openspace/interaction/keyframenavigator.h>
#include <openspace/properties/propertyowner.h>
#include <openspace/interaction/websocketcamerastates.h>
#include <openspace/navigation/keyframenavigator.h>
#include <openspace/navigation/navigationstate.h>
#include <openspace/navigation/orbitalnavigator.h>
#include <openspace/navigation/pathnavigator.h>
#include <openspace/properties/propertyowner.h>
#include <openspace/properties/stringproperty.h>
#include <openspace/properties/scalar/boolproperty.h>
#include <openspace/util/mouse.h>
@@ -48,31 +50,14 @@ namespace openspace::scripting { struct LuaLibrary; }
namespace openspace::interaction {
struct JoystickInputStates;
struct NavigationState;
struct WebsocketInputStates;
class KeyframeNavigator;
class OrbitalNavigator;
class PathNavigator;
class NavigationHandler : public properties::PropertyOwner {
public:
struct NavigationState {
NavigationState() = default;
NavigationState(const ghoul::Dictionary& dictionary);
NavigationState(std::string anchor, std::string aim, std::string referenceFrame,
glm::dvec3 position, std::optional<glm::dvec3> up = std::nullopt,
double yaw = 0.0, double pitch = 0.0);
ghoul::Dictionary dictionary() const;
static documentation::Documentation Documentation();
std::string anchor;
std::string aim;
std::string referenceFrame;
glm::dvec3 position = glm::dvec3(0.0);
std::optional<glm::dvec3> up;
double yaw = 0.0;
double pitch = 0.0;
};
NavigationHandler();
~NavigationHandler();
@@ -80,11 +65,9 @@ public:
void deinitialize();
// Mutators
void setFocusNode(SceneGraphNode* node);
void resetCameraDirection();
void setNavigationStateNextFame(NavigationState state);
void setCamera(Camera* camera);
void setInterpolationTime(float durationInSeconds);
@@ -101,6 +84,7 @@ public:
const OrbitalNavigator& orbitalNavigator() const;
OrbitalNavigator& orbitalNavigator();
KeyframeNavigator& keyframeNavigator();
PathNavigator& pathNavigator();
bool isKeyFrameInteractionEnabled() const;
float interpolationTime() const;
@@ -154,7 +138,7 @@ public:
static scripting::LuaLibrary luaLibrary();
private:
void applyNavigationState(const NavigationHandler::NavigationState& ns);
void applyNavigationState(const NavigationState& ns);
bool _playbackModeEnabled = false;
@@ -164,6 +148,7 @@ private:
OrbitalNavigator _orbitalNavigator;
KeyframeNavigator _keyframeNavigator;
PathNavigator _pathNavigator;
std::optional<NavigationState> _pendingNavigationState;

View File

@@ -0,0 +1,59 @@
/*****************************************************************************************
* *
* OpenSpace *
* *
* Copyright (c) 2014-2021 *
* *
* Permission is hereby granted, free of charge, to any person obtaining a copy of this *
* software and associated documentation files (the "Software"), to deal in the Software *
* without restriction, including without limitation the rights to use, copy, modify, *
* merge, publish, distribute, sublicense, and/or sell copies of the Software, and to *
* permit persons to whom the Software is furnished to do so, subject to the following *
* conditions: *
* *
* The above copyright notice and this permission notice shall be included in all copies *
* or substantial portions of the Software. *
* *
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, *
* INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A *
* PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT *
* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF *
* CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE *
* OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. *
****************************************************************************************/
#ifndef __OPENSPACE_CORE___NAVIGATIONSTATE___H__
#define __OPENSPACE_CORE___NAVIGATIONSTATE___H__
#include <openspace/documentation/documentation.h>
#include <optional>
namespace openspace {
struct CameraPose;
} // namespace openspace
namespace openspace::interaction {
struct NavigationState {
NavigationState() = default;
explicit NavigationState(const ghoul::Dictionary& dictionary);
NavigationState(std::string anchor, std::string aim, std::string referenceFrame,
glm::dvec3 position, std::optional<glm::dvec3> up = std::nullopt,
double yaw = 0.0, double pitch = 0.0);
CameraPose cameraPose() const;
ghoul::Dictionary dictionary() const;
static documentation::Documentation Documentation();
std::string anchor;
std::string aim;
std::string referenceFrame;
glm::dvec3 position = glm::dvec3(0.0);
std::optional<glm::dvec3> up;
double yaw = 0.0;
double pitch = 0.0;
};
} // namespace openspace::interaction
#endif // __OPENSPACE_CORE___NAVIGATIONSTATE___H__

View File

@@ -33,6 +33,7 @@
#include <openspace/interaction/mousecamerastates.h>
#include <openspace/interaction/scriptcamerastates.h>
#include <openspace/interaction/websocketcamerastates.h>
#include <openspace/properties/optionproperty.h>
#include <openspace/properties/stringproperty.h>
#include <openspace/properties/scalar/boolproperty.h>
#include <openspace/properties/scalar/floatproperty.h>
@@ -46,6 +47,7 @@
namespace openspace {
class SceneGraphNode;
class Camera;
struct CameraPose;
struct SurfacePositionHandle;
} // namespace
@@ -59,8 +61,16 @@ public:
void updateStatesFromInput(const InputState& inputState, double deltaTime);
void updateCameraStateFromStates(double deltaTime);
void updateCameraScalingFromAnchor(double deltaTime);
void resetVelocities();
/*
* This function should be called on every camera interaction: for example when
* navigating using an input device, changing the focus node or starting a path or
* a session recording playback
*/
void updateOnCameraInteraction();
Camera* camera() const;
void setCamera(Camera* camera);
void clearPreviousState();
@@ -104,11 +114,6 @@ private:
glm::dquat globalRotation = glm::dquat(1.0, 0.0, 0.0, 0.0);
};
struct CameraPose {
glm::dvec3 position = glm::dvec3(0.0);
glm::dquat rotation = glm::dquat(1.0, 0.0, 0.0, 0.0);
};
using Displacement = std::pair<glm::dvec3, glm::dvec3>;
struct Friction : public properties::PropertyOwner {
@@ -129,12 +134,12 @@ private:
Friction _friction;
// Anchor: Node to follow and orbit.
// Anchor: Node to follow and orbit
properties::StringProperty _anchor;
// Aim: Node to look at (when camera direction is reset),
// Empty string means same as anchor.
// If these are the same node we call it the `focus` node.
// If these are the same node we call it the `focus` node
properties::StringProperty _aim;
// Reset camera direction to the anchor node.
@@ -144,11 +149,17 @@ private:
properties::FloatProperty _followAnchorNodeRotationDistance;
properties::FloatProperty _minimumAllowedDistance;
properties::FloatProperty _flightDestinationDistance;
properties::DoubleProperty _flightDestinationFactor;
properties::BoolProperty _applyLinearFlight;
properties::FloatProperty _velocitySensitivity;
struct LinearFlight : public properties::PropertyOwner {
LinearFlight();
properties::BoolProperty apply;
properties::FloatProperty destinationDistance;
properties::DoubleProperty destinationFactor;
properties::FloatProperty velocitySensitivity;
};
LinearFlight _linearFlight;
properties::FloatProperty _mouseSensitivity;
properties::FloatProperty _joystickSensitivity;
properties::FloatProperty _websocketSensitivity;
@@ -182,6 +193,25 @@ private:
Interpolator<double> _retargetAnchorInterpolator;
Interpolator<double> _cameraToSurfaceDistanceInterpolator;
Interpolator<double> _followRotationInterpolator;
Interpolator<double> _idleBehaviorDampenInterpolator;
bool _invertIdleBehaviorInterpolation = false;
struct IdleBehavior : public properties::PropertyOwner {
enum Behavior {
Orbit = 0,
OrbitAtConstantLat,
OrbitAroundUp
};
IdleBehavior();
properties::BoolProperty apply;
properties::OptionProperty chosenBehavior;
properties::FloatProperty speedScale;
properties::BoolProperty abortOnCameraInteraction;
properties::FloatProperty dampenInterpolationTime;
};
IdleBehavior _idleBehavior;
/**
* Decomposes the camera's rotation in to a global and a local rotation defined by
@@ -197,7 +227,7 @@ private:
/**
* Decomposes the camera's rotation in to a global and a local rotation defined by
* CameraRotationDecomposition. The global rotation defines the rotation so that the
* camera points towards the reference node's origin.
* camera points towards the reference position.
* The local rotation defines the differential from the global to the current total
* rotation so that <code>cameraRotation = globalRotation * localRotation</code>.
*/
@@ -318,7 +348,7 @@ private:
/**
* Interpolates between rotationDiff and a 0 rotation.
*/
glm::dquat interpolateRotationDifferential(double deltaTime, double interpolationTime,
glm::dquat interpolateRotationDifferential(double deltaTime,
const glm::dvec3 cameraPosition, const glm::dquat& rotationDiff);
/**
@@ -332,6 +362,45 @@ private:
*/
SurfacePositionHandle calculateSurfacePositionHandle(const SceneGraphNode& node,
const glm::dvec3 cameraPositionWorldSpace);
/**
* Apply the currently selected idle behavior to the position and rotations
*/
void applyIdleBehavior(double deltaTime, glm::dvec3& position,
glm::dquat& localRotation, glm::dquat& globalRotation);
/**
* Orbit the current anchor node, in a right-bound orbit, by updating the position
* and global rotation of the camera.
*
* Used for IdleBehavior::Behavior::Orbit
*
* \param deltaTime The time step to use for the motion. Controls the rotation angle
* \param position The position of the camera. Will be changed by the function
* \param globalRotation The camera's global rotation. Will be changed by the function
* \param speedScale A speed scale that controls the speed of the motion
*/
void orbitAnchor(double deltaTime, glm::dvec3& position,
glm::dquat& globalRotation, double speedScale);
/**
* Orbit the current anchor node, by adding a rotation around the given axis. For
* example, when the axis is the north vector, the camera will stay on the current
* latitude band. Note that this creates a rolling motion if the camera's forward
* vector coincides with the axis, and should be used with care.
*
* Used for:
* IdleBehavior::Behavior::OrbitAtConstantLat ( axis = north = z-axis ) and
* IdleBehavior::Behavior::OrbitAroundUp ( axis = up = y-axis )
*
* \param axis The axis to arbit around, given in model coordinates of the anchor
* \param deltaTime The time step to use for the motion. Controls the rotation angle
* \param position The position of the camera. Will be changed by the function
* \param globalRotation The camera's global rotation. Will be changed by the function
* \param speedScale A speed scale that controls the speed of the motion
*/
void orbitAroundAxis(const glm::dvec3 axis, double deltaTime, glm::dvec3& position,
glm::dquat& globalRotation, double speedScale);
};
} // namespace openspace::interaction

View File

@@ -0,0 +1,144 @@
/*****************************************************************************************
* *
* OpenSpace *
* *
* Copyright (c) 2014-2021 *
* *
* Permission is hereby granted, free of charge, to any person obtaining a copy of this *
* software and associated documentation files (the "Software"), to deal in the Software *
* without restriction, including without limitation the rights to use, copy, modify, *
* merge, publish, distribute, sublicense, and/or sell copies of the Software, and to *
* permit persons to whom the Software is furnished to do so, subject to the following *
* conditions: *
* *
* The above copyright notice and this permission notice shall be included in all copies *
* or substantial portions of the Software. *
* *
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, *
* INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A *
* PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT *
* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF *
* CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE *
* OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. *
****************************************************************************************/
#ifndef __OPENSPACE_CORE___PATH___H__
#define __OPENSPACE_CORE___PATH___H__
#include <openspace/navigation/pathcurve.h>
#include <openspace/navigation/waypoint.h>
#include <ghoul/misc/dictionary.h>
#include <optional>
#include <vector>
namespace openspace {
struct CameraPose;
} // namespace openspace
namespace openspace::interaction {
class Path {
public:
enum Type {
AvoidCollision,
Linear,
ZoomOutOverview,
AvoidCollisionWithLookAt // @TODO (2021-08-13, emmbr) This type right now leads
// to rapid rotations, but is useful in specific
// scenarios, e.g. close to surfaces. Later we want to
// remove it, and create a curve type that looks nicely
// at the targets when moving, avoids collisions and
// doesn't introduce sudden large changes in rotation
};
Path(Waypoint start, Waypoint end, Type type,
std::optional<double> duration = std::nullopt);
Waypoint startPoint() const;
Waypoint endPoint() const;
/**
* Return the total length of the the curve for the path, in meters
*/
double pathLength() const;
/**
* Return a vector of positions corresponding to the control points of the path's
* spline curve
*/
std::vector<glm::dvec3> controlPoints() const;
/**
* Take a step along the current path, corresponding to the delta time step \p dt, and
* return the resulting camera pose. The \p speedScale is a factor that will be
* multiplied with the traversal speed
*/
CameraPose traversePath(double dt, float speedScale = 1.f);
/**
* Return the identifer of the node that is the current appropriate anchor node, of
* the start and end waypoint's reference node. Dtermined based on how far along the
* path we have traveled
*/
std::string currentAnchor() const;
/**
* Return wether the path has reached its end point or not
*/
bool hasReachedEnd() const;
/**
* Compute the interpolated camera pose at a certain distance along the path
*/
CameraPose interpolatedPose(double distance) const;
private:
/**
* Interpolate between the paths start and end rotation using the approach that
* corresponds to the path's curve type. The interpolation parameter \p t is the
* same as for the position interpolation, i.e. the relative traveled in distance
* along the path, in [0, 1]
*/
glm::dquat interpolateRotation(double t) const;
/**
* Compute the interpolated rotation quaternion using an eased SLERP approach
*/
glm::dquat easedSlerpRotation(double t) const;
/**
* Compute the interpolated rotation quaternion using an approach that first
* interpolates to look at the start node, and then the end node, before
* interpolating to the end rotation
*/
glm::dquat lookAtTargetsRotation(double t) const;
/**
* Evaluate the current traversal speed along the path, based on the currently
* traveled distance. The final speed will be scaled to match the desired duration
* for the path (which might have been specified by the user)
*/
double speedAlongPath(double traveledDistance) const;
Waypoint _start;
Waypoint _end;
Type _type;
std::unique_ptr<PathCurve> _curve;
double _speedFactorFromDuration = 1.0;
// Playback variables
double _traveledDistance = 0.0;
double _progressedTime = 0.0; // Time since playback started
};
// Create a path of the given type based on an instruction given as a dictionary.
// See top of cpp file for documentation on keys and values for the dictionary.
// Returns the created path.
Path createPathFromDictionary(const ghoul::Dictionary& dictionary, Path::Type type);
} // namespace openspace::interaction
#endif // __OPENSPACE_CORE___PATH___H__

View File

@@ -0,0 +1,101 @@
/*****************************************************************************************
* *
* OpenSpace *
* *
* Copyright (c) 2014-2021 *
* *
* Permission is hereby granted, free of charge, to any person obtaining a copy of this *
* software and associated documentation files (the "Software"), to deal in the Software *
* without restriction, including without limitation the rights to use, copy, modify, *
* merge, publish, distribute, sublicense, and/or sell copies of the Software, and to *
* permit persons to whom the Software is furnished to do so, subject to the following *
* conditions: *
* *
* The above copyright notice and this permission notice shall be included in all copies *
* or substantial portions of the Software. *
* *
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, *
* INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A *
* PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT *
* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF *
* CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE *
* OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. *
****************************************************************************************/
#ifndef __OPENSPACE_CORE___PATHCURVE___H__
#define __OPENSPACE_CORE___PATHCURVE___H__
#include <ghoul/glm.h>
#include <vector>
namespace openspace::interaction {
class Waypoint;
class PathCurve {
public:
virtual ~PathCurve() = 0;
double length() const;
/**
* Compute and return the position along the path at the specified relative
* distance. The input parameter should be in range [0, 1], where 1 correspond to
* the full length of the path
*/
glm::dvec3 positionAt(double relativeDistance) const;
/**
* Get the intorlatied position along the spline, based on the given curve parameter
* u in range [0, 1]. A curve parameter of 0 returns the start position and 1 the end
* position. Note that u does not correspond to the relatively traveled distance.
*/
virtual glm::dvec3 interpolate(double u) const;
/**
* Return the positions defining the control points for the spline interpolation
*/
std::vector<glm::dvec3> points() const;
protected:
/**
* Precompute information related to the spline parameters, that are
* needed for arc length reparameterization. Must be called after
* control point creation
*/
void initializeParameterData();
/**
* Compute curve parameter u that matches the input arc length s.
* Input s is a length value, in the range [0, _totalLength]. The returned curve
* parameter u is in range [0, 1]
*/
double curveParameter(double s) const;
double approximatedDerivative(double u, double h = 0.0001) const;
double arcLength(double limit = 1.0) const;
double arcLength(double lowerLimit, double upperLimit) const;
std::vector<glm::dvec3> _points;
unsigned int _nSegments = 0;
std::vector<double> _curveParameterSteps; // per segment
std::vector<double> _lengthSums; // per segment
double _totalLength = 0.0;
struct ParameterPair {
double u; // curve parameter
double s; // arc length parameter
};
std::vector<ParameterPair> _parameterSamples;
};
class LinearCurve : public PathCurve {
public:
LinearCurve(const Waypoint& start, const Waypoint& end);
};
} // namespace openspace::interaction
#endif // __OPENSPACE_CORE___PATHCURVE___H__

View File

@@ -0,0 +1,48 @@
/*****************************************************************************************
* *
* OpenSpace *
* *
* Copyright (c) 2014-2021 *
* *
* Permission is hereby granted, free of charge, to any person obtaining a copy of this *
* software and associated documentation files (the "Software"), to deal in the Software *
* without restriction, including without limitation the rights to use, copy, modify, *
* merge, publish, distribute, sublicense, and/or sell copies of the Software, and to *
* permit persons to whom the Software is furnished to do so, subject to the following *
* conditions: *
* *
* The above copyright notice and this permission notice shall be included in all copies *
* or substantial portions of the Software. *
* *
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, *
* INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A *
* PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT *
* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF *
* CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE *
* OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. *
****************************************************************************************/
#ifndef __OPENSPACE_CORE___AVOIDCOLLISIONCURVE___H__
#define __OPENSPACE_CORE___AVOIDCOLLISIONCURVE___H__
#include <openspace/navigation/pathcurve.h>
namespace openspace { class SceneGraphNode; }
namespace openspace::interaction {
class WayPoint;
class AvoidCollisionCurve : public PathCurve {
public:
AvoidCollisionCurve(const Waypoint& start, const Waypoint& end);
private:
void removeCollisions(int step = 0);
std::vector<SceneGraphNode*> _relevantNodes;
};
} // namespace openspace::interaction
#endif // __OPENSPACE_MODULE_AUTONAVIGATION___AVOIDCOLLISIONCURVE___H__

View File

@@ -0,0 +1,41 @@
/*****************************************************************************************
* *
* OpenSpace *
* *
* Copyright (c) 2014-2021 *
* *
* Permission is hereby granted, free of charge, to any person obtaining a copy of this *
* software and associated documentation files (the "Software"), to deal in the Software *
* without restriction, including without limitation the rights to use, copy, modify, *
* merge, publish, distribute, sublicense, and/or sell copies of the Software, and to *
* permit persons to whom the Software is furnished to do so, subject to the following *
* conditions: *
* *
* The above copyright notice and this permission notice shall be included in all copies *
* or substantial portions of the Software. *
* *
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, *
* INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A *
* PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT *
* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF *
* CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE *
* OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. *
****************************************************************************************/
#ifndef __OPENSPACE_CORE___ZOOMOUTOVERVIEWCURVE___H__
#define __OPENSPACE_CORE___ZOOMOUTOVERVIEWCURVE___H__
#include <openspace/navigation/pathcurve.h>
namespace openspace::interaction {
class WayPoint;
class ZoomOutOverviewCurve : public PathCurve {
public:
ZoomOutOverviewCurve(const Waypoint& start, const Waypoint& end);
};
} // namespace openspace::interaction
#endif // __OPENSPACE_CORE___ZOOMOUTOVERVIEWCURVE___H__

View File

@@ -0,0 +1,107 @@
/*****************************************************************************************
* *
* OpenSpace *
* *
* Copyright (c) 2014-2021 *
* *
* Permission is hereby granted, free of charge, to any person obtaining a copy of this *
* software and associated documentation files (the "Software"), to deal in the Software *
* without restriction, including without limitation the rights to use, copy, modify, *
* merge, publish, distribute, sublicense, and/or sell copies of the Software, and to *
* permit persons to whom the Software is furnished to do so, subject to the following *
* conditions: *
* *
* The above copyright notice and this permission notice shall be included in all copies *
* or substantial portions of the Software. *
* *
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, *
* INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A *
* PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT *
* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF *
* CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE *
* OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. *
****************************************************************************************/
#ifndef __OPENSPACE_CORE___PATHNAVIGATOR___H__
#define __OPENSPACE_CORE___PATHNAVIGATOR___H__
#include <openspace/properties/propertyowner.h>
#include <openspace/navigation/path.h>
#include <openspace/properties/list/stringlistproperty.h>
#include <openspace/properties/optionproperty.h>
#include <openspace/properties/scalar/boolproperty.h>
#include <openspace/properties/scalar/doubleproperty.h>
#include <openspace/properties/scalar/floatproperty.h>
#include <ghoul/glm.h>
#include <memory>
namespace openspace {
class Camera;
struct CameraPose;
class SceneGraphNode;
} // namespace openspace
namespace openspace::scripting { struct LuaLibrary; }
namespace openspace::interaction {
class Path;
class PathNavigator : public properties::PropertyOwner {
public:
PathNavigator();
~PathNavigator();
// Accessors
Camera* camera() const;
const SceneGraphNode* anchor() const;
const Path* currentPath() const;
double speedScale() const;
bool hasCurrentPath() const;
bool hasFinished() const;
bool isPlayingPath() const;
void updateCamera(double deltaTime);
void createPath(const ghoul::Dictionary& dictionary);
void clearPath();
void startPath();
void abortPath();
void pausePath();
void continuePath();
double minValidBoundingSphere() const;
const std::vector<SceneGraphNode*>& relevantNodes();
/**
* \return The Lua library that contains all Lua functions available to affect the
* path navigation
*/
static scripting::LuaLibrary luaLibrary();
private:
/**
* Populate list of nodes that are relevant for collision checks, etc
*/
void findRelevantNodes();
void removeRollRotation(CameraPose& pose, double deltaTime);
std::unique_ptr<Path> _currentPath = nullptr;
bool _isPlaying = false;
properties::OptionProperty _defaultPathType;
properties::BoolProperty _includeRoll;
properties::FloatProperty _speedScale;
properties::BoolProperty _applyIdleBehaviorOnFinish;
properties::DoubleProperty _minValidBoundingSphere;
properties::StringListProperty _relevantNodeTags;
std::vector<SceneGraphNode*> _relevantNodes;
bool _hasInitializedRelevantNodes = false;
};
} // namespace openspace::interaction
#endif // __OPENSPACE_CORE___PATHNAVIGATOR___H__

View File

@@ -22,66 +22,40 @@
* OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. *
****************************************************************************************/
#include <openspace/interaction/shortcutmanager.h>
#ifndef __OPENSPACE_CORE___WAYPOINT___H__
#define __OPENSPACE_CORE___WAYPOINT___H__
#include <openspace/engine/globals.h>
#include <openspace/scripting/lualibrary.h>
#include <openspace/scripting/scriptengine.h>
#include <openspace/camera/camerapose.h>
#include <ghoul/glm.h>
#include <sstream>
#include <string>
#include "shortcutmanager_lua.inl"
namespace openspace { class SceneGraphNode; }
namespace openspace::interaction {
void ShortcutManager::resetShortcuts() {
_shortcuts.clear();
}
struct NavigationState;
void ShortcutManager::addShortcut(ShortcutInformation info) {
_shortcuts.push_back(std::move(info));
}
class Waypoint {
public:
Waypoint() = default;
Waypoint(const glm::dvec3& pos, const glm::dquat& rot, const std::string& ref);
explicit Waypoint(const NavigationState& ns);
const std::vector<ShortcutManager::ShortcutInformation>&
ShortcutManager::shortcuts() const
{
return _shortcuts;
}
static double findValidBoundingSphere(const SceneGraphNode* node);
scripting::LuaLibrary ShortcutManager::luaLibrary() {
return {
"",
{
{
"clearShortcuts",
&luascriptfunctions::clearShortcuts,
{},
"",
"Clear all shortcuts in this scene"
},
{
"bindShortcut",
&luascriptfunctions::bindShortcut,
{},
"string, string [, string]",
"Binds a Lua script to a new shortcut that is executed both locally and "
"to be broadcast to clients if this is the host of a parallel session. "
"The first argument is a human-readable name for this shortcut, the "
"second argument is the Lua script that will be executed and the last "
"argument is a describtive text for the shortcut for tooltips, etc."
},
{
"bindShortcutLocal",
&luascriptfunctions::bindShortcutLocal,
{},
"string, string [, string]",
"Binds a Lua script to a new shortcut that is executed onlylocally. The "
"first argument is a human-readable name for this shortcut, the second "
"argument is the Lua script that will be executed and the last argument "
"is a describtive text for the shortcut for tooltips, etc."
}
}
};
}
CameraPose pose() const;
glm::dvec3 position() const;
glm::dquat rotation() const;
SceneGraphNode* node() const;
std::string nodeIdentifier() const;
double validBoundingSphere() const;
private:
CameraPose _pose;
std::string _nodeIdentifier;
double _validBoundingSphere = 0.0; // to be able to handle nodes with faulty bounding spheres
};
} // namespace openspace::interaction
#endif // __OPENSPACE_CORE___WAYPOINT___H__

View File

@@ -87,7 +87,7 @@ public:
*
* \param value The value that is used to set this Property
*/
virtual void set(std::any value) override;
virtual void set(std::any value) final;
/**
* Returns the <code>std::type_info</code> describing the template parameter

View File

@@ -94,9 +94,9 @@ public:
virtual void updateRendererData();
virtual void raycastersChanged(VolumeRaycaster& raycaster,
RaycasterListener::IsAttached attached);
RaycasterListener::IsAttached attached) override;
virtual void deferredcastersChanged(Deferredcaster& deferredcaster,
DeferredcasterListener::IsAttached isAttached);
DeferredcasterListener::IsAttached isAttached) override;
private:
using RaycasterProgObjMap = std::map<

View File

@@ -32,6 +32,7 @@
#include <openspace/properties/scalar/intproperty.h>
#include <openspace/properties/scalar/floatproperty.h>
#include <openspace/properties/vector/vec3property.h>
#include <openspace/properties/vector/vec4property.h>
#include <openspace/properties/triggerproperty.h>
#include <openspace/rendering/framebufferrenderer.h>
#include <chrono>
@@ -219,6 +220,9 @@ private:
} _cameraButtonLocations;
std::string _versionString;
properties::Vec4Property _enabledFontColor;
properties::Vec4Property _disabledFontColor;
};
} // namespace openspace

View File

@@ -26,9 +26,9 @@
#define __OPENSPACE_CORE___PROFILE___H__
#include <openspace/engine/globals.h>
#include <openspace/interaction/navigationhandler.h>
#include <openspace/properties/propertyowner.h>
#include <openspace/util/keys.h>
#include <ghoul/glm.h>
#include <ghoul/misc/exception.h>
#include <optional>
#include <string>
@@ -37,6 +37,8 @@
namespace openspace {
namespace interaction { struct NavigationState; }
namespace scripting { struct LuaLibrary; }
class Profile {
@@ -77,15 +79,20 @@ public:
SetType setType;
std::string name;
std::string value;
};
struct Keybinding {
KeyWithModifier key;
struct Action {
std::string identifier;
std::string documentation;
std::string name;
std::string guiPath;
bool isLocal;
std::string script;
};
struct Keybinding {
KeyWithModifier key;
std::string action;
};
struct Time {
enum class Type {
Absolute,
@@ -120,56 +127,36 @@ public:
explicit Profile(const std::string& content);
std::string serialize() const;
std::string convertToScene() const;
/**
* Saves all current settings, starting from the profile that was loaded at startup,
* and all of the property & asset changes that were made since startup.
*/
void saveCurrentSettingsToProfile(const properties::PropertyOwner& rootOwner,
std::string currentTime,
interaction::NavigationHandler::NavigationState navState);
std::string currentTime, interaction::NavigationState navState);
/// If the value passed to this function is 'true', the addAsset and removeAsset
/// functions will be no-ops instead
void setIgnoreUpdates(bool ignoreUpdates);
/// Adds a new asset and checks for duplicates
/// Adds a new asset and checks for duplicates unless the `ignoreUpdates` member is
/// set to `true`
void addAsset(const std::string& path);
/// Removes an asset
/// Removes an asset unless the `ignoreUpdates` member is set to `true`
void removeAsset(const std::string& path);
/// Removes all assets
void clearAssets();
static constexpr const Version CurrentVersion = Version{ 1, 1 };
Version version() const;
std::vector<Module> modules() const;
std::optional<Meta> meta() const;
std::vector<std::string> assets() const;
std::vector<Property> properties() const;
std::vector<Keybinding> keybindings() const;
std::optional<Time> time() const;
std::vector<double> deltaTimes() const;
std::optional<CameraType> camera() const;
std::vector<std::string> markNodes() const;
std::vector<std::string> additionalScripts() const;
void clearMeta();
void clearTime();
void clearCamera();
void setVersion(Version v);
void setModules(std::vector<Module>& m);
void setMeta(Meta m);
void setProperties(std::vector<Property>& p);
void setKeybindings(std::vector<Keybinding>& k);
void setTime(Time t);
void setDeltaTimes(std::vector<double> dt);
void setCamera(CameraType c);
void setMarkNodes(std::vector<std::string>& n);
void setAdditionalScripts(std::vector<std::string>& s);
Version version = CurrentVersion;
std::vector<Module> modules;
std::optional<Meta> meta;
std::vector<std::string> assets;
std::vector<Property> properties;
std::vector<Action> actions;
std::vector<Keybinding> keybindings;
std::optional<Time> time;
std::vector<double> deltaTimes;
std::optional<CameraType> camera;
std::vector<std::string> markNodes;
std::vector<std::string> additionalScripts;
bool ignoreUpdates = false;
/**
* Returns the Lua library that contains all Lua functions available to provide
@@ -177,25 +164,21 @@ public:
* \return The Lua library that contains all Lua functions available for profiles
*/
static scripting::LuaLibrary luaLibrary();
private:
static constexpr const Version CurrentVersion = Version { 1, 0 };
Version _version = CurrentVersion;
std::vector<Module> _modules;
std::optional<Meta> _meta;
std::vector<std::string> _assets;
std::vector<Property> _properties;
std::vector<Keybinding> _keybindings;
std::optional<Time> _time;
std::vector<double> _deltaTimes;
std::optional<CameraType> _camera;
std::vector<std::string> _markNodes;
std::vector<std::string> _additionalScripts;
bool _ignoreUpdates = false;
};
/**
* This function takes a profile and returns its asset-ifyied version as a string. This
* is the format that is saved as a scene file that, in turn, is provided to OpenSpace as
* the root asset to load. This function is a key step to be able to load a Profile in
* OpenSpace (at the moment).
*
* \param profile The profile that should be converted to the asset-file format
*
* \return The string representation of the provided profile, ready to be loaded as an
* asset
*/
std::string convertToScene(const Profile& profile);
} // namespace openspace
#endif // __OPENSPACE_CORE___PROFILE___H__

View File

@@ -41,7 +41,7 @@ public:
virtual bool isInitializing() const = 0;
};
class SingleThreadedSceneInitializer : public SceneInitializer {
class SingleThreadedSceneInitializer final : public SceneInitializer {
public:
void initializeNode(SceneGraphNode* node) override;
std::vector<SceneGraphNode*> takeInitializedNodes() override;
@@ -51,7 +51,7 @@ private:
std::vector<SceneGraphNode*> _initializedNodes;
};
class MultiThreadedSceneInitializer : public SceneInitializer {
class MultiThreadedSceneInitializer final : public SceneInitializer {
public:
MultiThreadedSceneInitializer(unsigned int nThreads);

View File

@@ -25,8 +25,8 @@
#ifndef __OPENSPACE_CORE___SCRIPTSCHEDULER___H__
#define __OPENSPACE_CORE___SCRIPTSCHEDULER___H__
#include <openspace/navigation/keyframenavigator.h>
#include <openspace/scripting/lualibrary.h>
#include <openspace/interaction/keyframenavigator.h>
#include <functional>
#include <queue>

View File

@@ -0,0 +1,59 @@
/*****************************************************************************************
* *
* OpenSpace *
* *
* Copyright (c) 2014-2021 *
* *
* Permission is hereby granted, free of charge, to any person obtaining a copy of this *
* software and associated documentation files (the "Software"), to deal in the Software *
* without restriction, including without limitation the rights to use, copy, modify, *
* merge, publish, distribute, sublicense, and/or sell copies of the Software, and to *
* permit persons to whom the Software is furnished to do so, subject to the following *
* conditions: *
* *
* The above copyright notice and this permission notice shall be included in all copies *
* or substantial portions of the Software. *
* *
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, *
* INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A *
* PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT *
* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF *
* CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE *
* OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. *
****************************************************************************************/
#ifndef __OPENSPACE_CORE___COLLISIONHELPER___H__
#define __OPENSPACE_CORE___COLLISIONHELPER___H__
#include <ghoul/glm.h>
namespace openspace::collision {
/*
* Calculate the intersection of a line segment and a sphere.
* The line segment is defined from \p p1 to \p p2.
* The sphere is defined by the radius \p r and center point \p center.
* The resulting intersection point is stored in the \p intersectionPoint parameter.
*
* In the case of two intersection points, only care about the first one.
*
* \param p1 The start point for the line segment
* \param p2 The end point for the line segment
* \param center The center point for the sphere
* \param r The radius of the sphere
* \param intersectionPoint A variable to store the resulting intersection point in
* \return True if the line between \p p1 and \p p2 intersects the sphere given by
* \p r and \p center, and false otherwise
*/
bool lineSphereIntersection(glm::dvec3 p1, glm::dvec3 p2, glm::dvec3 center,
double r, glm::dvec3& intersectionPoint);
/*
* Check if the point \p p is inside of the sphere defined by radius \p r and center
* point \p c
*/
bool isPointInsideSphere(const glm::dvec3& p, const glm::dvec3& c, double r);
} // namespace openspace::collision
#endif // __OPENSPACE_CORE___COLLISIONHELPER___H__

View File

@@ -58,545 +58,366 @@
// definitions GLFW v3.1
#include <ghoul/misc/stringconversion.h>
#include <array>
#include <map>
#include <string>
#include <unordered_map>
namespace openspace {
enum class KeyAction : int {
//////////////////////////////////////////////////////////////////////////////////////////
enum class KeyAction : uint8_t {
Release = 0,
Press = 1,
Repeat = 2
};
bool hasKeyAction(KeyAction lhs, KeyAction rhs);
constexpr bool hasKeyAction(KeyAction lhs, KeyAction rhs) {
return static_cast<std::underlying_type_t<KeyAction>>(lhs) &
static_cast<std::underlying_type_t<KeyAction>>(rhs);
}
KeyAction operator|(KeyAction lhs, KeyAction rhs);
KeyAction operator|=(KeyAction& lhs, KeyAction rhs);
constexpr KeyAction operator|(KeyAction lhs, KeyAction rhs) {
return static_cast<KeyAction>(
static_cast<std::underlying_type_t<KeyAction>>(lhs) |
static_cast<std::underlying_type_t<KeyAction>>(rhs)
);
}
enum class KeyModifier : int {
NoModifier = 0,
Shift = 0x0001,
Control = 0x0002,
Alt = 0x0004,
Super = 0x0008
constexpr KeyAction operator|=(KeyAction& lhs, KeyAction rhs) {
return (lhs | rhs);
}
//////////////////////////////////////////////////////////////////////////////////////////
enum class KeyModifier : uint8_t {
None = 0,
Shift = 0x01,
Control = 0x02,
Alt = 0x04,
Super = 0x08
};
static const std::map<int, std::string> KeyModifierNames = {
{0, ""},
{0x0001, "Shift"},
{0x0002, "Control"},
{0x0004, "Alt"},
{0x0008, "Super"},
{0x0003, "Shift+Control"},
{0x0005, "Shift+Alt"},
{0x0009, "Shift+Super"},
{0x0006, "Control+Alt"},
{0x000A, "Control+Super"},
{0x000C, "Alt+Super"},
{0x0007, "Shift+Control+Alt"},
{0x000B, "Shift+Control+Super"},
{0x000D, "Shift+Alt+Super"},
{0x000E, "Control+Alt+Super"},
{0x000F, "Shift+Control+Alt+Super"}
constexpr KeyModifier operator|(KeyModifier lhs, KeyModifier rhs) {
return static_cast<KeyModifier>(
static_cast<std::underlying_type_t<KeyModifier>>(lhs) |
static_cast<std::underlying_type_t<KeyModifier>>(rhs)
);
}
constexpr KeyModifier operator|=(KeyModifier& lhs, KeyModifier rhs) {
return lhs = (lhs | rhs);
}
struct KeyModifierInfo {
KeyModifier modifier;
std::string_view name;
std::string_view identifier;
};
bool hasKeyModifier(KeyModifier lhs, KeyModifier rhs);
KeyModifier operator|(KeyModifier lhs, KeyModifier rhs);
KeyModifier operator|=(KeyModifier& lhs, KeyModifier rhs);
enum class Key {
Unknown = -1,
Space = 32,
Apostrophe = 39,
Comma = 44,
Minus = 45,
Period = 46,
Slash = 47,
Num0 = 48,
Num1 = 49,
Num2 = 50,
Num3 = 51,
Num4 = 52,
Num5 = 53,
Num6 = 54,
Num7 = 55,
Num8 = 56,
Num9 = 57,
SemiColon = 59,
Equal = 61,
A = 65,
B = 66,
C = 67,
D = 68,
E = 69,
F = 70,
G = 71,
H = 72,
I = 73,
J = 74,
K = 75,
L = 76,
M = 77,
N = 78,
O = 79,
P = 80,
Q = 81,
R = 82,
S = 83,
T = 84,
U = 85,
V = 86,
W = 87,
X = 88,
Y = 89,
Z = 90,
LeftBracket = 91,
BackSlash = 92,
RightBracket = 93,
GraveAccent = 96,
World1 = 161,
World2 = 162,
Escape = 256,
Enter = 257,
Tab = 258,
BackSpace = 259,
Insert = 260,
Delete = 261,
Right = 262,
Left = 263,
Down = 264,
Up = 265,
PageUp = 266,
PageDown = 267,
Home = 268,
End = 269,
CapsLock = 280,
ScrollLock = 281,
NumLock = 282,
PrintScreen = 283,
Pause = 284,
F1 = 290,
F2 = 291,
F3 = 292,
F4 = 293,
F5 = 294,
F6 = 295,
F7 = 296,
F8 = 297,
F9 = 298,
F10 = 299,
F11 = 300,
F12 = 301,
F13 = 302,
F14 = 303,
F15 = 304,
F16 = 305,
F17 = 306,
F18 = 307,
F19 = 308,
F20 = 309,
F21 = 310,
F22 = 311,
F23 = 312,
F24 = 313,
F25 = 314,
Keypad0 = 320,
Keypad1 = 321,
Keypad2 = 322,
Keypad3 = 323,
Keypad4 = 324,
Keypad5 = 325,
Keypad6 = 326,
Keypad7 = 327,
Keypad8 = 328,
Keypad9 = 329,
KeypadDecimal = 330,
KeypadDivide = 331,
KeypadMultiply = 332,
KeypadSubtract = 333,
KeypadAdd = 334,
KeypadEnter = 335,
LeftShift = 340,
LeftControl = 341,
LeftAlt = 342,
LeftSuper = 343,
RightShift = 344,
RightControl = 345,
RightAlt = 346,
RightSuper = 347,
Menu = 348,
Last = Menu
constexpr std::array<KeyModifierInfo, 5> KeyModifierInfos = {
KeyModifierInfo{ KeyModifier::None, "", "" },
KeyModifierInfo{ KeyModifier::Shift, "Shift", "SHIFT" },
KeyModifierInfo{ KeyModifier::Control, "Control", "CTRL" },
KeyModifierInfo{ KeyModifier::Alt, "Alt", "ALT" },
KeyModifierInfo{ KeyModifier::Super, "Super", "SUPER" },
};
static const std::map<int, std::string> KeyNames = {
{32, "Space"},
{39, "'"},
{44, ","},
{45, "-"},
{46, "."},
{47, "/"},
{48, "0"},
{49, "1"},
{50, "2"},
{51, "3"},
{52, "4"},
{53, "5"},
{54, "6"},
{55, "7"},
{56, "8"},
{57, "9"},
{59, ";"},
{61, "="},
{65, "A"},
{66, "B"},
{67, "C"},
{68, "D"},
{69, "E"},
{70, "F"},
{71, "G"},
{72, "H"},
{73, "I"},
{74, "J"},
{75, "K"},
{76, "L"},
{77, "M"},
{78, "N"},
{79, "O"},
{80, "P"},
{81, "Q"},
{82, "R"},
{83, "S"},
{84, "T"},
{85, "U"},
{86, "V"},
{87, "W"},
{88, "X"},
{89, "Y"},
{90, "Z"},
{91, "["},
{92, "\\"},
{93, "]"},
{96, "`"},
{161, "World1"},
{162, "World2"},
{256, "Escape"},
{257, "Enter"},
{258, "Tab"},
{259, "BackSpace"},
{260, "Insert"},
{261, "Delete"},
{262, "Right"},
{263, "Left"},
{264, "Down"},
{265, "Up"},
{266, "PageUp"},
{267, "PageDown"},
{268, "Home"},
{269, "End"},
{280, "CapsLock"},
{281, "ScrollLock"},
{282, "NumLock"},
{283, "PrintScreen"},
{284, "Pause"},
{290, "F1"},
{291, "F2"},
{292, "F3"},
{293, "F4"},
{294, "F5"},
{295, "F6"},
{296, "F7"},
{297, "F8"},
{298, "F9"},
{299, "F10"},
{300, "F11"},
{301, "F12"},
{302, "F13"},
{303, "F14"},
{304, "F15"},
{305, "F16"},
{306, "F17"},
{307, "F18"},
{308, "F19"},
{309, "F20"},
{310, "F21"},
{311, "F22"},
{312, "F23"},
{313, "F24"},
{314, "F25"},
{320, "Keypad 0"},
{321, "Keypad 1"},
{322, "Keypad 2"},
{323, "Keypad 3"},
{324, "Keypad 4"},
{325, "Keypad 5"},
{326, "Keypad 6"},
{327, "Keypad 7"},
{328, "Keypad 8"},
{329, "Keypad 9"},
{330, "Keypad ."},
{331, "Keypad /"},
{332, "Keypad *"},
{333, "Keypad -"},
{334, "Keypad +"},
{335, "Keypad Enter"},
{340, "Left Shift"},
{341, "Left Control"},
{342, "Left Alt"},
{343, "Left Super"},
{344, "Right Shift"},
{345, "Right Control"},
{346, "Right Alt"},
{347, "Right Super"},
{348, "Menu"}
constexpr bool hasKeyModifier(KeyModifier lhs, KeyModifier rhs) {
return static_cast<std::underlying_type_t<KeyModifier>>(lhs) &
static_cast<std::underlying_type_t<KeyModifier>>(rhs);
}
//////////////////////////////////////////////////////////////////////////////////////////
enum class Key : uint16_t {
Unknown = uint16_t(-1),
Space = 32,
Apostrophe = 39,
Comma = 44,
Minus = 45,
Period = 46,
Slash = 47,
Num0 = 48,
Num1 = 49,
Num2 = 50,
Num3 = 51,
Num4 = 52,
Num5 = 53,
Num6 = 54,
Num7 = 55,
Num8 = 56,
Num9 = 57,
SemiColon = 59,
Equal = 61,
A = 65,
B = 66,
C = 67,
D = 68,
E = 69,
F = 70,
G = 71,
H = 72,
I = 73,
J = 74,
K = 75,
L = 76,
M = 77,
N = 78,
O = 79,
P = 80,
Q = 81,
R = 82,
S = 83,
T = 84,
U = 85,
V = 86,
W = 87,
X = 88,
Y = 89,
Z = 90,
LeftBracket = 91,
BackSlash = 92,
RightBracket = 93,
GraveAccent = 96,
World1 = 161,
World2 = 162,
Escape = 256,
Enter = 257,
Tab = 258,
BackSpace = 259,
Insert = 260,
Delete = 261,
Right = 262,
Left = 263,
Down = 264,
Up = 265,
PageUp = 266,
PageDown = 267,
Home = 268,
End = 269,
CapsLock = 280,
ScrollLock = 281,
NumLock = 282,
PrintScreen = 283,
Pause = 284,
F1 = 290,
F2 = 291,
F3 = 292,
F4 = 293,
F5 = 294,
F6 = 295,
F7 = 296,
F8 = 297,
F9 = 298,
F10 = 299,
F11 = 300,
F12 = 301,
F13 = 302,
F14 = 303,
F15 = 304,
F16 = 305,
F17 = 306,
F18 = 307,
F19 = 308,
F20 = 309,
F21 = 310,
F22 = 311,
F23 = 312,
F24 = 313,
F25 = 314,
Keypad0 = 320,
Keypad1 = 321,
Keypad2 = 322,
Keypad3 = 323,
Keypad4 = 324,
Keypad5 = 325,
Keypad6 = 326,
Keypad7 = 327,
Keypad8 = 328,
Keypad9 = 329,
KeypadDecimal = 330,
KeypadDivide = 331,
KeypadMultiply = 332,
KeypadSubtract = 333,
KeypadAdd = 334,
KeypadEnter = 335,
LeftShift = 340,
LeftControl = 341,
LeftAlt = 342,
LeftSuper = 343,
RightShift = 344,
RightControl = 345,
RightAlt = 346,
RightSuper = 347,
Menu = 348,
Last = Menu
};
struct KeyInfo {
Key key;
std::string_view name;
std::string_view identifier;
};
constexpr const std::array<KeyInfo, 120> KeyInfos = {
KeyInfo { Key::Unknown, "", "" },
KeyInfo { Key::Space, "Space", "SPACE" },
KeyInfo { Key::Apostrophe, "'", "APOSTROPHE" },
KeyInfo { Key::Comma, ",", "COMMA" },
KeyInfo { Key::Minus, "-", "MINUS" },
KeyInfo { Key::Period, ".", "PERIOD" },
KeyInfo { Key::Slash, "/", "SLASH" },
KeyInfo { Key::Num0, "0", "0" },
KeyInfo { Key::Num1, "1", "1" },
KeyInfo { Key::Num2, "2", "2" },
KeyInfo { Key::Num3, "3", "3" },
KeyInfo { Key::Num4, "4", "4" },
KeyInfo { Key::Num5, "5", "5" },
KeyInfo { Key::Num6, "6", "6" },
KeyInfo { Key::Num7, "7", "7" },
KeyInfo { Key::Num8, "8", "8" },
KeyInfo { Key::Num9, "9", "9" },
KeyInfo { Key::SemiColon, ";", "SEMICOLON" },
KeyInfo { Key::Equal, "=", "EQUAL" },
KeyInfo { Key::A, "A", "A" },
KeyInfo { Key::B, "B", "B" },
KeyInfo { Key::C, "C", "C" },
KeyInfo { Key::D, "D", "D" },
KeyInfo { Key::E, "E", "E" },
KeyInfo { Key::F, "F", "F" },
KeyInfo { Key::G, "G", "G" },
KeyInfo { Key::H, "H", "H" },
KeyInfo { Key::I, "I", "I" },
KeyInfo { Key::J, "J", "J" },
KeyInfo { Key::K, "K", "K" },
KeyInfo { Key::L, "L", "L" },
KeyInfo { Key::M, "M", "M" },
KeyInfo { Key::N, "N", "N" },
KeyInfo { Key::O, "O", "O" },
KeyInfo { Key::P, "P", "P" },
KeyInfo { Key::Q, "Q", "Q" },
KeyInfo { Key::R, "R", "R" },
KeyInfo { Key::S, "S", "S" },
KeyInfo { Key::T, "T", "T" },
KeyInfo { Key::U, "U", "U" },
KeyInfo { Key::V, "V", "V" },
KeyInfo { Key::W, "W", "W" },
KeyInfo { Key::X, "X", "X" },
KeyInfo { Key::Y, "Y", "Y" },
KeyInfo { Key::Z, "Z", "Z" },
KeyInfo { Key::LeftBracket, "[", "LEFTBRACKET" },
KeyInfo { Key::BackSlash, "\\", "BACKSLASH" },
KeyInfo { Key::RightBracket, "]", "RIGHTBRACKET" },
KeyInfo { Key::GraveAccent, "`", "GRAVEACCENT" },
KeyInfo { Key::World1, "World1", "WORLD1" },
KeyInfo { Key::World2, "World2", "WORLD2" },
KeyInfo { Key::Escape, "Escape", "ESC" },
KeyInfo { Key::Enter, "Enter", "ENTER" },
KeyInfo { Key::Tab, "Tab", "TAB" },
KeyInfo { Key::BackSpace, "Backspace", "BACKSPACE" },
KeyInfo { Key::Insert, "Insert", "INSERT" },
KeyInfo { Key::Delete, "Delete", "DELETE" },
KeyInfo { Key::Right, "Right", "RIGHT" },
KeyInfo { Key::Left, "Left", "LEFT" },
KeyInfo { Key::Down, "Down", "DOWN" },
KeyInfo { Key::Up, "Up", "UP" },
KeyInfo { Key::PageUp, "PageUp", "PAGEUP" },
KeyInfo { Key::PageDown, "PageDown", "PAGEDOWN" },
KeyInfo { Key::Home, "Home", "HOME" },
KeyInfo { Key::End, "End", "END" },
KeyInfo { Key::CapsLock, "CapsLock", "CAPS_LOCK" },
KeyInfo { Key::ScrollLock, "ScrollLock", "SCROLL_LOCK" },
KeyInfo { Key::NumLock, "NumLock", "NUM_LOCK" },
KeyInfo { Key::PrintScreen, "PrintScreen", "PRINT_SCREEN" },
KeyInfo { Key::Pause, "Pause", "PAUSE" },
KeyInfo { Key::F1, "F1", "F1" },
KeyInfo { Key::F2, "F2", "F2" },
KeyInfo { Key::F3, "F3", "F3" },
KeyInfo { Key::F4, "F4", "F4" },
KeyInfo { Key::F5, "F5", "F5" },
KeyInfo { Key::F6, "F6", "F6" },
KeyInfo { Key::F7, "F7", "F7" },
KeyInfo { Key::F8, "F8", "F8" },
KeyInfo { Key::F9, "F9", "F9" },
KeyInfo { Key::F10, "F10", "F10" },
KeyInfo { Key::F11, "F11", "F11" },
KeyInfo { Key::F12, "F12", "F12" },
KeyInfo { Key::F13, "F13", "F13" },
KeyInfo { Key::F14, "F14", "F14" },
KeyInfo { Key::F15, "F15", "F15" },
KeyInfo { Key::F16, "F16", "F16" },
KeyInfo { Key::F17, "F17", "F17" },
KeyInfo { Key::F18, "F18", "F18" },
KeyInfo { Key::F19, "F19", "F19" },
KeyInfo { Key::F20, "F20", "F20" },
KeyInfo { Key::F21, "F21", "F21" },
KeyInfo { Key::F22, "F22", "F22" },
KeyInfo { Key::F23, "F23", "F23" },
KeyInfo { Key::F24, "F24", "F24" },
KeyInfo { Key::F25, "F25", "F25" },
KeyInfo { Key::Keypad0, "Keypad 0", "KP_0" },
KeyInfo { Key::Keypad1, "Keypad 1", "KP_1" },
KeyInfo { Key::Keypad2, "Keypad 2", "KP_2" },
KeyInfo { Key::Keypad3, "Keypad 3", "KP_3" },
KeyInfo { Key::Keypad4, "Keypad 4", "KP_4" },
KeyInfo { Key::Keypad5, "Keypad 5", "KP_5" },
KeyInfo { Key::Keypad6, "Keypad 6", "KP_6" },
KeyInfo { Key::Keypad7, "Keypad 7", "KP_7" },
KeyInfo { Key::Keypad8, "Keypad 8", "KP_8" },
KeyInfo { Key::Keypad9, "Keypad 9", "KP_9" },
KeyInfo { Key::KeypadDecimal, "Keypad .", "KP_DECIMAL" },
KeyInfo { Key::KeypadDivide, "Keypad /", "KP_DIVIDE" },
KeyInfo { Key::KeypadMultiply, "Keypad *", "KP_MULTIPLY" },
KeyInfo { Key::KeypadSubtract, "Keypad -", "KP_SUBTRACT" },
KeyInfo { Key::KeypadAdd, "Keypad +", "KP_ADD" },
KeyInfo { Key::KeypadEnter, "Keypad Enter", "KP_ENTER" },
KeyInfo { Key::LeftShift, "Left Shift", "LEFT_SHIFT" },
KeyInfo { Key::LeftControl, "Left Control", "LEFT_CONTROL" },
KeyInfo { Key::LeftAlt, "Left Alt", "LEFT_ALT" },
KeyInfo { Key::LeftSuper, "Left Super", "LEFT_SUPER" },
KeyInfo { Key::RightShift, "Right Shift", "RIGHT_SHIFT" },
KeyInfo { Key::RightControl, "Right Control", "RIGHT_CONTROL" },
KeyInfo { Key::RightAlt, "Right Alt", "RIGHT_ALT" },
KeyInfo { Key::RightSuper, "Right Super", "RIGHT_SUPER" },
KeyInfo { Key::Menu, "Menu", "MENU" }
};
//////////////////////////////////////////////////////////////////////////////////////////
struct KeyWithModifier {
Key key;
KeyModifier modifier;
Key key = Key::Unknown;
KeyModifier modifier = KeyModifier::None;
};
constexpr inline bool isKeypadKey(Key key) noexcept {
return key == Key::Keypad0 || key == Key::Keypad1 || key == Key::Keypad2 ||
key == Key::Keypad3 || key == Key::Keypad4 || key == Key::Keypad5 ||
key == Key::Keypad6 || key == Key::Keypad7 || key == Key::Keypad8 ||
key == Key::Keypad9 || key == Key::KeypadEnter || key == Key::KeypadAdd ||
key == Key::KeypadSubtract || key == Key::KeypadMultiply ||
key == Key::KeypadDivide;
}
KeyWithModifier stringToKey(std::string str);
bool operator<(const KeyWithModifier& lhs, const KeyWithModifier& rhs);
bool operator==(const KeyWithModifier& lhs, const KeyWithModifier& rhs);
std::string keyToString(KeyWithModifier keyWithModifier);
static const std::map<std::string, KeyModifier> KeyModifierMapping = {
{ "SHIFT", KeyModifier::Shift },
{ "ALT", KeyModifier::Alt },
{ "CTRL", KeyModifier::Control },
{ "SUPER", KeyModifier::Super }
};
// @TODO (abock, 2021-08-12) This function should die
constexpr bool operator<(const KeyWithModifier& lhs, const KeyWithModifier& rhs) noexcept
{
if (lhs.modifier == rhs.modifier) {
return lhs.key < rhs.key;
}
else {
return lhs.modifier < rhs.modifier;
}
}
static const std::map<std::string, Key> KeyMapping = {
{ "0", Key::Num0 },
{ "1", Key::Num1 },
{ "2", Key::Num2 },
{ "3", Key::Num3 },
{ "4", Key::Num4 },
{ "5", Key::Num5 },
{ "6", Key::Num6 },
{ "7", Key::Num7 },
{ "8", Key::Num8 },
{ "9", Key::Num9 },
{ "A", Key::A },
{ "B", Key::B },
{ "C", Key::C },
{ "D", Key::D },
{ "E", Key::E },
{ "F", Key::F },
{ "G", Key::G },
{ "H", Key::H },
{ "I", Key::I },
{ "J", Key::J },
{ "K", Key::K },
{ "L", Key::L },
{ "M", Key::M },
{ "N", Key::N },
{ "O", Key::O },
{ "P", Key::P },
{ "Q", Key::Q },
{ "R", Key::R },
{ "S", Key::S },
{ "T", Key::T },
{ "U", Key::U },
{ "V", Key::V },
{ "W", Key::W },
{ "X", Key::X },
{ "Y", Key::Y },
{ "Z", Key::Z },
{ "LeftBracket", Key::LeftBracket },
{ "LEFTBRACKET", Key::LeftBracket },
{ "LEFT_BRACKET", Key::LeftBracket },
{ "Backslash", Key::BackSlash },
{ "BACKSLASH", Key::BackSlash },
{ "RightBracket", Key::RightBracket },
{ "RIGHTBRACKET", Key::RightBracket },
{ "RIGHT_BRACKET", Key::RightBracket },
{ "GraveAccent", Key::GraveAccent },
{ "GRAVEACCENT", Key::GraveAccent },
{ "GRAVE_ACCENT", Key::GraveAccent },
{ "Space", Key::Space },
{ "SPACE", Key::Space },
{ "Apostrophe", Key::Apostrophe },
{ "APOSTROPHE", Key::Apostrophe },
{ "Comma", Key::Comma },
{ "COMMA", Key::Comma },
{ "Minus", Key::Minus },
{ "MINUS", Key::Minus },
{ "Period", Key::Period },
{ "PERIOD", Key::Period },
{ "Slash", Key::Slash },
{ "SLASH", Key::Slash },
{ "Semicolon", Key::SemiColon },
{ "SEMICOLON", Key::SemiColon },
{ "SEMI COLON", Key::SemiColon },
{ "Equal", Key::Equal },
{ "EQUAL", Key::Equal },
{ "World1", Key::World1 },
{ "WORLD1", Key::World1 },
{ "WORLD_1", Key::World1 },
{ "World2", Key::World2 },
{ "WORLD2", Key::World2 },
{ "WORLD_2", Key::World2 },
{ "Esc", Key::Escape },
{ "ESC", Key::Escape },
{ "ESCAPE", Key::Escape},
{ "Enter", Key::Enter },
{ "ENTER", Key::Enter },
{ "Tab", Key::Tab },
{ "TAB", Key::Tab },
{ "Backspace", Key::BackSpace },
{ "BACKSPACE", Key::BackSpace },
{ "Insert", Key::Insert },
{ "INSERT", Key::Insert },
{ "DEL", Key::Delete },
{ "Delete", Key::Delete },
{ "DELETE", Key::Delete },
{ "Right", Key::Right },
{ "RIGHT", Key::Right },
{ "Left", Key::Left },
{ "LEFT", Key::Left },
{ "Down", Key::Down },
{ "DOWN", Key::Down },
{ "Up", Key::Up },
{ "UP", Key::Up },
{ "PageUp", Key::PageUp },
{ "PAGEUP", Key::PageUp },
{ "PAGE_UP", Key::PageUp },
{ "PageDown", Key::PageDown },
{ "PAGEDOWN", Key::PageDown },
{ "PAGE_DOWN", Key::PageDown },
{ "Home", Key::Home },
{ "HOME", Key::Home },
{ "End", Key::End },
{ "END", Key::End },
{ "CapsLock", Key::CapsLock },
{ "CAPSLOCK", Key::CapsLock },
{ "CAPS_LOCK", Key::CapsLock },
{ "ScrollLock", Key::ScrollLock },
{ "SCROLLLOCK", Key::ScrollLock },
{ "SCROLL_LOCK", Key::ScrollLock },
{ "NumLock", Key::NumLock },
{ "NUMLOCK", Key::NumLock },
{ "NUM_LOCK", Key::NumLock },
{ "PrintScreen", Key::PrintScreen },
{ "PRINTSCREEN", Key::PrintScreen },
{ "PRINT_SCREEN", Key::PrintScreen },
{ "Pause", Key::Pause },
{ "PAUSE", Key::Pause },
{ "F1", Key::F1 },
{ "F2", Key::F2 },
{ "F3", Key::F3 },
{ "F4", Key::F4 },
{ "F5", Key::F5 },
{ "F6", Key::F6 },
{ "F7", Key::F7 },
{ "F8", Key::F8 },
{ "F9", Key::F9 },
{ "F10", Key::F10 },
{ "F11", Key::F11 },
{ "F12", Key::F12 },
{ "F13", Key::F13 },
{ "F14", Key::F14 },
{ "F15", Key::F15 },
{ "F16", Key::F16 },
{ "F17", Key::F17 },
{ "F18", Key::F18 },
{ "F19", Key::F19 },
{ "F20", Key::F20 },
{ "F21", Key::F21 },
{ "F22", Key::F22 },
{ "F23", Key::F23 },
{ "F24", Key::F24 },
{ "F25", Key::F25 },
{ "Keypad0", Key::Keypad0 },
{ "KP0", Key::Keypad0 },
{ "KP_0", Key::Keypad0 },
{ "Keypad1", Key::Keypad1 },
{ "KP1", Key::Keypad1 },
{ "KP_1", Key::Keypad1 },
{ "Keypad2", Key::Keypad2 },
{ "KP2", Key::Keypad2 },
{ "KP_2", Key::Keypad2 },
{ "Keypad3", Key::Keypad3 },
{ "KP3", Key::Keypad3 },
{ "KP_3", Key::Keypad3 },
{ "Keypad4", Key::Keypad4 },
{ "KP4", Key::Keypad4 },
{ "KP_4", Key::Keypad4 },
{ "Keypad5", Key::Keypad5 },
{ "KP5", Key::Keypad5 },
{ "KP_5", Key::Keypad5 },
{ "Keypad6", Key::Keypad6 },
{ "KP6", Key::Keypad6 },
{ "KP_6", Key::Keypad6 },
{ "Keypad7", Key::Keypad7 },
{ "KP7", Key::Keypad7 },
{ "KP_7", Key::Keypad7 },
{ "Keypad8", Key::Keypad8 },
{ "KP8", Key::Keypad8 },
{ "KP_8", Key::Keypad8 },
{ "Keypad9", Key::Keypad9 },
{ "KP9", Key::Keypad9 },
{ "KP_9", Key::Keypad9 },
{ "KeypadDecimal", Key::KeypadDecimal },
{ "KPDECIMAL", Key::KeypadDecimal },
{ "KP_DECIMAL", Key::KeypadDecimal },
{ "KeypadDivide", Key::KeypadDivide },
{ "KPDIVIDE", Key::KeypadDivide },
{ "KP_DIVIDE", Key::KeypadDivide },
{ "KeypadMultiply", Key::KeypadMultiply },
{ "KPMULTIPLY", Key::KeypadMultiply },
{ "KP_MULTIPLY", Key::KeypadMultiply },
{ "KeypadSubtract", Key::KeypadSubtract },
{ "KPSUBTRACT", Key::KeypadSubtract },
{ "KP_SUBTRACT", Key::KeypadSubtract },
{ "KeypadAdd", Key::KeypadAdd },
{ "KPADD", Key::KeypadAdd },
{ "KP_ADD", Key::KeypadAdd },
{ "KeypadEnter", Key::KeypadEnter },
{ "KPENTER", Key::KeypadEnter },
{ "KP_ENTER", Key::KeypadEnter },
{ "KeypadEqual", Key::KeypadEnter },
{ "KPEQUAL", Key::KeypadEnter },
{ "KP_EQUAL", Key::KeypadEnter },
{ "LeftShift", Key::LeftShift },
{ "LSHIFT", Key::LeftShift },
{ "LEFTSHIFT", Key::LeftShift },
{ "LEFT_SHIFT", Key::LeftShift },
{ "LeftControl", Key::LeftControl },
{ "LCTRL", Key::LeftControl },
{ "LEFTCONTROL", Key::LeftControl },
{ "LEFT_CONTROL", Key::LeftControl },
{ "LeftAlt", Key::LeftAlt },
{ "LALT", Key::LeftAlt },
{ "LEFTALT", Key::LeftAlt },
{ "LEFT_ALT", Key::LeftAlt },
{ "LeftSuper", Key::LeftSuper },
{ "LEFTSUPER", Key::LeftSuper },
{ "LEFT_SUPER", Key::LeftSuper },
{ "RightShift", Key::RightShift },
{ "RSHIFT", Key::RightShift },
{ "RIGHTSHIFT", Key::RightShift },
{ "RIGHT_SHIFT", Key::RightShift },
{ "RightControl", Key::RightControl },
{ "RCTRL", Key::RightControl },
{ "RIGHTCONTROL", Key::RightControl },
{ "RIGHT_CONTROL", Key::RightControl },
{ "RightAlt", Key::RightAlt },
{ "RALT", Key::RightAlt },
{ "RIGHTALT", Key::RightAlt },
{ "RIGHT_ALT", Key::RightAlt },
{ "RightSuper", Key::RightSuper },
{ "RIGHTSUPER", Key::RightSuper },
{ "RIGHT_SUPER", Key::RightSuper },
{ "Menu", Key::Menu },
{ "MENU", Key::Menu }
};
constexpr bool operator==(const KeyWithModifier& lhs, const KeyWithModifier& rhs) noexcept
{
return (lhs.key == rhs.key) && (lhs.modifier == rhs.modifier);
}
} // namespace openspace

View File

@@ -0,0 +1,48 @@
/*****************************************************************************************
* *
* OpenSpace *
* *
* Copyright (c) 2014-2021 *
* *
* Permission is hereby granted, free of charge, to any person obtaining a copy of this *
* software and associated documentation files (the "Software"), to deal in the Software *
* without restriction, including without limitation the rights to use, copy, modify, *
* merge, publish, distribute, sublicense, and/or sell copies of the Software, and to *
* permit persons to whom the Software is furnished to do so, subject to the following *
* conditions: *
* *
* The above copyright notice and this permission notice shall be included in all copies *
* or substantial portions of the Software. *
* *
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, *
* INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A *
* PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT *
* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF *
* CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE *
* OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. *
****************************************************************************************/
#ifndef __OPENSPACE_CORE___UNIVERSALHELPERS___H__
#define __OPENSPACE_CORE___UNIVERSALHELPERS___H__
/*
* This file is meant to contain generally useful functions that is used a bit all over
* the place but that do not belong in any other, more specific, file.
*
* If you implement a function that can be useful in several other situations, feel free
* to document it and put it this file
*/
namespace openspace::helpers {
/*
* Remap a parameter t in [0,1] to a subinterval [start, end], by shifting and scaling
* the value to match the interval. If \p t is smaller than \p start, the return value
* will be 0 and if bigger than \p end it will be 1. Other values will be linearly
* interpolated within the range [start, end]
*/
double shiftAndScale(double t, double start, double end);
} // namespace openspace::helpers
#endif // __OPENSPACE_CORE___UNIVERSALHELPERS___H__

View File

@@ -25,7 +25,7 @@
#ifndef __OPENSPACE_CORE___UPDATESTRUCTURES___H__
#define __OPENSPACE_CORE___UPDATESTRUCTURES___H__
#include <openspace/util/camera.h>
#include <openspace/camera/camera.h>
#include <openspace/util/time.h>
namespace openspace {

View File

@@ -112,6 +112,7 @@ set(SOURCE_FILES
rendering/renderabletrailorbit.cpp
rendering/renderabletrailtrajectory.cpp
rendering/screenspacedashboard.cpp
rendering/screenspacedashboard_lua.inl
rendering/screenspaceframebuffer.cpp
rendering/screenspaceimagelocal.cpp
rendering/screenspaceimageonline.cpp

View File

@@ -24,15 +24,15 @@
#include <modules/base/dashboard/dashboarditemangle.h>
#include <openspace/camera/camera.h>
#include <openspace/documentation/documentation.h>
#include <openspace/documentation/verifier.h>
#include <openspace/engine/globals.h>
#include <openspace/interaction/navigationhandler.h>
#include <openspace/interaction/orbitalnavigator.h>
#include <openspace/navigation/navigationhandler.h>
#include <openspace/navigation/orbitalnavigator.h>
#include <openspace/rendering/renderengine.h>
#include <openspace/scene/scene.h>
#include <openspace/scene/scenegraphnode.h>
#include <openspace/util/camera.h>
#include <ghoul/font/font.h>
#include <ghoul/font/fontmanager.h>
#include <ghoul/font/fontrenderer.h>

View File

@@ -24,15 +24,15 @@
#include <modules/base/dashboard/dashboarditemdistance.h>
#include <openspace/camera/camera.h>
#include <openspace/documentation/documentation.h>
#include <openspace/documentation/verifier.h>
#include <openspace/engine/globals.h>
#include <openspace/interaction/navigationhandler.h>
#include <openspace/interaction/orbitalnavigator.h>
#include <openspace/navigation/navigationhandler.h>
#include <openspace/navigation/orbitalnavigator.h>
#include <openspace/rendering/renderengine.h>
#include <openspace/scene/scene.h>
#include <openspace/scene/scenegraphnode.h>
#include <openspace/util/camera.h>
#include <openspace/util/distanceconversion.h>
#include <ghoul/font/font.h>
#include <ghoul/font/fontmanager.h>

View File

@@ -24,15 +24,14 @@
#include <modules/base/dashboard/dashboarditemvelocity.h>
#include <openspace/camera/camera.h>
#include <openspace/documentation/documentation.h>
#include <openspace/documentation/verifier.h>
#include <openspace/engine/globals.h>
#include <openspace/engine/windowdelegate.h>
#include <openspace/interaction/navigationhandler.h>
#include <openspace/rendering/renderengine.h>
#include <openspace/scene/scene.h>
#include <openspace/scene/scenegraphnode.h>
#include <openspace/util/camera.h>
#include <openspace/util/distanceconversion.h>
#include <ghoul/font/font.h>
#include <ghoul/font/fontmanager.h>

View File

@@ -249,6 +249,14 @@ namespace {
// [[codegen::verbatim(EnableOpacityBlendingInfo.description)]]
std::optional<bool> enableOpacityBlending;
// The path to the vertex shader program that is used instead of the default
// shader.
std::optional<std::filesystem::path> vertexShader;
// The path to the fragment shader program that is used instead of the default
// shader.
std::optional<std::filesystem::path> fragmentShader;
};
#include "renderablemodel_codegen.cpp"
} // namespace
@@ -335,7 +343,7 @@ RenderableModel::RenderableModel(const ghoul::Dictionary& dictionary)
distanceUnit = DistanceUnit::Kilometer;
break;
// Weired units
// Weird units
case Parameters::ScaleUnit::Thou:
distanceUnit = DistanceUnit::Thou;
break;
@@ -472,6 +480,13 @@ RenderableModel::RenderableModel(const ghoul::Dictionary& dictionary)
_disableDepthTest = p.disableDepthTest.value_or(_disableDepthTest);
_disableFaceCulling = p.disableFaceCulling.value_or(_disableFaceCulling);
if (p.vertexShader.has_value()) {
_vertexShaderPath = p.vertexShader->string();
}
if (p.fragmentShader.has_value()) {
_fragmentShaderPath = p.fragmentShader->string();
}
if (p.lightSources.has_value()) {
std::vector<ghoul::Dictionary> lightsources = *p.lightSources;
@@ -560,16 +575,33 @@ void RenderableModel::initialize() {
void RenderableModel::initializeGL() {
ZoneScoped
std::string program = ProgramName;
if (!_vertexShaderPath.empty()) {
program += "|vs=" + _vertexShaderPath;
}
if (!_fragmentShaderPath.empty()) {
program += "|fs=" + _fragmentShaderPath;
}
_program = BaseModule::ProgramObjectManager.request(
ProgramName,
[]() -> std::unique_ptr<ghoul::opengl::ProgramObject> {
return global::renderEngine->buildRenderProgram(
ProgramName,
absPath("${MODULE_BASE}/shaders/model_vs.glsl"),
absPath("${MODULE_BASE}/shaders/model_fs.glsl")
);
program,
[&]() -> std::unique_ptr<ghoul::opengl::ProgramObject> {
std::filesystem::path vs =
_vertexShaderPath.empty() ?
absPath("${MODULE_BASE}/shaders/model_vs.glsl") :
_vertexShaderPath;
std::filesystem::path fs =
_fragmentShaderPath.empty() ?
absPath("${MODULE_BASE}/shaders/model_fs.glsl") :
_fragmentShaderPath;
return global::renderEngine->buildRenderProgram(ProgramName, vs, fs);
}
);
// We don't really know what kind of shader the user provides us with, so we can't
// make the assumption that we are going to use all uniforms
_program->setIgnoreUniformLocationError(
ghoul::opengl::ProgramObject::IgnoreError::Yes
);
ghoul::opengl::updateUniformLocations(*_program, _uniformCache, UniformNames);
@@ -581,8 +613,15 @@ void RenderableModel::deinitializeGL() {
_geometry->deinitialize();
_geometry.reset();
std::string program = ProgramName;
if (!_vertexShaderPath.empty()) {
program += "|vs=" + _vertexShaderPath;
}
if (!_fragmentShaderPath.empty()) {
program += "|fs=" + _fragmentShaderPath;
}
BaseModule::ProgramObjectManager.release(
ProgramName,
program,
[](ghoul::opengl::ProgramObject* p) {
global::renderEngine->removeRenderProgram(p);
}

View File

@@ -101,6 +101,8 @@ private:
properties::BoolProperty _enableOpacityBlending;
properties::OptionProperty _blendingFuncOption;
std::string _vertexShaderPath;
std::string _fragmentShaderPath;
ghoul::opengl::ProgramObject* _program = nullptr;
UniformCache(opacity, nLightSources, lightDirectionsViewSpace, lightIntensities,
modelViewTransform, normalTransform, projectionTransform,

View File

@@ -27,8 +27,8 @@
#include <modules/base/basemodule.h>
#include <openspace/documentation/verifier.h>
#include <openspace/engine/globals.h>
#include <openspace/interaction/navigationhandler.h>
#include <openspace/interaction/orbitalnavigator.h>
#include <openspace/navigation/navigationhandler.h>
#include <openspace/navigation/orbitalnavigator.h>
#include <openspace/rendering/renderengine.h>
#include <openspace/scene/scene.h>
#include <openspace/scene/translation.h>

View File

@@ -338,7 +338,6 @@ void RenderableTrail::internalRender(bool renderLines, bool renderPoints,
_programObject->setUniform(_uniformCache.nVertices, nVertices);
#if !defined(__APPLE__)
glm::ivec2 resolution = global::renderEngine->renderingResolution();
GLint viewport[4];
global::renderEngine->openglStateCache().viewport(viewport);
_programObject->setUniform(

View File

@@ -54,79 +54,10 @@ namespace {
#include "screenspacedashboard_codegen.cpp"
} // namespace
#include "screenspacedashboard_lua.inl"
namespace openspace {
namespace luascriptfunctions {
/**
* \ingroup LuaScripts
* addDashboardItemToScreenSpace(string, table):
*/
int addDashboardItemToScreenSpace(lua_State* L) {
ghoul::lua::checkArgumentsAndThrow(L, 2, "lua::addDashboardItemToScreenSpace");
const std::string& name = ghoul::lua::value<std::string>(L, 1);
const int type = lua_type(L, 2);
if (type != LUA_TTABLE) {
return ghoul::lua::luaError(L, "Expected argument of type 'table'");
}
ghoul::Dictionary d;
try {
ghoul::lua::luaDictionaryFromState(L, d);
}
catch (const ghoul::lua::LuaFormatException& e) {
LERRORC("addDashboardItem", e.what());
return 0;
}
ScreenSpaceRenderable* ssr = global::renderEngine->screenSpaceRenderable(name);
if (!ssr) {
return ghoul::lua::luaError(L, "Provided name is not a ScreenSpace item");
}
ScreenSpaceDashboard* dash = dynamic_cast<ScreenSpaceDashboard*>(ssr);
if (!dash) {
return ghoul::lua::luaError(
L,
"Provided name is a ScreenSpace item but not a dashboard"
);
}
dash->dashboard().addDashboardItem(DashboardItem::createFromDictionary(d));
lua_settop(L, 0);
return 0;
}
/**
* \ingroup LuaScripts
* removeDashboardItemsFromScreenSpace(string):
*/
int removeDashboardItemsFromScreenSpace(lua_State* L) {
ghoul::lua::checkArgumentsAndThrow(L, 1, "lua::removeDashboardItemsFromScreenSpace");
const std::string& name = ghoul::lua::value<std::string>(L, 1);
ScreenSpaceRenderable* ssr = global::renderEngine->screenSpaceRenderable(name);
if (!ssr) {
return ghoul::lua::luaError(L, "Provided name is not a ScreenSpace item");
}
ScreenSpaceDashboard* dash = dynamic_cast<ScreenSpaceDashboard*>(ssr);
if (!dash) {
return ghoul::lua::luaError(
L,
"Provided name is a ScreenSpace item but not a dashboard"
);
}
dash->dashboard().clearDashboardItems();
return 0;
}
} // namespace luascriptfunctions
documentation::Documentation ScreenSpaceDashboard::Documentation() {
return codegen::doc<Parameters>("base_screenspace_dashboard");
}

Some files were not shown because too many files have changed in this diff Show More