diff --git a/.gitattributes b/.gitattributes index 6f15cde045..1be02425ca 100644 --- a/.gitattributes +++ b/.gitattributes @@ -1,5 +1,18 @@ * text=auto +# Correct GitHub's language detection shenanigans + +# Asset files are not Unity, but Lua instead +*.asset linguist-language=Lua +# We have some SPICE frame kernels that get misclassified as code +*.tf -linguist-detectable +# We don't want to index the GDAL csv and xml files +modules/globebrowsing/gdal_data/* linguist-vendored +# No need to index any external files +*/ext/* linguist-vendored +# No C allowed +*.h linguist-language=C++ + # GitHub files ATTRIBUTION text AUTHORS text diff --git a/CMakeLists.txt b/CMakeLists.txt index 81d0833e7c..f66c1d9122 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -28,8 +28,8 @@ project(OpenSpace) set(OPENSPACE_VERSION_MAJOR 0) set(OPENSPACE_VERSION_MINOR 17) -set(OPENSPACE_VERSION_PATCH -1) -set(OPENSPACE_VERSION_STRING "Beta-10 [RC1]") +set(OPENSPACE_VERSION_PATCH 1) +set(OPENSPACE_VERSION_STRING "Beta-10") set(OPENSPACE_BASE_DIR "${PROJECT_SOURCE_DIR}") set(OPENSPACE_CMAKE_EXT_DIR "${OPENSPACE_BASE_DIR}/support/cmake") @@ -132,8 +132,6 @@ if (MSVC) set(GHOUL_OPTIMIZATION_ENABLE_OTHER_OPTIMIZATIONS ${OPENSPACE_OPTIMIZATION_ENABLE_OTHER_OPTIMIZATIONS} CACHE BOOL "" FORCE) endif () -option(OPENSPACE_WITH_ABUFFER_RENDERER "Compile ABuffer Renderer" OFF) - if (UNIX) if (CMAKE_CXX_COMPILER_ID MATCHES "Clang") set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++17 -stdlib=libc++") diff --git a/CREDITS.md b/CREDITS.md index c7201a953d..f12695c25d 100644 --- a/CREDITS.md +++ b/CREDITS.md @@ -4,17 +4,17 @@ Emil Axelsson Kalle Bladin Jonathas Costa Gene Payne -Jonas Strandstedt -Michal Marcinkowski -Elon Olsson Emma Broman +Jonas Strandstedt Micah Acinapura +Michal Marcinkowski +Malin Ejdbo +Elon Olsson Joakim Kilby Lovisa Hassler Mikael Petterson Erik Sundén Stefan Lindblad -Malin Ejdbo Corrie Roe Eric Myers diff --git a/README.md b/README.md index 19d721dd2a..1e17b0e290 100644 --- a/README.md +++ b/README.md @@ -1,13 +1,47 @@ -[OpenSpace](http://openspaceproject.com) is an open source, non-commercial, and freely available interactive data visualization software designed to visualize the entire known universe and portray our ongoing efforts to investigate the cosmos. Bringing the latest techniques from data visualization research to the general public, OpenSpace supports interactive presentation of dynamic data from observations, simulations, and space mission planning and operations. The software works on multiple operating systems (Windows, Linux, MacOS) with an extensible architecture powering high resolution tiled displays and planetarium domes, making use of the latest graphic card technologies for rapid data throughput. In addition, OpenSpace enables simultaneous connections across the globe creating opportunity for shared experiences among audiences worldwide. +![OpenSpace Logo](/data/openspace-horiz-logo-crop.png) +[OpenSpace](http://openspaceproject.com) is an open source, non-commercial, and freely available interactive data visualization software designed to visualize the entire known universe and portray our ongoing efforts to investigate the cosmos. Bringing the latest techniques from data visualization research to the general public, OpenSpace supports interactive presentation of dynamic data from observations, simulations, and space mission planning and operations. The software works on multiple operating systems (Windows, Linux, MacOS) with an extensible architecture capable of powering both personal computers and also high resolution tiled displays and planetarium domes. In addition, OpenSpace enables simultaneous connections across the globe creating opportunity for shared experiences among audiences worldwide. The target audience of the software reaches from the general public who wishes to explore our universe, enthusiasts interested in hacking the underlying components in OpenSpace to create unique experiences, informal science institutions wishing to create a low-cost, yet powerful exhibition piece, but also scientists desiring to visualize their datasets in a contextualized, powerful software. -The project stems from the same academic collaboration between Sweden’s [Linköping University](https://www.liu.se) (LiU) and the [American Museum of Natural History](https://www.amnh.org) (AMNH) that led to the creation of Uniview and its parent company [SCISS](http://sciss.se). Development of the software began several years ago through a close collaboration with NASA Goddard’s [Community Coordinated Modeling Center](https://ccmc.gsfc.nasa.gov) (CCMC) to model space weather forecasting and continued with visualizations of NASA’s New Horizons mission to Pluto and ESA’s Rosetta mission. This promising set of preliminary work provided a foundation for recent NASA funding, which has extended the collaboration to include the University of Utah’s [Scientific Computing and Imaging](https://www.sci.utah.edu) (SCI) Institute, [New York University](https://www.nyu.edu)’s Tandon School of Engineering, multiple informal science institutions across the United States, and multiple, international vendors. Current areas of focus within OpenSpace include: +[![License](https://img.shields.io/badge/License-MIT-purple.svg?style=flat-square)](LICENSE) +[![Download](https://img.shields.io/github/v/tag/OpenSpace/OpenSpace?label=Version&color=maroon&style=flat-square)](https://www.openspaceproject.com/installation) +![Size](https://img.shields.io/github/repo-size/OpenSpace/OpenSpace?style=flat-square&color=red) -- Visualization of dynamic simulations via interactive volumetric rendering, as a priority for communicating research in astrophysics. -- Utilization of NASA’s SPICE observational geometry system with its Planetary Data Service (PDS) to enable space mission visualizations that reveal how missions are designed to gather science. -- Globe browsing techniques across spatial and temporal scales to examine scientific campaigns on multiple planets, including close up surface exploration. +[![System Paper](https://img.shields.io/badge/System%20Paper-10.1109%2FTVCG.2019.2934259-blue?style=flat-square)](https://doi.org/10.1109/TVCG.2019.2934259) +[![GlobeBrowsing Paper](https://img.shields.io/badge/GlobeBrowsing%20Paper-https%3A%2F%2Fdoi.org%2F10.1109%2FTVCG.2017.2743958-blue?style=flat-square)](https://doi.org/10.1109/TVCG.2017.2743958) -OpenSpace requires graphics support for [OpenGL](https://www.opengl.org/) version 3.3. +![Contributors](https://img.shields.io/github/contributors/OpenSpace/OpenSpace?style=flat-square) +![Commits](https://img.shields.io/github/commit-activity/m/OpenSpace/OpenSpace?color=green&style=flat-square) -This repository contains the source code and example scenes for OpenSpace, but does not contain any data. To build and install the client, we refer to the [OpenSpace Wiki](http://wiki.openspaceproject.com/), specifically [building](http://wiki.openspaceproject.com/docs/developers/compiling/general) for [Windows](http://wiki.openspaceproject.com/docs/developers/compiling/windows), [Linux (Ubuntu)](http://wiki.openspaceproject.com/docs/developers/compiling/ubuntu), and [MacOS](http://wiki.openspaceproject.com/docs/developers/compiling/macos). Required preexisting dependencies are: [Boost](http://www.boost.org/) and [Qt](http://www.qt.io/download). Feel free to create issues for missing features, bug reports, or compile problems or contact us via [email](mailto:alexander.bock@me.com?subject=OpenSpace:). +![Image](https://github.com/OpenSpace/openspace.github.io/raw/master/assets/images/collection.jpg) -Regarding any issues, you are very welcome on our [Slack support channel](https://openspacesupport.slack.com) to which you can freely [sign-up](https://join.slack.com/t/openspacesupport/shared_invite/zt-37niq6y9-T0JaCIk4UoFLI4VF5U9Vsw). +# Background +OpenSpace started as a collaboration between Sweden's [Linköping University](https://scivis.github.io) (LiU) and the [American Museum of Natural History](https://www.amnh.org) (AMNH). Development of the software began several years ago through a close collaboration with NASA Goddard's [Community Coordinated Modeling Center](https://ccmc.gsfc.nasa.gov) (CCMC) to model space weather forecasting and continued with visualizations of NASA's New Horizons mission to Pluto and ESA's Rosetta mission to 67P/Churyumov–Gerasimenko. This promising set of preliminary work provided a foundation for continued funding from NASA, the Swedish eScience Research Centre, and the Knut and Alice Wallenberg foundation, which has extended the collaboration to include the University of Utah's [Scientific Computing and Imaging](https://www.sci.utah.edu) (SCI) Institute, [New York University](https://www.nyu.edu)'s Tandon School of Engineering, multiple informal science institutions across the world, and multiple, international vendors. + +![Image](https://github.com/OpenSpace/openspace.github.io/raw/master/assets/images/presentation.jpg) + +# Features +Some of the high-level features supported in OpenSpace are: + - AMNH's Digital Universe catalog of extrasolar datasets (stars, galaxies, quasars, ...) + - High-resolution planetary images for major objects in the solar system (Earth, Moon, Mars, Venus, ...) + - Animated 3D models representing space missions (ISS, New Horizons, JWST, ...) + - Support for custom profiles with arbitrary user-defined content + - Ability to drive any type of display environment (flat screen, multi-projector, planetariums, ...) + - Lua and JavaScript interface into the engine allowing highly customized controls + - Native support to export an interactive sessions as individual frames for video export + - much much more (see our [Changelog](http://wiki.openspaceproject.com/docs/general/releases)) + +OpenSpace requires at least support for [OpenGL](https://www.opengl.org/) version 3.3, some custom components require at least version 4.2. + +![Image](https://github.com/OpenSpace/openspace.github.io/raw/master/assets/images/display-systems.jpg) + +# Getting Started +This repository contains the source code and example profiles for OpenSpace, but does not contain any data. To build and install the application, please check out the [OpenSpace Wiki](http://wiki.openspaceproject.com/). Here, you will find two pages, a [build instruction](http://wiki.openspaceproject.com/docs/developers/compiling/general) for all operating systems and then additional instructions for [Windows](http://wiki.openspaceproject.com/docs/developers/compiling/windows), [Linux (Ubuntu)](http://wiki.openspaceproject.com/docs/developers/compiling/ubuntu), and [MacOS](http://wiki.openspaceproject.com/docs/developers/compiling/macos). + +Requirements for compiling are: + - CMake version 3.10 or above + - C++ compiler supporting C++17 (MSVC 16.10, GCC9, Clang10) + - [Boost](http://www.boost.org/) + - [Qt](http://www.qt.io/download) + +Feel free to create issues for missing features, bug reports, or compile problems or contact us via [email](mailto:openspace@amnh.org?subject=OpenSpace:). Regarding any issues, you are very welcome on our [Slack support channel](https://openspacesupport.slack.com) to which you can freely [sign-up](https://join.slack.com/t/openspacesupport/shared_invite/zt-37niq6y9-T0JaCIk4UoFLI4VF5U9Vsw). + +![Image](https://github.com/OpenSpace/openspace.github.io/raw/master/assets/images/himalaya-nkpg-dome.jpg) diff --git a/apps/OpenSpace/ext/launcher/CMakeLists.txt b/apps/OpenSpace/ext/launcher/CMakeLists.txt index 71126118cb..4dfa4eb535 100644 --- a/apps/OpenSpace/ext/launcher/CMakeLists.txt +++ b/apps/OpenSpace/ext/launcher/CMakeLists.txt @@ -27,6 +27,7 @@ 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/assetedit.h @@ -35,7 +36,6 @@ set(HEADER_FILES include/profile/cameradialog.h include/profile/deltatimesdialog.h include/profile/horizonsdialog.h - include/profile/keybindingsdialog.h include/profile/scriptlogdialog.h include/profile/line.h include/profile/marknodesdialog.h @@ -49,6 +49,7 @@ 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/assetedit.cpp @@ -57,7 +58,6 @@ set(SOURCE_FILES src/profile/cameradialog.cpp src/profile/deltatimesdialog.cpp src/profile/horizonsdialog.cpp - src/profile/keybindingsdialog.cpp src/profile/scriptlogdialog.cpp src/profile/line.cpp src/profile/marknodesdialog.cpp @@ -68,13 +68,9 @@ set(SOURCE_FILES src/profile/propertiesdialog.cpp ) -find_package(Qt5 COMPONENTS Widgets REQUIRED) -find_package(Qt5 COMPONENTS Network 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/assetedit.h @@ -82,7 +78,6 @@ qt5_wrap_cpp( include/profile/cameradialog.h include/profile/deltatimesdialog.h include/profile/horizonsdialog.h - include/profile/keybindingsdialog.h include/profile/scriptlogdialog.h include/profile/marknodesdialog.h include/profile/metadialog.h @@ -92,13 +87,42 @@ qt5_wrap_cpp( include/profile/propertiesdialog.h ) +find_package(QT NAMES Qt6 Qt5 COMPONENTS Core Widgets Network 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 Core Widgets Network) + 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 Core Widgets Network 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::Network 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 Qt${QT_VERSION_MAJOR}::Network +) if (MSVC) set(MSVC_WARNINGS diff --git a/apps/OpenSpace/ext/launcher/include/filesystemaccess.h b/apps/OpenSpace/ext/launcher/include/filesystemaccess.h index 6acdbb1c87..945fcb113d 100644 --- a/apps/OpenSpace/ext/launcher/include/filesystemaccess.h +++ b/apps/OpenSpace/ext/launcher/include/filesystemaccess.h @@ -34,10 +34,6 @@ public: * * \param fileExtension string that defines the filter used to find files. Only * files with this extension will be recognized (e.g. '.xml') - * \param approvedPaths vector or strings containing directory names to be included - * in the search. These are directories at the base level of - * the starting point of the search. Any sub-directories within - * these directories will be included. * \param hideFileExtensions if true then file extensions will be removed from the * listed files in the output * \param useCheckboxes if true then the text output format will contain a '0' as @@ -45,8 +41,7 @@ public: * used to represent checked ('1'), uncheck ('0') or doesn't * exist in filesystem ('x') states. */ - FileSystemAccess(std::string fileExtension, - std::vector approvedPaths, bool hideFileExtensions, + FileSystemAccess(std::string fileExtension, bool hideFileExtensions, bool useCheckboxes); /** @@ -54,7 +49,8 @@ public: * * \param dir The directory from which to start the search from */ - std::string useQtFileSystemModelToTraverseDir(std::string dir, bool usersAssets = false); + std::string useQtFileSystemModelToTraverseDir(std::string dir, + bool usersAssets = false); private: void parseChildDirElements(QFileInfo item, std::string space, int level, @@ -62,7 +58,6 @@ private: bool userAssets); void parseChildFile(std::string res, bool& hasDirHeaderBeenAdded, std::vector& dirNames, std::vector& output); - bool isApprovedPath(std::string path); QFileSystemModel _filesystemModel; QDir::Filters _fileFilterOptions = QDir::Files | QDir::Dirs | QDir::NoDotAndDotDot; diff --git a/apps/OpenSpace/ext/launcher/include/profile/actiondialog.h b/apps/OpenSpace/ext/launcher/include/profile/actiondialog.h new file mode 100644 index 0000000000..c08964631f --- /dev/null +++ b/apps/OpenSpace/ext/launcher/include/profile/actiondialog.h @@ -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 + +#include + +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* actions, + std::vector* 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* _actions = nullptr; + std::vector _actionData; + std::vector* _keybindings = nullptr; + std::vector _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__ diff --git a/apps/OpenSpace/ext/launcher/include/profile/additionalscriptsdialog.h b/apps/OpenSpace/ext/launcher/include/profile/additionalscriptsdialog.h index 9ff82c4e8b..40c330d9dd 100644 --- a/apps/OpenSpace/ext/launcher/include/profile/additionalscriptsdialog.h +++ b/apps/OpenSpace/ext/launcher/include/profile/additionalscriptsdialog.h @@ -27,11 +27,9 @@ #include -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* scripts); private slots: void parseScript(); @@ -57,7 +55,8 @@ private slots: private: void createWidgets(); - openspace::Profile& _profile; + std::vector* _scripts = nullptr; + std::vector _scriptsData; QTextEdit* _textScripts = nullptr; QPushButton* _chooseScriptsButton = nullptr; }; diff --git a/apps/OpenSpace/ext/launcher/include/profile/assetsdialog.h b/apps/OpenSpace/ext/launcher/include/profile/assetsdialog.h index 9a37605fd7..9f991ca65e 100644 --- a/apps/OpenSpace/ext/launcher/include/profile/assetsdialog.h +++ b/apps/OpenSpace/ext/launcher/include/profile/assetsdialog.h @@ -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(); @@ -63,7 +62,7 @@ private: QString createTextSummary(); void openAssetEditor(const std::string& asset); - openspace::Profile& _profile; + openspace::Profile* _profile = nullptr; AssetTreeModel _assetTreeModel; QTreeView* _assetTree = nullptr; QTextEdit* _summary = nullptr; diff --git a/apps/OpenSpace/ext/launcher/include/profile/assettreemodel.h b/apps/OpenSpace/ext/launcher/include/profile/assettreemodel.h index cce942a2d4..bfe3db62c7 100644 --- a/apps/OpenSpace/ext/launcher/include/profile/assettreemodel.h +++ b/apps/OpenSpace/ext/launcher/include/profile/assettreemodel.h @@ -31,7 +31,7 @@ #include "openspace/scene/profile.h" #include -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 diff --git a/apps/OpenSpace/ext/launcher/include/profile/cameradialog.h b/apps/OpenSpace/ext/launcher/include/profile/cameradialog.h index eeb6a32c06..3f60f6953a 100644 --- a/apps/OpenSpace/ext/launcher/include/profile/cameradialog.h +++ b/apps/OpenSpace/ext/launcher/include/profile/cameradialog.h @@ -27,13 +27,14 @@ #include -namespace openspace { class Profile; } +#include +#include 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* camera); private slots: void approved(); @@ -57,7 +58,7 @@ private: void addErrorMsg(QString errorDescription); bool areRequiredFormsFilledAndValid(); - openspace::Profile& _profile; + std::optional* _camera = nullptr; QTabWidget* _tabWidget = nullptr; struct { QLineEdit* anchor = nullptr; diff --git a/apps/OpenSpace/ext/launcher/include/profile/deltatimesdialog.h b/apps/OpenSpace/ext/launcher/include/profile/deltatimesdialog.h index 744a1db8ac..76c9184c25 100644 --- a/apps/OpenSpace/ext/launcher/include/profile/deltatimesdialog.h +++ b/apps/OpenSpace/ext/launcher/include/profile/deltatimesdialog.h @@ -27,15 +27,13 @@ #include -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* 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 _data; + std::vector* _deltaTimes = nullptr; + std::vector _deltaTimesData; bool _editModeNewItem = false; QListWidget* _listWidget = nullptr; diff --git a/apps/OpenSpace/ext/launcher/include/profile/keybindingsdialog.h b/apps/OpenSpace/ext/launcher/include/profile/keybindingsdialog.h deleted file mode 100644 index 34097a0b2a..0000000000 --- a/apps/OpenSpace/ext/launcher/include/profile/keybindingsdialog.h +++ /dev/null @@ -1,118 +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 - -#include -#include -#include - -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); - - /** - * 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& mapVector, int keyInt); - bool areRequiredFormsFilled(); - bool isLineEmpty(int index); - - openspace::Profile& _profile; - std::vector _data; - std::vector _mapModKeyComboBoxIndexToKeyValue; - std::vector _mapKeyComboBoxIndexToKeyValue; - bool _editModeNewItem = false; - - 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__ diff --git a/apps/OpenSpace/ext/launcher/include/profile/marknodesdialog.h b/apps/OpenSpace/ext/launcher/include/profile/marknodesdialog.h index f20d680f92..8ff3fd7cd6 100644 --- a/apps/OpenSpace/ext/launcher/include/profile/marknodesdialog.h +++ b/apps/OpenSpace/ext/launcher/include/profile/marknodesdialog.h @@ -27,14 +27,12 @@ #include -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* markedNodes); /** * Handles keypress while the Qt dialog window is open @@ -63,8 +61,8 @@ private: void createWidgets(); std::vector _markedNodesListItems; - openspace::Profile& _profile; - std::vector _data; + std::vector* _markedNodes; + std::vector _markedNodesData; QListWidget* _list = nullptr; QPushButton* _removeButton = nullptr; diff --git a/apps/OpenSpace/ext/launcher/include/profile/metadialog.h b/apps/OpenSpace/ext/launcher/include/profile/metadialog.h index 51c500f972..b8d784aabb 100644 --- a/apps/OpenSpace/ext/launcher/include/profile/metadialog.h +++ b/apps/OpenSpace/ext/launcher/include/profile/metadialog.h @@ -27,12 +27,13 @@ #include -namespace openspace { class Profile; } +#include +#include 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* meta); private slots: void save(); @@ -50,7 +51,7 @@ private slots: private: void createWidgets(); - openspace::Profile& _profile; + std::optional* _meta = nullptr; QLineEdit* _nameEdit = nullptr; QLineEdit* _versionEdit = nullptr; diff --git a/apps/OpenSpace/ext/launcher/include/profile/modulesdialog.h b/apps/OpenSpace/ext/launcher/include/profile/modulesdialog.h index 6533eff4ba..4245e5ff88 100644 --- a/apps/OpenSpace/ext/launcher/include/profile/modulesdialog.h +++ b/apps/OpenSpace/ext/launcher/include/profile/modulesdialog.h @@ -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* 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 _data; + std::vector* _modules = nullptr; + std::vector _moduleData; bool _editModeNewItem = false; QListWidget* _list = nullptr; diff --git a/apps/OpenSpace/ext/launcher/include/profile/profileedit.h b/apps/OpenSpace/ext/launcher/include/profile/profileedit.h index 2f7a655a09..f83fa1f458 100644 --- a/apps/OpenSpace/ext/launcher/include/profile/profileedit.h +++ b/apps/OpenSpace/ext/launcher/include/profile/profileedit.h @@ -36,7 +36,7 @@ class QLabel; class QLineEdit; class QTextEdit; -class ProfileEdit : public QDialog { +class ProfileEdit final : public QDialog { Q_OBJECT public: /** diff --git a/apps/OpenSpace/ext/launcher/include/profile/propertiesdialog.h b/apps/OpenSpace/ext/launcher/include/profile/propertiesdialog.h index 0938bc8659..c3ce1a1402 100644 --- a/apps/OpenSpace/ext/launcher/include/profile/propertiesdialog.h +++ b/apps/OpenSpace/ext/launcher/include/profile/propertiesdialog.h @@ -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* 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 _data; + std::vector* _properties = nullptr; + std::vector _propertyData; bool _editModeNewItem = false; QListWidget* _list = nullptr; diff --git a/apps/OpenSpace/ext/launcher/include/profile/scriptlogdialog.h b/apps/OpenSpace/ext/launcher/include/profile/scriptlogdialog.h index 34a5a0e555..dc970494f5 100644 --- a/apps/OpenSpace/ext/launcher/include/profile/scriptlogdialog.h +++ b/apps/OpenSpace/ext/launcher/include/profile/scriptlogdialog.h @@ -25,11 +25,10 @@ #ifndef __OPENSPACE_UI_LAUNCHER___SCRIPTLOG___H__ #define __OPENSPACE_UI_LAUNCHER___SCRIPTLOG___H__ -#include "profile/keybindingsdialog.h" #include #include -class ScriptlogDialog : public QDialog { +class ScriptlogDialog final : public QDialog { Q_OBJECT public: /** diff --git a/apps/OpenSpace/ext/launcher/include/profile/timedialog.h b/apps/OpenSpace/ext/launcher/include/profile/timedialog.h index 394b477f0f..81ddf0d144 100644 --- a/apps/OpenSpace/ext/launcher/include/profile/timedialog.h +++ b/apps/OpenSpace/ext/launcher/include/profile/timedialog.h @@ -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* 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* _time = nullptr; + openspace::Profile::Time _timeData; bool _initializedAsAbsolute = true; QComboBox* _typeCombo = nullptr; diff --git a/apps/OpenSpace/ext/launcher/resources/qss/launcher.qss b/apps/OpenSpace/ext/launcher/resources/qss/launcher.qss index 032ac15ccc..fcf37934bb 100644 --- a/apps/OpenSpace/ext/launcher/resources/qss/launcher.qss +++ b/apps/OpenSpace/ext/launcher/resources/qss/launcher.qss @@ -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 { @@ -115,15 +115,26 @@ PropertiesDialog QListWidget { */ AssetsDialog QTreeView { min-width: 40em; + min-height: 40em; } /* - * 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 */ diff --git a/apps/OpenSpace/ext/launcher/src/filesystemaccess.cpp b/apps/OpenSpace/ext/launcher/src/filesystemaccess.cpp index 9912c3bead..f58665913d 100644 --- a/apps/OpenSpace/ext/launcher/src/filesystemaccess.cpp +++ b/apps/OpenSpace/ext/launcher/src/filesystemaccess.cpp @@ -25,15 +25,14 @@ #include "filesystemaccess.h" FileSystemAccess::FileSystemAccess(std::string fileExtension, - std::vector approvedPaths, bool hideFileExtensions, bool useCheckboxes) : _fileExtension(std::move(fileExtension)) - , _approvedPaths(std::move(approvedPaths)) , _hideFileExtensions(hideFileExtensions) , _useCheckboxes(useCheckboxes) {} -std::string FileSystemAccess::useQtFileSystemModelToTraverseDir(std::string dir, bool userAssets) { +std::string FileSystemAccess::useQtFileSystemModelToTraverseDir(std::string dir, + bool userAssets) { _filesystemModel.setRootPath(QString::fromStdString(dir)); QModelIndex index = _filesystemModel.index(_filesystemModel.rootPath()); QFileInfo fileInfo = _filesystemModel.fileInfo(index); @@ -48,8 +47,10 @@ std::string FileSystemAccess::useQtFileSystemModelToTraverseDir(std::string dir, } void FileSystemAccess::parseChildDirElements(QFileInfo fileInfo, std::string space, - int level, std::vector& dirNames, - std::vector& output, bool userAssets) + int level, + std::vector& dirNames, + std::vector& output, + bool userAssets) { QDir dir(fileInfo.filePath()); bool hasDirHeaderBeenAdded = false; @@ -62,10 +63,8 @@ void FileSystemAccess::parseChildDirElements(QFileInfo fileInfo, std::string spa res = "${USER_ASSETS}/" + res; } if (fi.isDir()) { - if (level != 0 || (level == 0 && (isApprovedPath(res) || userAssets))) { - dirNames.push_back(res); - parseChildDirElements(fi, (space + " "), level + 1, dirNames, output, userAssets); - } + dirNames.push_back(res); + parseChildDirElements(fi, (space + " "), level + 1, dirNames, output, userAssets); } else { parseChildFile(res, hasDirHeaderBeenAdded, dirNames, output); @@ -77,19 +76,6 @@ void FileSystemAccess::parseChildDirElements(QFileInfo fileInfo, std::string spa } } -bool FileSystemAccess::isApprovedPath(std::string path) { - bool approvedMatch = false; - path.erase(0, path.find_first_not_of(" ")); - - for (const std::string& p : _approvedPaths) { - if (path.substr(0, p.length()).compare(p) == 0) { - approvedMatch = true; - break; - } - } - return approvedMatch; -} - void FileSystemAccess::parseChildFile(std::string filename, bool& hasDirHeaderBeenAdded, std::vector& dirNames, std::vector& output) diff --git a/apps/OpenSpace/ext/launcher/src/launcherwindow.cpp b/apps/OpenSpace/ext/launcher/src/launcherwindow.cpp index a7ebe492c3..d30eac9af3 100644 --- a/apps/OpenSpace/ext/launcher/src/launcherwindow.cpp +++ b/apps/OpenSpace/ext/launcher/src/launcherwindow.cpp @@ -28,16 +28,18 @@ #include #include +#include #include #include #include #include #include #include +#include #include +#include #include #include -#include using namespace openspace; @@ -312,8 +314,24 @@ void LauncherWindow::setBackgroundImage(const std::string& syncPath) { std::mt19937 g(rd()); std::shuffle(files.begin(), files.end(), g); // We know there has to be at least one folder, so it's fine to just pick the first - std::string image = files.front(); - _backgroundImage->setPixmap(QPixmap(QString::fromStdString(image))); + while (!files.empty()) { + std::string p = files.front(); + if (std::filesystem::path(p).extension() == ".png") { + // If the top path starts with the png extension, we have found our candidate + break; + } + else { + // There shouldn't be any non-png images in here, but you never know. So we + // just remove non-image files here + files.erase(files.begin()); + } + } + + // There better be at least one file left, but just in in case + if (!files.empty()) { + std::string image = files.front(); + _backgroundImage->setPixmap(QPixmap(QString::fromStdString(image))); + } } void LauncherWindow::populateProfilesList(std::string preset) { @@ -462,7 +480,7 @@ std::string LauncherWindow::selectedWindowConfig() const { int idx = _windowConfigBox->currentIndex(); if (idx == 0) { return _sgctConfigName; - } else if (idx > _userAssetCount) { + } else if (idx > _userConfigCount) { return "${CONFIG}/" + _windowConfigBox->currentText().toStdString(); } else { diff --git a/apps/OpenSpace/ext/launcher/src/profile/actiondialog.cpp b/apps/OpenSpace/ext/launcher/src/profile/actiondialog.cpp new file mode 100644 index 0000000000..8dbdf4471e --- /dev/null +++ b/apps/OpenSpace/ext/launcher/src/profile/actiondialog.cpp @@ -0,0 +1,725 @@ +/***************************************************************************************** + * * + * 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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +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* actions, + std::vector* 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) { + // We don't want to use the Shift, Alt, and Ctrl keys directly since we already + // have them as modifier keys + if (ki.key == Key::LeftShift || ki.key == Key::RightShift || + ki.key == Key::LeftAlt || ki.key == Key::RightAlt || + ki.key == Key::LeftControl || ki.key == Key::RightControl || + ki.key == Key::LeftSuper || ki.key == Key::RightSuper || + ki.key == Key::Menu || ki.key == Key::NumLock || + ki.key == Key::World1 || ki.key == Key::World2) + { + continue; + } + keyList += QString::fromStdString(std::string(ki.name)); + } + _keybindingWidgets.key->addItems(keyList); + _keybindingWidgets.key->setCurrentIndex(-1); + _keybindingWidgets.key->setEnabled(false); + connect( + _keybindingWidgets.key, QOverload::of(&QComboBox::currentIndexChanged), + [this](int newIndex) { + _keybindingWidgets.saveButtons->button(QDialogButtonBox::Save)->setEnabled( + newIndex > 0 + ); + } + ); + 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::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(_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(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(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(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); + // Only enable the save buttons if a key is selected, otherwise we would get an + // exception as the None key cannot be bound + _keybindingWidgets.saveButtons->button(QDialogButtonBox::Save)->setEnabled( + _keybindingWidgets.key->currentIndex() > 0 + ); + } + 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 keybinding 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(); +} diff --git a/apps/OpenSpace/ext/launcher/src/profile/additionalscriptsdialog.cpp b/apps/OpenSpace/ext/launcher/src/profile/additionalscriptsdialog.cpp index 6c91f58e1d..60ea7b3513 100644 --- a/apps/OpenSpace/ext/launcher/src/profile/additionalscriptsdialog.cpp +++ b/apps/OpenSpace/ext/launcher/src/profile/additionalscriptsdialog.cpp @@ -33,18 +33,19 @@ #include #include #include +#include -AdditionalScriptsDialog::AdditionalScriptsDialog(openspace::Profile& profile, - QWidget* parent) +AdditionalScriptsDialog::AdditionalScriptsDialog(QWidget* parent, + std::vector* scripts) : QDialog(parent) - , _profile(profile) + , _scripts(scripts) + , _scriptsData(*_scripts) { setWindowTitle("Additional Scripts"); createWidgets(); - std::vector 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(); } diff --git a/apps/OpenSpace/ext/launcher/src/profile/assetsdialog.cpp b/apps/OpenSpace/ext/launcher/src/profile/assetsdialog.cpp index 13843348cc..52611af489 100644 --- a/apps/OpenSpace/ext/launcher/src/profile/assetsdialog.cpp +++ b/apps/OpenSpace/ext/launcher/src/profile/assetsdialog.cpp @@ -28,6 +28,7 @@ #include "profile/line.h" #include +#include #include #include #include @@ -125,17 +126,15 @@ 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) { setWindowTitle("Assets"); _assetTreeModel.importModelData(assetBasePath, userAssetBasePath); - createWidgets(); -} -void AssetsDialog::createWidgets() { QBoxLayout* layout = new QVBoxLayout(this); { QGridLayout* container = new QGridLayout; @@ -177,10 +176,10 @@ void AssetsDialog::createWidgets() { 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)); @@ -190,18 +189,19 @@ void AssetsDialog::createWidgets() { nRows, _assetTreeModel.index(-1, 0) ); - layout->addWidget(_assetTree); + layout->addWidget(_assetTree, 4); } { + QWidget* box = new QWidget; + QBoxLayout* boxLayout = new QVBoxLayout(box); QLabel* summaryHeading = new QLabel("Selection summary"); summaryHeading->setObjectName("heading"); - layout->addWidget(summaryHeading); - } - { + boxLayout->addWidget(summaryHeading); _summary = new QTextEdit; _summary->setReadOnly(true); _summary->setText(createTextSummary()); - layout->addWidget(_summary); + boxLayout->addWidget(_summary); + layout->addWidget(box, 1); } layout->addWidget(new Line); @@ -247,13 +247,13 @@ void AssetsDialog::openAssetEditor(const std::string& asset) { } void AssetsDialog::parseSelections() { - _profile.clearAssets(); + _profile->assets.clear(); std::vector summaryPaths; std::vector summaryItems; _assetTreeModel.getSelectedAssets(summaryPaths, summaryItems); for (const std::string& sel : summaryPaths) { - _profile.addAsset(sel); + _profile->addAsset(sel); } accept(); } diff --git a/apps/OpenSpace/ext/launcher/src/profile/assettreemodel.cpp b/apps/OpenSpace/ext/launcher/src/profile/assettreemodel.cpp index 53521995f6..e588b103bd 100644 --- a/apps/OpenSpace/ext/launcher/src/profile/assettreemodel.cpp +++ b/apps/OpenSpace/ext/launcher/src/profile/assettreemodel.cpp @@ -149,9 +149,6 @@ void AssetTreeModel::importModelData(const std::string& assetBasePath, const std::string& userAssetBasePath) { FileSystemAccess assets( ".asset", - // @TODO (abock, 2021-03-24) We need some better solution for this; what is the - // problem of just including all subfolders instead? - { "scene", "global", "customization", "dashboard", "examples", "util" }, true, true ); diff --git a/apps/OpenSpace/ext/launcher/src/profile/cameradialog.cpp b/apps/OpenSpace/ext/launcher/src/profile/cameradialog.cpp index c5adbc8c6d..2b8d6f4aef 100644 --- a/apps/OpenSpace/ext/launcher/src/profile/cameradialog.cpp +++ b/apps/OpenSpace/ext/launcher/src/profile/cameradialog.cpp @@ -25,7 +25,6 @@ #include "profile/cameradialog.h" #include "profile/line.h" -#include #include #include #include @@ -56,15 +55,16 @@ namespace { } } // namespace -CameraDialog::CameraDialog(openspace::Profile& profile, QWidget *parent) +CameraDialog::CameraDialog(QWidget* parent, + std::optional* 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(); diff --git a/apps/OpenSpace/ext/launcher/src/profile/deltatimesdialog.cpp b/apps/OpenSpace/ext/launcher/src/profile/deltatimesdialog.cpp index 33db001533..2c23da48ff 100644 --- a/apps/OpenSpace/ext/launcher/src/profile/deltatimesdialog.cpp +++ b/apps/OpenSpace/ext/launcher/src/profile/deltatimesdialog.cpp @@ -26,6 +26,7 @@ #include "profile/line.h" #include +#include #include #include #include @@ -79,16 +80,15 @@ namespace { } } // namespace -DeltaTimesDialog::DeltaTimesDialog(openspace::Profile& profile, QWidget *parent) +DeltaTimesDialog::DeltaTimesDialog(QWidget* parent, std::vector* 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(_data.size()) - 1)) { + if (index < (static_cast(_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(_data.size())) { - index = static_cast(_data.size()) - 1; + if (index >= static_cast(_deltaTimesData.size())) { + index = static_cast(_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(_data.size()) - 1; + int finalNonzeroIndex = static_cast(_deltaTimesData.size()) - 1; for (; finalNonzeroIndex >= 0; --finalNonzeroIndex) { - if (_data.at(finalNonzeroIndex) != 0) { + if (_deltaTimesData.at(finalNonzeroIndex) != 0) { break; } } std::vector 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(); } diff --git a/apps/OpenSpace/ext/launcher/src/profile/keybindingsdialog.cpp b/apps/OpenSpace/ext/launcher/src/profile/keybindingsdialog.cpp deleted file mode 100644 index 273dde9ab6..0000000000 --- a/apps/OpenSpace/ext/launcher/src/profile/keybindingsdialog.cpp +++ /dev/null @@ -1,542 +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 -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -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(k.key.modifier); - if (keymod != static_cast(KeyModifier::NoModifier)) { - summary += KeyModifierNames.at(keymod) + " "; - } - int keyname = static_cast(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& m : KeyModifierNames) { - comboModKeysStringList += QString::fromStdString(m.second); - _mapModKeyComboBoxIndexToKeyValue.push_back(modIdx++); - } - _keyModCombo->addItems(comboModKeysStringList); - 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(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::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); - - if (_data.size() > 0) { - Profile::Keybinding& k = _data[index]; - const int modifierKey = indexInKeyMapping( - _mapModKeyComboBoxIndexToKeyValue, - static_cast(k.key.modifier) - ); - _keyModCombo->setCurrentIndex(modifierKey); - - if (k.key.key == Key::Unknown) { - _keyCombo->setCurrentIndex(0); - } - else { - const int key = indexInKeyMapping( - _mapKeyComboBoxIndexToKeyValue, - static_cast(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) { - const QString numKeyWarning = "Warning: Using a number key may conflict with the " - "keybindings for simulation time increments."; - QString errorContents = _errorMsg->text(); - bool alreadyContainsWarning = (errorContents.length() >= numKeyWarning.length() && - errorContents.left(numKeyWarning.length()) == numKeyWarning); - if (_mapKeyComboBoxIndexToKeyValue[index] >= static_cast(Key::Num0) - && _mapKeyComboBoxIndexToKeyValue[index] <= static_cast(Key::Num9)) - { - if (!alreadyContainsWarning) { - errorContents = numKeyWarning + errorContents; - _errorMsg->setText(errorContents); - } - } - else if (alreadyContainsWarning) { - _errorMsg->setText(errorContents.mid(numKeyWarning.length())); - } -} - -int KeybindingsDialog::indexInKeyMapping(std::vector& mapVector, int keyInt) { - const auto it = std::find(mapVector.cbegin(), mapVector.cend(), keyInt); - return static_cast(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(_data.back().key.modifier)); - if (_data.back().key.key == Key::Unknown) { - _keyCombo->setCurrentIndex(0); - } - else { - _keyCombo->setCurrentIndex(static_cast(_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)); - - _editModeNewItem = true; -} - -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(keyModIdx); - int keyIdx = _mapKeyComboBoxIndexToKeyValue.at(_keyCombo->currentIndex()); - _data[index].key.key = static_cast(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("Key"); - _keyModLabel->setText("Key Modifier"); - _nameLabel->setText("Name"); - _scriptLabel->setText("Script"); - _guiPathLabel->setText("GUI Path"); - _documentationLabel->setText("Documentation"); - - 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("Key"); - _keyModLabel->setText("Key Modifier"); - _nameLabel->setText("Name"); - _scriptLabel->setText("Script"); - _guiPathLabel->setText("GUI Path"); - _documentationLabel->setText("Documentation"); - 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); -} - diff --git a/apps/OpenSpace/ext/launcher/src/profile/marknodesdialog.cpp b/apps/OpenSpace/ext/launcher/src/profile/marknodesdialog.cpp index 9af27989c7..418c47a0d9 100644 --- a/apps/OpenSpace/ext/launcher/src/profile/marknodesdialog.cpp +++ b/apps/OpenSpace/ext/launcher/src/profile/marknodesdialog.cpp @@ -35,10 +35,10 @@ #include #include -MarkNodesDialog::MarkNodesDialog(openspace::Profile& profile, QWidget* parent) +MarkNodesDialog::MarkNodesDialog(QWidget* parent, std::vector* 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(std::distance(_data.cbegin(), it))); + const auto it = std::find( + _markedNodesData.cbegin(), _markedNodesData.cend(), + itemToAdd + ); + if (it != _markedNodesData.end()) { + _list->setCurrentRow( + static_cast(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(); } diff --git a/apps/OpenSpace/ext/launcher/src/profile/metadialog.cpp b/apps/OpenSpace/ext/launcher/src/profile/metadialog.cpp index 1edba2fdee..599307a729 100644 --- a/apps/OpenSpace/ext/launcher/src/profile/metadialog.cpp +++ b/apps/OpenSpace/ext/launcher/src/profile/metadialog.cpp @@ -34,32 +34,32 @@ #include #include -MetaDialog::MetaDialog(openspace::Profile& profile, QWidget *parent) +MetaDialog::MetaDialog(QWidget* parent, std::optional* 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(); } diff --git a/apps/OpenSpace/ext/launcher/src/profile/modulesdialog.cpp b/apps/OpenSpace/ext/launcher/src/profile/modulesdialog.cpp index 7359026d7e..871b9647fe 100644 --- a/apps/OpenSpace/ext/launcher/src/profile/modulesdialog.cpp +++ b/apps/OpenSpace/ext/launcher/src/profile/modulesdialog.cpp @@ -40,10 +40,11 @@ namespace { const Profile::Module Blank = { "", "", "" }; } // namespace -ModulesDialog::ModulesDialog(Profile& profile, QWidget *parent) +ModulesDialog::ModulesDialog(QWidget* parent, + std::vector* 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(); } diff --git a/apps/OpenSpace/ext/launcher/src/profile/profileedit.cpp b/apps/OpenSpace/ext/launcher/src/profile/profileedit.cpp index 6f6a9cea0c..04dc395b88 100644 --- a/apps/OpenSpace/ext/launcher/src/profile/profileedit.cpp +++ b/apps/OpenSpace/ext/launcher/src/profile/profileedit.cpp @@ -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 +#include #include #include #include @@ -69,17 +70,18 @@ namespace { return results; } - std::string summarizeKeybindings(const std::vector& keybindings) + std::string summarizeKeybindings(const std::vector& keybindings, + const std::vector& actions) { std::string results; for (Profile::Keybinding k : keybindings) { - results += k.name + " ("; - int keymod = static_cast(k.key.modifier); - if (keymod != static_cast(openspace::KeyModifier::NoModifier)) { - results += openspace::KeyModifierNames.at(keymod) + "+"; - } - results += openspace::KeyNames.at(static_cast(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& 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") ); } diff --git a/apps/OpenSpace/ext/launcher/src/profile/propertiesdialog.cpp b/apps/OpenSpace/ext/launcher/src/profile/propertiesdialog.cpp index 3a9441154e..a57548b5a2 100644 --- a/apps/OpenSpace/ext/launcher/src/profile/propertiesdialog.cpp +++ b/apps/OpenSpace/ext/launcher/src/profile/propertiesdialog.cpp @@ -46,10 +46,11 @@ namespace { }; } // namespace -PropertiesDialog::PropertiesDialog(Profile& profile, QWidget *parent) +PropertiesDialog::PropertiesDialog(QWidget* parent, + std::vector* 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(); } diff --git a/apps/OpenSpace/ext/launcher/src/profile/timedialog.cpp b/apps/OpenSpace/ext/launcher/src/profile/timedialog.cpp index 03d9526b82..efbcf4293c 100644 --- a/apps/OpenSpace/ext/launcher/src/profile/timedialog.cpp +++ b/apps/OpenSpace/ext/launcher/src/profile/timedialog.cpp @@ -37,20 +37,20 @@ using namespace openspace; -TimeDialog::TimeDialog(openspace::Profile& profile, QWidget* parent) +TimeDialog::TimeDialog(QWidget* parent, std::optional* 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 = "0d"; } _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 = "0d"; } - _initializedAsAbsolute = (_data.type == Profile::Time::Type::Absolute); - enableAccordingToType(static_cast(_data.type)); + _initializedAsAbsolute = (_timeData.type == Profile::Time::Type::Absolute); + enableAccordingToType(static_cast(_timeData.type)); } void TimeDialog::createWidgets() { @@ -114,18 +114,18 @@ void TimeDialog::enableAccordingToType(int idx) { if (comboIdx == Profile::Time::Type::Relative) { _relativeEdit->setText("Relative Time:"); if (_initializedAsAbsolute) { - _relativeEdit->setText("now"); + _relativeEdit->setText("0d"); } else { - _relativeEdit->setText(QString::fromStdString(_data.value)); + _relativeEdit->setText(QString::fromStdString(_timeData.value)); } _relativeEdit->setFocus(Qt::OtherFocusReason); } else { _relativeEdit->setText("Relative Time:"); - 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(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(); } diff --git a/apps/OpenSpace/ext/sgct b/apps/OpenSpace/ext/sgct index 2a3ef78f72..0a4596ff2e 160000 --- a/apps/OpenSpace/ext/sgct +++ b/apps/OpenSpace/ext/sgct @@ -1 +1 @@ -Subproject commit 2a3ef78f721e919531bb05b0cedab2dabe2bb0be +Subproject commit 0a4596ff2ea90c9f0dfbddd7b14f7ecee783baf1 diff --git a/apps/OpenSpace/main.cpp b/apps/OpenSpace/main.cpp index dfd8b32c52..c5943742a6 100644 --- a/apps/OpenSpace/main.cpp +++ b/apps/OpenSpace/main.cpp @@ -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; @@ -997,8 +997,7 @@ std::string selectedSgctProfileFromLauncher(LauncherWindow& lw, bool hasCliSGCTC } } else { - if ( (config.length() >= xmlExt.length()) - && (0 == config.compare(config.length() - xmlExt.length(), xmlExt.length(), xmlExt)) ) { + if (std::filesystem::path(config).extension() == ".xml") { //user customzied sgct config } else { @@ -1046,8 +1045,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 +1159,6 @@ int main(int argc, char* argv[]) { const std::string xmlExt = ".xml"; std::string windowCfgPreset = setWindowConfigPresetForGui( labelFromCfgFile, - xmlExt, hasSGCTConfig, sgctFunctionName ); diff --git a/apps/Wormhole/main.cpp b/apps/Wormhole/main.cpp index f38d7f130a..1faa0b7c5d 100644 --- a/apps/Wormhole/main.cpp +++ b/apps/Wormhole/main.cpp @@ -129,4 +129,4 @@ int main(int argc, char** argv) { LINFO("Server stopped"); return 0; -}; +} diff --git a/config/fullscreen1080.xml b/config/fullscreen1080.xml index 3b7f94c4cc..52d703f435 100644 --- a/config/fullscreen1080.xml +++ b/config/fullscreen1080.xml @@ -4,7 +4,7 @@ - + diff --git a/config/single_sbs_stereo.xml b/config/single_sbs_stereo.xml index 595d92cafb..e0707559c1 100644 --- a/config/single_sbs_stereo.xml +++ b/config/single_sbs_stereo.xml @@ -1,22 +1,16 @@ - + + + + - - - - - - + + + + + - - - - - - - - - + @@ -24,7 +18,7 @@ - + diff --git a/config/spout_output.xml b/config/spout_output.xml index bac296112f..da4efdc48f 100644 --- a/config/spout_output.xml +++ b/config/spout_output.xml @@ -7,7 +7,7 @@ - + diff --git a/data/assets/actions/toggle_trail.asset b/data/assets/actions/toggle_trail.asset new file mode 100644 index 0000000000..d3c5848d6c --- /dev/null +++ b/data/assets/actions/toggle_trail.asset @@ -0,0 +1,105 @@ +local toggle_trail = { + Identifier = "os.toggle_trail", + Name = "Toggle Trail", + Command = [[ + local node + if is_declared("args") then + node = args.Node + else + node = openspace.navigation.getNavigationState().Anchor + end + + local trail + if openspace.hasSceneGraphNode(node .. "Trail") then + trail = node .. "Trail" + elseif openspace.hasSceneGraphNode(node .. "_trail") then + trail = node .. "_trail" + else + -- No trail found, so nothing more to do here + return + end + + local visibility + if is_declared("args") then + if args.Transition == "Approaching" then + visibility = false + elseif args.Transition == "Exiting" then + visibility = true + else + return + end + else + visibility = not openspace.getPropertyValue("Scene." .. trail .. ".Renderable.Enabled") + end + + openspace.setPropertyValueSingle("Scene." .. trail .. ".Renderable.Enabled", visibility) + ]], + Documentation = [[Toggles the visibility of the associated trail of a scene graph node. + This action takes optional arguments to 1) determine which trail to hide (as the + 'Node') and 2) the transition direction (as 'After' and 'Before').]], + GuiPath = "/Trails", + IsLocal = true +} +asset.export("toggle_trail", toggle_trail.Identifier) + +local hide_trail = { + Identifier = "os.hide_trail", + Name = "Hide Trail", + Command = [[ + local node + if is_declared("args") then + node = args.Node + else + node = openspace.navigation.getNavigationState().Anchor + end + + if openspace.hasSceneGraphNode(node .. "Trail") then + openspace.setPropertyValue("Scene." .. node .. "Trail.Renderable.Enabled", false) + elseif openspace.hasSceneGraphNode(node .. "_trail") then + openspace.setPropertyValue("Scene." .. node .. "_trail.Renderable.Enabled", false) + end + ]], + Documentation = [[Hides the associated trail of a scene graph node. This action takes an + optional argument to determine whose trail to hide. If no argument is provided, the + current focus node is used instead]], + GuiPath = "/Trails", + IsLocal = true +} +asset.export("hide_trail", hide_trail.Identifier) + +local show_trail = { + Identifier = "os.show_trail", + Name = "Show Trail", + Command = [[ + local node + if is_declared("args") then + node = args.Node + else + node = openspace.navigation.getNavigationState().Anchor + end + + if openspace.hasSceneGraphNode(node .. "Trail") then + openspace.setPropertyValue("Scene." .. node .. "Trail.Renderable.Enabled", true) + elseif openspace.hasSceneGraphNode(node .. "_trail") then + openspace.setPropertyValue("Scene." .. node .. "_trail.Renderable.Enabled", true) + end + ]], + Documentation = [[Shows the associated trail of a scene graph node. This action takes an + optional argument to determine whose trail to hide. If no argument is provided, the + current focus node is used instead]], + GuiPath = "/Trails", + IsLocal = true +} +asset.export("show_trail", show_trail.Identifier) + +asset.onInitialize(function() + openspace.action.registerAction(toggle_trail) + openspace.action.registerAction(show_trail) + openspace.action.registerAction(hide_trail) +end) + +asset.onDeinitialize(function() + openspace.action.removeAction(toggle_trail.Identifier) + openspace.action.removeAction(show_trail.Identifier) + openspace.action.removeAction(hide_trail.Identifier) +end) diff --git a/data/assets/base_blank.asset b/data/assets/base_blank.asset index b318dcf2fd..6c47bea5d9 100644 --- a/data/assets/base_blank.asset +++ b/data/assets/base_blank.asset @@ -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) diff --git a/data/assets/events/toggle_trail.asset b/data/assets/events/toggle_trail.asset new file mode 100644 index 0000000000..2e397ed7d8 --- /dev/null +++ b/data/assets/events/toggle_trail.asset @@ -0,0 +1,27 @@ +local action = asset.require('actions/toggle_trail') + +asset.onInitialize(function() + openspace.event.registerEventAction( + "CameraFocusTransition", + action.show_trail, + { Transition = "Exiting" } + ); + openspace.event.registerEventAction( + "CameraFocusTransition", + action.hide_trail, + { Transition = "Approaching" } + ); +end) + +asset.onDeinitialize(function() + openspace.event.unregisterEventAction( + "CameraFocusTransition", + action.show_trail, + { Transition = "Exiting" } + ); + openspace.event.unregisterEventAction( + "CameraFocusTransition", + action.hide_trail, + { Transition = "Approaching" } + ); +end) diff --git a/data/assets/examples/approachevents.asset b/data/assets/examples/approachevents.asset new file mode 100644 index 0000000000..47ddc3281c --- /dev/null +++ b/data/assets/examples/approachevents.asset @@ -0,0 +1,68 @@ +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 generic_action = { + Identifier = "os.example.generic", + Name = "Generic Example", + Command = [[ + openspace.printInfo("Node: " .. args.Node) + openspace.printInfo("Transition: " .. args.Transition) + ]], + Documentation = "Prints the argument information for camera transitions to the log", + GuiPath = "/Examples/Events", + IsLocal = true +} + +local model = asset.syncedResource({ + Name = "Animated Box", + Type = "HttpSynchronization", + Identifier = "animated_box", + Version = 1 +}) + +local obj = { + Identifier = "ExampleEventModel", + Parent = transforms.EarthCenter.Identifier, + Transform = { + Translation = { + Type = "StaticTranslation", + Position = { 0.0, 11E7, 0.0 } + } + }, + Renderable = { + Type = "RenderableModel", + GeometryFile = model .. "/BoxAnimated.glb", + ModelScale = 1.0, + LightSources = { + { + Type = "SceneGraphLightSource", + Identifier = "Sun", + Node = sunTransforms.SolarSystemBarycenter.Identifier, + Intensity = 1.0 + } + }, + PerformShading = true, + DisableFaceCulling = true + }, + InteractionSphere = 1000.0, + OnApproach = { "os.example.generic" }, + OnReach = { "os.example.generic" }, + OnRecede = { "os.example.generic" }, + OnExit = { "os.example.generic" }, + GUI = { + Name = "Example Event Model", + Path = "/Example", + Description = "", + } +} + +asset.onInitialize(function() + openspace.action.registerAction(generic_action) + openspace.addSceneGraphNode(obj) +end) + +asset.onDeinitialize(function() + openspace.removeSceneGraphNode(obj.Identifier) + openspace.action.removeAction(generic_action.Identifier) +end) diff --git a/data/assets/examples/basic.scene b/data/assets/examples/basic.scene index b8c3eba619..a4ca571d1b 100644 --- a/data/assets/examples/basic.scene +++ b/data/assets/examples/basic.scene @@ -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') diff --git a/data/assets/examples/debugcoordinateaxes.asset b/data/assets/examples/debugcoordinateaxes.asset index 8ccf4bcff5..84932ea4a1 100644 --- a/data/assets/examples/debugcoordinateaxes.asset +++ b/data/assets/examples/debugcoordinateaxes.asset @@ -1,6 +1,8 @@ local transforms = asset.require('scene/solarsystem/planets/earth/transforms') local debugHelper = asset.require('util/debug_helper') +local sun_transforms = asset.require('scene/solarsystem/sun/transforms') +local sunRadius = 6.957E8 local earthRadius = 6.371E6 debugHelper.registerCartesianAxes(asset, { @@ -17,3 +19,13 @@ debugHelper.registerCartesianAxes(asset, { Parent = transforms.EarthIAU.Identifier, Scale = earthRadius * 1.5 }) + +debugHelper.registerCartesianAxes(asset, { + Parent = sun_transforms.SunIAU.Identifier, + Scale = sunRadius * 300 +}) + +debugHelper.registerCartesianAxes(asset, { + Parent = sun_transforms.SolarSystemBarycenter.Identifier, + Scale = sunRadius * 300 +}) diff --git a/data/assets/examples/globerotation.asset b/data/assets/examples/globerotation.asset new file mode 100644 index 0000000000..f685b0ae5e --- /dev/null +++ b/data/assets/examples/globerotation.asset @@ -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 }) diff --git a/data/assets/examples/globetranslation.asset b/data/assets/examples/globetranslation.asset index aedc5f5901..a61de7e465 100644 --- a/data/assets/examples/globetranslation.asset +++ b/data/assets/examples/globetranslation.asset @@ -2,19 +2,11 @@ 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 textures = asset.syncedResource({ - Name = "New Horizons Textures", - Type = "HttpSynchronization", - Identifier = "newhorizons_textures", - Version = 3 -}) - local models = asset.syncedResource({ Name = "New Horizons Model", Type = "HttpSynchronization", Identifier = "newhorizons_model", - Version = 1 + Version = 2 }) local Example_Fixed_Height = { @@ -24,19 +16,15 @@ local Example_Fixed_Height = { Translation = { Type = "GlobeTranslation", Globe = earth.Earth.Identifier, - Longitude = 0.0, - Latitude = 0.0, - FixedAltitude = 10000000.0 + Latitude = 40.7128, + Longitude = -74.006, + Altitude = 100000.0 } }, Renderable = { Type = "RenderableModel", Body = "NEW HORIZONS", - Geometry = {{ - Type = "MultiModelGeometry", - GeometryFile = models .. "/NewHorizonsCleanModel.obj", - ColorTexture = textures .. "/NHTexture.jpg" - }} + GeometryFile = models .. "/NewHorizonsCleanModel.obj" }, GUI = { Path = "/Example" @@ -50,18 +38,15 @@ local Example_Adaptive_Height = { Translation = { Type = "GlobeTranslation", Globe = earth.Earth.Identifier, + Latitude = 40.7128, Longitude = -74.006, - Latitude = 40.7128 + UseHeightmap = true } }, Renderable = { Type = "RenderableModel", Body = "NEW HORIZONS", - Geometry = {{ - Type = "MultiModelGeometry", - GeometryFile = models .. "/NewHorizonsCleanModel.obj", - ColorTexture = textures .. "/NHTexture.jpg" - }} + GeometryFile = models .. "/NewHorizonsCleanModel.obj" }, GUI = { Path = "/Example" diff --git a/data/assets/examples/luastatemachine.asset b/data/assets/examples/luastatemachine.asset new file mode 100644 index 0000000000..45ce5bb29a --- /dev/null +++ b/data/assets/examples/luastatemachine.asset @@ -0,0 +1,47 @@ +local stateMachineHelper = asset.require('util/lua_state_machine_helper') + +local states = { + { + Title = "Highlight EarthTrail", + Play = function () + openspace.setPropertyValue("Scene.EarthTrail.Renderable.Appearance.LineWidth", 10, 1) + end, + Rewind = function () + openspace.setPropertyValue("Scene.EarthTrail.Renderable.Appearance.LineWidth", 2, 1) + end + }, + { + Title = "Highlight MarsTrail", + Play = function () + openspace.setPropertyValue("Scene.EarthTrail.Renderable.Appearance.LineWidth", 2, 1) + openspace.setPropertyValue("Scene.MarsTrail.Renderable.Appearance.LineWidth", 10, 1) + end, + Rewind = function () + openspace.setPropertyValue("Scene.MarsTrail.Renderable.Appearance.LineWidth", 2, 1) + openspace.setPropertyValue("Scene.EarthTrail.Renderable.Appearance.LineWidth", 10, 1) + end + } +} + +local stateMachine + +function next() + stateMachine.goToNextState() +end + +function previous() + stateMachine.goToPreviousState() +end + +asset.onInitialize(function () + stateMachine = stateMachineHelper.createStateMachine(states) + openspace.bindKey('RIGHT', 'next()') + openspace.bindKey('LEFT', 'previous()') +end) + + +asset.onDeinitialize(function () + stateMachine = nil + openspace.clearKey('RIGHT') + openspace.clearKey('LEFT') +end) diff --git a/data/assets/examples/modelshader/model_fs.glsl b/data/assets/examples/modelshader/model_fs.glsl new file mode 100644 index 0000000000..854a04fa98 --- /dev/null +++ b/data/assets/examples/modelshader/model_fs.glsl @@ -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; +} diff --git a/data/assets/examples/modelshader/model_vs.glsl b/data/assets/examples/modelshader/model_vs.glsl new file mode 100644 index 0000000000..4ea52f749b --- /dev/null +++ b/data/assets/examples/modelshader/model_vs.glsl @@ -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); +} diff --git a/data/assets/examples/modelshader/modelshader.asset b/data/assets/examples/modelshader/modelshader.asset new file mode 100644 index 0000000000..3fafbb7184 --- /dev/null +++ b/data/assets/examples/modelshader/modelshader.asset @@ -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 }) diff --git a/data/assets/examples/slidedeck.asset b/data/assets/examples/slidedeck.asset index fdd3756450..885dabb3b8 100644 --- a/data/assets/examples/slidedeck.asset +++ b/data/assets/examples/slidedeck.asset @@ -15,22 +15,51 @@ asset.onInitialize(function () local interpolationDuration = 0.5 - function nextSlide() - helper.goToNextSlide(deck, interpolationDuration) - end + -- Add global functions for controlling slide deck and bind to keys + rawset(_G, "nextSlide", function() + helper.goToNextSlide(deck, interpolationDuration) + end) - function previousSlide() + rawset(_G, "previousSlide", function() helper.goToPreviousSlide(deck, interpolationDuration) - end + end) - function toggleSlides() + rawset(_G, "toggleSlides", function() helper.toggleSlides(deck, interpolationDuration) - end + end) helper.setCurrentSlide(deck, 1) - openspace.bindKey("KP_6", "nextSlide()", "Next slide", "Next slide", "/Slides") - openspace.bindKey("KP_4", "previousSlide()", "Previous slide", "Previous slide", "/Slides") - openspace.bindKey("KP_0", "toggleSlides()", "Toggle slides", "Toggle slides", "/Slides") + + openspace.action.registerAction({ + Identifier = "slide_deck.prevslide", + Name = "Previous slide", + Command = "previousSlide()", + Documentation = "Previous slide", + GuiPath = "/Slides", + IsLocal = false + }) + openspace.bindKey("KP_4", "slide_deck.prevslide"); + + openspace.action.registerAction({ + Identifier = "slide_deck.nextslide", + Name = "Next slide", + Command = "nextSlide()", + Documentation = "Next slide", + GuiPath = "/Slides", + IsLocal = false + }) + openspace.bindKey("KP_6", "slide_deck.nextslide") + + openspace.action.registerAction({ + Identifier = "slide_deck.toggleslides", + Name = "Toggle slides", + Command = "toggleSlides()", + Documentation = "Toggle slides", + GuiPath = "/Slides", + IsLocal = false + }) + openspace.bindKey("KP_0", "slide_deck.toggleslides") + end) diff --git a/data/assets/examples/statemachine.asset b/data/assets/examples/statemachine.asset index e97213011c..bbc41055f1 100644 --- a/data/assets/examples/statemachine.asset +++ b/data/assets/examples/statemachine.asset @@ -1,47 +1,72 @@ -local stateMachineHelper = asset.require('util/state_machine_helper') +-- Create a state machine with a few different states. The state machine can be controlled through +-- the scripting commands from the state machine module. -states = { +local targetNode = function(nodeIdentifier) + return [[ + openspace.setPropertyValueSingle("NavigationHandler.OrbitalNavigator.RetargetAnchor", nil) + openspace.setPropertyValueSingle( + "NavigationHandler.OrbitalNavigator.Anchor", + ']] .. nodeIdentifier .. [[' + ) + openspace.setPropertyValueSingle("NavigationHandler.OrbitalNavigator.Aim", '') + ]] +end + +local states = { { - Title = "Highlight EarthTrail", - Play = function () - openspace.setPropertyValue("Scene.EarthTrail.Renderable.LineWidth", 10, 1) - end, - Rewind = function () - openspace.setPropertyValue("Scene.EarthTrail.Renderable.LineWidth", 2, 1) - end - }, + Identifier = "Constellations", + Enter = [[ + openspace.setPropertyValueSingle('Scene.Constellations.Renderable.Opacity', 1.0, 1.0) + ]], + Exit = [[ + openspace.setPropertyValueSingle('Scene.Constellations.Renderable.Opacity', 0.0, 1.0) + ]] + }, { - Title = "Highlight MarsTrail", - Play = function () - openspace.setPropertyValue("Scene.EarthTrail.Renderable.LineWidth", 2, 1) - openspace.setPropertyValue("Scene.MarsTrail.Renderable.LineWidth", 10, 1) - end, - Rewind = function () - openspace.setPropertyValue("Scene.MarsTrail.Renderable.LineWidth", 2, 1) - openspace.setPropertyValue("Scene.EarthTrail.Renderable.LineWidth", 10, 1) - end + Identifier = "Earth", + Enter = "openspace.setPropertyValueSingle('Scene.EarthLabel.Renderable.Enabled', true)", + Exit = "openspace.setPropertyValueSingle('Scene.EarthLabel.Renderable.Enabled', false)" + }, + { + Identifier = "Moon" } } -local stateMachine +local transitions = { + { + From = "Earth", + To = "Moon", + Action = targetNode("Moon") + }, + { + From = "Moon", + To = "Earth", + Action = targetNode("Earth") + }, + { + From = "Earth", + To = "Constellations", + }, + { + From = "Constellations", + To = "Earth" + }, + { + From = "Moon", + To = "Constellations", + Action = targetNode("Earth") + }, + { + From = "Constellations", + To = "Moon", + Action = targetNode("Moon") + } +} -function next() - stateMachine.goToNextState() -end +asset.onInitialize(function() + -- Setup (could be done in the profile) + openspace.setPropertyValueSingle('Scene.Constellations.Renderable.Enabled', true) + openspace.setPropertyValueSingle('Scene.Constellations.Renderable.Opacity', 0.0) -function previous() - stateMachine.goToPreviousState() -end - -asset.onInitialize(function () - stateMachine = stateMachineHelper.createStateMachine(states) - openspace.bindKey('RIGHT', 'next()') - openspace.bindKey('LEFT', 'previous()') -end) - - -asset.onDeinitialize(function () - stateMachine = nil - openspace.clearKey('RIGHT') - openspace.clearKey('LEFT') + openspace.statemachine.createStateMachine(states, transitions, "Earth") end) diff --git a/data/assets/examples/temperature_land_highres.asset b/data/assets/examples/temperature_land_highres.asset new file mode 100644 index 0000000000..a5a07af757 --- /dev/null +++ b/data/assets/examples/temperature_land_highres.asset @@ -0,0 +1,39 @@ +local globeIdentifier = asset.require("scene/solarsystem/planets/earth/earth.asset").Earth.Identifier + +local path = asset.syncedResource({ + Name = "Earth Textures Climate", + Type = "HttpSynchronization", + Identifier = "earth_textures_climate", + Version = 1 +}) + +local layer = { + Identifier = "ERA5_Land_HighRes_Monthly_2M_Temperature_Temporal", + Name = "ERA5 Land HighRes Monthly 2M Temperature (Temporal)", + Type = "TemporalTileLayer", + FilePath = + "" .. + "1981-01-01" .. + "1990-10-01" .. + "1M" .. + "YYYY-MM-DD" .. + "" .. path .. "/rainbow.png" .. + "linear" .. + "" .. path .. "/${OpenSpaceTimeId}-land.png" .. + "", + Description = [[ Temporal coverage: 01 Jan 1981 - 31 Dec 2020.]] +} + +asset.onInitialize(function () + openspace.globebrowsing.addLayer(globeIdentifier, "ColorLayers", layer) +end) + +asset.export("layer", layer) +asset.meta = { + Name = "Climate Earth Layers", + Version = "1.0", + Description = [[ ERA5 data ]], + Author = "OpenSpace Team", + URL = "http://openspaceproject.com", + License = "MIT license" +} diff --git a/data/assets/examples/urlsynchronization.asset b/data/assets/examples/urlsynchronization.asset index de55aaaf82..3cae4f2179 100644 --- a/data/assets/examples/urlsynchronization.asset +++ b/data/assets/examples/urlsynchronization.asset @@ -35,12 +35,6 @@ asset.syncedResource({ Override = true }) -asset.syncedResource({ - Name = "Example No ident", - Type = "UrlSynchronization", - Url = "http://ipv4.download.thinkbroadband.com/5MB.zip" -}) - asset.syncedResource({ Name = "Example No Hash", Type = "UrlSynchronization", diff --git a/data/assets/scene/digitaluniverse/hdf.asset b/data/assets/scene/digitaluniverse/hdf.asset index 353ae96fdc..c943e1542f 100644 --- a/data/assets/scene/digitaluniverse/hdf.asset +++ b/data/assets/scene/digitaluniverse/hdf.asset @@ -1,5 +1,11 @@ local assetHelper = asset.require('util/asset_helper') -local circle = asset.require('util/circle').circle + +local circle = asset.syncedResource({ + Name = "Circle", + Type = "HttpSynchronization", + Identifier = "circle_image", + Version = 1 +}) local HUDFSpeck = asset.syncedResource({ Name = "HUDF Speck", diff --git a/data/assets/scene/digitaluniverse/stars.asset b/data/assets/scene/digitaluniverse/stars.asset index db0ac4adb7..77624e5725 100644 --- a/data/assets/scene/digitaluniverse/stars.asset +++ b/data/assets/scene/digitaluniverse/stars.asset @@ -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]] diff --git a/data/assets/scene/milkyway/constellations/constellation_art.asset b/data/assets/scene/milkyway/constellations/constellation_art.asset index 8df89c7658..1217742e88 100644 --- a/data/assets/scene/milkyway/constellations/constellation_art.asset +++ b/data/assets/scene/milkyway/constellations/constellation_art.asset @@ -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) diff --git a/data/assets/scene/milkyway/constellations/constellation_extrakeybinds.asset b/data/assets/scene/milkyway/constellations/constellation_extrakeybinds.asset index 383a82b0ea..33693141f8 100644 --- a/data/assets/scene/milkyway/constellations/constellation_extrakeybinds.asset +++ b/data/assets/scene/milkyway/constellations/constellation_extrakeybinds.asset @@ -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 = { diff --git a/data/assets/scene/milkyway/constellations/constellation_keybinds.asset b/data/assets/scene/milkyway/constellations/constellation_keybinds.asset index 08765add84..37b9f3e124 100644 --- a/data/assets/scene/milkyway/constellations/constellation_keybinds.asset +++ b/data/assets/scene/milkyway/constellations/constellation_keybinds.asset @@ -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) diff --git a/data/assets/scene/milkyway/exoplanets/exoplanets_textures.asset b/data/assets/scene/milkyway/exoplanets/exoplanets_textures.asset index dd80929b3d..2aaf885944 100644 --- a/data/assets/scene/milkyway/exoplanets/exoplanets_textures.asset +++ b/data/assets/scene/milkyway/exoplanets/exoplanets_textures.asset @@ -1,7 +1,12 @@ local habitableZoneTextures = asset.require('./../habitable_zones/habitable_zone_textures').TexturesPath -local sunTextures = asset.require('scene/solarsystem/sun/sun_textures').TexturesPath +local sunTextures = asset.syncedResource({ + Type = "HttpSynchronization", + Name = "Sun textures", + Identifier = "sun_textures", + Version = 4 +}) local TexturesPath = asset.syncedResource({ Name = "Exoplanet Textures", diff --git a/data/assets/scene/solarsystem/dwarf_planets/pluto/charon/charon.asset b/data/assets/scene/solarsystem/dwarf_planets/pluto/charon/charon.asset index e2411ef264..01ba4be29a 100644 --- a/data/assets/scene/solarsystem/dwarf_planets/pluto/charon/charon.asset +++ b/data/assets/scene/solarsystem/dwarf_planets/pluto/charon/charon.asset @@ -2,10 +2,16 @@ local assetHelper = asset.require('util/asset_helper') local transforms = asset.require('./../transforms') asset.require("spice/base") asset.require('../trail') -local labelsPath = asset.require('./../pluto_globelabels').LabelsPath +local labelsPath = asset.syncedResource({ + Name = "Pluto Labels", + Type = "HttpSynchronization", + Identifier = "pluto_labels", + Version = 1 +}) + local Charon = { Identifier = "Charon", Parent = transforms.PlutoBarycenter.Identifier, diff --git a/data/assets/scene/solarsystem/dwarf_planets/pluto/minor/hydra.asset b/data/assets/scene/solarsystem/dwarf_planets/pluto/minor/hydra.asset index 30bcb528b6..a7f991c8cc 100644 --- a/data/assets/scene/solarsystem/dwarf_planets/pluto/minor/hydra.asset +++ b/data/assets/scene/solarsystem/dwarf_planets/pluto/minor/hydra.asset @@ -21,7 +21,7 @@ local Hydra = { SegmentsPerPatch = 64, Layers = {} }, - Tag = { "moon_solarSystem", "moon_dwarf", "moon_pluto" }, + Tag = { "moon_solarSystem", "moon_dwarf", "moon_pluto", "moon_minor" }, GUI = { Path = "/Solar System/Dwarf Planets/Pluto" } diff --git a/data/assets/scene/solarsystem/dwarf_planets/pluto/minor/kerberos.asset b/data/assets/scene/solarsystem/dwarf_planets/pluto/minor/kerberos.asset index 8d394e60c4..2cf71c1de2 100644 --- a/data/assets/scene/solarsystem/dwarf_planets/pluto/minor/kerberos.asset +++ b/data/assets/scene/solarsystem/dwarf_planets/pluto/minor/kerberos.asset @@ -20,7 +20,7 @@ local Kerberos = { SegmentsPerPatch = 64, Layers = {} }, - Tag = { "moon_solarSystem", "moon_dwarf", "moon_pluto" }, + Tag = { "moon_solarSystem", "moon_dwarf", "moon_pluto", "moon_minor" }, GUI = { Path = "/Solar System/Dwarf Planets/Pluto" } diff --git a/data/assets/scene/solarsystem/dwarf_planets/pluto/minor/nix.asset b/data/assets/scene/solarsystem/dwarf_planets/pluto/minor/nix.asset index 4503fe1893..0c057482d2 100644 --- a/data/assets/scene/solarsystem/dwarf_planets/pluto/minor/nix.asset +++ b/data/assets/scene/solarsystem/dwarf_planets/pluto/minor/nix.asset @@ -20,7 +20,7 @@ local Nix = { SegmentsPerPatch = 64, Layers = {} }, - Tag = { "moon_solarSystem", "moon_dwarf", "moon_pluto" }, + Tag = { "moon_solarSystem", "moon_dwarf", "moon_pluto", "moon_minor" }, GUI = { Path = "/Solar System/Dwarf Planets/Pluto" } diff --git a/data/assets/scene/solarsystem/dwarf_planets/pluto/minor/styx.asset b/data/assets/scene/solarsystem/dwarf_planets/pluto/minor/styx.asset index 071839e0e4..ba9195d562 100644 --- a/data/assets/scene/solarsystem/dwarf_planets/pluto/minor/styx.asset +++ b/data/assets/scene/solarsystem/dwarf_planets/pluto/minor/styx.asset @@ -19,7 +19,7 @@ local Styx = { SegmentsPerPatch = 64, Layers = {} }, - Tag = { "moon_solarSystem", "moon_dwarf", "moon_pluto" }, + Tag = { "moon_solarSystem", "moon_dwarf", "moon_pluto", "moon_minor" }, GUI = { Path = "/Solar System/Dwarf Planets/Pluto" } diff --git a/data/assets/scene/solarsystem/dwarf_planets/pluto/pluto.asset b/data/assets/scene/solarsystem/dwarf_planets/pluto/pluto.asset index 947b762858..2a80986180 100644 --- a/data/assets/scene/solarsystem/dwarf_planets/pluto/pluto.asset +++ b/data/assets/scene/solarsystem/dwarf_planets/pluto/pluto.asset @@ -2,9 +2,14 @@ local assetHelper = asset.require('util/asset_helper') local transforms = asset.require('./transforms') asset.require("spice/base") asset.require('./trail') -local labelsPath = asset.require('./pluto_globelabels').LabelsPath +local labelsPath = asset.syncedResource({ + Name = "Pluto Labels", + Type = "HttpSynchronization", + Identifier = "pluto_labels", + Version = 1 +}) local Pluto = { Identifier = "Pluto", diff --git a/data/assets/scene/solarsystem/dwarf_planets/pluto/pluto_globelabels.asset b/data/assets/scene/solarsystem/dwarf_planets/pluto/pluto_globelabels.asset deleted file mode 100644 index 4a045b3e9d..0000000000 --- a/data/assets/scene/solarsystem/dwarf_planets/pluto/pluto_globelabels.asset +++ /dev/null @@ -1,7 +0,0 @@ -local LabelsPath = asset.syncedResource({ - Name = "Pluto Labels", - Type = "HttpSynchronization", - Identifier = "pluto_labels", - Version = 1 -}) -asset.export("LabelsPath", LabelsPath) diff --git a/data/assets/scene/solarsystem/dwarf_planets/pluto/pluto_trail_kepler.asset b/data/assets/scene/solarsystem/dwarf_planets/pluto/pluto_trail_kepler.asset index 95cc754503..f8272f2726 100644 --- a/data/assets/scene/solarsystem/dwarf_planets/pluto/pluto_trail_kepler.asset +++ b/data/assets/scene/solarsystem/dwarf_planets/pluto/pluto_trail_kepler.asset @@ -3,33 +3,35 @@ local transforms = asset.require('scene/solarsystem/sun/transforms') asset.require("spice/base") local kernels = asset.require('./kernels').PlutoKernels local OneAU = 1.496e+8 + + local PlutoKeplerianTrail = { - Identifier = "PlutoKeplerianTrail", - Parent = transforms.SunECLIPJ2000.Identifier, - Renderable = { - Type = "RenderableTrailOrbit", - Translation = { - Type = "KeplerTranslation", - Eccentricity = 2.543033082909471E-01, - SemiMajorAxis = 3.974407237841206E+01 * OneAU, - Inclination = 1.736609481151430E+01, - AscendingNode = 1.102099981996057E+02, - ArgumentOfPeriapsis = 1.142248569189779E+02, - MeanAnomaly = 14.53, - Epoch = '2000 01 01 00:00', - Period = 7.82438e+9 - }, - Color = { 0.2, 0.8, 0.3 }, - Period = 90487.27692706819, - Resolution = 1000, - Enabled = false + Identifier = "PlutoKeplerianTrail", + Parent = transforms.SunECLIPJ2000.Identifier, + Renderable = { + Type = "RenderableTrailOrbit", + Translation = { + Type = "KeplerTranslation", + Eccentricity = 2.543033082909471E-01, + SemiMajorAxis = 3.974407237841206E+01 * OneAU, + Inclination = 1.736609481151430E+01, + AscendingNode = 1.102099981996057E+02, + ArgumentOfPeriapsis = 1.142248569189779E+02, + MeanAnomaly = 14.53, + Epoch = '2000 01 01 00:00', + Period = 7.82438e+9 }, - Tag = { "planetTrail_dwarf" }, - GUI = { - Name = "Pluto Keplerian Trail", - Path = "/Solar System/Dwarf Planets/Pluto", - Description = "Keplerian trail of Pluto. Contains full orbit." - } + Color = { 0.2, 0.8, 0.3 }, + Period = 90487.27692706819, + Resolution = 1000, + Enabled = false + }, + Tag = { "planetTrail_dwarf" }, + GUI = { + Name = "Pluto Keplerian Trail", + Path = "/Solar System/Dwarf Planets/Pluto", + Description = "Keplerian trail of Pluto. Contains full orbit." + } } assetHelper.registerSceneGraphNodesAndExport(asset, { PlutoKeplerianTrail }) diff --git a/data/assets/scene/solarsystem/heliosphere/bastille_day/carringtonToHEEQRotation.asset b/data/assets/scene/solarsystem/heliosphere/bastille_day/carringtonToHEEQRotation.asset new file mode 100644 index 0000000000..3335e1a3bf --- /dev/null +++ b/data/assets/scene/solarsystem/heliosphere/bastille_day/carringtonToHEEQRotation.asset @@ -0,0 +1,16 @@ +local CarringtonLongitudeToHEEQ180Rotation = { + -- This is a rotation matrix to go from Carrington longitude referens frame to HEEQ180 + -- reference fram. At the reference time, MAS_seq = 0, 2000-07-14T08:33:37.105 the + -- Carrington longitude was 309.3 degrees. + -- Difference from HEEQ => 360-309.3=50.7 + -- (or 0-309.3 = -309.3 However this leads to the same rotation matrix in the end) + -- Since OpenSpace supports HEEQ180 and not HEEQ, 180 was added or subtracted + -- => a1 = -129.3 and a2 = 230.7 + -- Rotation matrix: (cos a, -sin a, 0)(sin a, cos a, 0)(0, 0, 1) leads to the result. + Type = "FixedRotation", + XAxis = { -0.63338087262755016203262119192353, -0.77384020972650618518999944537717, 0.0 }, + YAxis = { 0.77384020972650618518999944537717, -0.63338087262755016203262119192353, 0.0 }, + ZAxis = { 0.0, 0.0, 1.0 } +} + +asset.export("CarringtonLongitudeToHEEQ180Rotation", CarringtonLongitudeToHEEQ180Rotation) diff --git a/data/assets/scene/solarsystem/heliosphere/bastille_day/density_volume.asset b/data/assets/scene/solarsystem/heliosphere/bastille_day/density_volume.asset new file mode 100644 index 0000000000..b622245855 --- /dev/null +++ b/data/assets/scene/solarsystem/heliosphere/bastille_day/density_volume.asset @@ -0,0 +1,73 @@ +local assetHelper = asset.require("util/asset_helper") +local propertyHelper = asset.require('util/property_helper') +local sunTransforms = asset.require('scene/solarsystem/sun/transforms') + +local densityDirectory = asset.syncedResource({ + Name = "Bastille Day MAS Density", + Type = "HttpSynchronization", + Identifier = "bastille_day_mas_density", + Version = 1 +}) + +local sunRadius = 6.957E8 + +local densityVolume = { + Identifier = "MAS-MHD-Density-bastille-day-2000", + Parent = sunTransforms.SunIAU.Identifier, + Transform = { + Scale = { + Type = "StaticScale", + Scale = sunRadius + }, + Rotation = { + Type = "FixedRotation", + XAxis = { -1.0, 0.0, 0.0 }, + YAxis = { 0.0, 1.0, 0.0 }, + ZAxis = { 0.0, 0.0, -1.0 } + } + }, + Renderable = { + Type = "RenderableTimeVaryingVolume", + StepSize = 0.004, + Opacity = 0.3, + TransferFunction = asset.localResource("transferfunctions/mas-mhd-r-squared-old.txt"), + SourceDirectory = densityDirectory, + GridType = "Spherical", + SecondsBefore = 24*60*60, + SecondsAfter = 24*60*60, + Dimensions = { 100, 100, 128 }, + InvertDataAtZ = true + }, + GUI = { + Name = "MAS Density", + Path = "/Solar System/Heliosphere/Bastille Day 2000", + Description = "Volumetric rendering for the bastille day CME event. This asset contain data from 2000-07-14 08:33 to 2000-07-14 11:49" + } +} + +local toggle_volume = { + Identifier = "density_volume.toggle_volume", + Name = "Toggle volume", + Command = propertyHelper.invert("Scene.MAS-MHD-Density-bastille-day-2000.Renderable.Enabled"), + Documentation = "Toggle volume rendering of CME", + GuiPath = "/Bastille-Day 2000", + IsLocal = false +} + +asset.onInitialize(function () + openspace.action.registerAction(toggle_volume) +end) +asset.onDeinitialize(function () + openspace.action.removeAction(toggle_volume.Identifier) +end) +assetHelper.registerSceneGraphNodesAndExport(asset, { densityVolume }) + +asset.meta = { + Name = "Predictive Science Inc. Volume Rendering Bastille Day", + Version = "1.0", + Description = [[Volumetric rendering for the bastille day CME event]], + Author = "CCMC, OpenSpace team", + URL = "https://dx.doi.org/10.3847/1538-4357/aab36d", + License = "CC-BY", + Identifier = {"MAS-MHD-Density-bastille-day-2000"} +} diff --git a/data/assets/scene/solarsystem/heliosphere/bastille_day/fieldlines.asset b/data/assets/scene/solarsystem/heliosphere/bastille_day/fieldlines.asset new file mode 100644 index 0000000000..8672ddd590 --- /dev/null +++ b/data/assets/scene/solarsystem/heliosphere/bastille_day/fieldlines.asset @@ -0,0 +1,76 @@ +local assetHelper = asset.require('util/asset_helper') +local heliosphereTransforms = asset.require('scene/solarsystem/sun/transforms_heliosphere') +local propertyHelper = asset.require('util/property_helper') +local rot = asset.require('./carringtonToHEEQRotation.asset') + +local fieldlinesDirectory = asset.syncedResource({ + Name = "Bastille Day MAS Fieldlines", + Type = "HttpSynchronization", + Identifier = "bastille_day_mas_fieldlines", + Version = 1 +}) + +local sunRadius = 6.957E8 + +-- Fieldlies from binaries +local fieldlines = { + Identifier = "MAS-MHD-Fieldlines-bastille-day-2000", + Parent = heliosphereTransforms.HEEQ180ReferenceFrame.Identifier, + Transform = { + Scale = { + Type = "StaticScale", + Scale = sunRadius + }, + Rotation = rot.CarringtonLongitudeToHEEQ180Rotation + }, + Renderable = { + Type = "RenderableFieldlinesSequence", + SourceFolder = fieldlinesDirectory, + AlphaBlendlingEnabled = false, + InputFileType = "Osfls", + ColorTablePaths = { + asset.localResource("transferfunctions/density-fieldlines.txt"), + asset.localResource("transferfunctions/velocity-fieldlines.txt") + }, + ColorTableMinMax = { + { 0, 1000000 }, + { 100, 2000 } + }, + SimulationModel = "mas", + Color = { + Uniform = { 0.0, 0.725, 0.75, 1.0 } + } + }, + GUI = { + Path = "/Solar System/Heliosphere/Bastille Day 2000", + Name = "MAS Fieldlines", + Description = "Magnetic fieldlines for the bastille day CME event. This asset contains data from 2000-07-14 08:33 to 2000-07-14 11:49" + } +} + +local toggle_fieldlines = { + Identifier = "fieldlines.toggle_fieldlines", + Name = "Toggle Fieldlines", + Command = propertyHelper.invert("Scene.MAS-MHD-Fieldlines-bastille-day-2000.Renderable.Enabled"), + Documentation = "Toggle fieldline rendering of CME", + GuiPath = "/Bastille-Day 2000", + IsLocal = false +} + +asset.onInitialize(function () + openspace.action.registerAction(toggle_fieldlines) +end) +asset.onDeinitialize(function () + openspace.action.removeAction(toggle_fieldlines.Identifier) +end) +assetHelper.registerSceneGraphNodesAndExport(asset, { fieldlines }) + +asset.meta = { + Name = "Predictive Science Inc. Fieldlines Bastille Day", + Version = "1.0", + Description = [[Magnetic fieldlines for the bastille day CME event]], + Author = "CCMC, Jonathan Grangien, Matthias Berg", + URL = "https://dx.doi.org/10.3847/1538-4357/aab36d", + License = "CC-BY", + Identifier = {"MAS-MHD-Fieldlines-bastille-day-2000"} +} diff --git a/data/assets/scene/solarsystem/heliosphere/bastille_day/fluxnodes.asset b/data/assets/scene/solarsystem/heliosphere/bastille_day/fluxnodes.asset new file mode 100644 index 0000000000..2a8efbb70c --- /dev/null +++ b/data/assets/scene/solarsystem/heliosphere/bastille_day/fluxnodes.asset @@ -0,0 +1,58 @@ +local assetHelper = asset.require('util/asset_helper') +local heliosphereTransforms = asset.require('scene/solarsystem/sun/transforms_heliosphere') +local propertyHelper = asset.require('util/property_helper') +local rot = asset.require('./carringtonToHEEQRotation.asset') + +local fluxNodesBinaries = asset.syncedResource({ + Name = "Bastille day Flux nodes binaries", + Type = "HttpSynchronization", + Identifier = "bastille_day_streamnodes_binaries", + Version = 1 +}) + +-- FluxNodes from binaries +local fluxNodes = { + Identifier = "MAS-MHD-FluxNodes-bastille-day-2000", + Parent = heliosphereTransforms.HEEQ180ReferenceFrame.Identifier, + Transform = { + Rotation = rot.CarringtonLongitudeToHEEQ180Rotation + }, + Renderable = { + Type = "RenderableFluxNodes", + SourceFolder = fluxNodesBinaries, + ColorTablePath = asset.localResource("transferfunctions/CMR.txt"), + ColorTableRange = {-2.0, 4.0} + }, + GUI = { + Path = "/Solar System/Heliosphere/Bastille Day 2000", + Name = "Flux Nodes", + Description = "Flux nodes for the bastille day CME event. This asset contains data from 2000-07-14 08:38 to 2000-07-14 19:48" + } +} + +local toggle_fluxnodes = { + Identifier = "fluxnodes.toggle_fluxnodes", + Name = "Toggle flux nodes", + Command = propertyHelper.invert("Scene.MAS-MHD-FluxNodes-bastille-day-2000.Renderable.Enabled"), + Documentation = "Toggle flux node rendering of CME", + GuiPath = "/Bastille-Day 2000", + IsLocal = false +} + +asset.onInitialize(function () + openspace.action.registerAction(toggle_fluxnodes) +end) +asset.onDeinitialize(function () + openspace.action.removeAction(toggle_fluxnodes.Identifier) +end) +assetHelper.registerSceneGraphNodesAndExport(asset, { fluxNodes }) + +asset.meta = { + Name = "Predictive Science Inc. Flux nodes Bastille Day", + Version = "1.0", + Description = [[Flux nodes for the bastille day CME event]], + Author = "CCMC, Christian Adamsson, Emilie Ho", + URL = "https://dx.doi.org/10.3847/1538-4357/aab36d", + License = "CC-BY", + Identifier = {"MAS-MHD-FluxNodes-bastille-day-2000"} +} diff --git a/data/assets/scene/solarsystem/heliosphere/bastille_day/fluxnodescutplane.asset b/data/assets/scene/solarsystem/heliosphere/bastille_day/fluxnodescutplane.asset new file mode 100644 index 0000000000..52ec32efe8 --- /dev/null +++ b/data/assets/scene/solarsystem/heliosphere/bastille_day/fluxnodescutplane.asset @@ -0,0 +1,102 @@ +local assetHelper = asset.require("util/asset_helper") +local propertyHelper = asset.require("util/property_helper") +local transforms = asset.require('scene/solarsystem/sun/transforms_heliosphere') +local rot = asset.require('./carringtonToHEEQRotation.asset') + +local TexturesPathEquitorial = asset.syncedResource({ +Type = "HttpSynchronization", + Name = "cutplanes_textures", + Identifier = "cutplanes_textures", + Version = 1 +}) + +local TexturesPathMeridial = asset.syncedResource({ + Type = "HttpSynchronization", + Name = "cutplane_meridial_textures", + Identifier = "cutplane_meridial_textures", + Version = 1 +}) + +local EquatorialCutplane = { + Identifier = "EquatorialCutplane-bastille-day-2000", + Parent = transforms.HEEQ180ReferenceFrame.Identifier, + Transform = { + Rotation = rot.CarringtonLongitudeToHEEQ180Rotation + }, + Renderable = { + Type = "RenderablePlaneTimeVaryingImage", + Size = 1.57E11, + Enabled = true, + SourceFolder = TexturesPathEquitorial, + BlendMode = "Normal", + MirrorBackside = false, + Opacity = 0.7 + }, + GUI = { + Name = "Cutplane Equitorial", + Path = "/Solar System/Heliosphere/Bastille Day 2000", + Description = "Equatorial cutplane sequence for the bastille day CME event. This asset contains data from 2000-07-14 08:38 to 2000-07-14 12:00" + } +} + +local MeridialCutplane = { + Identifier = "MeridialCutplane-bastille-day-2000", + Parent = transforms.HEEQ180ReferenceFrame.Identifier, + Transform = { + Rotation = { + Type = "StaticRotation", + Rotation = { -math.pi/2, -math.pi, 0.0 } + } + }, + Renderable = { + Type = "RenderablePlaneTimeVaryingImage", + Size = 1.57E11, + Enabled = true, + SourceFolder = TexturesPathMeridial, + BlendMode = "Normal", + MirrorBackside = false, + Opacity = 0.7 + }, + GUI = { + Name = "Cutplane Meridial", + Path = "/Solar System/Heliosphere/Bastille Day 2000", + Description = "Meridial cutplane sequence for the bastille day CME event. This asset contains data from 2000-07-14 08:38 to 2000-07-14 12:00" + } +} + +local toggle_equatorial = { + Identifier = "fluxnodescutplane.toggle_equatorial", + Name = "Toggle equatorial cutplane", + Command = propertyHelper.invert("Scene.EquatorialCutplane-bastille-day-2000.Renderable.Enabled"), + Documentation = "Toggle equatorial cutplane of CME", + GuiPath = "/Bastille-Day 2000", + IsLocal = false +} +local toggle_meridial = { + Identifier = "fluxnodescutplane.toggle_meridial", + Name = "Toggle meridial cutplane", + Command = propertyHelper.invert("Scene.MeridialCutplane-bastille-day-2000.Renderable.Enabled"), + Documentation = "Toggle meridial cutplane of CME", + GuiPath = "/Bastille-Day 2000", + IsLocal = false +} + +asset.onInitialize(function () + openspace.action.registerAction(toggle_equatorial) + openspace.action.registerAction(toggle_meridial) +end) +asset.onDeinitialize(function () + openspace.action.removeAction(toggle_equatorial.Identifier) + openspace.action.removeAction(toggle_meridial.Identifier) +end) +assetHelper.registerSceneGraphNodesAndExport(asset, { EquatorialCutplane, MeridialCutplane}) + +asset.meta = { + Name = "Predictive Science Inc. Cutplanes Bastille Days", + Version = "1.0", + Description = [[Cutplanes for the bastille day CME event]], + Author = "CCMC, Christian Adamsson, Emilie Ho", + URL = "https://dx.doi.org/10.3847/1538-4357/aab36d", + License = "CC-BY", + Identifier = {"MeridialCutplane-bastille-day-2000", "EquatorialCutplane-bastille-day-2000"} +} diff --git a/data/assets/scene/solarsystem/heliosphere/bastille_day/fluxnodeslegend.asset b/data/assets/scene/solarsystem/heliosphere/bastille_day/fluxnodeslegend.asset new file mode 100644 index 0000000000..7f574ab978 --- /dev/null +++ b/data/assets/scene/solarsystem/heliosphere/bastille_day/fluxnodeslegend.asset @@ -0,0 +1,60 @@ +asset.require("spice/base") +local assetHelper = asset.require("util/asset_helper") + +local TexturesPath = asset.syncedResource({ + Type = "HttpSynchronization", + Name = "Streamnodes textures", + Identifier = "streamnodes_legend", + Version = 1 +}) + +local legend = { + Identifier = "LegendFluxNodes-bastille-day-2000", + Type = "ScreenSpaceImageLocal", + TexturePath = TexturesPath .. "/CMR_transparent_white_text.png", + Scale = 0.15, + CartesianPosition = { 0.677970, 0.0, -1.049180 } +} + +local show_legend = { + Identifier = "fluxnodelegend.show_legend", + Name = "Show the legend image", + Command = "openspace.setPropertyValueSingle('ScreenSpace.LegendFluxNodes-bastille-day-2000.Opacity', 0.0);" .. + "openspace.setPropertyValueSingle('ScreenSpace.LegendFluxNodes-bastille-day-2000.Enabled', true);" .. + "openspace.setPropertyValueSingle('ScreenSpace.LegendFluxNodes-bastille-day-2000.Opacity', 1.0, 4);", + Documentation = "Show the legend image", + GuiPath = "/Bastille-Day 2000", + IsLocal = false +} +local hide_legend = { + Identifier = "fluxnodelegend.hide_legend", + Name = "Hides the legend image", + Command = "openspace.setPropertyValueSingle('ScreenSpace.LegendFluxNodes-bastille-day-2000.Opacity', 0.0, 2);", + Documentation = "Hides the legend image", + GuiPath = "/Bastille-Day 2000", + IsLocal = false +} + +asset.onInitialize(function() + openspace.addScreenSpaceRenderable(legend) + -- These numbers are there to put the legend on the side of the screen. + openspace.setPropertyValueSingle('ScreenSpace.LegendFluxNodes-bastille-day-2000.Rotation', { 0.0, 0.0, 0.56652 }); + openspace.action.registerAction(show_legend) + openspace.action.registerAction(hide_legend) +end) + +asset.onDeinitialize(function () + openspace.removeScreenSpaceRenderable(legend.Identifier) + openspace.action.removeAction(show_legend.Identifier) + openspace.action.removeAction(hide_legend.Identifier) +end) + +asset.meta = { + Name = "Predictive Science Inc. Flux nodes legend for Bastille Days", + Version = "1.0", + Description = [[Screen space renderable image legend of flux nodes for the bastille day CME event]], + Author = "Christian Adamsson, Emilie Ho", + URL = "https://dx.doi.org/10.3847/1538-4357/aab36d", + License = "MIT", + Identifier = {"LegendFluxNodes-bastille-day-2000"} +} diff --git a/data/assets/scene/solarsystem/heliosphere/bastille_day/lightindicator.asset b/data/assets/scene/solarsystem/heliosphere/bastille_day/lightindicator.asset new file mode 100644 index 0000000000..533cb79ba7 --- /dev/null +++ b/data/assets/scene/solarsystem/heliosphere/bastille_day/lightindicator.asset @@ -0,0 +1,40 @@ +local assetHelper = asset.require('util/asset_helper') +local sunTransforms = asset.require('scene/solarsystem/sun/transforms') +local earthTransforms = asset.require('scene/solarsystem/planets/earth/transforms') + +local travelSpeedIndicator = { + Identifier = "TravelSpeedIndicator-2000", + --SunIAU adds an extra rotation. Using barycenter, then offsetting to SunIAU + Parent = sunTransforms.SolarSystemBarycenter.Identifier, + Transform = { + Translation = { + Type = "SpiceTranslation", + Target = "SUN", + Observer = "SSB" + } + }, + Renderable = { + Type = "RenderableTravelSpeed", + Target = earthTransforms.EarthCenter.Identifier, --name of scene graph node. Earth by default + LineWidth = 4, + IndicatorLength = 10, + FadeLength = 10 + }, + GUI = { + Path = "/Solar System/Heliosphere", + Name = "Speed indicator", + Description = "Speed of light indicator from sun to earth" + } +} + +assetHelper.registerSceneGraphNodesAndExport(asset, { travelSpeedIndicator }) + +asset.meta = { + Name = "Light travel from sun to earth", + Version = "1.0", + Description = [[Speed of light indicator from sun to earth]], + Author = "CCMC, Christian Adamsson, Emilie Ho", + URL = "", + License = "MIT", + Identifier = {"TravelSpeedIndicator-2000"} +} diff --git a/data/assets/scene/solarsystem/heliosphere/bastille_day/magnetogram.asset b/data/assets/scene/solarsystem/heliosphere/bastille_day/magnetogram.asset new file mode 100644 index 0000000000..8d83f6729d --- /dev/null +++ b/data/assets/scene/solarsystem/heliosphere/bastille_day/magnetogram.asset @@ -0,0 +1,22 @@ +local TexturesPath = asset.syncedResource({ + Name = "Bastille Day Magnetogram", + Type = "HttpSynchronization", + Identifier = "bastille_day_magnetogram", + Version = 5 +}) + +asset.export("TexturesPath", TexturesPath) + +-- Torok, T., Downs, C., Linker, J. A., Lionello, R., Titov, V. S., Mikic, Z., Riley, P., Caplan, R. M., and Wijaya, J. (2018). +-- Sun-to-Earth MHD Simulation of the 2000 July 14 Bastille Day Eruption. +-- ApJ, +-- 856:75. +asset.meta = { + Name = "Predictive Science Inc. MAS Bastille Day Textures", + Version = "1.0", + Description = [[Magnetograms of the sun as texture color layers]], + Author = "Jonathan Grangien, Matthias Berg", + URL = "https://dx.doi.org/10.3847/1538-4357/aab36d", + License = "CC-BY", + Identifier = {"Sun"} +} diff --git a/data/assets/scene/solarsystem/heliosphere/bastille_day/magnetogram_textures.asset b/data/assets/scene/solarsystem/heliosphere/bastille_day/magnetogram_textures.asset new file mode 100644 index 0000000000..4b91b6f5f4 --- /dev/null +++ b/data/assets/scene/solarsystem/heliosphere/bastille_day/magnetogram_textures.asset @@ -0,0 +1,60 @@ +local assetHelper = asset.require('util/asset_helper') +local sun = asset.require('scene/solarsystem/sun/sun') + +-- synced directories +local magnetogramDirectory = asset.require('./magnetogram').TexturesPath; +local magnetograms; + +local switch_color_layer = { + Identifier = "magnetogram_texture.switch_color_layer", + Name = "Next sun texture", + Command = [[ + local textureList = openspace.globebrowsing.getLayers('Sun', 'ColorLayers'); + if (magnetogramsTextureIndex == -1) then + magnetogramsTextureIndex = 2; + end; + magnetogramsTextureIndex = magnetogramsTextureIndex + 1; + if (magnetogramsTextureIndex >= #textureList) then + magnetogramsTextureIndex = 0; + end + openspace.setPropertyValue("Scene.Sun.Renderable.Layers.ColorLayers.*.Enabled", false); + if (magnetogramsTextureIndex == 0) then + openspace.setPropertyValueSingle("Scene.Sun.Renderable.Layers.ColorLayers.Texture.Enabled", true); + else + str = "Scene.Sun.Renderable.Layers.ColorLayers.magnetogram-" .. magnetogramsTextureIndex .. ".Enabled"; + openspace.setPropertyValueSingle(str, true); + end; + ]], + Documentation = "Display next sun texture in list of textures", + GuiPath = "/Bastille-Day 2000", + IsLocal = false +} + +asset.onInitialize(function () + magnetograms = openspace.walkDirectoryFiles(magnetogramDirectory); + rawset(_G, "magnetogramsTextureIndex", -1) + for i, imagename in ipairs(magnetograms) do + openspace.globebrowsing.addLayer( + 'Sun', + 'ColorLayers', + { + Identifier = "magnetogram-" .. i, + Name = imagename, --"Magnetogram-" .. i, + Description = "", + FilePath = imagename, + Enabled = false + } + ) + end + + openspace.action.registerAction(switch_color_layer) +end) + +asset.onDeinitialize(function () + for i, imagename in ipairs(magnetograms) do + openspace.globebrowsing.deleteLayer( + 'Sun', 'ColorLayers', 'magnetogram-' .. i + ) + end + openspace.action.removeAction(switch_color_layer.Identifier) +end) diff --git a/data/assets/scene/solarsystem/heliosphere/bastille_day/transferfunctions/CMR-illuminance.txt b/data/assets/scene/solarsystem/heliosphere/bastille_day/transferfunctions/CMR-illuminance.txt new file mode 100644 index 0000000000..91d79ca8b5 --- /dev/null +++ b/data/assets/scene/solarsystem/heliosphere/bastille_day/transferfunctions/CMR-illuminance.txt @@ -0,0 +1,14 @@ +width 10 +lower 0.0 +upper 1.0 + +mappingkey 0.0 17 17 56 255 +mappingkey 0.083 47 38 142 255 +mappingkey 0.166 80 39 189 255 +mappingkey 0.332 139 49 139 255 +mappingkey 0.415 221 60 68 255 +mappingkey 0.498 243 95 20 255 +mappingkey 0.664 230 147 8 255 +mappingkey 0.830 230 195 34 255 +mappingkey 0.915 230 226 118 255 +mappingkey 1.0 255 255 255 255 \ No newline at end of file diff --git a/data/assets/scene/solarsystem/heliosphere/bastille_day/transferfunctions/CMR-illuminance2.txt b/data/assets/scene/solarsystem/heliosphere/bastille_day/transferfunctions/CMR-illuminance2.txt new file mode 100644 index 0000000000..2ed4bff17e --- /dev/null +++ b/data/assets/scene/solarsystem/heliosphere/bastille_day/transferfunctions/CMR-illuminance2.txt @@ -0,0 +1,14 @@ +width 10 +lower 0.0 +upper 1.0 + +mappingkey 0.0 60 38 164 255 +mappingkey 0.083 106 43 167 255 +mappingkey 0.166 173 54 110 255 +mappingkey 0.332 253 64 40 255 +mappingkey 0.415 234 117 6 255 +mappingkey 0.498 230 169 16 255 +mappingkey 0.664 236 236 159 255 +mappingkey 0.830 251 251 235 255 +mappingkey 0.915 255 255 255 255 +mappingkey 1.0 255 255 255 255 \ No newline at end of file diff --git a/data/assets/scene/solarsystem/heliosphere/bastille_day/transferfunctions/CMR.txt b/data/assets/scene/solarsystem/heliosphere/bastille_day/transferfunctions/CMR.txt new file mode 100644 index 0000000000..cc5102d8a5 --- /dev/null +++ b/data/assets/scene/solarsystem/heliosphere/bastille_day/transferfunctions/CMR.txt @@ -0,0 +1,14 @@ +width 10 +lower 0.0 +upper 1.0 + +mappingkey 0.0 0 0 0 0 +mappingkey 0.083 30 30 100 255 +mappingkey 0.166 60 38 164 255 +mappingkey 0.332 106 43 167 255 +mappingkey 0.415 173 54 110 255 +mappingkey 0.498 253 64 40 255 +mappingkey 0.664 234 117 6 255 +mappingkey 0.830 230 169 16 255 +mappingkey 0.915 236 236 159 255 +mappingkey 1.0 251 251 235 255 \ No newline at end of file diff --git a/data/assets/scene/solarsystem/heliosphere/bastille_day/transferfunctions/density-fieldlines.txt b/data/assets/scene/solarsystem/heliosphere/bastille_day/transferfunctions/density-fieldlines.txt new file mode 100644 index 0000000000..61e11a9bc6 --- /dev/null +++ b/data/assets/scene/solarsystem/heliosphere/bastille_day/transferfunctions/density-fieldlines.txt @@ -0,0 +1,9 @@ +width 6 +lower 0.0 +upper 1.0 +mappingkey 0.0 0 0 255 250 +mappingkey 0.075 0 0 255 250 +mappingkey 0.4 0 255 255 250 +mappingkey 0.58 0 255 0 250 +mappingkey 0.73 255 255 0 250 +mappingkey 1.0 255 0 0 250 diff --git a/data/assets/scene/solarsystem/heliosphere/bastille_day/transferfunctions/flux-nodes-flow.txt b/data/assets/scene/solarsystem/heliosphere/bastille_day/transferfunctions/flux-nodes-flow.txt new file mode 100644 index 0000000000..a1b26fc561 --- /dev/null +++ b/data/assets/scene/solarsystem/heliosphere/bastille_day/transferfunctions/flux-nodes-flow.txt @@ -0,0 +1,11 @@ +width 7 +lower 0.0 +upper 1.0 + +mappingkey 0.0 153 51 255 255 +mappingkey 0.166 51 51 255 255 +mappingkey 0.332 51 255 255 255 +mappingkey 0.498 51 255 51 255 +mappingkey 0.664 255 255 51 255 +mappingkey 0.830 255 153 51 255 +mappingkey 1.0 255 51 51 255 \ No newline at end of file diff --git a/data/assets/scene/solarsystem/heliosphere/bastille_day/transferfunctions/flux-nodes-grey-scale.txt b/data/assets/scene/solarsystem/heliosphere/bastille_day/transferfunctions/flux-nodes-grey-scale.txt new file mode 100644 index 0000000000..a08a35ef75 --- /dev/null +++ b/data/assets/scene/solarsystem/heliosphere/bastille_day/transferfunctions/flux-nodes-grey-scale.txt @@ -0,0 +1,7 @@ +width 7 +lower 0.0 +upper 1.0 + +mappingkey 0.0 45 45 45 255 +mappingkey 0.5 45 45 45 255 +mappingkey 1.0 45 45 45 255 diff --git a/data/assets/scene/solarsystem/heliosphere/bastille_day/transferfunctions/flux-nodes.txt b/data/assets/scene/solarsystem/heliosphere/bastille_day/transferfunctions/flux-nodes.txt new file mode 100644 index 0000000000..71da29abee --- /dev/null +++ b/data/assets/scene/solarsystem/heliosphere/bastille_day/transferfunctions/flux-nodes.txt @@ -0,0 +1,14 @@ +width 10 +lower 0.0 +upper 1.0 + +mappingkey 0.0 127 0 255 255 +mappingkey 0.083 89 59 253 255 +mappingkey 0.166 55 90 246 255 +mappingkey 0.332 23 152 242 255 +mappingkey 0.415 13 194 224 255 +mappingkey 0.498 138 254 174 255 +mappingkey 0.664 227 197 105 255 +mappingkey 0.830 255 128 66 255 +mappingkey 0.915 251 79 37 255 +mappingkey 1.0 255 0 0 255 \ No newline at end of file diff --git a/data/assets/scene/solarsystem/heliosphere/bastille_day/transferfunctions/mas-mhd-blue-to-red.txt b/data/assets/scene/solarsystem/heliosphere/bastille_day/transferfunctions/mas-mhd-blue-to-red.txt new file mode 100644 index 0000000000..97cf430014 --- /dev/null +++ b/data/assets/scene/solarsystem/heliosphere/bastille_day/transferfunctions/mas-mhd-blue-to-red.txt @@ -0,0 +1,14 @@ +width 2048 +lower 0.0 +upper 1.0 + +mappingkey 0.005 0 54 135 0 +mappingkey 0.06 0 67 168 10 +mappingkey 0.1 100 180 200 70 +mappingkey 0.2 180 50 100 100 +mappingkey 0.3 180 90 25 150 +mappingkey 0.4 200 53 18 255 +mappingkey 0.5 255 177 42 255 +mappingkey 0.6 255 22 15 255 +mappingkey 0.7 255 5 5 255 +mappingkey 1.0 255 0 0 255 \ No newline at end of file diff --git a/data/assets/scene/solarsystem/heliosphere/bastille_day/transferfunctions/mas-mhd-original.txt b/data/assets/scene/solarsystem/heliosphere/bastille_day/transferfunctions/mas-mhd-original.txt new file mode 100644 index 0000000000..6520b07c3f --- /dev/null +++ b/data/assets/scene/solarsystem/heliosphere/bastille_day/transferfunctions/mas-mhd-original.txt @@ -0,0 +1,18 @@ +width 2048 +lower 0.0 +upper 1.0 + +mappingkey 0.000001 50 50 250 2 +mappingkey 0.000015 250 250 250 250 +mappingkey 0.00025 70 170 255 250 +mappingkey 0.004 120 230 255 250 +mappingkey 0.0045 255 220 180 250 +mappingkey 0.06 255 150 120 250 +mappingkey 0.1 255 50 20 250 + +mappingkey 0.15 250 0 0 200 +mappingkey 0.20 250 0 0 200 +mappingkey 0.35 250 20 0 200 +mappingkey 0.40 250 0 0 200 +mappingkey 0.60 250 0 0 200 +mappingkey 0.80 250 0 0 255 \ No newline at end of file diff --git a/data/assets/scene/solarsystem/heliosphere/bastille_day/transferfunctions/mas-mhd-r-squared-old.txt b/data/assets/scene/solarsystem/heliosphere/bastille_day/transferfunctions/mas-mhd-r-squared-old.txt new file mode 100644 index 0000000000..7b8b9011f9 --- /dev/null +++ b/data/assets/scene/solarsystem/heliosphere/bastille_day/transferfunctions/mas-mhd-r-squared-old.txt @@ -0,0 +1,18 @@ +width 2048 +lower 0.0 +upper 1.0 + +mappingkey 0.005 0 54 135 0 +mappingkey 0.06 0 85 125 11 +mappingkey 0.1 140 30 70 50 +mappingkey 0.13 160 160 0 45 +mappingkey 0.16 150 150 150 150 +mappingkey 0.2 180 210 255 190 +mappingkey 0.3 190 200 255 250 +mappingkey 0.4 255 255 255 0 +mappingkey 0.5 0 0 0 0 +mappingkey 0.6 137 223 255 0 +mappingkey 0.7 94 255 214 0 +mappingkey 0.8 255 200 180 0 +mappingkey 0.9 249 199 150 0 +mappingkey 1.0 255 140 100 0 diff --git a/data/assets/scene/solarsystem/heliosphere/bastille_day/transferfunctions/mas-mhd-r-squared.txt b/data/assets/scene/solarsystem/heliosphere/bastille_day/transferfunctions/mas-mhd-r-squared.txt new file mode 100644 index 0000000000..ed07552974 --- /dev/null +++ b/data/assets/scene/solarsystem/heliosphere/bastille_day/transferfunctions/mas-mhd-r-squared.txt @@ -0,0 +1,18 @@ +width 2048 +lower 0.0 +upper 1.0 + +mappingkey 0.005 0 54 135 0 +mappingkey 0.06 0 145 255 15 +mappingkey 0.1 0 130 255 70 +mappingkey 0.13 0 200 255 120 +mappingkey 0.16 0 255 255 255 +mappingkey 0.2 90 210 255 130 +mappingkey 0.3 90 200 255 250 +mappingkey 0.4 200 200 230 150 +mappingkey 0.5 92 177 242 200 +mappingkey 0.6 137 223 255 0 +mappingkey 0.7 94 255 214 0 +mappingkey 0.8 255 200 180 0 +mappingkey 0.9 249 199 150 0 +mappingkey 1.0 255 140 100 0 diff --git a/data/assets/scene/solarsystem/heliosphere/bastille_day/transferfunctions/mas-mhd-velocity.txt b/data/assets/scene/solarsystem/heliosphere/bastille_day/transferfunctions/mas-mhd-velocity.txt new file mode 100644 index 0000000000..c536437d85 --- /dev/null +++ b/data/assets/scene/solarsystem/heliosphere/bastille_day/transferfunctions/mas-mhd-velocity.txt @@ -0,0 +1,16 @@ +width 2048 +lower 0.0 +upper 1.0 + +mappingkey 0.005 0 54 135 0 +mappingkey 0.06 0 67 168 3 +mappingkey 0.1 90 180 255 75 +mappingkey 0.2 0 180 255 55 +mappingkey 0.3 0 180 255 70 +mappingkey 0.4 7 93 183 50 +mappingkey 0.5 0 177 242 10 +mappingkey 0.6 1 223 255 9 +mappingkey 0.7 94 255 214 0 +mappingkey 0.8 255 200 114 0 +mappingkey 0.9 249 199 97 0 +mappingkey 1.0 255 140 48 0 \ No newline at end of file diff --git a/data/assets/scene/solarsystem/heliosphere/bastille_day/transferfunctions/velocity-fieldlines.txt b/data/assets/scene/solarsystem/heliosphere/bastille_day/transferfunctions/velocity-fieldlines.txt new file mode 100644 index 0000000000..0852f05fc6 --- /dev/null +++ b/data/assets/scene/solarsystem/heliosphere/bastille_day/transferfunctions/velocity-fieldlines.txt @@ -0,0 +1,9 @@ +width 5 +lower 0.0 +upper 1.0 +mappingkey 0.0 0 0 0 255 +mappingkey 0.25 255 0 0 255 +mappingkey 0.5 255 140 0 255 +mappingkey 0.75 255 255 0 255 +mappingkey 1.0 255 255 255 255 + diff --git a/data/assets/scene/solarsystem/missions/apollo/11/apollo11.asset b/data/assets/scene/solarsystem/missions/apollo/11/apollo11.asset index 92b5cb3525..b353169587 100644 --- a/data/assets/scene/solarsystem/missions/apollo/11/apollo11.asset +++ b/data/assets/scene/solarsystem/missions/apollo/11/apollo11.asset @@ -5,10 +5,21 @@ local moon_transforms = asset.require('scene/solarsystem/planets/earth/moon/moon local descentKeyframes = asset.require('./lem_descent.asset') local descentRotationKeyframes = asset.require('./lem_descent_rotation.asset') -local lem_model = asset.require('scene/solarsystem/missions/apollo/lem_model') local kernels = asset.require('./kernels').kernels -local models = asset.require('./models').models +local models = asset.syncedResource({ + Name = "Apollo Models", + Type = "HttpSynchronization", + Identifier = "apollo_11_models", + Version = 1 +}) + +local lem_model = asset.syncedResource({ + Name = "Apollo Lem Models", + Type = "HttpSynchronization", + Identifier = "apollo_lem_model", + Version = 4 +}) asset.require('spice/base') @@ -171,7 +182,7 @@ local Apollo11LemDescentModel = { }, Renderable = { Type = "RenderableModel", - GeometryFile = lem_model.modelFolder .. "/lmremoved.obj", + GeometryFile = lem_model .. "/lmremoved.obj", SpecularIntensity = 0.0, RotationVector = { 273.750,28.0,309.85 }, LightSources = asset_helper.getDefaultLightSources(sun_transforms.SolarSystemBarycenter.Identifier) @@ -197,7 +208,7 @@ local Apollo11LemLandedModel = { }, Renderable = { Type = "RenderableModel", - GeometryFile = lem_model.modelFolder .. "/LM-2_ver2clean.obj", + GeometryFile = lem_model .. "/LM-2_ver2clean.obj", SpecularIntensity = 0.0, RotationVector = { 273.750,28.0,309.85 }, LightSources = asset_helper.getDefaultLightSources(sun_transforms.SolarSystemBarycenter.Identifier) diff --git a/data/assets/scene/solarsystem/missions/apollo/11/lem.asset b/data/assets/scene/solarsystem/missions/apollo/11/lem.asset index bb5a78ec79..3739de848d 100644 --- a/data/assets/scene/solarsystem/missions/apollo/11/lem.asset +++ b/data/assets/scene/solarsystem/missions/apollo/11/lem.asset @@ -3,8 +3,13 @@ local asset_helper = asset.require('util/asset_helper') local sun_transforms = asset.require('scene/solarsystem/sun/transforms') local moon_asset = asset.require('scene/solarsystem/planets/earth/moon/moon') -local lem_model = asset.require('scene/solarsystem/missions/apollo/lem_model') +local lem_model = asset.syncedResource({ + Name = "Apollo Lem Models", + Type = "HttpSynchronization", + Identifier = "apollo_lem_model", + Version = 4 +}) local Apollo11Lem = { Identifier = "Apollo11Lem", @@ -36,7 +41,7 @@ local Apollo11LemModel = { }, Renderable = { Type = "RenderableModel", - GeometryFile = lem_model.modelFolder .. "/LM-2_ver2clean.obj", + GeometryFile = lem_model .. "/LM-2_ver2clean.obj", RotationVector = { 91.044090,171.229706,111.666664 }, LightSources = asset_helper.getDefaultLightSources(sun_transforms.SolarSystemBarycenter.Identifier) }, diff --git a/data/assets/scene/solarsystem/missions/apollo/11/lem_flipbook.asset b/data/assets/scene/solarsystem/missions/apollo/11/lem_flipbook.asset index d158311265..29972a0ab0 100644 --- a/data/assets/scene/solarsystem/missions/apollo/11/lem_flipbook.asset +++ b/data/assets/scene/solarsystem/missions/apollo/11/lem_flipbook.asset @@ -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) diff --git a/data/assets/scene/solarsystem/missions/apollo/11/models.asset b/data/assets/scene/solarsystem/missions/apollo/11/models.asset deleted file mode 100644 index 46b87d9ba3..0000000000 --- a/data/assets/scene/solarsystem/missions/apollo/11/models.asset +++ /dev/null @@ -1,8 +0,0 @@ -local modelFolder = asset.syncedResource({ - Name = "Apollo Models", - Type = "HttpSynchronization", - Identifier = "apollo_11_models", - Version = 1 -}) - -asset.export('models', modelFolder) diff --git a/data/assets/scene/solarsystem/missions/apollo/15/apollo15.asset b/data/assets/scene/solarsystem/missions/apollo/15/apollo15.asset index 349ad80572..4cf0e06419 100644 --- a/data/assets/scene/solarsystem/missions/apollo/15/apollo15.asset +++ b/data/assets/scene/solarsystem/missions/apollo/15/apollo15.asset @@ -2,7 +2,13 @@ local assetHelper = asset.require('util/asset_helper') local moon_transforms = asset.require('scene/solarsystem/planets/earth/moon/moon') local sun_transforms = asset.require('scene/solarsystem/sun/transforms') asset.require('spice/base') -local models = asset.require('scene/solarsystem/missions/apollo/csm_model').models + +local models = asset.syncedResource({ + Name = "Apollo Models", + Type = "HttpSynchronization", + Identifier = "apollo_models", + Version = 4 +}) local kernels = asset.require('scene/solarsystem/missions/apollo/15/kernels').kernels @@ -50,6 +56,7 @@ local Apollo15 = { Renderable = { Type = "RenderableModel", GeometryFile = models .. "/ApolloCSM.osmodel", + ModelScale = 0.0001, LightSources = { { Type = "SceneGraphLightSource", diff --git a/data/assets/scene/solarsystem/missions/apollo/17/boulder_models.asset b/data/assets/scene/solarsystem/missions/apollo/17/boulder_models.asset deleted file mode 100644 index 79e51abc09..0000000000 --- a/data/assets/scene/solarsystem/missions/apollo/17/boulder_models.asset +++ /dev/null @@ -1,8 +0,0 @@ -local models = asset.syncedResource({ - Name = "Apollo Boulders Models", - Type = "HttpSynchronization", - Identifier = "apollo_boulders", - Version = 1 -}) - -asset.export('models', models) diff --git a/data/assets/scene/solarsystem/missions/apollo/17/bouldersstation2.asset b/data/assets/scene/solarsystem/missions/apollo/17/bouldersstation2.asset index ecf428a649..715cda0ffe 100644 --- a/data/assets/scene/solarsystem/missions/apollo/17/bouldersstation2.asset +++ b/data/assets/scene/solarsystem/missions/apollo/17/bouldersstation2.asset @@ -1,7 +1,13 @@ local sun_transforms = asset.require('scene/solarsystem/sun/transforms') local asset_helper = asset.require('util/asset_helper') local moon_asset = asset.require('scene/solarsystem/planets/earth/moon/moon') -local models = asset.require('./boulder_models').models + +local models = asset.syncedResource({ + Name = "Apollo Boulders Models", + Type = "HttpSynchronization", + Identifier = "apollo_boulders", + Version = 2 +}) local LightSources = { { @@ -47,11 +53,7 @@ local Station2Boulder1Model = { }, Renderable = { Type = "RenderableModel", - Geometry = {{ - Type = "MultiModelGeometry", - GeometryFile = models .. "/b1-v2.obj", - ColorTexture = models .. "/b1-v2_u1_v1.jpeg" - }}, + GeometryFile = models .. "/b1-v2.obj", RotationVector = { 243.243256 ,206.270264, 309.677429 }, LightSources = LightSources, PerformShading = false, @@ -93,11 +95,7 @@ local Station2Boulder2Model = { }, Renderable = { Type = "RenderableModel", - Geometry = {{ - Type = "MultiModelGeometry", - GeometryFile = models .. "/b2model.obj", - ColorTexture = models .. "/b2model_u1_v1.jpeg" - }}, + GeometryFile = models .. "/b2model.obj", RotationVector = { 66.162155, 7.783780, 114.193550 }, LightSources = LightSources, PerformShading = false, @@ -139,11 +137,7 @@ local Station2Boulder3Model = { }, Renderable = { Type = "RenderableModel", - Geometry = {{ - Type = "MultiModelGeometry", - GeometryFile = models .. "/b3model.obj", - ColorTexture = models .. "/b3model_u1_v1.jpeg" - }}, + GeometryFile = models .. "/b3model.obj", RotationVector = { 161.513519 ,243.243256, 65.806450 }, LightSources = LightSources, PerformShading = false, diff --git a/data/assets/scene/solarsystem/missions/apollo/17/bouldersstation6.asset b/data/assets/scene/solarsystem/missions/apollo/17/bouldersstation6.asset index 4f476305d2..ced25ff21e 100644 --- a/data/assets/scene/solarsystem/missions/apollo/17/bouldersstation6.asset +++ b/data/assets/scene/solarsystem/missions/apollo/17/bouldersstation6.asset @@ -1,7 +1,13 @@ local sun_transforms = asset.require('scene/solarsystem/sun/transforms') local asset_helper = asset.require('util/asset_helper') local moon_asset = asset.require('scene/solarsystem/planets/earth/moon/moon') -local models = asset.require('./boulder_models').models + +local models = asset.syncedResource({ + Name = "Apollo Boulders Models", + Type = "HttpSynchronization", + Identifier = "apollo_boulders", + Version = 2 +}) local LightSources = { { @@ -58,11 +64,7 @@ local Station6Frag1Model = { }, Renderable = { Type = "RenderableModel", - Geometry = {{ - Type = "MultiModelGeometry", - GeometryFile = models .. "/A17-S6-frag1.obj", - ColorTexture = models .. "/A17-S6-frag1.png" - }}, + GeometryFile = models .. "/A17-S6-frag1.obj", RotationVector = { 235.909088,165.000000,286.299194 }, LightSources = LightSources, PerformShading = false, @@ -105,11 +107,7 @@ local Station6Frag2Model = { }, Renderable = { Type = "RenderableModel", - Geometry = {{ - Type = "MultiModelGeometry", - GeometryFile = models .. "/station6_boulder_frag2.obj", - ColorTexture = models .. "/frag2crop_u1_v1.jpeg" - }}, + GeometryFile = models .. "/station6_boulder_frag2.obj", RotationVector = { 336.959991,210.239990,325.984253 }, LightSources = LightSources, PerformShading = false, @@ -140,11 +138,7 @@ local Station6Frag3Model = { }, Renderable = { Type = "RenderableModel", - Geometry = {{ - Type = "MultiModelGeometry", - GeometryFile = models .. "/station6_boulder_frag3.obj", - ColorTexture = models .. "/frag3crop_u1_v1.jpeg" - }}, + GeometryFile = models .. "/station6_boulder_frag3.obj", RotationVector = { 293.181824,255.000000,4.090910 }, LightSources = LightSources, PerformShading = false, diff --git a/data/assets/scene/solarsystem/missions/apollo/17/bouldersstation7.asset b/data/assets/scene/solarsystem/missions/apollo/17/bouldersstation7.asset index 26605a4a2a..ab596e44f8 100644 --- a/data/assets/scene/solarsystem/missions/apollo/17/bouldersstation7.asset +++ b/data/assets/scene/solarsystem/missions/apollo/17/bouldersstation7.asset @@ -1,7 +1,13 @@ local sun_transforms = asset.require('scene/solarsystem/sun/transforms') local asset_helper = asset.require('util/asset_helper') local moon_asset = asset.require('scene/solarsystem/planets/earth/moon/moon') -local models = asset.require('./boulder_models').models + +local models = asset.syncedResource({ + Name = "Apollo Boulders Models", + Type = "HttpSynchronization", + Identifier = "apollo_boulders", + Version = 2 +}) local LightSources = { { @@ -47,11 +53,7 @@ local Station7BoulderModel = { }, Renderable = { Type = "RenderableModel", - Geometry = {{ - Type = "MultiModelGeometry", - GeometryFile = models .. "/b7model.obj", - ColorTexture = models .. "/b7model_u1_v1.jpeg" - }}, + GeometryFile = models .. "/b7model.obj", RotationVector = { 1.945950,274.378387,212.903214 }, LightSources = LightSources, PerformShading = false, diff --git a/data/assets/scene/solarsystem/missions/apollo/17/lem.asset b/data/assets/scene/solarsystem/missions/apollo/17/lem.asset index 74dc722275..95339b0979 100644 --- a/data/assets/scene/solarsystem/missions/apollo/17/lem.asset +++ b/data/assets/scene/solarsystem/missions/apollo/17/lem.asset @@ -2,7 +2,12 @@ local asset_helper = asset.require('util/asset_helper') local sun_transforms = asset.require('scene/solarsystem/sun/transforms') local moon_asset = asset.require('scene/solarsystem/planets/earth/moon/moon') -local model = asset.require('scene/solarsystem/missions/apollo/lem_model') +local model = asset.syncedResource({ + Name = "Apollo Lem Models", + Type = "HttpSynchronization", + Identifier = "apollo_lem_model", + Version = 4 +}) local Apollo17Lem = { Identifier = "Apollo17Lem", @@ -34,7 +39,7 @@ local Apollo17LemModel = { }, Renderable = { Type = "RenderableModel", - GeometryFile = model.modelFolder .. "/LM-2_ver2clean.obj", + GeometryFile = model .. "/LM-2_ver2clean.obj", SpecularIntensity = 0.0, RotationVector = { 110.255219,171.229706,126.666664 }, LightSources = asset_helper.getDefaultLightSources(sun_transforms.SolarSystemBarycenter.Identifier) diff --git a/data/assets/scene/solarsystem/missions/apollo/8/launch_model.asset b/data/assets/scene/solarsystem/missions/apollo/8/launch_model.asset index 19a8084f4e..c5f39164b5 100644 --- a/data/assets/scene/solarsystem/missions/apollo/8/launch_model.asset +++ b/data/assets/scene/solarsystem/missions/apollo/8/launch_model.asset @@ -2,7 +2,13 @@ local asset_helper = asset.require('util/asset_helper') local earth_transforms = asset.require('scene/solarsystem/planets/earth/transforms') local sun_transforms = asset.require('scene/solarsystem/sun/transforms') local kernels = asset.require('./kernels').kernels -local models = asset.require('scene/solarsystem/missions/apollo/csm_model').models + +local models = asset.syncedResource({ + Name = "Apollo Models", + Type = "HttpSynchronization", + Identifier = "apollo_models", + Version = 4 +}) local apolloSpiceId = "-908" @@ -38,11 +44,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 +52,7 @@ local Apollo8LaunchModel = { Renderable = { Type = "RenderableModel", GeometryFile = models .. "/ApolloCSM.osmodel", + ModelScale = 0.0001, LightSources = { { Type = "SceneGraphLightSource", diff --git a/data/assets/scene/solarsystem/missions/apollo/8/model.asset b/data/assets/scene/solarsystem/missions/apollo/8/model.asset index 4399deb973..a110a45646 100644 --- a/data/assets/scene/solarsystem/missions/apollo/8/model.asset +++ b/data/assets/scene/solarsystem/missions/apollo/8/model.asset @@ -2,7 +2,13 @@ local asset_helper = asset.require('util/asset_helper') local earth_transforms = asset.require('scene/solarsystem/planets/earth/transforms') local sun_transforms = asset.require('scene/solarsystem/sun/transforms') local kernels = asset.require('./kernels').kernels -local models = asset.require('scene/solarsystem/missions/apollo/csm_model').models + +local models = asset.syncedResource({ + Name = "Apollo Models", + Type = "HttpSynchronization", + Identifier = "apollo_models", + Version = 4 +}) local apolloSpiceId = "-908" @@ -50,11 +56,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 +64,7 @@ local Apollo8Model = { Renderable = { Type = "RenderableModel", GeometryFile = models .. "/ApolloCSM.osmodel", + ModelScale = 0.0001, LightSources = { { Type = "SceneGraphLightSource", diff --git a/data/assets/scene/solarsystem/missions/apollo/csm_model.asset b/data/assets/scene/solarsystem/missions/apollo/csm_model.asset deleted file mode 100644 index fb8c6b2165..0000000000 --- a/data/assets/scene/solarsystem/missions/apollo/csm_model.asset +++ /dev/null @@ -1,8 +0,0 @@ -local models = asset.syncedResource({ - Name = "Apollo Models", - Type = "HttpSynchronization", - Identifier = "apollo_models", - Version = 3 -}) - -asset.export('models', models) diff --git a/data/assets/scene/solarsystem/missions/apollo/insignias_map.asset b/data/assets/scene/solarsystem/missions/apollo/insignias_map.asset index acd33f0daa..b79b609c3c 100644 --- a/data/assets/scene/solarsystem/missions/apollo/insignias_map.asset +++ b/data/assets/scene/solarsystem/missions/apollo/insignias_map.asset @@ -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) diff --git a/data/assets/scene/solarsystem/missions/apollo/lem_model.asset b/data/assets/scene/solarsystem/missions/apollo/lem_model.asset deleted file mode 100644 index 5490471d7e..0000000000 --- a/data/assets/scene/solarsystem/missions/apollo/lem_model.asset +++ /dev/null @@ -1,8 +0,0 @@ -local modelFolder = asset.syncedResource({ - Name = "Apollo Lem Models", - Type = "HttpSynchronization", - Identifier = "apollo_lem_model", - Version = 4 -}) - -asset.export('modelFolder', modelFolder) diff --git a/data/assets/scene/solarsystem/missions/dawn/ceres.asset b/data/assets/scene/solarsystem/missions/dawn/ceres.asset index 3b5bcc41f9..ec16cb3d4c 100644 --- a/data/assets/scene/solarsystem/missions/dawn/ceres.asset +++ b/data/assets/scene/solarsystem/missions/dawn/ceres.asset @@ -1,9 +1,15 @@ local assetHelper = asset.require('util/asset_helper') local transforms = asset.require('scene/solarsystem/sun/transforms') -local kernels = asset.require('./dawn_kernels').Kernels +local kernels = asset.syncedResource({ + Name = "Dawn Kernels", + Type = "HttpSynchronization", + Identifier = "dawn_kernels", + Version = 2 +}) + local textures = asset.syncedResource({ Name = "Ceres Textures", Type = "HttpSynchronization", @@ -43,8 +49,7 @@ local Ceres = { Layers = { ColorLayers = { { - Name = "Texture", - Identifier = "CeresTexture", + Identifier = "Texture", FilePath = textures .. "/gray.png", Enabled = true } diff --git a/data/assets/scene/solarsystem/missions/dawn/dawn.asset b/data/assets/scene/solarsystem/missions/dawn/dawn.asset index 5887fb10d0..6b9db76edd 100644 --- a/data/assets/scene/solarsystem/missions/dawn/dawn.asset +++ b/data/assets/scene/solarsystem/missions/dawn/dawn.asset @@ -1,9 +1,15 @@ local assetHelper = asset.require('util/asset_helper') local transforms = asset.require('scene/solarsystem/sun/transforms') -local kernels = asset.require('./dawn_kernels').Kernels local sunTransforms = asset.require('scene/solarsystem/sun/transforms') +local kernels = asset.syncedResource({ + Name = "Dawn Kernels", + Type = "HttpSynchronization", + Identifier = "dawn_kernels", + Version = 2 +}) + local textures = asset.syncedResource({ Name = "Dawn Textures", Type = "HttpSynchronization", diff --git a/data/assets/scene/solarsystem/missions/dawn/dawn_kernels.asset b/data/assets/scene/solarsystem/missions/dawn/dawn_kernels.asset deleted file mode 100644 index ab4e5d4c2e..0000000000 --- a/data/assets/scene/solarsystem/missions/dawn/dawn_kernels.asset +++ /dev/null @@ -1,8 +0,0 @@ -local Kernels = asset.syncedResource({ - Name = "Dawn Kernels", - Type = "HttpSynchronization", - Identifier = "dawn_kernels", - Version = 2 -}) - -asset.export("Kernels", Kernels) diff --git a/data/assets/scene/solarsystem/missions/dawn/vesta.asset b/data/assets/scene/solarsystem/missions/dawn/vesta.asset index 247e009502..d4f79dc20f 100644 --- a/data/assets/scene/solarsystem/missions/dawn/vesta.asset +++ b/data/assets/scene/solarsystem/missions/dawn/vesta.asset @@ -1,8 +1,14 @@ local assetHelper = asset.require('util/asset_helper') local transforms = asset.require('scene/solarsystem/sun/transforms') -local kernels = asset.require('./dawn_kernels').Kernels +local kernels = asset.syncedResource({ + Name = "Dawn Kernels", + Type = "HttpSynchronization", + Identifier = "dawn_kernels", + Version = 2 +}) + local textures = asset.syncedResource({ Name = "Vesta Textures", Type = "HttpSynchronization", diff --git a/data/assets/scene/solarsystem/missions/gaia/gaia.asset b/data/assets/scene/solarsystem/missions/gaia/gaia.asset index 2268aa01bd..638ad5833f 100644 --- a/data/assets/scene/solarsystem/missions/gaia/gaia.asset +++ b/data/assets/scene/solarsystem/missions/gaia/gaia.asset @@ -20,7 +20,7 @@ local Gaia = { XAxis = { 1.0, 0.0, 0.0 }, XAxisOrthogonal = true, YAxis = "Sun", - YAxisInverted = true + YAxisInvert = true }, Scale = { Type = "StaticScale", diff --git a/data/assets/scene/solarsystem/missions/gaia/trail.asset b/data/assets/scene/solarsystem/missions/gaia/trail.asset index ee00ea2a6c..64b8dfd8de 100644 --- a/data/assets/scene/solarsystem/missions/gaia/trail.asset +++ b/data/assets/scene/solarsystem/missions/gaia/trail.asset @@ -11,7 +11,7 @@ local trail = asset.syncedResource({ local GaiaTrail = { Identifier = "GaiaTrail", - Parent = earthTransforms.EarthBarycenter.Identifier, + Parent = earthTransforms.EarthCenter.Identifier, Renderable = { Type = "RenderableTrailTrajectory", Translation = { @@ -36,7 +36,7 @@ local GaiaTrail = { local GaiaTrailEclip = { Identifier = "GaiaTrail_Eclip", - Parent = sunTransforms.SolarSystemBarycenter.Identifier, + Parent = sunTransforms.SunCenter.Identifier, Renderable = { Type = "RenderableTrailTrajectory", Enabled = false, diff --git a/data/assets/scene/solarsystem/missions/gaia/transforms.asset b/data/assets/scene/solarsystem/missions/gaia/transforms.asset index 5db3a1205c..83441604d5 100644 --- a/data/assets/scene/solarsystem/missions/gaia/transforms.asset +++ b/data/assets/scene/solarsystem/missions/gaia/transforms.asset @@ -11,7 +11,7 @@ local trail = asset.syncedResource({ local GaiaPosition = { Identifier = "GaiaPosition", - Parent = earthTransforms.EarthBarycenter.Identifier, + Parent = earthTransforms.EarthCenter.Identifier, Transform = { Translation = { Type = "HorizonsTranslation", diff --git a/data/assets/scene/solarsystem/missions/jwst/HUDFImage.asset b/data/assets/scene/solarsystem/missions/jwst/hudf.asset similarity index 55% rename from data/assets/scene/solarsystem/missions/jwst/HUDFImage.asset rename to data/assets/scene/solarsystem/missions/jwst/hudf.asset index 7f45814a94..ef8cc9b4c7 100644 --- a/data/assets/scene/solarsystem/missions/jwst/HUDFImage.asset +++ b/data/assets/scene/solarsystem/missions/jwst/hudf.asset @@ -1,14 +1,8 @@ local assetHelper = asset.require('util/asset_helper') local transforms = asset.require('scene/solarsystem/planets/earth/transforms') -local jwstTransforms = asset.require('scene/solarsystem/missions/jwst/jwst') +local jwstTransforms = asset.require('./transforms') local sunTransforms = asset.require('scene/solarsystem/sun/transforms') - -local image = asset.syncedResource({ - Name = "HUDF image", - Type = "HttpSynchronization", - Identifier = "hudf_image", - Version = 1 -}) +local image = asset.require('./image').image local DISTANCE = 9.2E15; @@ -29,9 +23,12 @@ local HUDFPosition = { } }, GUI = { - Name = "Hubble Ultra Deep field", - Path = "/Solar System/Missions/JWST", - Hidden = true + Name = "Hubble Ultra Deep Field Position", + Path = "/Solar System/Missions/JWST/HUDF", + Hidden = true, + Description = [[ + Galactic cartesian position for the Hubble Ultra Deep Field + ]], } } @@ -39,18 +36,27 @@ local HUDFImage = { Identifier = "HUDFImage", Enabled = false, Type = "ScreenSpaceImageLocal", - Name = "Hubble Ultra Deep field", + Name = "Hubble Ultra Deep Field", UseRadiusAzimuthElevation = true, FaceCamera = false, - RadiusAzimuthElevation = { 200.0, 0.5, 0.15 }, + RadiusAzimuthElevation = { 200.0, 0.5, 0.1 }, UsePerspectiveProjection = false, Opacity = 1.0, - TexturePath = image .. "/Hubble_ultra_deep_field.jpg", + TexturePath = image .. "/Hubble_ultra_deep_field.png", Tag = { "mission_jwst_hudf" }, + Description = [[ + Image of the Hubble Ultra Deep Field by NASA, ESA, and S. Beckwith (STScI) and + the HUDF Team. + ]], } local HUDFJWSTLine = { Identifier = "HUDFJWSTLine", + TimeFrame = { + Type = "TimeFrameInterval", + Start = "2018 OCT 01 14:06:03", + End = "2021 OCT 01" + }, Parent = sunTransforms.SolarSystemBarycenter.Identifier, Renderable = { Enabled = false, @@ -63,7 +69,10 @@ local HUDFJWSTLine = { Tag = { "mission_jwst_hudf" }, GUI = { Name = "JWST to HUDF Line", - Path = "/Solar System/Missions/JWST", + Path = "/Solar System/Missions/JWST/HUDF", + Description = [[ + Line from the James Webb Space Telescope to the Hubble Ultra Deep Field + ]], } } @@ -75,3 +84,16 @@ end) asset.onDeinitialize(function() openspace.removeScreenSpaceRenderable(HUDFImage.Identifier) end) + +asset.meta = { + Name = "Hubble Ultra Deep Field Image and Line", + Version = "1.0", + Description = [[ + Screenspace image of the Hubble Ultra Deep Field and a line from the + James Webb Space Telescope to the Hubble Ultra Deep Field position. + ]], + Author = "OpenSpace Team", + URL = "http://openspaceproject.com", + License = "MIT license", + Identifiers = {"HUDFPosition", "HUDFImage", "HUDFJWSTLine"} +} diff --git a/data/assets/scene/solarsystem/missions/jwst/image.asset b/data/assets/scene/solarsystem/missions/jwst/image.asset new file mode 100644 index 0000000000..4ca58c42f2 --- /dev/null +++ b/data/assets/scene/solarsystem/missions/jwst/image.asset @@ -0,0 +1,21 @@ +local image = asset.syncedResource({ + Name = "HUDF Image", + Type = "HttpSynchronization", + Identifier = "hudf_image", + Version = 3 +}) + +asset.export('image', image) + +asset.meta = { + Name = "Hubble Ultra Deep Field", + Version = "1.0", + Description = "Hubble Ultra Deep Field Image", + Author = "NASA, ESA, and S. Beckwith (STScI) and the HUDF Team", + URL = "https://esahubble.org/images/heic0611b/", + License = [[ + Original image by NASA, ESA, and S. Beckwith (STScI) and the HUDF Team, + white frame and red arrow added by OpenSpace Team.
+ https://creativecommons.org/licenses/by/4.0/ + ]] +} diff --git a/data/assets/scene/solarsystem/missions/jwst/jwst.asset b/data/assets/scene/solarsystem/missions/jwst/jwst.asset index ebaf97a6a5..bbe6322584 100644 --- a/data/assets/scene/solarsystem/missions/jwst/jwst.asset +++ b/data/assets/scene/solarsystem/missions/jwst/jwst.asset @@ -1,29 +1,13 @@ local assetHelper = asset.require('util/asset_helper') local sunTransforms = asset.require('scene/solarsystem/sun/transforms') - +local transforms = asset.require('./transforms') asset.require('spice/base') -asset.require('scene/solarsystem/planets/earth/lagrange_points/lagrange_points') -local transforms = asset.require('scene/solarsystem/planets/earth/lagrange_points/L2') -local JWSTKernel = asset.syncedResource({ - Name = "JWST Kernel", - Type = "HttpSynchronization", - Identifier = "jwst_kernels", - Version = 1 -}) - ---[[local JWSTHorizons = asset.syncedResource({ - Name = "JWST Horizons", - Type = "HttpSynchronization", - Identifier = "jwst_horizons", - Version = 1 -})]]-- - -local model = asset.syncedResource({ +local models = asset.syncedResource({ Name = "JWST Model", Type = "HttpSynchronization", Identifier = "jwst_model", - Version = 1 + Version = 3 }) local band = asset.syncedResource({ @@ -33,47 +17,14 @@ local band = asset.syncedResource({ Version = 1 }) -local JWSTPosition = { - Identifier = "JWSTPosition", - Parent = transforms.L2.Identifier, - Transform = { - Translation = { - Type = "SpiceTranslation", - Target = "JWST", - Observer = "392", -- L2 - Kernels = JWSTKernel .. "/jwst_horizons_20200101_20240101_v01.bsp" - }, - }, - GUI = { - Name = "JWST Position", - Path = "/Solar System/Missions/JWST", - Hidden = true, - } -} - -local JWSTRotation = { - Identifier = "JWSTRotation", - Parent = JWSTPosition.Identifier, - Transform = { - Rotation = { - Type = "FixedRotation", - Attached = "JWSTRotation", - XAxis = { 1, 0, 0 }, - XAxisOrthogonal = true, - YAxisInvert = true, - YAxis = sunTransforms.SolarSystemBarycenter.Identifier - } - }, - GUI = { - Name = "JWST Rotation", - Path = "/Solar System/Missions/JWST", - Hidden = true, - } -} - local JWSTBand = { Identifier = "JWSTBand", - Parent = JWSTPosition.Identifier, + Parent = transforms.JWSTPosition.Identifier, + TimeFrame = { + Type = "TimeFrameInterval", + Start = "2018 OCT 01 14:06:03", + End = "2021 OCT 01" + }, Transform = { Rotation = { Type = "FixedRotation", @@ -97,25 +48,28 @@ local JWSTBand = { Tag = { "mission_jwst_fov" }, GUI = { Name = "JWST Safe Viewing Band", - Path = "/Solar System/Missions/JWST" + Path = "/Solar System/Missions/JWST", + Description = [[ + The safe viewing band for the James Webb Space Telescope at its current position + ]], } } local JWSTModel = { Identifier = "JWSTModel", - Parent = JWSTRotation.Identifier, + Parent = transforms.JWSTRotation.Identifier, TimeFrame = { Type = "TimeFrameInterval", - Start = "2020 JAN 01", - End = "2024 JAN 01" + Start = "2018 OCT 01 14:06:03", + End = "2021 OCT 01" }, Renderable = { Type = "RenderableModel", - GeometryFile = model .. "/JWSTFBX.osmodel", - ModelScale = "Foot", - InvertModelScale = true, + GeometryFile = models .. "/jwst_anim74_2fps_2018_nb.osmodel", + ModelScale = 0.0328, -- First scale down with centimeters then scale up with feet EnableAnimation = true, - AnimationStartTime = "2018 10 01 14:05:52", + AnimationStartTime = "2018 10 01 14:06:03", + AnimationTimeScale = "Millisecond", AnimationMode = "Once", LightSources = { { @@ -131,55 +85,21 @@ local JWSTModel = { GUI = { Name = "James Webb Space Telescope Model", Path = "/Solar System/Missions/JWST", - } -} - -local JWSTTrail = { - Identifier = "JWSTTrail", - Parent = transforms.L2.Identifier, - Renderable = { - Type = "RenderableTrailOrbit", - Translation = { - Type = "SpiceTranslation", - Target = "JWST", - Observer = "392", -- L2 - Kernels = JWSTKernel .. "/jwst_horizons_20200101_20240101_v01.bsp" - }, - Color = { 0.9, 0.9, 0.0 }, - Period = 91.3105, - Resolution = 100 - }, - GUI = { - Name = "JWST Trail", - Path = "/Solar System/Missions/JWST" - } -} - -local JWSTSunTrail = { - Identifier = "JWSTSunTrail", - Parent = sunTransforms.SolarSystemBarycenter.Identifier, - Renderable = { - Enabled = false, - Type = "RenderableTrailOrbit", - Translation = { - Type = "SpiceTranslation", - Target = "JWST", - Observer = "SSB", - Kernels = JWSTKernel .. "/jwst_horizons_20200101_20240101_v01.bsp" - }, - Color = { 0.0, 0.9, 0.9 }, - Period = 365.242, - Resolution = 1000 - }, - GUI = { - Name = "JWST Sun Trail", - Path = "/Solar System/Missions/JWST" + Description = [[ + Animated model of the James Webb Space Telescope that shows its deployment in + real time + ]], } } local JWSTFov = { Identifier = "JWSTFov", Parent = JWSTModel.Identifier, + TimeFrame = { + Type = "TimeFrameInterval", + Start = "2018 OCT 01 14:06:03", + End = "2021 OCT 01" + }, Renderable = { Enabled = false, Type = "RenderablePrism", @@ -200,103 +120,53 @@ local JWSTFov = { GUI = { Name = "JWST Field of View", Path = "/Solar System/Missions/JWST", + Description = [[ + The field of view for the James Webb Space Telescope at its current position + ]], } } --- Launch, coming soon ---[[local JWSTLaunchPosition = { - Identifier = "JWSTLaunchPosition", - Parent = transforms.L2.Identifier, - Transform = { - Translation = { - Type = "HorizonsTranslation", - HorizonsTextFile = JWSTHorizons .. "/horizons_jwst_launch.dat", - }, - }, - GUI = { - Name = "JWST Launch Position", - Path = "/Solar System/Missions/JWST", - Hidden = true, - } -} - -local JWSTLaunchModel = { - Identifier = "JWSTLaunchModel", - Parent = JWSTLaunchPosition.Identifier, +local JWSTLabel = { + Identifier = "JWSTLabel", + Parent = transforms.JWSTPosition.Identifier, TimeFrame = { Type = "TimeFrameInterval", - Start = "2018 OCT 01 14:05:52", - End = "2019 OCT 01" - }, - Transform = { - Rotation = { - Type = "FixedRotation", - Attached = "JWSTRotation", - XAxis = { 1, 0, 0 }, - XAxisOrthogonal = true, - YAxisInvert = true, - YAxis = sunTransforms.SolarSystemBarycenter.Identifier - } + Start = "2018 OCT 01 14:06:03", + End = "2021 OCT 01" }, Renderable = { - Type = "RenderableModel", - GeometryFile = model .. "/JWSTFBX.osmodel", - ModelScale = "Foot", - InvertModelScale = true, - EnableAnimation = true, - AnimationStartTime = "2018 10 01 14:05:52", - AnimationMode = "Once", - LightSources = { - { - Type = "SceneGraphLightSource", - Identifier = "Sun", - Node = sunTransforms.SolarSystemBarycenter.Identifier, - Intensity = 1.0 - } - }, - PerformShading = true, - DisableFaceCulling = true + Enabled = true, + Type = "RenderableLabels", + Text = "JWST", + FontSize = 20, + Size = 6.25, + MinMaxSize = { 1.0, 100.0 }, + OrientationOption = "Camera View Direction", + BlendMode = "Normal", + EnableFading = false }, GUI = { - Name = "JWST Launch Model", + Name = "JWST Label", Path = "/Solar System/Missions/JWST", + Description = "Main label for the James Webb Space Telescope" } } -local JWSTLaunchTrail = { - Identifier = "JWSTLaunchTrail", - Parent = transforms.L2.Identifier, - TimeFrame = { - Type = "TimeFrameInterval", - Start = "2018 OCT 01 13:18:00", - End = "2019 OCT 01" - }, - Renderable = { - Type = "RenderableTrailTrajectory", - Translation = { - Type = "HorizonsTranslation", - HorizonsTextFile = JWSTHorizons .. "/horizons_jwst_launch.dat", - }, - Color = { 0.9, 0.9, 0.0 }, - StartTime = "2018 OCT 01 13:18:00", - EndTime = "2019 OCT 01", - SampleInterval = 600 - }, - GUI = { - Name = "JWST Launch Trail", - Path = "/Solar System/Missions/JWST" - } -}]]-- - assetHelper.registerSceneGraphNodesAndExport(asset, { - JWSTTrail, - JWSTSunTrail, - --JWSTLaunchTrail, - JWSTPosition, - --JWSTLaunchPosition, - JWSTRotation, JWSTBand, JWSTModel, - --JWSTLaunchModel, - JWSTFov + JWSTFov, + JWSTLabel }) + +asset.meta = { + Name = "James Webb Space Telescope", + Version = "1.0", + Description = [[ + James Webb Space Telescope animated model, safe viewing band, field of view and label. + ]], + Author = "OpenSpace Team", + URL = "http://openspaceproject.com", + License = "MIT license", + Identifiers = {"JWSTBand", "JWSTModel", "JWSTFov", "JWSTLabel"} +} diff --git a/data/assets/scene/solarsystem/missions/jwst/timelapse.asset b/data/assets/scene/solarsystem/missions/jwst/timelapse.asset new file mode 100644 index 0000000000..8ba9149688 --- /dev/null +++ b/data/assets/scene/solarsystem/missions/jwst/timelapse.asset @@ -0,0 +1,436 @@ +local assetHelper = asset.require('util/asset_helper') + +-- JWST timelapse timeline +local timelapse = [[ + openspace.scriptScheduler.loadScheduledScript( + "2018 OCT 01 14:06:02", + "", + "openspace.scriptScheduler.clear(0)" + ) + -- Mission start + openspace.scriptScheduler.loadScheduledScript( + "2018 OCT 01 14:06:04", + "openspace.setPropertyValueSingle('Scene.Earth.Renderable.Layers.NightLayers.Earth_at_Night_2012.Settings.Gamma', 0.7)" .. + "openspace.setPropertyValueSingle('Scene.EarthAtmosphere.Renderable.Enabled', false)", + "openspace.time.interpolateDeltaTime(-1)" .. + "openspace.setPropertyValueSingle('Dashboard.JWSTStateText.Text', '')" .. + "openspace.setPropertyValueSingle('Scene.Earth.Renderable.Layers.NightLayers.Earth_at_Night_2012.Settings.Gamma', 1.0)" .. + "openspace.setPropertyValueSingle('Scene.EarthAtmosphere.Renderable.Enabled', true)" + ) + openspace.scriptScheduler.loadScheduledScript( + "2018 OCT 01 14:06:05", -- 2 sec delay + "openspace.time.interpolateDeltaTime(120)" .. + "openspace.setPropertyValueSingle('Dashboard.JWSTStateText.Text', 'Time speed: 2 minutes/second')", + "openspace.time.interpolateDeltaTime(-1)" .. + "openspace.setPropertyValueSingle('Dashboard.JWSTStateText.Text', '')" + ) + openspace.scriptScheduler.loadScheduledScript( + "2018 OCT 01 14:10:03", -- 4 min pre delay + "", + "openspace.time.interpolateDeltaTime(-1)" .. + "openspace.setPropertyValueSingle('Dashboard.JWSTStateText.Text', '')" + ) + + -- array deploy, forwards + openspace.scriptScheduler.loadScheduledScript( + "2018 OCT 01 14:35:23", -- 1 min pre delay so time to interpolate + "openspace.time.interpolateDeltaTime(1)" .. + "openspace.setPropertyValueSingle('Dashboard.JWSTStateText.Text', 'Time speed: 1 second/second')" + ) + -- array deploy, backwards + openspace.scriptScheduler.loadScheduledScript( + "2018 OCT 01 14:36:23", + "", + "openspace.time.interpolateDeltaTime(-120)" .. + "openspace.setPropertyValueSingle('Dashboard.JWSTStateText.Text', 'Time speed: -2 minutes/second')" + ) + + -- array complete, forwards + openspace.scriptScheduler.loadScheduledScript( + "2018 OCT 01 14:36:45", + "openspace.time.interpolateDeltaTime(7200)" .. + "openspace.setPropertyValueSingle('Dashboard.JWSTStateText.Text', 'Time speed: 2 hours/second')" + ) + -- array complete, backwards + openspace.scriptScheduler.loadScheduledScript( + "2018 OCT 01 14:37:55", -- 1 min 10 sec pre delay so time to interpolate + "", + "openspace.time.interpolateDeltaTime(-1)" .. + "openspace.setPropertyValueSingle('Dashboard.JWSTStateText.Text', 'Time speed: -1 second/second')" + ) + -- array complete, backwards prepare + openspace.scriptScheduler.loadScheduledScript( + "2018 OCT 01 15:46:45", -- 1h 10 min delay for interpolation + "", + "openspace.time.interpolateDeltaTime(-120)" .. + "openspace.setPropertyValueSingle('Dashboard.JWSTStateText.Text', 'Time speed: -2 minutes/second')" + ) + + -- antenna deploy + openspace.scriptScheduler.loadScheduledScript( + "2018 OCT 02 08:06:03", + "openspace.time.interpolateDeltaTime(1800)" .. + "openspace.setPropertyValueSingle('Dashboard.JWSTStateText.Text', 'Time speed: 30 minutes/second')", + "openspace.time.interpolateDeltaTime(-7200)" .. + "openspace.setPropertyValueSingle('Dashboard.JWSTStateText.Text', 'Time speed: -2 hours/second')" + ) + + -- antenna complete, forwards + openspace.scriptScheduler.loadScheduledScript( + "2018 OCT 02 13:45:03", + "openspace.time.interpolateDeltaTime(18000)" .. + "openspace.setPropertyValueSingle('Dashboard.JWSTStateText.Text', 'Time speed: 5 hours/second')" + ) + -- antenna complete, backwards + openspace.scriptScheduler.loadScheduledScript( + "2018 OCT 02 14:45:03", -- 1h pre delay so time to interpolate + "", + "openspace.time.interpolateDeltaTime(-1800)" .. + "openspace.setPropertyValueSingle('Dashboard.JWSTStateText.Text', 'Time speed: -30 minutes/second')" + ) + + -- fw palette deploy, forwards + openspace.scriptScheduler.loadScheduledScript( + "2018 OCT 04 06:26:38", -- 2h pre delay so time to interpolate + "openspace.time.interpolateDeltaTime(3600)" .. + "openspace.setPropertyValueSingle('Dashboard.JWSTStateText.Text', 'Time speed: 1 hour/second')" + ) + -- fw palette deploy, backwards + openspace.scriptScheduler.loadScheduledScript( + "2018 OCT 04 08:26:38", + "", + "openspace.time.interpolateDeltaTime(-18000)" .. + "openspace.setPropertyValueSingle('Dashboard.JWSTStateText.Text', 'Time speed: -5 hours/second')" + ) + + -- fw palette complete + openspace.scriptScheduler.loadScheduledScript( + "2018 OCT 04 20:06:03", + "openspace.time.interpolateDeltaTime(1800)" .. + "openspace.setPropertyValueSingle('Dashboard.JWSTStateText.Text', 'Time speed: 30 minutes/second')", + "openspace.time.interpolateDeltaTime(-3600)" .. + "openspace.setPropertyValueSingle('Dashboard.JWSTStateText.Text', 'Time speed: -1 hour/second')" + ) + + -- r palette deploy + openspace.scriptScheduler.loadScheduledScript( + "2018 OCT 04 22:57:03", + "openspace.time.interpolateDeltaTime(1800)" .. + "openspace.setPropertyValueSingle('Dashboard.JWSTStateText.Text', 'Time speed: 30 minutes/second')", + "openspace.time.interpolateDeltaTime(-1800)" .. + "openspace.setPropertyValueSingle('Dashboard.JWSTStateText.Text', 'Time speed: -30 minutes/second')" + ) + + -- r palette complete + openspace.scriptScheduler.loadScheduledScript( + "2018 OCT 05 02:06:03", + "openspace.time.interpolateDeltaTime(120)" .. + "openspace.setPropertyValueSingle('Dashboard.JWSTStateText.Text', 'Time speed: 2 minutes/second')", + "openspace.time.interpolateDeltaTime(-1800)" .. + "openspace.setPropertyValueSingle('Dashboard.JWSTStateText.Text', 'Time speed: -30 minutes/second')" + ) + + -- base rise deploy + openspace.scriptScheduler.loadScheduledScript( + "2018 OCT 05 02:28:03", + "openspace.time.interpolateDeltaTime(7200)" .. + "openspace.setPropertyValueSingle('Dashboard.JWSTStateText.Text', 'Time speed: 2 hours/second')", + "openspace.time.interpolateDeltaTime(-120)" .. + "openspace.setPropertyValueSingle('Dashboard.JWSTStateText.Text', 'Time speed: -2 minutes/second')" + ) + + -- base rise complete + openspace.scriptScheduler.loadScheduledScript( + "2018 OCT 06 07:41:03", + "openspace.time.interpolateDeltaTime(1800)" .. + "openspace.setPropertyValueSingle('Dashboard.JWSTStateText.Text', 'Time speed: 30 minutes/second')", + "openspace.time.interpolateDeltaTime(-7200)" .. + "openspace.setPropertyValueSingle('Dashboard.JWSTStateText.Text', 'Time speed: -2 hours/second')" + ) + + -- aft flap deploy + openspace.scriptScheduler.loadScheduledScript( + "2018 OCT 06 11:06:03", + "openspace.time.interpolateDeltaTime(600)" .. + "openspace.setPropertyValueSingle('Dashboard.JWSTStateText.Text', 'Time speed: 10 minutes/second')", + "openspace.time.interpolateDeltaTime(-1800)" .. + "openspace.setPropertyValueSingle('Dashboard.JWSTStateText.Text', 'Time speed: -30 minutes/second')" + ) + + -- aft flap complete, forwards + openspace.scriptScheduler.loadScheduledScript( + "2018 OCT 06 15:43:03", + "openspace.time.interpolateDeltaTime(3600)" .. + "openspace.setPropertyValueSingle('Dashboard.JWSTStateText.Text', 'Time speed: 1 hour/second')" + ) + -- aft flap complete, backwards + openspace.scriptScheduler.loadScheduledScript( + "2018 OCT 06 16:13:03", -- 30 min pre delay so time to interpolate + "", + "openspace.time.interpolateDeltaTime(-600)" .. + "openspace.setPropertyValueSingle('Dashboard.JWSTStateText.Text', 'Time speed: -10 minutes/second')" + ) + + -- mid booms extend + openspace.scriptScheduler.loadScheduledScript( + "2018 OCT 07 01:35:46", + "openspace.time.interpolateDeltaTime(1800)" .. + "openspace.setPropertyValueSingle('Dashboard.JWSTStateText.Text', 'Time speed: 30 minutes/second')", + "openspace.time.interpolateDeltaTime(-3600)" .. + "openspace.setPropertyValueSingle('Dashboard.JWSTStateText.Text', 'Time speed: -1 hour/second')" + ) + + -- first boom stop + openspace.scriptScheduler.loadScheduledScript( + "2018 OCT 07 02:22:19", + "openspace.time.interpolateDeltaTime(1800)" .. + "openspace.setPropertyValueSingle('Dashboard.JWSTStateText.Text', 'Time speed: 30 minutes/second')", + "openspace.time.interpolateDeltaTime(-1800)" .. + "openspace.setPropertyValueSingle('Dashboard.JWSTStateText.Text', 'Time speed: -30 minutes/second')" + ) + + -- right boom complete + openspace.scriptScheduler.loadScheduledScript( + "2018 OCT 07 07:48:08", + "openspace.time.interpolateDeltaTime(1800)" .. + "openspace.setPropertyValueSingle('Dashboard.JWSTStateText.Text', 'Time speed: 30 minutes/second')", + "openspace.time.interpolateDeltaTime(-1800)" .. + "openspace.setPropertyValueSingle('Dashboard.JWSTStateText.Text', 'Time speed: -30 minutes/second')" + ) + + -- left booms complete + openspace.scriptScheduler.loadScheduledScript( + "2018 OCT 07 12:12:03", + "openspace.time.interpolateDeltaTime(30)" .. + "openspace.setPropertyValueSingle('Dashboard.JWSTStateText.Text', 'Time speed: 30 seconds/second')", + "openspace.time.interpolateDeltaTime(-1800)" .. + "openspace.setPropertyValueSingle('Dashboard.JWSTStateText.Text', 'Time speed: -30 minutes/second')" + ) + + -- tension sun shield membranes + openspace.scriptScheduler.loadScheduledScript( + "2018 OCT 07 12:15:17", + "openspace.time.interpolateDeltaTime(60)" .. + "openspace.setPropertyValueSingle('Dashboard.JWSTStateText.Text', 'Time speed: 1 minute/second')", + "openspace.time.interpolateDeltaTime(-30)" .. + "openspace.setPropertyValueSingle('Dashboard.JWSTStateText.Text', 'Time speed: -30 seconds/second')" + ) + + -- membrane tension complete + openspace.scriptScheduler.loadScheduledScript( + "2018 OCT 07 12:26:03", + "openspace.time.interpolateDeltaTime(7200)" .. + "openspace.setPropertyValueSingle('Dashboard.JWSTStateText.Text', 'Time speed: 2 hours/second')", + "openspace.time.interpolateDeltaTime(-60)" .. + "openspace.setPropertyValueSingle('Dashboard.JWSTStateText.Text', 'Time speed: -1 minute/second')" + ) + + -- membranes separate + openspace.scriptScheduler.loadScheduledScript( + "2018 OCT 08 02:42:52", + "openspace.time.interpolateDeltaTime(3600)" .. + "openspace.setPropertyValueSingle('Dashboard.JWSTStateText.Text', 'Time speed: 1 hour/second')", + "openspace.time.interpolateDeltaTime(-7200)" .. + "openspace.setPropertyValueSingle('Dashboard.JWSTStateText.Text', 'Time speed: -2 hours/second')" + ) + + -- secondary mirror deploy + openspace.scriptScheduler.loadScheduledScript( + "2018 OCT 08 14:06:03", + "openspace.time.interpolateDeltaTime(18000)" .. + "openspace.setPropertyValueSingle('Dashboard.JWSTStateText.Text', 'Time speed: 5 hours/second')", + "openspace.time.interpolateDeltaTime(-3600)" .. + "openspace.setPropertyValueSingle('Dashboard.JWSTStateText.Text', 'Time speed: -1 hour/second')" + ) + + -- secondary mirror complete + openspace.scriptScheduler.loadScheduledScript( + "2018 OCT 13 00:39:03", + "openspace.time.interpolateDeltaTime(1200)" .. + "openspace.setPropertyValueSingle('Dashboard.JWSTStateText.Text', 'Time speed: 20 minutes/second')", + "openspace.time.interpolateDeltaTime(-18000)" .. + "openspace.setPropertyValueSingle('Dashboard.JWSTStateText.Text', 'Time speed: -5 hours/second')" + ) + + -- aft radiator deploy + openspace.scriptScheduler.loadScheduledScript( + "2018 OCT 13 02:26:51", + "openspace.time.interpolateDeltaTime(1800)" .. + "openspace.setPropertyValueSingle('Dashboard.JWSTStateText.Text', 'Time speed: 30 minutes/second')", + "openspace.time.interpolateDeltaTime(-1200)" .. + "openspace.setPropertyValueSingle('Dashboard.JWSTStateText.Text', 'Time speed: -20 minutes/second')" + ) + + -- aft radiator complete, forward + openspace.scriptScheduler.loadScheduledScript( + "2018 OCT 13 06:11:03", + "openspace.time.interpolateDeltaTime(7200)" .. + "openspace.setPropertyValueSingle('Dashboard.JWSTStateText.Text', 'Time speed: 2 hours/second')" + ) + -- aft radiator complete, backward + openspace.scriptScheduler.loadScheduledScript( + "2018 OCT 13 07:11:03", -- 1h pre delay so time to interpolate + "", + "openspace.time.interpolateDeltaTime(-1800)" .. + "openspace.setPropertyValueSingle('Dashboard.JWSTStateText.Text', 'Time speed: -30 minutes/second')" + ) + + -- rt cord fold wings deploy + openspace.scriptScheduler.loadScheduledScript( + "2018 OCT 13 23:36:03", + "openspace.time.interpolateDeltaTime(7200)" .. + "openspace.setPropertyValueSingle('Dashboard.JWSTStateText.Text', 'Time speed: 2 hours/second')", + "openspace.time.interpolateDeltaTime(-7200)" .. + "openspace.setPropertyValueSingle('Dashboard.JWSTStateText.Text', 'Time speed: -2 hours/second')" + ) + + -- rt cord fold wings complete + openspace.scriptScheduler.loadScheduledScript( + "2018 OCT 15 02:46:51", + "openspace.time.interpolateDeltaTime(7200)" .. + "openspace.setPropertyValueSingle('Dashboard.JWSTStateText.Text', 'Time speed: 2 hours/second')", + "openspace.time.interpolateDeltaTime(-7200)" .. + "openspace.setPropertyValueSingle('Dashboard.JWSTStateText.Text', 'Time speed: -2 hours/second')" + ) + + -- lft cord fold wings deploy + openspace.scriptScheduler.loadScheduledScript( + "2018 OCT 15 13:06:03", + "openspace.time.interpolateDeltaTime(7200)" .. + "openspace.setPropertyValueSingle('Dashboard.JWSTStateText.Text', 'Time speed: 2 hours/second')", + "openspace.time.interpolateDeltaTime(-7200)" .. + "openspace.setPropertyValueSingle('Dashboard.JWSTStateText.Text', 'Time speed: -2 hours/second')" + ) + + -- lft cord fold wings complete + openspace.scriptScheduler.loadScheduledScript( + "2018 OCT 16 09:06:03", + "openspace.time.interpolateDeltaTime(1)" .. + "openspace.setPropertyValueSingle('Dashboard.JWSTStateText.Text', '')" .. + "openspace.setPropertyValueSingle('Scene.Earth.Renderable.Layers.NightLayers.Earth_at_Night_2012.Settings.Gamma', 1.0)" .. + "openspace.setPropertyValueSingle('Scene.EarthAtmosphere.Renderable.Enabled', true)", + "openspace.time.interpolateDeltaTime(-7200)" .. + "openspace.setPropertyValueSingle('Dashboard.JWSTStateText.Text', 'Time speed: -2 hours/second')" .. + "openspace.setPropertyValueSingle('Scene.Earth.Renderable.Layers.NightLayers.Earth_at_Night_2012.Settings.Gamma', 0.7)" .. + "openspace.setPropertyValueSingle('Scene.EarthAtmosphere.Renderable.Enabled', false)" + ) + + openspace.scriptScheduler.loadScheduledScript( + "2018 OCT 16 09:06:05", + "openspace.scriptScheduler.clear(0)" + ) +]] + +local playForwards = { + Identifier = "jwst.play.forwards", + Name = "Play JWST from start", + Command = [[ + openspace.scriptScheduler.clear(0); + openspace.setPropertyValueSingle('Dashboard.JWSTStateText.Text', ''); + openspace.time.setDeltaTime(1); + openspace.time.setTime('2018 OCT 01 14:06:03'); + ]] .. timelapse .. [[ + ]], + Documentation = "Jump to the JWST launch time and play the timelapse of deployment forward", + GuiPath = "/JWST", + IsLocal = false +} + +local playBackwards = { + Identifier = "jwst.play.backwards", + Name = "Play JWST from end", + Command = [[ + openspace.scriptScheduler.clear(0); + openspace.setPropertyValueSingle('Dashboard.JWSTStateText.Text', ''); + openspace.time.setDeltaTime(-1); + openspace.time.setTime('2018 OCT 16 09:06:04'); + ]] .. timelapse .. [[ + ]], + Documentation = "Jump to the end of JWST deployment time and play the timelapse of deployment in reverse", + GuiPath = "/JWST", + IsLocal = false +} + +local clearPlay = { + Identifier = "jwst.play.clear", + Name = "Clear JWST timelapse", + Command = [[ + openspace.scriptScheduler.clear(0); + openspace.setPropertyValueSingle('Dashboard.JWSTStateText.Text', ''); + openspace.setPropertyValueSingle('Scene.Earth.Renderable.Layers.NightLayers.Earth_at_Night_2012.Settings.Gamma', 1.0) + openspace.setPropertyValueSingle('Scene.EarthAtmosphere.Renderable.Enabled', true) + local deltaTime = openspace.time.deltaTime(); + if deltaTime > 0 then + openspace.time.setDeltaTime(1); + else + openspace.time.setDeltaTime(-1); + end + ]], + Documentation = "Set delta time back to realtime and clear the JWST deployment timelapse", + GuiPath = "/JWST", + IsLocal = false +} + +local togglePlayDirection = { + Identifier = "jwst.toggle.direction", + Name = "Toggle forwards/ backwards", + Command = [[ + -- Flip deltatime + local deltaTime = openspace.time.deltaTime(); + openspace.time.setDeltaTime(-deltaTime); + + -- Update the dashboard text + local text = openspace.getPropertyValue('Dashboard.JWSTStateText.Text'); + if(string.len(text) > 14) then + local newText = '' + if(text:sub(13, 13) == '-') then + newText = text:sub(1,12) .. text:sub(14) + else + newText = text:sub(1,12) .. '-' .. text:sub(13) + end + openspace.setPropertyValueSingle('Dashboard.JWSTStateText.Text', tostring(newText)); + else + openspace.setPropertyValueSingle('Dashboard.JWSTStateText.Text', ''); + end + ]], + Documentation = "Toggle deployment timelapse direction between forwards and backwards", + GuiPath = "/JWST", + IsLocal = false +} + +asset.onInitialize(function() + openspace.action.registerAction(playForwards) + openspace.action.registerAction(playBackwards) + openspace.action.registerAction(clearPlay) + openspace.action.registerAction(togglePlayDirection) +end) + +asset.onDeinitialize(function () + openspace.scriptScheduler.clear() + + openspace.action.removeAction(playForwards.Identifier) + openspace.action.removeAction(playBackwards.Identifier) + openspace.action.removeAction(clearPlay.Identifier) + openspace.action.removeAction(togglePlayDirection.Identifier) +end) + +assetHelper.registerDashboardItems(asset, { + { + Type = "DashboardItemText", + Identifier = "JWSTStateText", + GuiName = "JWST State Dashboard Text", + Text = "" + } +}) + +asset.meta = { + Name = "James Webb Space Telescope Timelapse", + Version = "1.0", + Description = [[ + Scripts that are scheduled to alter the speed of the simulation time so the deployment + of the James Webb Space Telescope looks smoother. + ]], + Author = "OpenSpace Team", + URL = "http://openspaceproject.com", + License = "MIT license" +} diff --git a/data/assets/scene/solarsystem/missions/jwst/trail.asset b/data/assets/scene/solarsystem/missions/jwst/trail.asset new file mode 100644 index 0000000000..9a34011434 --- /dev/null +++ b/data/assets/scene/solarsystem/missions/jwst/trail.asset @@ -0,0 +1,134 @@ +local assetHelper = asset.require('util/asset_helper') +local transforms = asset.require('scene/solarsystem/planets/earth/lagrange_points/L2') +local earthTransforms = asset.require('scene/solarsystem/planets/earth/transforms') +local sunTransforms = asset.require('scene/solarsystem/sun/transforms') +asset.require("spice/base") + +local horizons = asset.syncedResource({ + Name = "JWST Horizons", + Type = "HttpSynchronization", + Identifier = "jwst_horizons", + Version = 2 +}) + +local kernels = asset.syncedResource({ + Name = "JWST Kernel", + Type = "HttpSynchronization", + Identifier = "jwst_kernels", + Version = 1 +}) + +-- (malej 2021-10-04) In general, there is no trajectery data of JWST for the scheduled +-- launch in December 2021, no horizons and no SPICE. Instead data from the 2018 launch +-- is used, old data from an old launch time that never happened because of delays. +-- If we can get our hands on the 2021 launch data, the jwst assets will be updated. + +-- Trail of JWST relative the Earth for the first month after launch +-- Makes histroy of trail to stay at Earth, that a trail relative to L2 won't +local JWSTTrailLaunch = { + Identifier = "JWSTTrailLaunch", + Parent = earthTransforms.EarthCenter.Identifier, + TimeFrame = { + Type = "TimeFrameInterval", + Start = "2018 OCT 01 14:06:03", + End = "2018 NOV 01" + }, + Renderable = { + Type = "RenderableTrailTrajectory", + Translation = { + Type = "HorizonsTranslation", + HorizonsTextFile = horizons .. "/horizons_jwst_launch.dat", + }, + Color = { 0.9, 0.9, 0.0 }, + StartTime = "2018 OCT 01 14:06:00", + EndTime = "2018 NOV 01", + SampleInterval = 60 + }, + GUI = { + Name = "JWST Launch Trail", + Path = "/Solar System/Missions/JWST/Trails", + Description = [[ + James Webb Space Telescope Launch Trail relative to Earth based on Horizons data from the + 2018 launch. + ]], + } +} + +-- Trail of JWST relative to L2 after first month to reach L2 +-- Gives a better trail history of the orbit around L2 than if it was relative to Earth +local JWSTTrailOrbit = { + Identifier = "JWSTTrailOrbit", + Parent = transforms.L2.Identifier, + TimeFrame = { + Type = "TimeFrameInterval", + Start = "2018 NOV 01 00:00:00", + End = "2024 OCT 01" + }, + Renderable = { + Type = "RenderableTrailOrbit", + Translation = { + Type = "HorizonsTranslation", + HorizonsTextFile = horizons .. "/horizons_jwst_orbit.dat", + }, + Color = { 0.9, 0.9, 0.0 }, + Period = 182.621099, -- About 6 months + Resolution = 4383 -- About a sample rate of once per hour + }, + GUI = { + Name = "JWST Orbit Trail", + Path = "/Solar System/Missions/JWST/Trails", + Description = [[ + James Webb Space Telescope Orbit Trail relative to L2 based on Horizons data from the + 2018 launch. + ]], + } +} + +-- JPL Horizons doesn't have data of JWST relative to the Sun, +-- instead a SPICE kernel with data from 2020 to 2024 is used. +-- However, this SPICE kernel is (somehow) based on the horizons +-- data of the 2018 launch anyway. Which mean that this kernel doesn't +-- have any data of the launch, just the orbit. +local JWSTSunTrail = { + Identifier = "JWSTSunTrail", + Parent = sunTransforms.SolarSystemBarycenter.Identifier, + Renderable = { + Enabled = false, + Type = "RenderableTrailOrbit", + Translation = { + Type = "SpiceTranslation", + Target = "JWST", + Observer = "SSB", + Kernels = kernels .. "/jwst_horizons_20200101_20240101_v01.bsp" + }, + Color = { 0.0, 0.9, 0.9 }, + Period = 365.242, + Resolution = 1000 + }, + GUI = { + Name = "JWST Sun Trail", + Path = "/Solar System/Missions/JWST/Trails", + Description = [[ + James Webb Space Telescope Trail relative to the Sun based on Horizons data from the + 2018 launch. + ]], + } +} + +assetHelper.registerSceneGraphNodesAndExport(asset, { + JWSTTrailLaunch, + JWSTTrailOrbit, + JWSTSunTrail +}) + +asset.meta = { + Name = "James Webb Space Telescope Trails", + Version = "1.0", + Description = [[ + Trail of James Webb Space Telescope in respect to Earth, L2 and the Sun + ]], + Author = "OpenSpace Team", + URL = "http://openspaceproject.com", + License = "MIT license", + Identifiers = {"JWSTTrailLaunch", "JWSTTrailOrbit", "JWSTSunTrail"} +} diff --git a/data/assets/scene/solarsystem/missions/jwst/transforms.asset b/data/assets/scene/solarsystem/missions/jwst/transforms.asset new file mode 100644 index 0000000000..53b55f8132 --- /dev/null +++ b/data/assets/scene/solarsystem/missions/jwst/transforms.asset @@ -0,0 +1,94 @@ +local assetHelper = asset.require('util/asset_helper') +local earthTransforms = asset.require('scene/solarsystem/planets/earth/transforms') +local sunTransforms = asset.require('scene/solarsystem/sun/transforms') +asset.require('spice/base') + +local horizons = asset.syncedResource({ + Name = "JWST Horizons", + Type = "HttpSynchronization", + Identifier = "jwst_horizons", + Version = 2 +}) + +local JWSTPosition = { + Identifier = "JWSTPosition", + Parent = earthTransforms.EarthCenter.Identifier, + Transform = { + Translation = { + Type = "TimelineTranslation", + ShouldInterpolate = false, + Keyframes = { + ['2018 OCT 01 14:06:03'] = { + Type = "HorizonsTranslation", + HorizonsTextFile = horizons .. "/horizons_jwst_launch.dat", + }, + ['2018 NOV 01 00:00:00'] = { + Type = "HorizonsTranslation", + HorizonsTextFile = horizons .. "/horizons_jwst_orbit.dat", + } + } + }, + }, + GUI = { + Name = "JWST Position", + Path = "/Solar System/Missions/JWST", + Hidden = true, + Description = [[ + James Webb Space Telescope Position relative to Earth based on Horizons data from the + 2018 launch. + ]], + } +} + +local JWSTRotation = { + Identifier = "JWSTRotation", + Parent = JWSTPosition.Identifier, + Transform = { + Rotation = { + Type = "FixedRotation", + Attached = "JWSTRotation", + XAxis = { 1, 0, 0 }, + XAxisOrthogonal = true, + YAxisInvert = true, + YAxis = sunTransforms.SolarSystemBarycenter.Identifier + } + }, + GUI = { + Name = "JWST Rotation", + Path = "/Solar System/Missions/JWST", + Hidden = true, + Description = [[ + James Webb Space Telescope Rotation so the sunshield always faces the Sun. + ]], + } +} + +-- Reparent the JWSTPosition node when the data changes at 01 Nov 2018 +asset.onInitialize(function() + openspace.scriptScheduler.loadScheduledScript( + "2018 NOV 01 00:00:00", + "openspace.setParent('JWSTPosition', 'L2')", + "openspace.setParent('JWSTPosition', 'EarthCenter')", + "", + 1 -- Not default group, never clear this script + ) +end) + +assetHelper.registerSceneGraphNodesAndExport(asset, { + JWSTPosition, + JWSTRotation +}) + +asset.meta = { + Name = "James Webb Space Telescope Transforms", + Version = "1.0", + Description = [[ + JWST transforms: JWST position relative to Earth using horizons data from the planned + launch of 2018. JWST rotation, a fixed rotation so sunshield always points toward + the Sun. + ]], + Author = "OpenSpace Team", + URL = "http://openspaceproject.com", + License = "MIT license", + Identifiers = {"JWSTPosition", "JWSTRotation"} +} diff --git a/data/assets/scene/solarsystem/missions/osirisrex/bennu.asset b/data/assets/scene/solarsystem/missions/osirisrex/bennu.asset index 5ebbea22e2..c6f7811eec 100644 --- a/data/assets/scene/solarsystem/missions/osirisrex/bennu.asset +++ b/data/assets/scene/solarsystem/missions/osirisrex/bennu.asset @@ -1,7 +1,13 @@ local assetHelper = asset.require('util/asset_helper') local transforms = asset.require('./transforms') local sunTransforms = asset.require('scene/solarsystem/sun/transforms') -local models = asset.require('./models').models + +local models = asset.syncedResource({ + Name = "Bennu Models", + Type = "HttpSynchronization", + Identifier = "bennu_models", + Version = 2 +}) local BENNU_BODY = "2101955" diff --git a/data/assets/scene/solarsystem/missions/osirisrex/bennu_projection.asset b/data/assets/scene/solarsystem/missions/osirisrex/bennu_projection.asset index afcfb529a7..9a81496a37 100644 --- a/data/assets/scene/solarsystem/missions/osirisrex/bennu_projection.asset +++ b/data/assets/scene/solarsystem/missions/osirisrex/bennu_projection.asset @@ -2,7 +2,12 @@ local assetHelper = asset.require('util/asset_helper') local transforms = asset.require('./transforms') local sunTransforms = asset.require('scene/solarsystem/sun/transforms') -local models = asset.require('./models').models +local models = asset.syncedResource({ + Name = "Bennu Models", + Type = "HttpSynchronization", + Identifier = "bennu_models", + Version = 2 +}) local BENNU_BODY = "2101955" @@ -34,7 +39,7 @@ local BennuProjection = { Enabled = true, Type = "RenderableModelProjection", Body = BENNU_BODY, - GeometryFile = models .. "/BennuTextured.obj", + GeometryFile = models .. "/Bennu_v20_200k_an.obj", Projection = { Sequence = { images, imagesA }, SequenceType = "image-sequence", diff --git a/data/assets/scene/solarsystem/missions/osirisrex/models.asset b/data/assets/scene/solarsystem/missions/osirisrex/models.asset deleted file mode 100644 index cdd95678ff..0000000000 --- a/data/assets/scene/solarsystem/missions/osirisrex/models.asset +++ /dev/null @@ -1,8 +0,0 @@ -local models = asset.syncedResource({ - Name = "Bennu Models", - Type = "HttpSynchronization", - Identifier = "bennu_models", - Version = 2 -}) - -asset.export('models', models) diff --git a/data/assets/scene/solarsystem/missions/pioneer/pioneermodel.asset b/data/assets/scene/solarsystem/missions/pioneer/pioneermodel.asset index 2663f7fb32..f414337170 100644 --- a/data/assets/scene/solarsystem/missions/pioneer/pioneermodel.asset +++ b/data/assets/scene/solarsystem/missions/pioneer/pioneermodel.asset @@ -5,16 +5,12 @@ local modelFolder = asset.syncedResource({ Name = "Pioneer 10/11 Models", Type = "HttpSynchronization", Identifier = "pioneer_10_11_model", - Version = 2 + Version = 3 }) local ModelRenderable = { Type = "RenderableModel", - Geometry = {{ - Type = "MultiModelGeometry", - GeometryFile = modelFolder .. "/Pioneer.obj", - ColorTexture = modelFolder .. "/gray.png" - }}, + GeometryFile = modelFolder .. "/pioneer.fbx", LightSources = assetHelper.getDefaultLightSources( sunTransforms.SolarSystemBarycenter.Identifier ) diff --git a/data/assets/scene/solarsystem/missions/voyager/model.asset b/data/assets/scene/solarsystem/missions/voyager/model.asset deleted file mode 100644 index c72367fd35..0000000000 --- a/data/assets/scene/solarsystem/missions/voyager/model.asset +++ /dev/null @@ -1,8 +0,0 @@ -local models = asset.syncedResource({ - Name = "Voyager Model", - Type = "HttpSynchronization", - Identifier = "voyager_model", - Version = 1 -}) - -asset.export('modelFolder', models) diff --git a/data/assets/scene/solarsystem/missions/voyager/voyager1.asset b/data/assets/scene/solarsystem/missions/voyager/voyager1.asset index a0d0d4ae22..6021db412f 100644 --- a/data/assets/scene/solarsystem/missions/voyager/voyager1.asset +++ b/data/assets/scene/solarsystem/missions/voyager/voyager1.asset @@ -1,6 +1,12 @@ local assetHelper = asset.require('util/asset_helper') local sunTransforms = asset.require('scene/solarsystem/sun/transforms') -local models = asset.require("./model" ).modelFolder; + +local models = asset.syncedResource({ + Name = "Voyager Model", + Type = "HttpSynchronization", + Identifier = "voyager_model", + Version = 1 +}) local kernels = asset.syncedResource({ Name = "Voyager 1 Kernels", diff --git a/data/assets/scene/solarsystem/missions/voyager/voyager2.asset b/data/assets/scene/solarsystem/missions/voyager/voyager2.asset index d2e7e80a17..87d32f852b 100644 --- a/data/assets/scene/solarsystem/missions/voyager/voyager2.asset +++ b/data/assets/scene/solarsystem/missions/voyager/voyager2.asset @@ -1,8 +1,14 @@ local assetHelper = asset.require('util/asset_helper') local sunTransforms = asset.require('scene/solarsystem/sun/transforms') -local models = asset.require("./model" ).modelFolder; +local models = asset.syncedResource({ + Name = "Voyager Model", + Type = "HttpSynchronization", + Identifier = "voyager_model", + Version = 1 +}) + local kernels = asset.syncedResource({ Name = "Voyager 2 Kernels", Type = "HttpSynchronization", diff --git a/data/assets/scene/solarsystem/planets/earth/earth.asset b/data/assets/scene/solarsystem/planets/earth/earth.asset index ef29f8c1f3..501140a5b5 100644 --- a/data/assets/scene/solarsystem/planets/earth/earth.asset +++ b/data/assets/scene/solarsystem/planets/earth/earth.asset @@ -1,6 +1,12 @@ local transforms = asset.require('./transforms') local assetHelper = asset.require('util/asset_helper') -local labelsPath = asset.require('./earth_globelabels').LabelsPath + +local labelsPath = asset.syncedResource({ + Name = "Earth Labels", + Type = "HttpSynchronization", + Identifier = "earth_labels", + Version = 1 +}) -- local earthEllipsoid = { 6378137.0, 6378137.0, 6356752.314245 } local earthEllipsoid = { 6378137.0, 6378137.0, 6378137.0 } diff --git a/data/assets/scene/solarsystem/planets/earth/earth_globelabels.asset b/data/assets/scene/solarsystem/planets/earth/earth_globelabels.asset deleted file mode 100644 index f454309a56..0000000000 --- a/data/assets/scene/solarsystem/planets/earth/earth_globelabels.asset +++ /dev/null @@ -1,7 +0,0 @@ -local LabelsPath = asset.syncedResource({ - Name = "Earth Labels", - Type = "HttpSynchronization", - Identifier = "earth_labels", - Version = 1 -}) -asset.export("LabelsPath", LabelsPath) diff --git a/data/assets/scene/solarsystem/planets/earth/earth_textures.asset b/data/assets/scene/solarsystem/planets/earth/earth_textures.asset deleted file mode 100644 index 73448a46b7..0000000000 --- a/data/assets/scene/solarsystem/planets/earth/earth_textures.asset +++ /dev/null @@ -1,7 +0,0 @@ -local TexturesPath = asset.syncedResource({ - Name = "Earth Textures", - Type = "HttpSynchronization", - Identifier = "earth_textures", - Version = 2 -}) -asset.export("TexturesPath", TexturesPath) diff --git a/data/assets/scene/solarsystem/planets/earth/kernels/GSM.ti b/data/assets/scene/solarsystem/planets/earth/kernels/GSM.ti new file mode 100644 index 0000000000..360c3274f3 --- /dev/null +++ b/data/assets/scene/solarsystem/planets/earth/kernels/GSM.ti @@ -0,0 +1,33 @@ +Geocentric Solar Magnetospheric (GSM) frame: +Used by the BATSRUS model +This Kernel's ID is not a valid ID! + + +X is parallel to the geometric earth-sun position vector. + + +Z axis is normalized component of north centered geomagnetic dipole + vector orthogonal to GSM +X axis. + + +Y completes the right-handed frame. + +\begindata + +FRAME_GSM = 13371333 +FRAME_13371333_NAME = 'GSM' +FRAME_13371333_CLASS = 5 +FRAME_13371333_CLASS_ID = 13371333 +FRAME_13371333_CENTER = 399 +FRAME_13371333_RELATIVE = 'GALACTIC' +FRAME_13371333_DEF_STYLE = 'PARAMETERIZED' +FRAME_13371333_FAMILY = 'TWO-VECTOR' +FRAME_13371333_PRI_AXIS = 'X' +FRAME_13371333_PRI_VECTOR_DEF = 'OBSERVER_TARGET_POSITION' +FRAME_13371333_PRI_OBSERVER = 'EARTH' +FRAME_13371333_PRI_TARGET = 'SUN' +FRAME_13371333_PRI_ABCORR = 'NONE' +FRAME_13371333_SEC_AXIS = 'Z' +FRAME_13371333_SEC_VECTOR_DEF = 'CONSTANT' +FRAME_13371333_SEC_FRAME = 'ECLIPJ2000' +FRAME_13371333_SEC_SPEC = 'LATITUDINAL' +FRAME_13371333_SEC_UNITS = 'DEGREES' +FRAME_13371333_SEC_LONGITUDE = 288.43 +FRAME_13371333_SEC_LATITUDE = 79.54 diff --git a/data/assets/scene/solarsystem/planets/earth/lagrange_points/L1.asset b/data/assets/scene/solarsystem/planets/earth/lagrange_points/L1.asset index 3d9905bf89..94822c0af6 100644 --- a/data/assets/scene/solarsystem/planets/earth/lagrange_points/L1.asset +++ b/data/assets/scene/solarsystem/planets/earth/lagrange_points/L1.asset @@ -1,14 +1,25 @@ local assetHelper = asset.require('util/asset_helper') local transforms = asset.require('scene/solarsystem/sun/transforms') -local circle = asset.require('util/circle').circle -local kernels = asset.require('scene/solarsystem/planets/earth/lagrange_points/lagrange_kernels').kernels asset.require('spice/base') +local circle = asset.syncedResource({ + Name = "Circle", + Type = "HttpSynchronization", + Identifier = "circle_image", + Version = 1 +}) + +local kernels = asset.syncedResource({ + Name = "Lagrange Kernels", + Type = "HttpSynchronization", + Identifier = "earth_lagrange_kernels", + Version = 1 +}) + local L1 = { Identifier = "L1", Parent = transforms.SolarSystemBarycenter.Identifier, Renderable = { - Enabled = false, Type = "RenderablePlaneImageLocal", RenderableType = "Opaque", Billboard = true, @@ -35,7 +46,6 @@ local L1Label = { Identifier = "L1Label", Parent = L1.Identifier, Renderable = { - Enabled = false, Type = "RenderableLabels", Text = "L1", FontSize = 20, diff --git a/data/assets/scene/solarsystem/planets/earth/lagrange_points/L2.asset b/data/assets/scene/solarsystem/planets/earth/lagrange_points/L2.asset index 0d3741f2de..645def7014 100644 --- a/data/assets/scene/solarsystem/planets/earth/lagrange_points/L2.asset +++ b/data/assets/scene/solarsystem/planets/earth/lagrange_points/L2.asset @@ -1,9 +1,21 @@ local assetHelper = asset.require('util/asset_helper') local transforms = asset.require('scene/solarsystem/sun/transforms') -local circle = asset.require('util/circle').circle -local kernels = asset.require('scene/solarsystem/planets/earth/lagrange_points/lagrange_kernels').kernels asset.require('spice/base') +local circle = asset.syncedResource({ + Name = "Circle", + Type = "HttpSynchronization", + Identifier = "circle_image", + Version = 1 +}) + +local kernels = asset.syncedResource({ + Name = "Lagrange Kernels", + Type = "HttpSynchronization", + Identifier = "earth_lagrange_kernels", + Version = 1 +}) + local L2Small = { Identifier = "L2Small", Parent = transforms.SolarSystemBarycenter.Identifier, @@ -34,7 +46,6 @@ local L2 = { Identifier = "L2", Parent = transforms.SolarSystemBarycenter.Identifier, Renderable = { - Enabled = false, Type = "RenderablePlaneImageLocal", RenderableType = "Opaque", Billboard = true, @@ -61,7 +72,6 @@ local L2SmallLabel = { Identifier = "L2SmallLabel", Parent = L2.Identifier, Renderable = { - Enabled = true, Type = "RenderableLabels", Text = "L2", FontSize = 20.0, @@ -83,7 +93,6 @@ local L2Label = { Identifier = "L2Label", Parent = L2.Identifier, Renderable = { - Enabled = false, Type = "RenderableLabels", Text = "L2", FontSize = 20, diff --git a/data/assets/scene/solarsystem/planets/earth/lagrange_points/L4.asset b/data/assets/scene/solarsystem/planets/earth/lagrange_points/L4.asset index 5ed34bcb8a..0b5faad71e 100644 --- a/data/assets/scene/solarsystem/planets/earth/lagrange_points/L4.asset +++ b/data/assets/scene/solarsystem/planets/earth/lagrange_points/L4.asset @@ -1,14 +1,25 @@ local assetHelper = asset.require('util/asset_helper') local transforms = asset.require('scene/solarsystem/sun/transforms') -local circle = asset.require('util/circle').circle -local kernels = asset.require('scene/solarsystem/planets/earth/lagrange_points/lagrange_kernels').kernels asset.require('spice/base') +local circle = asset.syncedResource({ + Name = "Circle", + Type = "HttpSynchronization", + Identifier = "circle_image", + Version = 1 +}) + +local kernels = asset.syncedResource({ + Name = "Lagrange Kernels", + Type = "HttpSynchronization", + Identifier = "earth_lagrange_kernels", + Version = 1 +}) + local L4 = { Identifier = "L4", Parent = transforms.SolarSystemBarycenter.Identifier, Renderable = { - Enabled = false, Type = "RenderablePlaneImageLocal", RenderableType = "Opaque", Billboard = true, @@ -35,7 +46,6 @@ local L4Label = { Identifier = "L4Label", Parent = L4.Identifier, Renderable = { - Enabled = false, Type = "RenderableLabels", Text = "L4", FontSize = 20, diff --git a/data/assets/scene/solarsystem/planets/earth/lagrange_points/L5.asset b/data/assets/scene/solarsystem/planets/earth/lagrange_points/L5.asset index 1fffca80db..ed3bb40514 100644 --- a/data/assets/scene/solarsystem/planets/earth/lagrange_points/L5.asset +++ b/data/assets/scene/solarsystem/planets/earth/lagrange_points/L5.asset @@ -1,14 +1,25 @@ local assetHelper = asset.require('util/asset_helper') local transforms = asset.require('scene/solarsystem/sun/transforms') -local circle = asset.require('util/circle').circle -local kernels = asset.require('scene/solarsystem/planets/earth/lagrange_points/lagrange_kernels').kernels asset.require('spice/base') +local circle = asset.syncedResource({ + Name = "Circle", + Type = "HttpSynchronization", + Identifier = "circle_image", + Version = 1 +}) + +local kernels = asset.syncedResource({ + Name = "Lagrange Kernels", + Type = "HttpSynchronization", + Identifier = "earth_lagrange_kernels", + Version = 1 +}) + local L5 = { Identifier = "L5", Parent = transforms.SolarSystemBarycenter.Identifier, Renderable = { - Enabled = false, Type = "RenderablePlaneImageLocal", RenderableType = "Opaque", Billboard = true, @@ -35,7 +46,6 @@ local L5Label = { Identifier = "L5Label", Parent = L5.Identifier, Renderable = { - Enabled = false, Type = "RenderableLabels", Text = "L5", FontSize = 20, diff --git a/data/assets/scene/solarsystem/planets/earth/lagrange_points/lagrange_kernels.asset b/data/assets/scene/solarsystem/planets/earth/lagrange_points/lagrange_kernels.asset deleted file mode 100644 index b78370a3a8..0000000000 --- a/data/assets/scene/solarsystem/planets/earth/lagrange_points/lagrange_kernels.asset +++ /dev/null @@ -1,8 +0,0 @@ -local kernels = asset.syncedResource({ - Name = "Lagrange Kernels", - Type = "HttpSynchronization", - Identifier = "earth_lagrange_kernels", - Version = 1 -}) - -asset.export('kernels', kernels) diff --git a/data/assets/scene/solarsystem/planets/earth/layers/colorlayers/fallbacks/blue_marble.asset b/data/assets/scene/solarsystem/planets/earth/layers/colorlayers/fallbacks/blue_marble.asset index ef07346d05..cded8f8ea0 100644 --- a/data/assets/scene/solarsystem/planets/earth/layers/colorlayers/fallbacks/blue_marble.asset +++ b/data/assets/scene/solarsystem/planets/earth/layers/colorlayers/fallbacks/blue_marble.asset @@ -1,6 +1,12 @@ -local texturesPath = asset.require("./../../../earth_textures").TexturesPath local globeIdentifier = asset.require("./../../../earth").Earth.Identifier +local texturesPath = asset.syncedResource({ + Name = "Earth Textures", + Type = "HttpSynchronization", + Identifier = "earth_textures", + Version = 2 +}) + local layer = { Identifier = "Blue_Marble", Name = "Blue Marble", diff --git a/data/assets/scene/solarsystem/planets/earth/layers/colorlayers/ghrsst_l4_mur_sea_surface_temperature_temporal.asset b/data/assets/scene/solarsystem/planets/earth/layers/colorlayers/ghrsst_l4_mur_sea_surface_temperature_temporal.asset index cb8055135c..e0ba5eba41 100644 --- a/data/assets/scene/solarsystem/planets/earth/layers/colorlayers/ghrsst_l4_mur_sea_surface_temperature_temporal.asset +++ b/data/assets/scene/solarsystem/planets/earth/layers/colorlayers/ghrsst_l4_mur_sea_surface_temperature_temporal.asset @@ -10,7 +10,7 @@ local layer = { "Yesterday", "1d", "1km", - "jpg" + "png" ), Description = [[ Temporal coverage: 01 June 2002 - Present. The imagery resolution is 1 km, and the temporal resolution is daily.]] diff --git a/data/assets/scene/solarsystem/planets/earth/layers/heightlayers/fallbacks/blue_marble_height.asset b/data/assets/scene/solarsystem/planets/earth/layers/heightlayers/fallbacks/blue_marble_height.asset index 116faf265f..e45c0fe506 100644 --- a/data/assets/scene/solarsystem/planets/earth/layers/heightlayers/fallbacks/blue_marble_height.asset +++ b/data/assets/scene/solarsystem/planets/earth/layers/heightlayers/fallbacks/blue_marble_height.asset @@ -1,4 +1,9 @@ -local texturesPath = asset.require("./../../../earth_textures").TexturesPath +local texturesPath = asset.syncedResource({ + Name = "Earth Textures", + Type = "HttpSynchronization", + Identifier = "earth_textures", + Version = 2 +}) local layer = { Name = "Earth Bluemarble Height", diff --git a/data/assets/scene/solarsystem/planets/earth/layers/nightlayers/fallbacks/earth_night_texture.asset b/data/assets/scene/solarsystem/planets/earth/layers/nightlayers/fallbacks/earth_night_texture.asset index 8ceae0261f..1779e8a5b6 100644 --- a/data/assets/scene/solarsystem/planets/earth/layers/nightlayers/fallbacks/earth_night_texture.asset +++ b/data/assets/scene/solarsystem/planets/earth/layers/nightlayers/fallbacks/earth_night_texture.asset @@ -1,4 +1,9 @@ -local texturesPath = asset.require("./../../../earth_textures").TexturesPath +local texturesPath = asset.syncedResource({ + Name = "Earth Textures", + Type = "HttpSynchronization", + Identifier = "earth_textures", + Version = 2 +}) local layer = { Identifier = "Earth_Night_Texture", diff --git a/data/assets/scene/solarsystem/planets/earth/magnetosphere/CMR-illuminance2.txt b/data/assets/scene/solarsystem/planets/earth/magnetosphere/CMR-illuminance2.txt new file mode 100644 index 0000000000..2ed4bff17e --- /dev/null +++ b/data/assets/scene/solarsystem/planets/earth/magnetosphere/CMR-illuminance2.txt @@ -0,0 +1,14 @@ +width 10 +lower 0.0 +upper 1.0 + +mappingkey 0.0 60 38 164 255 +mappingkey 0.083 106 43 167 255 +mappingkey 0.166 173 54 110 255 +mappingkey 0.332 253 64 40 255 +mappingkey 0.415 234 117 6 255 +mappingkey 0.498 230 169 16 255 +mappingkey 0.664 236 236 159 255 +mappingkey 0.830 251 251 235 255 +mappingkey 0.915 255 255 255 255 +mappingkey 1.0 255 255 255 255 \ No newline at end of file diff --git a/data/assets/scene/solarsystem/planets/earth/magnetosphere/magnetosphere.asset b/data/assets/scene/solarsystem/planets/earth/magnetosphere/magnetosphere.asset new file mode 100644 index 0000000000..eb9a36404b --- /dev/null +++ b/data/assets/scene/solarsystem/planets/earth/magnetosphere/magnetosphere.asset @@ -0,0 +1,50 @@ +local assetHelper = asset.require('util/asset_helper') +local transforms = asset.require('./transforms_magnetosphere') +local transferFunction = asset.localResource("./CMR-illuminance2.txt") + +local fieldlinesDirectory = asset.syncedResource({ + Name = "Magnetosphere 2012 event", + Type = "HttpSynchronization", + Identifier = "magnetosphere_2012_event", + Version = 1 +}) + +local earthMagnetosphere = { + Identifier = "EarthMagnetosphere", + Parent = transforms.GSMReferenceFrame.Identifier, + Renderable = { + Type = "RenderableFieldlinesSequence", + SourceFolder = fieldlinesDirectory, + LineWidth = 1.0, + AlphaBlendlingEnabled = false, + InputFileType = "Osfls", -- OpenSpace Field lines sequence + MaskingEnabled = true, + MaskingQuantity = 5, -- corresponds to "topology" + MaskingRanges = {{-0, 0}}, + ColorMethod = "By Quantity", + ColorQuantity = 4, + ColorTableRanges = {{50, 300}}, + ColorTablePaths = {transferFunction}, + LoadAtRuntime = true, + ScaleToMeters = 1.0, + Color = { + Uniform = { 1.0, 0.725, 0.75, 1.0 } + } + }, + GUI = { + Path = "/Solar System/Planets/Earth", + Name = "Magnetosphere" + }, +} + +assetHelper.registerSceneGraphNodesAndExport(asset, { earthMagnetosphere }) + +asset.meta = { + Name = "Static generic magnetosphere of fieldlines", + Version = "1.0", + Description = "Magnetic fieldlines for the bastille day CME event", + Author = "CCMC", + URL = "", + License = "", + Identifier = {"EarthMagnetosphere"} +} diff --git a/data/assets/scene/solarsystem/planets/earth/magnetosphere/transforms_magnetosphere.asset b/data/assets/scene/solarsystem/planets/earth/magnetosphere/transforms_magnetosphere.asset new file mode 100644 index 0000000000..3ceb18be2e --- /dev/null +++ b/data/assets/scene/solarsystem/planets/earth/magnetosphere/transforms_magnetosphere.asset @@ -0,0 +1,35 @@ +local assetHelper = asset.require('util/asset_helper') +local transforms = asset.require('scene/solarsystem/planets/earth/transforms') +asset.require("spice/base") + +local GSMKernel = asset.localResource("../kernels/GSM.ti") + +local GSMReferenceFrame = { + Identifier = "GSMReferenceFrame", + Parent = transforms.EarthCenter.Identifier, + Transform = { + Rotation = { + Type = "SpiceRotation", + SourceFrame = "GSM", --Geocentric Solar Magnetospheric + DestinationFrame = "GALACTIC", + Kernels = GSMKernel + } + }, + GUI = { + Name = "GSM Reference Frame", + Path = "/Solar System/Planets/Earth", + Hidden = true + } +} + +assetHelper.registerSceneGraphNodesAndExport(asset, { GSMReferenceFrame }) + +asset.meta = { + Name = "Earth magnetosphere transforms", + Version = "1.0", + Description = "Earth transforms: GSMReferenceFrame. Geocentric Solar Magnetospheric", + Author = "CCMC", + URL = "http://openspaceproject.com", + License = "MIT license", + Identifiers = {"GSMReferenceFrame"} +} diff --git a/data/assets/scene/solarsystem/planets/earth/map_service_configs/ESRI/Terrain.wms b/data/assets/scene/solarsystem/planets/earth/map_service_configs/ESRI/Terrain.wms index ab5521e76e..5de12576ea 100644 --- a/data/assets/scene/solarsystem/planets/earth/map_service_configs/ESRI/Terrain.wms +++ b/data/assets/scene/solarsystem/planets/earth/map_service_configs/ESRI/Terrain.wms @@ -1,8 +1,17 @@ - - http://198.102.45.23/arcgis/rest/services/worldelevation3d/terrain3d? - GCS_Elevation + + http://earthlive.maptiles.arcgis.com/arcgis/rest/services/GCS_Elevation3D/ImageServer/tile/${z}/${y}/${x} - 2 + + -180 90 + 180 -90 + 16777216 8388608 + 14 top + + EPSG:4326 + 512 512 + 1 Float32 + 5 + 404,400 diff --git a/data/assets/scene/solarsystem/planets/earth/markers.asset b/data/assets/scene/solarsystem/planets/earth/markers.asset index 79971e6339..975bb4b8b6 100644 --- a/data/assets/scene/solarsystem/planets/earth/markers.asset +++ b/data/assets/scene/solarsystem/planets/earth/markers.asset @@ -1,8 +1,13 @@ local transforms = asset.require('./transforms') local assetHelper = asset.require('util/asset_helper') -local texturesPath = asset.require('./earth_textures').TexturesPath +local texturesPath = asset.syncedResource({ + Name = "Earth Textures", + Type = "HttpSynchronization", + Identifier = "earth_textures", + Version = 2 +}) local EarthMarker = { Identifier = "EarthMarker", diff --git a/data/assets/scene/solarsystem/planets/earth/moon/moon.asset b/data/assets/scene/solarsystem/planets/earth/moon/moon.asset index f3cd2cea9a..6c3cf10831 100644 --- a/data/assets/scene/solarsystem/planets/earth/moon/moon.asset +++ b/data/assets/scene/solarsystem/planets/earth/moon/moon.asset @@ -3,7 +3,13 @@ local transforms = asset.require('scene/solarsystem/planets/earth/transforms') local sunAsset = asset.require('scene/solarsystem/sun/sun') local earthAsset = asset.require('../earth') asset.require('spice/base') -local labelsPath = asset.require('./moon_labels').LabelsPath + +local labelsPath = asset.syncedResource({ + Name = "Moon Labels", + Type = "HttpSynchronization", + Identifier = "moon_labels", + Version = 1 +}) local Moon = { Identifier = "Moon", diff --git a/data/assets/scene/solarsystem/planets/earth/moon/moon_labels.asset b/data/assets/scene/solarsystem/planets/earth/moon/moon_labels.asset deleted file mode 100644 index 7cdc6f6c2a..0000000000 --- a/data/assets/scene/solarsystem/planets/earth/moon/moon_labels.asset +++ /dev/null @@ -1,8 +0,0 @@ -local LabelsPath = asset.syncedResource({ - Name = "Moon Labels", - Type = "HttpSynchronization", - Identifier = "moon_labels", - Version = 1 -}) - -asset.export("LabelsPath", LabelsPath) diff --git a/data/assets/scene/solarsystem/planets/jupiter/callisto/callisto.asset b/data/assets/scene/solarsystem/planets/jupiter/callisto/callisto.asset index c4503abea0..f6417fdb88 100644 --- a/data/assets/scene/solarsystem/planets/jupiter/callisto/callisto.asset +++ b/data/assets/scene/solarsystem/planets/jupiter/callisto/callisto.asset @@ -3,7 +3,13 @@ local assetHelper = asset.require('util/asset_helper') asset.require("spice/base") asset.require('./trail') local kernel = asset.require('../kernels').jup310 -local labelsPath = asset.require('../jupiter_globelabels').LabelsPath + +local labelsPath = asset.syncedResource({ + Name = "Jupiter Labels", + Type = "HttpSynchronization", + Identifier = "jupiter_labels", + Version = 1 +}) local Callisto = { Identifier = "Callisto", diff --git a/data/assets/scene/solarsystem/planets/jupiter/callisto/callisto_textures.asset b/data/assets/scene/solarsystem/planets/jupiter/callisto/callisto_textures.asset deleted file mode 100644 index c6cc74bb68..0000000000 --- a/data/assets/scene/solarsystem/planets/jupiter/callisto/callisto_textures.asset +++ /dev/null @@ -1,7 +0,0 @@ -local TexturesPath = asset.syncedResource({ - Name = "Callisto Textures", - Type = "HttpSynchronization", - Identifier = "callisto_textures", - Version = 2 -}) -asset.export("TexturesPath", TexturesPath) diff --git a/data/assets/scene/solarsystem/planets/jupiter/callisto/layers/colorlayers/callisto_texture.asset b/data/assets/scene/solarsystem/planets/jupiter/callisto/layers/colorlayers/callisto_texture.asset index 21653cde87..113938eaf8 100644 --- a/data/assets/scene/solarsystem/planets/jupiter/callisto/layers/colorlayers/callisto_texture.asset +++ b/data/assets/scene/solarsystem/planets/jupiter/callisto/layers/colorlayers/callisto_texture.asset @@ -1,6 +1,12 @@ -local texturesPath = asset.require("./../../callisto_textures").TexturesPath local globeIdentifier = asset.require("./../../callisto").Callisto.Identifier +local texturesPath = asset.syncedResource({ + Name = "Callisto Textures", + Type = "HttpSynchronization", + Identifier = "callisto_textures", + Version = 2 +}) + local layer = { Identifier = "Texture", FilePath = texturesPath .. "/callisto_os.tif", diff --git a/data/assets/scene/solarsystem/planets/jupiter/europa/europa.asset b/data/assets/scene/solarsystem/planets/jupiter/europa/europa.asset index 1ecfb93b34..f6f5dae90e 100644 --- a/data/assets/scene/solarsystem/planets/jupiter/europa/europa.asset +++ b/data/assets/scene/solarsystem/planets/jupiter/europa/europa.asset @@ -3,7 +3,13 @@ local assetHelper = asset.require('util/asset_helper') asset.require("spice/base") asset.require('./trail') local kernel = asset.require('../kernels').jup310 -local labelsPath = asset.require('../jupiter_globelabels').LabelsPath + +local labelsPath = asset.syncedResource({ + Name = "Jupiter Labels", + Type = "HttpSynchronization", + Identifier = "jupiter_labels", + Version = 1 +}) local Europa = { Identifier = "Europa", diff --git a/data/assets/scene/solarsystem/planets/jupiter/europa/europa_textures.asset b/data/assets/scene/solarsystem/planets/jupiter/europa/europa_textures.asset deleted file mode 100644 index 259bec7da5..0000000000 --- a/data/assets/scene/solarsystem/planets/jupiter/europa/europa_textures.asset +++ /dev/null @@ -1,7 +0,0 @@ -local TexturesPath = asset.syncedResource({ - Name = "Europa Textures", - Type = "HttpSynchronization", - Identifier = "europa_textures", - Version = 2 -}) -asset.export("TexturesPath", TexturesPath) diff --git a/data/assets/scene/solarsystem/planets/jupiter/europa/layers/colorlayers/europa_texture.asset b/data/assets/scene/solarsystem/planets/jupiter/europa/layers/colorlayers/europa_texture.asset index 1e690211b2..ff04cd262f 100644 --- a/data/assets/scene/solarsystem/planets/jupiter/europa/layers/colorlayers/europa_texture.asset +++ b/data/assets/scene/solarsystem/planets/jupiter/europa/layers/colorlayers/europa_texture.asset @@ -1,6 +1,12 @@ -local texturesPath = asset.require("./../../europa_textures").TexturesPath local globeIdentifier = asset.require("./../../europa").Europa.Identifier +local texturesPath = asset.syncedResource({ + Name = "Europa Textures", + Type = "HttpSynchronization", + Identifier = "europa_textures", + Version = 2 +}) + local layer = { Identifier = "Texture", FilePath = texturesPath .. "/europa_os.tif", diff --git a/data/assets/scene/solarsystem/planets/jupiter/europa/layers/colorlayers/voyager_global_mosaic_local.asset b/data/assets/scene/solarsystem/planets/jupiter/europa/layers/colorlayers/voyager_global_mosaic_local.asset index 36e08d3c16..c4991eb4e7 100644 --- a/data/assets/scene/solarsystem/planets/jupiter/europa/layers/colorlayers/voyager_global_mosaic_local.asset +++ b/data/assets/scene/solarsystem/planets/jupiter/europa/layers/colorlayers/voyager_global_mosaic_local.asset @@ -1,6 +1,12 @@ -local texturesPath = asset.require("./../../europa_textures").TexturesPath local globeIdentifier = asset.require("./../../europa").Europa.Identifier +local texturesPath = asset.syncedResource({ + Name = "Europa Textures", + Type = "HttpSynchronization", + Identifier = "europa_textures", + Version = 2 +}) + local layer = { Identifier = "Voyager_Global_Mosaic_Local", Name = "Voyager Global Mosaic [Local]", diff --git a/data/assets/scene/solarsystem/planets/jupiter/ganymede/ganymede.asset b/data/assets/scene/solarsystem/planets/jupiter/ganymede/ganymede.asset index ccda9c129a..182c3aefeb 100644 --- a/data/assets/scene/solarsystem/planets/jupiter/ganymede/ganymede.asset +++ b/data/assets/scene/solarsystem/planets/jupiter/ganymede/ganymede.asset @@ -3,7 +3,13 @@ local assetHelper = asset.require('util/asset_helper') asset.require("spice/base") asset.require('./trail') local kernel = asset.require('../kernels').jup310 -local labelsPath = asset.require('../jupiter_globelabels').LabelsPath + +local labelsPath = asset.syncedResource({ + Name = "Jupiter Labels", + Type = "HttpSynchronization", + Identifier = "jupiter_labels", + Version = 1 +}) local Ganymede = { Identifier = "Ganymede", diff --git a/data/assets/scene/solarsystem/planets/jupiter/ganymede/ganymede_textures.asset b/data/assets/scene/solarsystem/planets/jupiter/ganymede/ganymede_textures.asset deleted file mode 100644 index e27f858103..0000000000 --- a/data/assets/scene/solarsystem/planets/jupiter/ganymede/ganymede_textures.asset +++ /dev/null @@ -1,7 +0,0 @@ -local TexturesPath = asset.syncedResource({ - Name = "Ganymede Textures", - Type = "HttpSynchronization", - Identifier = "ganymede_textures", - Version = 1 -}) -asset.export("TexturesPath", TexturesPath) diff --git a/data/assets/scene/solarsystem/planets/jupiter/ganymede/layers/colorlayers/ganymede_texture.asset b/data/assets/scene/solarsystem/planets/jupiter/ganymede/layers/colorlayers/ganymede_texture.asset index 6cddc4d319..5bfd9aa607 100644 --- a/data/assets/scene/solarsystem/planets/jupiter/ganymede/layers/colorlayers/ganymede_texture.asset +++ b/data/assets/scene/solarsystem/planets/jupiter/ganymede/layers/colorlayers/ganymede_texture.asset @@ -1,6 +1,12 @@ -local texturesPath = asset.require("./../../ganymede_textures").TexturesPath local globeIdentifier = asset.require("./../../ganymede").Ganymede.Identifier +local texturesPath = asset.syncedResource({ + Name = "Ganymede Textures", + Type = "HttpSynchronization", + Identifier = "ganymede_textures", + Version = 1 +}) + local layer = { Identifier = "Texture", FilePath = texturesPath .. "/ganymede.jpg", diff --git a/data/assets/scene/solarsystem/planets/jupiter/io/io.asset b/data/assets/scene/solarsystem/planets/jupiter/io/io.asset index 641cf411f6..3bf82f2cc8 100644 --- a/data/assets/scene/solarsystem/planets/jupiter/io/io.asset +++ b/data/assets/scene/solarsystem/planets/jupiter/io/io.asset @@ -3,7 +3,13 @@ local assetHelper = asset.require('util/asset_helper') asset.require("spice/base") asset.require('./trail') local kernel = asset.require('../kernels').jup310 -local labelsPath = asset.require('../jupiter_globelabels').LabelsPath + +local labelsPath = asset.syncedResource({ + Name = "Jupiter Labels", + Type = "HttpSynchronization", + Identifier = "jupiter_labels", + Version = 1 +}) local Io = { Identifier = "Io", diff --git a/data/assets/scene/solarsystem/planets/jupiter/io/io_textures.asset b/data/assets/scene/solarsystem/planets/jupiter/io/io_textures.asset deleted file mode 100644 index 36b55fdc1e..0000000000 --- a/data/assets/scene/solarsystem/planets/jupiter/io/io_textures.asset +++ /dev/null @@ -1,7 +0,0 @@ -local TexturesPath = asset.syncedResource({ - Name = "Io Textures", - Type = "HttpSynchronization", - Identifier = "io_textures", - Version = 1 -}) -asset.export("TexturesPath", TexturesPath) diff --git a/data/assets/scene/solarsystem/planets/jupiter/io/layers/colorlayers/io_texture.asset b/data/assets/scene/solarsystem/planets/jupiter/io/layers/colorlayers/io_texture.asset index 1e7eb5517e..baa929c659 100644 --- a/data/assets/scene/solarsystem/planets/jupiter/io/layers/colorlayers/io_texture.asset +++ b/data/assets/scene/solarsystem/planets/jupiter/io/layers/colorlayers/io_texture.asset @@ -1,6 +1,12 @@ -local texturesPath = asset.require("./../../io_textures").TexturesPath local globeIdentifier = asset.require("./../../io").Io.Identifier +local texturesPath = asset.syncedResource({ + Name = "Io Textures", + Type = "HttpSynchronization", + Identifier = "io_textures", + Version = 1 +}) + local layer = { Identifier = "Texture", FilePath = texturesPath .. "/io.jpg", diff --git a/data/assets/scene/solarsystem/planets/jupiter/jupiter_globelabels.asset b/data/assets/scene/solarsystem/planets/jupiter/jupiter_globelabels.asset deleted file mode 100644 index 9de72c055c..0000000000 --- a/data/assets/scene/solarsystem/planets/jupiter/jupiter_globelabels.asset +++ /dev/null @@ -1,7 +0,0 @@ -local LabelsPath = asset.syncedResource({ - Name = "Jupiter Labels", - Type = "HttpSynchronization", - Identifier = "jupiter_labels", - Version = 1 -}) -asset.export("LabelsPath", LabelsPath) diff --git a/data/assets/scene/solarsystem/planets/jupiter/jupiter_textures.asset b/data/assets/scene/solarsystem/planets/jupiter/jupiter_textures.asset deleted file mode 100644 index c310a1906b..0000000000 --- a/data/assets/scene/solarsystem/planets/jupiter/jupiter_textures.asset +++ /dev/null @@ -1,7 +0,0 @@ -local TexturesPath = asset.syncedResource({ - Name = "Jupiter Textures", - Type = "HttpSynchronization", - Identifier = "jupiter_textures", - Version = 2 -}) -asset.export("TexturesPath", TexturesPath) diff --git a/data/assets/scene/solarsystem/planets/jupiter/layers/colorlayers/jupiter_texture.asset b/data/assets/scene/solarsystem/planets/jupiter/layers/colorlayers/jupiter_texture.asset index 98b2d1543d..b1253cd604 100644 --- a/data/assets/scene/solarsystem/planets/jupiter/layers/colorlayers/jupiter_texture.asset +++ b/data/assets/scene/solarsystem/planets/jupiter/layers/colorlayers/jupiter_texture.asset @@ -1,6 +1,12 @@ -local texturesPath = asset.require("./../../jupiter_textures").TexturesPath local globeIdentifier = asset.require("./../../jupiter").Jupiter.Identifier +local texturesPath = asset.syncedResource({ + Name = "Jupiter Textures", + Type = "HttpSynchronization", + Identifier = "jupiter_textures", + Version = 2 +}) + local layer = { Identifier = "Texture", FilePath = texturesPath .. "/jupiter_os.tif", diff --git a/data/assets/scene/solarsystem/planets/jupiter/minor/ananke_group.asset b/data/assets/scene/solarsystem/planets/jupiter/minor/ananke_group.asset index b9cfabaede..d26e384b3e 100644 --- a/data/assets/scene/solarsystem/planets/jupiter/minor/ananke_group.asset +++ b/data/assets/scene/solarsystem/planets/jupiter/minor/ananke_group.asset @@ -7,7 +7,7 @@ local kernel = asset.require('../kernels').jup341 local parentIdentifier = transforms.JupiterBarycenter.Identifier local parentSpice = "JUPITER BARYCENTER" -local tags = { "moon_solarSystem", "moon_giants", "moon_jupiter", "moon_ananke"} +local tags = { "moon_solarSystem", "moon_giants", "moon_jupiter", "moon_ananke", "moon_minor" } local trailColor = { 0.4, 0.3, 0.01 } local trailTags = { "moonTrail_solarSystem", diff --git a/data/assets/scene/solarsystem/planets/jupiter/minor/carme_group.asset b/data/assets/scene/solarsystem/planets/jupiter/minor/carme_group.asset index e6b56d1db4..32f0c3b067 100644 --- a/data/assets/scene/solarsystem/planets/jupiter/minor/carme_group.asset +++ b/data/assets/scene/solarsystem/planets/jupiter/minor/carme_group.asset @@ -7,7 +7,7 @@ local kernel = asset.require('../kernels').jup341 local parentIdentifier = transforms.JupiterBarycenter.Identifier local parentSpice = "JUPITER BARYCENTER" -local tags = { "moon_solarSystem", "moon_giants", "moon_jupiter", "moon_carme" } +local tags = { "moon_solarSystem", "moon_giants", "moon_jupiter", "moon_carme", "moon_minor" } local trailColor = { 0.4, 0.3, 0.01 } local trailTags = { "moonTrail_solarSystem", diff --git a/data/assets/scene/solarsystem/planets/jupiter/minor/carpo_group.asset b/data/assets/scene/solarsystem/planets/jupiter/minor/carpo_group.asset index 7fcb8e9cdc..0731ce60ba 100644 --- a/data/assets/scene/solarsystem/planets/jupiter/minor/carpo_group.asset +++ b/data/assets/scene/solarsystem/planets/jupiter/minor/carpo_group.asset @@ -7,7 +7,7 @@ local kernel = asset.require('../kernels').jup341 local parentIdentifier = transforms.JupiterBarycenter.Identifier local parentSpice = "JUPITER BARYCENTER" -local tags = { "moon_solarSystem", "moon_giants", "moon_jupiter", "moon_carpo" } +local tags = { "moon_solarSystem", "moon_giants", "moon_jupiter", "moon_carpo", "moon_minor" } local trailColor = { 0.4, 0.3, 0.01 } local trailTags = { "moonTrail_solarSystem", diff --git a/data/assets/scene/solarsystem/planets/jupiter/minor/himalia_group.asset b/data/assets/scene/solarsystem/planets/jupiter/minor/himalia_group.asset index fa9117c43c..2b0619989c 100644 --- a/data/assets/scene/solarsystem/planets/jupiter/minor/himalia_group.asset +++ b/data/assets/scene/solarsystem/planets/jupiter/minor/himalia_group.asset @@ -7,7 +7,7 @@ local kernel = asset.require('../kernels').jup341 local parentIdentifier = transforms.JupiterBarycenter.Identifier local parentSpice = "JUPITER BARYCENTER" -local tags = { "moon_solarSystem", "moon_giants", "moon_jupiter", "moon_himalia" } +local tags = { "moon_solarSystem", "moon_giants", "moon_jupiter", "moon_himalia", "moon_minor" } local trailColor = { 0.4, 0.3, 0.01 } local trailTags = { "moonTrail_solarSystem", diff --git a/data/assets/scene/solarsystem/planets/jupiter/minor/inner_group.asset b/data/assets/scene/solarsystem/planets/jupiter/minor/inner_group.asset index 63a0ae8d98..34f81084ae 100644 --- a/data/assets/scene/solarsystem/planets/jupiter/minor/inner_group.asset +++ b/data/assets/scene/solarsystem/planets/jupiter/minor/inner_group.asset @@ -7,7 +7,7 @@ local kernel = asset.require('../kernels').jup341 local parentIdentifier = transforms.JupiterBarycenter.Identifier local parentSpice = "JUPITER BARYCENTER" -local tags = { "moon_solarSystem", "moon_giants", "moon_jupiter", "moon_inner" } +local tags = { "moon_solarSystem", "moon_giants", "moon_jupiter", "moon_inner", "moon_minor" } local trailColor = { 0.4, 0.3, 0.01 } local trailTags = { "moonTrail_solarSystem", diff --git a/data/assets/scene/solarsystem/planets/jupiter/minor/other_groups.asset b/data/assets/scene/solarsystem/planets/jupiter/minor/other_groups.asset index 644d959083..c72a04d69f 100644 --- a/data/assets/scene/solarsystem/planets/jupiter/minor/other_groups.asset +++ b/data/assets/scene/solarsystem/planets/jupiter/minor/other_groups.asset @@ -7,7 +7,7 @@ local kernel = asset.require('../kernels').jup341 local parentIdentifier = transforms.JupiterBarycenter.Identifier local parentSpice = "JUPITER BARYCENTER" -local tags = { "moon_solarSystem", "moon_giants", "moon_jupiter", "moon_other" } +local tags = { "moon_solarSystem", "moon_giants", "moon_jupiter", "moon_other", "moon_minor" } local trailColor = { 0.4, 0.3, 0.01 } local trailTags = { "moonTrail_solarSystem", diff --git a/data/assets/scene/solarsystem/planets/jupiter/minor/pasiphae_group.asset b/data/assets/scene/solarsystem/planets/jupiter/minor/pasiphae_group.asset index 4576f4e782..8268262874 100644 --- a/data/assets/scene/solarsystem/planets/jupiter/minor/pasiphae_group.asset +++ b/data/assets/scene/solarsystem/planets/jupiter/minor/pasiphae_group.asset @@ -7,7 +7,7 @@ local kernel = asset.require('../kernels').jup341 local parentIdentifier = transforms.JupiterBarycenter.Identifier local parentSpice = "JUPITER BARYCENTER" -local tags = { "moon_solarSystem", "moon_giants", "moon_jupiter", "moon_pasiphae" } +local tags = { "moon_solarSystem", "moon_giants", "moon_jupiter", "moon_pasiphae", "moon_minor" } local trailColor = { 0.4, 0.3, 0.01 } local trailTags = { "moonTrail_solarSystem", diff --git a/data/assets/scene/solarsystem/planets/jupiter/minor/themisto_group.asset b/data/assets/scene/solarsystem/planets/jupiter/minor/themisto_group.asset index 0a2299e611..343eb2c432 100644 --- a/data/assets/scene/solarsystem/planets/jupiter/minor/themisto_group.asset +++ b/data/assets/scene/solarsystem/planets/jupiter/minor/themisto_group.asset @@ -7,7 +7,7 @@ local kernel = asset.require('../kernels').jup341 local parentIdentifier = transforms.JupiterBarycenter.Identifier local parentSpice = "JUPITER BARYCENTER" -local tags = { "moon_solarSystem", "moon_giants", "moon_jupiter", "moon_themisto" } +local tags = { "moon_solarSystem", "moon_giants", "moon_jupiter", "moon_themisto", "moon_minor" } local trailColor = { 0.4, 0.3, 0.01 } local trailTags = { "moonTrail_solarSystem", diff --git a/data/assets/scene/solarsystem/planets/mars/atmosphere.asset b/data/assets/scene/solarsystem/planets/mars/atmosphere.asset index a3f30d278d..e76b1afd57 100644 --- a/data/assets/scene/solarsystem/planets/mars/atmosphere.asset +++ b/data/assets/scene/solarsystem/planets/mars/atmosphere.asset @@ -42,7 +42,6 @@ local Atmosphere = { G = 0.85 }, Debug = { - -- PreCalculatedTextureScale is a float from 1.0 to N, with N > 0.0 and N in Naturals (i.e., 1, 2, 3, 4, 5....) PreCalculatedTextureScale = 1.0, SaveCalculatedTextures = false } diff --git a/data/assets/scene/solarsystem/planets/mars/layers/colorlayers/fallbacks/mars_texture.asset b/data/assets/scene/solarsystem/planets/mars/layers/colorlayers/fallbacks/mars_texture.asset index beb227466d..c9094eaa85 100644 --- a/data/assets/scene/solarsystem/planets/mars/layers/colorlayers/fallbacks/mars_texture.asset +++ b/data/assets/scene/solarsystem/planets/mars/layers/colorlayers/fallbacks/mars_texture.asset @@ -1,4 +1,9 @@ -local texturesPath = asset.require("./../../../mars_textures").TexturesPath +local texturesPath = asset.syncedResource({ + Name = "Mars Textures", + Type = "HttpSynchronization", + Identifier = "mars_textures", + Version = 1 +}) local layer = { Identifier = "Mars_Texture", diff --git a/data/assets/scene/solarsystem/planets/mars/layers/colorlayers/mars_texture.asset b/data/assets/scene/solarsystem/planets/mars/layers/colorlayers/mars_texture.asset index 125d653a4b..18bf3f5e92 100644 --- a/data/assets/scene/solarsystem/planets/mars/layers/colorlayers/mars_texture.asset +++ b/data/assets/scene/solarsystem/planets/mars/layers/colorlayers/mars_texture.asset @@ -1,6 +1,12 @@ -local texturesPath = asset.require("./../../mars_textures").TexturesPath local globeIdentifier = asset.require("./../../mars").Mars.Identifier +local texturesPath = asset.syncedResource({ + Name = "Mars Textures", + Type = "HttpSynchronization", + Identifier = "mars_textures", + Version = 1 +}) + local layer = { Identifier = "Mars_Texture", Name = "Mars Texture", diff --git a/data/assets/scene/solarsystem/planets/mars/mar097.asset b/data/assets/scene/solarsystem/planets/mars/mar097.asset deleted file mode 100644 index 70af8b1c5f..0000000000 --- a/data/assets/scene/solarsystem/planets/mars/mar097.asset +++ /dev/null @@ -1,8 +0,0 @@ -local Kernels = asset.syncedResource({ - Name = "Mars Spice Kernels", - Type = "HttpSynchronization", - Identifier = "mars_kernels", - Version = 1 -}) - -asset.export("Kernels", Kernels .. '/mar097.bsp') diff --git a/data/assets/scene/solarsystem/planets/mars/mars.asset b/data/assets/scene/solarsystem/planets/mars/mars.asset index 38ea1c813f..b0d8c1c486 100644 --- a/data/assets/scene/solarsystem/planets/mars/mars.asset +++ b/data/assets/scene/solarsystem/planets/mars/mars.asset @@ -2,7 +2,13 @@ local transforms = asset.require('./transforms') local assetHelper = asset.require('util/asset_helper') asset.require("spice/base") asset.require('./trail') -local labelsPath = asset.require('./mars_globelabels').LabelsPath + +local labelsPath = asset.syncedResource({ + Name = "Mars Labels", + Type = "HttpSynchronization", + Identifier = "mars_labels", + Version = 1 +}) -- local marsRadii = { 3396190.0, 3396190.0, 3376200.0 } local marsRadii = { 3396190.0, 3396190.0, 3396190.0 } diff --git a/data/assets/scene/solarsystem/planets/mars/mars_globelabels.asset b/data/assets/scene/solarsystem/planets/mars/mars_globelabels.asset deleted file mode 100644 index ca47fef12e..0000000000 --- a/data/assets/scene/solarsystem/planets/mars/mars_globelabels.asset +++ /dev/null @@ -1,7 +0,0 @@ -local LabelsPath = asset.syncedResource({ - Name = "Mars Labels", - Type = "HttpSynchronization", - Identifier = "mars_labels", - Version = 1 -}) -asset.export("LabelsPath", LabelsPath) diff --git a/data/assets/scene/solarsystem/planets/mars/mars_textures.asset b/data/assets/scene/solarsystem/planets/mars/mars_textures.asset deleted file mode 100644 index 757bad1d08..0000000000 --- a/data/assets/scene/solarsystem/planets/mars/mars_textures.asset +++ /dev/null @@ -1,7 +0,0 @@ -local TexturesPath = asset.syncedResource({ - Name = "Mars Textures", - Type = "HttpSynchronization", - Identifier = "mars_textures", - Version = 1 -}) -asset.export("TexturesPath", TexturesPath) diff --git a/data/assets/scene/solarsystem/planets/mars/moons/deimos.asset b/data/assets/scene/solarsystem/planets/mars/moons/deimos.asset index a7b3d5e7aa..e5fb205cf4 100644 --- a/data/assets/scene/solarsystem/planets/mars/moons/deimos.asset +++ b/data/assets/scene/solarsystem/planets/mars/moons/deimos.asset @@ -1,6 +1,12 @@ local transforms = asset.require('../transforms') local assetHelper = asset.require('util/asset_helper') -local kernels = asset.require('../mar097').Kernels + +local kernels = asset.syncedResource({ + Name = "Mars Spice Kernels", + Type = "HttpSynchronization", + Identifier = "mars_kernels", + Version = 1 +}) local Deimos = { @@ -11,13 +17,13 @@ local Deimos = { Type = "SpiceRotation", SourceFrame = "IAU_DEIMOS", DestinationFrame = "GALACTIC", - Kernels = kernels + Kernels = kernels .. '/mar097.bsp' }, Translation = { Type = "SpiceTranslation", Target = "DEIMOS", Observer = "MARS BARYCENTER", - Kernels = kernels + Kernels = kernels .. '/mar097.bsp' } }, Renderable = { diff --git a/data/assets/scene/solarsystem/planets/mars/moons/phobos.asset b/data/assets/scene/solarsystem/planets/mars/moons/phobos.asset index 353c73e320..4daa558e81 100644 --- a/data/assets/scene/solarsystem/planets/mars/moons/phobos.asset +++ b/data/assets/scene/solarsystem/planets/mars/moons/phobos.asset @@ -1,6 +1,12 @@ local transforms = asset.require('../transforms') local assetHelper = asset.require('util/asset_helper') -local kernels = asset.require('../mar097').Kernels + +local kernels = asset.syncedResource({ + Name = "Mars Spice Kernels", + Type = "HttpSynchronization", + Identifier = "mars_kernels", + Version = 1 +}) local Phobos = { @@ -11,13 +17,13 @@ local Phobos = { Type = "SpiceRotation", SourceFrame = "IAU_PHOBOS", DestinationFrame = "GALACTIC", - Kernels = kernels + Kernels = kernels .. '/mar097.bsp' }, Translation = { Type = "SpiceTranslation", Target = "PHOBOS", Observer = "MARS BARYCENTER", - Kernels = kernels + Kernels = kernels .. '/mar097.bsp' } }, Renderable = { diff --git a/data/assets/scene/solarsystem/planets/mercury/layers/colorlayers/alsimap_02122015.asset b/data/assets/scene/solarsystem/planets/mercury/layers/colorlayers/alsimap_02122015.asset index 7ded2c0167..48e77aa092 100644 --- a/data/assets/scene/solarsystem/planets/mercury/layers/colorlayers/alsimap_02122015.asset +++ b/data/assets/scene/solarsystem/planets/mercury/layers/colorlayers/alsimap_02122015.asset @@ -1,6 +1,12 @@ -local texturesPath = asset.require("./../../mercury_textures").TexturesPath local globeIdentifier = asset.require("./../../mercury").Mercury.Identifier +local texturesPath = asset.syncedResource({ + Name = "Mercury Textures", + Type = "HttpSynchronization", + Identifier = "mercury_abundance_textures", + Version = 1 +}) + local layer = { Name = "Aluminium Abundance", Identifier = "alsimap_02122015", diff --git a/data/assets/scene/solarsystem/planets/mercury/layers/colorlayers/casimap_02122015.asset b/data/assets/scene/solarsystem/planets/mercury/layers/colorlayers/casimap_02122015.asset index 32f3535fd6..4349b52fa6 100644 --- a/data/assets/scene/solarsystem/planets/mercury/layers/colorlayers/casimap_02122015.asset +++ b/data/assets/scene/solarsystem/planets/mercury/layers/colorlayers/casimap_02122015.asset @@ -1,6 +1,12 @@ -local texturesPath = asset.require("./../../mercury_textures").TexturesPath local globeIdentifier = asset.require("./../../mercury").Mercury.Identifier +local texturesPath = asset.syncedResource({ + Name = "Mercury Textures", + Type = "HttpSynchronization", + Identifier = "mercury_abundance_textures", + Version = 1 +}) + local layer = { Name = "Calcium Abundance", Identifier = "casimap_02122015", diff --git a/data/assets/scene/solarsystem/planets/mercury/layers/colorlayers/fesimap_02122015.asset b/data/assets/scene/solarsystem/planets/mercury/layers/colorlayers/fesimap_02122015.asset index dd3c272b19..44de613d98 100644 --- a/data/assets/scene/solarsystem/planets/mercury/layers/colorlayers/fesimap_02122015.asset +++ b/data/assets/scene/solarsystem/planets/mercury/layers/colorlayers/fesimap_02122015.asset @@ -1,6 +1,12 @@ -local texturesPath = asset.require("./../../mercury_textures").TexturesPath local globeIdentifier = asset.require("./../../mercury").Mercury.Identifier +local texturesPath = asset.syncedResource({ + Name = "Mercury Textures", + Type = "HttpSynchronization", + Identifier = "mercury_abundance_textures", + Version = 1 +}) + local layer = { Name = "Iron Abundance", Identifier = "fesimap_02122015", diff --git a/data/assets/scene/solarsystem/planets/mercury/layers/colorlayers/mgsimap_02122015.asset b/data/assets/scene/solarsystem/planets/mercury/layers/colorlayers/mgsimap_02122015.asset index 8dbb6ce060..9eaa922e2e 100644 --- a/data/assets/scene/solarsystem/planets/mercury/layers/colorlayers/mgsimap_02122015.asset +++ b/data/assets/scene/solarsystem/planets/mercury/layers/colorlayers/mgsimap_02122015.asset @@ -1,6 +1,12 @@ -local texturesPath = asset.require("./../../mercury_textures").TexturesPath local globeIdentifier = asset.require("./../../mercury").Mercury.Identifier +local texturesPath = asset.syncedResource({ + Name = "Mercury Textures", + Type = "HttpSynchronization", + Identifier = "mercury_abundance_textures", + Version = 1 +}) + local layer = { Name = "Magnesium Abundance", Identifier = "mgsimap_02122015", diff --git a/data/assets/scene/solarsystem/planets/mercury/layers/colorlayers/ssimap_02122015.asset b/data/assets/scene/solarsystem/planets/mercury/layers/colorlayers/ssimap_02122015.asset index 8922f0cdfb..e07396ecb8 100644 --- a/data/assets/scene/solarsystem/planets/mercury/layers/colorlayers/ssimap_02122015.asset +++ b/data/assets/scene/solarsystem/planets/mercury/layers/colorlayers/ssimap_02122015.asset @@ -1,6 +1,12 @@ -local texturesPath = asset.require("./../../mercury_textures").TexturesPath local globeIdentifier = asset.require("./../../mercury").Mercury.Identifier +local texturesPath = asset.syncedResource({ + Name = "Mercury Textures", + Type = "HttpSynchronization", + Identifier = "mercury_abundance_textures", + Version = 1 +}) + local layer = { Name = "Silicon Abundance", Identifier = "ssimap_02122015", diff --git a/data/assets/scene/solarsystem/planets/mercury/mercury.asset b/data/assets/scene/solarsystem/planets/mercury/mercury.asset index f6e8465910..037c85a891 100644 --- a/data/assets/scene/solarsystem/planets/mercury/mercury.asset +++ b/data/assets/scene/solarsystem/planets/mercury/mercury.asset @@ -1,10 +1,16 @@ local assetHelper = asset.require('util/asset_helper') local transforms = asset.require('./transforms') -local labelsPath = asset.require('./mercury_globelabels').LabelsPath asset.require("spice/base") asset.require('./trail') +local labelsPath = asset.syncedResource({ + Name = "Mercury Labels", + Type = "HttpSynchronization", + Identifier = "mercury_labels", + Version = 1 +}) + local Mercury = { Identifier = "Mercury", Parent = transforms.MercuryBarycenter.Identifier, diff --git a/data/assets/scene/solarsystem/planets/mercury/mercury_globelabels.asset b/data/assets/scene/solarsystem/planets/mercury/mercury_globelabels.asset deleted file mode 100644 index 14cbb35a14..0000000000 --- a/data/assets/scene/solarsystem/planets/mercury/mercury_globelabels.asset +++ /dev/null @@ -1,7 +0,0 @@ -local LabelsPath = asset.syncedResource({ - Name = "Mercury Labels", - Type = "HttpSynchronization", - Identifier = "mercury_labels", - Version = 1 -}) -asset.export("LabelsPath", LabelsPath) \ No newline at end of file diff --git a/data/assets/scene/solarsystem/planets/mercury/mercury_textures.asset b/data/assets/scene/solarsystem/planets/mercury/mercury_textures.asset deleted file mode 100644 index 3ff8488a6d..0000000000 --- a/data/assets/scene/solarsystem/planets/mercury/mercury_textures.asset +++ /dev/null @@ -1,7 +0,0 @@ -local TexturesPath = asset.syncedResource({ - Name = "Mercury Textures", - Type = "HttpSynchronization", - Identifier = "mercury_abundance_textures", - Version = 1 -}) -asset.export("TexturesPath", TexturesPath) diff --git a/data/assets/scene/solarsystem/planets/neptune/inner_moons.asset b/data/assets/scene/solarsystem/planets/neptune/inner_moons.asset index 3a6dddaba4..dc8e85f381 100644 --- a/data/assets/scene/solarsystem/planets/neptune/inner_moons.asset +++ b/data/assets/scene/solarsystem/planets/neptune/inner_moons.asset @@ -10,7 +10,7 @@ local kernel088 = kernels.nep088 local parentIdentifier = transforms.NeptuneBarycenter.Identifier local parentSpice = "NEPTUNE BARYCENTER" -local tags = { "moon_solarSystem", "moon_giants", "moon_neptune", "moon_inner" } +local tags = { "moon_solarSystem", "moon_giants", "moon_neptune", "moon_inner", "moon_minor" } local trailColor = { 0.2, 0.5, 0.75 } local trailTags = { "moonTrail_solarSystem", diff --git a/data/assets/scene/solarsystem/planets/neptune/irregular_prograde_moons.asset b/data/assets/scene/solarsystem/planets/neptune/irregular_prograde_moons.asset index 810434bbc0..efb2834b56 100644 --- a/data/assets/scene/solarsystem/planets/neptune/irregular_prograde_moons.asset +++ b/data/assets/scene/solarsystem/planets/neptune/irregular_prograde_moons.asset @@ -10,7 +10,7 @@ local kernel088 = kernels.nep088 local parentIdentifier = transforms.NeptuneBarycenter.Identifier local parentSpice = "NEPTUNE BARYCENTER" -local tags = { "moon_solarSystem", "moon_giants", "moon_neptune", "moon_irregular_prograde" } +local tags = { "moon_solarSystem", "moon_giants", "moon_neptune", "moon_irregular_prograde", "moon_minor" } local trailColor = { 0.2, 0.5, 0.75 } local trailTags = { "moonTrail_solarSystem", diff --git a/data/assets/scene/solarsystem/planets/neptune/irregular_retrograde_moons.asset b/data/assets/scene/solarsystem/planets/neptune/irregular_retrograde_moons.asset index badb4eb266..38d9472ffa 100644 --- a/data/assets/scene/solarsystem/planets/neptune/irregular_retrograde_moons.asset +++ b/data/assets/scene/solarsystem/planets/neptune/irregular_retrograde_moons.asset @@ -9,7 +9,7 @@ local kernel086 = kernels.nep086 local parentIdentifier = transforms.NeptuneBarycenter.Identifier local parentSpice = "NEPTUNE BARYCENTER" -local tags = { "moon_solarSystem", "moon_giants", "moon_neptune", "moon_irregular_retrograde" } +local tags = { "moon_solarSystem", "moon_giants", "moon_neptune", "moon_irregular_retrograde", "moon_minor" } local trailColor = { 0.2, 0.5, 0.75 } local trailTags = { "moonTrail_solarSystem", diff --git a/data/assets/scene/solarsystem/planets/neptune/layers/colorlayers/neptune_texture.asset b/data/assets/scene/solarsystem/planets/neptune/layers/colorlayers/neptune_texture.asset index 5ee223dfa1..6d3f350826 100644 --- a/data/assets/scene/solarsystem/planets/neptune/layers/colorlayers/neptune_texture.asset +++ b/data/assets/scene/solarsystem/planets/neptune/layers/colorlayers/neptune_texture.asset @@ -1,6 +1,12 @@ -local texturesPath = asset.require("./../../neptune_textures").TexturesPath local globeIdentifier = asset.require("./../../neptune").Neptune.Identifier +local texturesPath = asset.syncedResource({ + Name = "Neptune textures", + Type = "HttpSynchronization", + Identifier = "neptune_textures", + Version = 1 +}) + local layer = { Identifier = "Texture", FilePath = texturesPath .. "/neptune.jpg", diff --git a/data/assets/scene/solarsystem/planets/neptune/neptune_textures.asset b/data/assets/scene/solarsystem/planets/neptune/neptune_textures.asset deleted file mode 100644 index 13adefb9a0..0000000000 --- a/data/assets/scene/solarsystem/planets/neptune/neptune_textures.asset +++ /dev/null @@ -1,7 +0,0 @@ -local TexturesPath = asset.syncedResource({ - Name = "Neptune textures", - Type = "HttpSynchronization", - Identifier = "neptune_textures", - Version = 1 -}) -asset.export("TexturesPath", TexturesPath) diff --git a/data/assets/scene/solarsystem/planets/saturn/dione/dione.asset b/data/assets/scene/solarsystem/planets/saturn/dione/dione.asset index f91edea8ed..a694b53569 100644 --- a/data/assets/scene/solarsystem/planets/saturn/dione/dione.asset +++ b/data/assets/scene/solarsystem/planets/saturn/dione/dione.asset @@ -2,7 +2,13 @@ local transforms = asset.require('../transforms') local assetHelper = asset.require('util/asset_helper') local kernel = asset.require('../kernels').sat375 asset.require('./trail') -local labelsPath = asset.require('../saturn_globelabels').LabelsPath + +local labelsPath = asset.syncedResource({ + Name = "Saturn Labels", + Type = "HttpSynchronization", + Identifier = "saturn_labels", + Version = 1 +}) local Dione = { Identifier = "Dione", diff --git a/data/assets/scene/solarsystem/planets/saturn/dione/dione_textures.asset b/data/assets/scene/solarsystem/planets/saturn/dione/dione_textures.asset deleted file mode 100644 index d104446236..0000000000 --- a/data/assets/scene/solarsystem/planets/saturn/dione/dione_textures.asset +++ /dev/null @@ -1,7 +0,0 @@ -local TexturesPath = asset.syncedResource({ - Name = "Dione textures", - Type = "HttpSynchronization", - Identifier = "dione_textures", - Version = 1 -}) -asset.export("TexturesPath", TexturesPath) diff --git a/data/assets/scene/solarsystem/planets/saturn/dione/layers/colorlayers/dione_texture.asset b/data/assets/scene/solarsystem/planets/saturn/dione/layers/colorlayers/dione_texture.asset index 8f58e9f7d2..a6adcf8c7e 100644 --- a/data/assets/scene/solarsystem/planets/saturn/dione/layers/colorlayers/dione_texture.asset +++ b/data/assets/scene/solarsystem/planets/saturn/dione/layers/colorlayers/dione_texture.asset @@ -1,6 +1,12 @@ -local texturesPath = asset.require("./../../dione_textures").TexturesPath local globeIdentifier = asset.require("./../../dione").Dione.Identifier +local texturesPath = asset.syncedResource({ + Name = "Dione textures", + Type = "HttpSynchronization", + Identifier = "dione_textures", + Version = 1 +}) + local layer = { Identifier = "Texture", FilePath = texturesPath .. "/dione.jpg", diff --git a/data/assets/scene/solarsystem/planets/saturn/enceladus/enceladus.asset b/data/assets/scene/solarsystem/planets/saturn/enceladus/enceladus.asset index 87d416faea..bba6f22c07 100644 --- a/data/assets/scene/solarsystem/planets/saturn/enceladus/enceladus.asset +++ b/data/assets/scene/solarsystem/planets/saturn/enceladus/enceladus.asset @@ -2,7 +2,13 @@ local transforms = asset.require('../transforms') local assetHelper = asset.require('util/asset_helper') local kernel = asset.require('../kernels').sat375 asset.require('./trail') -local labelsPath = asset.require('../saturn_globelabels').LabelsPath + +local labelsPath = asset.syncedResource({ + Name = "Saturn Labels", + Type = "HttpSynchronization", + Identifier = "saturn_labels", + Version = 1 +}) local Enceladus = { Identifier = "Enceladus", diff --git a/data/assets/scene/solarsystem/planets/saturn/enceladus/enceladus_textures.asset b/data/assets/scene/solarsystem/planets/saturn/enceladus/enceladus_textures.asset deleted file mode 100644 index 39beb256b2..0000000000 --- a/data/assets/scene/solarsystem/planets/saturn/enceladus/enceladus_textures.asset +++ /dev/null @@ -1,7 +0,0 @@ -local TexturesPath = asset.syncedResource({ - Name = "Enceladus textures", - Type = "HttpSynchronization", - Identifier = "enceladus_textures", - Version = 1 -}) -asset.export("TexturesPath", TexturesPath) diff --git a/data/assets/scene/solarsystem/planets/saturn/enceladus/layers/colorlayers/enceladus_texture.asset b/data/assets/scene/solarsystem/planets/saturn/enceladus/layers/colorlayers/enceladus_texture.asset index cb60a5f6f4..62cb627e83 100644 --- a/data/assets/scene/solarsystem/planets/saturn/enceladus/layers/colorlayers/enceladus_texture.asset +++ b/data/assets/scene/solarsystem/planets/saturn/enceladus/layers/colorlayers/enceladus_texture.asset @@ -1,6 +1,12 @@ -local texturesPath = asset.require("./../../enceladus_textures").TexturesPath local globeIdentifier = asset.require("./../../enceladus").Enceladus.Identifier +local texturesPath = asset.syncedResource({ + Name = "Enceladus textures", + Type = "HttpSynchronization", + Identifier = "enceladus_textures", + Version = 1 +}) + local layer = { Identifier = "Texture", FilePath = texturesPath .. "/enceladus.jpg", diff --git a/data/assets/scene/solarsystem/planets/saturn/hyperion/hyperion.asset b/data/assets/scene/solarsystem/planets/saturn/hyperion/hyperion.asset index 763123733a..25b4c940b2 100644 --- a/data/assets/scene/solarsystem/planets/saturn/hyperion/hyperion.asset +++ b/data/assets/scene/solarsystem/planets/saturn/hyperion/hyperion.asset @@ -2,7 +2,13 @@ local transforms = asset.require('../transforms') local assetHelper = asset.require('util/asset_helper') local kernel = asset.require('../kernels').sat375 asset.require('./trail') -local labelsPath = asset.require('../saturn_globelabels').LabelsPath + +local labelsPath = asset.syncedResource({ + Name = "Saturn Labels", + Type = "HttpSynchronization", + Identifier = "saturn_labels", + Version = 1 +}) local Hyperion = { Identifier = "Hyperion", diff --git a/data/assets/scene/solarsystem/planets/saturn/iapetus/iapetus.asset b/data/assets/scene/solarsystem/planets/saturn/iapetus/iapetus.asset index 17c3c89c4b..5be09e3359 100644 --- a/data/assets/scene/solarsystem/planets/saturn/iapetus/iapetus.asset +++ b/data/assets/scene/solarsystem/planets/saturn/iapetus/iapetus.asset @@ -2,7 +2,13 @@ local transforms = asset.require('../transforms') local assetHelper = asset.require('util/asset_helper') local kernel = asset.require('../kernels').sat375 asset.require('./trail') -local labelsPath = asset.require('../saturn_globelabels').LabelsPath + +local labelsPath = asset.syncedResource({ + Name = "Saturn Labels", + Type = "HttpSynchronization", + Identifier = "saturn_labels", + Version = 1 +}) local Iapetus = { Identifier = "Iapetus", diff --git a/data/assets/scene/solarsystem/planets/saturn/iapetus/iapetus_textures.asset b/data/assets/scene/solarsystem/planets/saturn/iapetus/iapetus_textures.asset deleted file mode 100644 index f1446cdb56..0000000000 --- a/data/assets/scene/solarsystem/planets/saturn/iapetus/iapetus_textures.asset +++ /dev/null @@ -1,7 +0,0 @@ -local TexturesPath = asset.syncedResource({ - Name = "Iapetus textures", - Type = "HttpSynchronization", - Identifier = "iapetus_textures", - Version = 1 -}) -asset.export("TexturesPath", TexturesPath) diff --git a/data/assets/scene/solarsystem/planets/saturn/iapetus/layers/colorlayers/iapetus_texture.asset b/data/assets/scene/solarsystem/planets/saturn/iapetus/layers/colorlayers/iapetus_texture.asset index d90c500f5f..454909fcff 100644 --- a/data/assets/scene/solarsystem/planets/saturn/iapetus/layers/colorlayers/iapetus_texture.asset +++ b/data/assets/scene/solarsystem/planets/saturn/iapetus/layers/colorlayers/iapetus_texture.asset @@ -1,6 +1,12 @@ -local texturesPath = asset.require("./../../iapetus_textures").TexturesPath local globeIdentifier = asset.require("./../../iapetus").Iapetus.Identifier +local texturesPath = asset.syncedResource({ + Name = "Iapetus textures", + Type = "HttpSynchronization", + Identifier = "iapetus_textures", + Version = 1 +}) + local layer = { Identifier = "Texture", FilePath = texturesPath .. "/iapetus.jpg", diff --git a/data/assets/scene/solarsystem/planets/saturn/layers/colorlayers/saturn_texture.asset b/data/assets/scene/solarsystem/planets/saturn/layers/colorlayers/saturn_texture.asset index 8f69e96224..7262a13bac 100644 --- a/data/assets/scene/solarsystem/planets/saturn/layers/colorlayers/saturn_texture.asset +++ b/data/assets/scene/solarsystem/planets/saturn/layers/colorlayers/saturn_texture.asset @@ -1,6 +1,12 @@ -local texturesPath = asset.require("./../../saturn_textures").TexturesPath local globeIdentifier = asset.require("./../../saturn").Saturn.Identifier +local texturesPath = asset.syncedResource({ + Type = "HttpSynchronization", + Name = "Saturn textures", + Identifier = "saturn_textures", + Version = 4 +}) + local layer = { Identifier = "Texture", FilePath = texturesPath .. "/saturn.jpg", diff --git a/data/assets/scene/solarsystem/planets/saturn/mimas/layers/colorlayers/mimas_texture.asset b/data/assets/scene/solarsystem/planets/saturn/mimas/layers/colorlayers/mimas_texture.asset index d16f67c799..7873d18ded 100644 --- a/data/assets/scene/solarsystem/planets/saturn/mimas/layers/colorlayers/mimas_texture.asset +++ b/data/assets/scene/solarsystem/planets/saturn/mimas/layers/colorlayers/mimas_texture.asset @@ -1,6 +1,12 @@ -local texturesPath = asset.require("./../../mimas_textures").TexturesPath local globeIdentifier = asset.require("./../../mimas").Mimas.Identifier +local texturesPath = asset.syncedResource({ + Name = "Mimas textures", + Type = "HttpSynchronization", + Identifier = "mimas_textures", + Version = 1 +}) + local layer = { Identifier = "Texture", FilePath = texturesPath .. "/mimas.jpg", diff --git a/data/assets/scene/solarsystem/planets/saturn/mimas/mimas.asset b/data/assets/scene/solarsystem/planets/saturn/mimas/mimas.asset index a54c8bc981..4726d070bc 100644 --- a/data/assets/scene/solarsystem/planets/saturn/mimas/mimas.asset +++ b/data/assets/scene/solarsystem/planets/saturn/mimas/mimas.asset @@ -2,7 +2,13 @@ local transforms = asset.require('../transforms') local assetHelper = asset.require('util/asset_helper') local kernel = asset.require('../kernels').sat375 asset.require('./trail') -local labelsPath = asset.require('../saturn_globelabels').LabelsPath + +local labelsPath = asset.syncedResource({ + Name = "Saturn Labels", + Type = "HttpSynchronization", + Identifier = "saturn_labels", + Version = 1 +}) local Mimas = { Identifier = "Mimas", diff --git a/data/assets/scene/solarsystem/planets/saturn/mimas/mimas_textures.asset b/data/assets/scene/solarsystem/planets/saturn/mimas/mimas_textures.asset deleted file mode 100644 index 9f38f20984..0000000000 --- a/data/assets/scene/solarsystem/planets/saturn/mimas/mimas_textures.asset +++ /dev/null @@ -1,7 +0,0 @@ -local TexturesPath = asset.syncedResource({ - Name = "Mimas textures", - Type = "HttpSynchronization", - Identifier = "mimas_textures", - Version = 1 -}) -asset.export("TexturesPath", TexturesPath) diff --git a/data/assets/scene/solarsystem/planets/saturn/minor/gallic_group.asset b/data/assets/scene/solarsystem/planets/saturn/minor/gallic_group.asset index a08b0fc03e..f67d555de2 100644 --- a/data/assets/scene/solarsystem/planets/saturn/minor/gallic_group.asset +++ b/data/assets/scene/solarsystem/planets/saturn/minor/gallic_group.asset @@ -7,7 +7,7 @@ local kernel = asset.require('../kernels').sat368 local parentIdentifier = transforms.SaturnBarycenter.Identifier local parentSpice = "SATURN BARYCENTER" -local tags = { "moon_solarSystem", "moon_giants", "moon_saturn", "moon_gallic" } +local tags = { "moon_solarSystem", "moon_giants", "moon_saturn", "moon_gallic", "moon_minor" } local trailColor = { 0.5, 0.3, 0.3 } local trailTags = { "moonTrail_solarSystem", diff --git a/data/assets/scene/solarsystem/planets/saturn/minor/inuit_group.asset b/data/assets/scene/solarsystem/planets/saturn/minor/inuit_group.asset index 9fd0637b38..ecdf1b457a 100644 --- a/data/assets/scene/solarsystem/planets/saturn/minor/inuit_group.asset +++ b/data/assets/scene/solarsystem/planets/saturn/minor/inuit_group.asset @@ -7,7 +7,7 @@ local kernel = asset.require('../kernels').sat368 local parentIdentifier = transforms.SaturnBarycenter.Identifier local parentSpice = "SATURN BARYCENTER" -local tags = { "moon_solarSystem", "moon_giants", "moon_saturn", "moon_inuit" } +local tags = { "moon_solarSystem", "moon_giants", "moon_saturn", "moon_inuit", "moon_minor" } local trailColor = { 0.5, 0.3, 0.3 } local trailTags = { "moonTrail_solarSystem", diff --git a/data/assets/scene/solarsystem/planets/saturn/minor/norse_group.asset b/data/assets/scene/solarsystem/planets/saturn/minor/norse_group.asset index 4cad89e12f..4eb04bb6cc 100644 --- a/data/assets/scene/solarsystem/planets/saturn/minor/norse_group.asset +++ b/data/assets/scene/solarsystem/planets/saturn/minor/norse_group.asset @@ -9,7 +9,7 @@ local kernel375 = kernels.sat375 local parentIdentifier = transforms.SaturnBarycenter.Identifier local parentSpice = "SATURN BARYCENTER" -local tags = { "moon_solarSystem", "moon_giants", "moon_saturn", "moon_norse" } +local tags = { "moon_solarSystem", "moon_giants", "moon_saturn", "moon_norse", "moon_minor" } local trailColor = { 0.5, 0.3, 0.3 } local trailTags = { "moonTrail_solarSystem", diff --git a/data/assets/scene/solarsystem/planets/saturn/minor/other_group.asset b/data/assets/scene/solarsystem/planets/saturn/minor/other_group.asset index 6ceaa4a9d1..1f7654e236 100644 --- a/data/assets/scene/solarsystem/planets/saturn/minor/other_group.asset +++ b/data/assets/scene/solarsystem/planets/saturn/minor/other_group.asset @@ -9,7 +9,7 @@ local kernel393 = kernels.sat393 local parentIdentifier = transforms.SaturnBarycenter.Identifier local parentSpice = "SATURN BARYCENTER" -local tags = { "moon_solarSystem", "moon_giants", "moon_saturn", "moon_other" } +local tags = { "moon_solarSystem", "moon_giants", "moon_saturn", "moon_other", "moon_minor" } local trailColor = { 0.5, 0.3, 0.3 } local trailTags = { "moonTrail_solarSystem", diff --git a/data/assets/scene/solarsystem/planets/saturn/rhea/layers/colorlayers/rhea_texture.asset b/data/assets/scene/solarsystem/planets/saturn/rhea/layers/colorlayers/rhea_texture.asset index dd36ba9160..c7899722cf 100644 --- a/data/assets/scene/solarsystem/planets/saturn/rhea/layers/colorlayers/rhea_texture.asset +++ b/data/assets/scene/solarsystem/planets/saturn/rhea/layers/colorlayers/rhea_texture.asset @@ -1,6 +1,12 @@ -local texturesPath = asset.require("./../../rhea_textures").TexturesPath local globeIdentifier = asset.require("./../../rhea").Rhea.Identifier +local texturesPath = asset.syncedResource({ + Name = "Rhea textures", + Type = "HttpSynchronization", + Identifier = "rhea_textures", + Version = 1 +}) + local layer = { Identifier = "Texture", FilePath = texturesPath .. "/rhea.jpg", diff --git a/data/assets/scene/solarsystem/planets/saturn/rhea/rhea.asset b/data/assets/scene/solarsystem/planets/saturn/rhea/rhea.asset index 48926b0140..cdfb4a9038 100644 --- a/data/assets/scene/solarsystem/planets/saturn/rhea/rhea.asset +++ b/data/assets/scene/solarsystem/planets/saturn/rhea/rhea.asset @@ -2,7 +2,13 @@ local transforms = asset.require('../transforms') local assetHelper = asset.require('util/asset_helper') local kernel = asset.require('../kernels').sat375 asset.require('./trail') -local labelsPath = asset.require('../saturn_globelabels').LabelsPath + +local labelsPath = asset.syncedResource({ + Name = "Saturn Labels", + Type = "HttpSynchronization", + Identifier = "saturn_labels", + Version = 1 +}) local Rhea = { Identifier = "Rhea", diff --git a/data/assets/scene/solarsystem/planets/saturn/rhea/rhea_textures.asset b/data/assets/scene/solarsystem/planets/saturn/rhea/rhea_textures.asset deleted file mode 100644 index 659a127fdc..0000000000 --- a/data/assets/scene/solarsystem/planets/saturn/rhea/rhea_textures.asset +++ /dev/null @@ -1,7 +0,0 @@ -local TexturesPath = asset.syncedResource({ - Name = "Rhea textures", - Type = "HttpSynchronization", - Identifier = "rhea_textures", - Version = 1 -}) -asset.export("TexturesPath", TexturesPath) diff --git a/data/assets/scene/solarsystem/planets/saturn/saturn.asset b/data/assets/scene/solarsystem/planets/saturn/saturn.asset index 77d44acf2a..de19cb60eb 100644 --- a/data/assets/scene/solarsystem/planets/saturn/saturn.asset +++ b/data/assets/scene/solarsystem/planets/saturn/saturn.asset @@ -3,7 +3,12 @@ local assetHelper = asset.require('util/asset_helper') asset.require("spice/base") asset.require('./trail') -local texturesPath = asset.require("./saturn_textures").TexturesPath +local texturesPath = asset.syncedResource({ + Type = "HttpSynchronization", + Name = "Saturn textures", + Identifier = "saturn_textures", + Version = 4 +}) local Saturn = { Identifier = "Saturn", diff --git a/data/assets/scene/solarsystem/planets/saturn/saturn_globelabels.asset b/data/assets/scene/solarsystem/planets/saturn/saturn_globelabels.asset deleted file mode 100644 index be23aa78c1..0000000000 --- a/data/assets/scene/solarsystem/planets/saturn/saturn_globelabels.asset +++ /dev/null @@ -1,7 +0,0 @@ -local LabelsPath = asset.syncedResource({ - Name = "Saturn Labels", - Type = "HttpSynchronization", - Identifier = "saturn_labels", - Version = 1 -}) -asset.export("LabelsPath", LabelsPath) diff --git a/data/assets/scene/solarsystem/planets/saturn/tethys/layers/colorlayers/tethys_texture.asset b/data/assets/scene/solarsystem/planets/saturn/tethys/layers/colorlayers/tethys_texture.asset index c8a546bc6c..da20584fcf 100644 --- a/data/assets/scene/solarsystem/planets/saturn/tethys/layers/colorlayers/tethys_texture.asset +++ b/data/assets/scene/solarsystem/planets/saturn/tethys/layers/colorlayers/tethys_texture.asset @@ -1,6 +1,12 @@ -local texturesPath = asset.require("./../../tethys_textures").TexturesPath local globeIdentifier = asset.require("./../../tethys").Tethys.Identifier +local texturesPath = asset.syncedResource({ + Name = "Tethys textures", + Type = "HttpSynchronization", + Identifier = "tethys_textures", + Version = 1 +}) + local layer = { Identifier = "Texture", FilePath = texturesPath .. "/tethys.jpg", diff --git a/data/assets/scene/solarsystem/planets/saturn/tethys/tethys.asset b/data/assets/scene/solarsystem/planets/saturn/tethys/tethys.asset index a87015d37d..3bc7f43987 100644 --- a/data/assets/scene/solarsystem/planets/saturn/tethys/tethys.asset +++ b/data/assets/scene/solarsystem/planets/saturn/tethys/tethys.asset @@ -2,7 +2,13 @@ local transforms = asset.require('../transforms') local assetHelper = asset.require('util/asset_helper') local kernel = asset.require('../kernels').sat375 asset.require('./trail') -local labelsPath = asset.require('../saturn_globelabels').LabelsPath + +local labelsPath = asset.syncedResource({ + Name = "Saturn Labels", + Type = "HttpSynchronization", + Identifier = "saturn_labels", + Version = 1 +}) local Tethys = { Identifier = "Tethys", diff --git a/data/assets/scene/solarsystem/planets/saturn/tethys/tethys_textures.asset b/data/assets/scene/solarsystem/planets/saturn/tethys/tethys_textures.asset deleted file mode 100644 index 804f577921..0000000000 --- a/data/assets/scene/solarsystem/planets/saturn/tethys/tethys_textures.asset +++ /dev/null @@ -1,7 +0,0 @@ -local TexturesPath = asset.syncedResource({ - Name = "Tethys textures", - Type = "HttpSynchronization", - Identifier = "tethys_textures", - Version = 1 -}) -asset.export("TexturesPath", TexturesPath) diff --git a/data/assets/scene/solarsystem/planets/saturn/titan/layers/colorlayers/cassini_iss_global_mosaic_4km_local.asset b/data/assets/scene/solarsystem/planets/saturn/titan/layers/colorlayers/cassini_iss_global_mosaic_4km_local.asset index 0356317b58..fe470aff6c 100644 --- a/data/assets/scene/solarsystem/planets/saturn/titan/layers/colorlayers/cassini_iss_global_mosaic_4km_local.asset +++ b/data/assets/scene/solarsystem/planets/saturn/titan/layers/colorlayers/cassini_iss_global_mosaic_4km_local.asset @@ -1,6 +1,12 @@ -local texturesPath = asset.require("./../../titan_textures").TexturesPath local globeIdentifier = asset.require("./../../titan").Titan.Identifier +local texturesPath = asset.syncedResource({ + Type = "HttpSynchronization", + Name = "Titan textures", + Identifier = "titan_textures", + Version = 2 +}) + local layer = { Identifier = "Cassini_ISS_Global_Mosaic_4km_Local", Name = "Cassini ISS Global Mosaic 4km", diff --git a/data/assets/scene/solarsystem/planets/saturn/titan/titan.asset b/data/assets/scene/solarsystem/planets/saturn/titan/titan.asset index 25e701052e..a68538c64b 100644 --- a/data/assets/scene/solarsystem/planets/saturn/titan/titan.asset +++ b/data/assets/scene/solarsystem/planets/saturn/titan/titan.asset @@ -2,7 +2,13 @@ local transforms = asset.require('../transforms') local assetHelper = asset.require('util/asset_helper') local kernel = asset.require('../kernels').sat375 asset.require('./trail') -local labelsPath = asset.require('../saturn_globelabels').LabelsPath + +local labelsPath = asset.syncedResource({ + Name = "Saturn Labels", + Type = "HttpSynchronization", + Identifier = "saturn_labels", + Version = 1 +}) local Titan = { Identifier = "Titan", diff --git a/data/assets/scene/solarsystem/planets/saturn/titan/titan_textures.asset b/data/assets/scene/solarsystem/planets/saturn/titan/titan_textures.asset deleted file mode 100644 index d64bdd04f3..0000000000 --- a/data/assets/scene/solarsystem/planets/saturn/titan/titan_textures.asset +++ /dev/null @@ -1,7 +0,0 @@ -local TexturesPath = asset.syncedResource({ - Type = "HttpSynchronization", - Name = "Titan textures", - Identifier = "titan_textures", - Version = 2 -}) -asset.export("TexturesPath", TexturesPath) diff --git a/data/assets/scene/solarsystem/planets/uranus/inner_moons.asset b/data/assets/scene/solarsystem/planets/uranus/inner_moons.asset index 662fde8b7b..54ff39f0cb 100644 --- a/data/assets/scene/solarsystem/planets/uranus/inner_moons.asset +++ b/data/assets/scene/solarsystem/planets/uranus/inner_moons.asset @@ -7,7 +7,7 @@ local kernel = asset.require('./kernels').ura091 local parentIdentifier = transforms.UranusBarycenter.Identifier local parentSpice = "URANUS BARYCENTER" -local tags = { "moon_solarSystem", "moon_giants", "moon_uranus", "moon_inner" } +local tags = { "moon_solarSystem", "moon_giants", "moon_uranus", "moon_inner", "moon_minor" } local trailColor = { 0.60, 0.65, 0.84 } local trailTags = { diff --git a/data/assets/scene/solarsystem/planets/uranus/irregular_prograde_moons.asset b/data/assets/scene/solarsystem/planets/uranus/irregular_prograde_moons.asset index a1d36a6a3f..97b359c59a 100644 --- a/data/assets/scene/solarsystem/planets/uranus/irregular_prograde_moons.asset +++ b/data/assets/scene/solarsystem/planets/uranus/irregular_prograde_moons.asset @@ -7,7 +7,7 @@ local kernel = asset.require('./kernels').ura112 local parentIdentifier = transforms.UranusBarycenter.Identifier local parentSpice = "URANUS BARYCENTER" -local tags = { "moon_solarSystem", "moon_giants", "moon_uranus", "moon_irregular_prograde" } +local tags = { "moon_solarSystem", "moon_giants", "moon_uranus", "moon_irregular_prograde", "moon_minor" } local trailColor = { 0.60, 0.65, 0.84 } local trailTags = { "moonTrail_solarSystem", diff --git a/data/assets/scene/solarsystem/planets/uranus/irregular_retrograde_moons.asset b/data/assets/scene/solarsystem/planets/uranus/irregular_retrograde_moons.asset index 11545d7f2d..c0d7b8efd9 100644 --- a/data/assets/scene/solarsystem/planets/uranus/irregular_retrograde_moons.asset +++ b/data/assets/scene/solarsystem/planets/uranus/irregular_retrograde_moons.asset @@ -7,7 +7,7 @@ local kernel = asset.require('./kernels').ura112 local parentIdentifier = transforms.UranusBarycenter.Identifier local parentSpice = "URANUS BARYCENTER" -local tags = { "moon_solarSystem", "moon_giants", "moon_uranus", "moon_irregular_retrograde" } +local tags = { "moon_solarSystem", "moon_giants", "moon_uranus", "moon_irregular_retrograde", "moon_minor" } local trailColor = { 0.60, 0.65, 0.84 } local trailTags = { "moonTrail_solarSystem", diff --git a/data/assets/scene/solarsystem/planets/uranus/layers/colorlayers/uranus_texture.asset b/data/assets/scene/solarsystem/planets/uranus/layers/colorlayers/uranus_texture.asset index bafffffe9c..b1c7636a47 100644 --- a/data/assets/scene/solarsystem/planets/uranus/layers/colorlayers/uranus_texture.asset +++ b/data/assets/scene/solarsystem/planets/uranus/layers/colorlayers/uranus_texture.asset @@ -1,6 +1,12 @@ -local texturesPath = asset.require("./../../uranus_textures").TexturesPath local globeIdentifier = asset.require("./../../uranus").Uranus.Identifier +local texturesPath = asset.syncedResource({ + Name = "Uranus Textures", + Type = "HttpSynchronization", + Identifier = "uranus_textures", + Version = 1 +}) + local layer = { Identifier = "Texture", FilePath = texturesPath .. "/uranus.jpg", diff --git a/data/assets/scene/solarsystem/planets/uranus/uranus_textures.asset b/data/assets/scene/solarsystem/planets/uranus/uranus_textures.asset deleted file mode 100644 index d7200697b6..0000000000 --- a/data/assets/scene/solarsystem/planets/uranus/uranus_textures.asset +++ /dev/null @@ -1,7 +0,0 @@ -local TexturesPath = asset.syncedResource({ - Name = "Uranus Textures", - Type = "HttpSynchronization", - Identifier = "uranus_textures", - Version = 1 -}) -asset.export("TexturesPath", TexturesPath) diff --git a/data/assets/scene/solarsystem/planets/venus/atmosphere.asset b/data/assets/scene/solarsystem/planets/venus/atmosphere.asset index a8d28ff7e4..7e39382692 100644 --- a/data/assets/scene/solarsystem/planets/venus/atmosphere.asset +++ b/data/assets/scene/solarsystem/planets/venus/atmosphere.asset @@ -42,7 +42,6 @@ local Atmosphere = { G = 0.85 }, Debug = { - -- PreCalculatedTextureScale is a float from 1.0 to N, with N > 0.0 and N in Naturals (i.e., 1, 2, 3, 4, 5....) PreCalculatedTextureScale = 1.0, SaveCalculatedTextures = false } diff --git a/data/assets/scene/solarsystem/planets/venus/layers/colorlayers/venus_texture.asset b/data/assets/scene/solarsystem/planets/venus/layers/colorlayers/venus_texture.asset index d9f40745c6..77fc18f747 100644 --- a/data/assets/scene/solarsystem/planets/venus/layers/colorlayers/venus_texture.asset +++ b/data/assets/scene/solarsystem/planets/venus/layers/colorlayers/venus_texture.asset @@ -1,6 +1,12 @@ -local texturesPath = asset.require("./../../venus_textures").TexturesPath local globeIdentifier = asset.require("./../../venus").Venus.Identifier +local texturesPath = asset.syncedResource({ + Name = "Venus Textures", + Type = "HttpSynchronization", + Identifier = "venus_textures", + Version = 1 +}) + local layer = { Identifier = "Texture", FilePath = texturesPath .. "/venus.jpg", diff --git a/data/assets/scene/solarsystem/planets/venus/venus.asset b/data/assets/scene/solarsystem/planets/venus/venus.asset index 062f58fade..b3cd407a63 100644 --- a/data/assets/scene/solarsystem/planets/venus/venus.asset +++ b/data/assets/scene/solarsystem/planets/venus/venus.asset @@ -2,7 +2,13 @@ local assetHelper = asset.require('util/asset_helper') local transforms = asset.require('./transforms') asset.require("spice/base") asset.require('./trail') -local labelsPath = asset.require('./venus_globelabels').LabelsPath + +local labelsPath = asset.syncedResource({ + Name = "Venus Labels", + Type = "HttpSynchronization", + Identifier = "venus_labels", + Version = 1 +}) local Venus = { Identifier = "Venus", diff --git a/data/assets/scene/solarsystem/planets/venus/venus_globelabels.asset b/data/assets/scene/solarsystem/planets/venus/venus_globelabels.asset deleted file mode 100644 index e38e2ea3f8..0000000000 --- a/data/assets/scene/solarsystem/planets/venus/venus_globelabels.asset +++ /dev/null @@ -1,7 +0,0 @@ -local LabelsPath = asset.syncedResource({ - Name = "Venus Labels", - Type = "HttpSynchronization", - Identifier = "venus_labels", - Version = 1 -}) -asset.export("LabelsPath", LabelsPath) diff --git a/data/assets/scene/solarsystem/planets/venus/venus_textures.asset b/data/assets/scene/solarsystem/planets/venus/venus_textures.asset deleted file mode 100644 index 38442cb484..0000000000 --- a/data/assets/scene/solarsystem/planets/venus/venus_textures.asset +++ /dev/null @@ -1,7 +0,0 @@ -local TexturesPath = asset.syncedResource({ - Name = "Venus Textures", - Type = "HttpSynchronization", - Identifier = "venus_textures", - Version = 1 -}) -asset.export("TexturesPath", TexturesPath) diff --git a/data/assets/scene/solarsystem/sun/EUV_layer.asset b/data/assets/scene/solarsystem/sun/EUV_layer.asset new file mode 100644 index 0000000000..92a7e3abb4 --- /dev/null +++ b/data/assets/scene/solarsystem/sun/EUV_layer.asset @@ -0,0 +1,57 @@ +asset.require("spice/base") +local assetHelper = asset.require("util/asset_helper") +local propertyHelper = asset.require('util/property_helper') +local transforms = asset.require("./transforms") + +local textureSourcePath = asset.syncedResource({ + Type = "HttpSynchronization", + Name = "euv_textures_bastille_event", + Identifier = "euv_textures_bastille_event", + Version = 1 +}) + +local EUVLayer = { + Identifier = "EUV-Layer-bastille-day-2000", + Parent = transforms.SunIAU.Identifier, + Renderable = { + Type = "RenderableTimeVaryingSphere", + Size = 6.96E8, -- Slightly bigger than the sun renderable, + Enabled = true, + TextureSource = textureSourcePath, + Opacity = 1, + Segments = 132 + }, + GUI = { + Name = "EUV Layer", + Path = "/Solar System/Sun", + Description = "Texture sequence of an extreme ultra violet (EUV) simulation, during the CME. This asset contains data from 2000-07-14 08:38 to 2000-07-14 19:48" + } +} + +local toggle_EUV_layer = { + Identifier = "euv_layer.toggle_EUV", + Name = "Toggle EUV Layer", + Command = propertyHelper.invert("Scene.EUV-Layer-bastille-day-2000.Renderable.Enabled"), + Documentation = "Toggle EUV layer of sun", + GuiPath = "/Bastille-Day 2000", + IsLocal = false +} + +asset.onInitialize(function () + openspace.action.registerAction(toggle_EUV_layer) +end) +asset.onDeinitialize(function () + openspace.action.removeAction(toggle_EUV_layer.Identifier) +end) +assetHelper.registerSceneGraphNodesAndExport(asset, { EUVLayer }) + +asset.meta = { + Name = "Predictive Science Inc. EUV texture sequence Bastille Days", + Version = "1.0", + Description = [[Texture sequence of an extreme ultraviolet (EUV) simulation during, + the CME]], + Author = "CCMC, OpenSpace team", + URL = "https://dx.doi.org/10.3847/1538-4357/aab36d", + License = "CC-BY", + Identifier = {"EUV-Layer-bastille-day-2000"} +} diff --git a/data/assets/scene/solarsystem/sun/default_layers.asset b/data/assets/scene/solarsystem/sun/default_layers.asset index 0b9ded96b0..5d0718e902 100644 --- a/data/assets/scene/solarsystem/sun/default_layers.asset +++ b/data/assets/scene/solarsystem/sun/default_layers.asset @@ -3,8 +3,8 @@ local colorLayersPath = "./layers/colorlayers" local colorLayer = asset.require(colorLayersPath .. "/sun_texture") -- Set enabled layers (temporary solution) --- @TODO: do this using a boolean that's passed to the 'asset.require' instead -asset.onInitialize(function () +-- @TODO: do this using a boolean that's passed to the 'asset.require' instead +asset.onInitialize(function () openspace.setPropertyValueSingle("Scene.Sun.Renderable.Layers.ColorLayers." .. colorLayer.layer.Identifier .. ".Enabled", true) end) diff --git a/data/assets/scene/solarsystem/sun/glare.asset b/data/assets/scene/solarsystem/sun/glare.asset index a45d80dd82..6566d245a3 100644 --- a/data/assets/scene/solarsystem/sun/glare.asset +++ b/data/assets/scene/solarsystem/sun/glare.asset @@ -1,9 +1,14 @@ local assetHelper = asset.require("util/asset_helper") local transforms = asset.require("./transforms") -local textures = asset.require('./sun_textures').TexturesPath asset.require("spice/base") +local textures = asset.syncedResource({ + Type = "HttpSynchronization", + Name = "Sun textures", + Identifier = "sun_textures", + Version = 4 +}) local SunGlare = { Identifier = "SunGlare", diff --git a/data/assets/scene/solarsystem/sun/kernels/HEEQ180.tf b/data/assets/scene/solarsystem/sun/kernels/HEEQ180.tf new file mode 100644 index 0000000000..4106801ce9 --- /dev/null +++ b/data/assets/scene/solarsystem/sun/kernels/HEEQ180.tf @@ -0,0 +1,41 @@ +\begintext + +Heliocentric Earth Equatorial (HEEQ+180) Frame +Used by the BATSRUS model +This Kernel's ID is not a valid ID! + Definition of the Heliocentric Earth Equatorial frame: + + All vectors are geometric: no aberration corrections are + used. + + The solar rotation axis is the primary vector: the Z axis points + in the solar north direction. + + The position of the sun relative to the earth is the secondary + vector: the X axis is the component of this position vector + orthogonal to the Z axis. + + The Y axis is Z cross X, completing the right-handed + reference frame. + +\begindata + + FRAME_HEEQ180 = 6666666 + FRAME_6666666_NAME = 'HEEQ180' + FRAME_6666666_CLASS = 5 + FRAME_6666666_CLASS_ID = 6666666 + FRAME_6666666_CENTER = 10 + FRAME_6666666_RELATIVE = 'J2000' + FRAME_6666666_DEF_STYLE = 'PARAMETERIZED' + FRAME_6666666_FAMILY = 'TWO-VECTOR' + FRAME_6666666_PRI_AXIS = 'Z' + FRAME_6666666_PRI_VECTOR_DEF = 'CONSTANT' + FRAME_6666666_PRI_FRAME = 'IAU_SUN' + FRAME_6666666_PRI_SPEC = 'RECTANGULAR' + FRAME_6666666_PRI_VECTOR = ( 0, 0, 1 ) + FRAME_6666666_SEC_AXIS = 'X' + FRAME_6666666_SEC_VECTOR_DEF = 'OBSERVER_TARGET_POSITION' + FRAME_6666666_SEC_OBSERVER = 'EARTH' + FRAME_6666666_SEC_TARGET = 'SUN' + FRAME_6666666_SEC_ABCORR = 'NONE' + FRAME_6666666_SEC_FRAME = 'IAU_SUN' diff --git a/data/assets/scene/solarsystem/sun/layers/colorlayers/sun_texture.asset b/data/assets/scene/solarsystem/sun/layers/colorlayers/sun_texture.asset index 3a37a2a610..557d57ff06 100644 --- a/data/assets/scene/solarsystem/sun/layers/colorlayers/sun_texture.asset +++ b/data/assets/scene/solarsystem/sun/layers/colorlayers/sun_texture.asset @@ -1,6 +1,13 @@ -local texturesPath = asset.require("./../../sun_textures").TexturesPath local globeIdentifier = asset.require("./../../sun").Sun.Identifier + +local texturesPath = asset.syncedResource({ + Type = "HttpSynchronization", + Name = "Sun textures", + Identifier = "sun_textures", + Version = 4 +}) + local layer = { Identifier = "Texture", FilePath = texturesPath .. "/sun.jpg", diff --git a/data/assets/scene/solarsystem/sun/marker.asset b/data/assets/scene/solarsystem/sun/marker.asset index 1c6648c2eb..43d2b9b42b 100644 --- a/data/assets/scene/solarsystem/sun/marker.asset +++ b/data/assets/scene/solarsystem/sun/marker.asset @@ -1,9 +1,14 @@ local assetHelper = asset.require("util/asset_helper") local transforms = asset.require("./transforms") -local textures = asset.require('./sun_textures').TexturesPath asset.require("spice/base") +local textures = asset.syncedResource({ + Type = "HttpSynchronization", + Name = "Sun textures", + Identifier = "sun_textures", + Version = 4 +}) local SunMarker = { Identifier = "SunMarker", diff --git a/data/assets/scene/solarsystem/sun/sun_textures.asset b/data/assets/scene/solarsystem/sun/sun_textures.asset deleted file mode 100644 index fd698e1aea..0000000000 --- a/data/assets/scene/solarsystem/sun/sun_textures.asset +++ /dev/null @@ -1,18 +0,0 @@ -local TexturesPath = asset.syncedResource({ - Type = "HttpSynchronization", - Name = "Sun textures", - Identifier = "sun_textures", - Version = 4 -}) - -asset.export("TexturesPath", TexturesPath) - - -asset.meta = { - Name = "Sun Textures", - Version = "4.0", - Description = [[ Default Sun textures]], - Author = "OpenSpace Team", - URL = "http://openspaceproject.com", - License = "MIT license" -} diff --git a/data/assets/scene/solarsystem/sun/transforms.asset b/data/assets/scene/solarsystem/sun/transforms.asset index 29ab4120b8..952b9e8515 100644 --- a/data/assets/scene/solarsystem/sun/transforms.asset +++ b/data/assets/scene/solarsystem/sun/transforms.asset @@ -20,6 +20,24 @@ local SolarSystemBarycenter = { } } +local SunCenter = { + Identifier = "SunCenter", + Parent = SolarSystemBarycenter.Identifier, + Transform = { + Translation = { + Type = "SpiceTranslation", + Target = "SUN", + Observer = "SSB" + } + }, + GUI = { + Name = "SUN Center", + Path = "/Solar System/Sun", + Description = [[Spice frame for the Sun]], + Hidden = true + } +} + -- Spice frame for the Sun local SunIAU = { Identifier = "SunIAU", @@ -67,14 +85,14 @@ local SunECLIPJ2000 = { } } -assetHelper.registerSceneGraphNodesAndExport(asset, { SolarSystemBarycenter, SunIAU, SunECLIPJ2000 }) +assetHelper.registerSceneGraphNodesAndExport(asset, { SolarSystemBarycenter, SunCenter, SunIAU, SunECLIPJ2000 }) asset.meta = { Name = "Sun Transforms", Version = "1.0", Description = [[ Sun transforms: Solar System Barycenter, SUN IAU and - SUN J2000]], + SUN J2000]], Author = "OpenSpace Team", URL = "http://openspaceproject.com", License = "MIT license", diff --git a/data/assets/scene/solarsystem/sun/transforms_heliosphere.asset b/data/assets/scene/solarsystem/sun/transforms_heliosphere.asset new file mode 100644 index 0000000000..7262083c83 --- /dev/null +++ b/data/assets/scene/solarsystem/sun/transforms_heliosphere.asset @@ -0,0 +1,39 @@ +local assetHelper = asset.require("util/asset_helper") +local sunTransforms = asset.require('scene/solarsystem/sun/transforms') +asset.require("spice/base") +local HEEQ180Kernel = asset.localResource("./kernels/HEEQ180.tf") + +local HEEQ180ReferenceFrame = { + Identifier = "HEEQ180ReferenceFrame", + -- The HEEQ180 reference frame should have Sun_IAU as parent + -- instead of Solar center, however the Sun_IAU adds + -- an unwanted rotation which is difficult to cancel out + -- since it is using SpiceRotation. Sun center + -- is used instead. + Parent = sunTransforms.SunCenter.Identifier, + Transform = { + Rotation = { + Type = "SpiceRotation", + SourceFrame = "HEEQ180", + DestinationFrame = "GALACTIC", + Kernels = HEEQ180Kernel + }, + }, + GUI = { + Name = "HEEQ180 Reference Frame", + Path = "/Solar System/Sun", + Hidden = true + } +} + +assetHelper.registerSceneGraphNodesAndExport(asset, { HEEQ180ReferenceFrame }) + +asset.meta = { + Name = "Sun Transform, HEEQ180", + Version = "1.0", + Description = "Sun transform: HEEQ180", + Author = "CCMC", + URL = "http://openspaceproject.com", + License = "MIT license", + Identifiers = {"HEEQ180ReferenceFrame"} +} diff --git a/data/assets/sync/everything.asset b/data/assets/sync/everything.asset index 976e7d3027..3f7806f4b9 100644 --- a/data/assets/sync/everything.asset +++ b/data/assets/sync/everything.asset @@ -1,6 +1,6 @@ --- Please note that this scene/asset is not meant to be included anywhere directly. --- Rather it is used in the Sync application to synchronize the entire asset folder --- without needing manual adaption +-- Please note that this scene/asset is not meant to be included anywhere directly and +-- OpenSpace will probably fail as soon as it gets to the initialization step, but at +-- least the synchronization will all work local assetHelper = asset.require('../util/asset_helper') diff --git a/data/assets/util/circle.asset b/data/assets/util/circle.asset deleted file mode 100644 index 4717b87883..0000000000 --- a/data/assets/util/circle.asset +++ /dev/null @@ -1,8 +0,0 @@ -local circle = asset.syncedResource({ - Name = "Circle", - Type = "HttpSynchronization", - Identifier = "circle_image", - Version = 1 -}) - -asset.export('circle', circle) diff --git a/data/assets/util/debug_helper.asset b/data/assets/util/debug_helper.asset index 6c75714d06..9b10fb04c6 100644 --- a/data/assets/util/debug_helper.asset +++ b/data/assets/util/debug_helper.asset @@ -67,7 +67,7 @@ local addCartesianAxes = function (specification) Parent = parent, Transform = { Scale = { - Type = "StaticScale", + Type = "NonUniformStaticScale", Scale = scale }, Translation = { diff --git a/data/assets/util/default_keybindings.asset b/data/assets/util/default_keybindings.asset index 05a5cdcc10..e7e771417d 100644 --- a/data/assets/util/default_keybindings.asset +++ b/data/assets/util/default_keybindings.asset @@ -1,155 +1,207 @@ -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 + + -- The take screenshot function is a bit special since we want to bind two keys to that action + openspace.bindKey("PRINT_SCREEN", take_screenshot.Identifier) end) asset.onDeinitialize(function () - sceneHelper.unbindKeys(Keybindings) -end) + openspace.clearKey("PRINT_SCREEN") -asset.export("DefaultKeybindings", Keybindings) + for _, action in ipairs(Actions) do + openspace.action.removeAction(action.Identifier) + openspace.clearKey(action.Key) + end +end) diff --git a/data/assets/util/launcher_images.asset b/data/assets/util/launcher_images.asset index 32098b0c64..d2fd2efe90 100644 --- a/data/assets/util/launcher_images.asset +++ b/data/assets/util/launcher_images.asset @@ -2,6 +2,6 @@ local DataPath = asset.syncedResource({ Name = "Launcher Images", Type = "HttpSynchronization", Identifier = "launcher_images", - Version = 1 + Version = 2 }) asset.export("DataPath", DataPath) diff --git a/data/assets/util/state_machine_helper.asset b/data/assets/util/lua_state_machine_helper.asset similarity index 87% rename from data/assets/util/state_machine_helper.asset rename to data/assets/util/lua_state_machine_helper.asset index 30f0f2ff3c..45369d01fb 100644 --- a/data/assets/util/state_machine_helper.asset +++ b/data/assets/util/lua_state_machine_helper.asset @@ -1,3 +1,8 @@ +-- Contains the required functions to create a simple Lua state machine, that can step +-- forwards and backwards through a list of states. +-- +-- A state is given as a table with a Title string, and two functions: Play and Rewind +-- (see example asset) local goToNextStateFunction = function (machine) if (machine.currentStateIndex >= #machine.states) then diff --git a/data/assets/util/scene_helper.asset b/data/assets/util/scene_helper.asset deleted file mode 100644 index 89f6c88a4c..0000000000 --- a/data/assets/util/scene_helper.asset +++ /dev/null @@ -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) diff --git a/data/assets/scene/solarsystem/planets/saturn/saturn_textures.asset b/data/assets/util/streamnodes_textures.asset similarity index 65% rename from data/assets/scene/solarsystem/planets/saturn/saturn_textures.asset rename to data/assets/util/streamnodes_textures.asset index 3f29c75b07..2c44e83e7a 100644 --- a/data/assets/scene/solarsystem/planets/saturn/saturn_textures.asset +++ b/data/assets/util/streamnodes_textures.asset @@ -1,7 +1,8 @@ local TexturesPath = asset.syncedResource({ Type = "HttpSynchronization", - Name = "Saturn textures", - Identifier = "saturn_textures", + Name = "Streamnodes textures", + Identifier = "streamnodes_textures", Version = 4 }) + asset.export("TexturesPath", TexturesPath) diff --git a/data/assets/util/testing_keybindings.asset b/data/assets/util/testing_keybindings.asset index 53a94a0dc1..ce15e6687e 100644 --- a/data/assets/util/testing_keybindings.asset +++ b/data/assets/util/testing_keybindings.asset @@ -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) diff --git a/data/assets/util/webgui.asset b/data/assets/util/webgui.asset index 15195ee953..698f491ec7 100644 --- a/data/assets/util/webgui.asset +++ b/data/assets/util/webgui.asset @@ -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 = "96b88e6c760e59d143bd29da6f06011eaafce4b1" +local frontendHash = "4fe18eea379c8493dbcb2cea6798d09a85819912" local dataProvider = "data.openspaceproject.com/files/webgui" local frontend = asset.syncedResource({ diff --git a/data/openspace-horiz-logo-crop.png b/data/openspace-horiz-logo-crop.png new file mode 100644 index 0000000000..05ae6643e0 Binary files /dev/null and b/data/openspace-horiz-logo-crop.png differ diff --git a/data/profiles/apollo.profile b/data/profiles/apollo.profile index e4d0d56f37..ce3e96b213 100644 --- a/data/profiles/apollo.profile +++ b/data/profiles/apollo.profile @@ -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 } } \ No newline at end of file diff --git a/data/profiles/bastille-day.profile b/data/profiles/bastille-day.profile new file mode 100644 index 0000000000..9cdf5449a6 --- /dev/null +++ b/data/profiles/bastille-day.profile @@ -0,0 +1,208 @@ +{ + "actions": [ + { + "documentation": "Reset button to start of CME", + "gui_path": "/Bastille-Day 2000", + "identifier": "bastille-day.reset_loops", + "is_local": false, + "name": "Reset button. Start of CME, no loop", + "script": "openspace.time.setTime('2000-JUL-14 10:03:00.00');openspace.scriptScheduler.clear();" + }, + { + "documentation": "New loop: Restarts time at 10:03 and stops at 10:16, sets delta time to 2 min/ second (120 seconds/ second)", + "gui_path": "/Bastille-Day 2000", + "identifier": "bastille-day.short_loop", + "is_local": false, + "name": "Loop 10:03 - 10:16, at 2 min/ second", + "script": "openspace.scriptScheduler.clear();openspace.time.setDeltaTime(120);openspace.time.setTime('2000-JUL-14 10:03:00.00');EndtimeShortLoop = \"2000 JUL 14 10:16:00\";StarttimescriptSlowLoop = \"openspace.time.setTime('2000 JUL 14 10:03:00')\";openspace.scriptScheduler.loadScheduledScript(EndtimeShortLoop, StarttimescriptSlowLoop);" + }, + { + "documentation": "New loop: Restarts time at 10:03 and stops at 11:00, delta time to 4 min/ second (240 seconds/ second)", + "gui_path": "/Bastille-Day 2000", + "identifier": "bastille-day.standard_loop", + "is_local": false, + "name": "Loop 10:03 - 11:00, at 4 min/ second", + "script": "StarttimescriptSlowLoop = \"openspace.time.setTime('2000 JUL 14 10:03:00')\";openspace.scriptScheduler.clear();openspace.time.setDeltaTime(240);openspace.time.setTime('2000-JUL-14 10:03:00.00');openspace.scriptScheduler.loadScheduledScript('2000 JUL 14 11:00:00', StarttimescriptSlowLoop);" + }, + { + "documentation": "Fast loop: Starts from 10:03 and sets delta time to 15 min/ second (900 seconds/ second)", + "gui_path": "/Bastille-Day 2000", + "identifier": "bastille-day.fast_loop", + "is_local": false, + "name": "Loop 10:03 - 11.48, at 15 min/ second", + "script": "openspace.scriptScheduler.clear();openspace.time.setDeltaTime(900);openspace.time.setTime('2000-JUL-14 10:03:00.00');StarttimescriptFastLoop = \"openspace.time.setTime('2000 JUL 14 10:03:00')\";openspace.scriptScheduler.loadScheduledScript('2000 JUL 14 11:48:00', StarttimescriptFastLoop);" + }, + { + "documentation": "Long loop: Restarts time at 09:30 and stops at 11:50, delta time to 4 min/ second (240 seconds/ second)", + "gui_path": "/Bastille-Day 2000", + "identifier": "bastille-day.long_loop", + "is_local": false, + "name": "Loop 09:30 - 13:00, at 4 min/ second", + "script": "openspace.scriptScheduler.clear();openspace.time.setDeltaTime(240);openspace.time.setTime('2000-JUL-14 09:30:00.00');StarttimescriptLongLoop = \"openspace.time.setTime('2000 JUL 14 09:30:00')\";openspace.scriptScheduler.loadScheduledScript('2000 JUL 14 13:00:00', StarttimescriptLongLoop);" + } + ], + "assets": [ + "base", + "dashboard/default_dashboard", + "scene/solarsystem/heliosphere/bastille_day/density_volume", + "scene/solarsystem/heliosphere/bastille_day/fieldlines", + "scene/solarsystem/heliosphere/bastille_day/fluxnodes", + "scene/solarsystem/heliosphere/bastille_day/fluxnodescutplane", + "scene/solarsystem/heliosphere/bastille_day/fluxnodeslegend", + "scene/solarsystem/heliosphere/bastille_day/lightindicator", + "scene/solarsystem/heliosphere/bastille_day/magnetogram", + "scene/solarsystem/heliosphere/bastille_day/magnetogram_textures", + "scene/solarsystem/planets/earth/magnetosphere/magnetosphere", + "scene/solarsystem/planets/earth/magnetosphere/transforms_magnetosphere", + "scene/solarsystem/planets/earth/satellites/satellites", + "scene/solarsystem/sun/euv_layer" + ], + "camera": { + "altitude": 3400000000.0, + "anchor": "Sun", + "latitude": 20.5877, + "longitude": -35.1924, + "type": "goToGeo" + }, + "delta_times": [ + 1.0, + 5.0, + 30.0, + 60.0, + 300.0, + 1800.0, + 3600.0, + 43200.0, + 86400.0, + 604800.0, + 1209600.0, + 2592000.0, + 5184000.0, + 7776000.0, + 15552000.0, + 31536000.0, + 63072000.0, + 157680000.0, + 315360000.0, + 630720000.0 + ], + "keybindings": [ + { + "action": "bastille-day.reset_loops", + "key": "R" + }, + { + "action": "bastille-day.short_loop", + "key": "CTRL+1" + }, + { + "action": "bastille-day.standard_loop", + "key": "CTRL+2" + }, + { + "action": "bastille-day.fast_loop", + "key": "CTRL+3" + }, + { + "action": "bastille-day.long_loop", + "key": "CTRL+4" + }, + { + "action": "density_volume.toggle_volume", + "key": "D" + }, + { + "action": "fluxnodelegend.show_legend", + "key": "N" + }, + { + "action": "fluxnodelegend.hide_legend", + "key": "M" + }, + { + "action": "magnetogram_texture.switch_color_layer", + "key": "I" + }, + { + "action": "euv_layer.toggle_EUV", + "key": "E" + }, + { + "action": "fluxnodes.toggle_fluxnodes", + "key": "O" + }, + { + "action": "fieldlines.toggle_fieldlines", + "key": "U" + }, + { + "action": "fluxnodescutplane.toggle_equatorial", + "key": "P" + }, + { + "action": "fluxnodescutplane.toggle_meridial", + "key": "LEFTBRACKET" + } + ], + "mark_nodes": [ + "Earth", + "Mars", + "Moon", + "Sun", + "Venus", + "ISS" + ], + "meta": { + "author": "CCMC", + "description": "This profile is showing the Coronal mass ejection of the bastille day 2000-07-14. The profile is data heavy and will require a powerful GPU.", + "license": "MIT License", + "name": "Bastille day", + "url": "https://www.openspaceproject.com", + "version": "1.0" + }, + "properties": [ + { + "name": "{earth_satellites}.Renderable.Enabled", + "type": "setPropertyValue", + "value": "false" + }, + { + "name": "Scene.Sun.Renderable.Enabled", + "type": "setPropertyValue", + "value": "true" + }, + { + "name": "Scene.SunGlare.Renderable.Enabled", + "type": "setPropertyValue", + "value": "false" + }, + { + "name": "Scene.Sun.Renderable.Layers.ColorLayers.Texture.Enabled", + "type": "setPropertyValue", + "value": "false" + }, + { + "name": "Scene.Sun.Renderable.Layers.ColorLayers.magnetogram-2.Enabled", + "type": "setPropertyValue", + "value": "true" + }, + { + "name": "Scene.Earth.Renderable.Layers.ColorLayers.ESRI_VIIRS_Combo.Enabled", + "type": "setPropertyValue", + "value": "false" + }, + { + "name": "Scene.Earth.Renderable.Layers.ColorLayers.ESRI_World_Imagery.Enabled", + "type": "setPropertyValue", + "value": "true" + } + ], + "time": { + "type": "absolute", + "value": "2000-07-14T08:42:00" + }, + "version": { + "major": 1, + "minor": 1 + } +} \ No newline at end of file diff --git a/data/profiles/default.profile b/data/profiles/default.profile index f3e5f95679..6d3077cc1b 100644 --- a/data/profiles/default.profile +++ b/data/profiles/default.profile @@ -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 } } \ No newline at end of file diff --git a/data/profiles/default_full.profile b/data/profiles/default_full.profile index 8d5113b15b..d2bbfc3a8c 100644 --- a/data/profiles/default_full.profile +++ b/data/profiles/default_full.profile @@ -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 } } \ No newline at end of file diff --git a/data/profiles/jwst.profile b/data/profiles/jwst.profile index d273706c84..701b6609cf 100644 --- a/data/profiles/jwst.profile +++ b/data/profiles/jwst.profile @@ -1,18 +1,109 @@ { + "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 line and small L2 label", + "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" + }, + { + "documentation": "Set the time to the 2018 launch time of JWST", + "gui_path": "/JWST", + "identifier": "profile.set.2018_launch", + "is_local": false, + "name": "Set to 2018 launch time", + "script": "openspace.time.setTime('2018-10-01T14:06:03'); openspace.time.setDeltaTime(1)" + }, + { + "documentation": "Set the time to 2021 where the JWST Sun trail has valid data (2020-2024)", + "gui_path": "/JWST", + "identifier": "profile.set.2021_sun", + "is_local": false, + "name": "Set to 2021 Sun trail", + "script": "openspace.time.setTime('2021-12-18T14:06:03'); openspace.time.setDeltaTime(1)" + }, + { + "documentation": "Toggle all planet and moon trails, except the Moon", + "gui_path": "/JWST", + "identifier": "profile.toggle.trails_not_moon", + "is_local": false, + "name": "Toggle trails (except Moon)", + "script": "local list = openspace.getProperty('{planetTrail_solarSystem}.Renderable.Enabled'); for _,v in pairs(list) do openspace.setPropertyValueSingle(v, not openspace.getPropertyValue(v)) end local moonlist = openspace.getProperty('{moonTrail_solarSystem}.Renderable.Enabled') for _,v in pairs(moonlist) do openspace.setPropertyValueSingle(v, not openspace.getPropertyValue(v)) end openspace.setPropertyValueSingle('Scene.MoonTrail.Renderable.Enabled', true)" + }, + { + "documentation": "Toggle JWST launch and orbit trails", + "gui_path": "/JWST", + "identifier": "profile.toggle.jwst_trails", + "is_local": false, + "name": "Toggle JWST trails", + "script": "local list = {'Scene.JWSTTrailLaunch.Renderable.Enabled', 'Scene.JWSTTrailOrbit.Renderable.Enabled'}; for _,v in pairs(list) do openspace.setPropertyValueSingle(v, not openspace.getPropertyValue(v)); end" + } + ], + "additional_scripts": [ + "openspace.setPropertyValue(\"Scene.MoonTrail.Renderable.Appearance.Color\", {0.7, 0.5, 0.5});" + ], "assets": [ "base", "scene/solarsystem/planets/earth/earth", "scene/solarsystem/planets/earth/satellites/satellites", + "scene/solarsystem/planets/earth/lagrange_points/lagrange_points", "scene/solarsystem/missions/jwst/jwst", - "scene/solarsystem/missions/jwst/HUDFImage", + "scene/solarsystem/missions/jwst/trail", + "scene/solarsystem/missions/jwst/hudf", + "scene/solarsystem/missions/jwst/timelapse", "scene/digitaluniverse/hdf" ], "camera": { - "altitude": 17000000.0, - "anchor": "Earth", - "latitude": 3.5559, - "longitude": -53.0515, - "type": "goToGeo" + "aim": "", + "anchor": "JWSTModel", + "frame": "Root", + "yaw": -0.005731, + "pitch": -0.001656, + "type": "setNavigationState", + "position": { + "x": 30.188156, + "y": -9.477188, + "z": -9.203491 + }, + "up": { + "x": 0.361587, + "y": 0.893643, + "z": 0.265813 + } }, "delta_times": [ 1.0, @@ -38,44 +129,56 @@ ], "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" + }, + { + "action": "profile.set.2018_launch", + "key": "J" + }, + { + "action": "profile.set.2021_sun", + "key": "K" + }, + { + "action": "jwst.play.forwards", + "key": "M" + }, + { + "action": "jwst.play.backwards", + "key": "N" + }, + { + "action": "jwst.play.clear", + "key": "B" + }, + { + "action": "profile.toggle.trails_not_moon", + "key": "G" + }, + { + "action": "jwst.toggle.direction", + "key": "Y" + }, + { + "action": "profile.toggle.jwst_trails", + "key": "T" } ], "mark_nodes": [ @@ -99,14 +202,79 @@ "name": "{earth_satellites}.Renderable.Enabled", "type": "setPropertyValue", "value": "false" + }, + { + "name": "Scene.MoonTrail.Renderable.Appearance.Fade", + "type": "setPropertyValueSingle", + "value": "3.0" + }, + { + "name": "Scene.JWSTTrailLaunch.Renderable.Appearance.EnableFade", + "type": "setPropertyValueSingle", + "value": "false" + }, + { + "name": "Scene.L1.Renderable.Enabled", + "type": "setPropertyValueSingle", + "value": "false" + }, + { + "name": "Scene.L1Label.Renderable.Enabled", + "type": "setPropertyValueSingle", + "value": "false" + }, + { + "name": "Scene.L2.Renderable.Enabled", + "type": "setPropertyValueSingle", + "value": "false" + }, + { + "name": "Scene.L2Label.Renderable.Enabled", + "type": "setPropertyValueSingle", + "value": "false" + }, + { + "name": "Scene.L4.Renderable.Enabled", + "type": "setPropertyValueSingle", + "value": "false" + }, + { + "name": "Scene.L4Label.Renderable.Enabled", + "type": "setPropertyValueSingle", + "value": "false" + }, + { + "name": "Scene.L5.Renderable.Enabled", + "type": "setPropertyValueSingle", + "value": "false" + }, + { + "name": "Scene.L5Label.Renderable.Enabled", + "type": "setPropertyValueSingle", + "value": "false" + }, + { + "name": "Scene.L2Small.Renderable.Enabled", + "type": "setPropertyValueSingle", + "value": "false" + }, + { + "name": "Scene.L2SmallLabel.Renderable.Enabled", + "type": "setPropertyValueSingle", + "value": "false" + }, + { + "name": "Scene.L2SunLine.Renderable.Enabled", + "type": "setPropertyValueSingle", + "value": "false" } ], "time": { "type": "absolute", - "value": "2021-10-31T00:00:00" + "value": "2018-10-01T14:06:03" }, "version": { "major": 1, - "minor": 0 + "minor": 1 } -} +} \ No newline at end of file diff --git a/data/profiles/mars.profile b/data/profiles/mars.profile index eb730ff151..b63767b8bd 100644 --- a/data/profiles/mars.profile +++ b/data/profiles/mars.profile @@ -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 } } \ No newline at end of file diff --git a/data/profiles/newhorizons.profile b/data/profiles/newhorizons.profile index f66c34681d..60bb04c35d 100644 --- a/data/profiles/newhorizons.profile +++ b/data/profiles/newhorizons.profile @@ -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 } -} +} \ No newline at end of file diff --git a/data/profiles/osirisrex.profile b/data/profiles/osirisrex.profile index a6b9399bcb..8f3a080085 100644 --- a/data/profiles/osirisrex.profile +++ b/data/profiles/osirisrex.profile @@ -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 } } \ No newline at end of file diff --git a/data/profiles/rosetta.profile b/data/profiles/rosetta.profile index 3f344c3893..9004efd649 100644 --- a/data/profiles/rosetta.profile +++ b/data/profiles/rosetta.profile @@ -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 } } \ No newline at end of file diff --git a/data/profiles/voyager.profile b/data/profiles/voyager.profile index d56b6f1fba..894f46ca4f 100644 --- a/data/profiles/voyager.profile +++ b/data/profiles/voyager.profile @@ -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 } } \ No newline at end of file diff --git a/data/tasks/exoplanets/datapreparation.task b/data/tasks/exoplanets/datapreparation.task index dd924210cd..76dec4e2ea 100644 --- a/data/tasks/exoplanets/datapreparation.task +++ b/data/tasks/exoplanets/datapreparation.task @@ -1,11 +1,11 @@ -local dataFolder = "D:/dev/exoplanets data config" +local dataFolder = "D:/data/prepared_exoplanets_data" return { { Type = "ExoplanetsDataPreparationTask", - InputDataFile = dataFolder .. "/exoplanets_data_composite.csv", - InputSPECK = "${SYNC}/http/digitaluniverse_exoplanets_speck/1/expl.speck", - TeffToBvFile = "${SYNC}/http/exoplanets_data/1/teff_bv.txt", + InputDataFile = "${DATA}/tasks/exoplanets/downloaded_exo_data.csv", + InputSPECK = "${SYNC}/http/digitaluniverse_exoplanets_speck/2/expl.speck", + TeffToBvFile = "${SYNC}/http/exoplanets_data/2/teff_bv.txt", OutputBIN = dataFolder .. "/exoplanets_data.bin", OutputLUT = dataFolder .. "/lookup.txt" } diff --git a/data/tasks/exoplanets/downloadexodata.py b/data/tasks/exoplanets/downloadexodata.py new file mode 100644 index 0000000000..9f4ea3c11c --- /dev/null +++ b/data/tasks/exoplanets/downloadexodata.py @@ -0,0 +1,39 @@ +## +# Download most recent exoplanet data from NASA Exoplanet Archive using the TAP service +# More info at: https://exoplanetarchive.ipac.caltech.edu/docs/TAP/usingTAP.html +# +# The data table is the Planetary Systems Composite dataset, where multiple sources have +# been combined into one row per planet. +# https://exoplanetarchive.ipac.caltech.edu/cgi-bin/TblView/nph-tblView?app=ExoTbls&config=PSCompPars +# +# The script downloads the columns needed for the visualization in OpenSpace and for the +# exoplanets datapreparation task, but more columns can be added if needed. +## + +import pandas as pd + +dataFileName = 'downloaded_exo_data.csv' + +# The columns we need for the visualization in OpenSpace +columns = 'pl_name,hostname,pl_letter,sy_snum,sy_pnum,pl_orbsmax,pl_orbsmaxerr1,pl_orbsmaxerr2,' \ + 'pl_orbeccen,pl_orbeccenerr1,pl_orbeccenerr2,pl_orbincl,pl_orbinclerr1,pl_orbinclerr2,' \ + 'pl_orblper,pl_orblpererr1,pl_orblpererr2,pl_orbper,pl_orbpererr1,pl_orbpererr2,' \ + 'pl_radj,pl_radjerr1,pl_radjerr2,pl_tranmid,pl_tranmiderr1,pl_tranmiderr2,ra,dec,' \ + 'sy_dist,st_rad,st_raderr1,st_raderr2,st_teff,st_tefferr1,st_tefferr2,' \ + 'st_lum,st_lumerr1,st_lumerr2,cb_flag,disc_year' + +# This may contain any extra conditions that one might want to fulfill. Start with a '+' sign +where = '' + +### +## Download and save csv file +print("Downloading all confirmed planets from NExSci's Exoplanets Archive... (Planetary Systems Composite Data table)") + +NEW_API = 'https://exoplanetarchive.ipac.caltech.edu/TAP/sync?query=' +url = NEW_API + 'select+' + columns + '+from+pscomppars' + where + '&format=csv' +print(url) +df = pd.read_csv(url) + +print("Writing data to file...") +df.to_csv(dataFileName) +print("Done!") diff --git a/data/tasks/full_sync.task b/data/tasks/full_sync.task deleted file mode 100644 index 4b1b5ad6e7..0000000000 --- a/data/tasks/full_sync.task +++ /dev/null @@ -1,34 +0,0 @@ -return { - { - Type = "SyncAssetTask", - Asset = "default" - }, - { - Type = "SyncAssetTask", - Asset = "newhorizons" - }, - { - Type = "SyncAssetTask", - Asset = "rosetta" - }, - { - Type = "SyncAssetTask", - Asset = "dawn" - }, - { - Type = "SyncAssetTask", - Asset = "juno" - }, - { - Type = "SyncAssetTask", - Asset = "osirisrex" - }, - { - Type = "SyncAssetTask", - Asset = "voyager" - }, - { - Type = "SyncAssetTask", - Asset = "sync/everything" - } -} diff --git a/data/tasks/gaia/gaia_download.task b/data/tasks/gaia/gaia_download.task deleted file mode 100644 index aa09142bde..0000000000 --- a/data/tasks/gaia/gaia_download.task +++ /dev/null @@ -1,6 +0,0 @@ -return { - { - Type = "SyncAssetTask", - Asset = "scene/milkyway/gaia/gaia_dr2_download_stars" - } -} diff --git a/ext/CMakeLists.txt b/ext/CMakeLists.txt index 797f419d56..9b28568d2c 100644 --- a/ext/CMakeLists.txt +++ b/ext/CMakeLists.txt @@ -65,13 +65,11 @@ add_library(external-curl INTERFACE) if (WIN32) target_include_directories(external-curl INTERFACE "${CMAKE_CURRENT_SOURCE_DIR}/curl/include") target_link_libraries(external-curl INTERFACE "${CMAKE_CURRENT_SOURCE_DIR}/curl/lib/libcurl.lib") - target_compile_definitions(external-curl INTERFACE "OPENSPACE_CURL_ENABLED" "CURL_STATICLIB") else () find_package(CURL) if (CURL_FOUND) target_include_directories(external-curl INTERFACE ${CURL_INCLUDE_DIRS}) target_link_libraries(external-curl INTERFACE ${CURL_LIBRARIES}) - target_compile_definitions(external-curl INTERFACE "OPENSPACE_CURL_ENABLED") endif () endif () end_dependency() diff --git a/ext/ghoul b/ext/ghoul index c5add410f3..6dfb7965bf 160000 --- a/ext/ghoul +++ b/ext/ghoul @@ -1 +1 @@ -Subproject commit c5add410f3367890e2a2f91f6087001baf8f2152 +Subproject commit 6dfb7965bf7d44a6d3690634daf21848b3be6df5 diff --git a/include/openspace/util/camera.h b/include/openspace/camera/camera.h similarity index 100% rename from include/openspace/util/camera.h rename to include/openspace/camera/camera.h diff --git a/include/openspace/scene/assetlistener.h b/include/openspace/camera/camerapose.h similarity index 81% rename from include/openspace/scene/assetlistener.h rename to include/openspace/camera/camerapose.h index 60546b521e..4b6ee21aa5 100644 --- a/include/openspace/scene/assetlistener.h +++ b/include/openspace/camera/camerapose.h @@ -22,21 +22,18 @@ * OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. * ****************************************************************************************/ -#ifndef __OPENSPACE_CORE___ASSETLISTENER___H__ -#define __OPENSPACE_CORE___ASSETLISTENER___H__ +#ifndef __OPENSPACE_CORE___CAMERAPOSE___H__ +#define __OPENSPACE_CORE___CAMERAPOSE___H__ -#include +#include namespace openspace { -class AssetListener { -public: - virtual ~AssetListener() = default; - virtual void assetStateChanged(Asset* asset, Asset::State state) = 0; - virtual void assetRequested(Asset* parent, std::shared_ptr child) = 0; - virtual void assetUnrequested(Asset* parent, std::shared_ptr child) = 0; +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___ASSETLISTENER___H__ +#endif // __OPENSPACE_CORE___CAMERAPOSE___H__ diff --git a/include/openspace/documentation/verifier.inl b/include/openspace/documentation/verifier.inl index 7363b325ec..6b86ff0918 100644 --- a/include/openspace/documentation/verifier.inl +++ b/include/openspace/documentation/verifier.inl @@ -175,7 +175,7 @@ TestResult OperatorVerifier::operator()(const ghoul::Dictionary& di o.offender = key; o.reason = TestResult::Offense::Reason::Verification; r.offenses.push_back(o); - return r; + return r; } } else { @@ -290,7 +290,7 @@ TestResult NotInListVerifier::operator()(const ghoul::Dictionary& dict, o.offender = key; o.reason = TestResult::Offense::Reason::Verification; r.offenses.push_back(o); - return r; + return r; } } else { @@ -346,7 +346,7 @@ TestResult InRangeVerifier::operator()(const ghoul::Dictionary& dict, o.offender = key; o.reason = TestResult::Offense::Reason::WrongType; r.offenses.push_back(o); - return r; + return r; } } else { @@ -363,7 +363,7 @@ TestResult InRangeVerifier::operator()(const ghoul::Dictionary& dict, o.offender = key; o.reason = TestResult::Offense::Reason::Verification; r.offenses.push_back(o); - return r; + return r; } } else { @@ -405,7 +405,7 @@ TestResult NotInRangeVerifier::operator()(const ghoul::Dictionary& dict, o.offender = key; o.reason = TestResult::Offense::Reason::WrongType; r.offenses.push_back(o); - return r; + return r; } } else { @@ -419,7 +419,7 @@ TestResult NotInRangeVerifier::operator()(const ghoul::Dictionary& dict, o.offender = key; o.reason = TestResult::Offense::Reason::Verification; r.offenses.push_back(o); - return r; + return r; } else { return { true, {}, {} }; diff --git a/include/openspace/engine/configuration.h b/include/openspace/engine/configuration.h index eed5c055c5..cb4303c5bb 100644 --- a/include/openspace/engine/configuration.h +++ b/include/openspace/engine/configuration.h @@ -89,6 +89,7 @@ struct Configuration { bool isCheckingOpenGLState = false; bool isLoggingOpenGLCalls = false; + bool isPrintingEvents = false; float shutdownCountdown = 0.f; @@ -98,18 +99,17 @@ struct Configuration { bool usePerProfileCache = false; bool isRenderingOnMasterDisabled = false; - glm::dvec3 globalRotation = glm::dvec3(0.0); - glm::dvec3 screenSpaceRotation = glm::dvec3(0.0); - glm::dvec3 masterRotation = glm::dvec3(0.0); + glm::vec3 globalRotation = glm::vec3(0.0); + glm::vec3 screenSpaceRotation = glm::vec3(0.0); + glm::vec3 masterRotation = glm::vec3(0.0); bool isConsoleDisabled = false; bool bypassLauncher = false; std::map moduleConfigurations; - std::string renderingMethod = "Framebuffer"; - struct OpenGLDebugContext { bool isActive = false; + bool printStacktrace = false; bool isSynchronous = true; struct IdentifierFilter { std::string type; @@ -132,7 +132,6 @@ struct Configuration { HTTPProxy httpProxy; // Values not read from the openspace.cfg file - bool usingProfile = false; std::string sgctConfigNameInitialized; static documentation::Documentation Documentation; diff --git a/include/openspace/engine/globals.h b/include/openspace/engine/globals.h index c308a08bf7..38b7d37915 100644 --- a/include/openspace/engine/globals.h +++ b/include/openspace/engine/globals.h @@ -36,6 +36,7 @@ namespace openspace { class Dashboard; class DeferredcasterManager; class DownloadManager; +class EventEngine; class LuaConsole; class MemoryManager; class MissionManager; @@ -54,6 +55,7 @@ namespace configuration { struct Configuration; } namespace interaction { struct JoystickInputStates; struct WebsocketInputStates; + class ActionManager; class InteractionMonitor; class KeybindingManager; class NavigationHandler; @@ -73,6 +75,7 @@ inline ghoul::fontrendering::FontManager* fontManager; inline Dashboard* dashboard; inline DeferredcasterManager* deferredcasterManager; inline DownloadManager* downloadManager; +inline EventEngine* eventEngine; inline LuaConsole* luaConsole; inline MemoryManager* memoryManager; inline MissionManager* missionManager; @@ -88,6 +91,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; diff --git a/include/openspace/engine/openspaceengine.h b/include/openspace/engine/openspaceengine.h index f06b61f356..cf6ed4ac19 100644 --- a/include/openspace/engine/openspaceengine.h +++ b/include/openspace/engine/openspaceengine.h @@ -26,6 +26,8 @@ #define __OPENSPACE_CORE___OPENSPACEENGINE___H__ #include +#include +#include #include #include #include @@ -90,7 +92,6 @@ public: std::vector encode(); void decode(std::vector data); - void scheduleLoadSingleAsset(std::string assetPath); void toggleShutdownMode(); // Guaranteed to return a valid pointer @@ -108,7 +109,7 @@ public: static scripting::LuaLibrary luaLibrary(); private: - void loadSingleAsset(const std::string& assetPath); + void loadAssets(); void loadFonts(); void runGlobalCustomizationScripts(); @@ -116,15 +117,14 @@ private: std::string generateFilePath(std::string openspaceRelativePath); void resetPropertyChangeFlagsOfSubowners(openspace::properties::PropertyOwner* po); + properties::BoolProperty _printEvents; + std::unique_ptr _scene; std::unique_ptr _assetManager; bool _shouldAbortLoading = false; std::unique_ptr _loadingScreen; std::unique_ptr _versionChecker; - bool _hasScheduledAssetLoading = false; - std::string _scheduledAssetPathToLoad; - glm::vec2 _mousePosition = glm::vec2(0.f); //grabs json from each module to pass to the documentation engine. @@ -136,9 +136,57 @@ private: // The first frame might take some more time in the update loop, so we need to know to // disable the synchronization; otherwise a hardware sync will kill us after 1 minute - bool _isFirstRenderingFirstFrame = true; + bool _isRenderingFirstFrame = true; }; +/** + * Sets the camera position using the time contents of a profile. The function will + * set an absolute position or a go-to-geolocation command using the globebrowsing + * module. + * \param p The Profile to be read. + */ +void setCameraFromProfile(const Profile& p); + +/** + * Reads a list of modules from a profile, and executes scripts based on whether or + * not the corresponding module is loaded. + * + * \param p The Profile to be read. + */ +void setModulesFromProfile(const Profile& p); + +/** + * Registers actions from the contents of a profile. + * + * \param p The Profile to be read. + */ +void setActionsFromProfile(const Profile& p); + +/** + * Registers keybindings from the contents of a profile. + * + * \param p The Profile to be read. + */ +void setKeybindingsFromProfile(const Profile& p); + +/** + * Reads list of nodes from profile to be marked as interesting nodes. + * If any nodes are listed, a script to mark these will be queued with the + * script engine. + * + * \param p The Profile to be read. + */ +void setMarkInterestingNodesFromProfile(const Profile& p); + +/** + * Reads list of "additional scripts" that are added to the profile to be run + * at the end of the initialization. Any openspace lua commands are allowed, + * and will be added to the script queue. + * + * \param p The Profile to be read. + */ +void setAdditionalScriptsFromProfile(const Profile& p); + } // namespace openspace // Lua functions - exposed for testing diff --git a/include/openspace/events/event.h b/include/openspace/events/event.h new file mode 100644 index 0000000000..201814da55 --- /dev/null +++ b/include/openspace/events/event.h @@ -0,0 +1,395 @@ +/***************************************************************************************** + * * + * 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___EVENT___H__ +#define __OPENSPACE_CORE___EVENT___H__ + +#include +#include +#include + +namespace openspace { + namespace properties { class Property; } + + class Camera; + class Layer; + class Profile; + class SceneGraphNode; + class ScreenSpaceRenderable; + class Time; +} // namespace openspace + +namespace openspace::events { + +struct Event { + // Steps to add a new event type: + // 1. Add a new entry into this enum list + // 2. Create a new subclass of Event in this file with a constructor that sets the + // Event's `type` to this new enum entry + // 3. In the cpp file, add a new `log` message that takes the new type as an argument + // and that prints something useful when the log is encountered and the user wants + // to see all events. + // 4. Add a new case into the logAllEvents function that handles the new enum entry + // 5. If the new event type has any parameters it takes in its constructor, go into + // the `toParameter` function and add a case label for the new enum type and + // return a dictionary with these parameters. This dictionary is passed to actions + // if they are triggered by events + // 6. Add the new enum entry into the `toString` and `fromString` methods + enum class Type { + SceneGraphNodeAdded, + SceneGraphNodeRemoved, + ParallelConnection, + ProfileLoadingFinished, + ApplicationShutdown, + ScreenSpaceRenderableAdded, + ScreenSpaceRenderableRemoved, + CameraFocusTransition, + TimeOfInterestReached, + MissionEventReached, + PlanetEclipsed, + InterpolationFinished, + FocusNodeChanged, + LayerAdded, + LayerRemoved, + SessionRecordingPlayback, + Custom + }; + constexpr explicit Event(Type type_) : type(type_) {} + + const Type type; + const Event* next = nullptr; +}; + +template +T* asType(Event* e) { + ghoul_assert(e->type == T::Type, "Wrong type requested, check 'isType'"); + return static_cast(e); +} + +template +bool isType(Event* e) { + return e->type == T::Type; +} + +std::string_view toString(Event::Type type); +Event::Type fromString(std::string_view str); + +ghoul::Dictionary toParameter(const Event& e); + +void logAllEvents(const Event* e); + +// +// Events +// + +/** + * This event is created whenever a new scene graph node is added to the system. By the + * time this event is signalled, the scene graph node has already been created and added + * to the scene. + * + * \param Node The identifier of the node that was added + */ +struct EventSceneGraphNodeAdded : public Event { + static const Type Type = Event::Type::SceneGraphNodeAdded; + + explicit EventSceneGraphNodeAdded(const SceneGraphNode* node_); + const tstring node; +}; + +/** + * This event is created whenever a scene graph node was removed. By the time this event + * is signalled, the scene graph node has already been removed. + * + * \param Node The identifier of that node that was removed + */ +struct EventSceneGraphNodeRemoved : public Event { + static const Type Type = Event::Type::SceneGraphNodeRemoved; + + explicit EventSceneGraphNodeRemoved(const SceneGraphNode* node_); + const tstring node; +}; + +/** + * This event is created whenever something in the parallel connection subsystem changes. + * The new state is sent as an argument with this event. + * + * \param State The new state of the parallel connection system; is one of `Established`, + * `Lost`, `HostshipGained`, or `HostshipLost` + */ +struct EventParallelConnection : public Event { + static const Type Type = Event::Type::ParallelConnection; + + enum class State : uint8_t { + Established, + Lost, + HostshipGained, + HostshipLost + }; + explicit EventParallelConnection(State state_); + State state; +}; + +/** + * This event is created when the loading of a profile is finished. This is emitted + * regardless of whether it is the initial profile, or any subsequent profile is loaded. + */ +struct EventProfileLoadingFinished : public Event { + static const Type Type = Event::Type::ProfileLoadingFinished; + + EventProfileLoadingFinished(); +}; + +/** + * This event is created whenever some information about the application shutdown sequence + * changes. This can either be that the seqeuence started, was aborted, or is finished, + * which means that OpenSpace is just about the shutdown. + * + * \param State The next state of the application shutdown sequence; is one of `Started`, + * `Aborted`, or `Finished` + */ +struct EventApplicationShutdown : public Event { + static const Type Type = Event::Type::ApplicationShutdown; + + enum class State : uint8_t { + Started, + Aborted, + Finished + }; + + explicit EventApplicationShutdown(State state_); + const State state; +}; + +/** + * This event is created when a new screenspace renderable has been created. By the time + * this event is craeted, the screenspace renderable is already registered and available. + * + * \param Renderable The identifier of the new screenspace renderable that was just added + * to the system + */ +struct EventScreenSpaceRenderableAdded : public Event { + static const Type Type = Event::Type::ScreenSpaceRenderableAdded; + + explicit EventScreenSpaceRenderableAdded(const ScreenSpaceRenderable* renderable_); + const tstring renderable; +}; + +/** + * This event is created when a screenspace renderable has been removed from the system. + * When this event is created, the screenspace renderable has already been removed and is + * no longer available + * + * \param Renderable The identifier of the screenspace renderable that was removed + */ +struct EventScreenSpaceRenderableRemoved : public Event { + static const Type Type = Event::Type::ScreenSpaceRenderableRemoved; + + explicit EventScreenSpaceRenderableRemoved(const ScreenSpaceRenderable* renderable_); + const tstring renderable; +}; + +/** + * This event is created when the camera transitions between different interaction sphere + * distances. Right now, only movement relative to camera's focus node is considered. + * Each scene graph node has an interaction sphere radius that serves as the reference + * distance for all spheres. +``` +Diagram of events for a camera moving from right-to-left. Interaction sphere is 'O' in +middle, and ')' are spherical boundaries. The approach factor, reach factor, and +interaction sphere radius are all taken from the current focus node. + +|<------------------->| Approach factor * Interaction sphere + |<------>| Reach Factor * Interaction sphere + +( ( O ) ) +^ ^ ^ ^ +Exiting Receding Reaching Approaching +``` + * + * \param Node The name of the node the camera is transitioning relative to. Currently is + * always the same as the camera's focus node + * \param Transition The transition type that the camera just finished; is one of + * `Approaching`, `Reaching`, `Receding`, or `Exiting` + */ +struct EventCameraFocusTransition : public Event { + static const Type Type = Event::Type::CameraFocusTransition; + + enum class Transition { + Approaching, + Reaching, + Receding, + Exiting + }; + + EventCameraFocusTransition(const Camera* camera_, const SceneGraphNode* node_, + Transition transition_); + + const Camera* camera = nullptr; + const tstring node; + const Transition transition; +}; + + +/** + * This event is created with a specific time of interest is reached. This event is + * currently unused. + */ +struct EventTimeOfInterestReached : public Event { + static const Type Type = Event::Type::TimeOfInterestReached; + + EventTimeOfInterestReached(const Time* time_, const Camera* camera_); + const Time* time = nullptr; + const Camera* camera = nullptr; +}; + + +/** + * This event is created when the end of a mission phase is reached. This event is + * currently unused. + */ +struct EventMissionEventReached : public Event { + static const Type Type = Event::Type::MissionEventReached; + + // Not sure which kind of parameters we want to pass here + EventMissionEventReached(); +}; + +/** + * This event is created when a planet is eclipsed by a moon or a different planet. This + * event is currently unused. + * + * \param Eclipsee The identifier of the scene graph node that is eclipsed by another + * object + * \param Eclipser The identifier of the scene graph node that is eclipsing the other + * object + */ +struct EventPlanetEclipsed : public Event { + static const Type Type = Event::Type::PlanetEclipsed; + + EventPlanetEclipsed(const SceneGraphNode* eclipsee_, const SceneGraphNode* eclipser_); + const tstring eclipsee; + const tstring eclipser; +}; + +/** + * This event is created when the interpolation of a property value is finished. If the + * interpolation time of a property change is 0s, this event is not fired + * + * \param Property The URI of the property whose interpolation has finished + */ +struct EventInterpolationFinished : public Event { + static const Type Type = Event::Type::InterpolationFinished; + + EventInterpolationFinished(const properties::Property* property_); + const tstring property; +}; + +/** + * This event is created when the camera changes focus nodes. Even if the camera position + * is interpolated, the node change happens instantaneously and the event is fired at the + * same time. + * + * \param OldNode The identifier of the scene graph node which was the old focus node + * \param NewNode The identifier of the scene graph node that is the new focus node + */ +struct EventFocusNodeChanged : public Event { + static const Type Type = Event::Type::FocusNodeChanged; + + EventFocusNodeChanged(const SceneGraphNode* oldNode_, const SceneGraphNode* newNode_); + const tstring oldNode; + const tstring newNode; +}; + +/** + * This event is created when a layer is added to to a globe. + * + * \param Globe The identifier of the globe to which the layer is added + * \param Group The identifier of the layer group to which the layer is added + * \param Layer The identifier of the layer that was added + */ +struct EventLayerAdded : public Event { + static const Type Type = Event::Type::LayerAdded; + + explicit EventLayerAdded(std::string_view node_, std::string_view layerGroup_, + std::string_view layer_); + const tstring node; + const tstring layerGroup; + const tstring layer; +}; + +/** + * This event is created when a layer is removed from a globe. + * + * \param Globe The identifier of the globe from which the layer is removed + * \param Group The identifier of the layer group from which the layer is removed + * \param Layer The identifier of the layer that was removed + */ +struct EventLayerRemoved : public Event { + static const Type Type = Event::Type::LayerRemoved; + + explicit EventLayerRemoved(std::string_view node_, std::string_view layerGroup_, + std::string_view layer_); + const tstring node; + const tstring layerGroup; + const tstring layer; +}; + +/** + * This event is created when something regarding a session recording playback changes. + * The event contains information about the new state of the session recording subsystem. + * + * \param State The new state of the session recording; one of `Started`, `Paused`, + * `Resumed`, `Finished` + */ +struct EventSessionRecordingPlayback : public Event { + static const Type Type = Event::Type::SessionRecordingPlayback; + + enum class State { + Started, + Paused, + Resumed, + Finished + }; + + EventSessionRecordingPlayback(State state_); + const State state; +}; + +/** + * A custom event type that can be used in a pinch when no explicit event type is + * available. This should only be used in special circumstances and it should be + * transitioned to a specific event type, if it is deemed to be useful. + */ +struct CustomEvent : public Event { + static const Type Type = Event::Type::Custom; + + CustomEvent(std::string_view subtype_, const void* payload_); + + const tstring subtype; + const void* payload = nullptr; +}; + +} // namespace openspace::events + +#endif // __OPENSPACE_CORE___EVENT___H__ diff --git a/include/openspace/events/eventengine.h b/include/openspace/events/eventengine.h new file mode 100644 index 0000000000..4e98175572 --- /dev/null +++ b/include/openspace/events/eventengine.h @@ -0,0 +1,125 @@ +/***************************************************************************************** + * * + * 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___EVENTENGINE___H__ +#define __OPENSPACE_CORE___EVENTENGINE___H__ + +#include +#include +#include +#include + +namespace openspace { + +namespace events { struct Event; } + +class EventEngine { +public: + /** + * This function returns the first event stored in the EventEngine, or \c nullptr if + * no event exists. To navigate the full list of events, you can access the returned + * Event's next function. If the end of the list is reached, the next pointer will be + * a nullptr + * + * \return The first event stored in the EventEngine or nullptr if no event exists + */ + events::Event* firstEvent() const; + + /** + * Publish a new event of type T by providing optional arguments Args to the Event's + * constructor. An example of usage is + * engine.publishEvent("a", 2.0); which would call the + * constructor of \c MyEvent with a const char* and \c double parameter. + * + * \param args The arguments that are passed to the constructor of T + * \tparam T The subclass of Event that is to be published + */ + template + void publishEvent(Args&&... args); + + /** + * This function cleans up the memory for all published events.After this function + * has been called, no previously published events are valid any longer. This means + * that pointers retrieved from events before this call must be kept beyond this call. + */ + void postFrameCleanup(); + + /** + * Registers a new action for a specific event type. + * + * \param type The type for which a new action is registered + * \param actionIdentifier The identifier of the action that will be triggered the + * identifier must not exist at this moment, but must exist by the time the + * event is encountered next + * \param filter If the filter is provided, it describes the event parameters that are + * checked and only if an event passes the filter, the corresponding action is + * triggered + */ + void registerEventAction(events::Event::Type type, std::string identifier, + std::optional filter = std::nullopt); + + /** + * Removing registration for a type/action combination. + * + * \param type The type of the action that should be unregistered + * \param actionIdentifier The identifier of the action that should be unregistered + * \param filter The optional filter applied to the event-action combination + */ + void unregisterEventAction(events::Event::Type type, + const std::string& identifier, + std::optional filter = std::nullopt); + + /** + * Triggers all actions that are registered for events that are in the current event + * queue + */ + void triggerActions() const; + + static scripting::LuaLibrary luaLibrary(); + +private: + /// The storage space in which Events are stored + ghoul::MemoryPool<4096> _memory; + /// The first event in the chain of events stored in the memory pool + events::Event* _firstEvent = nullptr; + /// The last event in the chain of events stored in the memory pool + events::Event* _lastEvent = nullptr; + + struct ActionInfo { + std::string action; + std::optional filter; + }; + std::unordered_map> _eventActions; + +#ifdef _DEBUG + /// Stores the total number of events during this frame for debugging purposes + static uint64_t nEvents; +#endif // _DEBUG +}; + +} // namespace openspace + +#include "eventengine.inl" + +#endif // __OPENSPACE_CORE___EVENTENGINE___H__ diff --git a/modules/sync/tasks/syncassettask.h b/include/openspace/events/eventengine.inl similarity index 80% rename from modules/sync/tasks/syncassettask.h rename to include/openspace/events/eventengine.inl index 5f0cf8f830..019540b48b 100644 --- a/modules/sync/tasks/syncassettask.h +++ b/include/openspace/events/eventengine.inl @@ -22,28 +22,30 @@ * OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. * ****************************************************************************************/ -#ifndef __OPENSPACE_MODULE_SYNC___SYNCASSETTASK___H__ -#define __OPENSPACE_MODULE_SYNC___SYNCASSETTASK___H__ - -#include - -#include +#include namespace openspace { -class SyncAssetTask : public Task { -public: - SyncAssetTask(const ghoul::Dictionary& dictionary); +template +void EventEngine::publishEvent(Args&&... args) { + static_assert( + std::is_base_of::value, + "T must be a subclass of Event" + ); - std::string description() override; - void perform(const Task::ProgressCallback& progressCallback) override; + T* e = _memory.alloc(args...); + if (!_firstEvent) { + _firstEvent = e; + _lastEvent = e; + } + else { + _lastEvent->next = e; + _lastEvent = e; + } - static documentation::Documentation documentation(); - -private: - std::string _asset; -}; +#ifdef _DEBUG + nEvents++; +#endif // _DEBUG +} } // namespace openspace - -#endif // __OPENSPACE_MODULE_SYNC___SYNCASSETTASK___H__ diff --git a/include/openspace/interaction/action.h b/include/openspace/interaction/action.h new file mode 100644 index 0000000000..05150d2b5b --- /dev/null +++ b/include/openspace/interaction/action.h @@ -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 +#include + +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__ diff --git a/include/openspace/interaction/shortcutmanager.h b/include/openspace/interaction/actionmanager.h similarity index 77% rename from include/openspace/interaction/shortcutmanager.h rename to include/openspace/interaction/actionmanager.h index d1043cf74b..79a07aa77c 100644 --- a/include/openspace/interaction/shortcutmanager.h +++ b/include/openspace/interaction/actionmanager.h @@ -22,39 +22,33 @@ * 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 -#include -#include +#include +#include +namespace ghoul { class Dictionary; } namespace openspace::scripting { struct LuaLibrary; } namespace openspace::interaction { -class ShortcutManager { +class ActionManager { public: - BooleanType(IsSynchronized); - - 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& shortcuts() const; + 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 actions() const; + void triggerAction(const std::string& identifier, + const ghoul::Dictionary& arguments) const; static scripting::LuaLibrary luaLibrary(); private: - std::vector _shortcuts; + std::unordered_map _actions; }; } // namespace openspace::interaction -#endif // __OPENSPACE_CORE___SHORTCUTMANAGER___H__ +#endif // __OPENSPACE_CORE___ACTIONMANAGER___H__ diff --git a/include/openspace/interaction/camerainteractionstates.h b/include/openspace/interaction/camerainteractionstates.h index ba51a74348..e619b1eaaf 100644 --- a/include/openspace/interaction/camerainteractionstates.h +++ b/include/openspace/interaction/camerainteractionstates.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); diff --git a/include/openspace/interaction/joystickinputstate.h b/include/openspace/interaction/joystickinputstate.h index c5d320c7b8..e256f39552 100644 --- a/include/openspace/interaction/joystickinputstate.h +++ b/include/openspace/interaction/joystickinputstate.h @@ -28,6 +28,7 @@ #include #include #include +#include #include #include #include @@ -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 diff --git a/include/openspace/interaction/keybindingmanager.h b/include/openspace/interaction/keybindingmanager.h index e837da5c36..196848a939 100644 --- a/include/openspace/interaction/keybindingmanager.h +++ b/include/openspace/interaction/keybindingmanager.h @@ -28,7 +28,6 @@ #include #include -#include 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> keyBinding( - const std::string& key) const; - - std::vector> keyBinding( + std::vector> keyBinding( const KeyWithModifier& key) const; static scripting::LuaLibrary luaLibrary(); @@ -76,10 +57,10 @@ public: std::string generateJson() const override; - const std::multimap& keyBindings() const; + const std::multimap& keyBindings() const; private: - std::multimap _keyLua; + std::multimap _keyLua; }; } // namespace openspace::interaction diff --git a/include/openspace/interaction/sessionrecording.h b/include/openspace/interaction/sessionrecording.h index 6e7167e8b3..c04a13ece1 100644 --- a/include/openspace/interaction/sessionrecording.h +++ b/include/openspace/interaction/sessionrecording.h @@ -26,7 +26,7 @@ #define __OPENSPACE_CORE___SESSIONRECORDING___H__ #include -#include +#include #include #include #include @@ -145,6 +145,19 @@ public: */ std::chrono::steady_clock::time_point currentPlaybackInterpolationTime() const; + /** + * Returns the simulated application time. This simulated application time is only + * used when playback is set to be in the mode where a screenshot is captured with + * every rendered frame (enableTakeScreenShotDuringPlayback() is used to enable this + * mode). At the start of playback, this timer is set to the value of the current + * applicationTime function provided by the window delegate (used during normal + * mode or playback). However, during playback it is incremented by the fixed + * framerate of the playback rather than the actual clock value. + * + * \returns application time in seconds, for use in playback-with-frames mode + */ + double currentApplicationInterpolationTime() const; + /** * Starts a recording session, which will save data to the provided filename * according to the data format specified, and will continue until recording is @@ -719,6 +732,7 @@ protected: double _saveRenderingCurrentRecordedTime; std::chrono::steady_clock::duration _saveRenderingDeltaTime_interpolation_usec; std::chrono::steady_clock::time_point _saveRenderingCurrentRecordedTime_interpolation; + double _saveRenderingCurrentApplicationTime_interpolation; long long _saveRenderingClockInterpolation_countsPerSec; bool _saveRendering_isFirstFrame = true; @@ -818,16 +832,16 @@ public: ~SessionRecording_legacy_0085() {} char FileHeaderVersion[FileHeaderVersionLength+1] = "00.85"; char TargetConvertVersion[FileHeaderVersionLength+1] = "01.00"; - std::string fileFormatVersion() { + std::string fileFormatVersion() override { return std::string(FileHeaderVersion); } - std::string targetFileFormatVersion() { + std::string targetFileFormatVersion() override { return std::string(TargetConvertVersion); } - std::string getLegacyConversionResult(std::string filename, int depth); + std::string getLegacyConversionResult(std::string filename, int depth) override; struct ScriptMessage_legacy_0085 : public datamessagestructures::ScriptMessage { - void read(std::istream* in) { + void read(std::istream* in) override { size_t strLen; //Read string length from file in->read(reinterpret_cast(&strLen), sizeof(strLen)); @@ -846,7 +860,7 @@ public: protected: bool convertScript(std::stringstream& inStream, DataMode mode, int lineNum, - std::string& inputLine, std::ofstream& outFile, unsigned char* buffer); + std::string& inputLine, std::ofstream& outFile, unsigned char* buffer) override; }; } // namespace openspace diff --git a/include/openspace/interaction/keyframenavigator.h b/include/openspace/navigation/keyframenavigator.h similarity index 100% rename from include/openspace/interaction/keyframenavigator.h rename to include/openspace/navigation/keyframenavigator.h index 767aced843..a651dd805d 100644 --- a/include/openspace/interaction/keyframenavigator.h +++ b/include/openspace/navigation/keyframenavigator.h @@ -25,8 +25,8 @@ #ifndef __OPENSPACE_CORE___KEYFRAMENAVIGATOR___H__ #define __OPENSPACE_CORE___KEYFRAMENAVIGATOR___H__ -#include #include +#include #include #include #include diff --git a/include/openspace/interaction/navigationhandler.h b/include/openspace/navigation/navigationhandler.h similarity index 87% rename from include/openspace/interaction/navigationhandler.h rename to include/openspace/navigation/navigationhandler.h index 15d080330b..8738c04caa 100644 --- a/include/openspace/interaction/navigationhandler.h +++ b/include/openspace/navigation/navigationhandler.h @@ -28,12 +28,15 @@ #include #include #include -#include -#include -#include #include +#include +#include +#include +#include +#include #include #include +#include #include #include #include @@ -48,31 +51,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 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 up; - double yaw = 0.0; - double pitch = 0.0; - }; - NavigationHandler(); ~NavigationHandler(); @@ -80,11 +66,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 +85,7 @@ public: const OrbitalNavigator& orbitalNavigator() const; OrbitalNavigator& orbitalNavigator(); KeyframeNavigator& keyframeNavigator(); + PathNavigator& pathNavigator(); bool isKeyFrameInteractionEnabled() const; float interpolationTime() const; @@ -154,7 +139,8 @@ public: static scripting::LuaLibrary luaLibrary(); private: - void applyNavigationState(const NavigationHandler::NavigationState& ns); + void applyNavigationState(const NavigationState& ns); + void updateCameraTransitions(); bool _playbackModeEnabled = false; @@ -162,8 +148,13 @@ private: Camera* _camera = nullptr; std::function _playbackEndCallback; + inline static const double InteractionHystersis = 0.0125; + bool _inAnchorApproachSphere = false; + bool _inAnchorReachSphere = false; + OrbitalNavigator _orbitalNavigator; KeyframeNavigator _keyframeNavigator; + PathNavigator _pathNavigator; std::optional _pendingNavigationState; diff --git a/include/openspace/navigation/navigationstate.h b/include/openspace/navigation/navigationstate.h new file mode 100644 index 0000000000..915f5b1b93 --- /dev/null +++ b/include/openspace/navigation/navigationstate.h @@ -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 +#include + +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 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 up; + double yaw = 0.0; + double pitch = 0.0; +}; + +} // namespace openspace::interaction + +#endif // __OPENSPACE_CORE___NAVIGATIONSTATE___H__ diff --git a/include/openspace/interaction/orbitalnavigator.h b/include/openspace/navigation/orbitalnavigator.h similarity index 79% rename from include/openspace/interaction/orbitalnavigator.h rename to include/openspace/navigation/orbitalnavigator.h index a8e2a02697..c964e1eef9 100644 --- a/include/openspace/interaction/orbitalnavigator.h +++ b/include/openspace/navigation/orbitalnavigator.h @@ -33,6 +33,7 @@ #include #include #include +#include #include #include #include @@ -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; 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 _retargetAnchorInterpolator; Interpolator _cameraToSurfaceDistanceInterpolator; Interpolator _followRotationInterpolator; + Interpolator _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 cameraRotation = globalRotation * localRotation. */ @@ -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 diff --git a/include/openspace/navigation/path.h b/include/openspace/navigation/path.h new file mode 100644 index 0000000000..baec1ad261 --- /dev/null +++ b/include/openspace/navigation/path.h @@ -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 +#include +#include +#include +#include + +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 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 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 _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__ diff --git a/src/interaction/shortcutmanager.cpp b/include/openspace/navigation/pathcurve.h similarity index 50% rename from src/interaction/shortcutmanager.cpp rename to include/openspace/navigation/pathcurve.h index 1170ce8f3e..ed0a4c5991 100644 --- a/src/interaction/shortcutmanager.cpp +++ b/include/openspace/navigation/pathcurve.h @@ -22,66 +22,80 @@ * OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. * ****************************************************************************************/ -#include +#ifndef __OPENSPACE_CORE___PATHCURVE___H__ +#define __OPENSPACE_CORE___PATHCURVE___H__ -#include -#include -#include #include -#include - -#include "shortcutmanager_lua.inl" +#include namespace openspace::interaction { -void ShortcutManager::resetShortcuts() { - _shortcuts.clear(); -} +class Waypoint; -void ShortcutManager::addShortcut(ShortcutInformation info) { - _shortcuts.push_back(std::move(info)); -} +class PathCurve { +public: + virtual ~PathCurve() = 0; -const std::vector& -ShortcutManager::shortcuts() const -{ - return _shortcuts; -} + double length() const; -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." - } - } + /** + * 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 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 _points; + unsigned int _nSegments = 0; + + std::vector _curveParameterSteps; // per segment + std::vector _lengthSums; // per segment + double _totalLength = 0.0; + + struct ParameterPair { + double u; // curve parameter + double s; // arc length parameter }; -} + + std::vector _parameterSamples; +}; + +class LinearCurve : public PathCurve { +public: + LinearCurve(const Waypoint& start, const Waypoint& end); +}; } // namespace openspace::interaction + +#endif // __OPENSPACE_CORE___PATHCURVE___H__ diff --git a/include/openspace/navigation/pathcurves/avoidcollisioncurve.h b/include/openspace/navigation/pathcurves/avoidcollisioncurve.h new file mode 100644 index 0000000000..b48a0529a7 --- /dev/null +++ b/include/openspace/navigation/pathcurves/avoidcollisioncurve.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 + +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 _relevantNodes; +}; + +} // namespace openspace::interaction + +#endif // __OPENSPACE_CORE___AVOIDCOLLISIONCURVE___H__ diff --git a/modules/imgui/include/guiassetcomponent.h b/include/openspace/navigation/pathcurves/zoomoutoverviewcurve.h similarity index 80% rename from modules/imgui/include/guiassetcomponent.h rename to include/openspace/navigation/pathcurves/zoomoutoverviewcurve.h index cd8b2bf6cc..dec8286e36 100644 --- a/modules/imgui/include/guiassetcomponent.h +++ b/include/openspace/navigation/pathcurves/zoomoutoverviewcurve.h @@ -22,25 +22,20 @@ * OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. * ****************************************************************************************/ -#ifndef __OPENSPACE_MODULE_IMGUI___GUIASSETCOMPONENT___H__ -#define __OPENSPACE_MODULE_IMGUI___GUIASSETCOMPONENT___H__ +#ifndef __OPENSPACE_CORE___ZOOMOUTOVERVIEWCURVE___H__ +#define __OPENSPACE_CORE___ZOOMOUTOVERVIEWCURVE___H__ -#include +#include -namespace openspace { class Asset; } +namespace openspace::interaction { -namespace openspace::gui { +class WayPoint; -class GuiAssetComponent : public GuiComponent { +class ZoomOutOverviewCurve : public PathCurve { public: - GuiAssetComponent(); - - void render() override; - -private: - void renderTree(const Asset& asset, const std::string& relativeToPath); + ZoomOutOverviewCurve(const Waypoint& start, const Waypoint& end); }; -} // namespace openspace::gui +} // namespace openspace::interaction -#endif // __OPENSPACE_MODULE_IMGUI___GUIASSETCOMPONENT___H__ +#endif // __OPENSPACE_CORE___ZOOMOUTOVERVIEWCURVE___H__ diff --git a/include/openspace/navigation/pathnavigator.h b/include/openspace/navigation/pathnavigator.h new file mode 100644 index 0000000000..aac05b038d --- /dev/null +++ b/include/openspace/navigation/pathnavigator.h @@ -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 + +#include +#include +#include +#include +#include +#include +#include +#include + +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& 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 _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 _relevantNodes; + bool _hasInitializedRelevantNodes = false; +}; + +} // namespace openspace::interaction + +#endif // __OPENSPACE_CORE___PATHNAVIGATOR___H__ diff --git a/include/openspace/navigation/waypoint.h b/include/openspace/navigation/waypoint.h new file mode 100644 index 0000000000..09970bb261 --- /dev/null +++ b/include/openspace/navigation/waypoint.h @@ -0,0 +1,62 @@ +/***************************************************************************************** + * * + * 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___WAYPOINT___H__ +#define __OPENSPACE_CORE___WAYPOINT___H__ + +#include +#include +#include + +namespace openspace { class SceneGraphNode; } + +namespace openspace::interaction { + +struct NavigationState; + +class Waypoint { +public: + Waypoint() = default; + Waypoint(const glm::dvec3& pos, const glm::dquat& rot, const std::string& ref); + explicit Waypoint(const NavigationState& ns); + + static double findValidBoundingSphere(const SceneGraphNode* node); + + 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; + // to be able to handle nodes with faulty bounding spheres + double _validBoundingSphere = 0.0; +}; + +} // namespace openspace::interaction + +#endif // __OPENSPACE_CORE___WAYPOINT___H__ diff --git a/include/openspace/network/messagestructures.h b/include/openspace/network/messagestructures.h index effe727cbe..f7b0d78fab 100644 --- a/include/openspace/network/messagestructures.h +++ b/include/openspace/network/messagestructures.h @@ -196,7 +196,9 @@ struct CameraKeyframe { << std::fixed << std::setprecision(7) << _rotation.y << ' ' << std::fixed << std::setprecision(7) << _rotation.z << ' ' << std::fixed << std::setprecision(7) << _rotation.w << ' '; - out << std::scientific << _scale << ' '; + out << std::fixed + << std::setprecision(std::numeric_limits::max_digits10) + << _scale << ' '; if (_followNodeRotation) { out << "F "; } diff --git a/include/openspace/properties/selectionproperty.h b/include/openspace/properties/selectionproperty.h index b17f580a52..f8d4b59ba8 100644 --- a/include/openspace/properties/selectionproperty.h +++ b/include/openspace/properties/selectionproperty.h @@ -114,7 +114,8 @@ public: using TemplateProperty>::operator=; protected: - std::set fromLuaConversion(lua_State* state, bool& success) const override; + std::set fromLuaConversion(lua_State* state, + bool& success) const override; void toLuaConversion(lua_State* state) const override; diff --git a/include/openspace/properties/templateproperty.h b/include/openspace/properties/templateproperty.h index a9ccd7a8b7..7ad5423c4a 100644 --- a/include/openspace/properties/templateproperty.h +++ b/include/openspace/properties/templateproperty.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 std::type_info describing the template parameter diff --git a/include/openspace/rendering/abufferrenderer.h b/include/openspace/rendering/abufferrenderer.h deleted file mode 100644 index 5769c1e28c..0000000000 --- a/include/openspace/rendering/abufferrenderer.h +++ /dev/null @@ -1,183 +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_CORE___ABUFFERRENDERER___H__ -#define __OPENSPACE_CORE___ABUFFERRENDERER___H__ - -#ifdef OPENSPACE_WITH_ABUFFER_RENDERER - -#include -#include - -#include -#include -#include -#include -#include -#include -#include - -namespace ghoul::filesystem { class File; } - -namespace ghoul::opengl { - class ProgramObject; - class Texture; -} // namespace ghoul::opengl - -namespace openspace { - -struct RaycasterTask; -class RenderableVolume; -class Camera; -class Scene; -struct RaycastData; - -class ABufferRenderer : public Renderer, public RaycasterListener { -public: - virtual ~ABufferRenderer() = default; - - void initialize() override; - void deinitialize() override; - - void setResolution(glm::ivec2 res) override; - void setNAaSamples(int nAaSamples) override; - void setBlurrinessLevel(int level) override; - void setHDRExposure(float hdrExposure) override; - void setGamma(float gamma) override; - void setMaxWhite(float maxWhite) override; - void setToneMapOperator(int tmOp) override; - void setBloomThreMin(float minV) override; - void setBloomThreMax(float maxV) override; - void setBloomOrigFactor(float origFactor) override; - void setBloomNewFactor(float newFactor) override; - void setKey(float key) override; - void setYwhite(float white) override; - void setTmoSaturation(float sat) override; - void setHue(float hue) override; - void setValue(float value) override; - void setSaturation(float sat) override; - void setLightness(float lightness) override; - void setColorSpace(unsigned int colorspace) override; - - void enableBloom(bool enable) override; - void enableHistogram(bool enable) override; - - int nAaSamples() const override; - const std::vector& mSSAPattern() const override; - - using Renderer::preRaycast; - void preRaycast(const RaycasterTask& raycasterTask); - using Renderer::postRaycast; - void postRaycast(const RaycasterTask& raycasterTask); - - void update() override; - void render(Scene* scene, Camera* camera, float blackoutFactor) override; - - /** - * Update render data - * Responsible for calling renderEngine::setRenderData - */ - virtual void updateRendererData() override; - virtual void raycastersChanged(VolumeRaycaster& raycaster, - IsAttached attached) override; - -private: - void clear(); - void updateResolution(); - void updateRaycastData(); - void updateResolveDictionary(); - void updateMSAASamplingPattern(); - void saveTextureToMemory(GLenum color_buffer_attachment, int width, int height, - std::vector & memory) const; - - glm::ivec2 _resolution = glm::ivec2(0); - - bool _dirtyResolution = true; - bool _dirtyRendererData = true; - bool _dirtyRaycastData = true; - bool _dirtyResolveDictionary = true; - - std::unique_ptr _resolveProgram = nullptr; - - /** - * When a volume is attached or detached from the scene graph, - * the resolve program needs to be recompiled. - * The _volumes map keeps track of which volumes that can - * be rendered using the current resolve program, along with their raycast data - * (id, namespace, etc) - */ - std::map _raycastData; - std::map< - VolumeRaycaster*, std::unique_ptr - > _boundsPrograms; - std::vector _helperPaths; - - ghoul::Dictionary _resolveDictionary; - - GLuint _mainColorTexture; - GLuint _mainDepthTexture; - - GLuint _mainFramebuffer; - GLuint _screenQuad; - GLuint _anchorPointerTexture; - GLuint _anchorPointerTextureInitializer; - GLuint _atomicCounterBuffer; - GLuint _fragmentBuffer; - GLuint _fragmentTexture; - GLuint _vertexPositionBuffer; - int _nAaSamples; - int _blurrinessLevel = 1; - - float _hdrExposure = 0.4f; - float _hdrBackground = 2.8f; - float _gamma = 2.2f; - float _maxWhite = 1.f; - float _blackoutFactor; - bool _bloomEnabled = false; - float _bloomThresholdMin = 0.0; - float _bloomThresholdMax = 1.0; - float _bloomOrigFactor = 1.0; - float _bloomNewFactor = 1.0; - int _toneMapOperator = 0; - bool _histogramEnabled = false; - int _numberOfBins = 1024; // JCC TODO: Add a parameter control for this. - float _tmoKey = 0.18f; - float _tmoYwhite = 1e6f; - float _tmoSaturation = 1.0f; - float _hue = 1.f; - float _saturation = 1.f; - float _value = 1.f; - float _lightness = 1.f; - unsigned int _colorSpace = 1; - - std::vector _mSAAPattern; - - ghoul::Dictionary _rendererData; -}; - -} // namespace openspace - -#endif // OPENSPACE_WITH_ABUFFER_RENDERER - -#endif // __OPENSPACE_CORE___ABUFFERRENDERER___H__ diff --git a/include/openspace/rendering/deferredcaster.h b/include/openspace/rendering/deferredcaster.h index 3d9f476848..c0b2f12d1e 100644 --- a/include/openspace/rendering/deferredcaster.h +++ b/include/openspace/rendering/deferredcaster.h @@ -51,8 +51,6 @@ public: const DeferredcastData& /*deferredData*/, ghoul::opengl::ProgramObject& /*program*/) {}; - virtual std::filesystem::path deferredcastPath() const = 0; - virtual std::filesystem::path deferredcastVSPath() const = 0; virtual std::filesystem::path deferredcastFSPath() const = 0; diff --git a/include/openspace/rendering/framebufferrenderer.h b/include/openspace/rendering/framebufferrenderer.h index d76c2c5d88..b4207b8dcf 100644 --- a/include/openspace/rendering/framebufferrenderer.h +++ b/include/openspace/rendering/framebufferrenderer.h @@ -25,8 +25,6 @@ #ifndef __OPENSPACE_CORE___FRAMEBUFFERRENDERER___H__ #define __OPENSPACE_CORE___FRAMEBUFFERRENDERER___H__ -#include -#include #include #include @@ -56,14 +54,14 @@ struct RaycasterTask; class Scene; struct UpdateStructures; -class FramebufferRenderer : public Renderer, public RaycasterListener, +class FramebufferRenderer : public RaycasterListener, public DeferredcasterListener { public: virtual ~FramebufferRenderer() = default; - void initialize() override; - void deinitialize() override; + void initialize(); + void deinitialize(); void updateResolution(); void updateRaycastData(); @@ -72,28 +70,28 @@ public: void updateFXAA(); void updateDownscaledVolume(); - void setResolution(glm::ivec2 res) override; - void setHDRExposure(float hdrExposure) override; - void setGamma(float gamma) override; - void setHue(float hue) override; - void setValue(float value) override; - void setSaturation(float sat) override; + void setResolution(glm::ivec2 res); + void setHDRExposure(float hdrExposure); + void setGamma(float gamma); + void setHue(float hue); + void setValue(float value); + void setSaturation(float sat); - void enableFXAA(bool enable) override; - void setDisableHDR(bool disable) override; + void enableFXAA(bool enable); + void setDisableHDR(bool disable); - void update() override; + void update(); void performRaycasterTasks(const std::vector& tasks, const glm::ivec4& viewport); void performDeferredTasks(const std::vector& tasks, const glm::ivec4& viewport); - void render(Scene* scene, Camera* camera, float blackoutFactor) override; + void render(Scene* scene, Camera* camera, float blackoutFactor); /** * Update render data * Responsible for calling renderEngine::setRenderData */ - virtual void updateRendererData() override; + virtual void updateRendererData(); virtual void raycastersChanged(VolumeRaycaster& raycaster, RaycasterListener::IsAttached attached) override; diff --git a/include/openspace/rendering/renderengine.h b/include/openspace/rendering/renderengine.h index 28cee7e43a..6da4d21c0d 100644 --- a/include/openspace/rendering/renderengine.h +++ b/include/openspace/rendering/renderengine.h @@ -32,7 +32,9 @@ #include #include #include +#include #include +#include #include #include @@ -54,7 +56,6 @@ namespace scripting { struct LuaLibrary; } class Camera; class RaycasterManager; class DeferredcasterManager; -class Renderer; class Scene; class SceneManager; class ScreenLog; @@ -63,12 +64,6 @@ struct ShutdownInformation; class RenderEngine : public properties::PropertyOwner { public: - enum class RendererImplementation { - Framebuffer = 0, - ABuffer, - Invalid - }; - RenderEngine(); ~RenderEngine(); @@ -80,9 +75,6 @@ public: Scene* scene(); void updateScene(); - const Renderer& renderer() const; - RendererImplementation rendererImplementation() const; - ghoul::opengl::OpenGLStateCache& openglStateCache(); void updateShaderPrograms(); @@ -120,24 +112,11 @@ public: void removeRenderProgram(ghoul::opengl::ProgramObject* program); - /** - * Set raycasting uniforms on the program object, and setup raycasting. - */ - void preRaycast(ghoul::opengl::ProgramObject& programObject); - - /** - * Tear down raycasting for the specified program object. - */ - void postRaycast(ghoul::opengl::ProgramObject& programObject); - /** * Set the camera to use for rendering */ void setCamera(Camera* camera); - - void setRendererFromString(const std::string& renderingMethod); - /** * Lets the renderer update the data to be brought into the rendererer programs * as a 'rendererData' variable in the dictionary. @@ -176,9 +155,6 @@ public: uint64_t frameNumber() const; private: - void setRenderer(std::unique_ptr renderer); - RendererImplementation rendererFromString(const std::string& renderingMethod) const; - void renderScreenLog(); void renderVersionInformation(); void renderCameraInformation(); @@ -188,13 +164,12 @@ private: Camera* _camera = nullptr; Scene* _scene = nullptr; - std::unique_ptr _renderer; - RendererImplementation _rendererImplementation = RendererImplementation::Invalid; + FramebufferRenderer _renderer; ghoul::Dictionary _rendererData; ghoul::Dictionary _resolveData; ScreenLog* _log = nullptr; - ghoul::opengl::OpenGLStateCache* _openglStateCache; + ghoul::opengl::OpenGLStateCache* _openglStateCache = nullptr; properties::BoolProperty _showOverlayOnSlaves; properties::BoolProperty _showLog; @@ -245,6 +220,9 @@ private: } _cameraButtonLocations; std::string _versionString; + + properties::Vec4Property _enabledFontColor; + properties::Vec4Property _disabledFontColor; }; } // namespace openspace diff --git a/include/openspace/scene/asset.h b/include/openspace/scene/asset.h index d20f42ccd2..eeb2dd72de 100644 --- a/include/openspace/scene/asset.h +++ b/include/openspace/scene/asset.h @@ -26,156 +26,276 @@ #define __OPENSPACE_CORE___ASSET___H__ #include -#include -#include +#include #include -#include -#include namespace openspace { -class AssetLoader; +class AssetManager; -class Asset : public std::enable_shared_from_this { +/** + * This class represents a successfully loaded Asset. Each Lua asset file results in + * exactly one instance of this class unless it contains a syntax error or some other + * error occurred while loading. Each Asset can have 0-* number of resource + * synchronizations that were requested through the `syncedResource` function in Lua and + * 0-* number of other Assets that this Asset requires (through the `require` function in + * Lua. There also is a list of requiring assets that contain all assets which require + * this asset. + * An asset goes through three external states. Starting out as unloaded when the instance + * is newly created but the file has not been processed. In this case the #isLoaded, + * #isSynchronized and the #isInitialized functions all return \c false. After the asset + * has been loaded it is in the \c Loaded state (#isLoaded = true, + * #isSynchronized = false, #isInitialized = false). After all registered synchronizations + * finish successfully, the Asset transitions into the Synchronized state + * (#isLoaded = true, #isSynchronized = true, #isInitialized = false) and after the final + * initialization step, the asset is initialized (#isLoaded = true, + * #isSynchronized = true and #isInitialized = true) + */ +class Asset { public: - enum class State { - Unloaded, - LoadingFailed, - Loaded, - Synchronizing, - SyncResolved, - SyncRejected, - Initialized, - InitializationFailed - }; - + /// This struct contains all the meta information about this asset struct MetaInformation { + /// The name of the asset std::string name; + /// The version number of the asset. This is only a string representation and does + /// not have to follow SemVer (even though it is advised) std::string version; + /// A user-facing description of the asset contents std::string description; + /// The author of the asset std::string author; + /// A URL where a consumer of the asset might find additional information about, + /// for example, the author or the used dataset(s) std::string url; + /// The license under which this asset has been provided std::string license; + /// A list of all scene graph nodes that have been created in this asset std::vector identifiers; }; /** - * Root asset constructor + * Creates a new Asset that is backed by the provided \p assetPath. The \p manager is + * the AssetManager instance that is responsible for loading this and all the other + * required Assets. + * + * \param manager The AssetManager that is responsible for loading this Asset and all + * of its dependencies + * \param assetPath The file path that will be used to load this Asset + * + * \pre The \p assetPath must not be empty and must be an existing file */ - Asset(AssetLoader* loader, SynchronizationWatcher* watcher); + Asset(AssetManager& manager, std::filesystem::path assetPath); /** - * Regular asset constructor + * Returns the path to the file that was used to initialize this Asset. + * + * \return The path to the file that was used to initialize this Asset */ - Asset(AssetLoader* loader, SynchronizationWatcher* watcher, std::string assetPath); - - std::string id() const; - const std::string& assetFilePath() const; - bool hasAssetFile() const; - std::string assetDirectory() const; - const std::string& assetName() const; - AssetLoader* loader() const; - State state() const; - - void addSynchronization(std::unique_ptr synchronization); - void clearSynchronizations(); - std::vector ownSynchronizations() const; - - void syncStateChanged(ResourceSynchronization* sync, - ResourceSynchronization::State state); + std::filesystem::path path() const; /** - * Load this asset and return true if successful, - * i.e. if this and all required assets loaded without errors. + * Adds a new dependent ResourceSynchronization object to this Asset. + * + * \param synchronization The resource synchronization object that is bound to this + * Asset + * \pre \p synchronization must not be nullptr + * \pre \p synchronization must not have been added to this Asset before + */ + void addSynchronization(ResourceSynchronization* synchronization); + + /** + * Updates the state of this Asset based on the latest synchronization being + * successfully resolved. Depending on the sum state of all registered + * synchronizations this Asset's state changes to successfully Synchronized, or Failed + */ + void setSynchronizationStateResolved(); + + /** + * Updates the state of this Asset based on the latest synchronization being rejected. + * Depending on the sum state of all registered synchronizations this Asset's state + * changes to successfully Synchronized, or Failed + */ + void setSynchronizationStateRejected(); + + /** + * If the asset has not yet been loaded, this function loads the asset and returns the + * success state. If the loading succeeded, the Asset transitions into the \c Loaded + * state. The \p parent that is provided is the Asset that caused this load operation + * to be triggered and might be \c nullptr if this asset does not have any parents. If + * this Asset has been previously loaded (even with a different \p parent), this + * function does nothing. + * + * \param parent The parent asset (or \c nullptr) that triggered this loading + */ + void load(Asset* parent); + + /** + * Returns \c true if this Asset has at least one parent that is in the Loaded state. + * + * \return \c true if this Asset has at least one parent that is in the Loaded state */ - bool load(); bool hasLoadedParent(); + + /** + * Returns \c true if this Asset has been successfully #load ed. + * + * /return \c true if this Asset has been successfully loaded + */ bool isLoaded() const; + + /** + * Unloads this Asset and unrequires all of its required assets, potentially causing + * a cascading effect of further #unload calls if this asset was those required assets + * only parent. After this call, this Asset will be in the Unloaded state. If this + * Asset has already been unloaded (or has not yet been loaded), this function does + * nothing. + */ void unload(); - void unloadIfUnwanted(); /** - * Start synchronizations of this asset and return true if all - * its own synchronizations and required assets' synchronizations could start. + * Starts the registered synchronizations of this asset and returns \c true if all its + * synchronizations and required assets' synchronizations could start. When all + * synchronizations have completed successfully, this Asset transitions into the + * Synchronized state. + * + * \pre This Asset must have been Loaded before */ - bool startSynchronizations(); - float requiredSynchronizationProgress() const; - float requestedSynchronizationProgress(); + void startSynchronizations(); /** - * Initialize this asset and return true if successful, - * i.e. if this and all required assets initialized without errors. + * Returns \c true if this Asset's synchronizations (if any) have completed + * successfully. + * + * \return \c true if this Asset is in the Synchronized or Initialized state + */ + bool isSynchronized() const; + + /** + * Initializes this asset and returns \c true if the initialized succeeded, i.e. if + * this and all required assets initialized without errors. After this call, if it has + * been successful, this Asset is in the Initialized state. If the Asset has already + * been initialized, calling this function does nothing. + */ + void initialize(); + + /** + * Returns \c true if this Asset has been #initialize d successfully. + * + * \return \c true if this Asset has been #initialize d successfully. It returns + * \c false both if this initialization failed as well as if thie #initialize + * function has not been called on this Asset */ - bool initialize(); - bool hasInitializedParent() const; bool isInitialized() const; + + /** + * Returns whether any of the parents of this Asset is currently in an initialized + * state, meaning that any parent is still interested in this Asset at all. + * + * \return \c true if there is at least one initialized parent, \c false otherwise + */ + bool hasInitializedParent() const; + + /** + * Deinitializes this Asset and recursively deinitializes the required assets if this + * Asset was their ownly initialized parent. If the Asset was already deinitialized, + * calling this function does nothing. + */ void deinitialize(); - void deinitializeIfUnwanted(); - // Dependency graph - bool requires(const Asset* asset) const; - void require(std::shared_ptr child); - void unrequire(Asset* child); + /** + * Marks the passed \p child as being required by \p this Asset. If the \p child is + * already required by this asset, this function does nothing. + * + * \param child The asset that is required by this asset + * \pre \p child must not be nullptr + */ + void require(Asset* child); - bool requests(Asset* asset) const; - void request(std::shared_ptr child); - void unrequest(Asset* child); - - std::vector requestedAssets() const; - std::vector requestingAssets() const; - std::vector requiredAssets() const; - std::vector requiringAssets() const; - - std::vector subTreeAssets() const; - std::vector childAssets() const; + /** + * Returns \c true if the loading of the Asset has failed in any way so that + * recovering from the error is impossible. + * + * \return \c true if the Asset handling failed in any way, \c false otherwise + */ + bool isFailed() const; + /** + * Sets the provided \p metaInformation as the meta information struct for this asset. + * If previous information existed, it will be silently overwritten. + * + * \param metaInformation The meta information about this asset + */ void setMetaInformation(MetaInformation metaInformation); + + /** + * Returns the meta information of this asset back to the caller. If no such + * information exists, a \c std::nullopt will be returned. + * + * \return The MetaInformation about this asset or \c std::nullopt + */ std::optional metaInformation() const; private: + /// All of the (internal) states that the Asset can move through. The externally + /// visible states (Loaded, Synchronized, Initialized) are a subset of these states + enum class State { + /// The asset is created, but the Lua file has not been executed yet + Unloaded, + /// The execution of the asset file as Lua failed with some error + LoadingFailed, + /// The loading of the asset file succeeded + Loaded, + /// The Asset is currently synchronizing its ResourceSynchronizations and waiting + /// for them to finish + Synchronizing, + /// All registered synchronizations have completed successfully + Synchronized, + /// At least one of the registered synchronizations failed to synchronize + SyncRejected, + /// The onInitialize method (if the asset has one) was executed successfully + Initialized, + /// The execution of the onInitialize method (if existing) resulted in a Lua error + InitializationFailed + }; + + /** + * Sets the \p state of this Asset to the new state. Depending on the current state of + * this Asset, if \p state is a state related to the synchronization, it will + * potentially propagate to this Asset's parents and cause them to be set to be + * successfully synchronized or faild. + * + * \param state The new State that this Asset is set to + */ void setState(State state); - void requiredAssetChangedState(Asset::State childState); - void requestedAssetChangedState(Asset* child, Asset::State childState); - - bool isSynchronized() const; + /// Returns whether the Asset is synchronizing or has successfully synchronized bool isSyncingOrResolved() const; - bool isSyncResolveReady(); - bool hasSyncingOrResolvedParent() const; - bool cancelAllSynchronizations(); - bool cancelUnwantedSynchronizations(); - std::vector requiredSubTreeAssets() const; + /// Returns whether the Asset has been successfully synchronized, meaning that both + /// its own resource synchronizations are finished as well as all requiered assets are + /// finished synchronizing + bool isSyncResolveReady() const; - std::atomic _state; - AssetLoader* _loader; - SynchronizationWatcher* _synchronizationWatcher; + /// The state that this Asset is currently in + std::atomic _state = State::Unloaded; - std::vector> _synchronizations; + /// Reference to the manager that is responsible for loading and unloading this asset + AssetManager& _manager; - bool _hasAssetPath; - // The name of the asset - std::string _assetName; - - // Absolute path to asset file - std::string _assetPath; + /// Absolute path to asset file + std::filesystem::path _assetPath; + /// Additional information about this asset, such as its name, author, license, etc std::optional _metaInformation; - // Required assets - std::vector> _requiredAssets; + /// Assets that are required by this asset + std::vector _requiredAssets; - // Assets that refers to this asset as a required asset - std::vector> _requiringAssets; + /// Assets that refers to this asset as a required asset + std::vector _parentAssets; - // Requested assets - std::vector> _requestedAssets; - - // Assets that refers to this asset as a requested asset - std::vector> _requestingAssets; - - // Synchronization watches - std::vector _syncWatches; + /// Synchronizations that were requested by this asset + std::vector _synchronizations; }; } // namespace openspace diff --git a/include/openspace/scene/assetloader.h b/include/openspace/scene/assetloader.h deleted file mode 100644 index 141dc5aa2c..0000000000 --- a/include/openspace/scene/assetloader.h +++ /dev/null @@ -1,225 +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_CORE___ASSETLOADER___H__ -#define __OPENSPACE_CORE___ASSETLOADER___H__ - -#include -#include -#include -#include -#include -#include - -struct lua_State; - -namespace ghoul::filesystem { class Directory; } -namespace ghoul::lua { class LuaState; } - -namespace openspace { - -namespace assetloader { - -int onInitialize(lua_State* state); -int onDeinitialize(lua_State* state); -int onInitializeDependency(lua_State* state); -int onDeinitializeDependency(lua_State* state); -int require(lua_State* state); -int exists(lua_State* state); -int localResource(lua_State* state); -int syncedResource(lua_State* state); -int exportAsset(lua_State* state); - -} // namespace assetloader - -class AssetListener; -class ResourceSynchronization; -class SynchronizationWatcher; - -class AssetLoader { -public: - AssetLoader(ghoul::lua::LuaState* luaState, SynchronizationWatcher* syncWatcher, - std::string assetRootDirectory); - - ~AssetLoader(); - - /** - * Add the asset as a request of the root asset - */ - std::shared_ptr add(const std::string& identifier); - - /** - * Remove the asset as a request of the root asset - */ - void remove(const std::string& identifier); - - /** - * Enable the asset to be reused when the same path is required/requested again - */ - void trackAsset(std::shared_ptr asset); - - /** - * Disable the asset from being reused when the same path is required/requested again - */ - void untrackAsset(Asset* asset); - - /** - * Return the asset identified by the identifier, - * if the asset is tracked. Otherwise return nullptr. - */ - std::shared_ptr has(const std::string& identifier) const; - - /// Return the root asset - const Asset& rootAsset() const; - - /// Return the root asset - Asset& rootAsset(); - - /** - * Return the asset root directory - */ - const std::string& assetRootDirectory() const; - - /** - * Load an asset - */ - bool loadAsset(Asset* asset); - - /** - * Unload an asset - */ - void unloadAsset(Asset* asset); - - /** - * Call the onInitialize function specified in the asset file - */ - void callOnInitialize(Asset* asset); - - /** - * Call the onDeinitialize function specified in the asset file - */ - void callOnDeinitialize(Asset* asset); - - /** - * Call the dependency.onInitialize function specified in the asset file - */ - void callOnDependencyInitialize(Asset* asset, Asset* dependant); - - /** - * Call the dependency.onDeinitialize function specified in the asset file - */ - void callOnDependencyDeinitialize(Asset* asset, Asset* dependant); - - /** - * Generate the absolute path for an asset specified as `path` - * relative to `baseDirectory` - */ - std::string generateAssetPath(const std::string& baseDirectory, - const std::string& assetPath) const; - - /** - * Add listener to asset state changes - */ - void addAssetListener(AssetListener* listener); - - /** - * Remove listener to asset state changes - */ - void removeAssetListener(AssetListener* listener); - - /** - * Notify listeners about asset state change - */ - void assetStateChanged(Asset* asset, Asset::State state); - - /** - * Notify listeners about new requests - */ - void assetRequested(Asset* parent, std::shared_ptr child); - - /** - * Notify listeners about removed requests - */ - void assetUnrequested(Asset* parent, std::shared_ptr child); - -private: - void unrequest(const std::string& identifier); - - void setUpAssetLuaTable(Asset* asset); - void tearDownAssetLuaTable(Asset* asset); - - std::shared_ptr getAsset(const std::string& name); - std::filesystem::path currentDirectory() const; - - void setCurrentAsset(Asset* asset); - void addLuaDependencyTable(Asset* dependant, Asset* dependency); - - // Lua functions - int onInitializeLua(Asset* asset); - int onDeinitializeLua(Asset* asset); - int onInitializeDependencyLua(Asset* dependant, Asset* dependency); - int onDeinitializeDependencyLua(Asset* dependant, Asset* dependency); - int requireLua(Asset* dependant); - int requestLua(Asset* parent); - int existsLua(Asset* asset); - int localResourceLua(Asset* asset); - int syncedResourceLua(Asset* asset); - int exportAssetLua(Asset* asset); - - // Friend C closures (callable from Lua, and maps to Lua functions above) - friend int assetloader::onInitialize(lua_State* state); - friend int assetloader::onDeinitialize(lua_State* state); - friend int assetloader::onInitializeDependency(lua_State* state); - friend int assetloader::onDeinitializeDependency(lua_State* state); - friend int assetloader::require(lua_State* state); - friend int assetloader::exists(lua_State* state); - friend int assetloader::localResource(lua_State* state); - friend int assetloader::syncedResource(lua_State* state); - friend int assetloader::exportAsset(lua_State* state); - - // Member variables - std::shared_ptr _rootAsset; - Asset* _currentAsset = nullptr; - std::unordered_map> _trackedAssets; - SynchronizationWatcher* _synchronizationWatcher; - std::string _assetRootDirectory; - ghoul::lua::LuaState* _luaState; - - // State change listeners - std::vector _assetListeners; - - // References to Lua values - std::unordered_map> _onInitializationFunctionRefs; - std::unordered_map> _onDeinitializationFunctionRefs; - std::unordered_map>> - _onDependencyInitializationFunctionRefs; - std::unordered_map>> - _onDependencyDeinitializationFunctionRefs; - - int _assetsTableRef = 0; -}; - -} // namespace openspace - -#endif // __OPENSPACE_CORE___ASSETLOADER___H__ diff --git a/include/openspace/scene/assetmanager.h b/include/openspace/scene/assetmanager.h index cec0176a17..93318c8f58 100644 --- a/include/openspace/scene/assetmanager.h +++ b/include/openspace/scene/assetmanager.h @@ -25,58 +25,184 @@ #ifndef __OPENSPACE_CORE___ASSETMANAGER___H__ #define __OPENSPACE_CORE___ASSETMANAGER___H__ -#include - -#include -#include #include -#include +#include #include -#include +#include namespace openspace { namespace scripting { struct LuaLibrary; } class Asset; -class AssetLoader; -class SynchronizationWatcher; +class ResourceSynchronization; /** - * Interface for managing assets. - * The asset manager interface is only concerned with "top level" assets, and not their - * dependencies. However, an asset is not considered synchronized before all its deps are - * synchronized. Also, setting a target state of an asset to Unloaded will only unload an - * asset from the system if it is not a dependency of a loaded asset. + * The AssetManager class manages the loading, initialization, and unloading of all assets + * loaded in OpenSpace. Most actions of this class are operating in a two-step process + * where first the intent of an action is registered, which is then executed in the next + * call to the #update function. + * All assets are loading through the same Lua state. */ -class AssetManager : AssetListener { +class AssetManager { public: - AssetManager(ghoul::lua::LuaState* state, std::string assetRootDirectory); + AssetManager(ghoul::lua::LuaState* state, std::filesystem::path assetRootDirectory); + ~AssetManager(); - virtual ~AssetManager() = default; - - void initialize(); void deinitialize(); + + /** + * Loads the asset at the provided \p path as a new root asset of the AssetManager. + * If the asset at that path was already loaded, nothing happens. + * + * \param path The path from which the Asset is loaded. This path can be either + * relative to the base directory (the path starting with . or ..), an absolute + * path (that path starting with *:/ or /) or relative to the global asset root + * (if the path starts any other way) + * \pre \p path must not be the empty string + */ void add(const std::string& path); + + /** + * Removes the asset at the provided \p path if it has been loaded by this + * AssetManager. If the asset at that path was not found, nothing happens. + * + * \param path The path from which the Asset is loaded. This path can be either + * relative to the base directory (the path starting with . or ..), an absolute + * path (that path starting with *:/ or /) or relative to the global asset root + * (if the path starts any other way) + * \pre \p path must not be the empty string + */ void remove(const std::string& path); - void removeAll(); - const Asset& rootAsset() const; - Asset& rootAsset(); - void assetStateChanged(Asset* asset, Asset::State state) override; - void assetRequested(Asset* parent, std::shared_ptr child) override; - void assetUnrequested(Asset* parent, std::shared_ptr child) override; + /** + * Update function that should be called at least once per frame that will load all + * queued asset loads and asset removal. + */ + void update(); - bool update(); scripting::LuaLibrary luaLibrary(); -private: - std::unordered_map _pendingStateChangeCommands; - std::mutex _pendingInitializationsMutex; - std::vector> _pendingInitializations; + /** + * Returns all assets that have been loaded by the AssetManager. The order of the + * assets is undefined. + * + * \return A list of all assets that have been previously loaded by the AssetManager + */ + std::vector allAssets() const; - SynchronizationWatcher _synchronizationWatcher; - AssetLoader _assetLoader; + std::vector allSynchronizations() const; + + /** + * Loads the provided \p asset as a child of the provided \p parent. Loading an asset + * means that asset file gets executed and the meta information is extracted from it. + * The \p parent is the asset file that caused this loading to happen and can be a + * \c nullptr if the asset is to be loaded as a root asset. + * + * \param asset The asset that should be loaded + * \param parent The parent of the loaded asset file or \c nullptr if the asset is a + * root asset + * \pre \p asset must not be a nullptr + */ + bool loadAsset(Asset* asset, Asset* parent); + + /** + * Unload the provided \p asset by removing all information about it from the Lua + * state and placing the asset onto the deletion queue. Please note that the asset + * will not actually get destroyed until the next #update call to the AssetManager. + * + * \param asset The asset that should get unloaded + * \pre \p asset must not be a nullptr + */ + void unloadAsset(Asset* asset); + + /** + * This function calls the `onInitialize` function that was specified in the file of + * the provided \p asset. + * + * \param asset The asset file whose `onInitialize` function should be called + */ + void callOnInitialize(Asset* asset) const; + + /** + * This function calls the `onDeinitialize` function that was specified in the file of + * the provided \p asset. + * + * \param asset The asset file whose `onDeinitialize` function should be called + */ + void callOnDeinitialize(Asset* asset) const; + +private: + /// Creates and registers all of the callback functions that the asset is expected to + /// call in the file, for example the `localResource`, `require`, etc. + void setUpAssetLuaTable(Asset* asset); + + /// Returns the loaded Asset by either trying to load the asset at the provided path + /// or returning a previously loaded copy + Asset* retrieveAsset(const std::filesystem::path& path); + + /// Setup the asset table of the provided asset in the shared Lua state + void setCurrentAsset(Asset* asset); + + /// Takes the asset path, determines the type of path (relative to base, relative to + /// root or absolute and returns fully formed path + std::filesystem::path generateAssetPath(const std::filesystem::path& baseDirectory, + const std::string& assetPath) const; + + // + // Assets + // + + /// The authoritative list of all assets loaded through the AssetManager + std::vector> _assets; + + /// A list of all root assets that have been loaded directly by the `add` function + std::vector _rootAssets; + + /// This list contains all of the assets that are queued to be loading in the next + /// update call + std::unordered_set _assetAddQueue; + + /// The list contains all of the assets that should be removed in the next update call + std::unordered_set _assetRemoveQueue; + + /// This list contains all assets that need to be initialized in the next update call + std::vector _toBeInitialized; + + /// This list contains all of the assets that will be deleted in the next update call + std::vector> _toBeDeleted; + + // + // ResourceSynchronizations + // + + /// Collection that stores the assets that have requested each ResourceSynchronization + struct SyncItem { + std::unique_ptr synchronization; + std::vector assets; + }; + /// Authoritative list over all ResourceSynchronizations that have been requested by + /// any asset + std::unordered_map> _synchronizations; + /// The list of ResourceSynchronizations that were not finished in the last update + /// call + std::vector _unfinishedSynchronizations; + + // + // Other values + // + + /// The location of the asset root directory + std::filesystem::path _assetRootDirectory; + + /// The Lua state that is used for all asset initialization + ghoul::lua::LuaState* _luaState = nullptr; + + // References to the onInitialize and the onDeinitialize functions for each Asset + std::unordered_map> _onInitializeFunctionRefs; + std::unordered_map> _onDeinitializeFunctionRefs; + + int _assetsTableRef = 0; }; } // namespace openspace diff --git a/include/openspace/scene/profile.h b/include/openspace/scene/profile.h index 28a3a360eb..eeb79b8adf 100644 --- a/include/openspace/scene/profile.h +++ b/include/openspace/scene/profile.h @@ -26,9 +26,9 @@ #define __OPENSPACE_CORE___PROFILE___H__ #include -#include #include #include +#include #include #include #include @@ -37,6 +37,8 @@ namespace openspace { +namespace interaction { struct NavigationState; } + namespace scripting { struct LuaLibrary; } class Profile { @@ -74,18 +76,22 @@ public: SetPropertyValueSingle }; - SetType setType; + SetType setType = SetType::SetPropertyValue; 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 +126,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 modules() const; - std::optional meta() const; - std::vector assets() const; - std::vector properties() const; - std::vector keybindings() const; - std::optional