Merge branch 'master' into feature/horizons-framework

This commit is contained in:
Malin E
2022-03-30 13:52:03 +02:00
64 changed files with 3189 additions and 156 deletions
+28 -1
View File
@@ -44,6 +44,13 @@ set(HEADER_FILES
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
)
set(SOURCE_FILES
@@ -66,6 +73,13 @@ set(SOURCE_FILES
src/profile/timedialog.cpp
src/profile/profileedit.cpp
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/windowcontrol.cpp
)
set(HEADER_SOURCE
@@ -85,6 +99,13 @@ set(HEADER_SOURCE
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)
@@ -116,7 +137,13 @@ endif()
add_library(openspace-ui-launcher STATIC ${HEADER_FILES} ${SOURCE_FILES} ${MOC_FILES} ${RESOURCE_FILES})
set_openspace_compile_settings(openspace-ui-launcher)
target_include_directories(openspace-ui-launcher PUBLIC include)
target_include_directories(
openspace-ui-launcher
PUBLIC
include
${OPENSPACE_APPS_DIR}/OpenSpace/ext/sgct/include
${OPENSPACE_APPS_DIR}/OpenSpace/ext/sgct/sgct/ext/glm
)
target_link_libraries(
openspace-ui-launcher
PUBLIC
@@ -27,7 +27,9 @@
#include <QMainWindow>
#include "sgctedit/sgctedit.h"
#include <openspace/scene/profile.h>
#include <QApplication>
#include <optional>
namespace openspace::configuration { struct Configuration; }
@@ -82,6 +84,7 @@ private:
void setBackgroundImage(const std::string& syncPath);
void openProfileEditor(const std::string& profile, bool isUserProfile);
void openWindowEditor();
void populateProfilesList(std::string preset);
void populateWindowConfigsList(std::string preset);
@@ -0,0 +1,101 @@
/*****************************************************************************************
* *
* 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___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 <vector>
class DisplayWindowUnion : 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
* 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.
*/
DisplayWindowUnion(std::shared_ptr<MonitorBox> monitorRenderBox,
std::vector<QRect>& monitorSizeList, unsigned int nMaxWindows,
const std::array<QColor, 4>& winColors);
/**
* Returns a vector of pointers to all WindowControl objects for all 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;
private slots:
void addWindow();
void removeWindow();
private:
void initializeWindowControl();
void initializeLayout();
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;
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__
@@ -0,0 +1,119 @@
/*****************************************************************************************
* *
* 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__
@@ -0,0 +1,126 @@
/*****************************************************************************************
* *
* 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___MONITORBOX___H__
#define __OPENSPACE_UI_LAUNCHER___MONITORBOX___H__
#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 {
Q_OBJECT
public:
/**
* Constructor for MonitorBox class, which displays the system's monitor(s),
* their relative position and size, and window(s) that they contain
*
* \param widgetDims The size of the display widget in pixels, stored in QRect
* \param monitorResolution A vector containing the monitor's maximum display
* size in pixels in a QRect object
* \param nWindows The current number of windows that has been selected by the user
* \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);
/**
* 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
*
* \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);
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);
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}
};
unsigned 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__
@@ -0,0 +1,83 @@
/*****************************************************************************************
* *
* 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___ORIENTATION___H__
#define __OPENSPACE_UI_LAUNCHER___ORIENTATION___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 {
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);
/**
* Gets the user-provided x,y,z orientation values (degrees)
*
* \return the orientation angles provided in sgct::quat object
*/
sgct::quat orientationValue() const;
/**
* Gets the value for if VSync is enabled
*
* \return true if the VSync option is checked/enabled
*/
bool vsyncValue() const;
private slots:
void orientationDialog();
private:
sgct::quat _orientationValue = {0.f, 0.f, 0.f, 0.f};
OrientationDialog _orientationDialog;
QHBoxLayout* _layoutOrientationFull = nullptr;
QCheckBox* _checkBoxVsync = nullptr;
};
#endif // __OPENSPACE_UI_LAUNCHER___ORIENTATION___H__
@@ -0,0 +1,59 @@
/*****************************************************************************************
* *
* 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___ORIENTATIONDIALOG___H__
#define __OPENSPACE_UI_LAUNCHER___ORIENTATIONDIALOG___H__
#include <QDialog>
#include <sgct/config.h>
#include <QLineEdit>
#include <glm/gtc/constants.hpp>
class QWidget;
class OrientationDialog : public QDialog {
Q_OBJECT
public:
/**
* Constructor for OrientationDialog object which contains the input text boxes for
* orientation x,y,z values
*
* \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:
QLineEdit* _linePitch = nullptr;
QLineEdit* _lineRoll = nullptr;
QLineEdit* _lineYaw = nullptr;
sgct::quat& _orientationValue;
};
#endif // __OPENSPACE_UI_LAUNCHER___ORIENTATIONDIALOG___H__
@@ -0,0 +1,105 @@
/*****************************************************************************************
* *
* 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___SGCTEDIT___H__
#define __OPENSPACE_UI_LAUNCHER___SGCTEDIT___H__
#include <QDialog>
#include <sgctedit/displaywindowunion.h>
#include <sgctedit/filesupport.h>
#include <sgctedit/monitorbox.h>
#include <sgctedit/orientation.h>
#include <QApplication>
#include <QColor>
#include <QLayout>
#include <QScreen>
#include <memory>
#include <string>
#include <vector>
class QWidget;
class SgctEdit final : public QDialog {
Q_OBJECT
public:
/**
* Constructor for SgctEdit class, the underlying class for the full window
* 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;
/**
* Returns the saved filename
*
* \return saved filename in std::string
*/
std::string saveFilename();
private:
void addDisplayLayout(QHBoxLayout* layout);
void createWidgets();
void systemMonitorConfiguration(const QList<QScreen*>& screenList);
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;
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)
};
};
#endif // __OPENSPACE_UI_LAUNCHER___SGCTEDIT___H__
@@ -0,0 +1,251 @@
/*****************************************************************************************
* *
* 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___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 <vector>
class WindowControl : public QWidget {
Q_OBJECT
public:
/**
* Constructor for WindowControl class, which contains settings and configuration
* for individual windows
*
* \param monitorIndex The zero-based index for monitor number that this window
* 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)
*/
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);
/**
* 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
*/
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 {
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 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);
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;
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;
QLineEdit* _windowName = nullptr;
QIcon _lockIcon;
QIcon _unlockIcon;
};
#endif // __OPENSPACE_UI_LAUNCHER___WINDOWCONTROL___H__
Binary file not shown.

After

Width:  |  Height:  |  Size: 278 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.4 KiB

@@ -3,5 +3,7 @@
<file>qss/launcher.qss</file>
<file>images/openspace-horiz-logo-small.png</file>
<file>images/launcher-background.png</file>
<file>images/outline_locked.png</file>
<file>images/outline_unlocked.png</file>
</qresource>
</RCC>
@@ -40,6 +40,7 @@
#include <fstream>
#include <iostream>
#include <random>
#include <sgct/readconfig.h>
using namespace openspace;
@@ -61,18 +62,24 @@ namespace {
constexpr const QRect ProfileBox(
LeftRuler, TopRuler + 110, ItemWidth, ItemHeight
);
constexpr const QRect OptionsLabel(LeftRuler, TopRuler + 180, 151, 24);
constexpr const QRect NewProfileButton(
LeftRuler + 140, TopRuler + 180, SmallItemWidth, SmallItemHeight
);
constexpr const QRect EditProfileButton(
LeftRuler, TopRuler + 180, SmallItemWidth, SmallItemHeight
);
constexpr const QRect OptionsLabel(LeftRuler, TopRuler + 230, 151, 24);
constexpr const QRect WindowConfigBox(
LeftRuler, TopRuler + 210, ItemWidth, ItemHeight
LeftRuler, TopRuler + 260, ItemWidth, ItemHeight
);
constexpr const QRect NewWindowButton(
LeftRuler + 140, TopRuler + 330, SmallItemWidth, SmallItemHeight
);
constexpr const QRect EditWindowButton(
LeftRuler, TopRuler + 330, SmallItemWidth, SmallItemHeight
);
constexpr const QRect StartButton(
LeftRuler, TopRuler + 290, ItemWidth, ItemHeight
);
constexpr const QRect NewButton(
LeftRuler + 140, TopRuler + 380, SmallItemWidth, SmallItemHeight
);
constexpr const QRect EditButton(
LeftRuler, TopRuler + 380, SmallItemWidth, SmallItemHeight
LeftRuler, TopRuler + 400, ItemWidth, ItemHeight
);
} // geometry
@@ -134,6 +141,25 @@ namespace {
);
}
}
void saveWindowConfig(QWidget* parent, const std::string& path,
sgct::config::Cluster& cluster)
{
std::ofstream outFile;
try {
outFile.open(path, std::ofstream::out);
outFile << sgct::serializeConfig(cluster);
}
catch (const std::ofstream::failure& e) {
QMessageBox::critical(
parent,
"Exception",
QString::fromStdString(fmt::format(
"Error writing data to file: {} ({})", path, e.what()
))
);
}
}
} // namespace
using namespace openspace;
@@ -248,20 +274,20 @@ QWidget* LauncherWindow::createCentralWidget() {
startButton->setGeometry(geometry::StartButton);
startButton->setCursor(Qt::PointingHandCursor);
QPushButton* newButton = new QPushButton("New", centralWidget);
QPushButton* newProfileButton = new QPushButton("New", centralWidget);
connect(
newButton, &QPushButton::released,
newProfileButton, &QPushButton::released,
[this]() {
openProfileEditor("", true);
}
);
newButton->setObjectName("small");
newButton->setGeometry(geometry::NewButton);
newButton->setCursor(Qt::PointingHandCursor);
newProfileButton->setObjectName("small");
newProfileButton->setGeometry(geometry::NewProfileButton);
newProfileButton->setCursor(Qt::PointingHandCursor);
QPushButton* editButton = new QPushButton("Edit", centralWidget);
QPushButton* editProfileButton = new QPushButton("Edit", centralWidget);
connect(
editButton, &QPushButton::released,
editProfileButton, &QPushButton::released,
[this]() {
const std::string selection = _profileBox->currentText().toStdString();
int selectedIndex = _profileBox->currentIndex();
@@ -269,9 +295,20 @@ QWidget* LauncherWindow::createCentralWidget() {
openProfileEditor(selection, isUserProfile);
}
);
editButton->setObjectName("small");
editButton->setGeometry(geometry::EditButton);
editButton->setCursor(Qt::PointingHandCursor);
editProfileButton->setObjectName("small");
editProfileButton->setGeometry(geometry::EditProfileButton);
editProfileButton->setCursor(Qt::PointingHandCursor);
QPushButton* newWindowButton = new QPushButton("New", centralWidget);
connect(
newWindowButton, &QPushButton::released,
[this]() {
openWindowEditor();
}
);
newWindowButton->setObjectName("small");
newWindowButton->setGeometry(geometry::NewWindowButton);
newWindowButton->setCursor(Qt::PointingHandCursor);
return centralWidget;
}
@@ -354,13 +391,18 @@ void LauncherWindow::populateProfilesList(std::string preset) {
++_userAssetCount;
// Add all the files with the .profile extension to the dropdown
std::vector<fs::directory_entry> profiles;
for (const fs::directory_entry& p : fs::directory_iterator(_userProfilePath)) {
if (p.path().extension() != ".profile") {
continue;
}
_profileBox->addItem(QString::fromStdString(p.path().stem().string()));
profiles.push_back(p);
++_userAssetCount;
}
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("--- OpenSpace Profiles ---"));
model = qobject_cast<const QStandardItemModel*>(_profileBox->model());
@@ -368,11 +410,17 @@ void LauncherWindow::populateProfilesList(std::string preset) {
++_userAssetCount;
// Add all the files with the .profile extension to the dropdown
for (const fs::directory_entry& p : fs::directory_iterator(_profilePath)) {
if (p.path().extension() != ".profile") {
profiles.clear();
for (const fs::directory_entry& path : fs::directory_iterator(_profilePath)) {
if (path.path().extension() != ".profile") {
continue;
}
_profileBox->addItem(QString::fromStdString(p.path().stem().string()));
profiles.push_back(path);
}
std::sort(profiles.begin(), profiles.end());
//add sorted items to list
for (const fs::directory_entry& profile : profiles) {
_profileBox->addItem(QString::fromStdString(profile.path().stem().string()));
}
// Try to find the requested profile and set it as the current one
@@ -414,8 +462,15 @@ void LauncherWindow::populateWindowConfigsList(std::string preset) {
bool hasXmlConfig = false;
// Add all the files with the .xml or .json extension to the dropdown
//sort files
std::vector<fs::directory_entry> files;
for (const fs::directory_entry& p : fs::directory_iterator(_userConfigPath)) {
files.push_back(p);
}
std::sort(files.begin(), files.end());
// Add all the files with the .xml or .json extension to the dropdown
for (const fs::directory_entry& p : files) {
bool isConfigFile = handleConfigurationFile(*_windowConfigBox, p);
if (isConfigFile) {
++_userConfigCount;
@@ -428,8 +483,14 @@ void LauncherWindow::populateWindowConfigsList(std::string preset) {
model->item(_userConfigCount)->setEnabled(false);
if (std::filesystem::exists(_configPath)) {
// Add all the files with the .xml or .json extension to the dropdown
//sort files
files.clear();
for (const fs::directory_entry& p : fs::directory_iterator(_configPath)) {
files.push_back(p);
}
std::sort(files.begin(), files.end());
// Add all the files with the .xml or .json extension to the dropdown
for (const fs::directory_entry& p : files) {
handleConfigurationFile(*_windowConfigBox, p);
hasXmlConfig |= p.path().extension() == ".xml";
}
@@ -452,6 +513,8 @@ void LauncherWindow::populateWindowConfigsList(std::string preset) {
);
}
//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
// list we need to add a preset that doesn't exist a file for
@@ -461,8 +524,11 @@ void LauncherWindow::populateWindowConfigsList(std::string preset) {
}
else {
// Add the requested preset at the top
_windowConfigBox->insertItem(0, QString::fromStdString(preset));
_windowConfigBox->setCurrentIndex(0);
_windowConfigBox->insertItem(1, QString::fromStdString(preset));
//Increment the user config count because there is an additional option added
//before the user config options
_userConfigCount++;
_windowConfigBox->setCurrentIndex(1);
}
}
@@ -500,6 +566,44 @@ 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);
}
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);
}
}
bool LauncherWindow::wasLaunchSelected() const {
return _shouldLaunch;
}
@@ -0,0 +1,179 @@
/*****************************************************************************************
* *
* 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/displaywindowunion.h"
#include <ghoul/fmt.h>
#include "sgctedit/monitorbox.h"
#include "sgctedit/windowcontrol.h"
#include <QApplication>
#include <QMainWindow>
#include <QScreen>
#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)
{
_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();
}
void DisplayWindowUnion::initializeLayout() {
QVBoxLayout* layout = new QVBoxLayout(this);
{
QHBoxLayout* layoutMonButton = new QHBoxLayout;
_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
);
_addWindowButton->setToolTip(QString::fromStdString(addTip));
_addWindowButton->setFocusPolicy(Qt::NoFocus);
_removeWindowButton->setFocusPolicy(Qt::NoFocus);
layoutMonButton->addWidget(_removeWindowButton);
layoutMonButton->addStretch(1);
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();
frameForNextWindow->setFrameShape(QFrame::VLine);
_frameBorderLines.push_back(frameForNextWindow);
layoutWindows->addWidget(frameForNextWindow);
}
}
_nWindowsDisplayed = 1;
showWindows();
layout->addLayout(layoutWindows);
}
std::vector<std::shared_ptr<WindowControl>> DisplayWindowUnion::windowControls() const {
return _windowControl;
}
unsigned int DisplayWindowUnion::nWindows() const {
return _nWindowsDisplayed;
}
void DisplayWindowUnion::addWindow() {
if (_nWindowsDisplayed < _nMaxWindows) {
_windowControl[_nWindowsDisplayed]->resetToDefaults();
_nWindowsDisplayed++;
showWindows();
}
}
void DisplayWindowUnion::removeWindow() {
if (_nWindowsDisplayed > 1) {
_nWindowsDisplayed--;
showWindows();
}
}
void DisplayWindowUnion::showWindows() {
for (size_t i = 0; i < _layoutWindowWrappers.size(); ++i) {
_layoutWindowWrappers[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) {
w->showWindowLabel(_nWindowsDisplayed > 1);
}
_monBox->setNumWindowsDisplayed(_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++;
}
}
@@ -0,0 +1,291 @@
/*****************************************************************************************
* *
* 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();
}
@@ -0,0 +1,255 @@
/*****************************************************************************************
* *
* 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/monitorbox.h"
constexpr float MarginFractionOfWidgetSize = 0.05f;
MonitorBox::MonitorBox(QRect widgetDims, std::vector<QRect> monitorResolution,
unsigned int nWindows, const std::array<QColor, 4>& winColors)
: _monitorWidgetSize(widgetDims)
, _monitorResolution(monitorResolution)
, _nWindows(nWindows)
, _colorsForWindows(winColors)
{
_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);
}
else {
borderMargin *= _monitorWidgetSize.height();
_monitorWidgetSize.setWidth(_monitorWidgetSize.height()
* _monitorArrangementAspectRatio + borderMargin);
}
this->setFixedSize(_monitorWidgetSize.width(), _monitorWidgetSize.height());
mapMonitorResolutionToWidgetCoordinates();
}
void MonitorBox::paintEvent(QPaintEvent* event) {
Q_UNUSED(event)
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) {
constexpr int Radius = 10;
painter.setPen(QPen(Qt::gray, 4));
painter.drawRoundedRect(0, 0, width - 1, height - 1, Radius, Radius);
}
void MonitorBox::paintMonitorBackgrounds(QPainter& painter) {
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");
}
}
}
}
}
void MonitorBox::paintWindowBeyondBounds(QPainter& painter, unsigned int winIdx) {
painter.setBrush(Qt::BDiagPattern);
setPenSpecificToWindow(painter, winIdx, false);
if (winIdx <= _windowRendering.size()) {
painter.drawRect(_windowRendering[winIdx]);
}
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);
}
}
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,
});
}
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
});
}
}
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
});
}
}
void MonitorBox::setNumWindowsDisplayed(unsigned 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();
}
@@ -0,0 +1,73 @@
/*****************************************************************************************
* *
* 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/orientation.h"
#include "sgctedit/orientationdialog.h"
Orientation::Orientation()
: _orientationDialog(_orientationValue, this)
{
_layoutOrientationFull = new QHBoxLayout;
{
QVBoxLayout* layoutOrientationControls = new QVBoxLayout;
QPushButton* orientationButton = new QPushButton("Global Orientation");
_checkBoxVsync = new QCheckBox("VSync All Windows", this);
_checkBoxVsync->setToolTip(
"If enabled, the server will frame lock and wait for all client nodes"
);
layoutOrientationControls->addWidget(_checkBoxVsync);
orientationButton->setToolTip(
"Opens a separate dialog for setting the pitch, "
"yaw, and roll of the camera\n(the orientation applies to all viewports)"
);
orientationButton->setFocusPolicy(Qt::NoFocus);
layoutOrientationControls->addWidget(orientationButton);
_layoutOrientationFull->addStretch(1);
_layoutOrientationFull->addLayout(layoutOrientationControls);
_layoutOrientationFull->addStretch(1);
connect(
orientationButton,
&QPushButton::released,
this,
&Orientation::orientationDialog
);
}
}
void Orientation::addControlsToParentLayout(QVBoxLayout* parentLayout) {
parentLayout->addLayout(_layoutOrientationFull);
}
void Orientation::orientationDialog() {
_orientationDialog.exec();
}
sgct::quat Orientation::orientationValue() const {
return _orientationValue;
}
bool Orientation::vsyncValue() const {
return (_checkBoxVsync->checkState() == Qt::Checked);
}
@@ -0,0 +1,119 @@
/*****************************************************************************************
* *
* 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/orientationdialog.h"
#include "sgctedit/displaywindowunion.h"
OrientationDialog::OrientationDialog(sgct::quat& orientation, QWidget* parent)
: QDialog(parent)
, _orientationValue(orientation)
{
setWindowTitle("Global Orientation");
QVBoxLayout* layoutWindow = new QVBoxLayout(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.";
labelPitch->setToolTip(pitchTip);
_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);
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.";
labelRoll->setToolTip(rollTip);
_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);
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.";
labelYaw->setToolTip(yawTip);
_lineYaw->setToolTip(yawTip);
layoutYaw->addWidget(labelYaw);
layoutYaw->addWidget(_lineYaw);
layoutWindow->addLayout(layoutYaw);
}
{
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);
}
}
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.w = 1.0;
accept();
}
void OrientationDialog::cancel() {
reject();
}
@@ -0,0 +1,139 @@
/*****************************************************************************************
* *
* 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/sgctedit.h"
#include <QFileDialog>
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();
}
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
};
_fileSupportWidget = new FileSupport(
layoutMainV,
userCfg,
sgctCfg,
[this](bool accepted) {
if (accepted) {
_saveSelected = true;
accept();
}
else {
reject();
}
}
);
}
}
void SgctEdit::addDisplayLayout(QHBoxLayout* layout) {
_displayLayout = new QVBoxLayout;
_displayWidget = std::make_shared<DisplayWindowUnion>(
_monBox,
_monitorSizeList,
_nMaxWindows,
_colorsForWindows
);
_displayFrame = new QFrame;
_displayLayout->addWidget(_displayWidget.get());
_displayFrame->setLayout(_displayLayout);
_displayFrame->setFrameStyle(QFrame::StyledPanel | QFrame::Plain);
layout->addWidget(_displayFrame);
}
bool SgctEdit::wasSaved() const {
return _saveSelected;
}
std::string SgctEdit::saveFilename() {
return _fileSupportWidget->saveFilename();
}
SgctEdit::~SgctEdit() {
delete _orientationWidget;
delete _fileSupportWidget;
delete _displayLayout;
}
@@ -0,0 +1,677 @@
/*****************************************************************************************
* *
* 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/windowcontrol.h"
#include <ghoul/fmt.h>
#include "sgctedit/displaywindowunion.h"
#include "sgctedit/monitorbox.h"
const std::string ProjectionTypeNames[5] = {"Planar", "Fisheye", "Spherical Mirror",
"Cylindrical", "Equirectangular"};
QList<QString> ProjectionTypes = {
QString::fromStdString(ProjectionTypeNames[static_cast<int>(
WindowControl::ProjectionIndeces::Planar)]),
QString::fromStdString(ProjectionTypeNames[static_cast<int>(
WindowControl::ProjectionIndeces::Fisheye)]),
QString::fromStdString(ProjectionTypeNames[static_cast<int>(
WindowControl::ProjectionIndeces::SphericalMirror)]),
QString::fromStdString(ProjectionTypeNames[static_cast<int>(
WindowControl::ProjectionIndeces::Cylindrical)]),
QString::fromStdString(ProjectionTypeNames[static_cast<int>(
WindowControl::ProjectionIndeces::Equirectangular)])
};
const QList<QString> QualityTypes = {
"Low (256)",
"Medium (512)",
"High (1K)",
"1.5K (1536)",
"2K (2048)",
"4K (4096)",
"8K (8192)",
"16K (16384)",
"32K (32768)",
"64K (65536)"
};
WindowControl::WindowControl(unsigned int monitorIndex, unsigned int windowIndex,
std::vector<QRect>& monitorDims,
const QColor& winColor, QWidget *parent)
: QWidget(parent)
, _monIndex(monitorIndex)
, _monIndexDefault(monitorIndex)
, _index(windowIndex)
, _monitorResolutions(monitorDims)
, _colorForWindow(winColor)
{
Q_INIT_RESOURCE(resources);
_nMonitors = static_cast<unsigned int>(_monitorResolutions.size());
createWidgets(parent);
resetToDefaults();
}
WindowControl::~WindowControl() {
delete _layoutFullWindow;
}
void WindowControl::resetToDefaults() {
determineIdealWindowSize();
_windowName->setText("");
_monIndex = _monIndexDefault;
if (_nMonitors > 1) {
_comboMonitorSelect->setCurrentIndex(_monIndexDefault);
}
_checkBoxWindowDecor->setCheckState(Qt::CheckState::Checked);
_checkBoxWebGui->setCheckState(Qt::CheckState::Unchecked);
onWebGuiSelection(_checkBoxWebGui->checkState());
_checkBoxSpoutOutput->setCheckState(Qt::CheckState::Unchecked);
onSpoutSelection(_checkBoxSpoutOutput->checkState());
_comboProjection->setCurrentIndex(static_cast<int>(ProjectionIndeces::Planar));
onProjectionChanged(_comboProjection->currentIndex());
_lineFovH->setText(QString::number(_defaultFovH));
_lineFovV->setText(QString::number(_defaultFovV));
_lineHeightOffset->setText(QString::number(_defaultHeightOffset));
_comboQuality->setCurrentIndex(2);
if (_windowChangeCallback) {
_windowChangeCallback(_monIndex, _index, _windowDims);
}
}
void WindowControl::determineIdealWindowSize() {
constexpr float idealAspectRatio = 16.f / 9.f;
constexpr float idealScaleVerticalLines = 2.f / 3.f;
const unsigned int primaryMonitorIdx = 0;
_windowDims = defaultWindowSizes[_index];
_offsetX->setText(QString::number(_windowDims.x()));
_offsetY->setText(QString::number(_windowDims.y()));
float newHeight = static_cast<float>(_monitorResolutions[primaryMonitorIdx].height())
* idealScaleVerticalLines;
float newWidth = newHeight * idealAspectRatio;
_windowDims.setHeight(newHeight);
_windowDims.setWidth(newWidth);
_sizeX->setText(QString::number(static_cast<int>(newWidth)));
_sizeY->setText(QString::number(static_cast<int>(newHeight)));
}
QString WindowControl::resolutionLabelText(QRect resolution) {
return QString::number(resolution.width()) + "x" +
QString::number(resolution.height());
}
void WindowControl::createWidgets(QWidget* parent) {
_windowName = new QLineEdit(parent);
_sizeX = new QLineEdit(parent);
_sizeY = new QLineEdit(parent);
_offsetX = new QLineEdit(parent);
_offsetY = new QLineEdit(parent);
_labelQuality = new QLabel;
_labelFovH = new QLabel;
_labelFovV = new QLabel;
_labelHeightOffset = new QLabel;
_buttonLockAspectRatio = new QPushButton(parent);
_buttonLockFov = new QPushButton(parent);
_lockIcon.addPixmap(QPixmap(":/images/outline_locked.png"));
_unlockIcon.addPixmap(QPixmap(":/images/outline_unlocked.png"));
_buttonLockAspectRatio->setIcon(_unlockIcon);
_buttonLockFov->setIcon(_lockIcon);
{
QIntValidator* validatorSizeX = new QIntValidator(10, _maxWindowSizePixels);
QIntValidator* validatorSizeY = new QIntValidator(10, _maxWindowSizePixels);
QIntValidator* validatorOffsetX = new QIntValidator(
-_maxWindowSizePixels,
_maxWindowSizePixels
);
QIntValidator* validatorOffsetY = new QIntValidator(
-_maxWindowSizePixels,
_maxWindowSizePixels
);
_sizeX->setValidator(validatorSizeX);
_sizeY->setValidator(validatorSizeY);
_offsetX->setValidator(validatorOffsetX);
_offsetY->setValidator(validatorOffsetY);
}
if (_nMonitors > 1) {
_comboMonitorSelect = new QComboBox(this);
for (unsigned int i = 0; i < _nMonitors; ++i) {
_monitorNames[i] += " (" + resolutionLabelText(_monitorResolutions[i]) + ")";
}
_comboMonitorSelect->addItems(_monitorNames);
_comboMonitorSelect->setCurrentIndex(_monIndexDefault);
}
_fullscreenButton = new QPushButton(this);
_fullscreenButton->setText("Set to Fullscreen");
_checkBoxWindowDecor = new QCheckBox("Window Decoration", this);
_checkBoxWindowDecor->setCheckState(Qt::CheckState::Checked);
_checkBoxWebGui = new QCheckBox("WebGUI only this window", this);
_checkBoxSpoutOutput = new QCheckBox("Spout Output", this);
_comboProjection = new QComboBox(this);
_comboProjection->addItems(ProjectionTypes);
_comboQuality = new QComboBox(this);
_comboQuality->addItems(QualityTypes);
{
_lineFovH = new QLineEdit(QString::number(_defaultFovH), parent);
_lineFovV = new QLineEdit(QString::number(_defaultFovV), parent);
QDoubleValidator* validatorFovH = new QDoubleValidator(-180.0, 180.0, 10);
_lineFovH->setValidator(validatorFovH);
QDoubleValidator* validatorFovV = new QDoubleValidator(-90.0, 90.0, 10);
_lineFovV->setValidator(validatorFovV);
_lineHeightOffset = new QLineEdit(QString::number(_defaultHeightOffset), parent);
QDoubleValidator* validatorHtOff= new QDoubleValidator(-1000000.0, 1000000.0, 12);
_lineHeightOffset->setValidator(validatorHtOff);
}
connect(_sizeX, &QLineEdit::textChanged, this, &WindowControl::onSizeXChanged);
connect(_sizeY, &QLineEdit::textChanged, this, &WindowControl::onSizeYChanged);
connect(_offsetX, &QLineEdit::textChanged, this, &WindowControl::onOffsetXChanged);
connect(_offsetY, &QLineEdit::textChanged, this, &WindowControl::onOffsetYChanged);
if (_nMonitors > 1) {
connect(
_comboMonitorSelect,
qOverload<int>(&QComboBox::currentIndexChanged),
this,
&WindowControl::onMonitorChanged
);
}
connect(
_comboProjection,
qOverload<int>(&QComboBox::currentIndexChanged),
this,
&WindowControl::onProjectionChanged
);
connect(
_checkBoxSpoutOutput,
&QCheckBox::stateChanged,
this,
&WindowControl::onSpoutSelection
);
connect(
_checkBoxWebGui,
&QCheckBox::stateChanged,
this,
&WindowControl::onWebGuiSelection
);
connect(
_fullscreenButton,
&QPushButton::released,
this,
&WindowControl::onFullscreenClicked
);
connect(
_buttonLockAspectRatio,
&QPushButton::released,
this,
&WindowControl::onAspectRatioLockClicked
);
connect(
_buttonLockFov,
&QPushButton::released,
this,
&WindowControl::onFovLockClicked
);
}
QVBoxLayout* WindowControl::initializeLayout() {
_layoutFullWindow = new QVBoxLayout;
//Window size
QVBoxLayout* layoutWindowCtrl = new QVBoxLayout;
_labelWinNum = new QLabel;
_labelWinNum->setText("Window " + QString::number(_index + 1));
QString colorStr = QString::fromStdString(
fmt::format("QLabel {{ color : #{:02x}{:02x}{:02x}; }}",
_colorForWindow.red(), _colorForWindow.green(), _colorForWindow.blue()));
_labelWinNum->setStyleSheet(colorStr);
QHBoxLayout* layoutWinNum = new QHBoxLayout;
layoutWinNum->addStretch(1);
layoutWinNum->addWidget(_labelWinNum);
layoutWinNum->addStretch(1);
layoutWindowCtrl->addLayout(layoutWinNum);
{
QHBoxLayout* layoutName = new QHBoxLayout;
QString tip("Enter a name for the window (displayed in title bar)");
QLabel* labelName = new QLabel(this);
labelName->setText("Name: ");
labelName->setToolTip(tip);
_windowName->setFixedWidth(160);
_windowName->setToolTip(tip);
layoutName->addWidget(labelName);
layoutName->addWidget(_windowName);
layoutName->addStretch(1);
layoutWindowCtrl->addLayout(layoutName);
}
if (_nMonitors > 1) {
QHBoxLayout* layoutMonitorNum = new QHBoxLayout;
QLabel* labelLocation = new QLabel(this);
labelLocation->setText("Monitor: ");
QString tip("Select monitor where this window is located");
labelLocation->setToolTip(tip);
_comboMonitorSelect->setToolTip(tip);
layoutMonitorNum->addWidget(labelLocation);
layoutMonitorNum->addWidget(_comboMonitorSelect);
layoutMonitorNum->addStretch(1);
layoutWindowCtrl->addLayout(layoutMonitorNum);
}
_sizeX->setFixedWidth(_lineEditWidthFixedWinSize);
_sizeY->setFixedWidth(_lineEditWidthFixedWinSize);
{
QLabel* labelSize = new QLabel(this);
QLabel* labelDelim = new QLabel(this);
QLabel* labelUnit = new QLabel(this);
QHBoxLayout* layoutSize = new QHBoxLayout;
labelSize->setToolTip("Enter window width & height in pixels");
_sizeX->setToolTip("Enter window width (pixels)");
_sizeY->setToolTip("Enter window height (pixels)");
_buttonLockAspectRatio->setFocusPolicy(Qt::NoFocus);
_buttonLockAspectRatio->setToolTip("Locks/Unlocks size aspect ratio");
layoutSize->addWidget(labelSize);
labelSize->setText("Size:");
labelSize->setFixedWidth(55);
layoutSize->addWidget(_sizeX);
layoutSize->addWidget(labelDelim);
layoutSize->addWidget(_sizeY);
layoutSize->addWidget(labelUnit);
layoutSize->addWidget(_buttonLockAspectRatio);
layoutSize->addStretch(1);
labelDelim->setText("x");
labelDelim->setFixedWidth(9);
labelUnit->setText(" px");
layoutWindowCtrl->addLayout(layoutSize);
}
_offsetX->setFixedWidth(_lineEditWidthFixedWinSize);
_offsetY->setFixedWidth(_lineEditWidthFixedWinSize);
{
QLabel* labelOffset = new QLabel(this);
QLabel* labelComma = new QLabel(this);
QLabel* labelUnit = new QLabel(this);
QHBoxLayout* layoutOffset = new QHBoxLayout;
std::string baseTip = "Enter {} location of window's upper left "
"corner from monitor's {} (pixels)";
labelOffset->setToolTip(QString::fromStdString(fmt::format(
baseTip, "x,y", "upper-left corner origin")));
_offsetX->setToolTip(QString::fromStdString(fmt::format(
baseTip, "x", "left side")));
_offsetY->setToolTip(QString::fromStdString(fmt::format(
baseTip, "y", "top edge")));
layoutOffset->addWidget(labelOffset);
labelOffset->setText("Offset:");
labelOffset->setFixedWidth(55);
layoutOffset->addWidget(_offsetX);
layoutOffset->addWidget(labelComma);
layoutOffset->addWidget(_offsetY);
layoutOffset->addWidget(labelUnit);
layoutOffset->addStretch(1);
labelComma->setText(",");
labelComma->setFixedWidth(9);
labelUnit->setText(" px");
layoutWindowCtrl->addLayout(layoutOffset);
}
{
QHBoxLayout* layoutCheckboxesFull1 = new QHBoxLayout;
QVBoxLayout* layoutCheckboxesFull2 = new QVBoxLayout;
QHBoxLayout* layoutFullscreenButton = new QHBoxLayout;
_fullscreenButton->setToolTip("If enabled, the window will be created in an "
"exclusive fullscreen mode. The size of this\nwindow will be set to the "
"screen resolution, and the window decoration automatically disabled.");
_fullscreenButton->setFocusPolicy(Qt::NoFocus);
layoutFullscreenButton->addWidget(_fullscreenButton);
layoutFullscreenButton->addStretch(1);
layoutCheckboxesFull2->addLayout(layoutFullscreenButton);
QHBoxLayout* layoutCBoxWindowDecor = new QHBoxLayout;
_checkBoxWindowDecor->setToolTip("If enabled, the window will not have a border "
"frame or title bar, and no\n controls for minimizing/maximizing, "
"resizing, or closing the window.");
layoutCBoxWindowDecor->addWidget(_checkBoxWindowDecor);
layoutCBoxWindowDecor->addStretch(1);
layoutCheckboxesFull2->addLayout(layoutCBoxWindowDecor);
QHBoxLayout* _layoutCBoxWebGui= new QHBoxLayout;
_checkBoxWebGui->setToolTip("If enabled, the window will be dedicated solely to "
"displaying the GUI controls, and will not\nrender any 3D content. All other "
"window(s) will render in 3D but will not have GUI controls.");
_layoutCBoxWebGui->addWidget(_checkBoxWebGui);
_layoutCBoxWebGui->addStretch(1);
layoutCheckboxesFull2->addLayout(_layoutCBoxWebGui);
QVBoxLayout* layoutProjectionGroup = new QVBoxLayout;
QHBoxLayout* layoutComboProjection = new QHBoxLayout;
_comboProjection->setToolTip("Select from the supported window projection types");
layoutComboProjection->addWidget(_comboProjection);
layoutComboProjection->addWidget(_buttonLockFov);
_buttonLockFov->setToolTip("Locks and scales the Horizontal & Vertical F.O.V. "
"to the ideal settings based on aspect ratio.");
_buttonLockFov->setFocusPolicy(Qt::NoFocus);
layoutComboProjection->addStretch(1);
layoutProjectionGroup->addLayout(layoutComboProjection);
QFrame* borderProjectionGroup = new QFrame;
borderProjectionGroup->setFrameStyle(QFrame::StyledPanel | QFrame::Plain);
borderProjectionGroup->setLayout(layoutProjectionGroup);
borderProjectionGroup->setVisible(true);
QHBoxLayout* layoutCBoxSpoutOutput= new QHBoxLayout;
QString spoutTip = "This projection method provides the ability to share the "
"reprojected image using the Spout library.\nThis library only supports the "
"Windows operating system. Spout makes it possible to make the rendered\n"
"images available to other real-time applications on the same machine for "
"further processing.\nThe SpoutOutputProjection option can work with either "
"Fisheye or Equirectangular projection.";
_checkBoxSpoutOutput->setToolTip(spoutTip);
layoutCBoxSpoutOutput->addWidget(_checkBoxSpoutOutput);
layoutCBoxSpoutOutput->addStretch(1);
layoutProjectionGroup->addLayout(layoutCBoxSpoutOutput);
QHBoxLayout* layoutComboQuality = new QHBoxLayout;
_labelQuality->setText("Quality:");
QString qualityTip = "Determines the pixel resolution of the projection "
"rendering. The higher resolution,\nthe better the rendering quality, but at "
"the expense of increased rendering times.";
_labelQuality->setToolTip(qualityTip);
_comboQuality->setToolTip(qualityTip);
layoutComboQuality->addWidget(_labelQuality);
layoutComboQuality->addWidget(_comboQuality);
layoutComboQuality->addStretch(1);
layoutProjectionGroup->addLayout(layoutComboQuality);
QHBoxLayout* layoutFovH = new QHBoxLayout;
_labelFovH->setText("Horizontal FOV:");
QString hfovTip = "The total horizontal field of view of the viewport (degrees). "
"Internally,\nthe values for 'left' & 'right' will each be half this value.";
_labelFovH->setToolTip(hfovTip);
_lineFovH->setToolTip(hfovTip);
layoutFovH->addWidget(_labelFovH);
layoutFovH->addStretch(1);
layoutFovH->addWidget(_lineFovH);
QHBoxLayout* layoutFovV = new QHBoxLayout;
_labelFovV->setText("Vertical FOV:");
QString vfovTip = "The total vertical field of view of the viewport (degrees). "
"Internally,\nthe values for 'up' & 'down' will each be half this value.";
_labelFovV->setToolTip(vfovTip);
_lineFovV->setToolTip(vfovTip);
layoutFovV->addWidget(_labelFovV);
layoutFovV->addStretch(1);
layoutFovV->addWidget(_lineFovV);
_lineFovH->setFixedWidth(_lineEditWidthFixedFov);
_lineFovV->setFixedWidth(_lineEditWidthFixedFov);
_lineFovH->setEnabled(false);
_lineFovV->setEnabled(false);
layoutProjectionGroup->addLayout(layoutFovH);
layoutProjectionGroup->addLayout(layoutFovV);
QHBoxLayout* layoutHeightOffset = new QHBoxLayout;
_labelHeightOffset->setText("Height Offset:");
QString heightTip = "Offsets the height from which the cylindrical projection "
"is generated.\nThis is, in general, only necessary if the user position is "
"offset and\ncountering that offset is desired in order to continue producing"
"\na 'standard' cylindrical projection.";
_labelHeightOffset->setToolTip(heightTip);
_lineHeightOffset->setToolTip(heightTip);
layoutHeightOffset->addWidget(_labelHeightOffset);
layoutHeightOffset->addWidget(_lineHeightOffset);
layoutHeightOffset->addStretch(1);
layoutProjectionGroup->addLayout(layoutHeightOffset);
layoutCheckboxesFull2->addWidget(borderProjectionGroup);
layoutCheckboxesFull1->addLayout(layoutCheckboxesFull2);
layoutCheckboxesFull1->addStretch(1);
layoutWindowCtrl->addLayout(layoutCheckboxesFull1);
}
layoutWindowCtrl->addStretch(1);
_layoutFullWindow->addLayout(layoutWindowCtrl);
_comboProjection->setCurrentIndex(0);
onProjectionChanged(static_cast<unsigned int>(ProjectionIndeces::Planar));
_comboQuality->setCurrentIndex(2);
return _layoutFullWindow;
}
void WindowControl::showWindowLabel(bool show) {
_labelWinNum->setVisible(show);
}
void WindowControl::onSizeXChanged(const QString& newText) {
_windowDims.setWidth(newText.toInt());
if (_aspectRatioLocked) {
int updatedHeight = _windowDims.width() / _aspectRatioSize;
_sizeY->blockSignals(true);
_sizeY->setText(QString::number(updatedHeight));
_sizeY->blockSignals(false);
_windowDims.setHeight(updatedHeight);
}
if (_windowChangeCallback) {
_windowChangeCallback(_monIndex, _index, _windowDims);
}
if (_FovLocked) {
updatePlanarLockedFov();
}
}
void WindowControl::onSizeYChanged(const QString& newText) {
_windowDims.setHeight(newText.toInt());
if (_aspectRatioLocked) {
int updatedWidth = _windowDims.height() * _aspectRatioSize;
_sizeX->blockSignals(true);
_sizeX->setText(QString::number(updatedWidth));
_sizeX->blockSignals(false);
_windowDims.setWidth(updatedWidth);
}
if (_windowChangeCallback) {
_windowChangeCallback(_monIndex, _index, _windowDims);
}
if (_FovLocked) {
updatePlanarLockedFov();
}
}
void WindowControl::onOffsetXChanged(const QString& newText) {
float prevWidth = _windowDims.width();
try {
_windowDims.setX(newText.toInt());
_windowDims.setWidth(prevWidth);
if (_windowChangeCallback) {
_windowChangeCallback(_monIndex, _index, _windowDims);
}
}
catch (std::exception const&) {
//The QIntValidator ensures that the range is a +/- integer
//However, it's possible to enter only a - character which
//causes an exception throw, which is ignored here (when user
//enters an integer after the - then the value will be updated).
}
}
void WindowControl::onOffsetYChanged(const QString& newText) {
float prevHeight = _windowDims.height();
try {
_windowDims.setY(newText.toInt());
_windowDims.setHeight(prevHeight);
if (_windowChangeCallback) {
_windowChangeCallback(_monIndex, _index, _windowDims);
}
}
catch (std::exception const&) {
//See comment in onOffsetXChanged
}
}
void WindowControl::onFullscreenClicked() {
_offsetX->setText("0");
_offsetY->setText("0");
_sizeX->setText(QString::number(_monitorResolutions[_monIndex].width()));
_sizeY->setText(QString::number(_monitorResolutions[_monIndex].height()));
_checkBoxWindowDecor->setCheckState(Qt::Unchecked);
}
void WindowControl::onWebGuiSelection(int selectionState) {
if (_windowGuiCheckCallback && (selectionState == Qt::Checked)) {
_windowGuiCheckCallback(_index);
}
}
void WindowControl::onSpoutSelection(int selectionState) {
if (selectionState == Qt::Checked) {
WindowControl::ProjectionIndeces currentProjectionSelection;
currentProjectionSelection = static_cast<WindowControl::ProjectionIndeces>(
_comboProjection->currentIndex()
);
if ((currentProjectionSelection != ProjectionIndeces::Equirectangular) &&
(currentProjectionSelection != ProjectionIndeces::Fisheye))
{
_comboProjection->setCurrentIndex(
static_cast<int>(ProjectionIndeces::Equirectangular)
);
}
}
}
void WindowControl::onMonitorChanged(int newSelection) {
_monIndex = newSelection;
if (_windowChangeCallback) {
_windowChangeCallback(_monIndex, _index, _windowDims);
}
}
void WindowControl::onProjectionChanged(int newSelection) {
WindowControl::ProjectionIndeces selected
= static_cast<WindowControl::ProjectionIndeces>(newSelection);
_comboQuality->setVisible(selected != ProjectionIndeces::Planar);
_labelQuality->setVisible(selected != ProjectionIndeces::Planar);
_labelFovH->setVisible(selected == ProjectionIndeces::Planar);
_lineFovH->setVisible(selected == ProjectionIndeces::Planar);
_labelFovV->setVisible(selected == ProjectionIndeces::Planar);
_lineFovV->setVisible(selected == ProjectionIndeces::Planar);
_buttonLockFov->setVisible(selected == ProjectionIndeces::Planar);
_labelHeightOffset->setVisible(selected == ProjectionIndeces::Cylindrical);
_lineHeightOffset->setVisible(selected == ProjectionIndeces::Cylindrical);
_checkBoxSpoutOutput->setVisible(selected == ProjectionIndeces::Fisheye
|| selected == ProjectionIndeces::Equirectangular);
}
void WindowControl::onAspectRatioLockClicked() {
_aspectRatioLocked = !_aspectRatioLocked;
_buttonLockAspectRatio->setIcon(_aspectRatioLocked ? _lockIcon : _unlockIcon);
if (_aspectRatioLocked) {
_aspectRatioSize = _windowDims.width() / _windowDims.height();
}
}
void WindowControl::onFovLockClicked() {
_FovLocked = !_FovLocked;
_buttonLockFov->setIcon(_FovLocked ? _lockIcon : _unlockIcon);
if (_FovLocked) {
_lineFovH->setEnabled(false);
_lineFovV->setEnabled(false);
updatePlanarLockedFov();
}
else {
_lineFovH->setEnabled(true);
_lineFovV->setEnabled(true);
}
}
void WindowControl::updatePlanarLockedFov() {
float currentAspectRatio = _windowDims.width() / _windowDims.height();
float relativeRatio = currentAspectRatio / _idealAspectRatio;
if (relativeRatio >= 1.0) {
_lineFovH->setText(QString::number(std::min(_defaultFovH *relativeRatio, 180.f)));
_lineFovV->setText(QString::number(_defaultFovV));
}
else {
_lineFovH->setText(QString::number(_defaultFovH));
_lineFovV->setText(QString::number(std::min(_defaultFovV /relativeRatio, 180.f)));
}
}
void WindowControl::setWindowChangeCallback(
std::function<void(int, int, const QRectF&)> cb)
{
_windowChangeCallback = std::move(cb);
}
void WindowControl::setWebGuiChangeCallback(std::function<void(unsigned int)> cb)
{
_windowGuiCheckCallback = std::move(cb);
}
void WindowControl::uncheckWebGuiOption() {
_checkBoxWebGui->setCheckState(Qt::Unchecked);
}
QRectF& WindowControl::dimensions() {
return _windowDims;
}
std::string WindowControl::windowName() const {
return _windowName->text().toStdString();
}
sgct::ivec2 WindowControl::windowSize() const {
return {
_sizeX->text().toInt(),
_sizeY->text().toInt()
};
}
sgct::ivec2 WindowControl::windowPos() const {
return {
_offsetX->text().toInt(),
_offsetY->text().toInt()
};
}
bool WindowControl::isDecorated() const {
return (_checkBoxWindowDecor->checkState() == Qt::Checked);
}
bool WindowControl::isGuiWindow() const {
return (_checkBoxWebGui->checkState() == Qt::Checked);
}
bool WindowControl::isSpoutSelected() const {
return (_checkBoxSpoutOutput->checkState() == Qt::Checked);
}
WindowControl::ProjectionIndeces WindowControl::projectionSelectedIndex() const {
return
static_cast<WindowControl::ProjectionIndeces>(_comboProjection->currentIndex());
}
int WindowControl::qualitySelectedValue() const {
return QualityValues[_comboQuality->currentIndex()];
}
float WindowControl::fovH() const {
return _lineFovH->text().toFloat();
}
float WindowControl::fovV() const {
return _lineFovV->text().toFloat();
}
float WindowControl::heightOffset() const {
return _lineHeightOffset->text().toFloat();
}
unsigned int WindowControl::monitorNum() const {
return _monIndex;
}
+2 -1
View File
@@ -1044,9 +1044,10 @@ int main(int argc, char* argv[]) {
// to make it possible to find other files in the same directory.
FileSys.registerPathToken(
"${BIN}",
std::filesystem::path(argv[0]).parent_path(),
std::filesystem::current_path() / std::filesystem::path(argv[0]).parent_path(),
ghoul::filesystem::FileSystem::Override::Yes
);
LDEBUG(fmt::format("Registering ${{BIN}} to {}", absPath("${BIN}")));
//
// Parse commandline arguments
@@ -1,3 +1,9 @@
local fullOS = openspace.systemCapabilities.fullOperatingSystem()
if string.find(fullOS, "Darwin") then
openspace.printWarning("Gaia module (RenderableGaiaStars) not supported on mac")
return
end
-- Download a preprocessed binary octree of Radial Velocity subset values per star (preprocessed into 8 binary files).
local starsFolder = asset.syncedResource({
Name = "Gaia Stars RV",
@@ -27,7 +27,7 @@ local images = asset.syncedResource({
Name = "Pluto Images",
Type = "HttpSynchronization",
Identifier = "newhorizons_plutoencounter_pluto_images",
Version = 1
Version = 2
})
local plutoRadius = 1.173E6
@@ -7,9 +7,7 @@ asset.require("./jupiter/europa/default_layers")
asset.require("./jupiter/ganymede/default_layers")
asset.require("./jupiter/io/default_layers")
asset.require("./mars/default_layers")
asset.require("./mars/moons/layers/colorlayers/deimos_viking")
asset.require("./mars/moons/layers/colorlayers/phobos_viking")
asset.require('./mars/default_layers')
asset.require("./mercury/default_layers")
@@ -3,7 +3,7 @@ local globeIdentifier = asset.require("../../mars").Mars.Identifier
local layer = {
Identifier = "Themis_IR_Night_Sweden",
Name = "Themis IR Night [Sweden]",
FilePath = asset.localResource("themis_ir_night_sweden.wms"),
FilePath = asset.localResource("themis_ir_night_sweden.vrt"),
BlendMode = "Color",
Description = [[This mosaic represents the Thermal Emission Imaging System (THEMIS)
-nighttime infrared (IR) 100 meter/pixel mosaic (version 12) released in the
@@ -0,0 +1,26 @@
<VRTDataset rasterXSize="213388" rasterYSize="106695">
<SRS>GEOGCS["GCS_Mars_2000_Sphere",DATUM["D_Mars_2000_Sphere",SPHEROID["Mars_2000_Sphere_IAU_IAG",3396190.0,0.0]],PRIMEM["Reference_Meridian",0.0],UNIT["Degree",0.0174532925199433]]</SRS>
<GeoTransform> -1.8000000000000000e+02, 1.6870676889047182e-03, 0.0000000000000000e+00, 9.0000000000000000e+01, 0.0000000000000000e+00, -1.6870518768452129e-03</GeoTransform>
<VRTRasterBand dataType="Byte" band="1">
<ColorInterp>Gray</ColorInterp>
<SimpleSource>
<SourceFilename relativeToVRT="1">themis_ir_night_sweden.wms</SourceFilename>
<SourceBand>1</SourceBand>
<SourceProperties RasterXSize="213388" RasterYSize="71130" DataType="Byte" BlockXSize="256" BlockYSize="256" />
<SrcRect xOff="0" yOff="0" xSize="213388" ySize="71130" />
<DstRect xOff="0" yOff="17782.5" xSize="213388" ySize="71130" />
</SimpleSource>
</VRTRasterBand>
<VRTRasterBand dataType="Byte" band="2">
<ColorInterp>Alpha</ColorInterp>
<ComplexSource>
<SourceFilename relativeToVRT="1">themis_ir_night_sweden.wms</SourceFilename>
<SourceBand>1</SourceBand>
<SourceProperties RasterXSize="213388" RasterYSize="71130" DataType="Byte" BlockXSize="256" BlockYSize="256" />
<SrcRect xOff="0" yOff="0" xSize="213388" ySize="71130" />
<DstRect xOff="0" yOff="17782.5" xSize="213388" ySize="71130" />
<ScaleRatio>255</ScaleRatio>
<NODATA>0</NODATA>
</ComplexSource>
</VRTRasterBand>
</VRTDataset>
@@ -4,9 +4,9 @@
</Service>
<DataWindow>
<UpperLeftX>-180.0</UpperLeftX>
<UpperLeftY>90.0</UpperLeftY>
<UpperLeftY>60.0</UpperLeftY>
<LowerRightX>180.0</LowerRightX>
<LowerRightY>-90.0</LowerRightY>
<LowerRightY>-60.0</LowerRightY>
<SizeX>213388</SizeX>
<SizeY>71130</SizeY>
<TileLevel>9</TileLevel>
@@ -3,7 +3,7 @@ local globeIdentifier = asset.require("../../mars").Mars.Identifier
local layer = {
Identifier = "Themis_IR_Night_Utah",
Name = "Themis IR Night [Utah]",
FilePath = asset.localResource("themis_ir_night_utah.wms"),
FilePath = asset.localResource("themis_ir_night_utah.vrt"),
BlendMode = "Color",
Description = [[This mosaic represents the Thermal Emission Imaging System (THEMIS)
-nighttime infrared (IR) 100 meter/pixel mosaic (version 12) released in the
@@ -0,0 +1,26 @@
<VRTDataset rasterXSize="213388" rasterYSize="106695">
<SRS>GEOGCS["GCS_Mars_2000_Sphere",DATUM["D_Mars_2000_Sphere",SPHEROID["Mars_2000_Sphere_IAU_IAG",3396190.0,0.0]],PRIMEM["Reference_Meridian",0.0],UNIT["Degree",0.0174532925199433]]</SRS>
<GeoTransform> -1.8000000000000000e+02, 1.6870676889047182e-03, 0.0000000000000000e+00, 9.0000000000000000e+01, 0.0000000000000000e+00, -1.6870518768452129e-03</GeoTransform>
<VRTRasterBand dataType="Byte" band="1">
<ColorInterp>Gray</ColorInterp>
<SimpleSource>
<SourceFilename relativeToVRT="1">themis_ir_night_utah.wms</SourceFilename>
<SourceBand>1</SourceBand>
<SourceProperties RasterXSize="213388" RasterYSize="71130" DataType="Byte" BlockXSize="256" BlockYSize="256" />
<SrcRect xOff="0" yOff="0" xSize="213388" ySize="71130" />
<DstRect xOff="0" yOff="17782.5" xSize="213388" ySize="71130" />
</SimpleSource>
</VRTRasterBand>
<VRTRasterBand dataType="Byte" band="2">
<ColorInterp>Alpha</ColorInterp>
<ComplexSource>
<SourceFilename relativeToVRT="1">themis_ir_night_utah.wms</SourceFilename>
<SourceBand>1</SourceBand>
<SourceProperties RasterXSize="213388" RasterYSize="71130" DataType="Byte" BlockXSize="256" BlockYSize="256" />
<SrcRect xOff="0" yOff="0" xSize="213388" ySize="71130" />
<DstRect xOff="0" yOff="17782.5" xSize="213388" ySize="71130" />
<ScaleRatio>255</ScaleRatio>
<NODATA>0</NODATA>
</ComplexSource>
</VRTRasterBand>
</VRTDataset>
@@ -4,9 +4,9 @@
</Service>
<DataWindow>
<UpperLeftX>-180.0</UpperLeftX>
<UpperLeftY>90.0</UpperLeftY>
<UpperLeftY>60.0</UpperLeftY>
<LowerRightX>180.0</LowerRightX>
<LowerRightY>-90.0</LowerRightY>
<LowerRightY>-60.0</LowerRightY>
<SizeX>213388</SizeX>
<SizeY>71130</SizeY>
<TileLevel>9</TileLevel>
@@ -1,4 +1,13 @@
local transforms = asset.require("../transforms")
local transforms = asset.require('scene/solarsystem/planets/mars/transforms')
local sunTransforms = asset.require('scene/solarsystem/sun/transforms')
local sun = asset.require("scene/solarsystem/sun/sun")
local model = asset.syncedResource({
Name = "Deimos Model",
Type = "HttpSynchronization",
Identifier = "deimos_model",
Version = 1
})
local kernels = asset.syncedResource({
Name = "Mars Spice Kernels",
@@ -25,10 +34,17 @@ local Deimos = {
}
},
Renderable = {
Type = "RenderableGlobe",
Radii = { 15000, 12200, 11000 },
SegmentsPerPatch = 90,
Layers = {}
Type = "RenderableModel",
GeometryFile = model .. "/Deimos_1_1000.glb",
ModelScale = 'Kilometer',
RotationVector = { 180, 0, 180 },
AmbientIntensity = 0.02,
SpecularIntensity = 0.0,
LightSources = {
sun.LightSource
},
PerformShading = true,
DisableFaceCulling = true
},
Tag = { "moon_solarSystem", "moon_terrestrial", "moon_mars" },
GUI = {
@@ -74,11 +90,10 @@ asset.export(Deimos)
asset.export(DeimosTrail)
asset.meta = {
Name = "Deimos",
Version = "1.1",
Description = [[ RenderableGlobe and Trail for Deimos.]],
Version = "1.0",
Description = [[ RenderableModel and Trail for Deimos.]],
Author = "OpenSpace Team",
URL = "http://openspaceproject.com",
License = "MIT license"
@@ -0,0 +1,63 @@
local transforms = asset.require('../transforms')
local kernels = asset.syncedResource({
Name = "Mars Spice Kernels",
Type = "HttpSynchronization",
Identifier = "mars_kernels",
Version = 1
})
local DeimosGlobe = {
Identifier = "Deimos_Globe",
Parent = transforms.MarsBarycenter.Identifier,
Transform = {
Rotation = {
Type = "SpiceRotation",
SourceFrame = "IAU_DEIMOS",
DestinationFrame = "GALACTIC",
Kernels = kernels .. "mar097.bsp"
},
Translation = {
Type = "SpiceTranslation",
Target = "DEIMOS",
Observer = "MARS BARYCENTER",
Kernels = kernels .. "mar097.bsp"
}
},
Renderable = {
Type = "RenderableGlobe",
Radii = { 7500, 6100, 5200 },
--Radius source
--https://sci.esa.int/documents/35171/36506/1567259108230-5-ESLAB46-Day2-Rosenblatt.pdf
SegmentsPerPatch = 90,
Layers = {}
},
Tag = { "moon_solarSystem", "moon_terrestrial", "moon_mars" },
GUI = {
Name = "Deimos_Globe",
Path = "/Solar System/Planets/Mars",
Description = [[One of two moons of Mars.]]
}
}
asset.onInitialize(function()
openspace.addSceneGraphNode(DeimosGlobe)
end)
asset.onDeinitialize(function()
openspace.removeSceneGraphNode(DeimosGlobe)
end)
asset.export(DeimosGlobe)
asset.meta = {
Name = "Deimos Globe",
Version = "1.0",
Description = [[ RenderableGlobe for Deimos.]],
Author = "OpenSpace Team",
URL = "http://openspaceproject.com",
License = "MIT license",
Identifiers = {"Deimos"}
}
@@ -1,4 +1,4 @@
local globeIdentifier = asset.require("../../deimos").Deimos.Identifier
local globeIdentifier = asset.require("./../../deimos_globe").Deimos_Globe.Identifier
local layer = {
Identifier = "Deimos_Global_Mosaic_USGS",
@@ -1,4 +1,4 @@
local globeIdentifier = asset.require("../../phobos").Phobos.Identifier
local globeIdentifier = asset.require("./../../phobos_globe").Phobos_Globe.Identifier
local layer = {
Identifier = "Phobos_Global_Shaded_Relief_USGS",
@@ -1,4 +1,13 @@
local transforms = asset.require("../transforms")
local transforms = asset.require('scene/solarsystem/planets/mars/transforms')
local sunTransforms = asset.require('scene/solarsystem/sun/transforms')
local sun = asset.require("scene/solarsystem/sun/sun")
local model = asset.syncedResource({
Name = "Phobos Model",
Type = "HttpSynchronization",
Identifier = "phobos_model",
Version = 1
})
local kernels = asset.syncedResource({
Name = "Mars Spice Kernels",
@@ -7,6 +16,7 @@ local kernels = asset.syncedResource({
Version = 1
})
local Phobos = {
Identifier = "Phobos",
Parent = transforms.MarsBarycenter.Identifier,
@@ -25,10 +35,17 @@ local Phobos = {
}
},
Renderable = {
Type = "RenderableGlobe",
Radii = { 27000, 22000, 18000 },
SegmentsPerPatch = 90,
Layers = {}
Type = "RenderableModel",
GeometryFile = model .. "/Phobos_1_1000.glb",
ModelScale = 'Kilometer',
RotationVector = { 90, 0, 90 },
AmbientIntensity = 0.02,
SpecularIntensity = 0.0,
LightSources = {
sun.LightSource
},
PerformShading = true,
DisableFaceCulling = true
},
Tag = { "moon_solarSystem", "moon_terrestrial", "moon_mars" },
GUI = {
@@ -46,7 +63,8 @@ local PhobosTrail = {
Translation = {
Type = "SpiceTranslation",
Target = "PHOBOS",
Observer = "MARS BARYCENTER"
Observer = "MARS BARYCENTER",
Kernels = kernels .. "mar097.bsp"
},
Color = { 1.0, 0.605, 0.420 },
Period = 0.31891023,
@@ -77,8 +95,8 @@ asset.export(PhobosTrail)
asset.meta = {
Name = "Phobos",
Version = "1.1",
Description = [[ RenderableGlobe and Trail for Phobos.]],
Version = "1.0",
Description = [[ RenderableModel and Trail for Phobos.]],
Author = "OpenSpace Team",
URL = "http://openspaceproject.com",
License = "MIT license"
@@ -0,0 +1,63 @@
local transforms = asset.require('../transforms')
local kernels = asset.syncedResource({
Name = "Mars Spice Kernels",
Type = "HttpSynchronization",
Identifier = "mars_kernels",
Version = 1
})
local PhobosGlobe = {
Identifier = "Phobos_Globe",
Parent = transforms.MarsBarycenter.Identifier,
Transform = {
Rotation = {
Type = "SpiceRotation",
SourceFrame = "IAU_PHOBOS",
DestinationFrame = "GALACTIC",
Kernels = kernels .. "mar097.bsp"
},
Translation = {
Type = "SpiceTranslation",
Target = "PHOBOS",
Observer = "MARS BARYCENTER",
Kernels = kernels .. "mar097.bsp"
}
},
Renderable = {
Type = "RenderableGlobe",
Radii = { 13030, 11400, 9140 },
--Radius source
--https://naif.jpl.nasa.gov/pub/naif/generic_kernels/dsk/satellites/willner_etal_phobos.pdf
SegmentsPerPatch = 90,
Layers = {}
},
Tag = { "moon_solarSystem", "moon_terrestrial", "moon_mars" },
GUI = {
Name = "Phobos_Globe",
Path = "/Solar System/Planets/Mars",
Description = [[One of two moons of Mars.]]
}
}
asset.onInitialize(function()
openspace.addSceneGraphNode(PhobosGlobe)
end)
asset.onDeinitialize(function()
openspace.removeSceneGraphNode(PhobosGlobe)
end)
asset.export(PhobosGlobe)
asset.meta = {
Name = "Phobos Globe",
Version = "1.0",
Description = [[ RenderableGlobe for Phobos.]],
Author = "OpenSpace Team",
URL = "http://openspaceproject.com",
License = "MIT license",
Identifiers = {"Phobos"}
}
@@ -33,13 +33,15 @@ asset.require("./layers/colorlayers/fesimap_02122015")
asset.require("./layers/colorlayers/mgsimap_02122015")
asset.require("./layers/colorlayers/ssimap_02122015")
asset.require("./layers/heightlayers/messenger_dem_utah")
local heightLayer = asset.require("./layers/heightlayers/messenger_dem_utah")
-- Set enabled layers (temporary solution)
-- @TODO: do this using a boolean that's passed to the 'asset.require' instead
asset.onInitialize(function ()
openspace.setPropertyValueSingle("Scene.Mercury.Renderable.Layers.ColorLayers." ..
colorLayer.layer.Identifier .. ".Enabled", true)
openspace.setPropertyValueSingle("Scene.Mercury.Renderable.Layers.HeightLayers." ..
heightLayer.layer.Identifier .. ".Enabled", true)
end)
@@ -4,6 +4,10 @@ local layer = {
Identifier = "Messenger_DEM_Utah",
Name = "Messenger DEM [Utah]",
FilePath = asset.localResource("messenger_dem_utah.wms"),
Settings = {
Gamma = 1.59,
Multiplier = 1.38
},
TilePixelSize = 64
}
@@ -27,7 +27,7 @@ local Mimas = {
},
Renderable = {
Type = "RenderableGlobe",
Radii = 198000,
Radii = { 207000, 197000, 191000 },
SegmentsPerPatch = 64,
Layers = { },
Labels = {
@@ -235,6 +235,8 @@ void RenderableBoxGrid::update(const UpdateData&) {
_varray.push_back({ v7.x, v7.y, v7.z });
_varray.push_back({ v3.x, v3.y, v3.z });
setBoundingSphere(glm::length(glm::dvec3(urb)));
glBindVertexArray(_vaoID);
glBindBuffer(GL_ARRAY_BUFFER, _vBufferID);
glBufferData(
@@ -243,6 +243,8 @@ void RenderableGrid::update(const UpdateData&) {
_varray[nr++] = { halfSize.x, y1, 0.f };
}
setBoundingSphere(glm::length(glm::dvec2(halfSize)));
glBindVertexArray(_vaoID);
glBindBuffer(GL_ARRAY_BUFFER, _vBufferID);
glBufferData(
@@ -274,6 +274,8 @@ void RenderableRadialGrid::update(const UpdateData&) {
}
_lines.update();
setBoundingSphere(static_cast<double>(outerRadius));
_gridIsDirty = false;
}
@@ -103,6 +103,9 @@ RenderableSphericalGrid::RenderableSphericalGrid(const ghoul::Dictionary& dictio
_lineWidth = p.lineWidth.value_or(_lineWidth);
addProperty(_lineWidth);
// Radius is always 1
setBoundingSphere(1.0);
}
bool RenderableSphericalGrid::isReady() const {
@@ -460,6 +460,9 @@ bool RenderableDUMeshes::readSpeckFile() {
return false;
}
const float scale = static_cast<float>(toMeter(_unit));
double maxRadius = 0.0;
int meshIndex = 0;
// The beginning of the speck file has a header that either contains comments
@@ -540,23 +543,55 @@ bool RenderableDUMeshes::readSpeckFile() {
// We can now read the vertices data:
for (int l = 0; l < mesh.numU * mesh.numV; ++l) {
std::getline(file, line);
if (line.substr(0, 1) != "}") {
std::stringstream lineData(line);
for (int i = 0; i < 7; ++i) {
GLfloat value;
lineData >> value;
bool errorReading = lineData.rdstate() & std::ifstream::failbit;
if (!errorReading) {
mesh.vertices.push_back(value);
}
else {
break;
}
}
}
else {
if (line.substr(0, 1) == "}") {
break;
}
std::stringstream lineData(line);
// Try to read three values for the position
glm::vec3 pos;
bool success = true;
for (int i = 0; i < 3; ++i) {
GLfloat value;
lineData >> value;
bool errorReading = lineData.rdstate() & std::ifstream::failbit;
if (errorReading) {
success = false;
break;
}
GLfloat scaledValue = value * scale;
pos[i] = scaledValue;
mesh.vertices.push_back(scaledValue);
}
if (!success) {
LERROR(fmt::format(
"Failed reading position on line {} of mesh {} in file: '{}'. "
"Stopped reading mesh data", l, meshIndex, _speckFile
));
break;
}
// Check if new max radius
const double r = glm::length(glm::dvec3(pos));
maxRadius = std::max(maxRadius, r);
// OLD CODE:
// (2022-03-23, emmbr) None of our files included texture coordinates,
// and if they would they would still not be used by the shader
//for (int i = 0; i < 7; ++i) {
// GLfloat value;
// lineData >> value;
// bool errorReading = lineData.rdstate() & std::ifstream::failbit;
// if (!errorReading) {
// mesh.vertices.push_back(value);
// }
// else {
// break;
// }
//}
}
std::getline(file, line);
@@ -569,6 +604,8 @@ bool RenderableDUMeshes::readSpeckFile() {
}
}
setBoundingSphere(maxRadius);
return true;
}
@@ -579,12 +616,6 @@ void RenderableDUMeshes::createMeshes() {
LDEBUG("Creating planes");
for (std::pair<const int, RenderingMesh>& p : _renderingMeshesMap) {
float scale = static_cast<float>(toMeter(_unit));
for (GLfloat& v : p.second.vertices) {
v *= scale;
}
for (int i = 0; i < p.second.numU; ++i) {
GLuint vao;
glGenVertexArrays(1, &vao);
@@ -605,29 +636,32 @@ void RenderableDUMeshes::createMeshes() {
);
// in_position
glEnableVertexAttribArray(0);
// U and V may not be given by the user
if (p.second.vertices.size() / (p.second.numU * p.second.numV) > 3) {
glVertexAttribPointer(
0,
3,
GL_FLOAT,
GL_FALSE,
sizeof(GLfloat) * 5,
reinterpret_cast<GLvoid*>(sizeof(GLfloat) * i * p.second.numV)
);
// (2022-03-23, emmbr) This code was actually never used. We only read three
// values per line and di not handle any texture cooridnates, even if there
// would have been some in the file
//// U and V may not be given by the user
//if (p.second.vertices.size() / (p.second.numU * p.second.numV) > 3) {
// glVertexAttribPointer(
// 0,
// 3,
// GL_FLOAT,
// GL_FALSE,
// sizeof(GLfloat) * 5,
// reinterpret_cast<GLvoid*>(sizeof(GLfloat) * i * p.second.numV)
// );
// texture coords
glEnableVertexAttribArray(1);
glVertexAttribPointer(
1,
2,
GL_FLOAT,
GL_FALSE,
sizeof(GLfloat) * 7,
reinterpret_cast<GLvoid*>(sizeof(GLfloat) * 3 * i * p.second.numV)
);
}
else { // no U and V:
// // texture coords
// glEnableVertexAttribArray(1);
// glVertexAttribPointer(
// 1,
// 2,
// GL_FLOAT,
// GL_FALSE,
// sizeof(GLfloat) * 7,
// reinterpret_cast<GLvoid*>(sizeof(GLfloat) * 3 * i * p.second.numV)
// );
//}
//else { // no U and V:
glVertexAttribPointer(
0,
3,
@@ -636,7 +670,7 @@ void RenderableDUMeshes::createMeshes() {
0,
reinterpret_cast<GLvoid*>(sizeof(GLfloat) * 3 * i * p.second.numV)
);
}
//}
}
// Grid: we need columns
@@ -397,12 +397,17 @@ std::vector<double> RenderablePoints::createDataSlice() {
slice.reserve(4 * _dataset.entries.size());
}
double maxRadius = 0.0;
int colorIndex = 0;
for (const speck::Dataset::Entry& e : _dataset.entries) {
glm::dvec3 p = e.position;
double scale = toMeter(_unit);
p *= scale;
const double r = glm::length(p);
maxRadius = std::max(maxRadius, r);
glm::dvec4 position(p, 1.0);
if (_hasColorMapFile) {
@@ -423,6 +428,7 @@ std::vector<double> RenderablePoints::createDataSlice() {
0 :
colorIndex + 1;
}
setBoundingSphere(maxRadius);
return slice;
}
@@ -48,6 +48,7 @@
#include <ghoul/opengl/texture.h>
#include <ghoul/opengl/textureunit.h>
#include <glm/gtc/matrix_transform.hpp>
#include <glm/gtx/component_wise.hpp>
#include <filesystem>
#include <fstream>
#include <optional>
@@ -318,6 +319,10 @@ RenderableGalaxy::RenderableGalaxy(const ghoul::Dictionary& dictionary)
_downScaleVolumeRendering.setVisibility(properties::Property::Visibility::Developer);
addProperty(_downScaleVolumeRendering);
addProperty(_numberOfRayCastingSteps);
// Use max component instead of length, to avoid problems with taking square
// of huge value
setBoundingSphere(glm::compMax(0.5f * _volumeSize));
}
void RenderableGalaxy::initialize() {
@@ -716,7 +716,7 @@ scripting::LuaLibrary GlobeBrowsingModule::luaLibrary() const {
codegen::lua::GetGeoPositionForCamera,
codegen::lua::LoadWMSCapabilities,
codegen::lua::RemoveWMSServer,
codegen::lua::Capabilities
codegen::lua::CapabilitiesWMS
};
res.scripts = {
absPath("${MODULE_GLOBEBROWSING}/scripts/layer_support.lua")
@@ -437,7 +437,7 @@ getLocalPositionFromGeo(std::string globeIdentifier, double latitude, double lon
* can be used in the 'FilePath' argument for a call to the 'addLayer' function to add the
* value to a globe.
*/
[[codegen::luawrap]] std::vector<ghoul::Dictionary> capabilities(std::string name) {
[[codegen::luawrap]] std::vector<ghoul::Dictionary> capabilitiesWMS(std::string name) {
using namespace openspace;
using namespace globebrowsing;
@@ -131,8 +131,9 @@ void DashboardItemInstruments::render(glm::vec2& penPosition) {
double previous = sequencer.prevCaptureTime(currentTime);
double next = sequencer.nextCaptureTime(currentTime);
double remaining = sequencer.nextCaptureTime(currentTime) - currentTime;
const float t = static_cast<float>(1.0 - remaining / (next - previous));
double remaining = next - currentTime;
float t = static_cast<float>(1.0 - remaining / (next - previous));
t = std::clamp(t, 0.f, 1.f);
if (remaining > 0.0) {
RenderFont(
+36 -22
View File
@@ -55,14 +55,15 @@ cmake_policy(SET CMP0074 NEW)
# Specify the CEF distribution version.
# Release from 04/24/2019 verified to work on Windows.
set(CEF_VERSION "73.1.13+g6e3c989+chromium-73.0.3683.75")
# Release from 03/21/2022 verified to work on Windows.
set(CEF_VERSION "91.1.23+g04c8d56+chromium-91.0.4472.164")
# Removing - micahnyc 03/21/2022
# 73.1.13 has an issue on MacOS: The GUI freezing upon interaction.
# Therefore, we fall back to 3.3578.1867 from 01/29/2019
if (APPLE)
set(CEF_VERSION "3.3578.1867.g0f6d65a")
endif ()
#if (APPLE)
# set(CEF_VERSION "3.3578.1867.g0f6d65a")
#endif ()
# CEF Sandbox is not working with the latest Visual Studio, so we disable it for now.
if (WIN32)
@@ -128,7 +129,9 @@ set(WEBBROWSER_SOURCES ${WEBBROWSER_SOURCES} ${WEBBROWSER_RESOURCES_SOURCES})
# CEF helper sources
set(WEBBROWSER_HELPER_SOURCES src/webbrowserapp.cpp)
set(WEBBROWSER_HELPER_SOURCES_MACOSX src/processhelpermac.cpp)
if (OS_MACOSX)
list(APPEND WEBBROWSER_HELPER_SOURCES src/processhelpermac.cpp)
endif()
set(WEBBROWSER_HELPER_SOURCES_WINDOWS src/processhelperwindows.cpp)
APPEND_PLATFORM_SOURCES(WEBBROWSER_HELPER_SOURCES)
@@ -151,30 +154,41 @@ set(WEBBROWSER_RESOURCES_SRCS
# Place Helper in separate executable
# The naming style "<ApplicionName> Helper" is required by Chromium.
set(CEF_HELPER_TARGET "OpenSpace Helper" CACHE INTERNAL "CEF_HELPER_TARGET")
set(CEF_HELPER_TARGET_GPU "OpenSpace Helper (GPU)" CACHE INTERNAL "CEF_HELPER_TARGET_GPU")
set(CEF_HELPER_TARGET_RENDERER "OpenSpace Helper (Renderer)" CACHE INTERNAL "CEF_HELPER_TARGET_RENDERER")
#
# CEF platform-specific config
#
list(APPEND Targets ${CEF_HELPER_TARGET} ${CEF_HELPER_TARGET_GPU} ${CEF_HELPER_TARGET_RENDERER})
if (OS_MACOSX)
# Helper executable target.
add_executable(${CEF_HELPER_TARGET} MACOSX_BUNDLE ${WEBBROWSER_HELPER_SOURCES})
SET_EXECUTABLE_TARGET_PROPERTIES(${CEF_HELPER_TARGET})
# add_cef_logical_target("libcef_lib" "${CEF_LIB_DEBUG}" "${CEF_LIB_RELEASE}")
add_dependencies(${CEF_HELPER_TARGET} libcef_dll_wrapper)
target_link_libraries(${CEF_HELPER_TARGET} libcef_dll_wrapper ${CEF_STANDARD_LIBS})
set_target_properties(${CEF_HELPER_TARGET} PROPERTIES
MACOSX_BUNDLE_INFO_PLIST ${CMAKE_CURRENT_SOURCE_DIR}/mac/helper-Info.plist
)
ADD_LOGICAL_TARGET("cef_sandbox_lib" "${CEF_SANDBOX_LIB_DEBUG}" "${CEF_SANDBOX_LIB_RELEASE}")
foreach(target IN LISTS Targets)
# Helper executable target.
add_executable(${target} MACOSX_BUNDLE ${WEBBROWSER_HELPER_SOURCES})
SET_EXECUTABLE_TARGET_PROPERTIES(${target})
# add_cef_logical_target("libcef_lib" "${CEF_LIB_DEBUG}" "${CEF_LIB_RELEASE}")
add_dependencies(${target} libcef_dll_wrapper)
target_link_libraries(${target} libcef_dll_wrapper ${CEF_STANDARD_LIBS})
set_target_properties(${target} PROPERTIES
MACOSX_BUNDLE_INFO_PLIST ${CMAKE_CURRENT_SOURCE_DIR}/mac/helper-Info.plist
)
target_compile_options(${CEF_HELPER_TARGET} PRIVATE -Wno-deprecated-declarations)
target_compile_options(libcef_dll_wrapper PRIVATE -Wno-deprecated-declarations)
target_compile_options(${target} PRIVATE -Wno-deprecated-declarations)
target_compile_options(libcef_dll_wrapper PRIVATE -Wno-deprecated-declarations)
if (USE_SANDBOX)
# Logical target used to link the cef_sandbox library.
target_link_libraries(${target} cef_sandbox_lib)
endif ()
endforeach()
set_property(TARGET ${CEF_HELPER_TARGET_GPU} PROPERTY FOLDER "Helper")
set_property(TARGET ${CEF_HELPER_TARGET_RENDERER} PROPERTY FOLDER "Helper")
if (USE_SANDBOX)
# Logical target used to link the cef_sandbox library.
ADD_LOGICAL_TARGET("cef_sandbox_lib" "${CEF_SANDBOX_LIB_DEBUG}" "${CEF_SANDBOX_LIB_RELEASE}")
target_link_libraries(${CEF_HELPER_TARGET} cef_sandbox_lib)
endif ()
endif ()
if (OS_WINDOWS)
@@ -100,7 +100,7 @@ if(OS_LINUX)
-fno-rtti # Disable real-time type information
-fno-threadsafe-statics # Don't generate thread-safe statics
-fvisibility-inlines-hidden # Give hidden visibility to inlined class member functions
-std=gnu++11 # Use the C++11 language standard including GNU extensions
-std=gnu++14 # Use the C++14 language standard including GNU extensions
-Wsign-compare # Warn about mixed signed/unsigned type comparisons
)
list(APPEND CEF_COMPILER_FLAGS_DEBUG
@@ -259,7 +259,7 @@ if(OS_MACOSX)
-fno-threadsafe-statics # Don't generate thread-safe statics
-fobjc-call-cxx-cdtors # Call the constructor/destructor of C++ instance variables in ObjC objects
-fvisibility-inlines-hidden # Give hidden visibility to inlined class member functions
-std=gnu++11 # Use the C++11 language standard including GNU extensions
-std=gnu++14 # Use the C++14 language standard including GNU extensions
-Wno-narrowing # Don't warn about type narrowing
-Wsign-compare # Warn about mixed signed/unsigned type comparisons
)
@@ -456,12 +456,10 @@ if(OS_WINDOWS)
# List of CEF binary files.
set(CEF_BINARY_FILES
chrome_elf.dll
d3dcompiler_43.dll
d3dcompiler_47.dll
libcef.dll
libEGL.dll
libGLESv2.dll
natives_blob.bin
snapshot_blob.bin
v8_context_snapshot.bin
#swiftshader
@@ -469,11 +467,9 @@ if(OS_WINDOWS)
# List of CEF resource files.
set(CEF_RESOURCE_FILES
cef.pak
cef_100_percent.pak
cef_200_percent.pak
cef_extensions.pak
devtools_resources.pak
chrome_100_percent.pak
chrome_200_percent.pak
resources.pak
icudtl.dat
locales
)
@@ -69,12 +69,16 @@ function(run_cef_macosx_config CEF_ROOT module_path)
set(CEF_FINAL_APP "${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/${CEF_OUTPUT_PREFIX}${CEF_TARGET}.app")
set(CEF_INTERMEDIATE_HELPER_APP "${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/${CEF_OUTPUT_PREFIX}${CEF_HELPER_TARGET}.app")
set(CEF_INTERMEDIATE_HELPER_APP_GPU "${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/${CEF_OUTPUT_PREFIX}${CEF_HELPER_TARGET_GPU}.app")
set(CEF_INTERMEDIATE_HELPER_APP_RENDERER "${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/${CEF_OUTPUT_PREFIX}${CEF_HELPER_TARGET_RENDERER}.app")
set(CEF_FINAL_HELPER_APP "${CEF_FINAL_APP}/Contents/Frameworks/${CEF_HELPER_TARGET}.app")
set(CEF_FINAL_HELPER_APP_GPU "${CEF_FINAL_APP}/Contents/Frameworks/${CEF_HELPER_TARGET_GPU}.app")
set(CEF_FINAL_HELPER_APP_RENDERER "${CEF_FINAL_APP}/Contents/Frameworks/${CEF_HELPER_TARGET_RENDERER}.app")
set(CEF_FRAMEWORK_LOCATION "${CEF_BINARY_DIR}/Chromium Embedded Framework.framework")
set(CEF_FRAMEWORK_FINAL_LOCATION "${CEF_FINAL_APP}/Contents/Frameworks/Chromium Embedded Framework.framework")
add_dependencies(${CEF_TARGET} libcef_dll_wrapper "${CEF_HELPER_TARGET}")
add_dependencies(${CEF_TARGET} libcef_dll_wrapper "${CEF_HELPER_TARGET}" "${CEF_HELPER_TARGET_GPU}" "${CEF_HELPER_TARGET_RENDERER}")
# target_link_libraries(${CEF_TARGET} PUBLIC libcef_lib libcef_dll_wrapper ${CEF_STANDARD_LIBS})
target_link_libraries(${CEF_TARGET} PUBLIC libcef_dll_wrapper ${CEF_STANDARD_LIBS})
@@ -89,6 +93,8 @@ function(run_cef_macosx_config CEF_ROOT module_path)
POST_BUILD
# Copy the helper app bundle into the Frameworks directory.
COMMAND ${CMAKE_COMMAND} -E copy_directory "${CEF_INTERMEDIATE_HELPER_APP}" "${CEF_FINAL_HELPER_APP}"
COMMAND ${CMAKE_COMMAND} -E copy_directory "${CEF_INTERMEDIATE_HELPER_APP_GPU}" "${CEF_FINAL_HELPER_APP_GPU}"
COMMAND ${CMAKE_COMMAND} -E copy_directory "${CEF_INTERMEDIATE_HELPER_APP_RENDERER}" "${CEF_FINAL_HELPER_APP_RENDERER}"
# Copy the CEF framework into the Frameworks directory.
COMMAND ${CMAKE_COMMAND} -E copy_directory "${CEF_FRAMEWORK_LOCATION}" "${CEF_FRAMEWORK_FINAL_LOCATION}"
VERBATIM
@@ -41,11 +41,17 @@ namespace openspace {
class DefaultBrowserLauncher : public CefLifeSpanHandler, public CefRequestHandler {
public:
bool OnBeforePopup(CefRefPtr<CefBrowser> browser, CefRefPtr<CefFrame> frame,
const CefString& targetUrl, const CefString& targetFrameName,
CefLifeSpanHandler::WindowOpenDisposition targetDisposition, bool userGesture,
const CefPopupFeatures& popupFeatures, CefWindowInfo& windowInfo,
CefRefPtr<CefClient>& client, CefBrowserSettings& settings,
bool OnBeforePopup(CefRefPtr<CefBrowser> browser,
CefRefPtr<CefFrame> frame,
const CefString& targetUrl,
const CefString& targetFrameName,
CefLifeSpanHandler::WindowOpenDisposition targetDisposition,
bool userGesture,
const CefPopupFeatures& popupFeatures,
CefWindowInfo& windowInfo,
CefRefPtr<CefClient>& client,
CefBrowserSettings& settings,
CefRefPtr<CefDictionaryValue>& extra_info,
bool* noJavascriptAccess) override;
//bool OnOpenURLFromTab(CefRefPtr<CefBrowser> browser, CefRefPtr<CefFrame> frame,
+2 -1
View File
@@ -48,7 +48,7 @@ BrowserInstance::BrowserInstance(WebRenderHandler* renderer,
: _renderHandler(renderer)
, _keyboardHandler(keyboardHandler)
{
_client = new BrowserClient(_renderHandler, _keyboardHandler);
_client = new BrowserClient(_renderHandler.get(), _keyboardHandler.get());
CefWindowInfo windowInfo;
windowInfo.SetAsWindowless(nullptr);
@@ -62,6 +62,7 @@ BrowserInstance::BrowserInstance(WebRenderHandler* renderer,
_client.get(),
url,
browserSettings,
nullptr,
nullptr
);
@@ -38,6 +38,7 @@ bool DefaultBrowserLauncher::OnBeforePopup(CefRefPtr<CefBrowser>, CefRefPtr<CefF
CefLifeSpanHandler::WindowOpenDisposition,
bool, const CefPopupFeatures&, CefWindowInfo&,
CefRefPtr<CefClient>&, CefBrowserSettings&,
CefRefPtr<CefDictionaryValue>&,
bool*)
{
// never permit CEF popups, always launch in default browser
@@ -94,8 +94,8 @@ ScreenSpaceBrowser::ScreenSpaceBrowser(const ghoul::Dictionary& dictionary)
_renderHandler = new ScreenSpaceRenderHandler;
_keyboardHandler = new WebKeyboardHandler();
_browserInstance = std::make_unique<BrowserInstance>(
_renderHandler,
_keyboardHandler
_renderHandler.get(),
_keyboardHandler.get()
);
_url.onChange([this]() { _isUrlDirty = true; });
+4 -2
View File
@@ -42,8 +42,10 @@ void WebBrowserApp::OnContextCreated(CefRefPtr<CefBrowser>, CefRefPtr<CefFrame>,
void WebBrowserApp::OnBeforeCommandLineProcessing(const CefString&,
CefRefPtr<CefCommandLine> commandLine)
{
commandLine->AppendSwitch("disable-gpu");
commandLine->AppendSwitch("disable-gpu-compositing");
commandLine->AppendSwitch("use-gl=desktop");
commandLine->AppendSwitch("ignore-gpu-blacklist");
commandLine->AppendSwitch("log-gpu-control-list-decisions");
commandLine->AppendSwitch("use-mock-keychain");
commandLine->AppendSwitch("enable-begin-frame-scheduling");
commandLine->AppendSwitchWithValue("autoplay-policy", "no-user-gesture-required");
}
+1
View File
@@ -2155,6 +2155,7 @@ std::vector<std::string> SessionRecording::playbackList() const {
}
}
}
std::sort(fileList.begin(), fileList.end());
return fileList;
}
+3 -1
View File
@@ -70,7 +70,9 @@ namespace {
* value of true is given, then playback will continually loop until it is manually
* stopped.
*/
[[codegen::luawrap]] void startPlaybackDefault(std::string file, bool loop = false) {
[[codegen::luawrap("startPlayback")]] void startPlaybackDefault(std::string file,
bool loop = false)
{
using namespace openspace;
if (file.empty()) {
+7 -3
View File
@@ -218,8 +218,10 @@ joystickAxis(std::string joystickName, int axis)
* Finds the input joystick with the given 'name' and sets the deadzone for a particular
* joystick axis, which means that any input less than this value is completely ignored.
*/
[[codegen::luawrap]] void setJoystickAxisDeadZone(std::string joystickName, int axis,
float deadzone)
[[codegen::luawrap("setAxisDeadZone")]] void setJoystickAxisDeadZone(
std::string joystickName,
int axis,
float deadzone)
{
using namespace openspace;
global::navigationHandler->setJoystickAxisDeadzone(joystickName, axis, deadzone);
@@ -228,7 +230,9 @@ joystickAxis(std::string joystickName, int axis)
/**
* Returns the deadzone for the desired axis of the provided joystick.
*/
[[codegen::luawrap]] float joystickAxisDeadzone(std::string joystickName, int axis) {
[[codegen::luawrap("axisDeadzone")]] float joystickAxisDeadzone(std::string joystickName,
int axis)
{
float deadzone = openspace::global::navigationHandler->joystickAxisDeadzone(
joystickName,
axis
@@ -95,7 +95,7 @@ namespace {
}
// Returns the L2 associativity.
[[codegen::luawrap]] int l2Associativity() {
[[codegen::luawrap("L2Associativity")]] int l2Associativity() {
int assoc = static_cast<int>(CpuCap.L2Associativity());
return assoc;
}
+1
View File
@@ -164,6 +164,7 @@ scripting::LuaLibrary Time::luaLibrary() {
codegen::lua::InterpolateTimeRelative,
codegen::lua::CurrentTime,
codegen::lua::CurrentTimeUTC,
codegen::lua::CurrentTimeSpice,
codegen::lua::CurrentWallTime,
codegen::lua::CurrentApplicationTime,
codegen::lua::AdvancedTime
+10 -1
View File
@@ -273,7 +273,16 @@ namespace {
/**
* Returns the current time as an ISO 8601 date string (YYYY-MM-DDTHH:MN:SS).
*/
[[codegen::luawrap]] std::string currentTimeUTC() {
[[codegen::luawrap("UTC")]] std::string currentTimeUTC() {
return std::string(openspace::global::timeManager->time().ISO8601());
}
/**
* Returns the current time as an date string of the form
* (YYYY MON DDTHR:MN:SC.### ::RND) as returned by SPICE.
*/
[[codegen::luawrap("SPICE")]] std::string currentTimeSpice() {
return std::string(openspace::global::timeManager->time().UTC());
}