Merging master in to sync with new release

This commit is contained in:
GPayne
2022-05-12 14:59:15 -06:00
3111 changed files with 102378 additions and 6391 deletions

View File

@@ -9,7 +9,3 @@ charset = utf-8
indent_style = space
indent_size = 4
insert_final_newline = true
# overwrite default settings here, for instance like this:
# [*.cpp]
# indent_style = tabs

View File

@@ -29,7 +29,7 @@ project(OpenSpace)
set(OPENSPACE_VERSION_MAJOR 0)
set(OPENSPACE_VERSION_MINOR 18)
set(OPENSPACE_VERSION_PATCH 0)
set(OPENSPACE_VERSION_STRING "Beta-11 (RC1)")
set(OPENSPACE_VERSION_STRING "Beta-11")
set(OPENSPACE_BASE_DIR "${PROJECT_SOURCE_DIR}")
set(OPENSPACE_CMAKE_EXT_DIR "${OPENSPACE_BASE_DIR}/support/cmake")

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)

View File

@@ -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:
/**

View File

@@ -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:

View File

@@ -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__

View File

@@ -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__

View File

@@ -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__

View File

@@ -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
*/

View File

@@ -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;
};

View File

@@ -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__

View File

@@ -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(qint64 ist, qint64 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__

View File

@@ -27,7 +27,7 @@
#include <QFrame>
class Line : public QFrame {
class Line final : public QFrame {
public:
Line();
};

View File

@@ -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__

View File

@@ -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__

View File

@@ -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__

View File

@@ -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__

View File

@@ -22,32 +22,35 @@
* 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>
#include <QListWidget>
class QLineEdit;
class QListWidget;
class QPushButton;
class ScriptlogDialog final : public QDialog {
Q_OBJECT
public:
/**
* Constructor for ScriptlogDialog class
*
* \param parent Pointer to parent Qt widget
*/
ScriptlogDialog(QWidget* parent);
signals:
void scriptsSelected(std::string script);
private slots:
void saveChosenScripts();
private:
void createWidgets();
void loadScriptFile();
void saveChosenScripts();
void updateScriptList();
QListWidget* _scriptlogList = nullptr;
QLineEdit* _filter = nullptr;
QPushButton* _reloadFile = nullptr;
std::vector<std::string> _scripts;
};
#endif // __OPENSPACE_UI_LAUNCHER___SCRIPTLOG___H__
#endif // __OPENSPACE_UI_LAUNCHER___SCRIPTLOGDIALOG___H__

View File

@@ -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__

View File

@@ -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__

View File

@@ -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__

View File

@@ -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__

View File

@@ -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;

View File

@@ -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__

View File

@@ -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__

View File

@@ -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__

View File

@@ -149,25 +149,41 @@ CameraDialog QLabel#error-message {
min-width: 10em;
}
/*
* ScriptlogDialog
*/
ScriptlogDialog QListWidget {
min-width: 60em;
}
/*
* Horizons dialog
*/
QPlainTextEdit#log {
HorizonsDialog QPlainTextEdit#log {
font-family: Courier;
}
QComboBox#mono {
HorizonsDialog QComboBox#mono {
font-family: Courier;
}
QLabel#thin {
HorizonsDialog QLabel#thin {
font-weight: normal;
}
QLabel#error {
HorizonsDialog QLabel#error {
color: rgb(221, 17, 17);
}
QLabel#normal {
HorizonsDialog QLabel#normal {
color: rgb(0, 0, 0);
}
/*
* SGCT
*/
WindowControl QLabel#info {
font-style: italic;
font-weight: normal;
font-size: 8pt;
}

View File

@@ -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;
@@ -395,7 +395,9 @@ void LauncherWindow::populateProfilesList(std::string preset) {
}
_profileBox->addItem(QString::fromStdString("--- User Profiles ---"));
const QStandardItemModel* model = qobject_cast<const QStandardItemModel*>(_profileBox->model());
const QStandardItemModel* model = qobject_cast<const QStandardItemModel*>(
_profileBox->model()
);
model->item(_userAssetCount)->setEnabled(false);
++_userAssetCount;
@@ -410,7 +412,10 @@ void LauncherWindow::populateProfilesList(std::string preset) {
}
std::sort(profiles.begin(), profiles.end());
for (const fs::directory_entry& p : profiles) {
_profileBox->addItem(QString::fromStdString(p.path().stem().string()));
_profileBox->addItem(
QString::fromStdString(p.path().stem().string()),
QString::fromStdString(p.path().string())
);
}
_profileBox->addItem(QString::fromStdString("--- OpenSpace Profiles ---"));
@@ -427,16 +432,33 @@ 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()));
std::string abc = profile.path().string();
_profileBox->addItem(
QString::fromStdString(profile.path().stem().string()),
QString::fromStdString(profile.path().string())
);
}
// Try to find the requested profile and set it as the current one
const int idx = _profileBox->findText(QString::fromStdString(std::move(preset)));
if (idx != -1) {
_profileBox->setCurrentIndex(idx);
int idx = _profileBox->findText(QString::fromStdString(preset));
if (idx == -1) {
// We didn't find the preset, so the user probably specified a path in the
// configuration file that doesn't match any value in the list
_profileBox->addItem(QString::fromStdString("--- Configuration File ---"));
model = qobject_cast<const QStandardItemModel*>(_profileBox->model());
model->item(_profileBox->count() - 1)->setEnabled(false);
_profileBox->addItem(
QString::fromStdString(preset),
QString::fromStdString(preset)
);
idx = _profileBox->count() - 1;
}
_profileBox->setCurrentIndex(idx);
}
// Returns 'true' if the file was a configuration file, 'false' otherwise
@@ -471,7 +493,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 +514,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 +544,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 +556,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 +568,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 +580,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 +605,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);
}
}
@@ -618,14 +623,16 @@ bool LauncherWindow::wasLaunchSelected() const {
}
std::string LauncherWindow::selectedProfile() const {
return _profileBox->currentText().toStdString();
// The user data stores the full path to the profile
return _profileBox->currentData().toString().toStdString();
}
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 {

View File

@@ -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);
@@ -485,9 +485,15 @@ void ActionDialog::actionRemove() {
for (size_t i = 0; i < _actionData.size(); ++i) {
if (_actionData[i].identifier == action->identifier) {
clearActionFields();
_actionData.erase(_actionData.begin() + i);
delete _actionWidgets.list->takeItem(static_cast<int>(i));
clearActionFields();
_keybindingWidgets.action->clear();
for (const Profile::Action& a : _actionData) {
_keybindingWidgets.action->addItem(QString::fromStdString(a.identifier));
}
clearKeybindingFields();
return;
}
}
@@ -587,6 +593,13 @@ void ActionDialog::actionSaved() {
action->script = _actionWidgets.script->toPlainText().toStdString();
updateListItem(_actionWidgets.list->currentItem(), *action);
// Update the list of actions available in the action chooser
_keybindingWidgets.action->clear();
for (const Profile::Action& a : _actionData) {
_keybindingWidgets.action->addItem(QString::fromStdString(a.identifier));
}
clearKeybindingFields();
clearActionFields();
}
@@ -648,9 +661,9 @@ void ActionDialog::keybindingRemove() {
if (_keybindingsData[i].key == keybinding->key &&
_keybindingsData[i].action == keybinding->action)
{
clearKeybindingFields();
_keybindingsData.erase(_keybindingsData.begin() + i);
delete _keybindingWidgets.list->takeItem(static_cast<int>(i));
clearKeybindingFields();
return;
}
}

View File

@@ -102,7 +102,10 @@ void AdditionalScriptsDialog::parseScript() {
void AdditionalScriptsDialog::chooseScripts() {
ScriptlogDialog d(this);
connect(&d, &ScriptlogDialog::scriptsSelected, this, &AdditionalScriptsDialog::appendScriptsToTextfield);
connect(
&d, &ScriptlogDialog::scriptsSelected,
this, &AdditionalScriptsDialog::appendScriptsToTextfield
);
d.exec();
}

View File

@@ -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();
}

View File

@@ -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

View File

@@ -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) {

View File

@@ -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, "");
}

View File

@@ -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();

View File

@@ -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;
}
}

View File

@@ -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(qint64 value, qint64 total) {
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

View File

@@ -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);
}

View File

@@ -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);
}

View File

@@ -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");

View File

@@ -23,15 +23,21 @@
****************************************************************************************/
#include "profile/scriptlogdialog.h"
#include "profile/line.h"
#include <openspace/engine/configuration.h>
#include <openspace/engine/globals.h>
#include <openspace/scene/profile.h>
#include <ghoul/filesystem/filesystem.h>
#include <ghoul/fmt.h>
#include <QGridLayout>
#include <QDialogButtonBox>
#include <QLabel>
#include <QLineEdit>
#include <QListWidget>
#include <QFile>
#include <QPushButton>
#include <QTextStream>
#include <QVBoxLayout>
ScriptlogDialog::ScriptlogDialog(QWidget* parent)
: QDialog(parent)
@@ -39,32 +45,43 @@ ScriptlogDialog::ScriptlogDialog(QWidget* parent)
setWindowTitle("Scriptlog");
createWidgets();
QFile file(QString::fromStdString(absPath("${LOGS}/scriptLog.txt").string()));
if (file.open(QIODevice::ReadOnly | QIODevice::Text)) {
QTextStream in(&file);
while (!in.atEnd()) {
QString line = in.readLine();
// removing return from a few statments
// these are usually generated by gui panels
line.remove(QRegularExpression("^return "));
if (!line.isEmpty()) {
_scriptlogList->addItem(line);
}
}
}
loadScriptFile();
}
void ScriptlogDialog::createWidgets() {
QBoxLayout* layout = new QVBoxLayout(this);
// Column 0 Column 1
// *-------------------------*------------*
// | Title |
// *--------------------------------------*
// | Filter scripts * Reload |
// *--------------------------------------*
// | Script list |
// *--------------------------------------*
// * Save Cancel *
// *-------------------------*------------*
QGridLayout* layout = new QGridLayout(this);
{
QLabel* heading = new QLabel("Choose commands from log/scriptLog.txt");
QLabel* heading = new QLabel(QString::fromStdString(fmt::format(
"Choose commands from \"{}\"", openspace::global::configuration->scriptLog
)));
heading->setObjectName("heading");
layout->addWidget(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);
layout->addWidget(_filter, 1, 0);
_reloadFile = new QPushButton("Reload");
_reloadFile->setToolTip("Reload the script log file");
connect(_reloadFile, &QPushButton::clicked, this, &ScriptlogDialog::loadScriptFile);
layout->addWidget(_reloadFile, 1, 1);
_scriptlogList = new QListWidget;
_scriptlogList->setSelectionMode(QAbstractItemView::SelectionMode::MultiSelection);
layout->addWidget(_scriptlogList);
layout->addWidget(_scriptlogList, 2, 0, 1, 2);
layout->addWidget(new Line);
{
@@ -78,10 +95,47 @@ void ScriptlogDialog::createWidgets() {
buttons, &QDialogButtonBox::rejected,
this, &ScriptlogDialog::reject
);
layout->addWidget(buttons);
layout->addWidget(buttons, 3, 0, 1, 2);
}
}
void ScriptlogDialog::loadScriptFile() {
std::string log = absPath(openspace::global::configuration->scriptLog).string();
QFile file(QString::fromStdString(log));
if (file.open(QIODevice::ReadOnly | QIODevice::Text)) {
QTextStream in(&file);
while (!in.atEnd()) {
QString line = in.readLine();
// removing return from statements which are usually generated by gui panels
line.remove(QRegularExpression("^return "));
if (!line.isEmpty()) {
_scripts.push_back(line.toStdString());
}
}
}
updateScriptList();
}
void ScriptlogDialog::updateScriptList() {
std::string filter = _filter->text().toStdString();
QListWidgetItem* curr = _scriptlogList->currentItem();
std::string selection;
if (curr) {
selection = curr->text().toStdString();
}
int index = -1;
_scriptlogList->clear();
for (const std::string& script : _scripts) {
if (script.find(filter) != std::string::npos) {
if (script == selection && index == -1) {
index = _scriptlogList->count();
}
_scriptlogList->addItem(QString::fromStdString(script));
}
}
_scriptlogList->setCurrentRow(index != -1 ? index : 0);
}
void ScriptlogDialog::saveChosenScripts() {
std::string chosenScripts;
QList<QListWidgetItem*> itemList = _scriptlogList->selectedItems();

View File

@@ -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)"

View File

@@ -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++;
}
}

View File

@@ -1,291 +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;
}
break;
case WindowControl::ProjectionIndeces::SphericalMirror:
{
sgct::config::SphericalMirrorProjection projection;
projection.quality = winControl->qualitySelectedValue();
return projection;
}
break;
case WindowControl::ProjectionIndeces::Cylindrical:
{
sgct::config::CylindricalProjection projection;
projection.quality = winControl->qualitySelectedValue();
projection.heightOffset = winControl->heightOffset();
return projection;
}
break;
case WindowControl::ProjectionIndeces::Equirectangular:
{
sgct::config::EquirectangularProjection projection;
projection.quality = winControl->qualitySelectedValue();
return projection;
}
break;
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;
}
break;
}
}
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();
}

View File

@@ -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();
}

View File

@@ -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();
}

View File

@@ -0,0 +1,82 @@
/*****************************************************************************************
* *
* 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/settingswidget.h"
#include "sgctedit/orientationdialog.h"
#include <QCheckBox>
#include <QPushButton>
#include <QVBoxLayout>
SettingsWidget::SettingsWidget(sgct::quat orientation, QWidget* parent)
: QWidget(parent)
, _orientationValue(std::move(orientation))
{
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();
}
);
}
sgct::quat SettingsWidget::orientation() const {
return _orientationValue;
}
bool SettingsWidget::vsync() const {
return _checkBoxVsync->isChecked();
}
bool SettingsWidget::showUiOnFirstWindow() const {
return _showUiOnFirstWindow->isChecked();
}

View File

@@ -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(),
actualWidth,
actualHeight
});
}
_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

View File

@@ -207,6 +207,71 @@ LONG WINAPI generateMiniDump(EXCEPTION_POINTERS* exceptionPointers) {
}
#endif // WIN32
void checkJoystickStatus() {
using namespace interaction;
for (int i = GLFW_JOYSTICK_1; i <= GLFW_JOYSTICK_LAST; ++i) {
ZoneScopedN("Joystick state");
JoystickInputState& state = global::joystickInputStates->at(i);
int present = glfwJoystickPresent(i);
if (present == GLFW_FALSE) {
state.isConnected = false;
continue;
}
if (!state.isConnected) {
// Joystick was added
state.isConnected = true;
state.name = glfwGetJoystickName(i);
std::fill(state.axes.begin(), state.axes.end(), 0.f);
std::fill(state.buttons.begin(), state.buttons.end(), JoystickAction::Idle);
// Check axes and buttons
glfwGetJoystickAxes(i, &state.nAxes);
glfwGetJoystickButtons(i, &state.nButtons);
}
const float* axes = glfwGetJoystickAxes(i, &state.nAxes);
state.axes.resize(state.nAxes);
std::memcpy(state.axes.data(), axes, state.nAxes * sizeof(float));
const unsigned char* buttons = glfwGetJoystickButtons(i, &state.nButtons);
state.buttons.resize(state.nButtons);
for (int j = 0; j < state.nButtons; ++j) {
const bool currentlyPressed = buttons[j] == GLFW_PRESS;
if (currentlyPressed) {
switch (state.buttons[j]) {
case JoystickAction::Idle:
case JoystickAction::Release:
state.buttons[j] = JoystickAction::Press;
break;
case JoystickAction::Press:
case JoystickAction::Repeat:
state.buttons[j] = JoystickAction::Repeat;
break;
}
}
else {
switch (state.buttons[j]) {
case JoystickAction::Idle:
case JoystickAction::Release:
state.buttons[j] = JoystickAction::Idle;
break;
case JoystickAction::Press:
case JoystickAction::Repeat:
state.buttons[j] = JoystickAction::Release;
break;
}
}
}
}
}
//
// Init function
//
@@ -319,6 +384,9 @@ void mainInitFunc(GLFWwindow*) {
#endif // OPENSPACE_HAS_SPOUT
}
// Query joystick status, those connected before start up
checkJoystickStatus();
LTRACE("main::mainInitFunc(end)");
}
@@ -336,87 +404,8 @@ void mainPreSyncFunc() {
Engine::instance().terminate();
}
// Query joystick status
using namespace interaction;
for (int i = GLFW_JOYSTICK_1; i <= GLFW_JOYSTICK_LAST; ++i) {
ZoneScopedN("Joystick state");
JoystickInputState& state = global::joystickInputStates->at(i);
int present = glfwJoystickPresent(i);
if (present == GLFW_FALSE) {
state.isConnected = false;
continue;
}
if (!state.isConnected) {
// Joystick was added
state.isConnected = true;
state.name = glfwGetJoystickName(i);
std::fill(state.axes.begin(), state.axes.end(), 0.f);
std::fill(state.buttons.begin(), state.buttons.end(), JoystickAction::Idle);
// Check axes and buttons
glfwGetJoystickAxes(i, &state.nAxes);
if (state.nAxes > JoystickInputState::MaxAxes) {
LWARNING(fmt::format(
"Joystick/Gamepad {} has {} axes, but only {} axes are supported. "
"All excess axes are ignored",
state.name, state.nAxes, JoystickInputState::MaxAxes
));
}
glfwGetJoystickButtons(i, &state.nButtons);
if (state.nButtons > JoystickInputState::MaxButtons) {
LWARNING(fmt::format(
"Joystick/Gamepad {} has {} buttons, but only {} buttons are "
"supported. All excess buttons are ignored",
state.name, state.nButtons, JoystickInputState::MaxButtons
));
}
}
const float* axes = glfwGetJoystickAxes(i, &state.nAxes);
if (state.nAxes > JoystickInputState::MaxAxes) {
state.nAxes = JoystickInputState::MaxAxes;
}
std::memcpy(state.axes.data(), axes, state.nAxes * sizeof(float));
const unsigned char* buttons = glfwGetJoystickButtons(i, &state.nButtons);
if (state.nButtons > JoystickInputState::MaxButtons) {
state.nButtons = JoystickInputState::MaxButtons;
}
for (int j = 0; j < state.nButtons; ++j) {
const bool currentlyPressed = buttons[j] == GLFW_PRESS;
if (currentlyPressed) {
switch (state.buttons[j]) {
case JoystickAction::Idle:
case JoystickAction::Release:
state.buttons[j] = JoystickAction::Press;
break;
case JoystickAction::Press:
case JoystickAction::Repeat:
state.buttons[j] = JoystickAction::Repeat;
break;
}
}
else {
switch (state.buttons[j]) {
case JoystickAction::Idle:
case JoystickAction::Release:
state.buttons[j] = JoystickAction::Idle;
break;
case JoystickAction::Press:
case JoystickAction::Repeat:
state.buttons[j] = JoystickAction::Release;
break;
}
}
}
}
// Query joystick status, those connected at run time
checkJoystickStatus();
LTRACE("main::mainPreSyncFunc(end)");
}

View File

@@ -12,6 +12,22 @@
"address": "localhost",
"port": 20401,
"windows": [
{
"fullscreen": false,
"border": false,
"name": "GUI",
"tags": [ "GUI" ],
"draw3d": false,
"stereo": "none",
"pos": { "x": 0, "y": 0 },
"size": { "x": 1920, "y": 1080 },
"viewports": [
{
"pos": { "x": 0.0, "y": 0.0 },
"size": { "x": 1.0, "y": 1.0 }
}
]
},
{
"fullscreen": true,
"monitor": 1,
@@ -35,22 +51,6 @@
}
}
]
},
{
"fullscreen": false,
"border": false,
"name": "GUI",
"tags": [ "GUI" ],
"draw3d": false,
"stereo": "none",
"pos": { "x": 0, "y": 0 },
"size": { "x": 1920, "y": 1080 },
"viewports": [
{
"pos": { "x": 0.0, "y": 0.0 },
"size": { "x": 1.0, "y": 1.0 }
}
]
}
]
}

View File

@@ -6,26 +6,6 @@
"address": "localhost",
"port": 20401,
"windows": [
{
"name": "OpenSpace",
"fullscreen": false,
"draw2d": false,
"stereo": "none",
"size": { "x": 1024, "y": 1024 },
"viewports": [
{
"pos": { "x": 0.0, "y": 0.0 },
"size": { "x": 1.0, "y": 1.0 },
"projection": {
"type": "FisheyeProjection",
"fov": 180.0,
"quality": "1k",
"tilt": 27.0,
"background": { "r": 0.1, "g": 0.1, "b": 0.1, "a": 1.0 }
}
}
]
},
{
"name": "GUI",
"tags": [ "GUI" ],
@@ -48,6 +28,26 @@
}
}
]
},
{
"name": "OpenSpace",
"fullscreen": false,
"draw2d": false,
"stereo": "none",
"size": { "x": 1024, "y": 1024 },
"viewports": [
{
"pos": { "x": 0.0, "y": 0.0 },
"size": { "x": 1.0, "y": 1.0 },
"projection": {
"type": "FisheyeProjection",
"fov": 180.0,
"quality": "1k",
"tilt": 27.0,
"background": { "r": 0.1, "g": 0.1, "b": 0.1, "a": 1.0 }
}
}
]
}
]
}

View File

@@ -13,15 +13,15 @@
"port": 20401,
"windows": [
{
"name": "OpenSpace",
"name": "GUI",
"tags": [ "GUI" ],
"fullscreen": false,
"draw2d": false,
"draw3d": false,
"stereo": "none",
"pos": { "x": 50, "y": 50 },
"size": { "x": 1280, "y": 720 },
"viewports": [
{
"tracked": true,
"pos": { "x": 0.0, "y": 0.0 },
"size": { "x": 1.0, "y": 1.0 },
"projection": {
@@ -36,15 +36,15 @@
]
},
{
"name": "GUI",
"tags": [ "GUI" ],
"name": "OpenSpace",
"fullscreen": false,
"draw3d": false,
"draw2d": false,
"stereo": "none",
"pos": { "x": 50, "y": 50 },
"size": { "x": 1280, "y": 720 },
"viewports": [
{
"tracked": true,
"pos": { "x": 0.0, "y": 0.0 },
"size": { "x": 1.0, "y": 1.0 },
"projection": {

View File

@@ -12,6 +12,27 @@
"address": "localhost",
"port": 20401,
"windows": [
{
"name": "GUI",
"pos": { "x": 50, "y": 50 },
"size": { "x": 1280, "y": 720 },
"stereo": "none",
"tags": [ "GUI" ],
"viewports": [
{
"pos": { "x": 0.0, "y": 0.0 },
"size": { "x": 1.0, "y": 1.0 },
"projection": {
"type": "PlanarProjection",
"fov": {
"hfov": 80.0,
"vfov": 50.53401565551758
},
"orientation": { "yaw": 0.0, "pitch": 0.0, "roll": 0.0 }
}
}
]
},
{
"name": "OpenSpace",
"pos": { "x": 50, "y": 50 },
@@ -33,27 +54,6 @@
}
}
]
},
{
"name": "GUI",
"pos": { "x": 50, "y": 50 },
"size": { "x": 1280, "y": 720 },
"stereo": "none",
"tags": [ "GUI" ],
"viewports": [
{
"pos": { "x": 0.0, "y": 0.0 },
"size": { "x": 1.0, "y": 1.0 },
"projection": {
"type": "PlanarProjection",
"fov": {
"hfov": 80.0,
"vfov": 50.53401565551758
},
"orientation": { "yaw": 0.0, "pitch": 0.0, "roll": 0.0 }
}
}
]
}
]
}

View File

@@ -6,29 +6,6 @@
"address": "127.0.0.1",
"port": 20401,
"windows": [
{
"fullscreen": false,
"name": "Spherical Projection",
"stereo": "none",
"draw2d": false,
"pos": { "x": 0, "y": 100 },
"size": { "x": 1280, "y": 720 },
"res": { "x": 2048, "y": 2048 },
"viewports": [
{
"mesh": "mesh/standard_16x9.data",
"pos": { "x": 0.0, "y": 0.0 },
"size": { "x": 1.0, "y": 1.0 },
"projection": {
"type": "FisheyeProjection",
"fov": 180.0,
"quality": "2k",
"tilt": 30.0,
"background": { "r": 0.1, "g": 0.1, "b": 0.1, "a": 1.0 }
}
}
]
},
{
"fullscreen": false,
"name": "GUI",
@@ -52,6 +29,29 @@
}
}
]
},
{
"fullscreen": false,
"name": "Spherical Projection",
"stereo": "none",
"draw2d": false,
"pos": { "x": 0, "y": 100 },
"size": { "x": 1280, "y": 720 },
"res": { "x": 2048, "y": 2048 },
"viewports": [
{
"mesh": "mesh/standard_16x9.data",
"pos": { "x": 0.0, "y": 0.0 },
"size": { "x": 1.0, "y": 1.0 },
"projection": {
"type": "FisheyeProjection",
"fov": 180.0,
"quality": "2k",
"tilt": 30.0,
"background": { "r": 0.1, "g": 0.1, "b": 0.1, "a": 1.0 }
}
}
]
}
]
}

View File

@@ -0,0 +1,89 @@
local ctx_enable_action = {
Identifier = "os.mars.ctx.fadein",
Name = "Fade in CTX",
Command = [[
openspace.setPropertyValueSingle("Scene.Mars.Renderable.Layers.ColorLayers.CTX_blended_01.Enabled", true)
openspace.setPropertyValueSingle("Scene.Mars.Renderable.Layers.ColorLayers.CTX_blended_01.Settings.Opacity", 0)
openspace.setPropertyValueSingle("Scene.Mars.Renderable.Layers.ColorLayers.CTX_blended_01.Settings.Opacity", 1, 2.0)]],
Documentation = "Enables and fades in CTX layer for Mars",
GuiPath = "/Solar System/Mars",
IsLocal = true
}
asset.export("ctx_enable_action", ctx_enable_action.Identifier)
local ctx_disable_action = {
Identifier = "os.mars.ctx.fadedout",
Name = "Fade out CTX Layer",
Command = [[openspace.setPropertyValueSingle("Scene.Mars.Renderable.Layers.ColorLayers.CTX_blended_01.Settings.Opacity", 0, 2.0)]],
Documentation = "Fade out CTX",
GuiPath = "/Solar System/Mars",
IsLocal = true
}
asset.export("ctx_disable_action", ctx_disable_action.Identifier)
local hirise_enable_action = {
Identifier = "os.mars.hirise.fadein",
Name = "Fade in HiRISE",
Command = [[
openspace.setPropertyValueSingle("Scene.Mars.Renderable.Layers.ColorLayers.HiRISE-PSP.Enabled", true)
openspace.setPropertyValueSingle("Scene.Mars.Renderable.Layers.ColorLayers.HiRISE-PSP.Settings.Opacity", 0)
openspace.setPropertyValueSingle("Scene.Mars.Renderable.Layers.ColorLayers.HiRISE-PSP.Settings.Opacity", 1, 2.0)]],
Documentation = "Enables and fades in HiRise layer for Mars",
GuiPath = "/Solar System/Mars",
IsLocal = true
}
asset.export("hirise_enable_action", hirise_enable_action.Identifier)
local hirise_disable_action = {
Identifier = "os.mars.hirise.fadedout",
Name = "Fade out HiRISE",
Command = [[openspace.setPropertyValueSingle("Scene.Mars.Renderable.Layers.ColorLayers.HiRISE-PSP.Settings.Opacity", 0, 2.0)]],
Documentation = "Fade out HiRISE layer for Mars",
GuiPath = "/Solar System/Mars",
IsLocal = true
}
asset.export("hirise_disable_action", hirise_disable_action.Identifier)
local lshirise_enable_action = {
Identifier = "os.mars.lshirise.fadein",
Name = "Fade in HiRISE Local Set",
Command = [[
openspace.setPropertyValueSingle("Scene.Mars.Renderable.Layers.ColorLayers.HiRISE-LS.Enabled", true)
openspace.setPropertyValueSingle("Scene.Mars.Renderable.Layers.HeightLayers.HiRISE-LS-DEM.Enabled", true)
openspace.setPropertyValueSingle("Scene.Mars.Renderable.Layers.ColorLayers.HiRISE-LS.Settings.Opacity", 0)
openspace.setPropertyValueSingle("Scene.Mars.Renderable.Layers.ColorLayers.HiRISE-LS.Settings.Opacity", 1, 2.0)]],
Documentation = "Enables and fades in HiRise local set layers for Mars (including height)",
GuiPath = "/Solar System/Mars",
IsLocal = true
}
asset.export("lshirise_enable_action", lshirise_enable_action.Identifier)
local lshirise_disable_action = {
Identifier = "os.mars.lshirise.fadedout",
Name = "Fade out HiRISE Local Set",
Command = [[openspace.setPropertyValueSingle("Scene.Mars.Renderable.Layers.ColorLayers.HiRISE-LS.Settings.Opacity", 0, 2.0)
openspace.setPropertyValueSingle("Scene.Mars.Renderable.Layers.HeightLayers.HiRISE-LS-DEM.Enabled", false)]],
Documentation = "Fade out HiRISE local set layer for Mars",
GuiPath = "/Solar System/Mars",
IsLocal = true
}
asset.export("lshirise_disable_action", lshirise_disable_action.Identifier)
asset.onInitialize(function()
openspace.action.registerAction(ctx_enable_action)
openspace.action.registerAction(ctx_disable_action)
openspace.action.registerAction(hirise_enable_action)
openspace.action.registerAction(hirise_disable_action)
openspace.action.registerAction(lshirise_enable_action)
openspace.action.registerAction(lshirise_disable_action)
end)
asset.onDeinitialize(function()
openspace.action.removeAction(lshirise_disable_action)
openspace.action.removeAction(lshirise_enable_action)
openspace.action.removeAction(hirise_disable_action)
openspace.action.removeAction(hirise_enable_action)
openspace.action.removeAction(ctx_disable_action)
openspace.action.removeAction(ctx_enable_action)
end)

View File

@@ -0,0 +1,126 @@
local function getIlluminationCommand(node, global)
local commandString = "local node = \"" .. node .. "\"\n"
if (node == "Current Focus") then
commandString = "local node = openspace.navigation.getNavigationState().Anchor\n"
end
if (global) then
commandString = commandString .. [[
if (openspace.hasProperty("Scene."..node..".Renderable.UseAccurateNormals")) then
local list = openspace.getProperty("Scene." .. node .. ".Renderable.Layers.NightLayers.*.Enabled")
if (#list > 0) then
openspace.setPropertyValue("Scene." .. node .. ".Renderable.Layers.NightLayers.*.Enabled", false)
else
openspace.setPropertyValueSingle("Scene." .. node .. ".Renderable.PerformShading", false)
end
if openspace.hasSceneGraphNode(node .. "Atmosphere") then
openspace.setPropertyValueSingle("Scene." .. node .. "Atmosphere.Renderable.SunFollowingCamera", true)
end
if openspace.hasProperty("Scene." .. node .. ".Renderable.ShadowsComponent.DistanceFraction") then
openspace.setPropertyValueSingle("Scene." .. node .. ".Renderable.ShadowsComponent.DistanceFraction", 3000)
end
else
openspace.printWarning("Illumination action only available for globes")
end]]
else
--todo @micahnyc this 40 wont do once we have more rings
commandString = commandString .. [[if (openspace.hasProperty("Scene."..node..".Renderable.UseAccurateNormals")) then
local list = openspace.getProperty("Scene." .. node .. ".Renderable.Layers.NightLayers.*.Enabled")
if (#list > 0) then
openspace.setPropertyValue(list[1], true)
else
openspace.setPropertyValueSingle("Scene." .. node .. ".Renderable.PerformShading", true)
end
if openspace.hasSceneGraphNode(node .. "Atmosphere") then
openspace.setPropertyValueSingle("Scene." .. node .. "Atmosphere.Renderable.SunFollowingCamera", false)
end
if openspace.hasProperty("Scene." .. node .. ".Renderable.ShadowsComponent.DistanceFraction") then
openspace.setPropertyValueSingle("Scene." .. node .. ".Renderable.ShadowsComponent.DistanceFraction", 40)
end
else
openspace.printWarning("Illumination action only available for globes")
end]]
end
return commandString
end
local function getIlluminationAction(node, node_lower, global)
local actionString = "_standard_illumination"
local actionName = "Standard Illumination"
local actionCommand = getIlluminationCommand(node, global)
if (global) then
actionString = "_global_illumination"
actionName = "Global Illumination"
actionCommand = getIlluminationCommand(node, global)
end
local action = {
Identifier = "os." .. string.gsub(node_lower, "%s+", "") .. actionString,
Name = node .. " " .. actionName,
Command = actionCommand,
Documentation = "Enables " .. string.lower(actionName) .. " for" .. node,
GuiPath = "/Solar System/" .. node,
IsLocal = true
}
return action
end
local current_focus_global = getIlluminationAction("Current Focus", "current_focus", true)
asset.export("current_focus_global", current_focus_global.Identifier)
local current_focus_standard = getIlluminationAction("Current Focus", "current_focus", false)
asset.export("current_focus_standard", current_focus_standard.Identifier)
local earth_global = getIlluminationAction("Earth", "earth", true)
asset.export("earth_global", earth_global.Identifier)
local earth_standard = getIlluminationAction("Earth", "earth", false)
asset.export("earth_standard", earth_standard.Identifier)
local mars_global = getIlluminationAction("Mars", "mars", true)
asset.export("mars_global", mars_global.Identifier)
local mars_standard = getIlluminationAction("Mars", "mars", false)
asset.export("mars_standard", mars_standard.Identifier)
local venus_global = getIlluminationAction("Venus", "venus", true)
asset.export("venus_global", venus_global.Identifier)
local venus_standard = getIlluminationAction("Venus", "venus", false)
asset.export("venus_standard", venus_standard.Identifier)
local titan_global = getIlluminationAction("Titan", "titan", true)
asset.export("titan_global", titan_global.Identifier)
local titan_standard = getIlluminationAction("Titan", "titan", false)
asset.export("titan_standard", titan_standard.Identifier)
local saturn_global = getIlluminationAction("Saturn", "saturn", true)
asset.export("saturn_global", saturn_global.Identifier)
local saturn_standard = getIlluminationAction("Saturn", "saturn", false)
asset.export("titan_standard", saturn_standard.Identifier)
asset.onInitialize(function()
openspace.action.registerAction(current_focus_global)
openspace.action.registerAction(current_focus_standard)
openspace.action.registerAction(earth_global)
openspace.action.registerAction(earth_standard)
openspace.action.registerAction(mars_global)
openspace.action.registerAction(mars_standard)
openspace.action.registerAction(venus_global)
openspace.action.registerAction(venus_standard)
openspace.action.registerAction(titan_global)
openspace.action.registerAction(titan_standard)
openspace.action.registerAction(saturn_global)
openspace.action.registerAction(saturn_standard)
end)
asset.onDeinitialize(function()
openspace.action.removeAction(saturn_standard)
openspace.action.removeAction(saturn_global)
openspace.action.removeAction(titan_standard)
openspace.action.removeAction(titan_global)
openspace.action.removeAction(venus_standard)
openspace.action.removeAction(venus_global)
openspace.action.removeAction(mars_standard)
openspace.action.removeAction(mars_global)
openspace.action.removeAction(earth_standard)
openspace.action.removeAction(earth_global)
openspace.action.removeAction(current_focus_standard)
openspace.action.removeAction(current_focus_global)
end)

View File

@@ -0,0 +1,127 @@
local function getScaleCommand(identifier, scale, speed)
local command = 'openspace.setPropertyValue("' .. identifier .. '.Scale.Scale", '
command = command .. scale .. ", " .. speed
if (scale == 1) then
command = command .. ")"
else
command = command .. ', "CubicEaseOut")'
end
return command
end
local function getScaleAction(identifier, scale, name, speed)
local actionString = "Grow"
if (scale == 1) then
actionString = "Shrink"
end
local action = {
Identifier = "os." .. actionString .. "_" .. identifier,
Name = actionString .. " " .. name,
Command = getScaleCommand(identifier, scale, speed),
Documentation = "Scales " .. name .. " to " .. scale .. "x",
GuiPath = "/Solar System/Scale",
IsLocal = true
}
return action
end
local function getToggleScaleAction(identifier, scale, name, speedup, speedown)
local action = {
Identifier = "os.toggle_" .. string.gsub(name, "%s+", "") .. "_scale",
Name = "Toggle " .. name .. " Scale",
Command = [[
local list = openspace.getProperty("]] .. identifier .. [[.Scale.Scale");
if #list == 0 then
openspace.printWarning("No planets to resize");
else
local prop = list[1];
local currentScale = openspace.getPropertyValue(prop);
local newScale = 1;
if (currentScale == 1) then
]] .. getScaleCommand(identifier, scale, speedup) .. [[
else
]] .. getScaleCommand(identifier, 1, speedown) .. [[
end
end
]],
GuiPath = "/Solar System/Scale",
Documentation = "Toggle the scale of " .. name,
IsLocal = true
}
return action
end
local grow_planets = getScaleAction("{planet_solarSystem}", 3400, "Planets", 3)
asset.export("grow_planets", grow_planets.Identifier)
local shrink_planets = getScaleAction("{planet_solarSystem}", 1, "Planets", 2)
asset.export("shrink_planets", shrink_planets.Identifier)
local toggle_planet_scale = getToggleScaleAction("{planet_solarSystem}", 3400, "Planets", 3, 2)
asset.export("toggle_planet_scale", toggle_planet_scale.Identifier)
local grow_inner_planets = getScaleAction("{planet_terrestrial}", 3400, "Inner Planets", 3)
asset.export("grow_inner_planets", grow_inner_planets.Identifier)
local shrink_inner_planets = getScaleAction("{planet_terrestrial}", 1, "Inner Planets", 2)
asset.export("shrink_inner_planets", shrink_inner_planets.Identifier)
local toggle_inner_planet_scale = getToggleScaleAction("{planet_terrestrial}", 3400, "Inner Planets", 3, 2)
asset.export("toggle_inner_planet_scale", toggle_inner_planet_scale.Identifier)
local grow_outter_planets = getScaleAction("{planet_giants}", 3400, "Outter Planets", 3)
asset.export("grow_outter_planets", grow_outter_planets.Identifier)
local shrink_outter_planets = getScaleAction("{planet_giants}", 1, "Outter Planets", 2)
asset.export("shrink_outter_planets", shrink_outter_planets.Identifier)
local toggle_outter_planet_scale = getToggleScaleAction("{planet_giants}", 3400, "Outter Planets", 3, 2)
asset.export("toggle_outter_planet_scale", toggle_outter_planet_scale.Identifier)
local grow_jupiter_moons = getScaleAction("{moon_jupiter}", 50, "Jupiter Moons", 3)
asset.export("grow_jupiter_moons", grow_jupiter_moons.Identifier)
local shrink_jupiter_moons = getScaleAction("{moon_jupiter}", 1, "Jupiter Moons", 2)
asset.export("shrink_jupiter_moons", shrink_jupiter_moons.Identifier)
local toggle_jupiter_moon_scales = getToggleScaleAction("{moon_jupiter}", 50, "Jupiter Moons", 3, 2)
asset.export("toggle_jupiter_moon_scales", toggle_jupiter_moon_scales.Identifier)
local grow_moon = getScaleAction("Scene.Moon", 25, "Moon", 3)
asset.export("grow_moon", grow_moon.Identifier)
local shrink_moon = getScaleAction("Scene.Moon", 1, "Moon", 2)
asset.export("shrink_moon", shrink_moon.Identifier)
local toggle_moon_scale = getToggleScaleAction("Scene.Moon", 25, "Moon", 3, 2)
asset.export("toggle_moon_scale", toggle_moon_scale.Identifier)
asset.onInitialize(function()
openspace.action.registerAction(grow_planets)
openspace.action.registerAction(shrink_planets)
openspace.action.registerAction(toggle_planet_scale)
openspace.action.registerAction(grow_inner_planets)
openspace.action.registerAction(shrink_inner_planets)
openspace.action.registerAction(toggle_inner_planet_scale)
openspace.action.registerAction(grow_outter_planets)
openspace.action.registerAction(shrink_outter_planets)
openspace.action.registerAction(toggle_outter_planet_scale)
openspace.action.registerAction(grow_jupiter_moons)
openspace.action.registerAction(shrink_jupiter_moons)
openspace.action.registerAction(toggle_jupiter_moon_scales)
openspace.action.registerAction(grow_moon)
openspace.action.registerAction(shrink_moon)
openspace.action.registerAction(toggle_moon_scale)
end)
asset.onDeinitialize(function()
openspace.action.removeAction(toggle_moon_scale)
openspace.action.removeAction(shrink_moon)
openspace.action.removeAction(grow_moon)
openspace.action.removeAction(toggle_outter_planet_scale)
openspace.action.removeAction(shrink_outter_planets)
openspace.action.removeAction(grow_outter_planets)
openspace.action.removeAction(toggle_inner_planet_scale)
openspace.action.removeAction(shrink_inner_planets)
openspace.action.removeAction(grow_inner_planets)
openspace.action.removeAction(toggle_planet_scale)
openspace.action.removeAction(shrink_planets)
openspace.action.removeAction(grow_planets)
end)

View File

@@ -0,0 +1,29 @@
local undo_event_fade = {
Identifier = "os.undo_event_fade",
Name = "Undo All Event Fading",
Command = [[
openspace.setPropertyValue("Scene.*.Renderable.Fade", 1.0, 0.5);
]],
Documentation = [[Sets the 'Fade' value of all renderables to 1. This internval values is managed by events.]],
GuiPath = "/System/Rendering",
IsLocal = true
}
asset.export("undo_event_fade", undo_event_fade.Identifier)
asset.onInitialize(function()
openspace.action.registerAction(undo_event_fade)
end)
asset.onDeinitialize(function()
openspace.action.removeAction(undo_event_fade)
end)
asset.meta = {
Name = "Actions - Undo All Event Fading",
Version = "1.0",
Description = [[ Asset providing debug ability to undo all event fading.]],
Author = "OpenSpace Team",
URL = "http://openspaceproject.com",
License = "MIT license"
}

View File

@@ -0,0 +1,67 @@
local fade_up_trails = {
Identifier = "os.fade_up_trails",
Name = "Show All Trails",
Command = [[
openspace.setPropertyValue("Scene.*Trail.Renderable.Fade", 1, 2);
openspace.setPropertyValue("Scene.*trail.Renderable.Fade", 1, 2);
]],
Documentation = "Fade up all enabled trails in the Scene",
GuiPath = "/Trails",
IsLocal = true
}
asset.export("fade_up_trails", fade_up_trails.Identifier)
local fade_down_trails = {
Identifier = "os.fade_down_trails",
Name = "Hide All Trails",
Command = [[
openspace.setPropertyValue("Scene.*Trail.Renderable.Fade", 0, 2);
openspace.setPropertyValue("Scene.*trail.Renderable.Fade", 0, 2);
]],
Documentation = "Fade down all enabled trails in the Scene",
GuiPath = "/Trails",
IsLocal = true
}
asset.export("fade_down_trails", fade_down_trails.Identifier)
local toggle_trails = {
Identifier = "os.toggle_trails",
Name = "Toggle All Trails",
Command = [[
local capList = openspace.getProperty("*Trail.Renderable.Fade");
local list = openspace.getProperty("*trail.Renderable.Fade");
if (#capList == 0) and (#list == 0) then
openspace.printWarning("No trails to toggle");
else
local prop;
if #capList > 0 then
prop = capList[1];
else
prop = list[1];
end
local currentFade = openspace.getPropertyValue(prop);
local newFade = 0;
if currentFade < 1 then
newFade = 1;
end
openspace.setPropertyValue("Scene.*Trail.Renderable.Fade", newFade, 2);
openspace.setPropertyValue("Scene.*trail.Renderable.Fade", newFade, 2);
end
]],
Documentation = "Toggle fade for all trails in the Scene",
GuiPath = "/Trails",
IsLocal = true
}
asset.export("toggle_trails", toggle_trails.Identifier)
asset.onInitialize(function()
openspace.action.registerAction(fade_up_trails)
openspace.action.registerAction(fade_down_trails)
openspace.action.registerAction(toggle_trails)
end)
asset.onDeinitialize(function()
openspace.action.removeAction(toggle_trails)
openspace.action.removeAction(fade_down_trails)
openspace.action.removeAction(fade_up_trails)
end)

View File

@@ -0,0 +1,24 @@
local toggle_trails = {
Identifier = "os_default.toggle_trails",
Name = "Toggle Planet and Moon Trails (Instant)",
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 = "/Solar System",
IsLocal = false,
}
asset.onInitialize(function()
openspace.action.registerAction(toggle_trails)
end)
asset.onDeinitialize(function()
openspace.action.removeAction(toggle_trails)
end)
asset.export(toggle_trails)

View File

@@ -0,0 +1,67 @@
local fade_up_trails = {
Identifier = "os.fade_up_trails_planets_moon",
Name = "Show Planet and Moon Trails",
Command = [[
openspace.setPropertyValue("{planetTrail_solarSystem}.Renderable.Fade", 1, 2);
openspace.setPropertyValue("{moonTrail_solarSystem}.Renderable.Fade", 1, 2);
]],
Documentation = "Fade up all planet and moon trails in the Scene",
GuiPath = "/Trails",
IsLocal = true
}
asset.export("fade_up_trails", fade_up_trails.Identifier)
local fade_down_trails = {
Identifier = "os.fade_down_trails_planets_moon",
Name = "Hide Planet and Moon Trails",
Command = [[
openspace.setPropertyValue("{planetTrail_solarSystem}.Renderable.Fade", 0, 2);
openspace.setPropertyValue("{moonTrail_solarSystem}.Renderable.Fade", 0, 2);
]],
Documentation = "Fade down all planet and moon trails in the Scene",
GuiPath = "/Trails",
IsLocal = true
}
asset.export("fade_down_trails", fade_down_trails.Identifier)
local toggle_trails = {
Identifier = "os.toggle_trails_planets_moon",
Name = "Toggle Planet and Moon Trails",
Command = [[
local capList = openspace.getProperty("{planetTrail_solarSystem}.Renderable.Fade");
local list = openspace.getProperty("{moonTrail_solarSystem}.Renderable.Fade");
if (#capList == 0) and (#list == 0) then
openspace.printWarning("No trails to toggle");
else
local prop;
if (#capList > 0) then
prop = capList[1];
else
prop = list[1];
end
local currentFade = openspace.getPropertyValue(prop);
local newFade = 0;
if currentFade < 1 then
newFade = 1;
end
openspace.setPropertyValue("{planetTrail_solarSystem}.Renderable.Fade", newFade, 2);
openspace.setPropertyValue("{moonTrail_solarSystem}.Renderable.Fade", newFade, 2);
end
]],
Documentation = "Toggle fade for planet and moon trails in the Scene",
GuiPath = "/Trails",
IsLocal = true
}
asset.export("toggle_trails", toggle_trails)
asset.onInitialize(function()
openspace.action.registerAction(fade_up_trails)
openspace.action.registerAction(fade_down_trails)
openspace.action.registerAction(toggle_trails)
end)
asset.onDeinitialize(function()
openspace.action.removeAction(toggle_trails)
openspace.action.removeAction(fade_down_trails)
openspace.action.removeAction(fade_up_trails)
end)

View File

@@ -0,0 +1,163 @@
local enable_trail_fading = {
Identifier = "os.enable_trail_fading",
Name = "Enable Trail Fading",
Command = [[
openspace.setPropertyValue("Scene.*Trail.Renderable.Appearance.EnableFade", true);
openspace.setPropertyValue("Scene.*trail.Renderable.Appearance.EnableFade", true);
]],
Documentation = "Set orbits to fade out towards the end",
GuiPath = "/Trails/Appearance",
IsLocal = true
}
asset.export("enable_trail_fading", enable_trail_fading.Identifier)
local disable_trail_fading = {
Identifier = "os.disable_trail_fading",
Name = "Disable Trail Fading",
Command = [[
openspace.setPropertyValue("Scene.*Trail.Renderable.Appearance.EnableFade", false);
openspace.setPropertyValue("Scene.*trail.Renderable.Appearance.EnableFade", false);
]],
Documentation = "Sets trails not to fade out torwards end",
GuiPath = "/Trails/Appearance",
IsLocal = true
}
asset.export("disable_trail_fading", disable_trail_fading.Identifier)
local toggle_trail_fading = {
Identifier = "os.toggle_trail_fading",
Name = "Toggle Trail Fading",
Command = [[
local capList = openspace.getProperty("*Trail.Renderable.Appearance.EnableFade")
local list = openspace.getProperty("*trail.Renderable.Appearance.EnableFade")
if (#capList == 0) and (#list == 0) then
openspace.printWarning("No trails to toggle");
else
local prop;
if #capList > 0 then
prop = capList[1];
else
prop = list[1];
end
local currentFade = openspace.getPropertyValue(prop);
local newFade = not currentFade;
openspace.setPropertyValue("Scene.*Trail.Renderable.Appearance.EnableFade", newFade);
openspace.setPropertyValue("Scene.*trail.Renderable.Appearance.EnableFade", newFade);
end
]],
Documentation = "Toggle trails to fade out towards the end for all trails in the Scene",
GuiPath = "/Trails/Appearance",
IsLocal = true
}
asset.export("toggle_trail_fading", toggle_trail_fading.Identifier)
local function getHightlightCommand(identifierString, value)
local easeFunction = "QuinticEaseOut"
if value > 1 then
easeFunction = "QuinticEaseIn"
end
local command = 'openspace.setPropertyValue("'
command = command .. identifierString .. '.Renderable.Appearance.Fade", '
command = command .. value .. ', 2, "' .. easeFunction .. '")'
return command;
end
local function getHighlightAction(identifierString, value, nameString)
local actionString = 'Dehighlight'
if value > 1 then
actionString = 'Highlight'
end
local action = {
Identifier = "os." .. actionString .. identifierString .. "_trail",
Name = actionString .. " " .. nameString .. " Trail",
Command = getHightlightCommand(identifierString, value),
Documentation = "Animates the trail fade of " .. nameString .. "'s Trail",
GuiPath = "/Trails/Appearance",
IsLocal = true
}
return action
end
local function getToggleHighlightAction(identifierString, value, nameString)
local action = {
Identifier = "os.toggle_" .. identifierString .. "_trail_highlight",
Name = "Toggle " .. nameString .. " Trail Highlight",
Command = [[
local list = openspace.getProperty("]] .. identifierString .. [[.Renderable.Appearance.Fade");
if #list == 0 then
openspace.printWarning("No planets to resize");
else
local prop = list[1];
local fadeValue = openspace.getPropertyValue(prop)
if fadeValue > 1 then
]] .. getHightlightCommand(identifierString, 1, nameString) .. "\n" .. [[
else
]] .. getHightlightCommand(identifierString, value, nameString) .. "\n" .. [[
end
end]],
Documentation = "Animates the trail fade of " .. nameString .. "'s trail",
GuiPath = "/Trails/Appearance",
IsLocal = true
}
return action
end
local earthTrailIdentifer = "Scene.EarthTrail"
local highlight_earth_trail = getHighlightAction(earthTrailIdentifer, 10, "Earth")
asset.export("highlight_earth_trail", highlight_earth_trail.Identifier)
local dehighlight_earth_trail = getHighlightAction(earthTrailIdentifer, 1, "Earth")
asset.export("dehighlight_earth_trail", dehighlight_earth_trail.Identifier)
local toggle_earth_trail_highlight = getToggleHighlightAction(earthTrailIdentifer, 10, "Earth")
asset.export("toggle_earth_trail_highlight", toggle_earth_trail_highlight.Identifier)
local highlight_inner_trails = getHighlightAction("{planetTrail_terrestrial}", 50, "Inner Planet")
asset.export("highlight_inner_trails", highlight_inner_trails.Identifier)
local dehighlight_inner_trails = getHighlightAction("{planetTrail_terrestrial}", 1, "Inner Planet")
asset.export("dehighlight_inner_trails", dehighlight_inner_trails.Identifier)
local toggle_inner_trail_highlight = getToggleHighlightAction("{planetTrail_terrestrial}", 50, "Inner Planet")
asset.export("toggle_inner_trail_highlight", toggle_inner_trail_highlight.Identifier)
local highlight_outter_trails = getHighlightAction("{planetTrail_giants}", 100, "Outter Planet")
asset.export("highlight_outter_trails", highlight_outter_trails.Identifier)
local dehighlight_outter_trails = getHighlightAction("{planetTrail_giants}", 1, "Outter Planet")
asset.export("dehighlight_outter_trails", dehighlight_outter_trails.Identifier)
local toggle_outter_trail_highlight = getToggleHighlightAction("{planetTrail_giants}", 100, "Outter Planet")
asset.export("toggle_outter_trail_highlight", toggle_outter_trail_highlight.Identifier)
asset.onInitialize(function()
openspace.action.registerAction(enable_trail_fading)
openspace.action.registerAction(disable_trail_fading)
openspace.action.registerAction(toggle_trail_fading)
openspace.action.registerAction(highlight_earth_trail)
openspace.action.registerAction(dehighlight_earth_trail)
openspace.action.registerAction(toggle_earth_trail_highlight)
openspace.action.registerAction(highlight_inner_trails)
openspace.action.registerAction(dehighlight_inner_trails)
openspace.action.registerAction(toggle_inner_trail_highlight)
openspace.action.registerAction(highlight_outter_trails)
openspace.action.registerAction(dehighlight_outter_trails)
openspace.action.registerAction(toggle_outter_trail_highlight)
end)
asset.onDeinitialize(function()
openspace.action.removeAction(toggle_outter_trail_highlight)
openspace.action.removeAction(dehighlight_outter_trails)
openspace.action.removeAction(highlight_outter_trails)
openspace.action.removeAction(highlight_inner_trails)
openspace.action.removeAction(dehighlight_inner_trails)
openspace.action.removeAction(toggle_inner_trail_highlight)
openspace.action.removeAction(highlight_earth_trail)
openspace.action.removeAction(dehighlight_earth_trail)
openspace.action.removeAction(toggle_earth_trail_highlight)
openspace.action.removeAction(toggle_trail_fading)
openspace.action.removeAction(disable_trail_fading)
openspace.action.removeAction(enable_trail_fading)
end)

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")
@@ -17,12 +21,6 @@ asset.require("scene/solarsystem/dwarf_planets/pluto/charon/default_layers")
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 +58,56 @@ asset.require("scene/digitaluniverse/supernovaremnants")
asset.require("scene/digitaluniverse/tully")
asset.require("scene/digitaluniverse/voids")
asset.require("customization/globebrowsing")
asset.require("util/default_actions")
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"
}
local trailAction = asset.require("actions/trails/toggle_trails_planets_moons").toggle_trails
asset.onInitialize(function ()
openspace.bindKey("h", trailAction.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.clearKey(toggle_trails.Key)
openspace.action.removeAction(toggle_planet_labels)
openspace.clearKey(toggle_planet_labels.Key)
end)

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

View File

@@ -1,8 +1,8 @@
local item = {
Type = "DashboardItemVelocity",
Identifier = "GlobeLocation",
Identifier = "CameraVelocity",
Simplification = true,
GuiName = "Velocity"
GuiName = "Camera Velocity"
}
asset.onInitialize(function()

View File

@@ -0,0 +1,27 @@
local action = asset.require("actions/trails/toggle_all_trails")
asset.onInitialize(function()
openspace.event.registerEventAction(
"CameraFocusTransition",
action.fade_up_trails,
{ Transition = "Exiting" }
)
openspace.event.registerEventAction(
"CameraFocusTransition",
action.fade_down_trails,
{ Transition = "Approaching" }
)
end)
asset.onDeinitialize(function()
openspace.event.unregisterEventAction(
"CameraFocusTransition",
action.fade_up_trails,
{ Transition = "Exiting" }
)
openspace.event.unregisterEventAction(
"CameraFocusTransition",
action.fade_down_trails,
{ Transition = "Approaching" }
)
end)

View File

@@ -22,7 +22,7 @@ local toggle_sun = {
Documentation = [[Toggles the visibility of the Sun glare and the Sun globe when the
camera is approaching either so that from far away the Sun Glare is rendered and when
close up, the globe is rendered instead.]],
GuiPath = "/Sun",
GuiPath = "/Solar System/Sun",
IsLocal = false
}

View File

@@ -1,4 +1,4 @@
local action = asset.require("actions/toggle_trail")
local action = asset.require("actions/trails/toggle_trail")
asset.onInitialize(function()
openspace.event.registerEventAction(

View File

@@ -0,0 +1,27 @@
local action = asset.require("actions/trails/toggle_trails_planets_moons")
asset.onInitialize(function()
openspace.event.registerEventAction(
"CameraFocusTransition",
action.fade_up_trails,
{ Transition = "Exiting" }
)
openspace.event.registerEventAction(
"CameraFocusTransition",
action.fade_down_trails,
{ Transition = "Approaching" }
)
end)
asset.onDeinitialize(function()
openspace.event.unregisterEventAction(
"CameraFocusTransition",
action.fade_up_trails,
{ Transition = "Exiting" }
)
openspace.event.unregisterEventAction(
"CameraFocusTransition",
action.fade_down_trails,
{ Transition = "Approaching" }
)
end)

View File

@@ -25,8 +25,8 @@
-- First - Name of the joystick that should be bound
-- Second - Which axis should be bound of this joystick
-- Third - The property uri
-- Fourth - (optional) The smallest value that you wnat to allow this property on the joystick
-- Fifth - (optional) The largest value that you wnat to allow this property on the joystick
-- Fourth - (optional) The smallest value that you want to allow this property on the joystick
-- Fifth - (optional) The largest value that you want to allow this property on the joystick
-- Sixth - (optional) Determines whether the axis should be inverted
-- Seventh - (optional) Should this property change be sent to other connected remote sessions

View File

@@ -32,7 +32,7 @@ local layer_folder = {
Type = "TemporalTileLayer",
Mode = "Folder",
Folder = {
Folder = "C:/Development/sync/http/earth_textures_climate/1",
Folder = path,
Format = "%Y-%m-%d-land.png"
},
Interpolation = true,

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)

View File

@@ -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"
}

View File

@@ -0,0 +1,3 @@
asset.require("./default_settings")
asset.require("./exoplanets_data")
asset.require("./exoplanets_textures")

View File

@@ -2,17 +2,19 @@ local DataPath = asset.syncedResource({
Name = "Exoplanet Data Files",
Type = "HttpSynchronization",
Identifier = "exoplanets_data",
Version = 2
Version = 3
})
local colormaps = asset.syncedResource({
Name = "Stars Color Table",
Type = "HttpSynchronization",
Identifier = "stars_colormap",
Version = 2
Version = 3
})
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]],

View File

@@ -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)

View File

@@ -0,0 +1,14 @@
asset.onInitialize(function ()
openspace.setPropertyValueSingle("Modules.SkyBrowser.Enabled", true)
openspace.setPropertyValueSingle("Modules.SkyBrowser.ShowTitleInGuiBrowser", false)
-- 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"
}

View File

@@ -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"
}

View File

@@ -0,0 +1,2 @@
asset.require("./default_settings")
asset.require("./hoverCircle")

View File

@@ -12,6 +12,13 @@ local speck = asset.syncedResource({
Version = 2
})
local colormaps = asset.syncedResource({
Name = "Quasars Colormap",
Type = "HttpSynchronization",
Identifier = "digitaluniverse_quasars_colormap",
Version = 1
})
local object = {
Identifier = "Quasars",
Renderable = {
@@ -25,7 +32,11 @@ local object = {
ScaleFactor = 540.9,
FadeInDistances = { 1000.0, 10000.0 }, -- Fade in value in the same unit as "Unit"
BillboardMinMaxSize = { 0.0, 11.1 },
EnablePixelSizeControl = true
EnablePixelSizeControl = true,
ColorMap = colormaps .. "viridis.cmap",
ColorOption = { "redshift", "Tlookback", "distMpc" },
ColorRange = { { 0.102, 7.085 }, { 1.4, 13.0 }, { 440.5, 8852.099609 } },
UseColorMap = false
},
GUI = {
Name = "Quasars",

View File

@@ -16,7 +16,7 @@ local colormaps = asset.syncedResource({
Name = "Stars Color Table",
Type = "HttpSynchronization",
Identifier = "stars_colormap",
Version = 2
Version = 3
})
local textures = asset.syncedResource({

View File

@@ -62,11 +62,11 @@ local createConstellations = function (baseIdentifier, guiPath, constellationfil
BlendMode = "Additive",
Opacity = 0.1
},
Tag = { "ConstellationArtImage", group },
Tag = { "ImageConstellation", group },
GUI = {
Name = name .. " Image",
Path = "/Milky Way/" .. guiPath,
Description = name .. " Constellation Image"
Description = name .. " Image"
}
}
table.insert(genConstellations, aconstellation);
@@ -83,9 +83,9 @@ local show_art = {
Identifier = "constellation_art.show_art",
Name = "Show Constellation Art",
Command = [[
openspace.setPropertyValue("Scene.ConstellationArt*.Renderable.Opacity", 0);
openspace.setPropertyValue("Scene.ConstellationArt*.Renderable.Enabled", true);
openspace.setPropertyValue("Scene.ConstellationArt*.Renderable.Opacity", 0.2, 2);
openspace.setPropertyValue("Scene.ImageConstellation*.Renderable.Opacity", 0);
openspace.setPropertyValue("Scene.ImageConstellation*.Renderable.Enabled", true);
openspace.setPropertyValue("Scene.ImageConstellation*.Renderable.Opacity", 0.2, 2);
]],
Documentation = "Enables and fades up constellation art work",
GuiPath = "/Rendering",
@@ -96,7 +96,7 @@ asset.export("ShowArtAction", show_art)
local hide_art = {
Identifier = "constellation_art.hide_art",
Name = "Hide Constellation Art",
Command = [[openspace.setPropertyValue("Scene.ConstellationArt*.Renderable.Opacity", 0, 2)]],
Command = [[openspace.setPropertyValue("Scene.ImageConstellation*.Renderable.Opacity", 0, 2)]],
Documentation = "Fades out constellation artwork",
GuiPath = "/Rendering",
IsLocal = false
@@ -106,7 +106,7 @@ asset.export("HideArtAction", hide_art)
local disable_art = {
Identifier = "constellation_art.disable_art",
Name = "Disable Constellation Art",
Command = [[openspace.setPropertyValue("Scene.ConstellationArt*.Renderable.Enabled", false)]],
Command = [[openspace.setPropertyValue("Scene.ImageConstellation*.Renderable.Enabled", false)]],
Documentation = "Disable constellation artwork",
GuiPath = "/Rendering",
IsLocal = false
@@ -117,7 +117,7 @@ local show_zodiac_art = {
Identifier = "constellation_art.show_zodiac_art",
Name = "Show Zodiac Art",
Command = [[
openspace.setPropertyValue("Scene.ConstellationArt*.Renderable.Opacity", 0);
openspace.setPropertyValue("Scene.ImageConstellation*.Renderable.Opacity", 0);
openspace.setPropertyValue("{zodiac}.Renderable.Enabled",true);
openspace.setPropertyValue("{zodiac}.Renderable.Opacity", 1, 2);
]],
@@ -142,7 +142,7 @@ local nodes = {}
asset.onInitialize(function ()
local constellationsCSV = images .. "constellation_data.csv"
nodes = createConstellations("ConstellationArt", "Constellation Art", constellationsCSV)
nodes = createConstellations("ImageConstellation", "Constellation Art", constellationsCSV)
for _, n in ipairs(nodes) do
openspace.addSceneGraphNode(n);
end

View File

@@ -9,7 +9,7 @@ local colormaps = asset.syncedResource({
Name = "Stars Color Table",
Type = "HttpSynchronization",
Identifier = "stars_colormap",
Version = 2
Version = 3
})
local textures = asset.syncedResource({
@@ -27,13 +27,14 @@ local gaia_abundance_apogee = {
File = speck .. "GaiaAbundApogee.speck",
ColorOption = "Other Data",
OtherData = "FeH",
MagnitudeExponent = 6.2,
MagnitudeExponent = 7.25,
SizeComposition = "Distance Modulus",
RenderMethod = "Texture Based",
Texture = textures .. "halo.png",
ColorRange = { { -0.8, 0.6 } },
-- ShapeTexture = textures .. "disc.png",
ColorMap = colormaps .. "colorbv.cmap",
OtherDataColorMap = colormaps .. "viridis.cmap",
OtherDataColorMap = colormaps .. "RainbowGradient.cmap",
StaticFilter = -9999,
StaticFilterReplacement = 0.0,
DataMapping = {

View File

@@ -16,7 +16,7 @@ local colormaps = asset.syncedResource({
Name = "Stars Color Table",
Type = "HttpSynchronization",
Identifier = "stars_colormap",
Version = 2
Version = 3
})
local textures = asset.syncedResource({
@@ -32,7 +32,7 @@ local GaiaStars = {
Type = "RenderableGaiaStars",
File = starsFolder,
FileReaderOption = "StreamOctree",
RenderOption = "Motion",
RenderMode = "Motion",
ShaderOption = "Point_SSBO",
Texture = textures .. "halo.png",
ColorMap = colormaps .. "colorbv.cmap",

View File

@@ -9,7 +9,7 @@ local colormaps = asset.syncedResource({
Name = "Stars Color Table",
Type = "HttpSynchronization",
Identifier = "stars_colormap",
Version = 2
Version = 3
})
local textures = asset.syncedResource({
@@ -27,13 +27,14 @@ local gaia_abundance_galah = {
File = speck .. "GaiaAbundGalah.speck",
Texture = textures .. "halo.png",
-- ShapeTexture = textures .. "disc.png",
MagnitudeExponent = 6.2,
MagnitudeExponent = 7.25,
SizeComposition = "Distance Modulus",
RenderMethod = "Texture Based",
ColorOption = "Other Data",
OtherData = "FeH",
ColorMap = colormaps .. "colorbv.cmap",
OtherDataColorMap = colormaps .. "viridis.cmap",
OtherDataColorMap = colormaps .. "RainbowGradient.cmap",
ColorRange = { { -0.8, 0.6 } },
StaticFilter = -9999,
StaticFilterReplacement = 0.0,
DataMapping = {

View File

@@ -0,0 +1,18 @@
local resetLoopAction = {
Documentation = "Reset button. Sets time to start of dataset. No loop",
GuiPath = "2012July",
Identifier = "2012july.reset_loop",
IsLocal = false,
Name = "Reset button",
Command = "openspace.time.setTime('2012-JUL-01 07:00:00.00');\nopenspace.time.setDeltaTime(1400);\nopenspace.scriptScheduler.clear();"
}
asset.export(resetLoopAction)
asset.onInitialize(function ()
openspace.action.registerAction(resetLoopAction)
end)
asset.onDeinitialize(function ()
openspace.asction.removeAction(resetLoopAction)
end)

View File

@@ -0,0 +1,3 @@
asset.require("./sun_earth_2012_fieldlines_enlil")
asset.require("./sun_earth_2012_fieldlines_batsrus")
asset.require("./sun_earth_2012_fieldlines_pfss")

View File

@@ -0,0 +1,168 @@
local transforms = asset.require('scene/solarsystem/planets/earth/magnetosphere/transforms_magnetosphere.asset')
asset.require('scene/solarsystem/heliosphere/2012/reset_loop_action.asset')
local transferFunctions = asset.syncedResource({
Name = "Fieldlines Transfer Functions",
Type = "HttpSynchronization",
Identifier = "sun_earth_event_july_2012-fieldlines_transferfunctions",
Version = 2
})
local fieldlineData = asset.syncedResource({
Name = "Fieldlines Data BATSRUS",
Type = "HttpSynchronization",
Identifier = "sun_earth_event_july_2012-batsrus",
Version = 1
})
local loop = {
Documentation = "Sets time to start of data, sets higher delta time and loops back from start, when at end of data.",
GuiPath = "2012July",
Identifier = "2012july.loop_batsrus",
IsLocal = false,
Name = "Loop BATSRUS",
Command = "openspace.scriptScheduler.clear();\nopenspace.time.setDeltaTime(1400);\nopenspace.time.setTime('2012-JUL-14 06:00:00.00');\nlocal StarttimescriptBatsrusLoop = \"openspace.time.setTime('2012 JUL 14 06:00:00')\";\nopenspace.scriptScheduler.loadScheduledScript('2012 JUL 16 07:30:00', StarttimescriptBatsrusLoop);"
}
local batsrusTemperatureColorTable = transferFunctions .. "batsrus_temperature.txt"
local batsrusDensityColorTable = transferFunctions .. "batsrus_density.txt"
local batsrusCurrentColorTable = transferFunctions .. "batsrus_current2.txt"
local batsrusVelocityColorTable = transferFunctions .. "batsrus_velocity.txt"
local batsrusTopologyColorTable = transferFunctions .. "batsrus_topology.txt"
local unzippedDataDestination = {
openClosed = fieldlineData .. "magnetic_fieldlines-open_closed",
velocityFlow = fieldlineData .. "velocity_flowlines-upstream",
asherStatic = fieldlineData .. "ashers_static_seeds"
}
local colorRanges = {
{ 0, 100000000 },
{ 0, 60 },
{ -0.015, 0.015 },
{ 150, 900 },
{ 0, 3 },
}
local interactionSphere = 6380000 -- A value slightly bigger than earth radius
----------------------LUTZ's JULY TRACES-------------------------
local BatsrusJ12OpenClosed = {
Identifier = "FL_BATSRUS_J12_OpenClosed",
Parent = transforms.GSMReferenceFrame.Identifier,
InteractionSphere = interactionSphere,
Renderable = {
Type = "RenderableFieldlinesSequence",
SourceFolder = unzippedDataDestination.openClosed,
InputFileType = "Osfls",
Color = { 0.7, 0.4, 0.0, 0.6 }, -- Default color
ColorMethod = "By Quantity", -- Color by Quantity
ColorQuantity = 0, -- Temperature
ColorTablePaths = {
batsrusTemperatureColorTable,
batsrusDensityColorTable,
batsrusCurrentColorTable,
batsrusVelocityColorTable,
batsrusTopologyColorTable,
},
ColorTableRanges = colorRanges,
MaskingEnabled = true,
MaskingQuantity = 4, -- Topology
MaskingRanges = { {2.5, 3.0} } -- Corresponds to closed fieldlines only
},
GUI = {
Name = "Fieldlines BATSRUS J12 Open/Closed",
Path = "/Solar System/Heliosphere"
}
}
--------------------- VELOCITY FLOWLINES ------------------------
local BatsrusJ12FlowLines = {
Identifier = "FL_BATSRUS_J12_FlowLines",
Parent = transforms.GSMReferenceFrame.Identifier,
InteractionSphere = interactionSphere,
Renderable = {
Type = "RenderableFieldlinesSequence",
SourceFolder = unzippedDataDestination.velocityFlow,
InputFileType = "Osfls",
ColorMethod = "By Quantity", -- Color by Quantity
ColorQuantity = 3, -- Velocity
Color = { 0.7, 0.4, 0.0, 0.12 }, -- Default color
ColorTablePaths = {
batsrusTemperatureColorTable,
batsrusDensityColorTable,
batsrusCurrentColorTable,
batsrusVelocityColorTable,
batsrusTopologyColorTable,
},
ColorTableRanges = colorRanges
},
GUI = {
Name = "Fieldlines BATSRUS J12 Flowlines",
Path = "/Solar System/Heliosphere"
}
}
--------------------- Ashers seedpoints ------------------------
local BatsrusAsherStaticSeedsFlowLines = {
Identifier = "FL_BATSRUS_ASHER_STATIC_SSEDS_FlowLines",
Parent = transforms.GSMReferenceFrame.Identifier,
InteractionSphere = interactionSphere,
Renderable = {
Type = "RenderableFieldlinesSequence",
SourceFolder = unzippedDataDestination.asherStatic,
Enabled = false,
InputFileType = "Osfls",
ColorTablePaths = {
batsrusTemperatureColorTable,
batsrusDensityColorTable,
batsrusCurrentColorTable,
batsrusVelocityColorTable,
batsrusTopologyColorTable,
},
ColorTableRanges = colorRanges
},
GUI = {
Name = "Fieldlines BATSRUS Asher Static",
Path = "/Solar System/Heliosphere"
}
}
asset.onInitialize(function ()
openspace.action.registerAction(loop)
if not openspace.directoryExists(unzippedDataDestination.openClosed) then
openspace.printInfo("Extracting " .. "Fieldlines from Batsrus model of 2012 event")
openspace.unzipFile(fieldlineData .. "magnetic_fieldlines-open_closed.zip", unzippedDataDestination.openClosed, true)
end
if not openspace.directoryExists(unzippedDataDestination.velocityFlow) then
openspace.printInfo("Extracting " .. "Fieldlines from Batsrus model of 2012 event")
openspace.unzipFile(fieldlineData .. "velocity_flowlines-upstream.zip", unzippedDataDestination.velocityFlow, true)
end
if not openspace.directoryExists(unzippedDataDestination.asherStatic) then
openspace.printInfo("Extracting " .. "Fieldlines from Batsrus model of 2012 event")
openspace.unzipFile(fieldlineData .. "ashers_static_seeds.zip", unzippedDataDestination.asherStatic, true)
end
openspace.addSceneGraphNode(BatsrusJ12OpenClosed)
openspace.addSceneGraphNode(BatsrusJ12FlowLines)
openspace.addSceneGraphNode(BatsrusAsherStaticSeedsFlowLines)
end)
asset.onDeinitialize(function ()
openspace.removeSceneGraphNode(BatsrusAsherStaticSeedsFlowLines)
openspace.removeSceneGraphNode(BatsrusJ12FlowLines)
openspace.removeSceneGraphNode(BatsrusJ12OpenClosed)
openspace.action.removeAction(loop)
end)
asset.meta = {
Name = "Fieldlines from Batsrus model of 2012 event",
Version = "1.0",
Description = "Magnetic fieldlines from Batsrus model for a 2012 CME event",
Author = "CCMC",
URL = "",
License = "CC-BY"
}

View File

@@ -0,0 +1,242 @@
local transforms = asset.require('scene/solarsystem/sun/transforms_heliosphere.asset')
asset.require('scene/solarsystem/heliosphere/2012/reset_loop_action.asset')
local transferFunctions = asset.syncedResource({
Name = "Fieldlines Transfer Functions",
Type = "HttpSynchronization",
Identifier = "sun_earth_event_july_2012-fieldlines_transferfunctions",
Version = 1
})
local fieldlineData = asset.syncedResource({
Name = "Fieldlines Data ENLIL",
Type = "HttpSynchronization",
Identifier = "sun_earth_event_july_2012-enlil",
Version = 1
})
local loop = {
Documentation = "Sets time to start of data, sets high delta time and loops back from start when at end of data",
GuiPath = "2012July",
Identifier = "2012july.loop_enlil",
IsLocal = false,
Name = "Loop ENLIL",
Command = "openspace.scriptScheduler.clear();\nopenspace.time.setDeltaTime(43200);\nopenspace.time.setTime('2012-JUL-01 07:00:00.00');\nlocal StarttimescriptENLILLoop = \"openspace.time.setTime('2012 JUL 01 07:00:00')\";\nopenspace.scriptScheduler.loadScheduledScript('2012 AUG 01 06:58:00', StarttimescriptENLILLoop);"
}
local enlilDensityColorTable = transferFunctions .. "enlil_density.txt"
local enlilVelocityColorTable = transferFunctions .. "kroyw.txt"
local unzippedDataDestination = {
EqPlane011AU1 = fieldlineData .. "011AU_eq_plane_1/",
EqPlane011AU2 = fieldlineData .. "011AU_eq_plane_2/",
Lat4011AU1 = fieldlineData .. "011AU_lat4_1/",
Lat4011AU2 = fieldlineData .. "011AU_lat4_2/",
Earth = fieldlineData .. "earth/",
StereoA = fieldlineData .. "stereoa/"
}
local colorRanges = {
{ 0, 1000000 },
{ 100, 2000 }
}
local interactionSphere = 695700000
local ENLILSliceEqPlane11AU1 = {
Identifier = "FL_ENLIL_slice_eqPlane_011AU_1",
Parent = transforms.HEEQ180ReferenceFrame.Identifier,
InteractionSphere = interactionSphere,
Renderable = {
Type = "RenderableFieldlinesSequence",
SourceFolder = unzippedDataDestination.EqPlane011AU1,
InputFileType = "Osfls",
Color = { 0.4, 0.15, 0.4, 0.6 },
ColorMethod = "By Quantity", -- Color by Quantity
ColorQuantity = 1, -- Velocity
ColorTablePaths = {
enlilDensityColorTable,
enlilVelocityColorTable,
},
ColorTableRanges = colorRanges
},
GUI = {
Name = "Fieldlines ENLIL Slice Equatorial Plane 0.11 AU 1",
Path = "/Solar System/Heliosphere"
}
}
local ENLILSliceEqPlane11AU2 = {
Identifier = "FL_ENLIL_slice_eqPlane_011AU_2",
Parent = transforms.HEEQ180ReferenceFrame.Identifier,
InteractionSphere = interactionSphere,
Renderable = {
Type = "RenderableFieldlinesSequence",
SourceFolder = unzippedDataDestination.EqPlane011AU2,
InputFileType = "Osfls",
Color = { 0.4, 0.15, 0.4, 0.6 },
ColorMethod = "By Quantity", -- Color by Quantity
ColorQuantity = 1, -- Velocity
ColorTablePaths = {
enlilDensityColorTable,
enlilVelocityColorTable,
},
ColorTableRanges = colorRanges
},
GUI = {
Name = "Fieldlines ENLIL Slice Equatorial Plane 0.11 AU 2",
Path = "/Solar System/Heliosphere"
}
}
local ENLILSliceLat411AU1 = {
Identifier = "FL_ENLIL_slice_lat4_011AU_1",
Parent = transforms.HEEQ180ReferenceFrame.Identifier,
InteractionSphere = interactionSphere,
Renderable = {
Type = "RenderableFieldlinesSequence",
SourceFolder = unzippedDataDestination.Lat4011AU1,
InputFileType = "Osfls",
Color = { 0.4, 0.15, 0.4, 0.6 },
ColorMethod = "By Quantity", -- Color by Quantity
ColorQuantity = 1, -- Velocity
ColorTablePaths = {
enlilDensityColorTable,
enlilVelocityColorTable,
},
ColorTableRanges = colorRanges
},
GUI = {
Name = "Fieldlines ENLIL Slice Latitude 4 0.11 AU 1",
Path = "/Solar System/Heliosphere"
}
}
local ENLILSliceLat411AU2 = {
Identifier = "FL_ENLIL_slice_lat4_011AU_2",
Parent = transforms.HEEQ180ReferenceFrame.Identifier,
InteractionSphere = interactionSphere,
Renderable = {
Type = "RenderableFieldlinesSequence",
SourceFolder = unzippedDataDestination.Lat4011AU2,
InputFileType = "Osfls",
Color = { 0.4, 0.15, 0.4, 0.6 },
ColorMethod = "By Quantity", -- Color by Quantity
ColorQuantity = 1, -- Velocity
ColorTablePaths = {
enlilDensityColorTable,
enlilVelocityColorTable,
},
ColorTableRanges = colorRanges
},
GUI = {
Name = "Fieldlines ENLIL Slice Latitude 4 0.11 AU 2",
Path = "/Solar System/Heliosphere"
}
}
local ENLILEarth = {
Identifier = "FL_ENLIL_earth",
Parent = transforms.HEEQ180ReferenceFrame.Identifier,
InteractionSphere = interactionSphere,
Renderable = {
Type = "RenderableFieldlinesSequence",
SourceFolder = unzippedDataDestination.Earth,
InputFileType = "Osfls",
Color = { 1.0, 1.0, 1.0, 0.6 },
ColorTablePaths = {
enlilDensityColorTable,
enlilVelocityColorTable,
},
ColorTableRanges = colorRanges
},
GUI = {
Name = "Fieldlines ENLIL Earth",
Path = "/Solar System/Heliosphere"
}
}
local ENLILStereoA = {
Identifier = "FL_ENLIL_stereoa",
Parent = transforms.HEEQ180ReferenceFrame.Identifier,
InteractionSphere = interactionSphere,
Renderable = {
Type = "RenderableFieldlinesSequence",
SourceFolder = unzippedDataDestination.StereoA,
InputFileType = "Osfls",
Color = { 1.0, 1.0, 1.0, 0.6 },
ColorTablePaths = {
enlilDensityColorTable,
enlilVelocityColorTable,
},
ColorTableRanges = colorRanges,
FlowEnabled = true,
ReversedFlow = true,
ParticleSize = 5,
ParticleSpacing = 25,
FlowSpeed = 25
},
GUI = {
Name = "Fieldlines ENLIL STEREO A",
Path = "/Solar System/Heliosphere"
}
}
asset.onInitialize(function ()
openspace.action.registerAction(loop)
if not openspace.directoryExists(unzippedDataDestination.EqPlane011AU1) then
openspace.printInfo("Extracting " .. "Fieldlines from ENLIL model of 2012 event")
openspace.unzipFile(fieldlineData .. "011AU_eq_plane_1.zip", unzippedDataDestination.EqPlane011AU1, true)
end
if not openspace.directoryExists(unzippedDataDestination.EqPlane011AU2) then
openspace.printInfo("Extracting " .. "Fieldlines from ENLIL model of 2012 event")
openspace.unzipFile(fieldlineData .. "011AU_eq_plane_2.zip", unzippedDataDestination.EqPlane011AU2, true)
end
if not openspace.directoryExists(unzippedDataDestination.Lat4011AU1) then
openspace.printInfo("Extracting " .. "Fieldlines from ENLIL model of 2012 event")
openspace.unzipFile(fieldlineData .. "011AU_lat4_1.zip", unzippedDataDestination.Lat4011AU1, true)
end
if not openspace.directoryExists(unzippedDataDestination.Lat4011AU2) then
openspace.printInfo("Extracting " .. "Fieldlines from ENLIL model of 2012 event")
openspace.unzipFile(fieldlineData .. "011AU_lat4_2.zip", unzippedDataDestination.Lat4011AU2, true)
end
if not openspace.directoryExists(unzippedDataDestination.Earth) then
openspace.printInfo("Extracting " .. "Fieldlines from ENLIL model of 2012 event")
openspace.unzipFile(fieldlineData .. "earth.zip", unzippedDataDestination.Earth, true)
end
if not openspace.directoryExists(unzippedDataDestination.StereoA) then
openspace.printInfo("Extracting " .. "Fieldlines from ENLIL model of 2012 event")
openspace.unzipFile(fieldlineData .. "stereoa.zip", unzippedDataDestination.StereoA, true)
end
openspace.addSceneGraphNode(ENLILSliceEqPlane11AU1)
openspace.addSceneGraphNode(ENLILSliceEqPlane11AU2)
openspace.addSceneGraphNode(ENLILSliceLat411AU1)
openspace.addSceneGraphNode(ENLILSliceLat411AU2)
openspace.addSceneGraphNode(ENLILEarth)
openspace.addSceneGraphNode(ENLILStereoA)
end)
asset.onDeinitialize(function ()
openspace.removeSceneGraphNode(ENLILStereoA)
openspace.removeSceneGraphNode(ENLILEarth)
openspace.removeSceneGraphNode(ENLILSliceLat411AU2)
openspace.removeSceneGraphNode(ENLILSliceLat411AU1)
openspace.removeSceneGraphNode(ENLILSliceEqPlane11AU2)
openspace.removeSceneGraphNode(ENLILSliceEqPlane11AU1)
openspace.action.removeAction(loop)
end)
asset.meta = {
Name = "Fieldlines from ENLIL model of 2012 event",
Version = "1.0",
Description = "Magnetic fieldlines from ENLIL model for a 2012 CME event",
Author = "CCMC",
URL = "",
License = "CC-BY"
}

View File

@@ -0,0 +1,94 @@
local transforms = asset.require('scene/solarsystem/sun/transforms_heliosphere.asset')
local transferFunctions = asset.syncedResource({
Name = "Fieldlines Transfer Functions",
Type = "HttpSynchronization",
Identifier = "sun_earth_event_july_2012-fieldlines_transferfunctions",
Version = 1
})
local fieldlineData = asset.syncedResource({
Name = "Fieldlines Data PFSS",
Type = "HttpSynchronization",
Identifier = "sun_earth_event_july_2012-pfss",
Version = 1
})
local darkenSun = {
Documentation = "Makes the Sun turn black",
GuiPath = "2012July",
Identifier = "2012july.dark_sun",
IsLocal = false,
Name = "Dark sun",
Command = "local textureMultiplier = openspace.getPropertyValue(\"Scene.Sun.Renderable.Layers.ColorLayers.Texture.Settings.Multiplier\");\nif(textureMultiplier < 0.01) then\nopenspace.setPropertyValueSingle(\"Scene.Sun.Renderable.Layers.ColorLayers.Texture.Settings.Multiplier\", 1.0, 1);\nelse\nopenspace.setPropertyValueSingle(\"Scene.Sun.Renderable.Layers.ColorLayers.Texture.Settings.Multiplier\", 0.0, 1)\nend"
}
local pfssTransitionColorTable = transferFunctions .. "pfss_transition.txt"
local pfssTopologyColorTable = transferFunctions .. "pfss_topology.txt"
local pfssBsignColorTable = transferFunctions .. "pfss_bsign.txt"
local PFSSPaths = {
SolarSoft = fieldlineData .. "leilas_solar_soft/"
}
local PFSS = {
Identifier = "FL_PFSS",
Parent = transforms.HEEQ180ReferenceFrame.Identifier,
InteractionSphere = 695700000,
Renderable = {
Type = "RenderableFieldlinesSequence",
SourceFolder = PFSSPaths.SolarSoft,
InputFileType = "Osfls",
Color = {0.35, 0.51, 0.875, 0.22},
FlowEnabled = true,
ReversedFlow = true,
FlowColor = { 1, 0.9, 1, 0.74 },
ParticleSize = 5,
ParticleSpacing = 250,
FlowSpeed = 75,
ColorTablePaths = {
pfssTopologyColorTable,
pfssBsignColorTable,
},
ColorTableRanges = {
{ 0, 2 },
{ -1, 1 },
},
},
GUI = {
Name = "Fieldlines PFSS",
Path = "/Solar System/Heliosphere"
}
}
asset.onInitialize(function ()
openspace.action.registerAction(darkenSun)
if not openspace.directoryExists(PFSSPaths.SolarSoft) then
openspace.printInfo("Extracting " .. "Fieldlines from PFSS model of 2012 event")
openspace.unzipFile(fieldlineData .. "leilas_solar_soft.zip", PFSSPaths.SolarSoft, true)
end
openspace.addSceneGraphNode(PFSS)
-- openspace.setPropertyValueSingle("Scene.FL_PFSS.Renderable.FlowEnabled", true)
-- openspace.setPropertyValueSingle("Scene.FL_PFSS.Renderable.Flow.Reversed", true)
--openspace.setPropertyValueSingle("Scene.FL_PFSS.Renderable.Flow.particleSize", 5)
--openspace.setPropertyValueSingle("Scene.FL_PFSS.Renderable.Flow.particleSpacing", 250)
--openspace.setPropertyValueSingle("Scene.FL_PFSS.Renderable.Flow.speed", 75.0)
end)
asset.onDeinitialize(function ()
openspace.removeSceneGraphNode(PFSS)
openspace.action.removeAction(darkenSun)
end)
asset.meta = {
Name = "Fieldlines from PFSS model of 2012 event",
Version = "1.0",
Description = "Magnetic fieldlines from PFSS model for a 2012 CME event",
Author = "CCMC",
URL = "",
License = "CC-BY"
}

View File

@@ -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 = {
@@ -28,7 +32,7 @@ local densityVolume = {
Renderable = {
Type = "RenderableTimeVaryingVolume",
StepSize = 0.004,
Opacity = 0.3,
Brightness = 0.3,
TransferFunction = asset.localResource("transferfunctions/mas-mhd-r-squared-old.txt"),
SourceDirectory = densityDirectory,
GridType = "Spherical",

View File

@@ -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",
@@ -31,14 +34,11 @@ local fieldlines = {
asset.localResource("transferfunctions/density-fieldlines.txt"),
asset.localResource("transferfunctions/velocity-fieldlines.txt")
},
ColorTableMinMax = {
ColorTableRanges = {
{ 0, 1000000 },
{ 100, 2000 }
},
SimulationModel = "mas",
Color = {
Uniform = { 0.0, 0.725, 0.75, 1.0 }
}
},
GUI = {
Path = "/Solar System/Heliosphere/Bastille Day 2000",
@@ -68,7 +68,6 @@ end)
asset.export(fieldlines)
asset.meta = {
Name = "Predictive Science Inc. Fieldlines Bastille Day",
Version = "1.0",

View File

@@ -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
},

View File

@@ -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",

View File

@@ -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",

View File

@@ -151,7 +151,7 @@ local RotationKeyframes = {
local InsightParent = {
Identifier = "InsightParent",
Parent = mars.Identifier,
Parent = mars.Mars.Identifier,
Transform = {
Translation ={
Type = "TimelineTranslation",

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