Merge branch 'master' into issue/1964

This commit is contained in:
Malin E
2022-04-26 10:55:54 +02:00
2850 changed files with 96105 additions and 2998 deletions
+4 -32
View File
@@ -45,10 +45,9 @@ set(HEADER_FILES
include/profile/profileedit.h
include/profile/propertiesdialog.h
include/sgctedit/displaywindowunion.h
include/sgctedit/filesupport.h
include/sgctedit/monitorbox.h
include/sgctedit/orientation.h
include/sgctedit/orientationdialog.h
include/sgctedit/settingswidget.h
include/sgctedit/sgctedit.h
include/sgctedit/windowcontrol.h
)
@@ -75,39 +74,12 @@ set(SOURCE_FILES
src/profile/propertiesdialog.cpp
src/sgctedit/sgctedit.cpp
src/sgctedit/displaywindowunion.cpp
src/sgctedit/filesupport.cpp
src/sgctedit/monitorbox.cpp
src/sgctedit/orientation.cpp
src/sgctedit/orientationdialog.cpp
src/sgctedit/settingswidget.cpp
src/sgctedit/windowcontrol.cpp
)
set(HEADER_SOURCE
include/launcherwindow.h
include/profile/actiondialog.h
include/profile/additionalscriptsdialog.h
include/profile/assetsdialog.h
include/profile/assetedit.h
include/profile/assettreemodel.h
include/profile/cameradialog.h
include/profile/deltatimesdialog.h
include/profile/horizonsdialog.h
include/profile/scriptlogdialog.h
include/profile/marknodesdialog.h
include/profile/metadialog.h
include/profile/modulesdialog.h
include/profile/timedialog.h
include/profile/profileedit.h
include/profile/propertiesdialog.h
include/sgctedit/displaywindowunion.h
include/sgctedit/filesupport.h
include/sgctedit/monitorbox.h
include/sgctedit/orientation.h
include/sgctedit/orientationdialog.h
include/sgctedit/sgctedit.h
include/sgctedit/windowcontrol.h
)
find_package(QT NAMES Qt6 Qt5 COMPONENTS Core Widgets Network REQUIRED)
set(MOC_FILES "")
set(RESOURCE_FILES "")
@@ -117,7 +89,7 @@ if (${QT_VERSION_MAJOR} EQUAL 5)
find_package(Qt5 COMPONENTS Core Widgets Network)
qt5_wrap_cpp(
MOC_FILES
${HEADER_SOURCE}
${HEADER_FILES}
)
qt5_add_resources(RESOURCE_FILES resources/resources.qrc)
set(LIBRARIES )
@@ -126,7 +98,7 @@ elseif (${QT_VERSION_MAJOR} EQUAL 6)
qt6_wrap_cpp(
MOC_FILES
${HEADER_SOURCE}
${HEADER_FILES}
)
qt6_add_resources(RESOURCE_FILES resources/resources.qrc)
elseif (NOT DEFINED QT_VERSION_MAJOR)
@@ -37,7 +37,7 @@ namespace openspace::configuration { struct Configuration; }
class QComboBox;
class QLabel;
class LauncherWindow : public QMainWindow {
class LauncherWindow final : public QMainWindow {
Q_OBJECT
public:
/**
@@ -41,8 +41,7 @@ class QTextEdit;
class ActionDialog final : public QDialog {
Q_OBJECT
public:
ActionDialog(QWidget* parent,
std::vector<openspace::Profile::Action>* actions,
ActionDialog(QWidget* parent, std::vector<openspace::Profile::Action>* actions,
std::vector<openspace::Profile::Keybinding>* keybindings);
private:
@@ -22,8 +22,8 @@
* OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. *
****************************************************************************************/
#ifndef __OPENSPACE_UI_LAUNCHER___ADDITIONALSCRIPTS___H__
#define __OPENSPACE_UI_LAUNCHER___ADDITIONALSCRIPTS___H__
#ifndef __OPENSPACE_UI_LAUNCHER___ADDITIONALSCRIPTSDIALOG___H__
#define __OPENSPACE_UI_LAUNCHER___ADDITIONALSCRIPTSDIALOG___H__
#include <QDialog>
@@ -41,7 +41,9 @@ public:
*/
AdditionalScriptsDialog(QWidget* parent, std::vector<std::string>* scripts);
private slots:
private:
void createWidgets();
void parseScript();
void chooseScripts();
@@ -52,13 +54,10 @@ private slots:
*/
void appendScriptsToTextfield(std::string scripts);
private:
void createWidgets();
std::vector<std::string>* _scripts = nullptr;
std::vector<std::string> _scriptsData;
QTextEdit* _textScripts = nullptr;
QPushButton* _chooseScriptsButton = nullptr;
};
#endif // __OPENSPACE_UI_LAUNCHER___ADDITIONALSCRIPTS___H__
#endif // __OPENSPACE_UI_LAUNCHER___ADDITIONALSCRIPTSDIALOG___H__
@@ -26,8 +26,6 @@
#define __OPENSPACE_UI_LAUNCHER___ASSETEDIT___H__
#include <QDialog>
#include <filesystem>
#include <string>
namespace openspace { class Asset; }
@@ -37,39 +35,21 @@ class QLabel;
class QLineEdit;
class QWidget;
class AssetEdit : public QDialog {
class AssetEdit final : public QDialog {
Q_OBJECT
public:
/**
* Constructor for AssetEdit class
*/
AssetEdit(QWidget* parent);
private slots:
//void openComponent();
//void openHorizonsFile();
void openHorizons();
void approved();
private:
void createWidgets();
void openHorizons();
void approved();
QBoxLayout* _layout = nullptr;
QLineEdit* _nameEdit = nullptr;
//QComboBox* _components = nullptr;
//std::filesystem::path _horizonsFile;
//QLineEdit* _horizonsFileEdit = nullptr;
QLabel* _errorMsg = nullptr;
// List of all the supported components
/*QStringList _supportedComponents = {
"Choose Component",
"Horizons Translation"
};*/
};
#endif // __OPENSPACE_UI_LAUNCHER___ASSETEDIT___H__
@@ -22,8 +22,8 @@
* OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. *
****************************************************************************************/
#ifndef __OPENSPACE_UI_LAUNCHER___ASSETS___H__
#define __OPENSPACE_UI_LAUNCHER___ASSETS___H__
#ifndef __OPENSPACE_UI_LAUNCHER___ASSETSDIALOG___H__
#define __OPENSPACE_UI_LAUNCHER___ASSETSDIALOG___H__
#include <QDialog>
@@ -48,17 +48,13 @@ public:
AssetsDialog(QWidget* parent, openspace::Profile* profile,
const std::string& assetBasePath, const std::string& userAssetBasePath);
private slots:
private:
void createWidgets();
void parseSelections();
void selected(const QModelIndex&);
private:
void createWidgets();
/**
* Creates a text summary of all assets and their paths
*
* \return the #std::string summary
*/
/// Creates a text summary of all assets and their paths
QString createTextSummary();
void openAssetEditor();
@@ -68,4 +64,4 @@ private:
QTextEdit* _summary = nullptr;
};
#endif // __OPENSPACE_UI_LAUNCHER___ASSETS___H__
#endif // __OPENSPACE_UI_LAUNCHER___ASSETSDIALOG___H__
@@ -30,20 +30,19 @@
class AssetTreeItem {
public:
static constexpr const int CheckboxColumn = 1;
static constexpr int CheckboxColumn = 1;
/**
* Constructor for assetTreeItem class
* Constructor for assetTreeItem class.
*
* \param data QVector containing the data contained in this tree view item
* \param parentItem The parent that contains this (and possibly other) children
* in the tree structure (optional).
*/
explicit AssetTreeItem(const std::vector<QVariant>& data,
AssetTreeItem* parentItem = nullptr);
AssetTreeItem(std::vector<QVariant> data, AssetTreeItem* parentItem = nullptr);
/**
* Destructor for assetTreeItem class
* Destructor for assetTreeItem class.
*/
~AssetTreeItem();
@@ -51,28 +50,25 @@ public:
* Returns pointer to this tree item's child at position \p row.
*
* \param row int of the row number of the child to get pointer
* \param parentItem The parent that contains this (and possibly other) children
* in the tree structure (optional).
* \return pointer to the child #assetTreeItem
*/
AssetTreeItem* child(int row);
AssetTreeItem* child(int row) const;
/**
* Returns the number of children this item has
* Returns the number of children this item has.
*
* \return The number of children
*/
int childCount() const;
/**
* Returns the number of data columns of this item
* Returns the number of data columns of this item.
*
* \return The number of data columns
*/
int columnCount() const;
/**
* Returns the data at column \p column of this item
* Returns the data at column \p column of this item.
*
* \param column Column number from which to retrieve data
* \return The data contained in the column
@@ -80,7 +76,7 @@ public:
QVariant data(int column) const;
/**
* Inserts children item(s) to the current item
* Inserts children item(s) to the current item.
*
* \param position where in this item's children to insert new children
* \param count number of children to insert
@@ -91,7 +87,7 @@ public:
bool insertChildren(int position, int count, int columns);
/**
* Inserts data column(s) in the current item
* Inserts data column(s) in the current item.
*
* \param position column number at which to insert column(s)
* \param columns number of columns to insert
@@ -100,21 +96,21 @@ public:
bool insertColumns(int position, int columns);
/**
* Returns a pointer to the current item's parent
* Returns a pointer to the current item's parent.
*
* \return pointer to the \p assetTreeItem parent
*/
AssetTreeItem* parent();
/**
* Returns the row number / child number of this item's parent
* Returns the row number / child number of this item's parent.
*
* \return The row number of this item's parent
*/
int row() const;
/**
* Returns the data at column \p column of this item
* Returns the data at column \p column of this item.
*
* \param position The position of the child(ren) to remove from the current
* item (which is parent)
@@ -124,13 +120,13 @@ public:
bool removeChildren(int position, int count);
/**
* Set data at column \p column
* Set data at column \p column.
*
* \param column The data column number to set
* \param value The #QVariant data element to store at column \p column
* \return true if the data set was successful
*/
bool setData(int column, const QVariant &value);
bool setData(int column, const QVariant& value);
/**
* Returns the checked state of this item. If an asset is selected to be included
@@ -141,7 +137,7 @@ public:
bool isChecked() const;
/**
* Sets the checked state of this item (whether or not it is selected for a profile)
* Sets the checked state of this item (whether or not it is selected for a profile).
*
* \param set bool for whether or not this is checked
*/
@@ -164,23 +160,23 @@ public:
bool isCategory() const;
/**
* Sets status of whether or not the asset exists in the current filesystem.
* It is possible that an imported profile lists an asset from another system
* that is not included on the current filesystem.
* Sets status of whether or not the asset exists in the current filesystem. It is
* possible that an imported profile lists an asset from another system that is not
* included on the current filesystem.
*
* \param set to true if the asset file exists in the current filesystem
*/
void setExistsInFilesystem(bool fileExists);
/**
* Returns bool for whether or not the asset exists in the current filesystem
* Returns bool for whether or not the asset exists in the current filesystem.
*
* \return true if the asset exists in the current filesystem
*/
bool doesExistInFilesystem() const;
/**
* Returns the asset name of the current item
* Returns the asset name of the current item.
*
* \return The asset name
*/
@@ -33,12 +33,11 @@
class AssetTreeModel final : public QAbstractItemModel {
Q_OBJECT
public:
AssetTreeModel(QObject* parent = nullptr);
/**
* Returns the data contained at an index
* Returns the data contained at an index.
*
* \param index that defines where the item is located in the tree model
* \param role Qt-defined role that describes the reason Qt is calling the
@@ -48,7 +47,7 @@ public:
QVariant data(const QModelIndex& index, int role) const final;
/**
* Returns the header data of the tree view
* Returns the header data of the tree view.
*
* \param section of data to be obtained from header
* \param orientation of the query (e.g. Qt::horizontal)
@@ -60,7 +59,7 @@ public:
int role = Qt::DisplayRole) const final;
/**
* Returns the index of item in #QModelIndex object form
* Returns the index of item in #QModelIndex object form.
*
* \param row the row number
* \param column the column number
@@ -71,7 +70,7 @@ public:
const QModelIndex& parent = QModelIndex()) const final;
/**
* Returns the index of the parent of the item specified by input param
* Returns the index of the parent of the item specified by input param.
*
* \param index of item that is a child of the parent
* \return #QModelIndex index of the parent
@@ -79,7 +78,7 @@ public:
QModelIndex parent(const QModelIndex& index) const final;
/**
* Returns the index of the parent of the item specified by the input params
* Returns the index of the parent of the item specified by the input params.
*
* \param row the row number
* \param column the column number
@@ -90,7 +89,7 @@ public:
const QModelIndex& parent = QModelIndex()) const;
/**
* Returns asset item at specified index
* Returns asset item at specified index.
*
* \param index of item that is a child of the parent
* \return #assetTreeItem pointer to the item at the provided index
@@ -98,7 +97,7 @@ public:
AssetTreeItem* assetItem(const QModelIndex& index);
/**
* Returns number of children/rows of the parent
* Returns number of children/rows of the parent.
*
* \param parent #QModelIndex of the parent item
* \return number of children/rows of this parent
@@ -106,7 +105,7 @@ public:
int rowCount(const QModelIndex& parent = QModelIndex()) const final;
/**
* Returns the number of columns of data in each item of the tree
* Returns the number of columns of data in each item of the tree.
*
* \param parent specified by the #QModelIndex index
* \return the number of data columns
@@ -115,7 +114,7 @@ public:
/**
* Return the Qt flags of the item specified by index, which can include
* Qt::ItemIsEnabled, Qt::ItemIsSelectable
* Qt::ItemIsEnabled, Qt::ItemIsSelectable.
*
* \param index specified by the #QModelIndex index
* \return the Qt flags
@@ -123,7 +122,7 @@ public:
Qt::ItemFlags flags(const QModelIndex& index) const final;
/**
* Set data at index \p index
* Set data at index \p index.
*
* \param index location of the item to set
* \param value The #QVariant data element to store at column \p column
@@ -134,12 +133,11 @@ public:
int role = Qt::EditRole) final;
/**
* Returns a vector of all #Assets selected in the tree view
* Returns a vector of all #Assets selected in the tree view.
*
* \param outputPaths vector of #openspace::Profile::Asset objects,
* each of which are selected
* \param outputItems vector of #assetTreeItem * objects,
* each of which are selected
* \param outputPaths vector of #openspace::Profile::Asset objects, each of which are
* selected
* \param outputItems vector of #assetTreeItem * objects, each of which are selected
*/
void getSelectedAssets(std::vector<std::string>& outputPaths,
std::vector<AssetTreeItem*>& outputItems);
@@ -154,7 +152,7 @@ public:
const std::string& userAssetBasePath);
/**
* Returns bool for if item is checked/selected
* Returns bool for if item is checked/selected.
*
* \param index location of the item to set
* \return true if the item is checked
@@ -162,7 +160,7 @@ public:
bool isChecked(QModelIndex& index) const;
/**
* Answers query about whether or not item is an asset
* Answers query about whether or not item is an asset.
*
* \param index location of the item to query
* \return true if the item is an asset (and not a directory)
@@ -170,7 +168,7 @@ public:
bool isAsset(QModelIndex& index) const;
/**
* Answers query about whether or not item is in the current filesystem
* Answers query about whether or not item is in the current filesystem.
*
* \param index location of the item to query
* \return true if the data is in the filesystem
@@ -178,7 +176,7 @@ public:
bool inFilesystem(QModelIndex& index) const;
/**
* Returns number of child items of referenced item
* Returns number of child items of referenced item.
*
* \param index location of the item to query
* \return number of child items
@@ -186,7 +184,7 @@ public:
int childCount(QModelIndex& index) const;
/**
* Returns a pointer to a child item of the current item
* Returns a pointer to a child item of the current item.
*
* \param row the child number of the current item
* \return assetTreeItem pointer to the child
@@ -194,7 +192,7 @@ public:
AssetTreeItem* child(int row) const;
/**
* Returns the asset name of the specified item
* Returns the asset name of the specified item.
*
* \param index location of the item to query
* \return the asset name of the item
@@ -202,7 +200,7 @@ public:
QString name(QModelIndex& index) const;
/**
* Set asset name at specified index
* Set asset name at specified index.
*
* \param index location of the item to set
* \param name the asset name to set
@@ -210,7 +208,7 @@ public:
void setName(QModelIndex& index, QString name);
/**
* Set state of checked/selected of an item
* Set state of checked/selected of an item.
*
* \param index location of the item to set
* \param checked true if item is checked/selected
@@ -218,7 +216,7 @@ public:
void setChecked(QModelIndex& index, bool checked);
/**
* Set state of whether or not asset exists in filesystem
* Set state of whether or not asset exists in filesystem.
*
* \param index location of the item to set
* \param fileExists true if asset exists in filesystem
@@ -226,7 +224,7 @@ public:
void setExistenceInFilesystem(QModelIndex& index, bool fileExists);
private:
AssetTreeItem* getItem(const QModelIndex& index) const;
AssetTreeItem* item(const QModelIndex& index) const;
std::unique_ptr<AssetTreeItem> _rootItem;
};
@@ -22,8 +22,8 @@
* OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. *
****************************************************************************************/
#ifndef __OPENSPACE_UI_LAUNCHER___DELTATIMES___H__
#define __OPENSPACE_UI_LAUNCHER___DELTATIMES___H__
#ifndef __OPENSPACE_UI_LAUNCHER___DELTATIMESDIALOG___H__
#define __OPENSPACE_UI_LAUNCHER___DELTATIMESDIALOG___H__
#include <QDialog>
@@ -61,8 +61,9 @@ public:
*/
virtual void keyPressEvent(QKeyEvent* evt) override;
private slots:
private:
void createWidgets();
void listItemSelected();
void valueChanged(const QString& text);
void saveDeltaTimeValue();
@@ -71,9 +72,6 @@ private slots:
void removeDeltaTimeValue();
void parseSelections();
private:
void createWidgets();
/**
* Called to transition to editing a particular dt value (gui settings)
*
@@ -103,4 +101,4 @@ private:
QLabel* _errorMsg = nullptr;
};
#endif // __OPENSPACE_UI_LAUNCHER___DELTATIMES___H__
#endif // __OPENSPACE_UI_LAUNCHER___DELTATIMESDIALOG___H__
@@ -22,11 +22,12 @@
* OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. *
****************************************************************************************/
#ifndef __OPENSPACE_UI_LAUNCHER___HORIZONS___H__
#define __OPENSPACE_UI_LAUNCHER___HORIZONS___H__
#ifndef __OPENSPACE_UI_LAUNCHER___HORIZONSDIALOG___H__
#define __OPENSPACE_UI_LAUNCHER___HORIZONSDIALOG___H__
#include <QDialog>
#include <openspace/json.h>
#include <QDialog>
#include <filesystem>
#include <string>
@@ -43,27 +44,12 @@ class QNetworkReply;
class QPlainTextEdit;
class QProgressBar;
class HorizonsDialog : public QDialog {
class HorizonsDialog final : public QDialog {
Q_OBJECT
public:
/**
* Constructor for HorizonsDialog class
*/
HorizonsDialog(QWidget* parent);
explicit HorizonsDialog(QWidget* parent);
#ifdef OPENSPACE_MODULE_SPACE_ENABLED
std::filesystem::path file() const;
#endif // OPENSPACE_MODULE_SPACE_ENABLED
private slots:
void openSaveAs();
void typeOnChange(int index);
void downloadProgress(int value, int max);
void importTimeRange();
#ifdef OPENSPACE_MODULE_SPACE_ENABLED
void approved();
#endif // OPENSPACE_MODULE_SPACE_ENABLED
private:
enum class LogLevel {
@@ -82,8 +68,14 @@ private:
};
void createWidgets();
void cleanAllWidgets();
void styleLabel(QLabel* label, bool isDirty);
void openSaveAs();
void typeOnChange(int index);
void downloadProgress(int value, int max);
void importTimeRange();
void approved();
bool isValidInput();
nlohmann::json sendRequest(const std::string& url);
nlohmann::json handleReply(QNetworkReply* reply);
@@ -133,4 +125,4 @@ private:
std::string _latestHorizonsError;
};
#endif // __OPENSPACE_UI_LAUNCHER___HORIZONS___H__
#endif // __OPENSPACE_UI_LAUNCHER___HORIZONSDIALOG___H__
@@ -27,7 +27,7 @@
#include <QFrame>
class Line : public QFrame {
class Line final : public QFrame {
public:
Line();
};
@@ -22,8 +22,8 @@
* OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. *
****************************************************************************************/
#ifndef __OPENSPACE_UI_LAUNCHER___MARKNODES___H__
#define __OPENSPACE_UI_LAUNCHER___MARKNODES___H__
#ifndef __OPENSPACE_UI_LAUNCHER___MARKNODESDIALOG___H__
#define __OPENSPACE_UI_LAUNCHER___MARKNODESDIALOG___H__
#include <QDialog>
@@ -51,15 +51,13 @@ public:
*/
void keyPressEvent(QKeyEvent* evt) override;
private slots:
void listItemSelected();
private:
void createWidgets();
void listItemAdded();
void listItemRemove();
void parseSelections();
private:
void createWidgets();
std::vector<QListWidgetItem*> _markedNodesListItems;
std::vector<std::string>* _markedNodes;
std::vector<std::string> _markedNodesData;
@@ -67,7 +65,6 @@ private:
QListWidget* _list = nullptr;
QPushButton* _removeButton = nullptr;
QLineEdit* _newNode = nullptr;
};
#endif // __OPENSPACE_UI_LAUNCHER___MARKNODES___H__
#endif // __OPENSPACE_UI_LAUNCHER___MARKNODESDIALOG___H__
@@ -22,8 +22,8 @@
* OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. *
****************************************************************************************/
#ifndef __OPENSPACE_UI_LAUNCHER___META___H__
#define __OPENSPACE_UI_LAUNCHER___META___H__
#ifndef __OPENSPACE_UI_LAUNCHER___METADIALOG___H__
#define __OPENSPACE_UI_LAUNCHER___METADIALOG___H__
#include <QDialog>
@@ -37,7 +37,7 @@ class MetaDialog final : public QDialog {
Q_OBJECT
public:
/**
* Constructor for meta class
* Constructor for meta class.
*
* \param profile The #openspace::Profile object containing all data of the
* new or imported profile.
@@ -45,12 +45,11 @@ public:
*/
MetaDialog(QWidget* parent, std::optional<openspace::Profile::Meta>* meta);
private slots:
void save();
private:
void createWidgets();
void save();
std::optional<openspace::Profile::Meta>* _meta = nullptr;
QLineEdit* _nameEdit = nullptr;
@@ -61,4 +60,4 @@ private:
QLineEdit* _licenseEdit = nullptr;
};
#endif // __OPENSPACE_UI_LAUNCHER___META___H__
#endif // __OPENSPACE_UI_LAUNCHER___METADIALOG___H__
@@ -22,8 +22,8 @@
* OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. *
****************************************************************************************/
#ifndef __OPENSPACE_UI_LAUNCHER___MODULES___H__
#define __OPENSPACE_UI_LAUNCHER___MODULES___H__
#ifndef __OPENSPACE_UI_LAUNCHER___MODULESDIALOG___H__
#define __OPENSPACE_UI_LAUNCHER___MODULESDIALOG___H__
#include <QDialog>
@@ -54,7 +54,9 @@ public:
*/
virtual void keyPressEvent(QKeyEvent* evt) override;
private slots:
private:
void createWidgets();
void listItemSelected();
void listItemAdded();
void listItemRemove();
@@ -63,9 +65,6 @@ private slots:
void transitionToEditMode();
void parseSelections();
private:
void createWidgets();
QString createOneLineSummary(openspace::Profile::Module m);
void transitionFromEditMode();
void editBoxDisabled(bool disabled);
@@ -92,4 +91,4 @@ private:
QLabel* _errorMsg = nullptr;
};
#endif // __OPENSPACE_UI_LAUNCHER___MODULES___H__
#endif // __OPENSPACE_UI_LAUNCHER___MODULESDIALOG___H__
@@ -22,8 +22,8 @@
* OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. *
****************************************************************************************/
#ifndef __OPENSPACE_UI_LAUNCHER___PROPERTIES___H__
#define __OPENSPACE_UI_LAUNCHER___PROPERTIES___H__
#ifndef __OPENSPACE_UI_LAUNCHER___PROPERTIESDIALOG___H__
#define __OPENSPACE_UI_LAUNCHER___PROPERTIESDIALOG___H__
#include <QDialog>
@@ -56,7 +56,9 @@ public:
*/
virtual void keyPressEvent(QKeyEvent* evt) override;
private slots:
private:
void createWidgets();
void listItemSelected();
void listItemAdded();
void listItemRemove();
@@ -67,9 +69,6 @@ private slots:
void selectLineFromScriptLog();
private:
void createWidgets();
QString createOneLineSummary(openspace::Profile::Property p);
void transitionFromEditMode();
void editBoxDisabled(bool disabled);
@@ -98,4 +97,4 @@ private:
QLabel* _errorMsg = nullptr;
};
#endif // __OPENSPACE_UI_LAUNCHER___PROPERTIES___H__
#endif // __OPENSPACE_UI_LAUNCHER___PROPERTIESDIALOG___H__
@@ -22,8 +22,8 @@
* OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. *
****************************************************************************************/
#ifndef __OPENSPACE_UI_LAUNCHER___SCRIPTLOG___H__
#define __OPENSPACE_UI_LAUNCHER___SCRIPTLOG___H__
#ifndef __OPENSPACE_UI_LAUNCHER___SCRIPTLOGDIALOG___H__
#define __OPENSPACE_UI_LAUNCHER___SCRIPTLOGDIALOG___H__
#include <QDialog>
@@ -39,12 +39,12 @@ public:
signals:
void scriptsSelected(std::string script);
private slots:
void saveChosenScripts();
private:
void createWidgets();
void loadScriptFile();
void saveChosenScripts();
void updateScriptList();
QListWidget* _scriptlogList = nullptr;
@@ -53,4 +53,4 @@ private:
std::vector<std::string> _scripts;
};
#endif // __OPENSPACE_UI_LAUNCHER___SCRIPTLOG___H__
#endif // __OPENSPACE_UI_LAUNCHER___SCRIPTLOGDIALOG___H__
@@ -22,8 +22,8 @@
* OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. *
****************************************************************************************/
#ifndef __OPENSPACE_UI_LAUNCHER___OSTIME___H__
#define __OPENSPACE_UI_LAUNCHER___OSTIME___H__
#ifndef __OPENSPACE_UI_LAUNCHER___TIMEDIALOG___H__
#define __OPENSPACE_UI_LAUNCHER___TIMEDIALOG___H__
#include <QDialog>
@@ -65,4 +65,4 @@ private:
QLineEdit* _relativeEdit = nullptr;
};
#endif // __OPENSPACE_UI_LAUNCHER___OSTIME___H__
#endif // __OPENSPACE_UI_LAUNCHER___TIMEDIALOG___H__
@@ -21,36 +21,26 @@
* 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___DISPLAYWINDOWUNION___H__
#define __OPENSPACE_UI_LAUNCHER___DISPLAYWINDOWUNION___H__
#include <QWidget>
#include "windowcontrol.h"
#include "monitorbox.h"
#include <QCheckBox>
#include <QComboBox>
#include <QIntValidator>
#include <QLabel>
#include <QLayout>
#include <QLineEdit>
#include <QPainter>
#include <QPainterPath>
#include <QPoint>
#include <QPushButton>
#include <QTextBrowser>
#include <QVector>
#include <memory>
#include <vector>
class DisplayWindowUnion : public QWidget {
class QFrame;
class QPushButton;
class QVBoxLayout;
class WindowControl;
class DisplayWindowUnion final : public QWidget {
Q_OBJECT
public:
/**
* Constructor for DisplayWindowUnion class, which manages the overall control layout
* including monitorBox, multiple WindowControl columns, and additional controls
*
* \param monitorRenderBox pointer to the MonitorBox object
* \param monitorSizeList A vector containing QRect objects containing pixel dims
* of each monitor
* \param nMaxWindows The maximum number of windows allowed (depends on the number
@@ -58,45 +48,59 @@ public:
* \param winColors An array of QColor objects for window colors. The indexing of
* this array matches the window indexing used elsewhere in the
* class. This allows for a unique color for each window.
*/
DisplayWindowUnion(std::shared_ptr<MonitorBox> monitorRenderBox,
std::vector<QRect>& monitorSizeList, unsigned int nMaxWindows,
const std::array<QColor, 4>& winColors);
* \param parent The parent to which this widget belongs
*/
DisplayWindowUnion(const std::vector<QRect>& monitorSizeList,
int nMaxWindows, const std::array<QColor, 4>& windowColors,
QWidget* parent = nullptr);
/**
* Returns a vector of pointers to all WindowControl objects for all windows
* Returns a vector of pointers to the WindowControl objects for all visible windows.
*
* \return vector of pointers of WindowControl objects
*/
std::vector<std::shared_ptr<WindowControl>> windowControls() const;
/**
* Returns the current number of windows
*
* \return the currently-selected number of windows in unsigned int
*/
unsigned int nWindows() const;
*/
std::vector<WindowControl*> windowControls() const;
private slots:
/**
* When called will add a new window to the set of windows, which will, in turn, send
* out all of the corresponding signals described below.
*/
void addWindow();
/**
* When called will remove the last window from the set of windows, which will, in
* turn, send out all of the corresponding signals described below.
*/
void removeWindow();
signals:
/**
* This signal is emitted when a windowhas changed.
*
* \param monitorIndex The 0-based index of the monitor to which the window belongs to
* \param windowIndex The 0-based index of the window that was changed
* \param newDimensions The pixel sizes of the window after the change
*/
void windowChanged(int monitorIndex, int windowIndex, const QRectF& newDimensions);
/**
* This signal is emitted when the total number of windows has changed.
*
* \param newCount The new total number of windows
*/
void nWindowsChanged(int newCount);
private:
void initializeWindowControl();
void initializeLayout();
void createWidgets(int nMaxWindows, std::vector<QRect> monitorResolutions,
std::array<QColor, 4> windowColors);
void showWindows();
std::shared_ptr<MonitorBox> _monBox;
std::vector<QRect>& _monitorResolutions;
unsigned int _nWindowsAllocated = 0;
unsigned int _nWindowsDisplayed = 0;
unsigned int _nMaxWindows = 3;
const std::array<QColor, 4>& _winColors;
std::vector<std::shared_ptr<WindowControl>> _windowControl;
std::vector<WindowControl*> _windowControl;
QPushButton* _addWindowButton = nullptr;
QPushButton* _removeWindowButton = nullptr;
unsigned int _monitorIdx = 0;
std::vector<QVBoxLayout*> _winCtrlLayouts;
std::vector<QWidget*> _layoutWindowWrappers;
std::vector<QFrame*> _frameBorderLines;
QFrame* _borderFrame = nullptr;
};
#endif // __OPENSPACE_UI_LAUNCHER___DISPLAYWINDOWUNION___H__
@@ -1,119 +0,0 @@
/*****************************************************************************************
* *
* OpenSpace *
* *
* Copyright (c) 2014-2022 *
* *
* 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___FILESUPPORT___H__
#define __OPENSPACE_UI_LAUNCHER___FILESUPPORT___H__
#include <QWidget>
#include <ghoul/filesystem/filesystem.h>
#include <sgctedit/displaywindowunion.h>
#include <sgctedit/orientation.h>
#include <sgct/config.h>
#include <QFileDialog>
#include <QFrame>
#include <QLabel>
#include <QLayout>
#include <QPushButton>
#include <QVector>
#include <filesystem>
#include <memory>
#include <vector>
using ProjectionOptions = std::variant<
sgct::config::NoProjection,
sgct::config::CylindricalProjection,
sgct::config::EquirectangularProjection,
sgct::config::FisheyeProjection,
sgct::config::PlanarProjection,
sgct::config::ProjectionPlane,
sgct::config::SphericalMirrorProjection,
sgct::config::SpoutOutputProjection,
sgct::config::SpoutFlatProjection
>;
struct SgctConfigElements {
std::vector<sgct::config::Window>& windowList;
sgct::config::Cluster& cluster;
};
struct UserConfigurationElements {
std::vector<QRect>& monitorList;
std::shared_ptr<DisplayWindowUnion> display;
Orientation* orientation;
const std::string configSavePath;
};
class FileSupport : public QWidget {
Q_OBJECT
public:
/**
* Constructor for FileSupport class, which saves the window configuration settings
* into the SGCT json structure according to the sgct code
*
* \param parentLayout Qt vertical (QVBoxLayout) layout where controls are added
* \param cfgElements struct of elements needed to read user settings from GUI
* \param sgctElements struct of the window and cluster objects needed for saving
* \param finishedCallback function to be called when user has selected to either
* save changes to file, apply and run without saving, or cancel
*/
FileSupport(QVBoxLayout* parentLayout, UserConfigurationElements& cfgElements,
SgctConfigElements& sgctElements, std::function<void(bool)> finishedCallback);
std::string saveFilename();
private slots:
void cancel();
void save();
void apply();
private:
bool isWindowFullscreen(unsigned int monitorIdx, sgct::ivec2 wDims);
std::optional<unsigned int> findGuiWindow();
void saveConfigToSgctFormat();
void saveCluster();
void saveWindows();
void saveUser();
ProjectionOptions saveProjectionInformation(
std::shared_ptr<WindowControl> winControl);
ProjectionOptions saveProjectionSpout(std::shared_ptr<WindowControl> winControl);
ProjectionOptions saveProjectionNoSpout(std::shared_ptr<WindowControl> winControl);
sgct::config::Viewport generateViewport();
sgct::config::Window saveWindowsDimensions(std::shared_ptr<WindowControl> wCtrl);
void saveWindowsWebGui(unsigned int wIdx, sgct::config::Window& win);
QHBoxLayout* _layoutButtonBox = nullptr;
QPushButton* _saveButton = nullptr;
QPushButton* _cancelButton = nullptr;
QPushButton* _applyButton = nullptr;
std::shared_ptr<DisplayWindowUnion> _displayWidget;
Orientation* _orientationWidget;
std::vector<QRect>& _monitors;
sgct::config::Cluster& _cluster;
std::vector<sgct::config::Window>& _windowList;
std::function<void(bool)> _finishedCallback;
const std::string _userConfigPath;
std::string _saveTarget;
};
#endif // __OPENSPACE_UI_LAUNCHER___FILESUPPORT___H__
@@ -27,20 +27,11 @@
#include <QWidget>
#include "windowcontrol.h"
#include <QColor>
#include <QIntValidator>
#include <QLineEdit>
#include <QPainter>
#include <QPainterPath>
#include <QPoint>
#include <QVector>
#include <algorithm>
#include <array>
#include <vector>
#include <iostream>
class MonitorBox : public QWidget {
class MonitorBox final : public QWidget {
Q_OBJECT
public:
/**
@@ -54,73 +45,50 @@ public:
* \param winColors An array of QColor objects for window colors. The indexing of
* this array matches the window indexing used elsewhere in the
* class. This allows for a unique color for each window.
*/
MonitorBox(QRect widgetDims, std::vector<QRect> monitorResolution,
unsigned int nWindows, const std::array<QColor, 4>& winColors);
* \param parent The parent which to which this MonitorBox belongs
*/
MonitorBox(QRect widgetDims, const std::vector<QRect>& monitorResolutions,
unsigned int nWindows, const std::array<QColor, 4>& windowColors,
QWidget* parent = nullptr);
/**
* Maps window resolution into the scaled resolution of the display widget
*
* \param mIdx The zero-based monitor index (primary monitor is 0)
* \param wIdx The zero-based window index
* \param winDimensions Dimensions (pixels) of window to be mapped in QRect
*/
void mapWindowResolutionToWidgetCoordinates(unsigned int mIdx, unsigned int wIdx,
const QRectF& winDimensions);
/**
* Sets the number of windows to be displayed
*
* \param nWindows Number of windows to be displayed
*/
void setNumWindowsDisplayed(unsigned int nWindows);
/**
* Called when window dimensions or monitor location have changed, requiring redraw
* Called when window dimensions or monitor location have changed, requiring redraw.
* This will also map the window resolution into the scaled resolution of the display
* widget.
*
* \param mIdx The zero-based monitor index (primary monitor is 0)
* \param wIdx The zero-based window index
* \param newDimensions Dimensions (pixels) of window to be mapped in QRect
*/
*/
void windowDimensionsChanged(unsigned int mIdx, unsigned int wIdx,
const QRectF& newDimensions);
const QRectF& newDimensions);
/**
* Called when the number of windows that should be displayed changes.
*
* \param newCount The new number of windows included
*/
void nWindowsDisplayedChanged(int newCount);
protected:
void paintEvent(QPaintEvent* event) override;
private:
void determineMonitorArrangement();
void mapMonitorResolutionToWidgetCoordinates();
void paintWidgetBorder(QPainter& painter, int width, int height);
void paintMonitorBackgrounds(QPainter& painter);
void paintWindow(QPainter& painter, size_t winIdx);
void paintWindowBeyondBounds(QPainter& painter, unsigned int winIdx);
void paintWindowNumber(QPainter& painter, unsigned int winIdx);
void setPenSpecificToWindow(QPainter& painter, unsigned int windowIdx,
bool visibleBorder);
void computeScaledResolutionLandscape(float aspectRatio, float maxWidth);
void computeScaledResolutionPortrait(float aspectRatio, float maxHeight);
std::vector<QSizeF> computeScaledResolutionLandscape(QRectF arrangement,
const std::vector<QRect>& resolutions);
std::vector<QSizeF> computeScaledResolutionPortrait(QRectF arrangement,
const std::vector<QRect>& resolutions);
unsigned int _maxNumMonitors = 2;
QRectF _monitorWidgetSize;
QRectF _monitorBoundaryRect;
unsigned int _nMonitors = 1;
float _monitorArrangementAspectRatio = 1.f;
QSizeF _monitorArrangementDimensions = { 0.0, 0.0 };
std::vector<QRect> _monitorResolution;
std::vector<QRectF> _monitorDimensionsScaled;
QRectF _negativeCorrectionOffsets = {0.f, 0.f, 0.f, 0.f};
std::vector<QRectF> _windowResolutions;
std::vector<QRectF> _windowRendering = {
{0.f, 0.f, 0.f, 0.f},
{0.f, 0.f, 0.f, 0.f},
{0.f, 0.f, 0.f, 0.f},
{0.f, 0.f, 0.f, 0.f}
std::array<QRectF, 4> _windowRendering = {
QRectF{ 0.f, 0.f, 0.f, 0.f },
QRectF{ 0.f, 0.f, 0.f, 0.f },
QRectF{ 0.f, 0.f, 0.f, 0.f },
QRectF{ 0.f, 0.f, 0.f, 0.f }
};
unsigned int _nWindows = 1;
int _nWindows = 1;
const std::array<QColor, 4> _colorsForWindows;
int _alphaWindowOpacity = 170;
float _monitorScaleFactor = 1.0;
bool _showLabel = false;
float _marginWidget = 5.0;
std::vector<QSizeF> _monitorOffsets;
};
#endif // __OPENSPACE_UI_LAUNCHER___MONITORBOX___H__
@@ -27,13 +27,12 @@
#include <QDialog>
#include <sgct/config.h>
#include <QLineEdit>
#include <glm/gtc/constants.hpp>
#include <sgct/math.h>
class QLineEdit;
class QWidget;
class OrientationDialog : public QDialog {
class OrientationDialog final : public QDialog {
Q_OBJECT
public:
/**
@@ -42,14 +41,12 @@ public:
*
* \param orientation x,y,z angles in degrees contained in sgct::quat object
* \param parent pointer to Qt QWidget parent object
*/
*/
OrientationDialog(sgct::quat& orientation, QWidget* parent);
private slots:
void cancel();
void ok();
private:
void ok();
QLineEdit* _linePitch = nullptr;
QLineEdit* _lineRoll = nullptr;
QLineEdit* _lineYaw = nullptr;
@@ -22,62 +22,50 @@
* OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. *
****************************************************************************************/
#ifndef __OPENSPACE_UI_LAUNCHER___ORIENTATION___H__
#define __OPENSPACE_UI_LAUNCHER___ORIENTATION___H__
#ifndef __OPENSPACE_UI_LAUNCHER___SETTINGSWIDGET___H__
#define __OPENSPACE_UI_LAUNCHER___SETTINGSWIDGET___H__
#include <QWidget>
#include <sgctedit/orientationdialog.h>
#include <sgct/config.h>
#include <sgct/math.h>
#include <QCheckBox>
#include <QLayout>
#include <QPushButton>
class Orientation : public QWidget {
class QCheckBox;
class QLabel;
class SettingsWidget final : public QWidget {
Q_OBJECT
public:
/**
* Constructor for Orientation class, which manages the overall control layout
* including monitorBox, multiple WindowControl columns, and additional controls
*
* \param monitorRenderBox pointer to the MonitorBox object
* \param monitorSizeList A vector containing QRect objects containing pixel dims
* of each monitor
* \param nMaxWindows The maximum number of windows allowed (depends on the number
* of monitors in the system)
* \param winColors An array of QColor objects for window colors. The indexing of
* this array matches the window indexing used elsewhere in the
* class. This allows for a unique color for each window.
*/
Orientation();
/**
* Add Orientation controls to the parent layout
*
* \param parentLayout the layout to which the Orientation's controls will be added
*/
void addControlsToParentLayout(QVBoxLayout* parentLayout);
*/
SettingsWidget(sgct::quat orientation, QWidget* parent = nullptr);
/**
* Gets the user-provided x,y,z orientation values (degrees)
*
* \return the orientation angles provided in sgct::quat object
*/
sgct::quat orientationValue() const;
*/
sgct::quat orientation() const;
/**
* Gets the value for if VSync is enabled
*
* \return true if the VSync option is checked/enabled
*/
bool vsyncValue() const;
*/
bool vsync() const;
private slots:
void orientationDialog();
/**
* Gets whether the UI should be restricted to the first window
*
* \return true if the UI should only be on the first window
*/
bool showUiOnFirstWindow() const;
private:
sgct::quat _orientationValue = {0.f, 0.f, 0.f, 0.f};
OrientationDialog _orientationDialog;
QHBoxLayout* _layoutOrientationFull = nullptr;
sgct::quat _orientationValue = { 0.f, 0.f, 0.f, 0.f };
QCheckBox* _checkBoxVsync = nullptr;
QCheckBox* _showUiOnFirstWindow = nullptr;
};
#endif // __OPENSPACE_UI_LAUNCHER___ORIENTATION___H__
#endif // __OPENSPACE_UI_LAUNCHER___SETTINGSWIDGET___H__
@@ -27,18 +27,15 @@
#include <QDialog>
#include <sgctedit/displaywindowunion.h>
#include <sgctedit/filesupport.h>
#include <sgctedit/monitorbox.h>
#include <sgctedit/orientation.h>
#include <QApplication>
#include <sgct/config.h>
#include <QColor>
#include <QLayout>
#include <QScreen>
#include <memory>
#include <array>
#include <filesystem>
#include <string>
#include <vector>
class DisplayWindowUnion;
class SettingsWidget;
class QBoxLayout;
class QWidget;
class SgctEdit final : public QDialog {
@@ -49,57 +46,48 @@ public:
* configuration editor
*
* \param parent The Qt QWidget parent object
* \param windowList vector of sgct::config::Window objects which will be modified
* by the user settings, and then used for writing to file in
* the launcher code
* \param cluster reference to sgct::config::Cluster object that contains sgct
* objects that will be modified by the window configuration settings
* \param screenList A QList containing a QScreen object for each monitor in the
* system
* \param userConfigPath A string containing the file path of the user config
* directory where all window configs are stored
*/
SgctEdit(QWidget* parent, std::vector<sgct::config::Window>& windowList,
sgct::config::Cluster& cluster, const QList<QScreen*>& screenList,
const std::string userConfigPath);
~SgctEdit();
/**
* Used to determine if the window configuration was saved to file, or canceled
*
* \return true if configuration was saved to file
*/
bool wasSaved() const;
*/
SgctEdit(QWidget* parent, std::string userConfigPath);
/**
* Returns the saved filename
*
* \return saved filename in std::string
*/
std::string saveFilename();
*/
std::filesystem::path saveFilename() const;
/**
* Returns the generated Cluster object.
*
* \return The generated Cluster object
*/
sgct::config::Cluster cluster() const;
private:
void addDisplayLayout(QHBoxLayout* layout);
void createWidgets();
void systemMonitorConfiguration(const QList<QScreen*>& screenList);
void createWidgets(const std::vector<QRect>& monitorSizes);
sgct::config::Cluster generateConfiguration() const;
std::shared_ptr<MonitorBox> _monBox = nullptr;
std::vector<QRect> _monitorSizeList;
QVBoxLayout* _displayLayout = nullptr;
QFrame* _displayFrame = nullptr;
std::shared_ptr<DisplayWindowUnion> _displayWidget = nullptr;
QRect _monitorWidgetSize = {0, 0, 500, 500};
FileSupport* _fileSupportWidget = nullptr;
Orientation* _orientationWidget = nullptr;
sgct::config::Cluster& _cluster;
std::vector<sgct::config::Window>& _windowList;
void save();
void apply();
DisplayWindowUnion* _displayWidget = nullptr;
SettingsWidget* _settingsWidget = nullptr;
sgct::config::Cluster _cluster;
const std::string _userConfigPath;
bool _saveSelected = false;
unsigned int _nMaxWindows = 3;
const std::array<QColor, 4> _colorsForWindows = {
QColor(0x2B, 0x9E, 0xC3),
QColor(0xFC, 0xAB, 0x10),
QColor(0x44, 0xAF, 0x69),
QColor(0xF8, 0x33, 0x3C)
};
QBoxLayout* _layoutButtonBox = nullptr;
QPushButton* _saveButton = nullptr;
QPushButton* _cancelButton = nullptr;
QPushButton* _applyButton = nullptr;
std::string _saveTarget;
};
#endif // __OPENSPACE_UI_LAUNCHER___SGCTEDIT___H__
@@ -21,21 +21,24 @@
* 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___WINDOWCONTROL___H__
#define __OPENSPACE_UI_LAUNCHER___WINDOWCONTROL___H__
#include <QWidget>
#include <sgct/config.h>
#include <QCheckBox>
#include <QComboBox>
#include <QLabel>
#include <QLayout>
#include <QLineEdit>
#include <QPushButton>
#include <QIcon>
#include <vector>
class WindowControl : public QWidget {
class QCheckBox;
class QComboBox;
class QDoubleSpinBox;
class QLabel;
class QLineEdit;
class QSpinBox;
class WindowControl final : public QWidget {
Q_OBJECT
public:
/**
@@ -46,206 +49,107 @@ public:
* resides in
* \param windowIndex The zero-based window index
* \param monitorDims Vector of monitor dimensions in QRect form
* \param winColor A QColor object for this window's unique color
*/
WindowControl(unsigned int monitorIndex, unsigned int windowIndex,
std::vector<QRect>& monitorDims, const QColor& winColor,
QWidget *parent);
~WindowControl();
/**
* Sets callback function to be invoked when a window's setting changes
*
* \param cb Callback function that accepts the listed arg types, in order of
* monitorIndex, windowIndex, and windowDims (that were just changed)
* \param winColor A QColor object for this window's unique color
*/
void setWindowChangeCallback(std::function<void(int, int, const QRectF&)> cb);
/**
* Sets callback function to be invoked when a window gets its GUI checkbox selected
*
* \param cb Callback function that accepts the index of the window that has its
* WebGUI option selected
*/
void setWebGuiChangeCallback(std::function<void(unsigned int)> cb);
WindowControl(int monitorIndex, int windowIndex,
const std::vector<QRect>& monitorDims, const QColor& winColor, QWidget* parent);
/**
* Makes the window label at top of a window control column visible
*
* \param bool Shows the window label if true
*/
void showWindowLabel(bool show);
/**
* Initializes the layout of a window controls column, returning the Qt layout object
*
* \return the QVBoxLayout object that contains the entire windows control column
* Resets all controls for this window to default settings
*/
QVBoxLayout* initializeLayout();
/**
* Returns the dimensions of the window
*
* \return the QRectF object that contains the windows dimensions
*/
QRectF& dimensions();
/**
* Returns the title name of the window
*
* \return the std::string of the window name
*/
std::string windowName() const;
/**
* Returns the user-entered window size width, height from the text line objects
*
* \return the user-entered window size in sgct::ivec2 object
*/
sgct::ivec2 windowSize() const;
/**
* Returns the user-entered window position in x,y pixles from the text line objects
*
* \return the user-entered window position in sgct::ivec2 object
*/
sgct::ivec2 windowPos() const;
/**
* Returns bool for if the window control checkbox is set to be decorated
*
* \return bool for if window decoration is enabled
*/
bool isDecorated() const;
/**
* Returns bool for if the window control checkbox spout selection is enabled
*
* \return bool for if window has spout enabled
*/
bool isSpoutSelected() const;
/**
* Returns bool for if the window control checkbox for WebGUI is enabled
*
* \return bool for if window has WebGUI enabled
*/
bool isGuiWindow() const;
/**
* Function called in order to disable/uncheck the WebGUI checkbox option
*/
void uncheckWebGuiOption();
/**
* Returns index number of the selected window quality value. This is an index into
* the QualityValues array
*
* \return index int into the QualityValues array
*/
int qualitySelectedValue() const;
/**
* Returns index number of the monitor that this window is assigned to
*
* \return int index of monitor
*/
unsigned int monitorNum() const;
/**
* Returns the user-entered horizontal field-of-view (planar projection only)
*
* \return float value of horizontal FOV
*/
float fovH() const;
/**
* Returns the user-entered vertical field-of-view (planar projection only)
*
* \return float value of vertical FOV
*/
float fovV() const;
/**
* Returns the user-entered height offset (cylindrical projection only)
*
* \return float value of height offset
*/
float heightOffset() const;
enum class ProjectionIndeces {
void resetToDefaults();
sgct::config::Window generateWindowInformation() const;
signals:
void windowChanged(int monitorIndex, int windowIndex, const QRectF& newDimensions);
private:
enum class ProjectionIndices {
Planar = 0,
Fisheye,
SphericalMirror,
Cylindrical,
Equirectangular
};
/**
* Returns the user-selected window projection type
*
* \return ProjectionIndeces enum of the projection type
*/
ProjectionIndeces projectionSelectedIndex() const;
/**
* Resets all controls for this window to default settings
*/
void resetToDefaults();
private slots:
void onSizeXChanged(const QString& newText);
void onSizeYChanged(const QString& newText);
void onOffsetXChanged(const QString& newText);
void onOffsetYChanged(const QString& newText);
void onMonitorChanged(int newSelection);
void createWidgets(const QColor& windowColor);
QWidget* createPlanarWidget();
QWidget* createFisheyeWidget();
QWidget* createSphericalMirrorWidget();
QWidget* createCylindricalWidget();
QWidget* createEquirectangularWidget();
void onSizeXChanged(int newValue);
void onSizeYChanged(int newValue);
void onOffsetXChanged(int newValue);
void onOffsetYChanged(int newValue);
void onProjectionChanged(int newSelection);
void onFullscreenClicked();
void onSpoutSelection(int selectionState);
void onWebGuiSelection(int selectionState);
void onAspectRatioLockClicked();
void onFovLockClicked();
private:
void createWidgets(QWidget* parent);
void determineIdealWindowSize();
QString resolutionLabelText(QRect resolution);
sgct::config::Projections generateProjectionInformation() const;
void updatePlanarLockedFov();
void updateScaledWindowDimensions();
std::function<void(int, int, const QRectF&)> _windowChangeCallback;
std::function<void(unsigned int)> _windowGuiCheckCallback;
QRectF defaultWindowSizes[4] = {
{50.f, 50.f, 1280.f, 720.f},
{150.f, 150.f, 1280.f, 720.f},
{50.f, 50.f, 1280.f, 720.f},
{150.f, 150.f, 1280.f, 720.f}
};
QList<QString> _monitorNames = { "Primary", "Secondary" };
int QualityValues[10] = { 256, 512, 1024, 1536, 2048, 4096, 8192, 16384,
32768, 65536 };
int _lineEditWidthFixedWinSize = 50;
int _lineEditWidthFixedFov = 80;
const float _idealAspectRatio = 16.f / 9.f;
float _aspectRatioSize = _idealAspectRatio;
float _marginFractionOfWidgetSize = 0.025f;
float _defaultFovH = 80.f;
float _defaultFovV = 50.534f;
float _defaultHeightOffset = 0.f;
unsigned int _nMonitors = 1;
unsigned int _monIndex = 0;
unsigned int _monIndexDefault = 0;
unsigned int _index = 0;
static constexpr float IdealAspectRatio = 16.f / 9.f;
float _aspectRatioSize = IdealAspectRatio;
const int _monitorIndexDefault = 0;
int _windowIndex = 0;
bool _aspectRatioLocked = false;
bool _FovLocked = true;
std::vector<QRect>& _monitorResolutions;
int _maxWindowSizePixels = 10000;
const QColor& _colorForWindow;
QVBoxLayout* _layoutFullWindow = nullptr;
QLabel* _labelWinNum = nullptr;
QLineEdit* _sizeX = nullptr;
QLineEdit* _sizeY = nullptr;
QLineEdit* _offsetX = nullptr;
QLineEdit* _offsetY = nullptr;
QPushButton* _buttonLockAspectRatio = nullptr;
QPushButton* _buttonLockFov = nullptr;
QRectF _windowDims;
QPushButton* _fullscreenButton = nullptr;
QCheckBox* _checkBoxWindowDecor = nullptr;
QCheckBox* _checkBoxWebGui = nullptr;
QCheckBox* _checkBoxSpoutOutput = nullptr;
QComboBox* _comboMonitorSelect = nullptr;
QComboBox* _comboProjection = nullptr;
QComboBox* _comboQuality = nullptr;
QLabel* _labelQuality = nullptr;
QLabel* _labelFovH = nullptr;
QLineEdit* _lineFovH = nullptr;
QLabel* _labelFovV = nullptr;
QLineEdit* _lineFovV = nullptr;
QLabel* _labelHeightOffset = nullptr;
QLineEdit* _lineHeightOffset = nullptr;
bool _fovLocked = true;
std::vector<QRect> _monitorResolutions;
QRectF _windowDimensions;
QLabel* _windowNumber = nullptr;
QLineEdit* _windowName = nullptr;
QIcon _lockIcon;
QIcon _unlockIcon;
QComboBox* _monitor = nullptr;
QSpinBox* _sizeX = nullptr;
QSpinBox* _sizeY = nullptr;
QSpinBox* _offsetX = nullptr;
QSpinBox* _offsetY = nullptr;
QCheckBox* _windowDecoration = nullptr;
QComboBox* _projectionType = nullptr;
struct {
QWidget* widget = nullptr;
QDoubleSpinBox* fovH = nullptr;
QDoubleSpinBox* fovV = nullptr;
} _planar;
struct {
QWidget* widget = nullptr;
QComboBox* quality = nullptr;
QCheckBox* spoutOutput = nullptr;
} _fisheye;
struct {
QWidget* widget = nullptr;
QComboBox* quality = nullptr;
} _sphericalMirror;
struct {
QWidget* widget = nullptr;
QComboBox* quality = nullptr;
QDoubleSpinBox* heightOffset = nullptr;
} _cylindrical;
struct {
QWidget* widget = nullptr;
QComboBox* quality = nullptr;
QCheckBox* spoutOutput = nullptr;
} _equirectangular;
const QIcon _lockIcon;
const QIcon _unlockIcon;
};
#endif // __OPENSPACE_UI_LAUNCHER___WINDOWCONTROL___H__
@@ -178,3 +178,12 @@ HorizonsDialog QLabel#error {
HorizonsDialog QLabel#normal {
color: rgb(0, 0, 0);
}
/*
* SGCT
*/
WindowControl QLabel#info {
font-style: italic;
font-weight: normal;
font-size: 8pt;
}
@@ -143,7 +143,7 @@ namespace {
}
}
void saveWindowConfig(QWidget* parent, const std::string& path,
void saveWindowConfig(QWidget* parent, const std::filesystem::path& path,
sgct::config::Cluster& cluster)
{
std::ofstream outFile;
@@ -427,7 +427,8 @@ void LauncherWindow::populateProfilesList(std::string preset) {
profiles.push_back(path);
}
std::sort(profiles.begin(), profiles.end());
//add sorted items to list
// Add sorted items to list
for (const fs::directory_entry& profile : profiles) {
_profileBox->addItem(QString::fromStdString(profile.path().stem().string()));
}
@@ -471,7 +472,7 @@ void LauncherWindow::populateWindowConfigsList(std::string preset) {
bool hasXmlConfig = false;
//sort files
// Sort files
std::vector<fs::directory_entry> files;
for (const fs::directory_entry& p : fs::directory_iterator(_userConfigPath)) {
files.push_back(p);
@@ -492,7 +493,7 @@ void LauncherWindow::populateWindowConfigsList(std::string preset) {
model->item(_userConfigCount)->setEnabled(false);
if (std::filesystem::exists(_configPath)) {
//sort files
// Sort files
files.clear();
for (const fs::directory_entry& p : fs::directory_iterator(_configPath)) {
files.push_back(p);
@@ -522,7 +523,7 @@ void LauncherWindow::populateWindowConfigsList(std::string preset) {
);
}
//Always add the .cfg sgct default as first item
// Always add the .cfg sgct default as first item
_windowConfigBox->insertItem(0, QString::fromStdString(_sgctConfigName));
// Try to find the requested configuration file and set it as the current one. As we
// have support for function-generated configuration files that will not be in the
@@ -534,8 +535,8 @@ void LauncherWindow::populateWindowConfigsList(std::string preset) {
else {
// Add the requested preset at the top
_windowConfigBox->insertItem(1, QString::fromStdString(preset));
//Increment the user config count because there is an additional option added
//before the user config options
// Increment the user config count because there is an additional option added
// before the user config options
_userConfigCount++;
_windowConfigBox->setCurrentIndex(1);
}
@@ -546,7 +547,6 @@ void LauncherWindow::openProfileEditor(const std::string& profile, bool isUserPr
std::string saveProfilePath = isUserProfile ? _userProfilePath : _profilePath;
if (profile.empty()) {
// If the requested profile is the empty string, then we want to create a new one
p = Profile();
}
else {
@@ -559,13 +559,21 @@ void LauncherWindow::openProfileEditor(const std::string& profile, bool isUserPr
}
}
ProfileEdit editor(*p, profile, _assetPath, _userAssetPath, saveProfilePath, _readOnlyProfiles, this);
ProfileEdit editor(
*p,
profile,
_assetPath,
_userAssetPath,
saveProfilePath,
_readOnlyProfiles,
this
);
editor.exec();
if (editor.wasSaved()) {
if (editor.specifiedFilename() != profile) {
saveProfilePath = _userProfilePath;
}
const std::string path = saveProfilePath + editor.specifiedFilename() + ".profile";
std::string path = saveProfilePath + editor.specifiedFilename() + ".profile";
saveProfile(this, path, *p);
populateProfilesList(editor.specifiedFilename());
}
@@ -576,40 +584,16 @@ void LauncherWindow::openProfileEditor(const std::string& profile, bool isUserPr
}
void LauncherWindow::openWindowEditor() {
QList<QScreen*> screenList = qApp->screens();
if (screenList.length() == 0) {
LERRORC(
"LauncherWindow",
"Error: Qt reports no screens/monitors available"
);
return;
}
sgct::config::Cluster cluster;
std::vector<sgct::config::Window> windowList;
SgctEdit editor(this, windowList, cluster, screenList, _userConfigPath);
editor.exec();
if (editor.wasSaved()) {
std::string ext = ".json";
std::string savePath = editor.saveFilename();
if (savePath.size() >= ext.size()
&& !(savePath.substr(savePath.size() - ext.size()).compare(ext) == 0))
{
savePath += ext;
}
if (cluster.nodes.size() == 0) {
cluster.nodes.push_back(sgct::config::Node());
}
for (auto w : windowList) {
cluster.nodes[0].windows.push_back(w);
}
SgctEdit editor(this, _userConfigPath);
int ret = editor.exec();
if (ret == QDialog::DialogCode::Accepted) {
sgct::config::Cluster cluster = editor.cluster();
std::filesystem::path savePath = editor.saveFilename();
saveWindowConfig(this, savePath, cluster);
//Truncate path to convert this back to path relative to _userConfigPath
savePath = savePath.substr(_userConfigPath.size());
populateWindowConfigsList(savePath);
}
else {
const std::string current = _windowConfigBox->currentText().toStdString();
populateWindowConfigsList(current);
// Truncate path to convert this back to path relative to _userConfigPath
std::string p = savePath.string().substr(_userConfigPath.size());
populateWindowConfigsList(p);
}
}
@@ -625,7 +609,8 @@ std::string LauncherWindow::selectedWindowConfig() const {
int idx = _windowConfigBox->currentIndex();
if (idx == 0) {
return _sgctConfigName;
} else if (idx > _userConfigCount) {
}
else if (idx > _userConfigCount) {
return "${CONFIG}/" + _windowConfigBox->currentText().toStdString();
}
else {
@@ -85,7 +85,7 @@ void ActionDialog::createWidgets() {
// | | Is Local | [] [choosescr] | Row 5
// | | Script | [oooooooooooo] | Row 6
// *----------------------*---------------*----------------*
// | [+] [-] | | [Save] [Cancel]| Row 7
// | [+] [-] | | <Save> <Cancel>| Row 7
// *----------------------*---------------*----------------*
// |=======================================================| Row 8
// | Keybindings | Row 9
@@ -95,11 +95,11 @@ void ActionDialog::createWidgets() {
// | | Add actions | DDDDDDDDDDDD> | Row 12
// | | Action | [oooooooooooo] | Row 13
// *----------------------*---------------*----------------*
// | [+] [-] | | [Save] [Cancel]| Row 14
// | [+] [-] | | <Save> <Cancel>| Row 14
// *----------------------*---------------*----------------*
// |=======================================================| Row 14
// *----------------------*---------------*----------------*
// | | [Save] [Cancel]| Row 15
// | | <Save> <Cancel>| Row 15
// *----------------------*---------------*----------------*
QGridLayout* layout = new QGridLayout(this);
@@ -35,6 +35,8 @@
#include <QPushButton>
#include <QVBoxLayout>
#include <QWidget>
#include <filesystem>
#include <string>
AssetEdit::AssetEdit(QWidget* parent)
: QDialog(parent)
@@ -46,18 +48,15 @@ AssetEdit::AssetEdit(QWidget* parent)
void AssetEdit::createWidgets() {
_layout = new QVBoxLayout(this);
{
QLabel* heading =
new QLabel("The Asset Editor is coming soon in a future release", this);
QLabel* heading = new QLabel("The Asset Editor is coming in a future release");
heading->setObjectName("heading");
_layout->addWidget(heading);
}
{
QPushButton* generateButton = new QPushButton("Generate Horizons File", this);
QPushButton* generateButton = new QPushButton("Generate Horizons File");
connect(
generateButton,
&QPushButton::released,
this,
&AssetEdit::openHorizons
generateButton, &QPushButton::released,
this, &AssetEdit::openHorizons
);
generateButton->setDefault(false);
@@ -73,32 +72,32 @@ void AssetEdit::createWidgets() {
_layout->addWidget(generateButton);
}
/*{
QBoxLayout* container = new QHBoxLayout(this);
QLabel* assetLabel = new QLabel("Asset Name:");
assetLabel->setObjectName("profile");
container->addWidget(assetLabel);
//{
// QBoxLayout* container = new QHBoxLayout(this);
// QLabel* assetLabel = new QLabel("Asset Name:");
// assetLabel->setObjectName("profile");
// container->addWidget(assetLabel);
_nameEdit = new QLineEdit();
container->addWidget(_nameEdit);
// _nameEdit = new QLineEdit();
// container->addWidget(_nameEdit);
_layout->addLayout(container);
}
_layout->addWidget(new Line);
{
QBoxLayout* container = new QHBoxLayout(this);
_components = new QComboBox(this);
_components->addItems(_supportedComponents);
_components->setCurrentIndex(0);
container->addWidget(_components);
// _layout->addLayout(container);
//}
//_layout->addWidget(new Line);
//{
// QBoxLayout* container = new QHBoxLayout(this);
// _components = new QComboBox(this);
// _components->addItems(_supportedComponents);
// _components->setCurrentIndex(0);
// container->addWidget(_components);
QPushButton* addButton = new QPushButton("Add", this);
connect(addButton, &QPushButton::clicked, this, &AssetEdit::openComponent);
addButton->setCursor(Qt::PointingHandCursor);
container->addWidget(addButton);
// QPushButton* addButton = new QPushButton("Add", this);
// connect(addButton, &QPushButton::clicked, this, &AssetEdit::openComponent);
// addButton->setCursor(Qt::PointingHandCursor);
// container->addWidget(addButton);
_layout->addLayout(container);
}*/
// _layout->addLayout(container);
//}
_layout->addWidget(new Line);
{
QBoxLayout* footer = new QHBoxLayout;
@@ -116,77 +115,77 @@ void AssetEdit::createWidgets() {
}
}
/*void AssetEdit::openComponent() {
switch (_components->currentIndex()) {
case 0:
_errorMsg->setText("Choose a component to add to the asset");
break;
case 1: {
QBoxLayout* horizonsLayout = new QVBoxLayout(this);
{
QLabel* label = new QLabel("Horizons Translation:", this);
label->setObjectName("heading");
horizonsLayout->addWidget(label);
}
{
QBoxLayout* container = new QHBoxLayout(this);
QLabel* fileLabel = new QLabel("File path:", this);
container->addWidget(fileLabel);
_horizonsFileEdit = new QLineEdit(this);
container->addWidget(_horizonsFileEdit);
QPushButton* fileButton = new QPushButton("Browse", this);
connect(
fileButton,
&QPushButton::released,
this,
&AssetEdit::openHorizonsFile
);
fileButton->setCursor(Qt::PointingHandCursor);
container->addWidget(fileButton);
QPushButton* generateButton = new QPushButton("Generate", this);
connect(
generateButton,
&QPushButton::released,
this,
&AssetEdit::openHorizons
);
// In order to generate a Horizons File the Space module is required
#ifndef OPENSPACE_MODULE_SPACE_ENABLED
generateButton->setEnabled(false);
generateButton->setToolTip(
"Connot generate Horizons file without the space module enabled"
);
#else
generateButton->setCursor(Qt::PointingHandCursor);
#endif // OPENSPACE_MODULE_SPACE_ENABLED
container->addWidget(generateButton);
horizonsLayout->addLayout(container);
}
horizonsLayout->addWidget(new Line);
_layout->insertLayout(_layout->count() - 3, horizonsLayout);
break;
}
default:
_errorMsg->setText("Unkown component");
break;
}
}
void AssetEdit::openHorizonsFile() {
std::string filePath = QFileDialog::getOpenFileName(
this,
tr("Open Horizons file"),
"",
tr("Horiozons file (*.dat)")
).toStdString();
_horizonsFile = std::filesystem::absolute(filePath);
_horizonsFileEdit->setText(QString(_horizonsFile.string().c_str()));
}*/
//void AssetEdit::openComponent() {
// switch (_components->currentIndex()) {
// case 0:
// _errorMsg->setText("Choose a component to add to the asset");
// break;
// case 1: {
// QBoxLayout* horizonsLayout = new QVBoxLayout(this);
// {
// QLabel* label = new QLabel("Horizons Translation:", this);
// label->setObjectName("heading");
// horizonsLayout->addWidget(label);
// }
// {
// QBoxLayout* container = new QHBoxLayout(this);
// QLabel* fileLabel = new QLabel("File path:", this);
// container->addWidget(fileLabel);
//
// _horizonsFileEdit = new QLineEdit(this);
// container->addWidget(_horizonsFileEdit);
//
// QPushButton* fileButton = new QPushButton("Browse", this);
// connect(
// fileButton,
// &QPushButton::released,
// this,
// &AssetEdit::openHorizonsFile
// );
// fileButton->setCursor(Qt::PointingHandCursor);
// container->addWidget(fileButton);
//
// QPushButton* generateButton = new QPushButton("Generate", this);
// connect(
// generateButton,
// &QPushButton::released,
// this,
// &AssetEdit::openHorizons
// );
//
// // In order to generate a Horizons File the Space module is required
// #ifndef OPENSPACE_MODULE_SPACE_ENABLED
// generateButton->setEnabled(false);
// generateButton->setToolTip(
// "Connot generate Horizons file without the space module enabled"
// );
// #else
// generateButton->setCursor(Qt::PointingHandCursor);
// #endif // OPENSPACE_MODULE_SPACE_ENABLED
//
// container->addWidget(generateButton);
// horizonsLayout->addLayout(container);
// }
// horizonsLayout->addWidget(new Line);
// _layout->insertLayout(_layout->count() - 3, horizonsLayout);
// break;
// }
// default:
// _errorMsg->setText("Unkown component");
// break;
// }
//}
//
//void AssetEdit::openHorizonsFile() {
// std::string filePath = QFileDialog::getOpenFileName(
// this,
// tr("Open Horizons file"),
// "",
// tr("Horiozons file (*.dat)")
// ).toStdString();
// _horizonsFile = std::filesystem::absolute(filePath);
// _horizonsFileEdit->setText(QString(_horizonsFile.string().c_str()));
//}
void AssetEdit::openHorizons() {
_errorMsg->clear();
@@ -199,10 +198,10 @@ void AssetEdit::openHorizons() {
}
void AssetEdit::approved() {
/*std::string assetName = _nameEdit->text().toStdString();
if (assetName.empty()) {
_errorMsg->setText("Asset name must be specified");
return;
}*/
// std::string assetName = _nameEdit->text().toStdString();
// if (assetName.empty()) {
// _errorMsg->setText("Asset name must be specified");
// return;
// }
accept();
}
@@ -25,7 +25,6 @@
#include "profile/assetsdialog.h"
#include "profile/assetedit.h"
#include "profile/line.h"
#include <openspace/scene/profile.h>
#include <ghoul/fmt.h>
@@ -38,8 +37,8 @@
#include <QTreeView>
namespace {
bool traverseToExpandSelectedItems(QTreeView& tree, AssetTreeModel& model,
int rows, QModelIndex parent)
bool traverseToExpandSelectedItems(QTreeView& tree, AssetTreeModel& model, int rows,
QModelIndex parent)
{
bool isExpanded = false;
@@ -144,7 +143,7 @@ AssetsDialog::AssetsDialog(QWidget* parent, openspace::Profile* profile,
heading->setObjectName("heading");
container->addWidget(heading, 0, 0);
QPushButton* newAssetButton = new QPushButton("New Asset", this);
QPushButton* newAssetButton = new QPushButton("New Asset");
connect(
newAssetButton, &QPushButton::released,
this, &AssetsDialog::openAssetEditor
@@ -24,8 +24,8 @@
#include "profile/assettreeitem.h"
AssetTreeItem::AssetTreeItem(const std::vector<QVariant>& data, AssetTreeItem* parentItem)
: _itemData(data)
AssetTreeItem::AssetTreeItem(std::vector<QVariant> data, AssetTreeItem* parentItem)
: _itemData(std::move(data))
, _parentItem(parentItem)
{}
@@ -35,12 +35,12 @@ AssetTreeItem::~AssetTreeItem() {
}
}
AssetTreeItem* AssetTreeItem::child(int row) {
if (row < 0 || row >= static_cast<int>(_childItems.size())) {
return nullptr;
AssetTreeItem* AssetTreeItem::child(int row) const {
if (row >= 0 && row < static_cast<int>(_childItems.size())) {
return _childItems.at(row);
}
else {
return _childItems.at(row);
return nullptr;
}
}
@@ -67,11 +67,11 @@ int AssetTreeItem::columnCount() const {
}
QVariant AssetTreeItem::data(int column) const {
if (column < 0 || column >= static_cast<int>(_itemData.size())) {
return QVariant();
if (column >= 0 && column < static_cast<int>(_itemData.size())) {
return _itemData.at(column);
}
else {
return _itemData.at(column);
return QVariant();
}
}
@@ -96,11 +96,11 @@ void AssetTreeItem::setChecked(bool set) {
}
bool AssetTreeItem::isAsset() const {
return (childCount() == 0);
return childCount() == 0;
}
bool AssetTreeItem::isCategory() const {
return (childCount() > 0);
return childCount() > 0;
}
void AssetTreeItem::setExistsInFilesystem(bool fileExists) {
@@ -139,8 +139,9 @@ AssetTreeModel::AssetTreeModel(QObject* parent)
: QAbstractItemModel(parent)
{
_rootItem = std::make_unique<AssetTreeItem>(
std::vector<QVariant>{
QString::fromStdString(Header1), QString::fromStdString(Header2)
std::vector<QVariant> {
QString::fromStdString(Header1),
QString::fromStdString(Header2)
}
);
}
@@ -162,7 +163,7 @@ void AssetTreeModel::importModelData(const std::string& assetBasePath,
}
}
AssetTreeItem* AssetTreeModel::getItem(const QModelIndex& index) const {
AssetTreeItem* AssetTreeModel::item(const QModelIndex& index) const {
if (index.isValid()) {
AssetTreeItem* item = static_cast<AssetTreeItem*>(index.internalPointer());
if (item) {
@@ -173,46 +174,46 @@ AssetTreeItem* AssetTreeModel::getItem(const QModelIndex& index) const {
}
bool AssetTreeModel::isChecked(QModelIndex& index) const {
AssetTreeItem* item = getItem(index);
const int isChecked = item->data(1).toInt();
AssetTreeItem* i = item(index);
const int isChecked = i->data(1).toInt();
return isChecked == Qt::Checked;
}
bool AssetTreeModel::isAsset(QModelIndex& index) const {
AssetTreeItem* item = getItem(index);
return item->isAsset();
AssetTreeItem* i = item(index);
return i->isAsset();
}
bool AssetTreeModel::inFilesystem(QModelIndex& index) const {
AssetTreeItem* item = getItem(index);
return item->doesExistInFilesystem();
AssetTreeItem* i = item(index);
return i->doesExistInFilesystem();
}
int AssetTreeModel::childCount(QModelIndex& index) const {
return getItem(index)->childCount();
return item(index)->childCount();
}
QString AssetTreeModel::name(QModelIndex& index) const {
return getItem(index)->name();
return item(index)->name();
}
void AssetTreeModel::setName(QModelIndex& index, QString name) {
getItem(index)->setData(0, name);
item(index)->setData(0, name);
}
void AssetTreeModel::setChecked(QModelIndex& index, bool checked) {
getItem(index)->setData(1, checked ? Qt::Checked : Qt::Unchecked);
item(index)->setData(1, checked ? Qt::Checked : Qt::Unchecked);
}
void AssetTreeModel::setExistenceInFilesystem(QModelIndex& index, bool fileExists) {
getItem(index)->setExistsInFilesystem(fileExists);
item(index)->setExistsInFilesystem(fileExists);
}
AssetTreeItem* AssetTreeModel::child(int row) const {
QModelIndex i = index(row, 0);
int nKids = childCount(i);
if (row < nKids) {
return getItem(i)->child(row);
const int nChildren = childCount(i);
if (row < nChildren) {
return item(i)->child(row);
}
return nullptr;
}
@@ -224,7 +225,7 @@ QModelIndex AssetTreeModel::index(int row, int column, const QModelIndex& parent
if (!hasIndex(row, column, parent)) {
return QModelIndex();
}
AssetTreeItem* parentItem = getItem(parent);
AssetTreeItem* parentItem = item(parent);
if (!parentItem) {
return QModelIndex();
}
@@ -250,7 +251,7 @@ QModelIndex AssetTreeModel::parent(const QModelIndex& index) const {
return QModelIndex();
}
AssetTreeItem* childItem = getItem(index);
AssetTreeItem* childItem = item(index);
AssetTreeItem* parentItem = childItem ? childItem->parent() : nullptr;
if (parentItem == _rootItem.get() || !parentItem) {
return QModelIndex();
@@ -260,11 +261,11 @@ QModelIndex AssetTreeModel::parent(const QModelIndex& index) const {
}
AssetTreeItem* AssetTreeModel::assetItem(const QModelIndex& index) {
return getItem(index);
return item(index);
}
int AssetTreeModel::rowCount(const QModelIndex& parent) const {
const AssetTreeItem* parentItem = getItem(parent);
const AssetTreeItem* parentItem = item(parent);
return parentItem ? parentItem->childCount() : 0;
}
@@ -289,12 +290,7 @@ QVariant AssetTreeModel::data(const QModelIndex& index, int role) const {
}
if (role == Qt::ForegroundRole) {
if (item->doesExistInFilesystem()) {
return QVariant(QColor(Qt::black));
}
else {
return QVariant(QColor(Qt::red));
}
return item->doesExistInFilesystem() ? QColor(Qt::black) : QColor(Qt::red);
}
else if (role == Qt::DisplayRole) {
return item->data(index.column());
@@ -345,7 +341,7 @@ QVariant AssetTreeModel::headerData(int section, Qt::Orientation orientation,
}
void AssetTreeModel::getSelectedAssets(std::vector<std::string>& outputPaths,
std::vector<AssetTreeItem*>& outputItems)
std::vector<AssetTreeItem*>& outputItems)
{
parseChildrenForSelected(_rootItem.get(), outputPaths, outputItems, "");
}
@@ -39,7 +39,7 @@ namespace {
constexpr const int CameraTypeGeo = 1;
template <class... Ts> struct overloaded : Ts... { using Ts::operator()...; };
template <class... Ts> overloaded(Ts...)->overloaded<Ts...>;
template <class... Ts> overloaded(Ts...) -> overloaded<Ts...>;
bool inNumericalRange(QLineEdit* le, float min, float max) {
QString s = le->text();
@@ -41,14 +41,14 @@
#include <iostream>
namespace {
constexpr const int MaxNumberOfKeys = 30;
constexpr int MaxNumberOfKeys = 30;
struct TimeInterval {
uint64_t secondsPerInterval;
std::string intervalName;
};
std::array<TimeInterval, 7> TimeIntervals = {
const std::array<TimeInterval, 7> TimeIntervals = {
TimeInterval{ 31536000, "year" },
TimeInterval{ 18144000, "month" },
TimeInterval{ 604800, "week" },
@@ -98,17 +98,16 @@ DeltaTimesDialog::DeltaTimesDialog(QWidget* parent, std::vector<double>* deltaTi
void DeltaTimesDialog::createWidgets() {
QBoxLayout* layout = new QVBoxLayout(this);
{
_listWidget = new QListWidget;
connect(
_listWidget, &QListWidget::itemSelectionChanged,
this, &DeltaTimesDialog::listItemSelected
);
_listWidget->setAutoScroll(true);
_listWidget->setLayoutMode(QListView::SinglePass);
layout->addWidget(_listWidget);
}
_listWidget = new QListWidget;
connect(
_listWidget, &QListWidget::itemSelectionChanged,
this, &DeltaTimesDialog::listItemSelected
);
_listWidget->setAutoScroll(true);
_listWidget->setLayoutMode(QListView::SinglePass);
layout->addWidget(_listWidget);
{
QBoxLayout* buttonLayout = new QHBoxLayout;
_addButton = new QPushButton("Add Entry");
@@ -128,10 +127,10 @@ void DeltaTimesDialog::createWidgets() {
buttonLayout->addStretch();
layout->addLayout(buttonLayout);
}
{
_adjustLabel = new QLabel("Set Simulation Time Increment for key");
layout->addWidget(_adjustLabel);
}
_adjustLabel = new QLabel("Set Simulation Time Increment for key");
layout->addWidget(_adjustLabel);
{
QBoxLayout* box = new QHBoxLayout;
_seconds = new QLineEdit;
@@ -184,7 +183,7 @@ void DeltaTimesDialog::createWidgets() {
}
std::string DeltaTimesDialog::createSummaryForDeltaTime(size_t idx, bool forListView) {
int k = (idx%10 == 9) ? 0 : idx%10 + 1;
int k = (idx % 10 == 9) ? 0 : idx % 10 + 1;
k = (idx == 0) ? 1 : k;
std::string key = std::to_string(k);
@@ -204,9 +203,7 @@ std::string DeltaTimesDialog::createSummaryForDeltaTime(size_t idx, bool forList
if (forListView) {
s += fmt::format(
"\t{}\t{}",
std::to_string(_deltaTimesData.at(idx)),
timeDescription(_deltaTimesData.at(idx))
"\t{}\t{}", _deltaTimesData.at(idx), timeDescription(_deltaTimesData.at(idx))
);
}
return s;
@@ -252,9 +249,7 @@ void DeltaTimesDialog::valueChanged(const QString& text) {
else {
int value = text.toDouble();
if (value != 0) {
_value->setText(QString::fromStdString(
timeDescription(text.toDouble()))
);
_value->setText(QString::fromStdString(timeDescription(text.toDouble())));
_errorMsg->setText("");
}
}
@@ -296,15 +291,13 @@ void DeltaTimesDialog::addDeltaTimeValue() {
void DeltaTimesDialog::saveDeltaTimeValue() {
QListWidgetItem* item = _listWidget->currentItem();
if (item != nullptr) {
if (item && !_deltaTimesData.empty()) {
int index = _listWidget->row(item);
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);
_editModeNewItem = false;
}
_deltaTimesData.at(index) = _seconds->text().toDouble();
std::string summary = createSummaryForDeltaTime(index, true);
_listWidget->item(index)->setText(QString::fromStdString(summary));
transitionEditMode(index, false);
_editModeNewItem = false;
}
}
@@ -28,29 +28,37 @@
#include <ghoul/filesystem/filesystem.h>
#include <ghoul/fmt.h>
#include <ghoul/logging/logmanager.h>
#include <ghoul/misc/boolean.h>
#include <QComboBox>
#include <QDateTimeEdit>
#include <QDialogButtonBox>
#include <QDir>
#include <QEventLoop>
#include <QFileDialog>
#include <QGridLayout>
#include <QLabel>
#include <QLineEdit>
#include <QMessageBox>
#include <QNetworkAccessManager>
#include <QNetworkReply>
#include <QNetworkRequest>
#include <QPlainTextEdit>
#include <QProgressBar>
#include <QPushButton>
#include <QScrollBar>
#include <QVBoxLayout>
#include <algorithm>
#include <fstream>
#include <iostream>
#include <QStyle>
#include <sstream>
using json = nlohmann::json;
using namespace openspace;
namespace {
BooleanType(IsDirty);
void styleLabel(QLabel* label, IsDirty isDirty) {
std::string newStyle = isDirty ? "error" : "normal";
label->setObjectName(QString::fromStdString(newStyle));
label->style()->unpolish(label);
label->style()->polish(label);
}
} // namespace
namespace {
constexpr std::string_view _loggerCat = "HorizonsDialog";
@@ -85,20 +93,23 @@ HorizonsDialog::HorizonsDialog(QWidget* parent)
#endif // OPENSPACE_MODULE_SPACE_ENABLED
}
#ifdef OPENSPACE_MODULE_SPACE_ENABLED
std::filesystem::path HorizonsDialog::file() const {
#ifdef OPENSPACE_MODULE_SPACE_ENABLED
return _horizonsFile.file();
}
#else // OPENSPACE_MODULE_SPACE_ENABLED
return std::filesystem::path();
#endif // OPENSPACE_MODULE_SPACE_ENABLED
}
void HorizonsDialog::openSaveAs() {
QString filename = QFileDialog::getSaveFileName(
this,
"Choose a file path where the generated Horizons file will be saved",
QString::fromStdString(absPath("${USER}").string()),
"Horizons data file (*.hrz);;(*.hrz)",
"Horizons data file (*.hrz)",
nullptr
#ifdef __linux__
// Linux in Qt5 and Qt6 crashes when trying to access the native dialog here
, QFileDialog::DontUseNativeDialog
#endif
);
@@ -116,49 +127,34 @@ void HorizonsDialog::typeOnChange(int index) {
}
else {
_errorMsg->setText("Invalid Horizons type");
styleLabel(_typeLabel, true);
styleLabel(_typeLabel, IsDirty::Yes);
}
}
void HorizonsDialog::downloadProgress(int value, int total) {
if (total < 0) {
_downloadProgress->setRange(0, 0);
return;
}
_downloadProgress->setRange(0, total);
_downloadProgress->setValue(value);
else {
_downloadProgress->setRange(0, total);
_downloadProgress->setValue(value);
}
}
void HorizonsDialog::importTimeRange() {
QDateTime start, end;
start = QDateTime::fromString(
QString::fromStdString(_validTimeRange.first),
"yyyy-MMM-dd T hh:mm"
);
end = QDateTime::fromString(
QString::fromStdString(_validTimeRange.second),
"yyyy-MMM-dd T hh:mm"
);
QString startStr = QString::fromStdString(_validTimeRange.first);
QString endStr = QString::fromStdString(_validTimeRange.second);
QDateTime start = QDateTime::fromString(startStr, "yyyy-MMM-dd T hh:mm");
QDateTime end = QDateTime::fromString(endStr, "yyyy-MMM-dd T hh:mm");
if (!start.isValid() || !end.isValid()) {
start = QDateTime::fromString(
QString::fromStdString(_validTimeRange.first),
"yyyy-MMM-dd T hh:mm:ss"
);
end = QDateTime::fromString(
QString::fromStdString(_validTimeRange.second),
"yyyy-MMM-dd T hh:mm:ss"
);
start = QDateTime::fromString(startStr, "yyyy-MMM-dd T hh:mm:ss");
end = QDateTime::fromString(endStr, "yyyy-MMM-dd T hh:mm:ss");
if (!start.isValid() || !end.isValid()) {
QDate startDate = QDate::fromString(
QString::fromStdString(_validTimeRange.first),
"yyyy-MMM-dd"
);
QDate endDate = QDate::fromString(
QString::fromStdString(_validTimeRange.second),
"yyyy-MMM-dd"
);
QDate startDate = QDate::fromString(startStr, "yyyy-MMM-dd");
QDate endDate = QDate::fromString(endStr, "yyyy-MMM-dd");
if (startDate.isValid() && endDate.isValid()) {
_startEdit->setDate(startDate);
@@ -170,8 +166,8 @@ void HorizonsDialog::importTimeRange() {
_errorMsg->setText("Could not import time range");
std::string msg = fmt::format(
"Could not import time range '{}' to '{}'", _validTimeRange.first,
_validTimeRange.second
"Could not import time range '{}' to '{}'",
_validTimeRange.first, _validTimeRange.second
);
appendLog(msg, LogLevel::Error);
return;
@@ -183,17 +179,17 @@ void HorizonsDialog::importTimeRange() {
_validTimeRange = std::pair<std::string, std::string>();
}
#ifdef OPENSPACE_MODULE_SPACE_ENABLED
// When the user presses the 'Save' button
void HorizonsDialog::approved() {
#ifdef OPENSPACE_MODULE_SPACE_ENABLED
_downloadLabel->show();
bool result = handleRequest();
_downloadLabel->hide();
if (result && std::filesystem::is_regular_file(_horizonsFile.file())) {
accept();
}
}
#endif // OPENSPACE_MODULE_SPACE_ENABLED
}
void HorizonsDialog::createWidgets() {
QGridLayout* layout = new QGridLayout(this);
@@ -203,10 +199,10 @@ void HorizonsDialog::createWidgets() {
generateLabel->setObjectName("heading");
layout->addWidget(generateLabel, 0, 0, 1, 3);
QLabel* infoLabel = new QLabel("<p>For more information about the Horizons "
"system please visit: <a href=\"https://ssd.jpl.nasa.gov/horizons/\">"
"https://ssd.jpl.nasa.gov/horizons/</a></p>",
this
QLabel* infoLabel = new QLabel(
"<p>For more information about the Horizons system please visit: "
"<a href=\"https://ssd.jpl.nasa.gov/horizons/\">"
"https://ssd.jpl.nasa.gov/horizons/</a></p>"
);
infoLabel->setWordWrap(true);
infoLabel->setObjectName("thin");
@@ -214,11 +210,11 @@ void HorizonsDialog::createWidgets() {
layout->addWidget(infoLabel, 1, 0, 1, 3);
}
{
_typeLabel = new QLabel("Horizons data type:", this);
_typeLabel = new QLabel("Horizons data type:");
_typeLabel->setToolTip("Choose Horizons data type");
layout->addWidget(_typeLabel, 2, 0, 1, 2);
_typeCombo = new QComboBox(this);
_typeCombo = new QComboBox;
_typeCombo->setToolTip("Choose Horizons data type");
QStringList types = {
"Vector table",
@@ -226,24 +222,26 @@ void HorizonsDialog::createWidgets() {
};
_typeCombo->addItems(types);
_typeCombo->setCurrentIndex(0);
connect(_typeCombo, QOverload<int>::of(&QComboBox::currentIndexChanged),
connect(
_typeCombo, QOverload<int>::of(&QComboBox::currentIndexChanged),
this, &HorizonsDialog::typeOnChange
);
layout->addWidget(_typeCombo, 2, 2);
}
{
_fileLabel = new QLabel("File Path:", this);
_fileLabel = new QLabel("File Path:");
_fileLabel->setToolTip("Where the generated Horizons file is saved");
layout->addWidget(_fileLabel, 3, 0);
QBoxLayout* container = new QHBoxLayout(this);
QBoxLayout* container = new QHBoxLayout;
_fileEdit = new QLineEdit(this);
_fileEdit->setToolTip("Where the generated Horizons file is saved");
container->addWidget(_fileEdit);
QPushButton* browseButton = new QPushButton("Browse", this);
QPushButton* browseButton = new QPushButton("Browse");
browseButton->setDefault(false);
connect(browseButton, &QPushButton::released, this,
connect(
browseButton, &QPushButton::released, this,
&HorizonsDialog::openSaveAs
);
browseButton->setCursor(Qt::PointingHandCursor);
@@ -255,20 +253,19 @@ void HorizonsDialog::createWidgets() {
layout->addLayout(container, 3, 1, 1, 2);
}
{
_targetLabel = new QLabel("Target Body:", this);
_targetLabel = new QLabel("Target Body:");
_targetLabel->setToolTip(
"Which target or body would you like Horizons trajectery data for?"
);
layout->addWidget(_targetLabel, 4, 0);
_targetEdit =
new QLineEdit("Tesla", this);
_targetEdit = new QLineEdit("Tesla");
_targetEdit->setToolTip(
"Which target or body would you like Horizons trajectery data for?"
);
layout->addWidget(_targetEdit, 4, 1, 1, 2);
_chooseTargetCombo = new QComboBox(this);
_chooseTargetCombo = new QComboBox;
_chooseTargetCombo->setObjectName("mono");
_chooseTargetCombo->hide();
_chooseTargetCombo->setToolTip(
@@ -277,15 +274,15 @@ void HorizonsDialog::createWidgets() {
layout->addWidget(_chooseTargetCombo, 5, 1, 1, 2);
}
{
_centerLabel = new QLabel("Observer Location:", this);
_centerLabel = new QLabel("Observer Location:");
_centerLabel->setToolTip("In which reference frame do you want the data in?");
layout->addWidget(_centerLabel, 6, 0);
_centerEdit = new QLineEdit(QString::fromStdString("@ssb"), this);
_centerEdit = new QLineEdit(QString::fromStdString("@ssb"));
_centerEdit->setToolTip("In which reference frame do you want the data in?");
layout->addWidget(_centerEdit, 6, 1, 1, 2);
_chooseObserverCombo = new QComboBox(this);
_chooseObserverCombo = new QComboBox;
_chooseObserverCombo->setObjectName("mono");
_chooseObserverCombo->hide();
_chooseObserverCombo->setToolTip(
@@ -294,17 +291,17 @@ void HorizonsDialog::createWidgets() {
layout->addWidget(_chooseObserverCombo, 7, 1, 1, 2);
}
{
_startLabel = new QLabel("Start Time:", this);
_startLabel = new QLabel("Start Time:");
_startLabel->setToolTip("Enter the start date and time for the data");
layout->addWidget(_startLabel, 8, 0, 1, 2);
_startEdit = new QDateTimeEdit(this);
_startEdit = new QDateTimeEdit;
_startEdit->setDisplayFormat("yyyy-MM-dd T hh:mm:ss");
_startEdit->setDate(QDate::currentDate().addYears(-1));
_startEdit->setToolTip("Enter the start date and time for the data");
layout->addWidget(_startEdit, 8, 2);
}
{
_endLabel = new QLabel("End Time:", this);
_endLabel = new QLabel("End Time:");
_endLabel->setToolTip("Enter the end date and time for the data");
layout->addWidget(_endLabel, 9, 0, 1, 2);
_endEdit = new QDateTimeEdit(this);
@@ -314,30 +311,29 @@ void HorizonsDialog::createWidgets() {
layout->addWidget(_endEdit, 9, 2);
}
{
_importTimeButton = new QPushButton("Import timerange", this);
_importTimeButton = new QPushButton("Import timerange");
_importTimeButton->setDefault(false);
connect(_importTimeButton, &QPushButton::released, this,
&HorizonsDialog::importTimeRange
connect(
_importTimeButton, &QPushButton::released,
this, &HorizonsDialog::importTimeRange
);
_importTimeButton->setCursor(Qt::PointingHandCursor);
_importTimeButton->setToolTip(
"Import parsed timerange for full data coverage"
);
_importTimeButton->setToolTip("Import parsed timerange for full data coverage");
_importTimeButton->hide();
layout->addWidget(_importTimeButton, 10, 2);
}
{
_stepLabel = new QLabel("Step Size:", this);
_stepLabel = new QLabel("Step Size:");
_stepLabel->setToolTip("Enter the step size for the data");
layout->addWidget(_stepLabel, 11, 0);
_stepEdit = new QLineEdit(this);
_stepEdit = new QLineEdit;
_stepEdit->setValidator(new QIntValidator(this));
_stepEdit->setText(QString::number(1));
_stepEdit->setToolTip("Enter the step size for the data");
layout->addWidget(_stepEdit, 11, 1);
_timeTypeCombo = new QComboBox(this);
_timeTypeCombo = new QComboBox;
_timeTypeCombo->setToolTip("Choose unit of the step size");
QStringList timeTypes = {
Minutes.data(),
@@ -353,7 +349,7 @@ void HorizonsDialog::createWidgets() {
}
layout->addWidget(new Line, 12, 0, 1, 3);
{
_log = new QPlainTextEdit(this);
_log = new QPlainTextEdit;
_log->setReadOnly(true);
_log->setObjectName("log");
@@ -369,55 +365,36 @@ void HorizonsDialog::createWidgets() {
}
layout->addWidget(new Line, 14, 0, 1, 3);
{
_downloadLabel = new QLabel("Downloading file...", this);
_downloadLabel = new QLabel("Downloading file...");
_downloadLabel->setObjectName("thin");
_downloadLabel->hide();
layout->addWidget(_downloadLabel, 15, 0);
_downloadProgress = new QProgressBar(this);
_downloadProgress = new QProgressBar;
_downloadProgress->hide();
layout->addWidget(_downloadProgress, 15, 1, 1, 2);
}
{
QBoxLayout* footer = new QHBoxLayout(this);
_errorMsg = new QLabel(this);
QBoxLayout* footer = new QHBoxLayout;
_errorMsg = new QLabel;
_errorMsg->setObjectName("error-message");
_errorMsg->setWordWrap(true);
footer->addWidget(_errorMsg);
QDialogButtonBox* buttons = new QDialogButtonBox(this);
QDialogButtonBox* buttons = new QDialogButtonBox;
buttons->setStandardButtons(QDialogButtonBox::Save | QDialogButtonBox::Cancel);
#ifdef OPENSPACE_MODULE_SPACE_ENABLED
connect(buttons, &QDialogButtonBox::accepted, this, &HorizonsDialog::approved);
#endif // OPENSPACE_MODULE_SPACE_ENABLED
connect(buttons, &QDialogButtonBox::rejected, this, &HorizonsDialog::reject);
footer->addWidget(buttons);
layout->addLayout(footer, 16, 0, 1, 3);
}
}
void HorizonsDialog::cleanAllWidgets() {
styleLabel(_typeLabel, false);
styleLabel(_fileLabel, false);
styleLabel(_targetLabel, false);
styleLabel(_centerLabel, false);
styleLabel(_startLabel, false);
styleLabel(_endLabel, false);
styleLabel(_stepLabel, false);
}
void HorizonsDialog::styleLabel(QLabel* label, bool isDirty) {
std::string newStyle = isDirty ? "error" : "normal";
label->setObjectName(QString::fromStdString(newStyle));
label->style()->unpolish(label);
label->style()->polish(label);
}
bool HorizonsDialog::isValidInput() {
// File
if (_fileEdit->text().isEmpty()) {
_errorMsg->setText("File path not selected");
styleLabel(_fileLabel, true);
styleLabel(_fileLabel, IsDirty::Yes);
return false;
}
@@ -426,13 +403,13 @@ bool HorizonsDialog::isValidInput() {
_chooseTargetCombo->currentIndex() == 0) || _chooseTargetCombo->count() == 0))
{
_errorMsg->setText("Target not selected");
styleLabel(_targetLabel, true);
styleLabel(_targetLabel, IsDirty::Yes);
return false;
}
if (_targetEdit->text().toStdString().find_first_of("¤<>§£´¨€") != std::string::npos)
{
_errorMsg->setText("Target includes illegal characters");
styleLabel(_targetLabel, true);
styleLabel(_targetLabel, IsDirty::Yes);
return false;
}
@@ -441,13 +418,13 @@ bool HorizonsDialog::isValidInput() {
_chooseObserverCombo->currentIndex() == 0) || _chooseObserverCombo->count() == 0))
{
_errorMsg->setText("Observer not selected");
styleLabel(_centerLabel, true);
styleLabel(_centerLabel, IsDirty::Yes);
return false;
}
if (_centerEdit->text().toStdString().find_first_of("¤<>§£´¨€") != std::string::npos)
{
_errorMsg->setText("Observer includes illegal characters");
styleLabel(_centerLabel, true);
styleLabel(_centerLabel, IsDirty::Yes);
return false;
}
@@ -455,7 +432,7 @@ bool HorizonsDialog::isValidInput() {
// Empty
if (_stepEdit->text().isEmpty()) {
_errorMsg->setText("Step size not selected");
styleLabel(_stepLabel, true);
styleLabel(_stepLabel, IsDirty::Yes);
return false;
}
// Numerical
@@ -464,29 +441,29 @@ bool HorizonsDialog::isValidInput() {
if (!couldConvert) {
_errorMsg->setText(QString::fromStdString(fmt::format(
"Step size needs to be a number in range 1 to {}",
std::to_string(std::numeric_limits<int32_t>::max())
std::numeric_limits<int32_t>::max()
)));
styleLabel(_stepLabel, true);
styleLabel(_stepLabel, IsDirty::Yes);
return false;
}
// In the case of arcseconds range is different
if (_timeTypeCombo->currentText().toStdString() == TimeVarying) {
if (step < 60 || step > 3600) {
_errorMsg->setText("Angular step size needs to be in range 60 to 3600");
styleLabel(_stepLabel, true);
styleLabel(_stepLabel, IsDirty::Yes);
return false;
}
}
// Range 1 to 2147483647 (max of 32 bit int).
// Horizons read the step size into a 32 bit int, but verifies the input on their
// website as a uint32_t. If step size over 32 bit int is sent, this error
// message is recived: Cannot read numeric value -- re-enter
// website as a uint32_t. If step size over 32 bit int is sent, this error message is
// recived: Cannot read numeric value -- re-enter
if (step < 1 || step > std::numeric_limits<int32_t>::max()) {
_errorMsg->setText(QString::fromStdString(fmt::format(
"Step size is outside valid range 1 to '{}'",
std::to_string(std::numeric_limits<int32_t>::max())
std::numeric_limits<int32_t>::max()
)));
styleLabel(_stepLabel, true);
styleLabel(_stepLabel, IsDirty::Yes);
return false;
}
return true;
@@ -499,20 +476,20 @@ json HorizonsDialog::sendRequest(const std::string& url) {
request.setUrl(QUrl(QString::fromStdString(url)));
QNetworkReply* reply = _manager->get(request);
connect(reply, &QNetworkReply::downloadProgress, this,
&HorizonsDialog::downloadProgress
connect(
reply, &QNetworkReply::downloadProgress,
this, &HorizonsDialog::downloadProgress
);
_downloadProgress->reset();
_downloadProgress->show();
QEventLoop loop;
QMetaObject::Connection status =
QObject::connect(reply, &QNetworkReply::finished, &loop, &QEventLoop::quit);
QMetaObject::Connection status = connect(
reply, &QNetworkReply::finished,
&loop, &QEventLoop::quit
);
if (!status) {
appendLog(
"Could not connect to Horizons API",
HorizonsDialog::LogLevel::Error
);
appendLog("Could not connect to Horizons API", HorizonsDialog::LogLevel::Error);
return json();
}
@@ -570,21 +547,22 @@ bool HorizonsDialog::checkHttpStatus(const QVariant& statusCode) {
statusCode.toInt() != static_cast<int>(HorizonsDialog::HTTPCodes::Ok))
{
std::string message;
int code = statusCode.toInt();
HorizonsDialog::HTTPCodes code =
static_cast<HorizonsDialog::HTTPCodes>(statusCode.toInt());
switch (code) {
case static_cast<int>(HorizonsDialog::HTTPCodes::BadRequest):
case HorizonsDialog::HTTPCodes::BadRequest:
message = "The request contained invalid keywords and/or used "
"a method other than GET or POST";
break;
case static_cast<int>(HorizonsDialog::HTTPCodes::MethodNotAllowed):
case HorizonsDialog::HTTPCodes::MethodNotAllowed:
message = "The request used an incorrect method";
break;
case static_cast<int>(HorizonsDialog::HTTPCodes::InternalServerError):
case HorizonsDialog::HTTPCodes::InternalServerError:
message = "The database is currently not available, try again at a "
"later time";
break;
case static_cast<int>(HorizonsDialog::HTTPCodes::ServiceUnavailable):
case HorizonsDialog::HTTPCodes::ServiceUnavailable:
message = "The server is currently unable to handle the request due to a "
"temporary overloading or maintenance of the server, try again at a "
"later time";
@@ -714,7 +692,17 @@ bool HorizonsDialog::handleRequest() {
// Reset
_errorMsg->clear();
cleanAllWidgets();
//
// Clean all widgets
styleLabel(_typeLabel, IsDirty::No);
styleLabel(_fileLabel, IsDirty::No);
styleLabel(_targetLabel, IsDirty::No);
styleLabel(_centerLabel, IsDirty::No);
styleLabel(_startLabel, IsDirty::No);
styleLabel(_endLabel, IsDirty::No);
styleLabel(_stepLabel, IsDirty::No);
_importTimeButton->hide();
_validTimeRange = std::pair<std::string, std::string>();
_latestHorizonsError.clear();
@@ -732,14 +720,13 @@ bool HorizonsDialog::handleRequest() {
return false;
}
openspace::HorizonsFile file = handleAnswer(answer);
HorizonsFile file = handleAnswer(answer);
if (!file.hasFile()) {
return false;
}
_horizonsFile = std::move(file);
openspace::HorizonsResultCode result =
openspace::isValidHorizonsFile(_horizonsFile.file());
HorizonsResultCode result = isValidHorizonsFile(_horizonsFile.file());
bool isValid = handleResult(result);
@@ -764,23 +751,23 @@ bool HorizonsDialog::handleRequest() {
std::string HorizonsDialog::constructUrl() {
// Construct url for request
openspace::HorizonsType type;
HorizonsType type;
if (_typeCombo->currentIndex() == 0) {
type = openspace::HorizonsType::Vector;
type = HorizonsType::Vector;
}
else if (_typeCombo->currentIndex() == 1) {
type = openspace::HorizonsType::Observer;
type = HorizonsType::Observer;
}
else {
_errorMsg->setText("Invalid Horizons type");
styleLabel(_typeLabel, true);
styleLabel(_typeLabel, IsDirty::Yes);
return "";
}
std::string command;
if (_chooseTargetCombo->count() > 0 && _chooseTargetCombo->currentIndex() != 0) {
QVariant target = _chooseTargetCombo->itemData(_chooseTargetCombo->currentIndex());
command = target.toString().toStdString();
QVariant t = _chooseTargetCombo->itemData(_chooseTargetCombo->currentIndex());
command = t.toString().toStdString();
_targetName = _chooseTargetCombo->currentText().toStdString();
_targetEdit->setText(QString::fromStdString(command));
}
@@ -839,11 +826,11 @@ std::string HorizonsDialog::constructUrl() {
}
else {
_errorMsg->setText("Invalid time unit type");
styleLabel(_stepLabel, true);
styleLabel(_stepLabel, IsDirty::Yes);
return "";
}
return openspace::constructHorizonsUrl(
return constructHorizonsUrl(
type,
command,
center,
@@ -860,11 +847,10 @@ openspace::HorizonsFile HorizonsDialog::handleAnswer(json& answer) {
_latestHorizonsError = *it;
}
openspace::HorizonsResultCode isValid =
openspace::isValidHorizonsAnswer(answer);
if (isValid != openspace::HorizonsResultCode::Valid &&
isValid != openspace::HorizonsResultCode::MultipleObserverStations &&
isValid != openspace::HorizonsResultCode::ErrorTimeRange)
HorizonsResultCode isValid = isValidHorizonsAnswer(answer);
if (isValid != HorizonsResultCode::Valid &&
isValid != HorizonsResultCode::MultipleObserverStations &&
isValid != HorizonsResultCode::ErrorTimeRange)
{
// Special case with MultipleObserverStations since it is detected as an error
// but could be fixed by parsing the matches and let user choose
@@ -901,11 +887,11 @@ openspace::HorizonsFile HorizonsDialog::handleAnswer(json& answer) {
case QMessageBox::No:
case QMessageBox::Cancel:
_errorMsg->setText("File already exist, try another file path");
styleLabel(_fileLabel, true);
styleLabel(_fileLabel, IsDirty::Yes);
return openspace::HorizonsFile();
default:
_errorMsg->setText("Invalid answer");
styleLabel(_fileLabel, true);
styleLabel(_fileLabel, IsDirty::Yes);
return openspace::HorizonsFile();
}
}
@@ -916,7 +902,7 @@ openspace::HorizonsFile HorizonsDialog::handleAnswer(json& answer) {
bool HorizonsDialog::handleResult(openspace::HorizonsResultCode& result) {
switch (result) {
case openspace::HorizonsResultCode::Valid: {
case HorizonsResultCode::Valid: {
// If the request worked then delete the corresponding error file if it exist
std::filesystem::path validFile(_horizonsFile.file());
@@ -930,7 +916,7 @@ bool HorizonsDialog::handleResult(openspace::HorizonsResultCode& result) {
}
break;
}
case openspace::HorizonsResultCode::Empty: {
case HorizonsResultCode::Empty: {
_errorMsg->setText("The horizons file is empty");
if (!_latestHorizonsError.empty()) {
std::string msg = fmt::format(
@@ -942,7 +928,7 @@ bool HorizonsDialog::handleResult(openspace::HorizonsResultCode& result) {
std::filesystem::remove(_horizonsFile.file());
break;
}
case openspace::HorizonsResultCode::ErrorSize: {
case HorizonsResultCode::ErrorSize: {
std::string msg = fmt::format(
"Time range '{}' to '{}' with step size '{} {}' is too big, try to "
"increase the step size and/or decrease the time range",
@@ -950,29 +936,29 @@ bool HorizonsDialog::handleResult(openspace::HorizonsResultCode& result) {
_timeTypeCombo->currentText().toStdString()
);
appendLog(msg, HorizonsDialog::LogLevel::Error);
styleLabel(_startLabel, true);
styleLabel(_endLabel, true);
styleLabel(_stepLabel, true);
styleLabel(_startLabel, IsDirty::Yes);
styleLabel(_endLabel, IsDirty::Yes);
styleLabel(_stepLabel, IsDirty::Yes);
std::filesystem::remove(_horizonsFile.file());
break;
}
case openspace::HorizonsResultCode::ErrorSpan:
case HorizonsResultCode::ErrorSpan:
appendLog(
"Step size is too big, exceeds available time span for target",
HorizonsDialog::LogLevel::Error
);
styleLabel(_stepLabel, true);
styleLabel(_stepLabel, IsDirty::Yes);
std::filesystem::remove(_horizonsFile.file());
break;
case openspace::HorizonsResultCode::ErrorTimeRange: {
case HorizonsResultCode::ErrorTimeRange: {
std::string msg = fmt::format(
"Time range is outside the valid range for target '{}'", _targetName
);
appendLog(msg, HorizonsDialog::LogLevel::Error);
styleLabel(_startLabel, true);
styleLabel(_endLabel, true);
styleLabel(_startLabel, IsDirty::Yes);
styleLabel(_endLabel, IsDirty::Yes);
_validTimeRange = readTimeRange();
if (_validTimeRange.first.empty() || _validTimeRange.second.empty()) {
@@ -993,7 +979,7 @@ bool HorizonsDialog::handleResult(openspace::HorizonsResultCode& result) {
std::filesystem::remove(_horizonsFile.file());
break;
}
case openspace::HorizonsResultCode::ErrorNoObserver: {
case HorizonsResultCode::ErrorNoObserver: {
std::string msg = fmt::format(
"No match was found for observer '{}'", _observerName
);
@@ -1004,24 +990,24 @@ bool HorizonsDialog::handleResult(openspace::HorizonsResultCode& result) {
_observerName
);
appendLog(msg, HorizonsDialog::LogLevel::Info);
styleLabel(_centerLabel, true);
styleLabel(_centerLabel, IsDirty::Yes);
std::filesystem::remove(_horizonsFile.file());
break;
}
case openspace::HorizonsResultCode::ErrorObserverTargetSame: {
case HorizonsResultCode::ErrorObserverTargetSame: {
std::string msg = fmt::format(
"The observer '{}' and target '{}' are the same. Please use another "
"observer for the current target.", _observerName, _targetName
);
appendLog(msg, HorizonsDialog::LogLevel::Error);
styleLabel(_targetLabel, true);
styleLabel(_centerLabel, true);
styleLabel(_targetLabel, IsDirty::Yes);
styleLabel(_centerLabel, IsDirty::Yes);
std::filesystem::remove(_horizonsFile.file());
break;
}
case openspace::HorizonsResultCode::ErrorNoData: {
case HorizonsResultCode::ErrorNoData: {
std::string msg = fmt::format(
"There is not enough data to compute the state of target '{}' in "
"relation to the observer '{}' for the time range '{}' to '{}'. Try to "
@@ -1033,7 +1019,7 @@ bool HorizonsDialog::handleResult(openspace::HorizonsResultCode& result) {
std::filesystem::remove(_horizonsFile.file());
break;
}
case openspace::HorizonsResultCode::MultipleObserverStations: {
case HorizonsResultCode::MultipleObserverStations: {
std::string msg = fmt::format(
"Multiple matching observer stations were found for observer '{}'. ",
_observerName
@@ -1045,7 +1031,7 @@ bool HorizonsDialog::handleResult(openspace::HorizonsResultCode& result) {
"for alternatives.", _observerName
);
appendLog(msg, HorizonsDialog::LogLevel::Info);
styleLabel(_centerLabel, true);
styleLabel(_centerLabel, IsDirty::Yes);
std::vector<std::string> matchingstations =
_horizonsFile.parseMatches(
@@ -1076,12 +1062,12 @@ bool HorizonsDialog::handleResult(openspace::HorizonsResultCode& result) {
std::filesystem::remove(_horizonsFile.file());
break;
}
case openspace::HorizonsResultCode::MultipleObserver: {
case HorizonsResultCode::MultipleObserver: {
std::string msg = fmt::format(
"Multiple matches were found for observer '{}'", _observerName
);
appendLog(msg, HorizonsDialog::LogLevel::Warning);
styleLabel(_centerLabel, true);
styleLabel(_centerLabel, IsDirty::Yes);
std::vector<std::string> matchingObservers =
_horizonsFile.parseMatches("Name", "matches", ">MATCH NAME<");
@@ -1111,7 +1097,7 @@ bool HorizonsDialog::handleResult(openspace::HorizonsResultCode& result) {
std::filesystem::remove(_horizonsFile.file());
break;
}
case openspace::HorizonsResultCode::ErrorNoTarget: {
case HorizonsResultCode::ErrorNoTarget: {
std::string msg = fmt::format(
"No match was found for target '{}'", _targetName
);
@@ -1122,12 +1108,12 @@ bool HorizonsDialog::handleResult(openspace::HorizonsResultCode& result) {
_targetName
);
appendLog(msg, HorizonsDialog::LogLevel::Info);
styleLabel(_targetLabel, true);
styleLabel(_targetLabel, IsDirty::Yes);
std::filesystem::remove(_horizonsFile.file());
break;
}
case openspace::HorizonsResultCode::MultipleTarget: {
case HorizonsResultCode::MultipleTarget: {
// Case Small Bodies:
// Line before data: Matching small-bodies
// Format: Record #, Epoch-yr, >MATCH DESIG<, Primary Desig, Name
@@ -1143,7 +1129,7 @@ bool HorizonsDialog::handleResult(openspace::HorizonsResultCode& result) {
"Multiple matches were found for target '{}'", _targetName
);
appendLog(msg, HorizonsDialog::LogLevel::Warning);
styleLabel(_targetLabel, true);
styleLabel(_targetLabel, IsDirty::Yes);
std::vector<std::string> matchingTargets =
_horizonsFile.parseMatches("Name", "matches", ">MATCH NAME<");
@@ -1171,7 +1157,7 @@ bool HorizonsDialog::handleResult(openspace::HorizonsResultCode& result) {
std::filesystem::remove(_horizonsFile.file());
break;
}
case openspace::HorizonsResultCode::UnknownError: {
case HorizonsResultCode::UnknownError: {
appendLog("Unknown error", LogLevel::Error);
if (!_latestHorizonsError.empty()) {
std::string msg = fmt::format(
@@ -1193,6 +1179,6 @@ bool HorizonsDialog::handleResult(openspace::HorizonsResultCode& result) {
break;
}
}
return result == openspace::HorizonsResultCode::Valid;
return result == HorizonsResultCode::Valid;
}
#endif // OPENSPACE_MODULE_SPACE_ENABLED
@@ -49,7 +49,9 @@ void MarkNodesDialog::createWidgets() {
_list = new QListWidget;
connect(
_list, &QListWidget::itemSelectionChanged,
this, &MarkNodesDialog::listItemSelected
[this]() {
_removeButton->setEnabled(true);
}
);
_list->setAlternatingRowColors(true);
_list->setMovement(QListView::Free);
@@ -77,10 +79,7 @@ void MarkNodesDialog::createWidgets() {
box->addWidget(_newNode);
QPushButton* addButton = new QPushButton("Add new");
connect(
addButton, &QPushButton::clicked,
this, &MarkNodesDialog::listItemAdded
);
connect(addButton, &QPushButton::clicked, this, &MarkNodesDialog::listItemAdded);
box->addWidget(addButton);
layout->addLayout(box);
}
@@ -88,22 +87,15 @@ void MarkNodesDialog::createWidgets() {
{
QDialogButtonBox* buttons = new QDialogButtonBox;
buttons->setStandardButtons(QDialogButtonBox::Save | QDialogButtonBox::Cancel);
QObject::connect(
connect(
buttons, &QDialogButtonBox::accepted,
this, &MarkNodesDialog::parseSelections
);
QObject::connect(
buttons, &QDialogButtonBox::rejected,
this, &MarkNodesDialog::reject
);
connect(buttons, &QDialogButtonBox::rejected, this, &MarkNodesDialog::reject);
layout->addWidget(buttons);
}
}
void MarkNodesDialog::listItemSelected() {
_removeButton->setEnabled(true);
}
void MarkNodesDialog::listItemAdded() {
if (_newNode->text().isEmpty()) {
return;
@@ -151,12 +143,11 @@ void MarkNodesDialog::parseSelections() {
}
void MarkNodesDialog::keyPressEvent(QKeyEvent* evt) {
if (evt->key() == Qt::Key_Enter || evt->key() == Qt::Key_Return) {
if (_newNode->text().length() > 0 && _newNode->hasFocus()) {
listItemAdded();
return;
}
}
if ((evt->key() == Qt::Key_Enter || evt->key() == Qt::Key_Return) &&
(!_newNode->text().isEmpty() && _newNode->hasFocus()))
{
listItemAdded();
return;
}
QDialog::keyPressEvent(evt);
}
@@ -54,21 +54,21 @@ ModulesDialog::ModulesDialog(QWidget* parent,
void ModulesDialog::createWidgets() {
QBoxLayout* layout = new QVBoxLayout(this);
{
_list = new QListWidget;
connect(
_list, &QListWidget::itemSelectionChanged,
this, &ModulesDialog::listItemSelected
);
_list->setAlternatingRowColors(true);
_list->setMovement(QListView::Free);
_list->setResizeMode(QListView::Adjust);
for (const Profile::Module& m : _moduleData) {
_list->addItem(new QListWidgetItem(createOneLineSummary(m)));
}
layout->addWidget(_list);
_list = new QListWidget;
connect(
_list, &QListWidget::itemSelectionChanged,
this, &ModulesDialog::listItemSelected
);
_list->setAlternatingRowColors(true);
_list->setMovement(QListView::Free);
_list->setResizeMode(QListView::Adjust);
for (const Profile::Module& m : _moduleData) {
_list->addItem(new QListWidgetItem(createOneLineSummary(m)));
}
layout->addWidget(_list);
{
QBoxLayout* box = new QHBoxLayout;
_buttonAdd = new QPushButton("Add new");
@@ -89,12 +89,14 @@ void ModulesDialog::createWidgets() {
{
_moduleLabel = new QLabel("Module");
layout->addWidget(_moduleLabel);
_moduleEdit = new QLineEdit;
_moduleEdit->setToolTip("Name of OpenSpace module related to this profile");
layout->addWidget(_moduleEdit);
_loadedLabel = new QLabel("Command if Module is Loaded");
layout->addWidget(_loadedLabel);
_loadedEdit = new QLineEdit;
_loadedEdit->setToolTip(
"Lua command(s) to execute if OpenSpace has been compiled with the module"
@@ -103,6 +105,7 @@ void ModulesDialog::createWidgets() {
_notLoadedLabel = new QLabel("Command if Module is NOT Loaded");
layout->addWidget(_notLoadedLabel);
_notLoadedEdit = new QLineEdit;
_notLoadedEdit->setToolTip(
"Lua command(s) to execute if the module is not present in the OpenSpace "
@@ -155,8 +158,8 @@ void ModulesDialog::createWidgets() {
QString ModulesDialog::createOneLineSummary(Profile::Module m) {
QString summary = QString::fromStdString(m.name);
bool hasCommandForLoaded = (m.loadedInstruction->length() > 0);
bool hasCommandForNotLoaded = (m.notLoadedInstruction->length() > 0);
bool hasCommandForLoaded = !m.loadedInstruction->empty();
bool hasCommandForNotLoaded = !m.notLoadedInstruction->empty();
if (hasCommandForLoaded && hasCommandForNotLoaded) {
summary += " (commands set for both loaded & not-loaded conditions)";
@@ -186,6 +189,7 @@ void ModulesDialog::listItemSelected() {
else {
_loadedEdit->clear();
}
if (m.notLoadedInstruction.has_value()) {
_notLoadedEdit->setText(QString::fromStdString(*m.notLoadedInstruction));
}
@@ -197,14 +201,9 @@ void ModulesDialog::listItemSelected() {
}
bool ModulesDialog::isLineEmpty(int index) const {
bool isEmpty = true;
if (!_list->item(index)->text().isEmpty()) {
isEmpty = false;
}
if (!_moduleData.empty() && !_moduleData.at(0).name.empty()) {
isEmpty = false;
}
return isEmpty;
return
_list->item(index)->text().isEmpty() &&
_moduleData.empty() && !_moduleData.at(0).name.empty();
}
void ModulesDialog::listItemAdded() {
@@ -258,7 +257,7 @@ void ModulesDialog::listItemSave() {
QListWidgetItem* item = _list->currentItem();
int index = _list->row(item);
if (_moduleData.size() > 0) {
if (!_moduleData.empty()) {
_moduleData[index].name = _moduleEdit->text().toStdString();
_moduleData[index].loadedInstruction = _loadedEdit->text().toStdString();
_moduleData[index].notLoadedInstruction = _notLoadedEdit->text().toStdString();
@@ -277,21 +276,21 @@ void ModulesDialog::listItemCancelSave() {
}
void ModulesDialog::listItemRemove() {
if (_list->count() > 0) {
if (_list->currentRow() >= 0 && _list->currentRow() < _list->count()) {
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)
_moduleData.at(0) = Blank;
_list->item(0)->setText("");
}
else {
int index = _list->currentRow();
if (index >= 0 && index < _list->count()) {
delete _list->takeItem(index);
if (!_moduleData.empty()) {
_moduleData.erase(_moduleData.begin() + index);
}
if (_list->count() > 0 &&
_list->currentRow() >= 0 && _list->currentRow() < _list->count())
{
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)
_moduleData.at(0) = Blank;
_list->item(0)->setText("");
}
else {
int index = _list->currentRow();
if (index >= 0 && index < _list->count()) {
delete _list->takeItem(index);
if (!_moduleData.empty()) {
_moduleData.erase(_moduleData.begin() + index);
}
}
}
@@ -361,4 +360,3 @@ void ModulesDialog::keyPressEvent(QKeyEvent* evt) {
}
QDialog::keyPressEvent(evt);
}
@@ -183,7 +183,7 @@ void PropertiesDialog::listItemSelected() {
QListWidgetItem* item = _list->currentItem();
int index = _list->row(item);
if (_propertyData.size() > 0) {
if (!_propertyData.empty()) {
Profile::Property& p = _propertyData[index];
if (p.setType == Profile::Property::SetType::SetPropertyValueSingle) {
_commandCombo->setCurrentIndex(0);
@@ -211,21 +211,21 @@ bool PropertiesDialog::isLineEmpty(int index) {
void PropertiesDialog::listItemAdded() {
int currentListSize = _list->count();
if ((currentListSize == 1) && (isLineEmpty(0))) {
// 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.
_propertyData.at(0) = Blank;
_list->item(0)->setText(" (Enter details below & click 'Save')");
_list->setCurrentRow(0);
transitionToEditMode();
}
else {
_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);
}
if ((currentListSize == 1) && (isLineEmpty(0))) {
// 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.
_propertyData.at(0) = Blank;
_list->item(0)->setText(" (Enter details below & click 'Save')");
_list->setCurrentRow(0);
transitionToEditMode();
}
else {
_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);
}
// Blank-out the 2 text fields, set combo box to index 0
_commandCombo->setCurrentIndex(0);
@@ -243,7 +243,7 @@ void PropertiesDialog::listItemSave() {
QListWidgetItem* item = _list->currentItem();
int index = _list->row(item);
if (_propertyData.size() > 0) {
if (!_propertyData.empty()) {
if (_commandCombo->currentIndex() == 0) {
_propertyData[index].setType =
Profile::Property::SetType::SetPropertyValueSingle;
@@ -262,12 +262,12 @@ void PropertiesDialog::listItemSave() {
bool PropertiesDialog::areRequiredFormsFilled() {
bool requiredFormsFilled = true;
QString errors;
if (_propertyEdit->text().length() == 0) {
if (_propertyEdit->text().isEmpty()) {
errors += "Missing property name";
requiredFormsFilled = false;
}
if (_valueEdit->text().length() == 0) {
if (errors.length() > 0) {
if (_valueEdit->text().isEmpty()) {
if (!errors.isEmpty()) {
errors += ", ";
}
errors += "Missing value";
@@ -280,34 +280,30 @@ bool PropertiesDialog::areRequiredFormsFilled() {
void PropertiesDialog::listItemCancelSave() {
listItemSelected();
transitionFromEditMode();
if (_editModeNewItem) {
if (_propertyData.size() > 0) {
if (_propertyData.back().name.length() == 0 ||
_propertyData.back().value.length() == 0)
{
listItemRemove();
}
}
if (_editModeNewItem && !_propertyData.empty() &&
(_propertyData.back().name.empty() || _propertyData.back().value.empty()))
{
listItemRemove();
}
_editModeNewItem = false;
}
void PropertiesDialog::listItemRemove() {
if (_list->count() > 0) {
if (_list->currentRow() >= 0 && _list->currentRow() < _list->count()) {
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)
_propertyData.at(0) = Blank;
_list->item(0)->setText("");
}
else {
int index = _list->currentRow();
if (index >= 0 && index < _list->count()) {
delete _list->takeItem(index);
if (_propertyData.size() > 0) {
_propertyData.erase(_propertyData.begin() + index);
}
if (_list->count() > 0 &&
(_list->currentRow() >= 0 && _list->currentRow() < _list->count()))
{
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)
_propertyData.at(0) = Blank;
_list->item(0)->setText("");
}
else {
int index = _list->currentRow();
if (index >= 0 && index < _list->count()) {
delete _list->takeItem(index);
if (_propertyData.size() > 0) {
_propertyData.erase(_propertyData.begin() + index);
}
}
}
@@ -370,11 +366,9 @@ void PropertiesDialog::keyPressEvent(QKeyEvent* evt) {
}
return;
}
else if (evt->key() == Qt::Key_Escape) {
if (_editModeNewItem) {
listItemCancelSave();
return;
}
else if (evt->key() == Qt::Key_Escape && _editModeNewItem) {
listItemCancelSave();
return;
}
QDialog::keyPressEvent(evt);
}
@@ -405,49 +399,52 @@ void PropertiesDialog::selectLineFromScriptLog() {
QDialog dialog;
connect(&dialog, &QDialog::finished, [this, comboBox](int result) {
if (result == QDialog::Rejected) {
return;
connect(
&dialog, &QDialog::finished,
[this, comboBox](int result) {
if (result == QDialog::Rejected) {
return;
}
QString text = comboBox->currentText();
if (!text.startsWith("openspace.setPropertyValue")) {
return;
}
// We have a string that is of the form:
// openspace.setPropertyValue('prop', value);
if (text.startsWith("openspace.setPropertyValueSingle")) {
_commandCombo->setCurrentIndex(0);
std::string_view prefix = "openspace.setPropertyValueSingle";
text = text.mid(static_cast<int>(prefix.size()) + 1); // +1 for (
}
else {
// command == "openspace.setPropertyValue"
_commandCombo->setCurrentIndex(1);
std::string_view prefix = "openspace.setPropertyValue";
text = text.mid(static_cast<int>(prefix.size()) + 1); // +1 for (
}
// Remove everything past the closing brace
text = text.left(text.indexOf(")"));
QStringList textList = text.split(",");
if (textList.size() < 2) {
return;
}
// Remove the string markers around the property
QString property = textList[0].mid(1, textList[0].size() - 2);
textList.removeFirst();
QString value = textList.join(",");
_propertyEdit->setText(property.trimmed());
_valueEdit->setText(value.trimmed());
}
QString text = comboBox->currentText();
if (!text.startsWith("openspace.setPropertyValue")) {
return;
}
// We have a string that is of the form:
// openspace.setPropertyValue('prop', value);
if (text.startsWith("openspace.setPropertyValueSingle")) {
_commandCombo->setCurrentIndex(0);
std::string_view prefix = "openspace.setPropertyValueSingle";
text = text.mid(static_cast<int>(prefix.size()) + 1); // +1 for (
}
else {
// command == "openspace.setPropertyValue"
_commandCombo->setCurrentIndex(1);
std::string_view prefix = "openspace.setPropertyValue";
text = text.mid(static_cast<int>(prefix.size()) + 1); // +1 for (
}
// Remove everything past the closing brace
text = text.left(text.indexOf(")"));
QStringList textList = text.split(",");
if (textList.size() < 2) {
return;
}
// Remove the string markers around the property
QString property = textList[0].mid(1, textList[0].size() - 2);
textList.removeFirst();
QString value = textList.join(",");
_propertyEdit->setText(property.trimmed());
_valueEdit->setText(value.trimmed());
});
);
QLayout* layout = new QVBoxLayout;
QLabel* label = new QLabel("Select a line from the Script Log to add");
@@ -60,32 +60,23 @@ void ScriptlogDialog::createWidgets() {
// * Save Cancel *
// *-------------------------*------------*
QGridLayout* layout = new QGridLayout;
QGridLayout* layout = new QGridLayout(this);
{
QLabel* heading = new QLabel(QString::fromStdString(
fmt::format(
"Choose commands from \"{}\"",
openspace::global::configuration->scriptLog
)
));
QLabel* heading = new QLabel(QString::fromStdString(fmt::format(
"Choose commands from \"{}\"", openspace::global::configuration->scriptLog
)));
heading->setObjectName("heading");
layout->addWidget(heading, 0, 0, 1, 2);
}
_filter = new QLineEdit;
_filter->setPlaceholderText("Filter the list of scripts");
connect(
_filter, &QLineEdit::textEdited,
this, &ScriptlogDialog::updateScriptList
);
connect(_filter, &QLineEdit::textEdited, this, &ScriptlogDialog::updateScriptList);
layout->addWidget(_filter, 1, 0);
_reloadFile = new QPushButton("Reload");
_reloadFile->setToolTip("Reload the script log file");
connect(
_reloadFile, &QPushButton::clicked,
this, &ScriptlogDialog::loadScriptFile
);
connect(_reloadFile, &QPushButton::clicked, this, &ScriptlogDialog::loadScriptFile);
layout->addWidget(_reloadFile, 1, 1);
_scriptlogList = new QListWidget;
@@ -106,8 +97,6 @@ void ScriptlogDialog::createWidgets() {
);
layout->addWidget(buttons, 3, 0, 1, 2);
}
setLayout(layout);
}
void ScriptlogDialog::loadScriptFile() {
@@ -117,8 +106,7 @@ void ScriptlogDialog::loadScriptFile() {
QTextStream in(&file);
while (!in.atEnd()) {
QString line = in.readLine();
// removing return from a few statments
// these are usually generated by gui panels
// removing return from statements which are usually generated by gui panels
line.remove(QRegularExpression("^return "));
if (!line.isEmpty()) {
_scripts.push_back(line.toStdString());
@@ -49,7 +49,7 @@ TimeDialog::TimeDialog(QWidget* parent, std::optional<openspace::Profile::Time>*
if (_time->has_value()) {
_timeData = **_time;
if (_timeData.type == Profile::Time::Type::Relative) {
if (_timeData.value == "") {
if (_timeData.value.empty()) {
_timeData.value = "0d";
}
_relativeEdit->setSelection(0, _relativeEdit->text().length());
@@ -81,6 +81,7 @@ void TimeDialog::createWidgets() {
{
_absoluteLabel = new QLabel("Absolute UTC:");
layout->addWidget(_absoluteLabel);
_absoluteEdit = new QDateTimeEdit;
_absoluteEdit->setDisplayFormat("yyyy-MM-dd T hh:mm:ss");
_absoluteEdit->setDateTime(QDateTime::currentDateTime());
@@ -89,6 +90,7 @@ void TimeDialog::createWidgets() {
{
_relativeLabel = new QLabel("Relative Time:");
layout->addWidget(_relativeLabel);
_relativeEdit = new QLineEdit;
_relativeEdit->setToolTip(
"String for relative time to actual (e.g. \"-1d\" for back 1 day)"
@@ -24,93 +24,112 @@
#include "sgctedit/displaywindowunion.h"
#include <ghoul/fmt.h>
#include "sgctedit/monitorbox.h"
#include "sgctedit/windowcontrol.h"
#include <QApplication>
#include <QMainWindow>
#include <QScreen>
#include <ghoul/fmt.h>
#include <QColor>
#include <QFrame>
#include <QPushButton>
#include <QVBoxLayout>
#include <array>
#include <string>
DisplayWindowUnion::DisplayWindowUnion(std::shared_ptr<MonitorBox> monitorRenderBox,
std::vector<QRect>& monitorSizeList, unsigned int nMaxWindows,
const std::array<QColor, 4>& winColors)
: _monBox(monitorRenderBox)
, _monitorResolutions(monitorSizeList)
, _nMaxWindows(nMaxWindows)
, _winColors(winColors)
DisplayWindowUnion::DisplayWindowUnion(const std::vector<QRect>& monitorSizeList,
int nMaxWindows,
const std::array<QColor, 4>& windowColors,
QWidget* parent)
: QWidget(parent)
{
_addWindowButton = new QPushButton("Add Window");
_removeWindowButton = new QPushButton("Remove Window");
//Add all window controls (some will be hidden from GUI initially)
for (unsigned int i = 0; i < _nMaxWindows; ++i) {
initializeWindowControl();
}
connect(
_addWindowButton,
&QPushButton::clicked,
this,
&DisplayWindowUnion::addWindow
);
connect(
_removeWindowButton,
&QPushButton::clicked,
this,
&DisplayWindowUnion::removeWindow
);
initializeLayout();
createWidgets(nMaxWindows, monitorSizeList, windowColors);
showWindows();
}
void DisplayWindowUnion::initializeLayout() {
QVBoxLayout* layout = new QVBoxLayout(this);
void DisplayWindowUnion::createWidgets(int nMaxWindows,
std::vector<QRect> monitorResolutions,
std::array<QColor, 4> windowColors)
{
// Add all window controls (some will be hidden from GUI initially)
for (unsigned int i = 0; i < nMaxWindows; ++i) {
const unsigned int monitorNumForThisWindow = (nMaxWindows > 3 && i >= 2) ? 1 : 0;
WindowControl* ctrl = new WindowControl(
monitorNumForThisWindow,
i,
monitorResolutions,
windowColors[i],
this
);
_windowControl.push_back(ctrl);
connect(
ctrl, &WindowControl::windowChanged,
this, &DisplayWindowUnion::windowChanged
);
}
QBoxLayout* layout = new QVBoxLayout(this);
layout->setContentsMargins(0, 0, 0, 0);
layout->setSizeConstraint(QLayout::SizeConstraint::SetMinimumSize);
{
QHBoxLayout* layoutMonButton = new QHBoxLayout;
QBoxLayout* layoutMonButton = new QHBoxLayout;
_removeWindowButton = new QPushButton("Remove Window");
_removeWindowButton->setFocusPolicy(Qt::NoFocus);
_removeWindowButton->setToolTip(
"Remove window from the configuration (at least one window is required)"
);
std::string addTip = fmt::format(
"Add a window to the configuration (up to {} windows allowed)", _nMaxWindows
connect(
_removeWindowButton, &QPushButton::clicked,
this, &DisplayWindowUnion::removeWindow
);
_addWindowButton->setToolTip(QString::fromStdString(addTip));
_addWindowButton->setFocusPolicy(Qt::NoFocus);
_removeWindowButton->setFocusPolicy(Qt::NoFocus);
layoutMonButton->addWidget(_removeWindowButton);
layoutMonButton->addStretch(1);
_addWindowButton = new QPushButton("Add Window");
_addWindowButton->setToolTip(QString::fromStdString(fmt::format(
"Add a window to the configuration (up to {} windows allowed)", nMaxWindows
)));
_addWindowButton->setFocusPolicy(Qt::NoFocus);
connect(
_addWindowButton, &QPushButton::clicked,
this, &DisplayWindowUnion::addWindow
);
layoutMonButton->addWidget(_addWindowButton);
layout->addLayout(layoutMonButton);
}
QHBoxLayout* layoutWindows = new QHBoxLayout;
layout->addStretch();
for (unsigned int i = 0; i < _nMaxWindows; ++i) {
QVBoxLayout* layoutForNextWindow = _windowControl[i]->initializeLayout();
_winCtrlLayouts.push_back(layoutForNextWindow);
QWidget* layoutWrapper = new QWidget();
layoutWrapper->setLayout(layoutForNextWindow);
_layoutWindowWrappers.push_back(layoutWrapper);
layoutWindows->addWidget(layoutWrapper);
if (i < (_nMaxWindows - 1)) {
QFrame* frameForNextWindow = new QFrame();
QFrame* line = new QFrame;
line->setFrameShape(QFrame::HLine);
line->setFrameShadow(QFrame::Sunken);
layout->addWidget(line);
QBoxLayout* layoutWindows = new QHBoxLayout;
layoutWindows->setContentsMargins(0, 0, 0, 0);
layoutWindows->setSpacing(0);
for (int i = 0; i < nMaxWindows; ++i) {
layoutWindows->addWidget(_windowControl[i]);
if (i < (nMaxWindows - 1)) {
QFrame* frameForNextWindow = new QFrame;
frameForNextWindow->setFrameShape(QFrame::VLine);
_frameBorderLines.push_back(frameForNextWindow);
layoutWindows->addWidget(frameForNextWindow);
}
}
_nWindowsDisplayed = 1;
showWindows();
layout->addLayout(layoutWindows);
layout->addStretch();
}
std::vector<std::shared_ptr<WindowControl>> DisplayWindowUnion::windowControls() const {
return _windowControl;
}
unsigned int DisplayWindowUnion::nWindows() const {
return _nWindowsDisplayed;
std::vector<WindowControl*> DisplayWindowUnion::windowControls() const {
std::vector<WindowControl*> res;
res.reserve(_nWindowsDisplayed);
for (unsigned int i = 0; i < _nWindowsDisplayed; ++i) {
res.push_back(_windowControl[i]);
}
return res;
}
void DisplayWindowUnion::addWindow() {
if (_nWindowsDisplayed < _nMaxWindows) {
if (_nWindowsDisplayed < _windowControl.size()) {
_windowControl[_nWindowsDisplayed]->resetToDefaults();
_nWindowsDisplayed++;
showWindows();
@@ -125,55 +144,16 @@ void DisplayWindowUnion::removeWindow() {
}
void DisplayWindowUnion::showWindows() {
for (size_t i = 0; i < _layoutWindowWrappers.size(); ++i) {
_layoutWindowWrappers[i]->setVisible(i < _nWindowsDisplayed);
for (size_t i = 0; i < _windowControl.size(); ++i) {
_windowControl[i]->setVisible(i < _nWindowsDisplayed);
}
for (size_t i = 0; i < _frameBorderLines.size(); ++i) {
_frameBorderLines[i]->setVisible(i < (_nWindowsDisplayed - 1));
}
_removeWindowButton->setEnabled(_nWindowsDisplayed > 1);
_addWindowButton->setEnabled(_nWindowsDisplayed != _nMaxWindows);
for (std::shared_ptr<WindowControl> w : _windowControl) {
_addWindowButton->setEnabled(_nWindowsDisplayed != _windowControl.size());
for (WindowControl* w : _windowControl) {
w->showWindowLabel(_nWindowsDisplayed > 1);
}
_monBox->setNumWindowsDisplayed(_nWindowsDisplayed);
emit nWindowsChanged(_nWindowsDisplayed);
}
void DisplayWindowUnion::initializeWindowControl() {
if (_nWindowsAllocated < _nMaxWindows) {
unsigned int monitorNumForThisWindow = 0;
if (_nMaxWindows > 3 && _nWindowsAllocated >= 2) {
monitorNumForThisWindow = 1;
}
_windowControl.push_back(
std::make_shared<WindowControl>(
monitorNumForThisWindow,
_nWindowsAllocated,
_monitorResolutions,
_winColors[_nWindowsAllocated],
this
)
);
_windowControl.back()->setWindowChangeCallback(
[this](int monIndex, int winIndex, const QRectF& newDims) {
_monBox->windowDimensionsChanged(monIndex, winIndex, newDims);
}
);
_windowControl.back()->setWebGuiChangeCallback(
[this](unsigned int winIndex) {
for (unsigned int w = 0; w < _nMaxWindows; ++w) {
if (w != winIndex) {
_windowControl[w]->uncheckWebGuiOption();
}
}
}
);
_monBox->mapWindowResolutionToWidgetCoordinates(
monitorNumForThisWindow,
_nWindowsAllocated,
_windowControl.back()->dimensions()
);
_nWindowsAllocated++;
}
}
@@ -1,282 +0,0 @@
/*****************************************************************************************
* *
* OpenSpace *
* *
* Copyright (c) 2014-2022 *
* *
* 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 "sgctedit/filesupport.h"
FileSupport::FileSupport(QVBoxLayout* parentLayout,
UserConfigurationElements& cfgElements,
SgctConfigElements& sgctElements,
std::function<void(bool)> finishedCallback)
: _displayWidget(cfgElements.display)
, _orientationWidget(cfgElements.orientation)
, _monitors(cfgElements.monitorList)
, _cluster(sgctElements.cluster)
, _windowList(sgctElements.windowList)
, _finishedCallback(finishedCallback)
, _userConfigPath(cfgElements.configSavePath)
{
QVBoxLayout* layoutFullVertical = new QVBoxLayout;
_saveButton = new QPushButton("Save As");
_saveButton->setToolTip("Save configuration changes (opens file chooser dialog)");
_saveButton->setFocusPolicy(Qt::NoFocus);
connect(_saveButton, &QPushButton::released, this, &FileSupport::save);
_cancelButton = new QPushButton("Cancel");
_cancelButton->setToolTip("Cancel changes");
_cancelButton->setFocusPolicy(Qt::NoFocus);
connect(_cancelButton, &QPushButton::released, this, &FileSupport::cancel);
_applyButton = new QPushButton("Apply Without Saving");
_applyButton->setToolTip("Apply configuration changes without saving to file");
_applyButton->setFocusPolicy(Qt::NoFocus);
connect(_applyButton, &QPushButton::released, this, &FileSupport::apply);
{
QHBoxLayout* layoutButtonBox = new QHBoxLayout;
layoutButtonBox->addStretch(1);
layoutButtonBox->addWidget(_cancelButton);
layoutButtonBox->addWidget(_saveButton);
layoutButtonBox->addWidget(_applyButton);
layoutFullVertical->addLayout(layoutButtonBox);
}
parentLayout->addLayout(layoutFullVertical);
}
void FileSupport::saveCluster() {
if (_orientationWidget) {
sgct::config::Scene initScene;
initScene.orientation = _orientationWidget->orientationValue();
_cluster.nodes.clear();
sgct::config::Node tmpNode;
tmpNode.address = "localhost";
tmpNode.port = 20401;
_cluster.nodes.push_back(tmpNode);
_cluster.masterAddress = "localhost";
_cluster.scene = std::move(initScene);
_cluster.firmSync = _orientationWidget->vsyncValue();
}
}
void FileSupport::saveUser() {
if (_orientationWidget) {
sgct::config::User user;
user.eyeSeparation = 0.065f;
user.position = {0.0f, 0.0f, 4.0f};
_cluster.users.push_back(user);
}
}
bool FileSupport::isWindowFullscreen(unsigned int monitorIdx, sgct::ivec2 wDims) {
return (_monitors[monitorIdx].width() == wDims.x &&
_monitors[monitorIdx].height() == wDims.y);
}
std::optional<unsigned int> FileSupport::findGuiWindow() {
unsigned int windowIndex = 0;
for (unsigned int w = 0; w < _displayWidget->nWindows(); ++w) {
if (_displayWidget->windowControls()[w]->isGuiWindow()) {
return std::optional<unsigned int>(windowIndex);
}
windowIndex++;
}
return std::nullopt;
}
void FileSupport::saveWindows() {
unsigned int windowIndex = 0;
for (unsigned int w = 0; w < _displayWidget->nWindows(); ++w) {
std::shared_ptr<WindowControl> wCtrl = _displayWidget->windowControls()[w];
sgct::config::Window tmpWindow = saveWindowsDimensions(wCtrl);
tmpWindow.viewports.push_back(generateViewport());
tmpWindow.viewports.back().projection = saveProjectionInformation(wCtrl);
tmpWindow.isDecorated = wCtrl->isDecorated();
tmpWindow.isFullScreen = isWindowFullscreen(
wCtrl->monitorNum(),
wCtrl->windowSize()
);
if (tmpWindow.isFullScreen) {
tmpWindow.monitor = wCtrl->monitorNum();
}
saveWindowsWebGui(windowIndex, tmpWindow);
if (!wCtrl->windowName().empty()) {
tmpWindow.name = wCtrl->windowName();
}
tmpWindow.id = windowIndex++;
_windowList.push_back(tmpWindow);
}
}
sgct::config::Viewport FileSupport::generateViewport() {
sgct::config::Viewport vp;
vp.isTracked = true;
vp.position = {0.f, 0.f};
vp.size = {1.f, 1.f};
return vp;
}
sgct::config::Window FileSupport::saveWindowsDimensions(
std::shared_ptr<WindowControl> wCtrl)
{
sgct::config::Window tmpWindow;
tmpWindow.size = wCtrl->windowSize();
tmpWindow.pos = {
_monitors[wCtrl->monitorNum()].x() + wCtrl->windowPos().x,
_monitors[wCtrl->monitorNum()].y() + wCtrl->windowPos().y,
};
return tmpWindow;
}
void FileSupport::saveWindowsWebGui(unsigned int wIdx, sgct::config::Window& win) {
win.viewports.back().isTracked = true;
std::optional<unsigned int> webGuiWindowIndex = findGuiWindow();
bool isOneOfWindowsSetAsWebGui = webGuiWindowIndex.has_value();
if (isOneOfWindowsSetAsWebGui) {
if (wIdx == webGuiWindowIndex.value()) {
win.viewports.back().isTracked = false;
win.tags.push_back("GUI");
}
win.draw2D = (wIdx == webGuiWindowIndex.value());
win.draw3D = !(win.draw2D.value());
}
}
ProjectionOptions FileSupport::saveProjectionInformation(
std::shared_ptr<WindowControl> winControl)
{
if (winControl->isSpoutSelected()) {
return saveProjectionSpout(winControl);
}
else {
return saveProjectionNoSpout(winControl);
}
}
ProjectionOptions FileSupport::saveProjectionSpout(
std::shared_ptr<WindowControl> winControl)
{
sgct::config::SpoutOutputProjection projection;
switch(winControl->projectionSelectedIndex()) {
case WindowControl::ProjectionIndeces::Fisheye:
projection.mapping
= sgct::config::SpoutOutputProjection::Mapping::Fisheye;
break;
case WindowControl::ProjectionIndeces::Equirectangular:
default:
projection.mapping
= sgct::config::SpoutOutputProjection::Mapping::Equirectangular;
break;
}
projection.quality = winControl->qualitySelectedValue();
projection.mappingSpoutName = "OpenSpace";
return projection;
}
ProjectionOptions FileSupport::saveProjectionNoSpout(
std::shared_ptr<WindowControl> winControl)
{
switch(winControl->projectionSelectedIndex()) {
case WindowControl::ProjectionIndeces::Fisheye:
{
sgct::config::FisheyeProjection projection;
projection.quality = winControl->qualitySelectedValue();
projection.fov = 180.f;
projection.tilt = 0.f;
return projection;
}
case WindowControl::ProjectionIndeces::SphericalMirror:
{
sgct::config::SphericalMirrorProjection projection;
projection.quality = winControl->qualitySelectedValue();
return projection;
}
case WindowControl::ProjectionIndeces::Cylindrical:
{
sgct::config::CylindricalProjection projection;
projection.quality = winControl->qualitySelectedValue();
projection.heightOffset = winControl->heightOffset();
return projection;
}
case WindowControl::ProjectionIndeces::Equirectangular:
{
sgct::config::EquirectangularProjection projection;
projection.quality = winControl->qualitySelectedValue();
return projection;
}
case WindowControl::ProjectionIndeces::Planar:
default:
{
// The negative values for left & down are according to sgct's convention
sgct::config::PlanarProjection projection;
projection.fov.right = winControl->fovH() / 2.0;
projection.fov.left = -projection.fov.right;
projection.fov.up = winControl->fovV() / 2.0;
projection.fov.down = -projection.fov.up;
return projection;
}
}
}
std::string FileSupport::saveFilename() {
return _saveTarget;
}
void FileSupport::save() {
QString fileName = QFileDialog::getSaveFileName(
this,
"Save Window Configuration File",
QString::fromStdString(_userConfigPath),
"Window Configuration (*.json);;(*.json)",
nullptr
#ifdef __linux__
, QFileDialog::DontUseNativeDialog
#endif
);
if (fileName.length() != 0) {
_saveTarget = fileName.toStdString();
saveConfigToSgctFormat();
_finishedCallback(true);
}
}
void FileSupport::cancel() {
_finishedCallback(false);
}
void FileSupport::apply() {
std::string userCfgTempDir = _userConfigPath;
if (userCfgTempDir.back() != '/') {
userCfgTempDir += "/";
}
userCfgTempDir += "temp";
if (!std::filesystem::is_directory(userCfgTempDir)) {
std::filesystem::create_directories(absPath(userCfgTempDir));
}
_saveTarget = userCfgTempDir + "/" + "apply-without-saving.json";
saveConfigToSgctFormat();
_finishedCallback(true);
}
void FileSupport::saveConfigToSgctFormat() {
saveCluster();
saveWindows();
saveUser();
}
@@ -24,232 +24,183 @@
#include "sgctedit/monitorbox.h"
constexpr float MarginFractionOfWidgetSize = 0.05f;
#include <QPainter>
MonitorBox::MonitorBox(QRect widgetDims, std::vector<QRect> monitorResolution,
unsigned int nWindows, const std::array<QColor, 4>& winColors)
: _monitorWidgetSize(widgetDims)
, _monitorResolution(monitorResolution)
namespace {
constexpr float MarginFractionOfWidgetSize = 0.05f;
constexpr int WindowOpacity = 170;
QRectF computeUnion(const std::vector<QRect>& monitorResolutions) {
QRectF res = { 0.f, 0.f, 0.f, 0.f };
for (const QRect& m : monitorResolutions) {
res |= m;
}
return res;
}
} // namespace
MonitorBox::MonitorBox(QRect widgetDims, const std::vector<QRect>& monitorResolutions,
unsigned int nWindows, const std::array<QColor, 4>& windowColors,
QWidget* parent)
: QWidget(parent)
, _nWindows(nWindows)
, _colorsForWindows(winColors)
, _colorsForWindows(windowColors)
{
_nMonitors = static_cast<unsigned int>(monitorResolution.size());
_showLabel = (_nMonitors > 1);
determineMonitorArrangement();
this->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed);
float borderMargin = MarginFractionOfWidgetSize * 2.f;
if (_monitorArrangementAspectRatio > 1.0) {
borderMargin *= _monitorWidgetSize.width();
_monitorWidgetSize.setHeight(_monitorWidgetSize.width()
/ _monitorArrangementAspectRatio + borderMargin);
setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed);
QRectF monitorArrangement = computeUnion(monitorResolutions);
const float aspectRatio = monitorArrangement.width() / monitorArrangement.height();
if (aspectRatio > 1.0) {
float borderMargin = 2.f * MarginFractionOfWidgetSize * widgetDims.width();
widgetDims.setHeight(widgetDims.width() / aspectRatio + borderMargin);
}
else {
borderMargin *= _monitorWidgetSize.height();
_monitorWidgetSize.setWidth(_monitorWidgetSize.height()
* _monitorArrangementAspectRatio + borderMargin);
float borderMargin = 2.f * MarginFractionOfWidgetSize * widgetDims.height();
widgetDims.setWidth(widgetDims.height() * aspectRatio + borderMargin);
}
setFixedSize(widgetDims.width(), widgetDims.height());
//
// Map monitor resolution to widget coordinates
std::vector<QSizeF> offsets =
aspectRatio >= 1.f ?
computeScaledResolutionLandscape(monitorArrangement, monitorResolutions) :
computeScaledResolutionPortrait(monitorArrangement, monitorResolutions);
for (size_t i = 0; i < monitorResolutions.size(); ++i) {
_monitorDimensionsScaled.emplace_back(
offsets[i].width(),
offsets[i].height(),
monitorResolutions[i].width() * _monitorScaleFactor,
monitorResolutions[i].height() * _monitorScaleFactor
);
}
this->setFixedSize(_monitorWidgetSize.width(), _monitorWidgetSize.height());
mapMonitorResolutionToWidgetCoordinates();
}
void MonitorBox::paintEvent(QPaintEvent* event) {
Q_UNUSED(event)
void MonitorBox::paintEvent(QPaintEvent*) {
QPainter painter(this);
QPen pen = painter.pen();
painter.setPen(pen);
paintWidgetBorder(painter, width(), height());
//Draw window out-of-bounds region(s) first
for (unsigned int i = 0; i < _nWindows; ++i) {
paintWindowBeyondBounds(painter, i);
}
//Draw & fill monitors over the out-of-bounds regions
paintMonitorBackgrounds(painter);
//Draw window number(s) first for darker contrast, then window(s) over both
//out-of-bounds and monitors
for (unsigned int i = 0; i < _nWindows; ++i) {
paintWindowNumber(painter, i);
}
for (unsigned int i = 0; i < _nWindows; ++i) {
paintWindow(painter, i);
}
}
void MonitorBox::paintWidgetBorder(QPainter& painter, int width, int height) {
//
// Draw widget border
constexpr int Radius = 10;
painter.setPen(QPen(Qt::gray, 4));
painter.drawRoundedRect(0, 0, width - 1, height - 1, Radius, Radius);
}
painter.drawRoundedRect(0, 0, width() - 1, height() - 1, Radius, Radius);
void MonitorBox::paintMonitorBackgrounds(QPainter& painter) {
//
// Draw window out-of-bounds region(s) first
for (int i = 0; i < _nWindows; ++i) {
painter.setBrush(Qt::BDiagPattern);
painter.setPen(QPen(_colorsForWindows[i], 0));
painter.drawRect(_windowRendering[i]);
}
// Draw & fill monitors over the out-of-bounds regions
painter.setPen(QPen(Qt::black, 2));
QFont f("Arial");
f.setPixelSize(24);
painter.setFont(f);
for (unsigned int i = 0; i < _nMonitors; ++i) {
if (i <= _monitorDimensionsScaled.size()) {
painter.drawRect(_monitorDimensionsScaled[i]);
QColor fillColor("#DDDDDD");
QBrush brush(fillColor);
brush.setStyle(Qt::SolidPattern);
painter.fillRect(_monitorDimensionsScaled[i], brush);
if (_showLabel) {
QPointF textPos = QPointF(
_monitorDimensionsScaled[i].left() + 4,
_monitorDimensionsScaled[i].top() + 24
);
if (i == 0) {
painter.drawText(textPos, "Primary");
}
}
painter.setBrush(Qt::NoBrush);
for (size_t i = 0; i < _monitorDimensionsScaled.size(); ++i) {
const QColor Grey = QColor(0xDD, 0xDD, 0xDD);
painter.drawRect(_monitorDimensionsScaled[i]);
painter.fillRect(_monitorDimensionsScaled[i], QBrush(Grey, Qt::SolidPattern));
if (_monitorDimensionsScaled.size() > 1 && i == 0) {
// We only want to render the "Primary" if there are multiple windows
QPointF textPos = QPointF(
_monitorDimensionsScaled[i].left() + 4.0,
_monitorDimensionsScaled[i].top() + 24.0
);
QFont f("Arial");
f.setPixelSize(24);
painter.setFont(f);
painter.drawText(textPos, "Primary");
}
}
}
void MonitorBox::paintWindowBeyondBounds(QPainter& painter, unsigned int winIdx) {
painter.setBrush(Qt::BDiagPattern);
setPenSpecificToWindow(painter, winIdx, false);
if (winIdx <= _windowRendering.size()) {
painter.drawRect(_windowRendering[winIdx]);
// Draw window number(s) first for darker contrast, then window(s) over both
// out-of-bounds and monitors
for (int i = 0; i < _nWindows; ++i) {
QPointF p = QPointF(
_windowRendering[i].left() + 5.0,
_windowRendering[i].bottom() - 5.0
);
p.setX(std::clamp(p.x(), 0.0, static_cast<double>(size().width()) - 10.0));
p.setY(std::clamp(p.y(), 20.0, static_cast<double>(size().height())));
painter.drawText(p, QString::number(i + 1));
}
setPenSpecificToWindow(painter, winIdx, true);
painter.setBrush(Qt::NoBrush);
}
void MonitorBox::paintWindow(QPainter& painter, size_t winIdx) {
setPenSpecificToWindow(painter, static_cast<unsigned int>(winIdx), true);
if (winIdx <= _windowRendering.size()) {
painter.drawRect(_windowRendering[winIdx]);
QColor fillColor = _colorsForWindows[winIdx];
fillColor.setAlpha(_alphaWindowOpacity);
QBrush brush(fillColor);
brush.setStyle(Qt::SolidPattern);
painter.fillRect(_windowRendering[winIdx], brush);
//
// Paint window
for (int i = 0; i < _nWindows; ++i) {
painter.setPen(QPen(_colorsForWindows[i], 1));
painter.drawRect(_windowRendering[i]);
QColor fillColor = _colorsForWindows[i];
fillColor.setAlpha(WindowOpacity);
painter.fillRect(_windowRendering[i], QBrush(fillColor, Qt::SolidPattern));
}
}
void MonitorBox::paintWindowNumber(QPainter& painter, unsigned int winIdx) {
QPointF textPos = QPointF(_windowRendering[winIdx].left() + 5,
_windowRendering[winIdx].bottom() - 5);
textPos.setX(std::clamp(textPos.x(), 0.0, _monitorWidgetSize.width() - 10));
textPos.setY(std::clamp(textPos.y(), 20.0, _monitorWidgetSize.height()));
painter.drawText(textPos, QString::fromStdString(std::to_string(winIdx + 1)));
}
void MonitorBox::setPenSpecificToWindow(QPainter& painter, unsigned int windowIdx,
bool visibleBorder)
{
int penWidth = (visibleBorder) ? 1 : -1;
painter.setPen(QPen(_colorsForWindows[windowIdx], penWidth));
}
void MonitorBox::windowDimensionsChanged(unsigned int mIdx, unsigned int wIdx,
const QRectF& newDimensions)
{
mapWindowResolutionToWidgetCoordinates(mIdx, wIdx, newDimensions);
}
void MonitorBox::determineMonitorArrangement() {
for (const QRect& m : _monitorResolution) {
if (m.x() < _negativeCorrectionOffsets.x()) {
_negativeCorrectionOffsets.setX(m.x());
}
if (m.y() < _negativeCorrectionOffsets.y()) {
_negativeCorrectionOffsets.setY(m.y());
}
}
for (const QRect& m : _monitorResolution) {
if ((m.x() + m.width() - _negativeCorrectionOffsets.x())
> _monitorArrangementDimensions.width())
{
_monitorArrangementDimensions.setWidth(
m.x() + m.width() - _negativeCorrectionOffsets.x());
}
if ((m.y() + m.height() - _negativeCorrectionOffsets.y())
> _monitorArrangementDimensions.height())
{
_monitorArrangementDimensions.setHeight(
m.y() + m.height() - _negativeCorrectionOffsets.y());
}
}
_monitorArrangementAspectRatio = _monitorArrangementDimensions.width()
/ _monitorArrangementDimensions.height();
}
void MonitorBox::mapMonitorResolutionToWidgetCoordinates() {
if (_monitorArrangementAspectRatio >= 1.0) {
computeScaledResolutionLandscape(
_monitorArrangementAspectRatio,
_monitorArrangementDimensions.width()
);
}
else {
computeScaledResolutionPortrait(
_monitorArrangementAspectRatio,
_monitorArrangementDimensions.height()
);
}
for (size_t m = 0; m < _monitorResolution.size(); ++m) {
_monitorDimensionsScaled.push_back({
_monitorOffsets[m].width(),
_monitorOffsets[m].height(),
_monitorResolution[m].width() * _monitorScaleFactor,
_monitorResolution[m].height() * _monitorScaleFactor,
});
}
_windowRendering[wIdx] = {
_monitorDimensionsScaled[mIdx].x() + newDimensions.left() * _monitorScaleFactor,
_monitorDimensionsScaled[mIdx].y() + newDimensions.top() * _monitorScaleFactor,
newDimensions.width() * _monitorScaleFactor,
newDimensions.height() * _monitorScaleFactor
};
update();
}
void MonitorBox::computeScaledResolutionLandscape(float aspectRatio, float maxWidth) {
_marginWidget = _monitorWidgetSize.width() * MarginFractionOfWidgetSize;
float virtualWidth = _monitorWidgetSize.width()
* (1.0 - MarginFractionOfWidgetSize * 2.0);
_monitorScaleFactor = virtualWidth / maxWidth;
float newHeight = virtualWidth / aspectRatio;
for (size_t m = 0; m < _monitorResolution.size(); ++m) {
_monitorOffsets.push_back({
_marginWidget + (_monitorResolution[m].x() - _negativeCorrectionOffsets.x())
* _monitorScaleFactor,
_marginWidget + (_monitorWidgetSize.height() - newHeight - _marginWidget) / 4.0
+ (_monitorResolution[m].y() - _negativeCorrectionOffsets.y())
* _monitorScaleFactor
});
std::vector<QSizeF> MonitorBox::computeScaledResolutionLandscape(QRectF arrangement,
const std::vector<QRect>& resolutions)
{
std::vector<QSizeF> offsets;
float marginWidget = size().width() * MarginFractionOfWidgetSize;
float virtualWidth = size().width() * (1.f - MarginFractionOfWidgetSize * 2.f);
_monitorScaleFactor = virtualWidth / arrangement.width();
const float aspectRatio = arrangement.width() / arrangement.height();
const float newHeight = virtualWidth / aspectRatio;
for (const QRect& res : resolutions) {
float x = marginWidget + (res.x() - arrangement.x()) * _monitorScaleFactor;
float y = marginWidget + (size().height() - newHeight - marginWidget) / 4.f +
(res.y() - arrangement.y()) * _monitorScaleFactor;
offsets.emplace_back(x, y);
}
return offsets;
}
void MonitorBox::computeScaledResolutionPortrait(float aspectRatio, float maxHeight) {
_marginWidget = _monitorWidgetSize.height() * MarginFractionOfWidgetSize;
float virtualHeight = _monitorWidgetSize.height()
* (1.0 - MarginFractionOfWidgetSize * 2.0);
_monitorScaleFactor = virtualHeight / maxHeight;
float newWidth = virtualHeight * aspectRatio;
for (size_t m = 0; m < _monitorResolution.size(); ++m) {
_monitorOffsets.push_back({
_marginWidget + (_monitorWidgetSize.width() - newWidth - _marginWidget) / 4.0
+ (_monitorResolution[m].x() - _negativeCorrectionOffsets.x())
* _monitorScaleFactor,
_marginWidget + (_monitorResolution[m].y() - _negativeCorrectionOffsets.y())
* _monitorScaleFactor
});
std::vector<QSizeF> MonitorBox::computeScaledResolutionPortrait(QRectF arrangement,
const std::vector<QRect>& resolutions)
{
std::vector<QSizeF> offsets;
float marginWidget = size().height() * MarginFractionOfWidgetSize;
float virtualHeight = size().height() * (1.f - MarginFractionOfWidgetSize * 2.f);
_monitorScaleFactor = virtualHeight / arrangement.height();
const float aspectRatio = arrangement.width() / arrangement.height();
const float newWidth = virtualHeight * aspectRatio;
for (const QRect& res : resolutions) {
float x = marginWidget + (size().width() - newWidth - marginWidget) / 4.f +
(res.x() - arrangement.x()) * _monitorScaleFactor;
float y = marginWidget + (res.y() - arrangement.y()) * _monitorScaleFactor;
offsets.emplace_back(x, y);
}
return offsets;
}
void MonitorBox::setNumWindowsDisplayed(unsigned int nWindows) {
void MonitorBox::nWindowsDisplayedChanged(int nWindows) {
if (_nWindows != nWindows) {
_nWindows = nWindows;
update();
}
}
void MonitorBox::mapWindowResolutionToWidgetCoordinates(unsigned int mIdx,
unsigned int wIdx,
const QRectF& winDimensions)
{
QRectF wF = winDimensions;
_windowRendering[wIdx] = {
_monitorDimensionsScaled[mIdx].x() + wF.left() * _monitorScaleFactor,
_monitorDimensionsScaled[mIdx].y() + wF.top() * _monitorScaleFactor,
wF.width() * _monitorScaleFactor,
wF.height() * _monitorScaleFactor
};
update();
}
@@ -24,96 +24,86 @@
#include "sgctedit/orientationdialog.h"
#include "sgctedit/displaywindowunion.h"
#include <QDialogButtonBox>
#include <QDoubleValidator>
#include <QGridLayout>
#include <QLabel>
#include <QLineEdit>
#include <ghoul/glm.h>
OrientationDialog::OrientationDialog(sgct::quat& orientation, QWidget* parent)
: QDialog(parent)
, _orientationValue(orientation)
{
setWindowTitle("Global Orientation");
QVBoxLayout* layoutWindow = new QVBoxLayout(this);
QGridLayout* layoutWindow = new QGridLayout(this);
_linePitch = new QLineEdit;
_lineRoll = new QLineEdit;
_lineYaw = new QLineEdit;
_linePitch->setText(QString::number(_orientationValue.x));
_lineRoll->setText(QString::number(_orientationValue.z));
_lineYaw->setText(QString::number(_orientationValue.y));
{
QDoubleValidator* validatorPitch = new QDoubleValidator(-90.0, 90.0, 15);
QDoubleValidator* validatorRoll = new QDoubleValidator(-360.0, 360.0, 15);
QDoubleValidator* validatorYaw = new QDoubleValidator(-180.0, 180.0, 15);
validatorPitch->setNotation(QDoubleValidator::StandardNotation);
validatorRoll->setNotation(QDoubleValidator::StandardNotation);
validatorYaw->setNotation(QDoubleValidator::StandardNotation);
_linePitch->setValidator(validatorPitch);
_lineRoll->setValidator(validatorRoll);
_lineYaw->setValidator(validatorYaw);
}
{
QLabel* labelPitch = new QLabel;
labelPitch->setText("Pitch: ");
QHBoxLayout* layoutPitch = new QHBoxLayout;
layoutPitch->addStretch(1);
QString pitchTip = "Pitch or elevation: negative numbers tilt the camera "
"downwards; positive numbers tilt upwards.\nThe allowed range is [-90, 90]. "
"Internally, this corresponds to the x value in the quaternion.";
QLabel* labelPitch = new QLabel("Pitch");
labelPitch->setToolTip(pitchTip);
layoutWindow->addWidget(labelPitch, 0, 0);
_linePitch = new QLineEdit;
_linePitch->setText(QString::number(glm::degrees(_orientationValue.x)));
_linePitch->setToolTip(pitchTip);
layoutPitch->addWidget(labelPitch);
layoutPitch->addWidget(_linePitch);
layoutWindow->addLayout(layoutPitch);
QLabel* labelRoll = new QLabel;
labelRoll ->setText("Roll: ");
QHBoxLayout* layoutRoll = new QHBoxLayout;
layoutRoll->addStretch(1);
QDoubleValidator* validatorPitch = new QDoubleValidator(-90.0, 90.0, 15);
validatorPitch->setNotation(QDoubleValidator::StandardNotation);
_linePitch->setValidator(validatorPitch);
layoutWindow->addWidget(_linePitch, 0, 1);
}
{
QString rollTip = "Roll or bank: negative numbers rotate the camera counter-"
"clockwise; positive numbers clockwise.\nThe allowed range is [-180, 180]. "
"Internally, this corresponds to the z value in the quaternion.";
QLabel* labelRoll = new QLabel("Roll");
labelRoll->setToolTip(rollTip);
layoutWindow->addWidget(labelRoll, 1, 0);
_lineRoll = new QLineEdit;
_lineRoll->setText(QString::number(glm::degrees(_orientationValue.z)));
_lineRoll->setToolTip(rollTip);
layoutRoll->addWidget(labelRoll);
layoutRoll->addWidget(_lineRoll);
layoutWindow->addLayout(layoutRoll);
QLabel* labelYaw = new QLabel;
labelYaw ->setText("Yaw: ");
QHBoxLayout* layoutYaw = new QHBoxLayout;
layoutYaw->addStretch(1);
QDoubleValidator* validatorRoll = new QDoubleValidator(-360.0, 360.0, 15);
validatorRoll->setNotation(QDoubleValidator::StandardNotation);
_lineRoll->setValidator(validatorRoll);
layoutWindow->addWidget(_lineRoll, 1, 1);
}
{
QString yawTip = "Yaw, heading, or azimuth: negative numbers pan the camera "
"to the left; positive numbers pan to the\nright. The allowed range is "
"[-360, 360]. Internally, this corresponds to the y value in the quaternion.";
QLabel* labelYaw = new QLabel;
labelYaw ->setText("Yaw");
labelYaw->setToolTip(yawTip);
layoutWindow->addWidget(labelYaw, 2, 0);
_lineYaw = new QLineEdit;
_lineYaw->setText(QString::number(glm::degrees(_orientationValue.y)));
_lineYaw->setToolTip(yawTip);
layoutYaw->addWidget(labelYaw);
layoutYaw->addWidget(_lineYaw);
layoutWindow->addLayout(layoutYaw);
QDoubleValidator* validatorYaw = new QDoubleValidator(-180.0, 180.0, 15, this);
validatorYaw->setNotation(QDoubleValidator::StandardNotation);
_lineYaw->setValidator(validatorYaw);
layoutWindow->addWidget(_lineYaw, 2, 1);
}
{
QHBoxLayout* layoutButtonBox = new QHBoxLayout;
QPushButton* buttonSave = new QPushButton("OK");
buttonSave->setToolTip("Save global orientation changes");
buttonSave->setFocusPolicy(Qt::NoFocus);
layoutButtonBox->addStretch(1);
layoutButtonBox->addWidget(buttonSave);
QPushButton* buttonCancel = new QPushButton("Cancel");
buttonCancel->setToolTip("Cancel global orientation changes");
buttonCancel->setFocusPolicy(Qt::NoFocus);
layoutButtonBox->addWidget(buttonCancel);
layoutButtonBox->addStretch(1);
connect(buttonSave, &QPushButton::released, this, &OrientationDialog::ok);
connect(buttonCancel, &QPushButton::released, this, &OrientationDialog::cancel);
layoutWindow->addLayout(layoutButtonBox);
QDialogButtonBox* buttons = new QDialogButtonBox(
QDialogButtonBox::Ok | QDialogButtonBox::Cancel
);
connect(buttons, &QDialogButtonBox::accepted, this, &OrientationDialog::ok);
connect(buttons, &QDialogButtonBox::rejected, this, &OrientationDialog::reject);
layoutWindow->addWidget(buttons, 3, 0, 1, 2);
}
}
void OrientationDialog::ok() {
_orientationValue.x = _linePitch->text().toFloat() / 180.0 * glm::pi<float>();
_orientationValue.y = _lineYaw->text().toFloat() / 180.0 * glm::pi<float>();
_orientationValue.z = _lineRoll->text().toFloat() / 180.0 * glm::pi<float>();
_orientationValue.x = glm::radians(_linePitch->text().toFloat());
_orientationValue.y = glm::radians(_lineYaw->text().toFloat());
_orientationValue.z = glm::radians(_lineRoll->text().toFloat());
_orientationValue.w = 1.0;
accept();
}
void OrientationDialog::cancel() {
reject();
}
@@ -22,52 +22,61 @@
* OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. *
****************************************************************************************/
#include "sgctedit/orientation.h"
#include "sgctedit/settingswidget.h"
#include "sgctedit/orientationdialog.h"
#include <QCheckBox>
#include <QPushButton>
#include <QVBoxLayout>
Orientation::Orientation()
: _orientationDialog(_orientationValue, this)
SettingsWidget::SettingsWidget(sgct::quat orientation, QWidget* parent)
: QWidget(parent)
, _orientationValue(std::move(orientation))
{
_layoutOrientationFull = new QHBoxLayout;
{
QVBoxLayout* layoutOrientationControls = new QVBoxLayout;
QPushButton* orientationButton = new QPushButton("Global Orientation");
_checkBoxVsync = new QCheckBox("VSync All Windows", this);
_checkBoxVsync->setToolTip(
"If enabled, the server will frame lock and wait for all client nodes"
);
layoutOrientationControls->addWidget(_checkBoxVsync);
orientationButton->setToolTip(
"Opens a separate dialog for setting the pitch, "
"yaw, and roll of the camera\n(the orientation applies to all viewports)"
);
orientationButton->setFocusPolicy(Qt::NoFocus);
layoutOrientationControls->addWidget(orientationButton);
_layoutOrientationFull->addStretch(1);
_layoutOrientationFull->addLayout(layoutOrientationControls);
_layoutOrientationFull->addStretch(1);
connect(
orientationButton,
&QPushButton::released,
this,
&Orientation::orientationDialog
);
}
QBoxLayout* layout = new QVBoxLayout(this);
layout->setContentsMargins(0, 0, 0, 0);
_showUiOnFirstWindow = new QCheckBox("Show only user interface on the first window");
_showUiOnFirstWindow->setChecked(false);
_showUiOnFirstWindow->setToolTip(
"If enabled the first window is marked as a GUI window resulting in the user "
"interface only being shown on that window and the rendering is suppressed on "
"this first window. The remaining windows will render normally but they will not "
"show the user interface"
);
layout->addWidget(_showUiOnFirstWindow);
_checkBoxVsync = new QCheckBox("Enable VSync");
_checkBoxVsync->setToolTip(
"If enabled the framerate will be locked to the refresh rate of the monitor"
);
layout->addWidget(_checkBoxVsync);
QPushButton* orientationButton = new QPushButton("Global Orientation");
orientationButton->setToolTip(
"Opens a separate dialog for setting the pitch, yaw, and roll of the camera\n"
"(the orientation applies to all viewports)"
);
orientationButton->setFocusPolicy(Qt::NoFocus);
layout->addWidget(orientationButton);
connect(
orientationButton, &QPushButton::released,
[this]() {
OrientationDialog _orientationDialog(_orientationValue, this);
_orientationDialog.exec();
}
);
}
void Orientation::addControlsToParentLayout(QVBoxLayout* parentLayout) {
parentLayout->addLayout(_layoutOrientationFull);
}
void Orientation::orientationDialog() {
_orientationDialog.exec();
}
sgct::quat Orientation::orientationValue() const {
sgct::quat SettingsWidget::orientation() const {
return _orientationValue;
}
bool Orientation::vsyncValue() const {
return (_checkBoxVsync->checkState() == Qt::Checked);
bool SettingsWidget::vsync() const {
return _checkBoxVsync->isChecked();
}
bool SettingsWidget::showUiOnFirstWindow() const {
return _showUiOnFirstWindow->isChecked();
}
@@ -23,117 +23,272 @@
****************************************************************************************/
#include "sgctedit/sgctedit.h"
#include <sgctedit/displaywindowunion.h>
#include <sgctedit/monitorbox.h>
#include <sgctedit/settingswidget.h>
#include <sgctedit/windowcontrol.h>
#include <ghoul/filesystem/filesystem.h>
#include <QApplication>
#include <QFileDialog>
#include <QFrame>
#include <QMessageBox>
#include <QPushButton>
#include <QScreen>
#include <QVBoxLayout>
#include <filesystem>
SgctEdit::SgctEdit(QWidget* parent, std::vector<sgct::config::Window>& windowList,
sgct::config::Cluster& cluster, const QList<QScreen*>& screenList,
const std::string userConfigPath)
: QDialog(parent)
, _cluster(cluster)
, _windowList(windowList)
, _userConfigPath(userConfigPath)
{
systemMonitorConfiguration(screenList);
setWindowTitle("Window Configuration Editor");
createWidgets();
}
namespace {
constexpr QRect MonitorWidgetSize = { 0, 0, 500, 500 };
constexpr int MaxNumberWindows = 4;
void SgctEdit::systemMonitorConfiguration(const QList<QScreen*>& screenList) {
size_t nScreensManaged = std::min(static_cast<int>(screenList.length()), 2);
for (unsigned int s = 0; s < static_cast<unsigned int>(nScreensManaged); ++s) {
int actualWidth = std::max(
screenList[s]->size().width(),
screenList[s]->availableGeometry().width()
);
int actualHeight = std::max(
screenList[s]->size().height(),
screenList[s]->availableGeometry().height()
);
_monitorSizeList.push_back({
screenList[s]->availableGeometry().x(),
screenList[s]->availableGeometry().y(),
static_cast<int>(actualWidth * screenList[s]->devicePixelRatio()),
static_cast<int>(actualHeight * screenList[s]->devicePixelRatio())
});
}
_nMaxWindows = (_monitorSizeList.size() == 1) ? 3 : 4;
}
void SgctEdit::createWidgets() {
QVBoxLayout* layoutMainV = new QVBoxLayout(this);
QHBoxLayout* layoutMainH = new QHBoxLayout;
_orientationWidget = new Orientation();
{
_monBox = std::make_shared<MonitorBox>(
_monitorWidgetSize,
_monitorSizeList,
_nMaxWindows,
_colorsForWindows
);
QHBoxLayout* layoutMonBox = new QHBoxLayout;
layoutMonBox->addStretch(1);
layoutMonBox->addWidget(_monBox.get());
layoutMonBox->addStretch(1);
layoutMainV->addLayout(layoutMonBox);
addDisplayLayout(layoutMainH);
}
{
layoutMainV->addLayout(layoutMainH);
_orientationWidget->addControlsToParentLayout(layoutMainV);
QFrame* bottomBorder = new QFrame();
bottomBorder->setFrameShape(QFrame::HLine);
layoutMainV->addWidget(bottomBorder);
SgctConfigElements sgctCfg = {_windowList, _cluster};
UserConfigurationElements userCfg = {
_monitorSizeList,
_displayWidget,
_orientationWidget,
_userConfigPath
// Returns true if the windows are not ordered correctly. 'Correct' in this means that
// there is a smaller window defined before a bigger one
// This check is only necessary until
// https://github.com/OpenSpace/OpenSpace/issues/507
// is fixed
bool hasWindowIssues(const sgct::config::Cluster& cluster) {
sgct::ivec2 size = {
std::numeric_limits<int>::max(),
std::numeric_limits<int>::max()
};
_fileSupportWidget = new FileSupport(
layoutMainV,
userCfg,
sgctCfg,
[this](bool accepted) {
if (accepted) {
_saveSelected = true;
accept();
}
else {
reject();
}
for (const sgct::config::Window& window : cluster.nodes.front().windows) {
if (window.size.x <= size.x && window.size.y <= size.y) {
size = window.size;
}
else {
// The window size is bigger than a previous one, so we gotta bail
return true;
}
}
// We got to the end without running into any problems, so we are golden
return false;
}
} // namespace
SgctEdit::SgctEdit(QWidget* parent, std::string userConfigPath)
: QDialog(parent)
, _userConfigPath(std::move(userConfigPath))
{
QList<QScreen*> screens = qApp->screens();
setWindowTitle("Window Configuration Editor");
int nScreensManaged = std::min(static_cast<int>(screens.length()), 4);
std::vector<QRect> monitorSizes;
for (int s = 0; s < nScreensManaged; ++s) {
QSize size = screens[s]->size();
QRect geometry = screens[s]->availableGeometry();
int actualWidth = std::max(size.width(), geometry.width());
int actualHeight = std::max(size.height(), geometry.height());
monitorSizes.emplace_back(
geometry.x(),
geometry.y(),
static_cast<int>(actualWidth * screens[s]->devicePixelRatio()),
static_cast<int>(actualHeight * screens[s]->devicePixelRatio())
);
}
createWidgets(monitorSizes);
}
void SgctEdit::createWidgets(const std::vector<QRect>& monitorSizes) {
QBoxLayout* layout = new QVBoxLayout(this);
layout->setSizeConstraint(QLayout::SetFixedSize);
sgct::quat orientation = { 0.f, 0.f, 0.f, 0.f };
if (_cluster.scene.has_value() && _cluster.scene->orientation.has_value()) {
orientation = *_cluster.scene->orientation;
}
{
MonitorBox* monitorBox = new MonitorBox(
MonitorWidgetSize,
monitorSizes,
MaxNumberWindows,
_colorsForWindows,
this
);
layout->addWidget(monitorBox, 0, Qt::AlignCenter);
QFrame* displayFrame = new QFrame;
displayFrame->setFrameStyle(QFrame::StyledPanel | QFrame::Plain);
QBoxLayout* displayLayout = new QVBoxLayout(displayFrame);
_displayWidget = new DisplayWindowUnion(
monitorSizes,
MaxNumberWindows,
_colorsForWindows,
this
);
connect(
_displayWidget, &DisplayWindowUnion::windowChanged,
monitorBox, &MonitorBox::windowDimensionsChanged
);
connect(
_displayWidget, &DisplayWindowUnion::nWindowsChanged,
monitorBox, &MonitorBox::nWindowsDisplayedChanged
);
_displayWidget->addWindow();
displayLayout->addWidget(_displayWidget);
layout->addWidget(displayFrame);
}
_settingsWidget = new SettingsWidget(orientation, this);
layout->addWidget(_settingsWidget);
{
QHBoxLayout* layoutButtonBox = new QHBoxLayout;
layoutButtonBox->addStretch(1);
QFrame* bottomBorder = new QFrame;
bottomBorder->setFrameShape(QFrame::HLine);
layout->addWidget(bottomBorder);
_cancelButton = new QPushButton("Cancel");
_cancelButton->setToolTip("Cancel changes.");
_cancelButton->setFocusPolicy(Qt::NoFocus);
connect(_cancelButton, &QPushButton::released, this, &SgctEdit::reject);
layoutButtonBox->addWidget(_cancelButton);
_saveButton = new QPushButton("Save As");
_saveButton->setToolTip("Save configuration changes.");
_saveButton->setFocusPolicy(Qt::NoFocus);
connect(_saveButton, &QPushButton::released, this, &SgctEdit::save);
layoutButtonBox->addWidget(_saveButton);
_applyButton = new QPushButton("Apply Without Saving");
_applyButton->setToolTip("Apply configuration changes without saving to file.");
_applyButton->setFocusPolicy(Qt::NoFocus);
connect(_applyButton, &QPushButton::released, this, &SgctEdit::apply);
layoutButtonBox->addWidget(_applyButton);
layout->addLayout(layoutButtonBox);
}
}
void SgctEdit::addDisplayLayout(QHBoxLayout* layout) {
_displayLayout = new QVBoxLayout;
_displayWidget = std::make_shared<DisplayWindowUnion>(
_monBox,
_monitorSizeList,
_nMaxWindows,
_colorsForWindows
std::filesystem::path SgctEdit::saveFilename() const {
return _saveTarget;
}
void SgctEdit::save() {
sgct::config::Cluster cluster = generateConfiguration();
if (hasWindowIssues(cluster)) {
int ret = QMessageBox::warning(
this,
"Window Sizes Incompatible",
"Window sizes for multiple windows have to be strictly ordered, meaning that "
"the size of window 1 has to be bigger in each dimension than window 2, "
"window 2 has to be bigger than window 3 (if it exists), and window 3 has to "
"be bigger than window 4.\nOtherwise, rendering errors might occur.\n\nAre "
"you sure you want to continue?",
QMessageBox::StandardButtons(QMessageBox::Yes || QMessageBox::No)
);
if (ret == QMessageBox::No) {
return;
}
}
QString fileName = QFileDialog::getSaveFileName(
this,
"Save Window Configuration File",
QString::fromStdString(_userConfigPath),
"Window Configuration (*.json)",
nullptr
#ifdef __linux__
// Linux in Qt5 and Qt6 crashes when trying to access the native dialog here
, QFileDialog::DontUseNativeDialog
#endif
);
_displayFrame = new QFrame;
_displayLayout->addWidget(_displayWidget.get());
_displayFrame->setLayout(_displayLayout);
_displayFrame->setFrameStyle(QFrame::StyledPanel | QFrame::Plain);
layout->addWidget(_displayFrame);
if (!fileName.isEmpty()) {
_saveTarget = fileName.toStdString();
_cluster = std::move(cluster);
accept();
}
}
bool SgctEdit::wasSaved() const {
return _saveSelected;
void SgctEdit::apply() {
sgct::config::Cluster cluster = generateConfiguration();
if (hasWindowIssues(cluster)) {
int ret = QMessageBox::warning(
this,
"Window Sizes Incompatible",
"Window sizes for multiple windows have to be strictly ordered, meaning that "
"the size of window 1 has to be bigger in each dimension than window 2, "
"window 2 has to be bigger than window 3 (if it exists), and window 3 has to "
"be bigger than window 4.\nOtherwise, rendering errors might occur.\n\nAre "
"you sure you want to continue?",
QMessageBox::Yes | QMessageBox::No
);
if (ret == QMessageBox::No) {
return;
}
}
std::string userCfgTempDir = _userConfigPath;
if (userCfgTempDir.back() != '/') {
userCfgTempDir += '/';
}
userCfgTempDir += "temp";
if (!std::filesystem::is_directory(absPath(userCfgTempDir))) {
std::filesystem::create_directories(absPath(userCfgTempDir));
}
_saveTarget = userCfgTempDir + "/apply-without-saving.json";
_cluster = std::move(cluster);
accept();
}
std::string SgctEdit::saveFilename() {
return _fileSupportWidget->saveFilename();
sgct::config::Cluster SgctEdit::generateConfiguration() const {
sgct::config::Cluster cluster;
sgct::config::Scene scene;
scene.orientation = _settingsWidget->orientation();
cluster.scene = std::move(scene);
cluster.masterAddress = "localhost";
if (_settingsWidget->vsync()) {
sgct::config::Settings::Display display;
display.swapInterval = 1;
sgct::config::Settings settings;
settings.display = display;
cluster.settings = settings;
}
sgct::config::Node node;
node.address = "localhost";
node.port = 20401;
// Save Windows
unsigned int windowIndex = 0;
for (WindowControl* wCtrl : _displayWidget->windowControls()) {
sgct::config::Window window = wCtrl->generateWindowInformation();
window.id = windowIndex++;
node.windows.push_back(std::move(window));
}
if (_settingsWidget->showUiOnFirstWindow()) {
sgct::config::Window& window = node.windows.front();
window.viewports.back().isTracked = false;
window.tags.push_back("GUI");
window.draw2D = true;
window.draw3D = false;
}
cluster.nodes.push_back(node);
sgct::config::User user;
user.eyeSeparation = 0.065f;
user.position = { 0.f, 0.f, 4.f };
cluster.users = { user };
return cluster;
}
SgctEdit::~SgctEdit() {
delete _orientationWidget;
delete _fileSupportWidget;
delete _displayLayout;
sgct::config::Cluster SgctEdit::cluster() const {
return _cluster;
}
File diff suppressed because it is too large Load Diff
+50 -6
View File
@@ -4,6 +4,10 @@
asset.require("./base_blank")
-- Modules and component settings
asset.require("modules/exoplanets/exoplanets")
asset.require("modules/skybrowser/skybrowser")
-- Specifying which other assets should be loaded in this scene
asset.require("scene/solarsystem/sun/sun")
asset.require("scene/solarsystem/sun/glare")
@@ -18,11 +22,6 @@ asset.require("scene/milkyway/milkyway/volume")
asset.require("scene/milkyway/constellations/constellation_art")
asset.require("scene/milkyway/constellations/constellation_keybinds")
asset.require("scene/milkyway/objects/orionnebula/orionnebula")
asset.require("util/launcher_images")
-- For exoplanet system visualizations
asset.require("scene/milkyway/exoplanets/exoplanets_data")
asset.require("scene/milkyway/exoplanets/exoplanets_textures")
asset.require("scene/digitaluniverse/2dF")
asset.require("scene/digitaluniverse/2mass")
@@ -60,11 +59,56 @@ asset.require("scene/digitaluniverse/supernovaremnants")
asset.require("scene/digitaluniverse/tully")
asset.require("scene/digitaluniverse/voids")
asset.require("customization/globebrowsing")
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
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 ()
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.globebrowsing.loadWMSServersFromFile(
openspace.absPath("${DATA}/globebrowsing_servers.lua")
)
end)
asset.onDeinitialize(function ()
openspace.action.removeAction(toggle_trails)
openspace.clearKey(toggle_trails.Key)
openspace.action.removeAction(toggle_planet_labels)
openspace.clearKey(toggle_planet_labels.Key)
end)
+2 -46
View File
@@ -15,55 +15,11 @@ local webGui = asset.require("util/webgui")
-- Scale the different UI components based on the operating system's DPI scaling value
asset.require("util/dpiscaling")
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
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"
}
-- Load the images required for the launcher to show up
asset.require("util/launcher_images")
asset.onInitialize(function ()
webGui.setCefRoute("onscreen")
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 ()
openspace.action.removeAction(toggle_trails)
openspace.clearKey(toggle_trails.Key)
openspace.action.removeAction(toggle_planet_labels)
openspace.clearKey(toggle_planet_labels.Key)
end)
Binary file not shown.

Before

Width:  |  Height:  |  Size: 18 KiB

-29
View File
@@ -1,29 +0,0 @@
-- This asset requires OpenSpace to be built with the OPENSPACE_MODULE_SPOUT enabled
local transforms = asset.require("scene/solarsystem/sun/transforms")
local circle = {
Identifier = "hoverCircle",
Parent = transforms.SolarSystemBarycenter.Identifier,
Renderable = {
Type = "RenderablePlaneImageLocal",
Size = 3.0E15,
Origin = "Center",
Billboard = true,
Texture = "${ASSETS}/circle.png"
},
GUI = {
Path = "/SkyBrowser"
}
}
asset.onInitialize(function()
openspace.addSceneGraphNode(circle)
openspace.skybrowser.setHoverCircle('hoverCircle')
end)
asset.onDeinitialize(function()
openspace.removeSceneGraphNode(circle)
end)
asset.export(circle)
@@ -0,0 +1,16 @@
asset.onInitialize(function ()
openspace.setPropertyValueSingle("Modules.Exoplanets.Enabled", true)
openspace.setPropertyValueSingle("Modules.Exoplanets.ShowComparisonCircle", false)
openspace.setPropertyValueSingle("Modules.Exoplanets.ShowHabitableZone", true)
openspace.setPropertyValueSingle("Modules.Exoplanets.UseOptimisticZone", true)
openspace.setPropertyValueSingle("Modules.Exoplanets.HabitableZoneOpacity", 0.1)
end)
asset.meta = {
Name = "Exoplanet Default Settings",
Version = "1.0",
Description = [[ Some default settings related to the exoplanet module ]],
Author = "OpenSpace Team",
URL = "http://openspaceproject.com",
License = "MIT license"
}
@@ -0,0 +1,3 @@
asset.require("./default_settings")
asset.require("./exoplanets_data")
asset.require("./exoplanets_textures")
@@ -2,7 +2,7 @@ local DataPath = asset.syncedResource({
Name = "Exoplanet Data Files",
Type = "HttpSynchronization",
Identifier = "exoplanets_data",
Version = 2
Version = 3
})
local colormaps = asset.syncedResource({
@@ -13,6 +13,8 @@ local colormaps = asset.syncedResource({
})
asset.onInitialize(function ()
-- Set the default data files used for the exoplanet system creation
-- (Check if already set, to not override value set in another file)
local p = "Modules.Exoplanets.DataFolder";
if (openspace.getPropertyValue(p) == "") then
openspace.setPropertyValueSingle(p, DataPath)
@@ -28,7 +30,7 @@ asset.export("DataPath", DataPath)
asset.meta = {
Name = "Exoplanet Data",
Version = "2.0",
Version = "3.0",
Description = [[ The data that is used for the exoplanet systems. The data has been
derived from the 'Planetary Systems Composite Data' dataset from the NASA Exoplanet
Archive]],
@@ -1,5 +1,6 @@
local habitableZoneTextures =
asset.require("../habitable_zones/habitable_zone_textures").TexturesPath
local habitableZoneTextures = asset.require(
"scene/milkyway/habitable_zones/habitable_zone_textures"
).TexturesPath
local sunTextures = asset.syncedResource({
Type = "HttpSynchronization",
@@ -25,7 +26,7 @@ asset.onInitialize(function ()
local hzTexture = habitableZoneTextures .. "hot_to_cold_faded.png"
-- Set the default textures used for the exoplanet system creation
-- (Check if already set, to not override value in config file)
-- (Check if already set, to not override value set in another file)
local p = "Modules.Exoplanets.StarTexture";
if (openspace.getPropertyValue(p) == "") then
openspace.setPropertyValueSingle(p, starTexture)
@@ -0,0 +1,13 @@
asset.onInitialize(function ()
openspace.setPropertyValueSingle("Modules.SkyBrowser.Enabled", true)
-- More settings are available, but for now using the default values
end)
asset.meta = {
Name = "SkyBrowser Module Default Settings",
Version = "1.0",
Description = [[ Some default settings related to the SkyBrowser module ]],
Author = "OpenSpace Team",
URL = "http://openspaceproject.com",
License = "MIT license"
}
@@ -0,0 +1,50 @@
-- This asset requires OpenSpace to be built with the OPENSPACE_MODULE_SPOUT enabled
local transforms = asset.require("scene/solarsystem/sun/transforms")
local imageFolder = asset.syncedResource({
Name = "Hover Circle Image",
Type = "HttpSynchronization",
Identifier = "misc_ring_image",
Version = 1
})
local circle = {
Identifier = "hoverCircle",
Parent = transforms.SolarSystemBarycenter.Identifier,
Renderable = {
Type = "RenderablePlaneImageLocal",
Size = 3.0E15,
Origin = "Center",
Billboard = true,
Texture = imageFolder .. "ring.png"
},
GUI = {
Name = "Hover Circle",
Description = [[A circular marker that shows the position on the night sky
of the object hovered in the sky browser UI. The circle will hide/show up
dynamically, depending on the interaction with the items in the UI. ]],
Path = "/SkyBrowser"
}
}
asset.onInitialize(function()
openspace.addSceneGraphNode(circle)
openspace.skybrowser.setHoverCircle('hoverCircle')
end)
asset.onDeinitialize(function()
openspace.removeSceneGraphNode(circle)
end)
asset.export(circle)
asset.meta = {
Name = "SkyBrowser Hover Circle",
Version = "1.0",
Description = [[Includes a circular marker that shows the position on the night sky
of the object hovered in the sky browser UI. ]],
Author = "OpenSpace Team",
URL = "http://openspaceproject.com",
License = "MIT license"
}
@@ -0,0 +1,2 @@
asset.require("./default_settings")
asset.require("./hoverCircle")
@@ -1,5 +1,6 @@
local propertyHelper = asset.require("util/property_helper")
local sunTransforms = asset.require("scene/solarsystem/sun/transforms")
local sunAsset = asset.require("scene/solarsystem/sun/sun")
local densityDirectory = asset.syncedResource({
Name = "Bastille Day MAS Density",
@@ -12,6 +13,9 @@ local sunRadius = 6.957E8
local densityVolume = {
Identifier = "MAS-MHD-Density-bastille-day-2000",
-- TODO Elon: 21 April 2022. Interaction sphere should not depend on the transform scale.
-- InteractionSphere = sunAsset.Sun.Renderable.Radii[1] * 1.05,
InteractionSphere = 1/695700000,
Parent = sunTransforms.SunIAU.Identifier,
Transform = {
Scale = {
@@ -15,6 +15,9 @@ local sunRadius = 6.957E8
local fieldlines = {
Identifier = "MAS-MHD-Fieldlines-bastille-day-2000",
Parent = heliosphereTransforms.HEEQ180ReferenceFrame.Identifier,
-- TODO Elon: 21 April 2022. Interaction sphere should not depend on the transform scale.
-- InteractionSphere = sunAsset.Sun.Renderable.Radii[1] * 1.05,
InteractionSphere = 1/695700000,
Transform = {
Scale = {
Type = "StaticScale",
@@ -13,6 +13,9 @@ local fluxNodesBinaries = asset.syncedResource({
local fluxNodes = {
Identifier = "MAS-MHD-FluxNodes-bastille-day-2000",
Parent = heliosphereTransforms.HEEQ180ReferenceFrame.Identifier,
-- TODO Elon: 21 April 2022. Interaction sphere should not depend on the transform scale.
-- InteractionSphere = sunAsset.Sun.Renderable.Radii[1] * 1.05,
InteractionSphere = 695700000.0,
Transform = {
Rotation = rot.CarringtonLongitudeToHEEQ180Rotation
},
@@ -19,6 +19,9 @@ local TexturesPathMeridial = asset.syncedResource({
local EquatorialCutplane = {
Identifier = "EquatorialCutplane-bastille-day-2000",
Parent = transforms.HEEQ180ReferenceFrame.Identifier,
-- TODO Elon: 21 April 2022. Interaction sphere should not depend on the transform scale.
-- InteractionSphere = sunAsset.Sun.Renderable.Radii[1] * 1.05,
InteractionSphere = 695700000.0,
Transform = {
Rotation = rot.CarringtonLongitudeToHEEQ180Rotation
},
@@ -41,6 +44,9 @@ local EquatorialCutplane = {
local MeridialCutplane = {
Identifier = "MeridialCutplane-bastille-day-2000",
Parent = transforms.HEEQ180ReferenceFrame.Identifier,
-- TODO Elon: 21 April 2022. Interaction sphere should not depend on the transform scale.
-- InteractionSphere = sunAsset.Sun.Renderable.Radii[1] * 1.05,
InteractionSphere = 695700000,
Transform = {
Rotation = {
Type = "StaticRotation",
@@ -5,6 +5,9 @@ local travelSpeedIndicator = {
Identifier = "TravelSpeedIndicator-2000",
--SunIAU adds an extra rotation. Using barycenter, then offsetting to SunIAU
Parent = sunTransforms.SolarSystemBarycenter.Identifier,
-- TODO Elon: 21 April 2022. Interaction sphere should not depend on the transform scale.
-- InteractionSphere = sunAsset.Sun.Renderable.Radii[1] * 1.05,
InteractionSphere = 695700000.0,
Transform = {
Translation = {
Type = "SpiceTranslation",
@@ -4,9 +4,11 @@ local point_jwst = {
Command = [[
local ra
local dec
local duration
if is_declared("args") then
ra = args.Ra
dec = args.Dec
duration = args.Duration
else
return
end
@@ -47,6 +49,8 @@ local point_jwst = {
local D0 = math.rad(27.1284)
-- Galactic longitude of the equatorial north pole
local L0 = math.rad(122.9320)
-- distance = 9.2E15 m (set to size of view sphere)
local distance = 9.2E15
-- (Ra, Dec) -> (a, d)
local a = math.rad(ra)
@@ -61,9 +65,9 @@ local point_jwst = {
-- Convert to cartesian
local rGalactic = {
math.cos(b) * math.cos(l),
math.cos(b) * math.sin(l),
math.sin(b)
distance * math.cos(b) * math.cos(l),
distance * math.cos(b) * math.sin(l),
distance * math.sin(b)
}
return rGalactic
@@ -100,11 +104,9 @@ local point_jwst = {
end
local coordinates = convertRaDec(ra, dec)
local JWSTPosition = openspace.worldPosition('JWSTModel')
local JWSTRotation = openspace.worldRotation('JWSTRotation')
openspace.printInfo(JWSTPosition)
openspace.printInfo(JWSTRotation)
local JWSTtoCoord = {
coordinates[1] - JWSTPosition[1],
coordinates[2] - JWSTPosition[2],
@@ -114,11 +116,6 @@ local point_jwst = {
local JWSTtoCoordRotated = applyMatrix(JWSTRotation, JWSTtoCoord)
local JWSTAngles = calculateJWSTAngles(JWSTtoCoordRotated)
-- Check non 0
if JWSTAngles[1] == 0 and JWSTAngles[2] == 0 then
return
end
-- Check if the new angle violate the sunshield
-- -45 deg to 5 deg is valid in x rotation
if JWSTAngles[1] < math.rad(-45) or JWSTAngles[1] > math.rad(5) then
@@ -128,7 +125,7 @@ local point_jwst = {
openspace.setPropertyValueSingle(
'Scene.JWSTModel.Rotation.Rotation',
{ JWSTAngles[1], JWSTAngles[2], 0.0},
3.0
duration
)
]],
Documentation = [[
@@ -143,14 +140,14 @@ asset.onInitialize(function()
openspace.action.registerAction(point_jwst)
openspace.event.registerEventAction(
"PointJwstRequested",
"PointSpacecraft",
point_jwst.Identifier
)
end)
asset.onDeinitialize(function()
openspace.event.unregisterEventAction(
"PointJwstRequested",
"PointSpacecraft",
point_jwst.Identifier
)
@@ -1,5 +1,6 @@
local transforms = asset.require("./transforms_magnetosphere")
local transferFunction = asset.localResource("./CMR-illuminance2.txt")
local earthAsset = asset.require("scene/solarsystem/planets/earth/earth")
local fieldlinesDirectory = asset.syncedResource({
Name = "Magnetosphere 2012 event",
@@ -11,6 +12,8 @@ local fieldlinesDirectory = asset.syncedResource({
local earthMagnetosphere = {
Identifier = "EarthMagnetosphere",
Parent = transforms.GSMReferenceFrame.Identifier,
-- Grabs a value from earths ellipsoid. 1.05 just to make it somewhat bigger than earth
InteractionSphere = earthAsset.Earth.Renderable.Radii[1] * 1.05,
Renderable = {
Type = "RenderableFieldlinesSequence",
SourceFolder = fieldlinesDirectory,
@@ -39,11 +42,11 @@ local earthMagnetosphere = {
asset.onInitialize(function()
openspace.addSceneGraphNode(earthMagnetosphere)
end)
asset.onDeinitialize(function()
openspace.removeSceneGraphNode(earthMagnetosphere)
end)
asset.export(earthMagnetosphere)
@@ -1,17 +0,0 @@
local globeIdentifier = asset.require("scene/solarsystem/planets/earth/moon/moon").Moon.Identifier
local layer = {
Identifier = "Apollo15_MetricCam_ClrConf_Global_1024ppd",
Name = "Apollo 15 Metric Cam DEM, Colorized Confidence",
FilePath = asset.localResource("Apollo15_MetricCam_ClrConf_Global_1024ppd.wms")
}
asset.onInitialize(function()
openspace.globebrowsing.addLayer(globeIdentifier, "ColorLayers", layer)
end)
asset.onDeinitialize(function()
openspace.globebrowsing.deleteLayer(globeIdentifier, "ColorLayers", layer.Identifier)
end)
asset.export("layer", layer)
@@ -1,48 +0,0 @@
<VRTDataset rasterXSize="16384" rasterYSize="8192">
<SRS dataAxisToSRSAxisMapping="1,2">GEOGCS["GCS_Moon_2000",DATUM["D_Moon_2000",SPHEROID["Moon_2000_IAU_IAG",1737400,0]],PRIMEM["Reference_Meridian",0],UNIT["degree",0.0174532925199433],AXIS["Longitude",EAST],AXIS["Latitude",NORTH]]</SRS>
<GeoTransform> -1.8000000000000000e+02, 2.1972656250000000e-02, 0.0000000000000000e+00, 9.0000000000000000e+01, 0.0000000000000000e+00, -2.1972656250000000e-02</GeoTransform>
<VRTRasterBand dataType="Byte" band="1">
<ColorInterp>Red</ColorInterp>
<SimpleSource>
<SourceFilename relativeToVRT="1">Apollo15_MetricCam_ClrConf_Global_1024ppd.wms</SourceFilename>
<SourceBand>1</SourceBand>
<SourceProperties RasterXSize="16384" RasterYSize="8192" DataType="Byte" BlockXSize="256" BlockYSize="256" />
<SrcRect xOff="0" yOff="0" xSize="16384" ySize="8192" />
<DstRect xOff="0" yOff="0" xSize="16384" ySize="8192" />
</SimpleSource>
</VRTRasterBand>
<VRTRasterBand dataType="Byte" band="2">
<ColorInterp>Green</ColorInterp>
<SimpleSource>
<SourceFilename relativeToVRT="1">Apollo15_MetricCam_ClrConf_Global_1024ppd.wms</SourceFilename>
<SourceBand>2</SourceBand>
<SourceProperties RasterXSize="16384" RasterYSize="8192" DataType="Byte" BlockXSize="256" BlockYSize="256" />
<SrcRect xOff="0" yOff="0" xSize="16384" ySize="8192" />
<DstRect xOff="0" yOff="0" xSize="16384" ySize="8192" />
</SimpleSource>
</VRTRasterBand>
<VRTRasterBand dataType="Byte" band="3">
<ColorInterp>Blue</ColorInterp>
<SimpleSource>
<SourceFilename relativeToVRT="1">Apollo15_MetricCam_ClrConf_Global_1024ppd.wms</SourceFilename>
<SourceBand>3</SourceBand>
<SourceProperties RasterXSize="16384" RasterYSize="8192" DataType="Byte" BlockXSize="256" BlockYSize="256" />
<SrcRect xOff="0" yOff="0" xSize="16384" ySize="8192" />
<DstRect xOff="0" yOff="0" xSize="16384" ySize="8192" />
</SimpleSource>
</VRTRasterBand>
<VRTRasterBand dataType="Byte" band="4">
<NoDataValue>0</NoDataValue>
<ColorInterp>Alpha</ColorInterp>
<ComplexSource>
<SourceFilename relativeToVRT="1">Apollo15_MetricCam_ClrConf_Global_1024ppd.wms</SourceFilename>
<SourceBand>1</SourceBand>
<SourceProperties RasterXSize="16384" RasterYSize="8192" DataType="Byte" BlockXSize="256" BlockYSize="256" />
<SrcRect xOff="0" yOff="0" xSize="16384" ySize="8192" />
<DstRect xOff="0" yOff="0" xSize="16384" ySize="8192" />
<ScaleOffset>255</ScaleOffset>
<ScaleRatio>0</ScaleRatio>
<NODATA>0</NODATA>
</ComplexSource>
</VRTRasterBand>
</VRTDataset>
@@ -1,24 +0,0 @@
<GDAL_WMS>
<Service name="TMS">
<ServerUrl>https://trek.nasa.gov/tiles/Moon/EQ/Apollo15_MetricCam_ClrConf_Global_1024ppd/1.0.0//default/default028mm/${z}/${y}/${x}.png</ServerUrl>
</Service>
<DataWindow>
<UpperLeftX>-180.0</UpperLeftX>
<UpperLeftY>90.0</UpperLeftY>
<LowerRightX>180.0</LowerRightX>
<LowerRightY>-90.0</LowerRightY>
<TileCountX>2</TileCountX>
<TileCountY>1</TileCountY>
<TileLevel>5</TileLevel>
<YOrigin>top</YOrigin>
</DataWindow>
<Projection>
GEOGCS["GCS_Moon_2000",
DATUM["D_Moon_2000",SPHEROID["Moon_2000_IAU_IAG",1737400,0]],
PRIMEM["Reference_Meridian",0],UNIT["degree",0.0174532925199433]]
</Projection>
<BlockSizeX>256</BlockSizeX>
<BlockSizeY>256</BlockSizeY>
<BandsCount>3</BandsCount>
<MaxConnections>10</MaxConnections>
</GDAL_WMS>
@@ -1,17 +0,0 @@
local globeIdentifier = asset.require("scene/solarsystem/planets/earth/moon/moon").Moon.Identifier
local layer = {
Identifier = "Apollo15_MetricCam_Gray_Global_1024ppd",
Name = "Apollo 15 Metric Cam DEM, Grayscale",
FilePath = asset.localResource("Apollo15_MetricCam_Gray_Global_1024ppd.vrt")
}
asset.onInitialize(function()
openspace.globebrowsing.addLayer(globeIdentifier, "ColorLayers", layer)
end)
asset.onDeinitialize(function()
openspace.globebrowsing.deleteLayer(globeIdentifier, "ColorLayers", layer.Identifier)
end)
asset.export("layer", layer)
@@ -1,54 +0,0 @@
<VRTDataset rasterXSize="16384" rasterYSize="8192">
<SRS dataAxisToSRSAxisMapping="1,2">GEOGCS["GCS_Moon_2000",DATUM["D_Moon_2000",SPHEROID["Moon_2000_IAU_IAG",1737400,0]],PRIMEM["Reference_Meridian",0],UNIT["degree",0.0174532925199433],AXIS["Longitude",EAST],AXIS["Latitude",NORTH]]</SRS>
<GeoTransform> -1.8000000000000000e+02, 2.1972656250000000e-02, 0.0000000000000000e+00, 9.0000000000000000e+01, 0.0000000000000000e+00, -2.1972656250000000e-02</GeoTransform>
<VRTRasterBand dataType="Byte" band="1">
<NoDataValue>0</NoDataValue>
<ColorInterp>Red</ColorInterp>
<ComplexSource>
<SourceFilename relativeToVRT="1">Apollo15_MetricCam_Gray_Global_1024ppd.wms</SourceFilename>
<SourceBand>1</SourceBand>
<SourceProperties RasterXSize="16384" RasterYSize="8192" DataType="Byte" BlockXSize="256" BlockYSize="256" />
<SrcRect xOff="0" yOff="0" xSize="16384" ySize="8192" />
<DstRect xOff="0" yOff="0" xSize="16384" ySize="8192" />
<NODATA>0</NODATA>
</ComplexSource>
</VRTRasterBand>
<VRTRasterBand dataType="Byte" band="2">
<NoDataValue>0</NoDataValue>
<ColorInterp>Green</ColorInterp>
<ComplexSource>
<SourceFilename relativeToVRT="1">Apollo15_MetricCam_Gray_Global_1024ppd.wms</SourceFilename>
<SourceBand>2</SourceBand>
<SourceProperties RasterXSize="16384" RasterYSize="8192" DataType="Byte" BlockXSize="256" BlockYSize="256" />
<SrcRect xOff="0" yOff="0" xSize="16384" ySize="8192" />
<DstRect xOff="0" yOff="0" xSize="16384" ySize="8192" />
<NODATA>0</NODATA>
</ComplexSource>
</VRTRasterBand>
<VRTRasterBand dataType="Byte" band="3">
<NoDataValue>0</NoDataValue>
<ColorInterp>Blue</ColorInterp>
<ComplexSource>
<SourceFilename relativeToVRT="1">Apollo15_MetricCam_Gray_Global_1024ppd.wms</SourceFilename>
<SourceBand>3</SourceBand>
<SourceProperties RasterXSize="16384" RasterYSize="8192" DataType="Byte" BlockXSize="256" BlockYSize="256" />
<SrcRect xOff="0" yOff="0" xSize="16384" ySize="8192" />
<DstRect xOff="0" yOff="0" xSize="16384" ySize="8192" />
<NODATA>0</NODATA>
</ComplexSource>
</VRTRasterBand>
<VRTRasterBand dataType="Byte" band="4">
<NoDataValue>0</NoDataValue>
<ColorInterp>Alpha</ColorInterp>
<ComplexSource>
<SourceFilename relativeToVRT="1">Apollo15_MetricCam_Gray_Global_1024ppd.wms</SourceFilename>
<SourceBand>1</SourceBand>
<SourceProperties RasterXSize="16384" RasterYSize="8192" DataType="Byte" BlockXSize="256" BlockYSize="256" />
<SrcRect xOff="0" yOff="0" xSize="16384" ySize="8192" />
<DstRect xOff="0" yOff="0" xSize="16384" ySize="8192" />
<ScaleOffset>255</ScaleOffset>
<ScaleRatio>0</ScaleRatio>
<NODATA>0</NODATA>
</ComplexSource>
</VRTRasterBand>
</VRTDataset>
@@ -1,26 +0,0 @@
<GDAL_WMS>
<Service name="TMS">
<ServerUrl>https://trek.nasa.gov/tiles/Moon/EQ/Apollo15_MetricCam_Gray_Global_1024ppd/1.0.0//default/default028mm/${z}/${y}/${x}.png</ServerUrl>
</Service>
<DataWindow>
<UpperLeftX>-180.0</UpperLeftX>
<UpperLeftY>90.0</UpperLeftY>
<LowerRightX>180.0</LowerRightX>
<LowerRightY>-90.0</LowerRightY>
<TileCountX>2</TileCountX>
<TileCountY>1</TileCountY>
<TileLevel>5</TileLevel>
<YOrigin>top</YOrigin>
</DataWindow>
<Projection>
GEOGCS["GCS_Moon_2000",
DATUM["D_Moon_2000",SPHEROID["Moon_2000_IAU_IAG",1737400,0]],
PRIMEM["Reference_Meridian",0],UNIT["degree",0.0174532925199433]]
</Projection>
<BlockSizeX>256</BlockSizeX>
<BlockSizeY>256</BlockSizeY>
<BandsCount>3</BandsCount>
<MaxConnections>10</MaxConnections>
<DataValues NoData="0" Min="1" Max="255"/>
<ZeroBlockHttpCodes>404,400</ZeroBlockHttpCodes>
</GDAL_WMS>
@@ -0,0 +1,53 @@
<VRTDataset rasterXSize="262144" rasterYSize="131072">
<SRS>GEOGCS["GCS_Moon_2000",DATUM["D_Moon_2000",SPHEROID["Moon_2000_IAU_IAG",1737400.0,0.0]],PRIMEM["Reference_Meridian",0.0],UNIT["Degree",0.0174532925199433]]</SRS>
<GeoTransform> -1.8000000000000000e+02, 1.3732910156250000e-03, 0.0000000000000000e+00, 9.0000000000000000e+01, 0.0000000000000000e+00, -1.3732910156250000e-03</GeoTransform>
<VRTRasterBand dataType="Byte" band="1">
<NoDataValue>0</NoDataValue>
<ColorInterp>Red</ColorInterp>
<ComplexSource>
<SourceFilename relativeToVRT="1">Apollo15_MetricCam_ClrShade_Global_1024ppd.wms</SourceFilename>
<SourceBand>1</SourceBand>
<SourceProperties RasterXSize="262144" RasterYSize="131072" DataType="Byte" BlockXSize="256" BlockYSize="256" />
<SrcRect xOff="0" yOff="0" xSize="262144" ySize="131072" />
<DstRect xOff="0" yOff="0" xSize="262144" ySize="131072" />
<NODATA>0</NODATA>
</ComplexSource>
</VRTRasterBand>
<VRTRasterBand dataType="Byte" band="2">
<NoDataValue>0</NoDataValue>
<ColorInterp>Green</ColorInterp>
<ComplexSource>
<SourceFilename relativeToVRT="1">Apollo15_MetricCam_ClrShade_Global_1024ppd.wms</SourceFilename>
<SourceBand>2</SourceBand>
<SourceProperties RasterXSize="262144" RasterYSize="131072" DataType="Byte" BlockXSize="256" BlockYSize="256" />
<SrcRect xOff="0" yOff="0" xSize="262144" ySize="131072" />
<DstRect xOff="0" yOff="0" xSize="262144" ySize="131072" />
<NODATA>0</NODATA>
</ComplexSource>
</VRTRasterBand>
<VRTRasterBand dataType="Byte" band="3">
<NoDataValue>0</NoDataValue>
<ColorInterp>Blue</ColorInterp>
<ComplexSource>
<SourceFilename relativeToVRT="1">Apollo15_MetricCam_ClrShade_Global_1024ppd.wms</SourceFilename>
<SourceBand>3</SourceBand>
<SourceProperties RasterXSize="262144" RasterYSize="131072" DataType="Byte" BlockXSize="256" BlockYSize="256" />
<SrcRect xOff="0" yOff="0" xSize="262144" ySize="131072" />
<DstRect xOff="0" yOff="0" xSize="262144" ySize="131072" />
<NODATA>0</NODATA>
</ComplexSource>
</VRTRasterBand>
<VRTRasterBand dataType="Byte" band="4">
<ColorInterp>Alpha</ColorInterp>
<ComplexSource>
<SourceFilename relativeToVRT="1">Apollo15_MetricCam_ClrShade_Global_1024ppd.wms</SourceFilename>
<SourceBand>1</SourceBand>
<SourceProperties RasterXSize="262144" RasterYSize="131072" DataType="Byte" BlockXSize="256" BlockYSize="256" />
<SrcRect xOff="0" yOff="0" xSize="262144" ySize="131072" />
<DstRect xOff="0" yOff="0" xSize="262144" ySize="131072" />
<ScaleOffset>255</ScaleOffset>
<ScaleRatio>0</ScaleRatio>
<NODATA>0</NODATA>
</ComplexSource>
</VRTRasterBand>
</VRTDataset>
@@ -0,0 +1,24 @@
<GDAL_WMS>
<Service name="TMS">
<ServerUrl>https://trek.nasa.gov/tiles/Moon/EQ/Apollo15_MetricCam_ClrShade_Global_1024ppd/1.0.0//default/default028mm/${z}/${y}/${x}.png</ServerUrl>
</Service>
<DataWindow>
<UpperLeftX>-180</UpperLeftX>
<UpperLeftY>90</UpperLeftY>
<LowerRightX>180</LowerRightX>
<LowerRightY>-90</LowerRightY>
<TileCountX>2</TileCountX>
<TileCountY>1</TileCountY>
<TileLevel>9</TileLevel>
<YOrigin>top</YOrigin>
</DataWindow>
<Projection>
GEOGCS["GCS_Moon_2000",DATUM["D_Moon_2000",SPHEROID["Moon_2000_IAU_IAG",1737400.0,0.0]],PRIMEM["Reference_Meridian",0.0],UNIT["Degree",0.0174532925199433]]
</Projection>
<BlockSizeX>256</BlockSizeX>
<BlockSizeY>256</BlockSizeY>
<BandsCount>3</BandsCount>
<MaxConnections>10</MaxConnections>
<DataValues NoData="0" Min="1" Max="255"/>
<ZeroBlockHttpCodes>400</ZeroBlockHttpCodes>
</GDAL_WMS>
@@ -0,0 +1,28 @@
local globeIdentifier = asset.require("scene/solarsystem//planets/earth/moon/moon").Moon.Identifier
local layer = {
Identifier = "Apollo15_MetricCam_ClrShade_Global_1024ppd",
Name = [[Apollo 15 Metric Cam DEM, ColorHillshade]],
FilePath = asset.localResource("Apollo15_MetricCam_ClrShade_Global_1024ppd.vrt"),
Description = [[]]
}
asset.onInitialize(function()
openspace.globebrowsing.addLayer(globeIdentifier, "ColorLayers", layer)
end)
asset.onDeinitialize(function()
openspace.globebrowsing.deleteLayer(globeIdentifier, "ColorLayers", layer.Identifier)
end)
asset.export("layer", layer)
asset.meta = {
Name = [[Apollo 15 Metric Cam DEM, ColorHillshade]],
Version = "1.0",
Author = "NASA/Treks",
URL = "https://trek.nasa.gov/moon/#v=0.1&x=0&y=0&z=1&p=urn:ogc:def:crs:EPSG::104903&d=&l=Apollo15_MetricCam_ClrShade_Global_1024ppd%2Ctrue%2C1&b=moon&e=-180.0%2C-90.0%2C180.0%2C90.0&sfv=&w=",
License = "NASA/Treks",
Description = [[Apollo 15 Metric Cam DEM, ColorHillshade layer from NASA/Treks for Moon]]
}
@@ -0,0 +1,53 @@
<VRTDataset rasterXSize="262144" rasterYSize="131072">
<SRS>GEOGCS["GCS_Moon_2000",DATUM["D_Moon_2000",SPHEROID["Moon_2000_IAU_IAG",1737400,0]],PRIMEM["Reference_Meridian",0],UNIT["degree",0.0174532925199433]]</SRS>
<GeoTransform> -1.8000000000000000e+02, 1.3732910156250000e-03, 0.0000000000000000e+00, 9.0000000000000000e+01, 0.0000000000000000e+00, -1.3732910156250000e-03</GeoTransform>
<VRTRasterBand dataType="Byte" band="1">
<NoDataValue>0</NoDataValue>
<ColorInterp>Red</ColorInterp>
<ComplexSource>
<SourceFilename relativeToVRT="1">Apollo15_MetricCam_ClrConf_Global_1024ppd.wms</SourceFilename>
<SourceBand>1</SourceBand>
<SourceProperties RasterXSize="262144" RasterYSize="131072" DataType="Byte" BlockXSize="256" BlockYSize="256" />
<SrcRect xOff="0" yOff="0" xSize="262144" ySize="131072" />
<DstRect xOff="0" yOff="0" xSize="262144" ySize="131072" />
<NODATA>0</NODATA>
</ComplexSource>
</VRTRasterBand>
<VRTRasterBand dataType="Byte" band="2">
<NoDataValue>0</NoDataValue>
<ColorInterp>Green</ColorInterp>
<ComplexSource>
<SourceFilename relativeToVRT="1">Apollo15_MetricCam_ClrConf_Global_1024ppd.wms</SourceFilename>
<SourceBand>2</SourceBand>
<SourceProperties RasterXSize="262144" RasterYSize="131072" DataType="Byte" BlockXSize="256" BlockYSize="256" />
<SrcRect xOff="0" yOff="0" xSize="262144" ySize="131072" />
<DstRect xOff="0" yOff="0" xSize="262144" ySize="131072" />
<NODATA>0</NODATA>
</ComplexSource>
</VRTRasterBand>
<VRTRasterBand dataType="Byte" band="3">
<NoDataValue>0</NoDataValue>
<ColorInterp>Blue</ColorInterp>
<ComplexSource>
<SourceFilename relativeToVRT="1">Apollo15_MetricCam_ClrConf_Global_1024ppd.wms</SourceFilename>
<SourceBand>3</SourceBand>
<SourceProperties RasterXSize="262144" RasterYSize="131072" DataType="Byte" BlockXSize="256" BlockYSize="256" />
<SrcRect xOff="0" yOff="0" xSize="262144" ySize="131072" />
<DstRect xOff="0" yOff="0" xSize="262144" ySize="131072" />
<NODATA>0</NODATA>
</ComplexSource>
</VRTRasterBand>
<VRTRasterBand dataType="Byte" band="4">
<ColorInterp>Alpha</ColorInterp>
<ComplexSource>
<SourceFilename relativeToVRT="1">Apollo15_MetricCam_ClrConf_Global_1024ppd.wms</SourceFilename>
<SourceBand>1</SourceBand>
<SourceProperties RasterXSize="262144" RasterYSize="131072" DataType="Byte" BlockXSize="256" BlockYSize="256" />
<SrcRect xOff="0" yOff="0" xSize="262144" ySize="131072" />
<DstRect xOff="0" yOff="0" xSize="262144" ySize="131072" />
<ScaleOffset>255</ScaleOffset>
<ScaleRatio>0</ScaleRatio>
<NODATA>0</NODATA>
</ComplexSource>
</VRTRasterBand>
</VRTDataset>
@@ -0,0 +1,24 @@
<GDAL_WMS>
<Service name="TMS">
<ServerUrl>https://trek.nasa.gov/tiles/Moon/EQ/Apollo15_MetricCam_ClrConf_Global_1024ppd/1.0.0//default/default028mm/${z}/${y}/${x}.png</ServerUrl>
</Service>
<DataWindow>
<UpperLeftX>-180</UpperLeftX>
<UpperLeftY>90</UpperLeftY>
<LowerRightX>180</LowerRightX>
<LowerRightY>-90</LowerRightY>
<TileCountX>2</TileCountX>
<TileCountY>1</TileCountY>
<TileLevel>9</TileLevel>
<YOrigin>top</YOrigin>
</DataWindow>
<Projection>
GEOGCS["GCS_Moon_2000",DATUM["D_Moon_2000",SPHEROID["Moon_2000_IAU_IAG",1737400,0]],PRIMEM["Reference_Meridian",0],UNIT["degree",0.0174532925199433]]
</Projection>
<BlockSizeX>256</BlockSizeX>
<BlockSizeY>256</BlockSizeY>
<BandsCount>3</BandsCount>
<MaxConnections>10</MaxConnections>
<DataValues NoData="0" Min="1" Max="255"/>
<ZeroBlockHttpCodes>400</ZeroBlockHttpCodes>
</GDAL_WMS>
@@ -0,0 +1,28 @@
local globeIdentifier = asset.require("scene/solarsystem//planets/earth/moon/moon").Moon.Identifier
local layer = {
Identifier = "Apollo15_MetricCam_ClrConf_Global_1024ppd",
Name = [[Apollo 15 Metric Cam DEM, Colorized Confidence]],
FilePath = asset.localResource("Apollo15_MetricCam_ClrConf_Global_1024ppd.vrt"),
Description = [[]]
}
asset.onInitialize(function()
openspace.globebrowsing.addLayer(globeIdentifier, "ColorLayers", layer)
end)
asset.onDeinitialize(function()
openspace.globebrowsing.deleteLayer(globeIdentifier, "ColorLayers", layer.Identifier)
end)
asset.export("layer", layer)
asset.meta = {
Name = [[Apollo 15 Metric Cam DEM, Colorized Confidence]],
Version = "1.0",
Author = "NASA/Treks",
URL = "https://trek.nasa.gov/moon/#v=0.1&x=0&y=0&z=1&p=urn:ogc:def:crs:EPSG::104903&d=&l=Apollo15_MetricCam_ClrConf_Global_1024ppd%2Ctrue%2C1&b=moon&e=-180.0%2C-90.0%2C180.0%2C90.0&sfv=&w=",
License = "NASA/Treks",
Description = [[Apollo 15 Metric Cam DEM, Colorized Confidence layer from NASA/Treks for Moon]]
}
@@ -0,0 +1,29 @@
<VRTDataset rasterXSize="262144" rasterYSize="131072">
<SRS>GEOGCS["GCS_Moon_2000",DATUM["D_Moon_2000",SPHEROID["Moon_2000_IAU_IAG",1737400.0,0.0]],PRIMEM["Reference_Meridian",0.0],UNIT["Degree",0.0174532925199433]]</SRS>
<GeoTransform> -1.8000000000000000e+02, 1.3732910156250000e-03, 0.0000000000000000e+00, 9.0000000000000000e+01, 0.0000000000000000e+00, -1.3732910156250000e-03</GeoTransform>
<VRTRasterBand dataType="Byte" band="1">
<NoDataValue>0</NoDataValue>
<ColorInterp>Gray</ColorInterp>
<ComplexSource>
<SourceFilename relativeToVRT="1">Apollo15_MetricCam_Gray_Global_1024ppd.wms</SourceFilename>
<SourceBand>1</SourceBand>
<SourceProperties RasterXSize="262144" RasterYSize="131072" DataType="Byte" BlockXSize="256" BlockYSize="256" />
<SrcRect xOff="0" yOff="0" xSize="262144" ySize="131072" />
<DstRect xOff="0" yOff="0" xSize="262144" ySize="131072" />
<NODATA>0</NODATA>
</ComplexSource>
</VRTRasterBand>
<VRTRasterBand dataType="Byte" band="2">
<ColorInterp>Alpha</ColorInterp>
<ComplexSource>
<SourceFilename relativeToVRT="1">Apollo15_MetricCam_Gray_Global_1024ppd.wms</SourceFilename>
<SourceBand>1</SourceBand>
<SourceProperties RasterXSize="262144" RasterYSize="131072" DataType="Byte" BlockXSize="256" BlockYSize="256" />
<SrcRect xOff="0" yOff="0" xSize="262144" ySize="131072" />
<DstRect xOff="0" yOff="0" xSize="262144" ySize="131072" />
<ScaleOffset>255</ScaleOffset>
<ScaleRatio>0</ScaleRatio>
<NODATA>0</NODATA>
</ComplexSource>
</VRTRasterBand>
</VRTDataset>
@@ -0,0 +1,24 @@
<GDAL_WMS>
<Service name="TMS">
<ServerUrl>https://trek.nasa.gov/tiles/Moon/EQ/Apollo15_MetricCam_Gray_Global_1024ppd/1.0.0//default/default028mm/${z}/${y}/${x}.png</ServerUrl>
</Service>
<DataWindow>
<UpperLeftX>-180</UpperLeftX>
<UpperLeftY>90</UpperLeftY>
<LowerRightX>180</LowerRightX>
<LowerRightY>-90</LowerRightY>
<TileCountX>2</TileCountX>
<TileCountY>1</TileCountY>
<TileLevel>9</TileLevel>
<YOrigin>top</YOrigin>
</DataWindow>
<Projection>
GEOGCS["GCS_Moon_2000",DATUM["D_Moon_2000",SPHEROID["Moon_2000_IAU_IAG",1737400.0,0.0]],PRIMEM["Reference_Meridian",0.0],UNIT["Degree",0.0174532925199433]]
</Projection>
<BlockSizeX>256</BlockSizeX>
<BlockSizeY>256</BlockSizeY>
<BandsCount>1</BandsCount>
<MaxConnections>10</MaxConnections>
<DataValues NoData="0" Min="1" Max="255"/>
<ZeroBlockHttpCodes>400</ZeroBlockHttpCodes>
</GDAL_WMS>
@@ -0,0 +1,28 @@
local globeIdentifier = asset.require("scene/solarsystem//planets/earth/moon/moon").Moon.Identifier
local layer = {
Identifier = "Apollo15_MetricCam_Gray_Global_1024ppd",
Name = [[Apollo 15 Metric Cam DEM, Grayscale]],
FilePath = asset.localResource("Apollo15_MetricCam_Gray_Global_1024ppd.vrt"),
Description = [[]]
}
asset.onInitialize(function()
openspace.globebrowsing.addLayer(globeIdentifier, "ColorLayers", layer)
end)
asset.onDeinitialize(function()
openspace.globebrowsing.deleteLayer(globeIdentifier, "ColorLayers", layer.Identifier)
end)
asset.export("layer", layer)
asset.meta = {
Name = [[Apollo 15 Metric Cam DEM, Grayscale]],
Version = "1.0",
Author = "NASA/Treks",
URL = "https://trek.nasa.gov/moon/#v=0.1&x=0&y=0&z=1&p=urn:ogc:def:crs:EPSG::104903&d=&l=Apollo15_MetricCam_Gray_Global_1024ppd%2Ctrue%2C1&b=moon&e=-180.0%2C-90.0%2C180.0%2C90.0&sfv=&w=",
License = "NASA/Treks",
Description = [[Apollo 15 Metric Cam DEM, Grayscale layer from NASA/Treks for Moon]]
}
@@ -0,0 +1,29 @@
<VRTDataset rasterXSize="262144" rasterYSize="131072">
<SRS>GEOGCS["GCS_Moon_2000",DATUM["D_Moon_2000",SPHEROID["Moon_2000_IAU_IAG",1737400.0,0.0]],PRIMEM["Reference_Meridian",0.0],UNIT["Degree",0.0174532925199433]]</SRS>
<GeoTransform> -1.8000000000000000e+02, 1.3732910156250000e-03, 0.0000000000000000e+00, 9.0000000000000000e+01, 0.0000000000000000e+00, -1.3732910156250000e-03</GeoTransform>
<VRTRasterBand dataType="Byte" band="1">
<NoDataValue>0</NoDataValue>
<ColorInterp>Gray</ColorInterp>
<ComplexSource>
<SourceFilename relativeToVRT="1">Apollo15_MetricCam_Shade_Global_1024ppd.wms</SourceFilename>
<SourceBand>1</SourceBand>
<SourceProperties RasterXSize="262144" RasterYSize="131072" DataType="Byte" BlockXSize="256" BlockYSize="256" />
<SrcRect xOff="0" yOff="0" xSize="262144" ySize="131072" />
<DstRect xOff="0" yOff="0" xSize="262144" ySize="131072" />
<NODATA>0</NODATA>
</ComplexSource>
</VRTRasterBand>
<VRTRasterBand dataType="Byte" band="2">
<ColorInterp>Alpha</ColorInterp>
<ComplexSource>
<SourceFilename relativeToVRT="1">Apollo15_MetricCam_Shade_Global_1024ppd.wms</SourceFilename>
<SourceBand>1</SourceBand>
<SourceProperties RasterXSize="262144" RasterYSize="131072" DataType="Byte" BlockXSize="256" BlockYSize="256" />
<SrcRect xOff="0" yOff="0" xSize="262144" ySize="131072" />
<DstRect xOff="0" yOff="0" xSize="262144" ySize="131072" />
<ScaleOffset>255</ScaleOffset>
<ScaleRatio>0</ScaleRatio>
<NODATA>0</NODATA>
</ComplexSource>
</VRTRasterBand>
</VRTDataset>
@@ -0,0 +1,24 @@
<GDAL_WMS>
<Service name="TMS">
<ServerUrl>https://trek.nasa.gov/tiles/Moon/EQ/Apollo15_MetricCam_Shade_Global_1024ppd/1.0.0//default/default028mm/${z}/${y}/${x}.png</ServerUrl>
</Service>
<DataWindow>
<UpperLeftX>-180</UpperLeftX>
<UpperLeftY>90</UpperLeftY>
<LowerRightX>180</LowerRightX>
<LowerRightY>-90</LowerRightY>
<TileCountX>2</TileCountX>
<TileCountY>1</TileCountY>
<TileLevel>9</TileLevel>
<YOrigin>top</YOrigin>
</DataWindow>
<Projection>
GEOGCS["GCS_Moon_2000",DATUM["D_Moon_2000",SPHEROID["Moon_2000_IAU_IAG",1737400.0,0.0]],PRIMEM["Reference_Meridian",0.0],UNIT["Degree",0.0174532925199433]]
</Projection>
<BlockSizeX>256</BlockSizeX>
<BlockSizeY>256</BlockSizeY>
<BandsCount>1</BandsCount>
<MaxConnections>10</MaxConnections>
<DataValues NoData="0" Min="1" Max="255"/>
<ZeroBlockHttpCodes>400</ZeroBlockHttpCodes>
</GDAL_WMS>
@@ -0,0 +1,28 @@
local globeIdentifier = asset.require("scene/solarsystem//planets/earth/moon/moon").Moon.Identifier
local layer = {
Identifier = "Apollo15_MetricCam_Shade_Global_1024ppd",
Name = [[Apollo 15 Metric Cam DEM, Hillshade]],
FilePath = asset.localResource("Apollo15_MetricCam_Shade_Global_1024ppd.vrt"),
Description = [[]]
}
asset.onInitialize(function()
openspace.globebrowsing.addLayer(globeIdentifier, "ColorLayers", layer)
end)
asset.onDeinitialize(function()
openspace.globebrowsing.deleteLayer(globeIdentifier, "ColorLayers", layer.Identifier)
end)
asset.export("layer", layer)
asset.meta = {
Name = [[Apollo 15 Metric Cam DEM, Hillshade]],
Version = "1.0",
Author = "NASA/Treks",
URL = "https://trek.nasa.gov/moon/#v=0.1&x=0&y=0&z=1&p=urn:ogc:def:crs:EPSG::104903&d=&l=Apollo15_MetricCam_Shade_Global_1024ppd%2Ctrue%2C1&b=moon&e=-180.0%2C-90.0%2C180.0%2C90.0&sfv=&w=",
License = "NASA/Treks",
Description = [[Apollo 15 Metric Cam DEM, Hillshade layer from NASA/Treks for Moon]]
}
@@ -0,0 +1,29 @@
<VRTDataset rasterXSize="2097152" rasterYSize="1048576">
<SRS>GEOGCS["GCS_Moon_2000",DATUM["D_Moon_2000",SPHEROID["Moon_2000_IAU_IAG",1737400.0,0.0]],PRIMEM["Reference_Meridian",0.0],UNIT["Degree",0.0174532925199433]]</SRS>
<GeoTransform> -1.8000000000000000e+02, 1.7166137695312500e-04, 0.0000000000000000e+00, 9.0000000000000000e+01, 0.0000000000000000e+00, -1.7166137695312500e-04</GeoTransform>
<VRTRasterBand dataType="Byte" band="1">
<NoDataValue>0</NoDataValue>
<ColorInterp>Gray</ColorInterp>
<ComplexSource>
<SourceFilename relativeToVRT="1">Apollo15_MetricCam_Mosaic_Global_4096ppd.wms</SourceFilename>
<SourceBand>1</SourceBand>
<SourceProperties RasterXSize="2097152" RasterYSize="1048576" DataType="Byte" BlockXSize="256" BlockYSize="256" />
<SrcRect xOff="0" yOff="0" xSize="2097152" ySize="1048576" />
<DstRect xOff="0" yOff="0" xSize="2097152" ySize="1048576" />
<NODATA>0</NODATA>
</ComplexSource>
</VRTRasterBand>
<VRTRasterBand dataType="Byte" band="2">
<ColorInterp>Alpha</ColorInterp>
<ComplexSource>
<SourceFilename relativeToVRT="1">Apollo15_MetricCam_Mosaic_Global_4096ppd.wms</SourceFilename>
<SourceBand>1</SourceBand>
<SourceProperties RasterXSize="2097152" RasterYSize="1048576" DataType="Byte" BlockXSize="256" BlockYSize="256" />
<SrcRect xOff="0" yOff="0" xSize="2097152" ySize="1048576" />
<DstRect xOff="0" yOff="0" xSize="2097152" ySize="1048576" />
<ScaleOffset>255</ScaleOffset>
<ScaleRatio>0</ScaleRatio>
<NODATA>0</NODATA>
</ComplexSource>
</VRTRasterBand>
</VRTDataset>
@@ -0,0 +1,24 @@
<GDAL_WMS>
<Service name="TMS">
<ServerUrl>https://trek.nasa.gov/tiles/Moon/EQ/Apollo15_MetricCam_Mosaic_Global_4096ppd/1.0.0//default/default028mm/${z}/${y}/${x}.png</ServerUrl>
</Service>
<DataWindow>
<UpperLeftX>-180</UpperLeftX>
<UpperLeftY>90</UpperLeftY>
<LowerRightX>180</LowerRightX>
<LowerRightY>-90</LowerRightY>
<TileCountX>2</TileCountX>
<TileCountY>1</TileCountY>
<TileLevel>12</TileLevel>
<YOrigin>top</YOrigin>
</DataWindow>
<Projection>
GEOGCS["GCS_Moon_2000",DATUM["D_Moon_2000",SPHEROID["Moon_2000_IAU_IAG",1737400.0,0.0]],PRIMEM["Reference_Meridian",0.0],UNIT["Degree",0.0174532925199433]]
</Projection>
<BlockSizeX>256</BlockSizeX>
<BlockSizeY>256</BlockSizeY>
<BandsCount>1</BandsCount>
<MaxConnections>10</MaxConnections>
<DataValues NoData="0" Min="1" Max="255"/>
<ZeroBlockHttpCodes>400</ZeroBlockHttpCodes>
</GDAL_WMS>
@@ -0,0 +1,28 @@
local globeIdentifier = asset.require("scene/solarsystem//planets/earth/moon/moon").Moon.Identifier
local layer = {
Identifier = "Apollo15_MetricCam_Mosaic_Global_4096ppd",
Name = [[Apollo 15 Metric Cam Image Mosaic]],
FilePath = asset.localResource("Apollo15_MetricCam_Mosaic_Global_4096ppd.vrt"),
Description = [[]]
}
asset.onInitialize(function()
openspace.globebrowsing.addLayer(globeIdentifier, "ColorLayers", layer)
end)
asset.onDeinitialize(function()
openspace.globebrowsing.deleteLayer(globeIdentifier, "ColorLayers", layer.Identifier)
end)
asset.export("layer", layer)
asset.meta = {
Name = [[Apollo 15 Metric Cam Image Mosaic]],
Version = "1.0",
Author = "NASA/Treks",
URL = "https://trek.nasa.gov/moon/#v=0.1&x=0&y=0&z=1&p=urn:ogc:def:crs:EPSG::104903&d=&l=Apollo15_MetricCam_Mosaic_Global_4096ppd%2Ctrue%2C1&b=moon&e=-180.0%2C-90.0%2C180.0%2C90.0&sfv=&w=",
License = "NASA/Treks",
Description = [[Apollo 15 Metric Cam Image Mosaic layer from NASA/Treks for Moon]]
}
@@ -0,0 +1,53 @@
<VRTDataset rasterXSize="2097152" rasterYSize="1048576">
<SRS>PROJCS["Equirectangular MOON",GEOGCS["GCS_MOON",DATUM["D_MOON",SPHEROID["MOON_localRadius",1737400,0]],PRIMEM["Reference_Meridian",0],UNIT["degree",0.0174532925199433]],PROJECTION["Equirectangular"],PARAMETER["latitude_of_origin",0],PARAMETER["central_meridian",0],PARAMETER["standard_parallel_1",25],PARAMETER["false_easting",0],PARAMETER["false_northing",0],UNIT["metre",1,AUTHORITY["EPSG","9001"]]]</SRS>
<GeoTransform> -1.8000000000000000e+02, 1.7166137695312500e-04, 0.0000000000000000e+00, 9.0000000000000000e+01, 0.0000000000000000e+00, -1.7166137695312500e-04</GeoTransform>
<VRTRasterBand dataType="Byte" band="1">
<NoDataValue>0</NoDataValue>
<ColorInterp>Red</ColorInterp>
<ComplexSource>
<SourceFilename relativeToVRT="1">Apollo15_PanCam_ClrShade_25N311E_5mp.wms</SourceFilename>
<SourceBand>1</SourceBand>
<SourceProperties RasterXSize="2097152" RasterYSize="1048576" DataType="Byte" BlockXSize="256" BlockYSize="256" />
<SrcRect xOff="0" yOff="0" xSize="2097152" ySize="1048576" />
<DstRect xOff="0" yOff="0" xSize="2097152" ySize="1048576" />
<NODATA>0</NODATA>
</ComplexSource>
</VRTRasterBand>
<VRTRasterBand dataType="Byte" band="2">
<NoDataValue>0</NoDataValue>
<ColorInterp>Green</ColorInterp>
<ComplexSource>
<SourceFilename relativeToVRT="1">Apollo15_PanCam_ClrShade_25N311E_5mp.wms</SourceFilename>
<SourceBand>2</SourceBand>
<SourceProperties RasterXSize="2097152" RasterYSize="1048576" DataType="Byte" BlockXSize="256" BlockYSize="256" />
<SrcRect xOff="0" yOff="0" xSize="2097152" ySize="1048576" />
<DstRect xOff="0" yOff="0" xSize="2097152" ySize="1048576" />
<NODATA>0</NODATA>
</ComplexSource>
</VRTRasterBand>
<VRTRasterBand dataType="Byte" band="3">
<NoDataValue>0</NoDataValue>
<ColorInterp>Blue</ColorInterp>
<ComplexSource>
<SourceFilename relativeToVRT="1">Apollo15_PanCam_ClrShade_25N311E_5mp.wms</SourceFilename>
<SourceBand>3</SourceBand>
<SourceProperties RasterXSize="2097152" RasterYSize="1048576" DataType="Byte" BlockXSize="256" BlockYSize="256" />
<SrcRect xOff="0" yOff="0" xSize="2097152" ySize="1048576" />
<DstRect xOff="0" yOff="0" xSize="2097152" ySize="1048576" />
<NODATA>0</NODATA>
</ComplexSource>
</VRTRasterBand>
<VRTRasterBand dataType="Byte" band="4">
<ColorInterp>Alpha</ColorInterp>
<ComplexSource>
<SourceFilename relativeToVRT="1">Apollo15_PanCam_ClrShade_25N311E_5mp.wms</SourceFilename>
<SourceBand>1</SourceBand>
<SourceProperties RasterXSize="2097152" RasterYSize="1048576" DataType="Byte" BlockXSize="256" BlockYSize="256" />
<SrcRect xOff="0" yOff="0" xSize="2097152" ySize="1048576" />
<DstRect xOff="0" yOff="0" xSize="2097152" ySize="1048576" />
<ScaleOffset>255</ScaleOffset>
<ScaleRatio>0</ScaleRatio>
<NODATA>0</NODATA>
</ComplexSource>
</VRTRasterBand>
</VRTDataset>
@@ -0,0 +1,24 @@
<GDAL_WMS>
<Service name="TMS">
<ServerUrl>https://trek.nasa.gov/tiles/Moon/EQ/Apollo15_PanCam_ClrShade_25N311E_5mp/1.0.0//default/default028mm/${z}/${y}/${x}.png</ServerUrl>
</Service>
<DataWindow>
<UpperLeftX>-180</UpperLeftX>
<UpperLeftY>90</UpperLeftY>
<LowerRightX>180</LowerRightX>
<LowerRightY>-90</LowerRightY>
<TileCountX>2</TileCountX>
<TileCountY>1</TileCountY>
<TileLevel>12</TileLevel>
<YOrigin>top</YOrigin>
</DataWindow>
<Projection>
PROJCS["Equirectangular MOON",GEOGCS["GCS_MOON",DATUM["D_MOON",SPHEROID["MOON_localRadius",1737400,0]],PRIMEM["Reference_Meridian",0],UNIT["degree",0.0174532925199433]],PROJECTION["Equirectangular"],PARAMETER["latitude_of_origin",0],PARAMETER["central_meridian",0],PARAMETER["standard_parallel_1",25],PARAMETER["false_easting",0],PARAMETER["false_northing",0],UNIT["metre",1,AUTHORITY["EPSG","9001"]]]
</Projection>
<BlockSizeX>256</BlockSizeX>
<BlockSizeY>256</BlockSizeY>
<BandsCount>3</BandsCount>
<MaxConnections>10</MaxConnections>
<DataValues NoData="0" Min="1" Max="255"/>
<ZeroBlockHttpCodes>404,400</ZeroBlockHttpCodes>
</GDAL_WMS>
@@ -0,0 +1,28 @@
local globeIdentifier = asset.require("scene/solarsystem//planets/earth/moon/moon").Moon.Identifier
local layer = {
Identifier = "Apollo15_PanCam_ClrShade_25N311E_5mp",
Name = [[Apollo 15 Pan Cam DEM, Aristarchus Plateau 1, ColorHillshade]],
FilePath = asset.localResource("Apollo15_PanCam_ClrShade_25N311E_5mp.vrt"),
Description = [[]]
}
asset.onInitialize(function()
openspace.globebrowsing.addLayer(globeIdentifier, "ColorLayers", layer)
end)
asset.onDeinitialize(function()
openspace.globebrowsing.deleteLayer(globeIdentifier, "ColorLayers", layer.Identifier)
end)
asset.export("layer", layer)
asset.meta = {
Name = [[Apollo 15 Pan Cam DEM, Aristarchus Plateau 1, ColorHillshade]],
Version = "1.0",
Author = "NASA/Treks",
URL = "https://trek.nasa.gov/moon/#v=0.1&x=0&y=0&z=1&p=urn:ogc:def:crs:EPSG::104903&d=&l=Apollo15_PanCam_ClrShade_25N311E_5mp%2Ctrue%2C1&b=moon&e=-180.0%2C-90.0%2C180.0%2C90.0&sfv=&w=",
License = "NASA/Treks",
Description = [[Apollo 15 Pan Cam DEM, Aristarchus Plateau 1, ColorHillshade layer from NASA/Treks for Moon]]
}
@@ -0,0 +1,53 @@
<VRTDataset rasterXSize="2097152" rasterYSize="1048576">
<SRS>PROJCS["Equirectangular MOON",GEOGCS["GCS_MOON",DATUM["D_MOON",SPHEROID["MOON_localRadius",1737400,0]],PRIMEM["Reference_Meridian",0],UNIT["degree",0.0174532925199433]],PROJECTION["Equirectangular"],PARAMETER["latitude_of_origin",0],PARAMETER["central_meridian",0],PARAMETER["standard_parallel_1",-2],PARAMETER["false_easting",0],PARAMETER["false_northing",0],UNIT["metre",1,AUTHORITY["EPSG","9001"]]]</SRS>
<GeoTransform> -1.8000000000000000e+02, 1.7166137695312500e-04, 0.0000000000000000e+00, 9.0000000000000000e+01, 0.0000000000000000e+00, -1.7166137695312500e-04</GeoTransform>
<VRTRasterBand dataType="Byte" band="1">
<NoDataValue>0</NoDataValue>
<ColorInterp>Red</ColorInterp>
<ComplexSource>
<SourceFilename relativeToVRT="1">Apollo15_PanCam_ClrConf_25N311E_5mp.wms</SourceFilename>
<SourceBand>1</SourceBand>
<SourceProperties RasterXSize="2097152" RasterYSize="1048576" DataType="Byte" BlockXSize="256" BlockYSize="256" />
<SrcRect xOff="0" yOff="0" xSize="2097152" ySize="1048576" />
<DstRect xOff="0" yOff="0" xSize="2097152" ySize="1048576" />
<NODATA>0</NODATA>
</ComplexSource>
</VRTRasterBand>
<VRTRasterBand dataType="Byte" band="2">
<NoDataValue>0</NoDataValue>
<ColorInterp>Green</ColorInterp>
<ComplexSource>
<SourceFilename relativeToVRT="1">Apollo15_PanCam_ClrConf_25N311E_5mp.wms</SourceFilename>
<SourceBand>2</SourceBand>
<SourceProperties RasterXSize="2097152" RasterYSize="1048576" DataType="Byte" BlockXSize="256" BlockYSize="256" />
<SrcRect xOff="0" yOff="0" xSize="2097152" ySize="1048576" />
<DstRect xOff="0" yOff="0" xSize="2097152" ySize="1048576" />
<NODATA>0</NODATA>
</ComplexSource>
</VRTRasterBand>
<VRTRasterBand dataType="Byte" band="3">
<NoDataValue>0</NoDataValue>
<ColorInterp>Blue</ColorInterp>
<ComplexSource>
<SourceFilename relativeToVRT="1">Apollo15_PanCam_ClrConf_25N311E_5mp.wms</SourceFilename>
<SourceBand>3</SourceBand>
<SourceProperties RasterXSize="2097152" RasterYSize="1048576" DataType="Byte" BlockXSize="256" BlockYSize="256" />
<SrcRect xOff="0" yOff="0" xSize="2097152" ySize="1048576" />
<DstRect xOff="0" yOff="0" xSize="2097152" ySize="1048576" />
<NODATA>0</NODATA>
</ComplexSource>
</VRTRasterBand>
<VRTRasterBand dataType="Byte" band="4">
<ColorInterp>Alpha</ColorInterp>
<ComplexSource>
<SourceFilename relativeToVRT="1">Apollo15_PanCam_ClrConf_25N311E_5mp.wms</SourceFilename>
<SourceBand>1</SourceBand>
<SourceProperties RasterXSize="2097152" RasterYSize="1048576" DataType="Byte" BlockXSize="256" BlockYSize="256" />
<SrcRect xOff="0" yOff="0" xSize="2097152" ySize="1048576" />
<DstRect xOff="0" yOff="0" xSize="2097152" ySize="1048576" />
<ScaleOffset>255</ScaleOffset>
<ScaleRatio>0</ScaleRatio>
<NODATA>0</NODATA>
</ComplexSource>
</VRTRasterBand>
</VRTDataset>
@@ -0,0 +1,24 @@
<GDAL_WMS>
<Service name="TMS">
<ServerUrl>https://trek.nasa.gov/tiles/Moon/EQ/Apollo15_PanCam_ClrConf_25N311E_5mp/1.0.0//default/default028mm/${z}/${y}/${x}.png</ServerUrl>
</Service>
<DataWindow>
<UpperLeftX>-180</UpperLeftX>
<UpperLeftY>90</UpperLeftY>
<LowerRightX>180</LowerRightX>
<LowerRightY>-90</LowerRightY>
<TileCountX>2</TileCountX>
<TileCountY>1</TileCountY>
<TileLevel>12</TileLevel>
<YOrigin>top</YOrigin>
</DataWindow>
<Projection>
PROJCS["Equirectangular MOON",GEOGCS["GCS_MOON",DATUM["D_MOON",SPHEROID["MOON_localRadius",1737400,0]],PRIMEM["Reference_Meridian",0],UNIT["degree",0.0174532925199433]],PROJECTION["Equirectangular"],PARAMETER["latitude_of_origin",0],PARAMETER["central_meridian",0],PARAMETER["standard_parallel_1",-2],PARAMETER["false_easting",0],PARAMETER["false_northing",0],UNIT["metre",1,AUTHORITY["EPSG","9001"]]]
</Projection>
<BlockSizeX>256</BlockSizeX>
<BlockSizeY>256</BlockSizeY>
<BandsCount>3</BandsCount>
<MaxConnections>10</MaxConnections>
<DataValues NoData="0" Min="1" Max="255"/>
<ZeroBlockHttpCodes>404,400</ZeroBlockHttpCodes>
</GDAL_WMS>
@@ -0,0 +1,28 @@
local globeIdentifier = asset.require("scene/solarsystem//planets/earth/moon/moon").Moon.Identifier
local layer = {
Identifier = "Apollo15_PanCam_ClrConf_25N311E_5mp",
Name = [[Apollo 15 Pan Cam DEM, Aristarchus Plateau 1, Colorized Confidence]],
FilePath = asset.localResource("Apollo15_PanCam_ClrConf_25N311E_5mp.vrt"),
Description = [[]]
}
asset.onInitialize(function()
openspace.globebrowsing.addLayer(globeIdentifier, "ColorLayers", layer)
end)
asset.onDeinitialize(function()
openspace.globebrowsing.deleteLayer(globeIdentifier, "ColorLayers", layer.Identifier)
end)
asset.export("layer", layer)
asset.meta = {
Name = [[Apollo 15 Pan Cam DEM, Aristarchus Plateau 1, Colorized Confidence]],
Version = "1.0",
Author = "NASA/Treks",
URL = "https://trek.nasa.gov/moon/#v=0.1&x=0&y=0&z=1&p=urn:ogc:def:crs:EPSG::104903&d=&l=Apollo15_PanCam_ClrConf_25N311E_5mp%2Ctrue%2C1&b=moon&e=-180.0%2C-90.0%2C180.0%2C90.0&sfv=&w=",
License = "NASA/Treks",
Description = [[Apollo 15 Pan Cam DEM, Aristarchus Plateau 1, Colorized Confidence layer from NASA/Treks for Moon]]
}
@@ -0,0 +1,53 @@
<VRTDataset rasterXSize="2097152" rasterYSize="1048576">
<SRS>PROJCS["Equirectangular MOON",GEOGCS["GCS_MOON",DATUM["D_MOON",SPHEROID["MOON_localRadius",1737400,0]],PRIMEM["Reference_Meridian",0],UNIT["degree",0.0174532925199433]],PROJECTION["Equirectangular"],PARAMETER["latitude_of_origin",0],PARAMETER["central_meridian",0],PARAMETER["standard_parallel_1",25],PARAMETER["false_easting",0],PARAMETER["false_northing",0],UNIT["metre",1,AUTHORITY["EPSG","9001"]]]</SRS>
<GeoTransform> -1.8000000000000000e+02, 1.7166137695312500e-04, 0.0000000000000000e+00, 9.0000000000000000e+01, 0.0000000000000000e+00, -1.7166137695312500e-04</GeoTransform>
<VRTRasterBand dataType="Byte" band="1">
<NoDataValue>0</NoDataValue>
<ColorInterp>Red</ColorInterp>
<ComplexSource>
<SourceFilename relativeToVRT="1">Apollo15_PanCam_Slope_25N311E_5mp.wms</SourceFilename>
<SourceBand>1</SourceBand>
<SourceProperties RasterXSize="2097152" RasterYSize="1048576" DataType="Byte" BlockXSize="256" BlockYSize="256" />
<SrcRect xOff="0" yOff="0" xSize="2097152" ySize="1048576" />
<DstRect xOff="0" yOff="0" xSize="2097152" ySize="1048576" />
<NODATA>0</NODATA>
</ComplexSource>
</VRTRasterBand>
<VRTRasterBand dataType="Byte" band="2">
<NoDataValue>0</NoDataValue>
<ColorInterp>Green</ColorInterp>
<ComplexSource>
<SourceFilename relativeToVRT="1">Apollo15_PanCam_Slope_25N311E_5mp.wms</SourceFilename>
<SourceBand>2</SourceBand>
<SourceProperties RasterXSize="2097152" RasterYSize="1048576" DataType="Byte" BlockXSize="256" BlockYSize="256" />
<SrcRect xOff="0" yOff="0" xSize="2097152" ySize="1048576" />
<DstRect xOff="0" yOff="0" xSize="2097152" ySize="1048576" />
<NODATA>0</NODATA>
</ComplexSource>
</VRTRasterBand>
<VRTRasterBand dataType="Byte" band="3">
<NoDataValue>0</NoDataValue>
<ColorInterp>Blue</ColorInterp>
<ComplexSource>
<SourceFilename relativeToVRT="1">Apollo15_PanCam_Slope_25N311E_5mp.wms</SourceFilename>
<SourceBand>3</SourceBand>
<SourceProperties RasterXSize="2097152" RasterYSize="1048576" DataType="Byte" BlockXSize="256" BlockYSize="256" />
<SrcRect xOff="0" yOff="0" xSize="2097152" ySize="1048576" />
<DstRect xOff="0" yOff="0" xSize="2097152" ySize="1048576" />
<NODATA>0</NODATA>
</ComplexSource>
</VRTRasterBand>
<VRTRasterBand dataType="Byte" band="4">
<ColorInterp>Alpha</ColorInterp>
<ComplexSource>
<SourceFilename relativeToVRT="1">Apollo15_PanCam_Slope_25N311E_5mp.wms</SourceFilename>
<SourceBand>1</SourceBand>
<SourceProperties RasterXSize="2097152" RasterYSize="1048576" DataType="Byte" BlockXSize="256" BlockYSize="256" />
<SrcRect xOff="0" yOff="0" xSize="2097152" ySize="1048576" />
<DstRect xOff="0" yOff="0" xSize="2097152" ySize="1048576" />
<ScaleOffset>255</ScaleOffset>
<ScaleRatio>0</ScaleRatio>
<NODATA>0</NODATA>
</ComplexSource>
</VRTRasterBand>
</VRTDataset>
@@ -0,0 +1,24 @@
<GDAL_WMS>
<Service name="TMS">
<ServerUrl>https://trek.nasa.gov/tiles/Moon/EQ/Apollo15_PanCam_Slope_25N311E_5mp/1.0.0//default/default028mm/${z}/${y}/${x}.png</ServerUrl>
</Service>
<DataWindow>
<UpperLeftX>-180</UpperLeftX>
<UpperLeftY>90</UpperLeftY>
<LowerRightX>180</LowerRightX>
<LowerRightY>-90</LowerRightY>
<TileCountX>2</TileCountX>
<TileCountY>1</TileCountY>
<TileLevel>12</TileLevel>
<YOrigin>top</YOrigin>
</DataWindow>
<Projection>
PROJCS["Equirectangular MOON",GEOGCS["GCS_MOON",DATUM["D_MOON",SPHEROID["MOON_localRadius",1737400,0]],PRIMEM["Reference_Meridian",0],UNIT["degree",0.0174532925199433]],PROJECTION["Equirectangular"],PARAMETER["latitude_of_origin",0],PARAMETER["central_meridian",0],PARAMETER["standard_parallel_1",25],PARAMETER["false_easting",0],PARAMETER["false_northing",0],UNIT["metre",1,AUTHORITY["EPSG","9001"]]]
</Projection>
<BlockSizeX>256</BlockSizeX>
<BlockSizeY>256</BlockSizeY>
<BandsCount>3</BandsCount>
<MaxConnections>10</MaxConnections>
<DataValues NoData="0" Min="1" Max="255"/>
<ZeroBlockHttpCodes>404,400</ZeroBlockHttpCodes>
</GDAL_WMS>
@@ -0,0 +1,28 @@
local globeIdentifier = asset.require("scene/solarsystem//planets/earth/moon/moon").Moon.Identifier
local layer = {
Identifier = "Apollo15_PanCam_Slope_25N311E_5mp",
Name = [[Apollo 15 Pan Cam DEM, Aristarchus Plateau 1, Colorized Slope]],
FilePath = asset.localResource("Apollo15_PanCam_Slope_25N311E_5mp.vrt"),
Description = [[]]
}
asset.onInitialize(function()
openspace.globebrowsing.addLayer(globeIdentifier, "ColorLayers", layer)
end)
asset.onDeinitialize(function()
openspace.globebrowsing.deleteLayer(globeIdentifier, "ColorLayers", layer.Identifier)
end)
asset.export("layer", layer)
asset.meta = {
Name = [[Apollo 15 Pan Cam DEM, Aristarchus Plateau 1, Colorized Slope]],
Version = "1.0",
Author = "NASA/Treks",
URL = "https://trek.nasa.gov/moon/#v=0.1&x=0&y=0&z=1&p=urn:ogc:def:crs:EPSG::104903&d=&l=Apollo15_PanCam_Slope_25N311E_5mp%2Ctrue%2C1&b=moon&e=-180.0%2C-90.0%2C180.0%2C90.0&sfv=&w=",
License = "NASA/Treks",
Description = [[Apollo 15 Pan Cam DEM, Aristarchus Plateau 1, Colorized Slope layer from NASA/Treks for Moon]]
}
@@ -0,0 +1,29 @@
<VRTDataset rasterXSize="2097152" rasterYSize="1048576">
<SRS>PROJCS["Equirectangular MOON",GEOGCS["GCS_MOON",DATUM["D_MOON",SPHEROID["MOON_localRadius",1737400,0]],PRIMEM["Reference_Meridian",0],UNIT["degree",0.0174532925199433]],PROJECTION["Equirectangular"],PARAMETER["latitude_of_origin",0],PARAMETER["central_meridian",0],PARAMETER["standard_parallel_1",-2],PARAMETER["false_easting",0],PARAMETER["false_northing",0],UNIT["metre",1,AUTHORITY["EPSG","9001"]]]</SRS>
<GeoTransform> -1.8000000000000000e+02, 1.7166137695312500e-04, 0.0000000000000000e+00, 9.0000000000000000e+01, 0.0000000000000000e+00, -1.7166137695312500e-04</GeoTransform>
<VRTRasterBand dataType="Byte" band="1">
<NoDataValue>0</NoDataValue>
<ColorInterp>Gray</ColorInterp>
<ComplexSource>
<SourceFilename relativeToVRT="1">Apollo15_PanCam_Gray_25N311E_5mp.wms</SourceFilename>
<SourceBand>1</SourceBand>
<SourceProperties RasterXSize="2097152" RasterYSize="1048576" DataType="Byte" BlockXSize="256" BlockYSize="256" />
<SrcRect xOff="0" yOff="0" xSize="2097152" ySize="1048576" />
<DstRect xOff="0" yOff="0" xSize="2097152" ySize="1048576" />
<NODATA>0</NODATA>
</ComplexSource>
</VRTRasterBand>
<VRTRasterBand dataType="Byte" band="2">
<ColorInterp>Alpha</ColorInterp>
<ComplexSource>
<SourceFilename relativeToVRT="1">Apollo15_PanCam_Gray_25N311E_5mp.wms</SourceFilename>
<SourceBand>1</SourceBand>
<SourceProperties RasterXSize="2097152" RasterYSize="1048576" DataType="Byte" BlockXSize="256" BlockYSize="256" />
<SrcRect xOff="0" yOff="0" xSize="2097152" ySize="1048576" />
<DstRect xOff="0" yOff="0" xSize="2097152" ySize="1048576" />
<ScaleOffset>255</ScaleOffset>
<ScaleRatio>0</ScaleRatio>
<NODATA>0</NODATA>
</ComplexSource>
</VRTRasterBand>
</VRTDataset>
@@ -0,0 +1,24 @@
<GDAL_WMS>
<Service name="TMS">
<ServerUrl>https://trek.nasa.gov/tiles/Moon/EQ/Apollo15_PanCam_Gray_25N311E_5mp/1.0.0//default/default028mm/${z}/${y}/${x}.png</ServerUrl>
</Service>
<DataWindow>
<UpperLeftX>-180</UpperLeftX>
<UpperLeftY>90</UpperLeftY>
<LowerRightX>180</LowerRightX>
<LowerRightY>-90</LowerRightY>
<TileCountX>2</TileCountX>
<TileCountY>1</TileCountY>
<TileLevel>12</TileLevel>
<YOrigin>top</YOrigin>
</DataWindow>
<Projection>
PROJCS["Equirectangular MOON",GEOGCS["GCS_MOON",DATUM["D_MOON",SPHEROID["MOON_localRadius",1737400,0]],PRIMEM["Reference_Meridian",0],UNIT["degree",0.0174532925199433]],PROJECTION["Equirectangular"],PARAMETER["latitude_of_origin",0],PARAMETER["central_meridian",0],PARAMETER["standard_parallel_1",-2],PARAMETER["false_easting",0],PARAMETER["false_northing",0],UNIT["metre",1,AUTHORITY["EPSG","9001"]]]
</Projection>
<BlockSizeX>256</BlockSizeX>
<BlockSizeY>256</BlockSizeY>
<BandsCount>1</BandsCount>
<MaxConnections>10</MaxConnections>
<DataValues NoData="0" Min="1" Max="255"/>
<ZeroBlockHttpCodes>404,400</ZeroBlockHttpCodes>
</GDAL_WMS>
@@ -0,0 +1,28 @@
local globeIdentifier = asset.require("scene/solarsystem//planets/earth/moon/moon").Moon.Identifier
local layer = {
Identifier = "Apollo15_PanCam_Gray_25N311E_5mp",
Name = [[Apollo 15 Pan Cam DEM, Aristarchus Plateau 1, Grayscale]],
FilePath = asset.localResource("Apollo15_PanCam_Gray_25N311E_5mp.vrt"),
Description = [[]]
}
asset.onInitialize(function()
openspace.globebrowsing.addLayer(globeIdentifier, "ColorLayers", layer)
end)
asset.onDeinitialize(function()
openspace.globebrowsing.deleteLayer(globeIdentifier, "ColorLayers", layer.Identifier)
end)
asset.export("layer", layer)
asset.meta = {
Name = [[Apollo 15 Pan Cam DEM, Aristarchus Plateau 1, Grayscale]],
Version = "1.0",
Author = "NASA/Treks",
URL = "https://trek.nasa.gov/moon/#v=0.1&x=0&y=0&z=1&p=urn:ogc:def:crs:EPSG::104903&d=&l=Apollo15_PanCam_Gray_25N311E_5mp%2Ctrue%2C1&b=moon&e=-180.0%2C-90.0%2C180.0%2C90.0&sfv=&w=",
License = "NASA/Treks",
Description = [[Apollo 15 Pan Cam DEM, Aristarchus Plateau 1, Grayscale layer from NASA/Treks for Moon]]
}
@@ -0,0 +1,29 @@
<VRTDataset rasterXSize="2097152" rasterYSize="1048576">
<SRS>PROJCS["Equirectangular MOON",GEOGCS["GCS_MOON",DATUM["D_MOON",SPHEROID["MOON_localRadius",1737400,0]],PRIMEM["Reference_Meridian",0],UNIT["degree",0.0174532925199433]],PROJECTION["Equirectangular"],PARAMETER["latitude_of_origin",0],PARAMETER["central_meridian",0],PARAMETER["standard_parallel_1",25],PARAMETER["false_easting",0],PARAMETER["false_northing",0],UNIT["metre",1,AUTHORITY["EPSG","9001"]]]</SRS>
<GeoTransform> -1.8000000000000000e+02, 1.7166137695312500e-04, 0.0000000000000000e+00, 9.0000000000000000e+01, 0.0000000000000000e+00, -1.7166137695312500e-04</GeoTransform>
<VRTRasterBand dataType="Byte" band="1">
<NoDataValue>0</NoDataValue>
<ColorInterp>Gray</ColorInterp>
<ComplexSource>
<SourceFilename relativeToVRT="1">Apollo15_PanCam_Shade_25N311E_5mp.wms</SourceFilename>
<SourceBand>1</SourceBand>
<SourceProperties RasterXSize="2097152" RasterYSize="1048576" DataType="Byte" BlockXSize="256" BlockYSize="256" />
<SrcRect xOff="0" yOff="0" xSize="2097152" ySize="1048576" />
<DstRect xOff="0" yOff="0" xSize="2097152" ySize="1048576" />
<NODATA>0</NODATA>
</ComplexSource>
</VRTRasterBand>
<VRTRasterBand dataType="Byte" band="2">
<ColorInterp>Alpha</ColorInterp>
<ComplexSource>
<SourceFilename relativeToVRT="1">Apollo15_PanCam_Shade_25N311E_5mp.wms</SourceFilename>
<SourceBand>1</SourceBand>
<SourceProperties RasterXSize="2097152" RasterYSize="1048576" DataType="Byte" BlockXSize="256" BlockYSize="256" />
<SrcRect xOff="0" yOff="0" xSize="2097152" ySize="1048576" />
<DstRect xOff="0" yOff="0" xSize="2097152" ySize="1048576" />
<ScaleOffset>255</ScaleOffset>
<ScaleRatio>0</ScaleRatio>
<NODATA>0</NODATA>
</ComplexSource>
</VRTRasterBand>
</VRTDataset>
@@ -0,0 +1,24 @@
<GDAL_WMS>
<Service name="TMS">
<ServerUrl>https://trek.nasa.gov/tiles/Moon/EQ/Apollo15_PanCam_Shade_25N311E_5mp/1.0.0//default/default028mm/${z}/${y}/${x}.png</ServerUrl>
</Service>
<DataWindow>
<UpperLeftX>-180</UpperLeftX>
<UpperLeftY>90</UpperLeftY>
<LowerRightX>180</LowerRightX>
<LowerRightY>-90</LowerRightY>
<TileCountX>2</TileCountX>
<TileCountY>1</TileCountY>
<TileLevel>12</TileLevel>
<YOrigin>top</YOrigin>
</DataWindow>
<Projection>
PROJCS["Equirectangular MOON",GEOGCS["GCS_MOON",DATUM["D_MOON",SPHEROID["MOON_localRadius",1737400,0]],PRIMEM["Reference_Meridian",0],UNIT["degree",0.0174532925199433]],PROJECTION["Equirectangular"],PARAMETER["latitude_of_origin",0],PARAMETER["central_meridian",0],PARAMETER["standard_parallel_1",25],PARAMETER["false_easting",0],PARAMETER["false_northing",0],UNIT["metre",1,AUTHORITY["EPSG","9001"]]]
</Projection>
<BlockSizeX>256</BlockSizeX>
<BlockSizeY>256</BlockSizeY>
<BandsCount>1</BandsCount>
<MaxConnections>10</MaxConnections>
<DataValues NoData="0" Min="1" Max="255"/>
<ZeroBlockHttpCodes>404,400</ZeroBlockHttpCodes>
</GDAL_WMS>

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