mirror of
https://github.com/OpenSpace/OpenSpace.git
synced 2026-01-07 04:00:37 -06:00
Merge branch 'master' into thesis/2020/radiation
This commit is contained in:
@@ -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
|
||||
|
||||
103
apps/OpenSpace/ext/launcher/include/profile/actiondialog.h
Normal file
103
apps/OpenSpace/ext/launcher/include/profile/actiondialog.h
Normal 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__
|
||||
@@ -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;
|
||||
};
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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__
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -36,7 +36,7 @@ class QLabel;
|
||||
class QLineEdit;
|
||||
class QTextEdit;
|
||||
|
||||
class ProfileEdit : public QDialog {
|
||||
class ProfileEdit final : public QDialog {
|
||||
Q_OBJECT
|
||||
public:
|
||||
/**
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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:
|
||||
/**
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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
|
||||
*/
|
||||
|
||||
@@ -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;
|
||||
|
||||
|
||||
698
apps/OpenSpace/ext/launcher/src/profile/actiondialog.cpp
Normal file
698
apps/OpenSpace/ext/launcher/src/profile/actiondialog.cpp
Normal 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();
|
||||
}
|
||||
@@ -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();
|
||||
}
|
||||
|
||||
|
||||
@@ -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();
|
||||
}
|
||||
|
||||
@@ -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();
|
||||
|
||||
@@ -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();
|
||||
}
|
||||
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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();
|
||||
}
|
||||
|
||||
|
||||
@@ -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();
|
||||
}
|
||||
|
||||
@@ -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();
|
||||
}
|
||||
|
||||
|
||||
@@ -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")
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
@@ -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();
|
||||
}
|
||||
|
||||
|
||||
@@ -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();
|
||||
}
|
||||
|
||||
@@ -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
|
||||
);
|
||||
|
||||
@@ -129,4 +129,4 @@ int main(int argc, char** argv) {
|
||||
LINFO("Server stopped");
|
||||
|
||||
return 0;
|
||||
};
|
||||
}
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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')
|
||||
|
||||
|
||||
47
data/assets/examples/globerotation.asset
Normal file
47
data/assets/examples/globerotation.asset
Normal 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 })
|
||||
@@ -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
|
||||
}
|
||||
},
|
||||
|
||||
75
data/assets/examples/modelshader/model_fs.glsl
Normal file
75
data/assets/examples/modelshader/model_fs.glsl
Normal 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;
|
||||
}
|
||||
68
data/assets/examples/modelshader/model_vs.glsl
Normal file
68
data/assets/examples/modelshader/model_vs.glsl
Normal 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);
|
||||
}
|
||||
45
data/assets/examples/modelshader/modelshader.asset
Normal file
45
data/assets/examples/modelshader/modelshader.asset
Normal 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 })
|
||||
@@ -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)
|
||||
|
||||
|
||||
@@ -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]]
|
||||
|
||||
@@ -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)
|
||||
|
||||
|
||||
|
||||
@@ -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 = {
|
||||
|
||||
@@ -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)
|
||||
|
||||
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -50,6 +50,7 @@ local Apollo15 = {
|
||||
Renderable = {
|
||||
Type = "RenderableModel",
|
||||
GeometryFile = models .. "/ApolloCSM.osmodel",
|
||||
ModelScale = 0.0001,
|
||||
LightSources = {
|
||||
{
|
||||
Type = "SceneGraphLightSource",
|
||||
|
||||
@@ -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",
|
||||
|
||||
@@ -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",
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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)
|
||||
@@ -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)
|
||||
|
||||
@@ -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({
|
||||
|
||||
@@ -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
|
||||
}
|
||||
}
|
||||
@@ -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
|
||||
}
|
||||
}
|
||||
@@ -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
|
||||
}
|
||||
}
|
||||
@@ -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
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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
|
||||
}
|
||||
}
|
||||
@@ -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
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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
|
||||
}
|
||||
}
|
||||
@@ -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
|
||||
}
|
||||
}
|
||||
@@ -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
|
||||
}
|
||||
}
|
||||
39
include/openspace/camera/camerapose.h
Normal file
39
include/openspace/camera/camerapose.h
Normal 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__
|
||||
@@ -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;
|
||||
|
||||
70
include/openspace/interaction/action.h
Normal file
70
include/openspace/interaction/action.h
Normal 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__
|
||||
@@ -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__
|
||||
@@ -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);
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -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>
|
||||
@@ -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;
|
||||
|
||||
59
include/openspace/navigation/navigationstate.h
Normal file
59
include/openspace/navigation/navigationstate.h
Normal 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__
|
||||
@@ -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
|
||||
144
include/openspace/navigation/path.h
Normal file
144
include/openspace/navigation/path.h
Normal 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__
|
||||
101
include/openspace/navigation/pathcurve.h
Normal file
101
include/openspace/navigation/pathcurve.h
Normal 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__
|
||||
@@ -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__
|
||||
@@ -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__
|
||||
107
include/openspace/navigation/pathnavigator.h
Normal file
107
include/openspace/navigation/pathnavigator.h
Normal file
@@ -0,0 +1,107 @@
|
||||
/*****************************************************************************************
|
||||
* *
|
||||
* OpenSpace *
|
||||
* *
|
||||
* Copyright (c) 2014-2021 *
|
||||
* *
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy of this *
|
||||
* software and associated documentation files (the "Software"), to deal in the Software *
|
||||
* without restriction, including without limitation the rights to use, copy, modify, *
|
||||
* merge, publish, distribute, sublicense, and/or sell copies of the Software, and to *
|
||||
* permit persons to whom the Software is furnished to do so, subject to the following *
|
||||
* conditions: *
|
||||
* *
|
||||
* The above copyright notice and this permission notice shall be included in all copies *
|
||||
* or substantial portions of the Software. *
|
||||
* *
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, *
|
||||
* INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A *
|
||||
* PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT *
|
||||
* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF *
|
||||
* CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE *
|
||||
* OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. *
|
||||
****************************************************************************************/
|
||||
|
||||
#ifndef __OPENSPACE_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__
|
||||
@@ -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__
|
||||
@@ -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
|
||||
|
||||
@@ -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<
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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__
|
||||
|
||||
@@ -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);
|
||||
|
||||
|
||||
@@ -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>
|
||||
|
||||
59
include/openspace/util/collisionhelper.h
Normal file
59
include/openspace/util/collisionhelper.h
Normal 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__
|
||||
@@ -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
|
||||
|
||||
|
||||
48
include/openspace/util/universalhelpers.h
Normal file
48
include/openspace/util/universalhelpers.h
Normal 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__
|
||||
@@ -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 {
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -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(
|
||||
|
||||
@@ -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
Reference in New Issue
Block a user