Merge branch 'master' into feature/model-animation

* Resolve conflicts
This commit is contained in:
Malin Ejdbo
2021-03-25 13:54:51 +01:00
52 changed files with 1899 additions and 1136 deletions

View File

@@ -34,6 +34,7 @@ set(HEADER_FILES
include/profile/cameradialog.h
include/profile/deltatimesdialog.h
include/profile/keybindingsdialog.h
include/profile/scriptlogdialog.h
include/profile/line.h
include/profile/marknodesdialog.h
include/profile/metadialog.h
@@ -53,6 +54,7 @@ set(SOURCE_FILES
src/profile/cameradialog.cpp
src/profile/deltatimesdialog.cpp
src/profile/keybindingsdialog.cpp
src/profile/scriptlogdialog.cpp
src/profile/line.cpp
src/profile/marknodesdialog.cpp
src/profile/metadialog.cpp
@@ -74,6 +76,7 @@ qt5_wrap_cpp(
include/profile/cameradialog.h
include/profile/deltatimesdialog.h
include/profile/keybindingsdialog.h
include/profile/scriptlogdialog.h
include/profile/marknodesdialog.h
include/profile/metadialog.h
include/profile/modulesdialog.h

View File

@@ -58,6 +58,13 @@ public:
*/
virtual void keyPressEvent(QKeyEvent* evt) override;
/**
* Adds scripts to the _scriptEdit from outside dialogs
*
* \param scripts #std::string scripts to be appended
*/
void appendScriptsToKeybind(const std::string& scripts);
private slots:
void listItemSelected();
void listItemAdded();
@@ -66,6 +73,7 @@ private slots:
void listItemCancelSave();
void transitionToEditMode();
void parseSelections();
void chooseScripts();
void keySelected(int index);
private:
@@ -99,6 +107,7 @@ private:
QPushButton* _addButton = nullptr;
QPushButton* _removeButton = nullptr;
QPushButton* _chooseScriptsButton = nullptr;
QPushButton* _saveButton = nullptr;
QPushButton* _cancelButton = nullptr;
QDialogButtonBox* _buttonBox = nullptr;

View File

@@ -0,0 +1,53 @@
/*****************************************************************************************
* *
* OpenSpace *
* *
* Copyright (c) 2014-2021 *
* *
* Permission is hereby granted, free of charge, to any person obtaining a copy of this *
* software and associated documentation files (the "Software"), to deal in the Software *
* without restriction, including without limitation the rights to use, copy, modify, *
* merge, publish, distribute, sublicense, and/or sell copies of the Software, and to *
* permit persons to whom the Software is furnished to do so, subject to the following *
* conditions: *
* *
* The above copyright notice and this permission notice shall be included in all copies *
* or substantial portions of the Software. *
* *
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, *
* INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A *
* PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT *
* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF *
* CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE *
* OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. *
****************************************************************************************/
#ifndef __OPENSPACE_UI_LAUNCHER___SCRIPTLOG___H__
#define __OPENSPACE_UI_LAUNCHER___SCRIPTLOG___H__
#include "profile/keybindingsdialog.h"
#include <QDialog>
#include <QListWidget>
class ScriptlogDialog : public QDialog {
Q_OBJECT
public:
/**
* Constructor for ScriptlogDialog class
*
* \param bindingDialog keybindingDialog that openend this window.
* \param parent Pointer to parent Qt widget
*/
ScriptlogDialog(KeybindingsDialog* bindingDialog, QWidget* parent);
private slots:
void saveChosenScripts();
private:
void createWidgets();
KeybindingsDialog* _bindingDialog = nullptr;
QListWidget* _scriptlogList = nullptr;
};
#endif // __OPENSPACE_UI_LAUNCHER___SCRIPTLOG___H__

View File

@@ -149,7 +149,9 @@ void AssetTreeModel::importModelData(const std::string& assetBasePath,
const std::string& userAssetBasePath) {
FileSystemAccess assets(
".asset",
{ "scene", "global", "customization", "examples", "util" },
// @TODO (abock, 2021-03-24) We need some better solution for this; what is the
// problem of just including all subfolders instead?
{ "scene", "global", "customization", "dashboard", "examples", "util" },
true,
true
);

View File

@@ -25,6 +25,8 @@
#include "profile/keybindingsdialog.h"
#include "profile/line.h"
#include "profile/scriptlogdialog.h"
#include <openspace/scene/profile.h>
#include <openspace/util/keys.h>
#include <qevent.h>
@@ -106,6 +108,10 @@ KeybindingsDialog::KeybindingsDialog(Profile& profile, QWidget *parent)
transitionFromEditMode();
}
void KeybindingsDialog::appendScriptsToKeybind(const std::string& scripts) {
_scriptEdit->append(QString::fromStdString(scripts));
}
void KeybindingsDialog::createWidgets() {
QBoxLayout* layout = new QVBoxLayout(this);
{
@@ -220,6 +226,14 @@ void KeybindingsDialog::createWidgets() {
_scriptLabel = new QLabel("Script");
box->addWidget(_scriptLabel, 6, 0, 1, 2);
_chooseScriptsButton = new QPushButton("Choose Scripts");
connect(
_chooseScriptsButton, &QPushButton::clicked,
this, &KeybindingsDialog::chooseScripts
);
box->addWidget(_chooseScriptsButton, 6, 1, 1, 1);
_scriptEdit = new QTextEdit;
_scriptEdit->setAcceptRichText(false);
_scriptEdit->setToolTip("Command(s) to execute at keypress event");
@@ -497,6 +511,7 @@ void KeybindingsDialog::editBoxDisabled(bool disabled) {
_scriptEdit->setDisabled(disabled);
_cancelButton->setDisabled(disabled);
_saveButton->setDisabled(disabled);
_chooseScriptsButton->setDisabled(disabled);
}
void KeybindingsDialog::parseSelections() {
@@ -508,6 +523,11 @@ void KeybindingsDialog::parseSelections() {
accept();
}
void KeybindingsDialog::chooseScripts() {
_errorMsg->clear();
ScriptlogDialog(this, this).exec();
}
void KeybindingsDialog::keyPressEvent(QKeyEvent* evt) {
if (evt->key() == Qt::Key_Enter || evt->key() == Qt::Key_Return) {
return;

View File

@@ -0,0 +1,99 @@
/*****************************************************************************************
* *
* OpenSpace *
* *
* Copyright (c) 2014-2021 *
* *
* Permission is hereby granted, free of charge, to any person obtaining a copy of this *
* software and associated documentation files (the "Software"), to deal in the Software *
* without restriction, including without limitation the rights to use, copy, modify, *
* merge, publish, distribute, sublicense, and/or sell copies of the Software, and to *
* permit persons to whom the Software is furnished to do so, subject to the following *
* conditions: *
* *
* The above copyright notice and this permission notice shall be included in all copies *
* or substantial portions of the Software. *
* *
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, *
* INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A *
* PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT *
* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF *
* CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE *
* OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. *
****************************************************************************************/
#include "profile/scriptlogdialog.h"
#include "profile/line.h"
#include <openspace/engine/configuration.h>
#include <openspace/scene/profile.h>
#include <ghoul/filesystem/filesystem.h>
#include <QDialogButtonBox>
#include <QLabel>
#include <QFile>
#include <QTextStream>
#include <QVBoxLayout>
ScriptlogDialog::ScriptlogDialog(KeybindingsDialog* bindingDialog,
QWidget* parent)
: QDialog(parent)
, _bindingDialog(bindingDialog)
{
setWindowTitle("Scriptlog");
createWidgets();
QFile file(QString::fromStdString(absPath("${LOGS}/scriptLog.txt")));
if (file.open(QIODevice::ReadOnly | QIODevice::Text)) {
QTextStream in(&file);
while (!in.atEnd()) {
QString line = in.readLine();
// removing return from a few statments
// these are usually generated by gui panels
line.remove(QRegularExpression("^return "));
if (!line.isEmpty()) {
_scriptlogList->addItem(line);
}
}
}
}
void ScriptlogDialog::createWidgets() {
QBoxLayout* layout = new QVBoxLayout(this);
{
QLabel* heading = new QLabel("Choose commands from log/scriptLog.txt");
heading->setObjectName("heading");
layout->addWidget(heading);
}
_scriptlogList = new QListWidget;
_scriptlogList->setSelectionMode(QAbstractItemView::SelectionMode::MultiSelection);
layout->addWidget(_scriptlogList);
layout->addWidget(new Line);
{
QDialogButtonBox* buttons = new QDialogButtonBox;
buttons->setStandardButtons(QDialogButtonBox::Save | QDialogButtonBox::Cancel);
connect(
buttons, &QDialogButtonBox::accepted,
this, &ScriptlogDialog::saveChosenScripts
);
connect(
buttons, &QDialogButtonBox::rejected,
this, &ScriptlogDialog::reject
);
layout->addWidget(buttons);
}
}
void ScriptlogDialog::saveChosenScripts() {
std::string chosenScripts;
QList<QListWidgetItem*> itemList = _scriptlogList->selectedItems();
for (int i = 0; i < itemList.size(); ++i) {
chosenScripts += itemList.at(i)->text().toStdString();
if (i < itemList.size()) {
chosenScripts += "\n";
}
}
_bindingDialog->appendScriptsToKeybind(chosenScripts);
accept();
}

View File

@@ -218,6 +218,15 @@ void mainInitFunc(GLFWwindow*) {
LTRACE("main::mainInitFunc(begin)");
//
// Screenshots
//
// We save the startup value of the screenshots just in case we want to add a date
// to them later in the RenderEngine
std::string screenshotPath = absPath("${SCREENSHOTS}");
FileSys.registerPathToken("${STARTUP_SCREENSHOT}", screenshotPath);
Settings::instance().setCapturePath(screenshotPath);
LDEBUG("Initializing OpenSpace Engine started");
global::openSpaceEngine->initialize();
LDEBUG("Initializing OpenSpace Engine finished");
@@ -321,27 +330,6 @@ void mainInitFunc(GLFWwindow*) {
#endif // OPENSPACE_HAS_SPOUT
}
//
// Screenshots
//
std::string screenshotPath = "${SCREENSHOTS}";
if (global::configuration->shouldUseScreenshotDate) {
std::time_t now = std::time(nullptr);
std::tm* nowTime = std::localtime(&now);
char mbstr[128];
strftime(mbstr, sizeof(mbstr), "%Y-%m-%d-%H-%M", nowTime);
FileSys.registerPathToken(
"${SCREENSHOTS}",
absPath(screenshotPath + '/' + std::string(mbstr)),
ghoul::filesystem::FileSystem::Override::Yes
);
}
Settings::instance().setCapturePath(absPath(screenshotPath));
LTRACE("main::mainInitFunc(end)");
}
@@ -1117,22 +1105,17 @@ int main(int argc, char* argv[]) {
}
LINFO(fmt::format("Configuration Path: '{}'", configurationFilePath));
// Register the base path as the directory where the configuration file lives
std::string base = ghoul::filesystem::File(configurationFilePath).directoryName();
constexpr const char* BasePathToken = "${BASE}";
FileSys.registerPathToken(BasePathToken, base);
// Loading configuration from disk
LDEBUG("Loading configuration from disk");
*global::configuration = configuration::loadConfigurationFromFile(
configurationFilePath
configurationFilePath,
commandlineArguments.configurationOverride
);
// If the user requested a commandline-based configuration script that should
// overwrite some of the values, this is the time to do it
if (!commandlineArguments.configurationOverride.empty()) {
LDEBUG("Executing Lua script passed through the commandline:");
LDEBUG(commandlineArguments.configurationOverride);
ghoul::lua::runScript(
global::configuration->state,
commandlineArguments.configurationOverride
);
parseLuaState(*global::configuration);
}
// Determining SGCT configuration file
LDEBUG("SGCT Configuration file: " + global::configuration->windowConfiguration);

View File

@@ -8,8 +8,8 @@ local propertyHelper = asset.require('util/property_helper')
asset.require('spice/base')
-- Load default key bindings applicable to most scenes
asset.require('dashboard/default_dashboard')
asset.require('util/default_keybindings')
asset.require('util/default_dashboard')
asset.require('util/default_joystick')
-- Load web gui

View File

@@ -0,0 +1,13 @@
local item = {
Type = "DashboardItemDate",
Identifier = "Date",
GuiName = "Date"
}
asset.onInitialize(function()
openspace.dashboard.addDashboardItem(item)
end)
asset.onDeinitialize(function()
openspace.dashboard.removeDashboardItem(item.Identifier)
end)

View File

@@ -0,0 +1,8 @@
local assetHelper = asset.require('util/asset_helper')
asset.require('./date')
asset.require('./simulationincrement')
asset.require('./distance')
asset.require('./framerate')
asset.require('./parallelconnection')
asset.require('./globelocation')

View File

@@ -0,0 +1,13 @@
local item = {
Type = "DashboardItemDistance",
Identifier = "Distance",
GuiName = "Distance"
}
asset.onInitialize(function()
openspace.dashboard.addDashboardItem(item)
end)
asset.onDeinitialize(function()
openspace.dashboard.removeDashboardItem(item.Identifier)
end)

View File

@@ -0,0 +1,13 @@
local item = {
Type = "DashboardItemFramerate",
Identifier = "Framerate",
GuiName = "Framerate"
}
asset.onInitialize(function()
openspace.dashboard.addDashboardItem(item)
end)
asset.onDeinitialize(function()
openspace.dashboard.removeDashboardItem(item.Identifier)
end)

View File

@@ -0,0 +1,13 @@
local item = {
Type = "DashboardItemGlobeLocation",
Identifier = "GlobeLocation",
GuiName = "Globe Location"
}
asset.onInitialize(function()
openspace.dashboard.addDashboardItem(item)
end)
asset.onDeinitialize(function()
openspace.dashboard.removeDashboardItem(item.Identifier)
end)

View File

@@ -0,0 +1,13 @@
local item = {
Type = "DashboardItemParallelConnection",
Identifier = "ParallelConnection",
GuiName = "Parallel Connection"
}
asset.onInitialize(function()
openspace.dashboard.addDashboardItem(item)
end)
asset.onDeinitialize(function()
openspace.dashboard.removeDashboardItem(item.Identifier)
end)

View File

@@ -0,0 +1,13 @@
local item = {
Type = "DashboardItemSimulationIncrement",
Identifier = "SimulationIncrement",
GuiName = "Simulation Increment"
}
asset.onInitialize(function()
openspace.dashboard.addDashboardItem(item)
end)
asset.onDeinitialize(function()
openspace.dashboard.removeDashboardItem(item.Identifier)
end)

View File

@@ -0,0 +1,14 @@
local item = {
Type = "DashboardItemVelocity",
Identifier = "GlobeLocation",
Simplification = true,
GuiName = "Velocity"
}
asset.onInitialize(function()
openspace.dashboard.addDashboardItem(item)
end)
asset.onDeinitialize(function()
openspace.dashboard.removeDashboardItem(item.Identifier)
end)

View File

@@ -104,12 +104,6 @@ local ecliptic = {
local eclipticLabels = {
Identifier = "EclipticSphereLabels",
Parent = transforms.SolarSystemBarycenter.Name,
Transform = {
Rotation = {
Type = "StaticRotation",
Rotation = eclipticRotationMatrix
}
},
Renderable = {
Type = "RenderableBillboardsCloud",
Enabled = false,
@@ -122,6 +116,12 @@ local eclipticLabels = {
TextMinSize = 1.3,
TextMaxSize = 50.0,
Unit = "pc",
TransformationMatrix = {
-0.05487554, 0.4941095, -0.8676661, 0.0,
-0.9938214 , -0.1109906, -0.0003515167, 0.0,
-0.09647644, 0.8622859, 0.4971472, 0.0,
0.0, 0.0, 0.0, 1.0
}
},
GUI = {
Name = "Ecliptic Sphere Labels",
@@ -158,12 +158,6 @@ local equatorial = {
local equatorialLabels = {
Identifier = "EquatorialSphereLabels",
Parent = transforms.SolarSystemBarycenter.Name,
Transform = {
Rotation = {
Type = "StaticRotation",
Rotation = equatorialRotationMatrix
}
},
Renderable = {
Type = "RenderableBillboardsCloud",
Enabled = false,
@@ -176,6 +170,12 @@ local equatorialLabels = {
TextMinSize = 1.7,
TextMaxSize = 70.0,
Unit = "pc",
TransformationMatrix = {
-0.05487554, 0.4941095, -0.8676661, 0.0,
-0.8734371 , -0.4448296, -0.1980764, 0.0,
-0.483835 , 0.7469823, 0.4559838, 0.0,
0.0 , 0.0 , 0.0 , 1.0
}
},
GUI = {
Name = "Equatorial Sphere Labels",

View File

@@ -1,34 +0,0 @@
local assetHelper = asset.require('util/asset_helper')
assetHelper.registerDashboardItems(asset, {
{
Type = "DashboardItemDate",
Identifier = "Date",
GuiName = "Date"
},
{
Type = "DashboardItemSimulationIncrement",
Identifier = "SimulationIncrement",
GuiName = "Simulation Increment"
},
{
Type = "DashboardItemDistance",
Identifier = "Distance",
GuiName = "Distance"
},
{
Type = "DashboardItemFramerate",
Identifier = "Framerate",
GuiName = "Framerate"
},
{
Type = "DashboardItemParallelConnection",
Identifier = "ParallelConnection",
GuiName = "Parallel Connection"
},
{
Type = "DashboardItemGlobeLocation",
Identifier = "GlobeLocation",
GuiName = "Globe Location"
}
})

View File

@@ -156,7 +156,17 @@ struct IntVerifier : public TemplateVerifier<int> {
* <code>std::string</code>. No implicit conversion is considered in this testing.
*/
struct StringVerifier : public TemplateVerifier<std::string> {
StringVerifier(bool mustBeNotEmpty = false);
TestResult operator()(const ghoul::Dictionary& dictionary,
const std::string& key) const override;
std::string type() const override;
bool mustBeNotEmpty() const;
private:
bool _mustBeNotEmpty = false;
};
/**

View File

@@ -43,7 +43,6 @@ struct Configuration {
Configuration& operator=(Configuration&&) = default;
std::string windowConfiguration = "${CONFIG}/single.xml";
std::string sgctConfigNameInitialized;
std::string asset;
std::string profile;
std::vector<std::string> readOnlyProfiles;
@@ -93,7 +92,6 @@ struct Configuration {
glm::dvec3 screenSpaceRotation = glm::dvec3(0.0);
glm::dvec3 masterRotation = glm::dvec3(0.0);
bool isConsoleDisabled = false;
bool usingProfile = false;
bool bypassLauncher = false;
std::map<std::string, ghoul::Dictionary> moduleConfigurations;
@@ -123,6 +121,9 @@ struct Configuration {
};
HTTPProxy httpProxy;
// Values not read from the openspace.cfg file
bool usingProfile = false;
std::string sgctConfigNameInitialized;
static documentation::Documentation Documentation;
ghoul::lua::LuaState state;
@@ -130,9 +131,8 @@ struct Configuration {
std::string findConfiguration(const std::string& filename = "openspace.cfg");
Configuration loadConfigurationFromFile(const std::string& filename);
void parseLuaState(Configuration& configuration);
Configuration loadConfigurationFromFile(const std::string& filename,
const std::string& overrideScript);
} // namespace openspace::configuration

View File

@@ -144,7 +144,7 @@ private:
// Lua functions - exposed for testing
namespace openspace::luascriptfunctions {
int createSingeColorImage(lua_State* L);
int createSingleColorImage(lua_State* L);
} // openspace::luascriptfunctions

View File

@@ -28,12 +28,9 @@
#include <openspace/properties/propertyowner.h>
#include <openspace/properties/scalar/boolproperty.h>
#include <openspace/properties/scalar/floatproperty.h>
#include <openspace/properties/stringproperty.h>
#include <ghoul/glm.h>
namespace ghoul { class Dictionary; }
namespace ghoul::fontrendering { class Font; }
namespace openspace {
@@ -58,22 +55,6 @@ protected:
properties::BoolProperty _isEnabled;
};
class DashboardTextItem : public DashboardItem {
public:
static documentation::Documentation Documentation();
DashboardTextItem(const ghoul::Dictionary& dictionary, float fontSize = 10.f,
const std::string& fontName = "Mono");
protected:
properties::StringProperty _fontName;
properties::FloatProperty _fontSize;
std::shared_ptr<ghoul::fontrendering::Font> _font;
};
} // openspace
#endif // __OPENSPACE_CORE___DASHBOARDITEM___H__

View File

@@ -0,0 +1,56 @@
/*****************************************************************************************
* *
* OpenSpace *
* *
* Copyright (c) 2014-2021 *
* *
* Permission is hereby granted, free of charge, to any person obtaining a copy of this *
* software and associated documentation files (the "Software"), to deal in the Software *
* without restriction, including without limitation the rights to use, copy, modify, *
* merge, publish, distribute, sublicense, and/or sell copies of the Software, and to *
* permit persons to whom the Software is furnished to do so, subject to the following *
* conditions: *
* *
* The above copyright notice and this permission notice shall be included in all copies *
* or substantial portions of the Software. *
* *
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, *
* INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A *
* PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT *
* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF *
* CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE *
* OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. *
****************************************************************************************/
#ifndef __OPENSPACE_CORE___DASHBOARDTEXTITEM___H__
#define __OPENSPACE_CORE___DASHBOARDTEXTITEM___H__
#include <openspace/rendering/dashboarditem.h>
#include <openspace/properties/scalar/floatproperty.h>
#include <openspace/properties/stringproperty.h>
namespace ghoul { class Dictionary; }
namespace ghoul::fontrendering { class Font; }
namespace openspace {
namespace documentation { struct Documentation; }
class DashboardTextItem : public DashboardItem {
public:
static documentation::Documentation Documentation();
DashboardTextItem(const ghoul::Dictionary& dictionary, float fontSize = 10.f,
const std::string& fontName = "Mono");
protected:
properties::StringProperty _fontName;
properties::FloatProperty _fontSize;
std::shared_ptr<ghoul::fontrendering::Font> _font;
};
} // openspace
#endif // __OPENSPACE_CORE___DASHBOARDITEM___H__

View File

@@ -201,6 +201,7 @@ private:
properties::BoolProperty _showCameraInfo;
properties::BoolProperty _applyWarping;
properties::BoolProperty _screenshotUseDate;
properties::BoolProperty _showFrameInformation;
properties::BoolProperty _disableMasterRendering;

View File

@@ -25,7 +25,7 @@
#ifndef __OPENSPACE_MODULE_BASE___DASHBOARDITEMANGLE___H__
#define __OPENSPACE_MODULE_BASE___DASHBOARDITEMANGLE___H__
#include <openspace/rendering/dashboarditem.h>
#include <openspace/rendering/dashboardtextitem.h>
#include <openspace/properties/optionproperty.h>
#include <openspace/properties/stringproperty.h>

View File

@@ -25,7 +25,7 @@
#ifndef __OPENSPACE_MODULE_BASE___DASHBOARDITEMDATE___H__
#define __OPENSPACE_MODULE_BASE___DASHBOARDITEMDATE___H__
#include <openspace/rendering/dashboarditem.h>
#include <openspace/rendering/dashboardtextitem.h>
#include <openspace/properties/stringproperty.h>

View File

@@ -25,7 +25,7 @@
#ifndef __OPENSPACE_MODULE_BASE___DASHBOARDITEMDISTANCE___H__
#define __OPENSPACE_MODULE_BASE___DASHBOARDITEMDISTANCE___H__
#include <openspace/rendering/dashboarditem.h>
#include <openspace/rendering/dashboardtextitem.h>
#include <openspace/properties/optionproperty.h>
#include <openspace/properties/stringproperty.h>

View File

@@ -25,7 +25,7 @@
#ifndef __OPENSPACE_MODULE_BASE___DASHBOARDITEMFRAMERATE___H__
#define __OPENSPACE_MODULE_BASE___DASHBOARDITEMFRAMERATE___H__
#include <openspace/rendering/dashboarditem.h>
#include <openspace/rendering/dashboardtextitem.h>
#include <openspace/properties/optionproperty.h>
#include <openspace/properties/triggerproperty.h>

View File

@@ -25,7 +25,7 @@
#ifndef __OPENSPACE_MODULE_BASE___DASHBOARDITEMMISSION___H__
#define __OPENSPACE_MODULE_BASE___DASHBOARDITEMMISSION___H__
#include <openspace/rendering/dashboarditem.h>
#include <openspace/rendering/dashboardtextitem.h>
namespace openspace {

View File

@@ -25,7 +25,7 @@
#ifndef __OPENSPACE_MODULE_BASE___DASHBOARDITEMPARALLELCONNECTION___H__
#define __OPENSPACE_MODULE_BASE___DASHBOARDITEMPARALLELCONNECTION___H__
#include <openspace/rendering/dashboarditem.h>
#include <openspace/rendering/dashboardtextitem.h>
namespace openspace {

View File

@@ -25,7 +25,7 @@
#ifndef __OPENSPACE_MODULE_BASE___DASHBOARDITEMPROPERTYVALUE___H__
#define __OPENSPACE_MODULE_BASE___DASHBOARDITEMPROPERTYVALUE___H__
#include <openspace/rendering/dashboarditem.h>
#include <openspace/rendering/dashboardtextitem.h>
#include <openspace/properties/stringproperty.h>

View File

@@ -25,7 +25,7 @@
#ifndef __OPENSPACE_MODULE_BASE___DASHBOARDITEMSIMULATIONINCREMENT___H__
#define __OPENSPACE_MODULE_BASE___DASHBOARDITEMSIMULATIONINCREMENT___H__
#include <openspace/rendering/dashboarditem.h>
#include <openspace/rendering/dashboardtextitem.h>
#include <openspace/properties/optionproperty.h>
#include <openspace/properties/stringproperty.h>

View File

@@ -25,7 +25,7 @@
#ifndef __OPENSPACE_MODULE_BASE___DASHBOARDITEMTEXT___H__
#define __OPENSPACE_MODULE_BASE___DASHBOARDITEMTEXT___H__
#include <openspace/rendering/dashboarditem.h>
#include <openspace/rendering/dashboardtextitem.h>
#include <openspace/properties/stringproperty.h>

View File

@@ -25,7 +25,7 @@
#ifndef __OPENSPACE_MODULE_BASE___DASHBOARDITEMVELOCITY___H__
#define __OPENSPACE_MODULE_BASE___DASHBOARDITEMVELOCITY___H__
#include <openspace/rendering/dashboarditem.h>
#include <openspace/rendering/dashboardtextitem.h>
#include <openspace/properties/optionproperty.h>
#include <openspace/properties/scalar/boolproperty.h>

View File

@@ -1492,6 +1492,11 @@ void RenderableBillboardsCloud::createDataSlice() {
ZoneScoped
_slicedData.clear();
if (_fullData.empty() || _nValuesPerAstronomicalObject == 0) {
return;
}
if (_hasColorMapFile) {
_slicedData.reserve(8 * (_fullData.size() / _nValuesPerAstronomicalObject));
}

View File

@@ -32,7 +32,6 @@ set(OPENSPACE_SOURCE
${OPENSPACE_BASE_DIR}/src/documentation/documentationgenerator.cpp
${OPENSPACE_BASE_DIR}/src/documentation/verifier.cpp
${OPENSPACE_BASE_DIR}/src/engine/configuration.cpp
${OPENSPACE_BASE_DIR}/src/engine/configuration_doc.inl
${OPENSPACE_BASE_DIR}/src/engine/downloadmanager.cpp
${OPENSPACE_BASE_DIR}/src/engine/globals.cpp
${OPENSPACE_BASE_DIR}/src/engine/globalscallbacks.cpp
@@ -133,6 +132,7 @@ set(OPENSPACE_SOURCE
${OPENSPACE_BASE_DIR}/src/rendering/dashboard.cpp
${OPENSPACE_BASE_DIR}/src/rendering/dashboard_lua.inl
${OPENSPACE_BASE_DIR}/src/rendering/dashboarditem.cpp
${OPENSPACE_BASE_DIR}/src/rendering/dashboardtextitem.cpp
${OPENSPACE_BASE_DIR}/src/rendering/framebufferrenderer.cpp
${OPENSPACE_BASE_DIR}/src/rendering/deferredcastermanager.cpp
${OPENSPACE_BASE_DIR}/src/rendering/helper.cpp
@@ -323,6 +323,7 @@ set(OPENSPACE_HEADER
${OPENSPACE_BASE_DIR}/include/openspace/rendering/abufferrenderer.h
${OPENSPACE_BASE_DIR}/include/openspace/rendering/dashboard.h
${OPENSPACE_BASE_DIR}/include/openspace/rendering/dashboarditem.h
${OPENSPACE_BASE_DIR}/include/openspace/rendering/dashboardtextitem.h
${OPENSPACE_BASE_DIR}/include/openspace/rendering/framebufferrenderer.h
${OPENSPACE_BASE_DIR}/include/openspace/rendering/deferredcaster.h
${OPENSPACE_BASE_DIR}/include/openspace/rendering/deferredcasterlistener.h

View File

@@ -176,6 +176,33 @@ std::string IntVerifier::type() const {
return "Integer";
}
StringVerifier::StringVerifier(bool mustBeNotEmpty)
: TemplateVerifier<std::string>()
, _mustBeNotEmpty(mustBeNotEmpty)
{}
TestResult StringVerifier::operator()(const ghoul::Dictionary& dictionary,
const std::string& key) const
{
TestResult res = TemplateVerifier<std::string>::operator()(dictionary, key);
if (!res.success) {
return res;
}
std::string value = dictionary.value<std::string>(key);
if (value.empty() && _mustBeNotEmpty) {
res.success = false;
res.offenses.push_back({
key, TestResult::Offense::Reason::Verification, "value must not be empty"
});
}
return res;
}
bool StringVerifier::mustBeNotEmpty() const {
return _mustBeNotEmpty;
}
std::string StringVerifier::type() const {
return "String";
}

View File

@@ -27,287 +27,304 @@
#include <openspace/documentation/documentation.h>
#include <ghoul/filesystem/file.h>
#include <ghoul/filesystem/filesystem.h>
#include <ghoul/logging/logmanager.h>
#include <ghoul/lua/ghoul_lua.h>
#include <ghoul/lua/lua_helper.h>
#include <ghoul/misc/assert.h>
#include <optional>
namespace {
constexpr const char* BasePathToken = "${BASE}";
// We can't use ${SCRIPTS} here as that hasn't been defined by this point
constexpr const char* InitialConfigHelper =
"${BASE}/scripts/configuration_helper.lua";
// Variable names for the openspace.cfg file
// These are also used in the _doc include file
constexpr const char* KeySGCTConfig = "SGCTConfig";
constexpr const char* KeyAsset = "Asset";
constexpr const char* KeyProfile = "Profile";
constexpr const char* KeyGlobalCustomizationScripts = "GlobalCustomizationScripts";
constexpr const char* KeyPaths = "Paths";
constexpr const char* KeyFonts = "Fonts";
constexpr const char* KeyLogging = "Logging";
constexpr const char* KeyLogDir = "LogDir";
constexpr const char* KeyPerformancePrefix = "PerformancePrefix";
constexpr const char* KeyLogLevel = "LogLevel";
constexpr const char* KeyImmediateFlush = "ImmediateFlush";
constexpr const char* KeyLogs = "Logs";
constexpr const char* KeyCapabilitiesVerbosity = "CapabilitiesVerbosity";
constexpr const char* KeyDocumentationPath = "Path";
constexpr const char* KeyDocumentation = "Documentation";
constexpr const char* KeyScriptLog = "ScriptLog";
constexpr const char* KeyShutdownCountdown = "ShutdownCountdown";
constexpr const char* KeyPerSceneCache = "PerSceneCache";
constexpr const char* KeyOnScreenTextScaling = "OnScreenTextScaling";
constexpr const char* KeyRenderingMethod = "RenderingMethod";
constexpr const char* KeyDisableRenderingOnMaster = "DisableRenderingOnMaster";
constexpr const char* KeyGlobalRotation = "GlobalRotation";
constexpr const char* KeyScreenSpaceRotation = "ScreenSpaceRotation";
constexpr const char* KeyMasterRotation = "MasterRotation";
constexpr const char* KeyDisableInGameConsole = "DisableInGameConsole";
constexpr const char* KeyScreenshotUseDate = "ScreenshotUseDate";
constexpr const char* KeyHttpProxy = "HttpProxy";
constexpr const char* KeyAddress = "Address";
constexpr const char* KeyPort = "Port";
constexpr const char* KeyAuthentication = "Authentication";
constexpr const char* KeyUser = "User";
constexpr const char* KeyPassword = "Password";
constexpr const char* KeyOpenGLDebugContext = "OpenGLDebugContext";
constexpr const char* KeyActivate = "Activate";
constexpr const char* KeySynchronous = "Synchronous";
constexpr const char* KeyFilterIdentifier = "FilterIdentifier";
constexpr const char* KeyIdentifier = "Identifier";
constexpr const char* KeySource = "Source";
constexpr const char* KeyType = "Type";
constexpr const char* KeyFilterSeverity = "FilterSeverity";
constexpr const char* KeyCheckOpenGLState = "CheckOpenGLState";
constexpr const char* KeyLogEachOpenGLCall = "LogEachOpenGLCall";
constexpr const char* KeyVersionCheckUrl = "VersionCheckUrl";
constexpr const char* KeyUseMultithreadedInitialization =
"UseMultithreadedInitialization";
constexpr const char* KeyLoadingScreen = "LoadingScreen";
constexpr const char* KeyShowMessage = "ShowMessage";
constexpr const char* KeyShowNodeNames = "ShowNodeNames";
constexpr const char* KeyShowProgressbar = "ShowProgressbar";
constexpr const char* KeyModuleConfigurations = "ModuleConfigurations";
struct [[codegen::Dictionary(Configuration)]] Parameters {
// The SGCT configuration file that determines the window and view frustum
// settings that are being used when OpenSpace is started
std::optional<std::string> windowConfiguration [[codegen::key("SGCTConfig")]];
constexpr const char* KeySgctConfigNameInitialized = "sgctconfiginitializeString";
constexpr const char* KeyReadOnlyProfiles = "ReadOnlyProfiles";
constexpr const char* KeyBypassLauncher = "BypassLauncher";
// The scene description that is used to populate the application after startup.
// The scene determines which objects are loaded, the startup time and other
// scene-specific settings. More information is provided in the Scene
// documentation. If the 'Asset' and the 'Profile' values are specified, the asset
// is silently ignored
std::optional<std::string> asset;
template <typename T>
void getValue(ghoul::lua::LuaState& L, const char* name, T& value) {
using namespace openspace::configuration;
// The profile that should be loaded at the startup. The profile determines which
// assets are loaded, the startup time, keyboard shortcuts, and other settings.
std::optional<std::string> profile;
auto it = std::find_if(
Configuration::Documentation.entries.begin(),
Configuration::Documentation.entries.end(),
[name](const openspace::documentation::DocumentationEntry& e) {
return e.key == name;
}
);
// This value names a list of scripts that get executed after initialization of
// any scene. These scripts can be used for user-specific customization, such as a
// global rebinding of keys from the default
std::optional<std::vector<std::string>> globalCustomizationScripts;
bool isOptional =
it != Configuration::Documentation.entries.end()
? it->optional :
true;
// A list of paths that are automatically registered with the file system. If a
// key X is used in the table, it is then useable by referencing ${X} in all other
// configuration files or scripts
std::map<std::string, std::string> paths;
lua_getglobal(L, name);
if (isOptional && lua_isnil(L, -1)) {
return;
}
// A list of all fonts that will automatically be loaded on startup. Each
// key-value pair contained in the table will become the name and the file for a
// font
std::optional<std::map<std::string, std::string>> fonts;
if (!isOptional && lua_isnil(L, -1)) {
openspace::documentation::TestResult testResult = {
false,
{ {
name,
openspace::documentation::TestResult::Offense::Reason::MissingKey
}},
{}
struct Logging {
// List from logmanager.cpp::levelFromString
enum class Level {
Trace,
Debug,
Info,
Warning,
Error,
Fatal,
None
};
throw openspace::documentation::SpecificationError(
std::move(testResult),
"Configuration"
);
}
// The severity of log messages that will be displayed. Only messages of the
// selected level or higher will be displayed. All levels below will be
// silently discarded. The order of severities is:
// Debug < Info < Warning < Error < Fatal < None.
std::optional<Level> logLevel;
if constexpr (std::is_same_v<T, glm::dvec3>) {
ghoul::Dictionary d = ghoul::lua::value<ghoul::Dictionary>(L);
glm::dvec3 res;
res.x = d.value<double>("1");
res.y = d.value<double>("2");
res.z = d.value<double>("3");
value = res;
}
// NOLINTNEXTLINE
else if constexpr (std::is_same_v<T, std::vector<std::string>>) {
ghoul::Dictionary d = ghoul::lua::value<ghoul::Dictionary>(L);
// Determines whether error messages will be displayed immediately or if it is
// acceptable to have a short delay, but being more performant. If the delay
// is allowed ('true'), messages might get lost if the application crashes
// shortly after a message was logged
std::optional<bool> immediateFlush;
std::vector<std::string> res;
for (size_t i = 1; i <= d.size(); ++i) {
res.push_back(d.value<std::string>(std::to_string(i)));
}
value = std::move(res);
}
// NOLINTNEXTLINE
else if constexpr (std::is_same_v<T, std::map<std::string, std::string>>) {
ghoul::Dictionary d = ghoul::lua::value<ghoul::Dictionary>(L);
// Per default, log messages are written to the console, the onscreen text,
// and (if available) the Visual Studio output window. This table can define
// other logging methods that will be used additionally
std::optional<std::vector<ghoul::Dictionary>> logs
[[codegen::reference("core_logfactory")]];
std::map<std::string, std::string> res;
std::vector<std::string_view> keys = d.keys();
for (size_t i = 0; i < d.size(); ++i) {
std::string_view key = keys[i];
std::string v = d.value<std::string>(key);
res[std::string(key)] = std::move(v);
}
value = std::move(res);
}
// NOLINTNEXTLINE
else if constexpr (std::is_same_v<T, std::map<std::string, ghoul::Dictionary>>) {
ghoul::Dictionary d = ghoul::lua::value<ghoul::Dictionary>(L);
// List from OpenspaceEngine::initialize
enum class Verbosity {
None,
Minimal,
Default,
Full
};
// At startup, a list of system capabilities is created and logged. This value
// determines how verbose this listing should be
std::optional<Verbosity> capabilitiesVerbosity;
};
// Configurations for the logging of messages that are generated throughout the
// code and are useful for debugging potential errors or other information
std::optional<Logging> logging;
std::map<std::string, ghoul::Dictionary> res;
std::vector<std::string_view> keys = d.keys();
for (size_t i = 0; i < d.size(); ++i) {
std::string_view key = keys[i];
ghoul::Dictionary v = d.value<ghoul::Dictionary>(key);
res[std::string(key)] = std::move(v);
}
value = std::move(res);
}
// NOLINTNEXTLINE
else if constexpr (std::is_same_v<T, Configuration::Logging>) {
Configuration::Logging& v = static_cast<Configuration::Logging&>(value);
ghoul::Dictionary d = ghoul::lua::value<ghoul::Dictionary>(L);
// The file that will be created on startup containing the log of all Lua scripts
// that are executed in the last session. Any existing file (including the results
// from previous runs) will be silently overwritten
std::optional<std::string> scriptLog;
if (d.hasValue<std::string>(KeyLogLevel)) {
v.level = d.value<std::string>(KeyLogLevel);
}
if (d.hasValue<bool>(KeyImmediateFlush)) {
v.forceImmediateFlush = d.value<bool>(KeyImmediateFlush);
}
if (d.hasValue<std::string>(KeyCapabilitiesVerbosity)) {
v.capabilitiesVerbosity = d.value<std::string>(KeyCapabilitiesVerbosity);
}
struct Documentation {
// The path where the documentation files will be stored
std::optional<std::string> path;
};
// Right now only contains the path where the documentation is written to
std::optional<Documentation> documentation;
if (d.hasValue<ghoul::Dictionary>(KeyLogs)) {
ghoul::Dictionary l = d.value<ghoul::Dictionary>(KeyLogs);
std::vector<ghoul::Dictionary> res;
for (size_t i = 1; i <= l.size(); ++i) {
res.push_back(l.value<ghoul::Dictionary>(std::to_string(i)));
}
v.logs = res;
}
}
// NOLINTNEXTLINE
else if constexpr (std::is_same_v<T, Configuration::DocumentationInfo>) {
Configuration::DocumentationInfo& v =
static_cast<Configuration::DocumentationInfo&>(value);
ghoul::Dictionary d = ghoul::lua::value<ghoul::Dictionary>(L);
if (d.hasValue<std::string>(KeyDocumentationPath)) {
v.path = d.value<std::string>(KeyDocumentationPath);
}
}
// NOLINTNEXTLINE
else if constexpr (std::is_same_v<T, Configuration::LoadingScreen>) {
Configuration::LoadingScreen& v =
static_cast<Configuration::LoadingScreen&>(value);
ghoul::Dictionary d = ghoul::lua::value<ghoul::Dictionary>(L);
if (d.hasValue<bool>(KeyShowMessage)) {
v.isShowingMessages = d.value<bool>(KeyShowMessage);
}
if (d.hasValue<bool>(KeyShowNodeNames)) {
v.isShowingNodeNames = d.value<bool>(KeyShowNodeNames);
}
if (d.hasValue<bool>(KeyShowProgressbar)) {
v.isShowingProgressbar = d.value<bool>(KeyShowProgressbar);
}
}
// NOLINTNEXTLINE
else if constexpr (std::is_same_v<T, Configuration::OpenGLDebugContext>) {
Configuration::OpenGLDebugContext& v =
static_cast<Configuration::OpenGLDebugContext&>(value);
ghoul::Dictionary d = ghoul::lua::value<ghoul::Dictionary>(L);
// The countdown that the application will wait between pressing ESC and actually
// shutting down. If ESC is pressed again in this time, the shutdown is aborted
std::optional<float> shutdownCountdown [[codegen::greater(0.0)]];
if (d.hasValue<bool>(KeyActivate)) {
v.isActive = d.value<bool>(KeyActivate);
}
if (d.hasValue<bool>(KeySynchronous)) {
v.isSynchronous = d.value<bool>(KeySynchronous);
}
// If this is set to 'true', the name of the scene will be appended to the cache
// directory, thus not reusing the same directory. This is useful in cases where
// the same instance of OpenSpace is run with multiple scenes, but the caches
// should be retained. This value defaults to 'false'
std::optional<bool> perSceneCache;
if (d.hasValue<ghoul::Dictionary>(KeyFilterIdentifier)) {
ghoul::Dictionary f = d.value<ghoul::Dictionary>(KeyFilterIdentifier);
enum class Scaling {
Window [[codegen::key("window")]],
Framebuffer [[codegen::key("framebuffer")]]
};
// The method for scaling the onscreen text in the window. As the resolution of
// the rendering can be different from the size of the window, the onscreen text
// can either be scaled according to the window size ('window'), or the rendering
// resolution ('framebuffer'). This value defaults to 'window'
std::optional<Scaling> onScreenTextScaling;
std::vector<Configuration::OpenGLDebugContext::IdentifierFilter> res;
for (size_t i = 1; i <= f.size(); ++i) {
Configuration::OpenGLDebugContext::IdentifierFilter filter;
ghoul::Dictionary fi = f.value<ghoul::Dictionary>(std::to_string(i));
// List from RenderEngine::setRendererFromString
enum class RenderingMethod {
Framebuffer,
ABuffer
};
// The renderer that is use after startup. The renderer 'ABuffer' requires support
// for at least OpenGL 4.3
std::optional<RenderingMethod> renderingMethod;
if (fi.hasValue<double>(KeyIdentifier)) {
filter.identifier = static_cast<unsigned int>(
fi.value<double>(KeyIdentifier)
);
}
if (fi.hasValue<std::string>(KeySource)) {
filter.source = fi.value<std::string>(KeySource);
}
if (fi.hasValue<std::string>(KeyType)) {
filter.type = fi.value<std::string>(KeyType);
}
// Toggles whether the master in a multi-application setup should be rendering or
// just managing the state of the network. This is desired in cases where the
// master computer does not have the resources to render a scene
std::optional<bool> disableRenderingOnMaster;
auto fff = filter;
const auto ffg = filter;
// Applies a global view rotation. Use this to rotate the position of the focus
// node away from the default location on the screen. This setting persists even
// when a new focus node is selected. Defined using roll, pitch, yaw in radians
std::optional<glm::dvec3> globalRotation;
res.push_back(std::move(filter));
}
// Applies a view rotation for only the master node, defined using roll, pitch yaw
// in radians. This can be used to compensate the master view direction for tilted
// display systems in clustered immersive environments
std::optional<glm::dvec3> masterRotation;
v.identifierFilters = res;
}
// Applies a global rotation for all screenspace renderables. Defined using roll,
// pitch, yaw in radians
std::optional<glm::dvec3> screenSpaceRotation;
if (d.hasValue<ghoul::Dictionary>(KeyFilterSeverity)) {
ghoul::Dictionary f = d.value<ghoul::Dictionary>(KeyFilterSeverity);
// If this value is set to 'true' the ingame console is disabled, locking the
// system down against random access
std::optional<bool> disableInGameConsole;
std::vector<std::string> res;
for (size_t i = 1; i <= f.size(); ++i) {
res.push_back(f.value<std::string>(std::to_string(i)));
}
v.severityFilters = res;
}
}
// NOLINTNEXTLINE
else if constexpr (std::is_same_v<T, Configuration::HTTPProxy>) {
Configuration::HTTPProxy& v = static_cast<Configuration::HTTPProxy&>(value);
ghoul::Dictionary d = ghoul::lua::value<ghoul::Dictionary>(L);
// Toggles whether screenshots generated by OpenSpace contain the date when the
// concrete OpenSpace instance was started. This value is enabled by default, but
// it is advised to disable this value if rendering sessions of individual frames
// pass beyond local midnight
std::optional<bool> screenshotUseDate;
if (d.hasValue<bool>(KeyActivate)) {
v.usingHttpProxy = d.value<bool>(KeyActivate);
}
if (d.hasValue<std::string>(KeyAddress)) {
v.address = d.value<std::string>(KeyAddress);
}
if (d.hasValue<double>(KeyPort)) {
v.port = static_cast<unsigned int>(d.value<double>(KeyPort));
}
if (d.hasValue<std::string>(KeyAuthentication)) {
v.authentication = d.value<std::string>(KeyAuthentication);
}
if (d.hasValue<std::string>(KeyUser)) {
v.user = d.value<std::string>(KeyUser);
}
if (d.hasValue<std::string>(KeyPassword)) {
v.password = d.value<std::string>(KeyPassword);
}
}
else {
value = ghoul::lua::value<T>(L);
}
}
struct HttpProxy {
// Determines whether the proxy is being used
std::optional<bool> activate;
// The address of the http proxy
std::string address;
// The port of the http proxy
int port [[codegen::inrange(0, 65536)]];
enum class Authentication {
Basic [[codegen::key("basic")]],
Ntlm [[codegen::key("ntlm")]],
Digest [[codegen::key("digest")]],
Any [[codegen::key("any")]]
};
// The authentication method of the http proxy
std::optional<Authentication> authentication;
// The user of the http proxy
std::optional<std::string> user;
// The password of the http proxy
std::optional<std::string> password;
};
// This defines the use for a proxy when fetching data over http. No proxy will be
// used if this is left out
std::optional<HttpProxy> httpProxy;
struct OpenGLDebugContext {
// Determines whether the OpenGL context should be a debug context
bool activate;
// Determines whether the OpenGL debug callbacks are performed synchronously.
// If set to 'true' the callbacks are in the same thread as the context and in
// the scope of the OpenGL function that triggered the message. The default
// value is 'true'
std::optional<bool> synchronous;
// Individual OpenGL debug message identifiers
struct Filter {
// The identifier that is to be filtered
int identifier;
// Taken from ghoul::debugcontext.cpp
enum class Source {
API,
WindowSystem [[codegen::key("Window System")]],
ShaderCompiler [[codegen::key("Shader Compiler")]],
ThirdParty [[codegen::key("Third Party")]],
Application,
Other,
DontCare [[codegen::key("Don't care")]]
};
// The source of the identifier to be filtered
Source source;
// Taken from ghoul::debugcontext.cpp
enum class Type {
Error,
Deprecated,
Undefined,
Portability,
Performance,
Marker,
PushGroup [[codegen::key("Push group")]],
PopGroup [[codegen::key("Pop group")]],
Other,
DontCare [[codegen::key("Don't care")]]
};
// The type of the identifier to be filtered
Type type;
};
// A list of OpenGL debug messages identifiers that are filtered
std::optional<std::vector<Filter>> filterIdentifier;
// A list of severities that can are filtered out
enum class Severity {
High,
Medium,
Low,
Notification
};
// Determines the settings for the creation of an OpenGL debug context
std::optional<std::vector<Severity>> filterSeverity;
};
// Determines the settings for the creation of an OpenGL debug context
std::optional<OpenGLDebugContext> openGLDebugContext;
// Determines whether the OpenGL state is checked after each OpenGL function call.
// This will dramatically slow down the rendering, but will make finding OpenGL
// errors easier. This defaults to 'false'
std::optional<bool> checkOpenGLState;
// Determines whether each OpenGL call that happens should be logged using the
// 'TRACE' loglevel. This will bring the rendering to a crawl but provides useful
// debugging features for the order in which OpenGL calls occur. This defaults to
// 'false'
std::optional<bool> logEachOpenGLCall;
// This value determines whether the initialization of the scene graph should
// occur multithreaded, that is, whether multiple scene graph nodes should
// initialize in parallel. The only use for this value is to disable it for
// debugging support
std::optional<bool> useMultithreadedInitialization;
// If this value is set to 'true', the launcher will not be shown and OpenSpace
// will start with the provided configuration options directly. Useful in
// multiprojector setups where a launcher window would be undesired
std::optional<bool> bypassLauncher;
// The URL that is pinged to check which version of OpenSpace is the most current
// if you don't want this request to happen, this value should not be set at all
std::optional<std::string> versionCheckUrl;
struct LoadingScreen {
// If this value is set to 'true', the loading screen will display a message
// information about the current phase the loading is in
std::optional<bool> showMessage;
// If this value is set to 'true', the loading screen will display a list of
// all of the nodes with their respective status (created, loaded,
// initialized)
std::optional<bool> showNodeNames;
// If this value is set to 'true', the loading screen will contain a progress
// bar that gives an estimate of the loading progression
std::optional<bool> showProgressbar;
};
// Values in this table describe the behavior of the loading screen that is
// displayed while the scene graph is created and initialized
std::optional<LoadingScreen> loadingScreen;
// List of profiles that cannot be overwritten by user
std::optional<std::vector<std::string>> readOnlyProfiles;
// Configurations for each module
std::optional<std::map<std::string, ghoul::Dictionary>> moduleConfigurations;
};
#include "configuration_codegen.cpp"
} // namespace
#include "configuration_doc.inl"
namespace openspace::configuration {
void parseLuaState(Configuration& configuration) {
@@ -317,40 +334,277 @@ void parseLuaState(Configuration& configuration) {
Configuration& c = configuration;
LuaState& s = c.state;
getValue(s, KeySGCTConfig, c.windowConfiguration);
getValue(s, KeyAsset, c.asset);
getValue(s, KeyProfile, c.profile);
getValue(s, KeyGlobalCustomizationScripts, c.globalCustomizationScripts);
getValue(s, KeyPaths, c.pathTokens);
getValue(s, KeyFonts, c.fonts);
getValue(s, KeyScriptLog, c.scriptLog);
getValue(s, KeyVersionCheckUrl, c.versionCheckUrl);
getValue(s, KeyUseMultithreadedInitialization, c.useMultithreadedInitialization);
getValue(s, KeyCheckOpenGLState, c.isCheckingOpenGLState);
getValue(s, KeyLogEachOpenGLCall, c.isLoggingOpenGLCalls);
getValue(s, KeyShutdownCountdown, c.shutdownCountdown);
getValue(s, KeyScreenshotUseDate, c.shouldUseScreenshotDate);
getValue(s, KeyOnScreenTextScaling, c.onScreenTextScaling);
getValue(s, KeyPerSceneCache, c.usePerSceneCache);
getValue(s, KeyDisableRenderingOnMaster, c.isRenderingOnMasterDisabled);
// The sgctConfigNameInitialized is a bit special
lua_getglobal(s, "sgctconfiginitializeString");
c.sgctConfigNameInitialized = ghoul::lua::value<std::string>(
s,
ghoul::lua::PopValue::Yes
);
getValue(s, KeyGlobalRotation, c.globalRotation);
getValue(s, KeyScreenSpaceRotation, c.screenSpaceRotation);
getValue(s, KeyMasterRotation, c.masterRotation);
getValue(s, KeyDisableInGameConsole, c.isConsoleDisabled);
getValue(s, KeyRenderingMethod, c.renderingMethod);
getValue(s, KeyLogging, c.logging);
getValue(s, KeyDocumentation, c.documentation);
getValue(s, KeyLoadingScreen, c.loadingScreen);
getValue(s, KeyModuleConfigurations, c.moduleConfigurations);
getValue(s, KeyOpenGLDebugContext, c.openGLDebugContext);
getValue(s, KeyHttpProxy, c.httpProxy);
getValue(s, KeySgctConfigNameInitialized, c.sgctConfigNameInitialized);
getValue(s, KeyReadOnlyProfiles, c.readOnlyProfiles);
getValue(s, KeyBypassLauncher, c.bypassLauncher);
// The configuration file sets all values as global variables, so we need to pull them
// into a table first so that we can pass that table to the dictionary constructor
lua_newtable(s);
// We go through all of the entries and lift them from global scope into the table on
// the stack so that we can create a ghoul::Dictionary from this new table
documentation::Documentation doc = codegen::doc<Parameters>();
for (const documentation::DocumentationEntry& e : doc.entries) {
lua_pushstring(s, e.key.c_str());
lua_getglobal(s, e.key.c_str());
lua_settable(s, -3);
}
ghoul::Dictionary d;
ghoul::lua::luaDictionaryFromState(s, d);
lua_settop(s, 0);
const Parameters p = codegen::bake<Parameters>(d);
c.windowConfiguration = p.windowConfiguration.value_or(c.windowConfiguration);
c.asset = p.asset.value_or(c.asset);
c.profile = p.profile.value_or(c.profile);
c.globalCustomizationScripts =
p.globalCustomizationScripts.value_or(c.globalCustomizationScripts);
c.pathTokens = p.paths;
c.fonts = p.fonts.value_or(c.fonts);
c.scriptLog = p.scriptLog.value_or(c.scriptLog);
c.versionCheckUrl = p.versionCheckUrl.value_or(c.versionCheckUrl);
c.useMultithreadedInitialization =
p.useMultithreadedInitialization.value_or(c.useMultithreadedInitialization);
c.isCheckingOpenGLState = p.checkOpenGLState.value_or(c.isCheckingOpenGLState);
c.isLoggingOpenGLCalls = p.logEachOpenGLCall.value_or(c.isLoggingOpenGLCalls);
c.shutdownCountdown = p.shutdownCountdown.value_or(c.shutdownCountdown);
c.shouldUseScreenshotDate = p.screenshotUseDate.value_or(c.shouldUseScreenshotDate);
if (p.onScreenTextScaling.has_value()) {
switch (*p.onScreenTextScaling) {
case Parameters::Scaling::Window:
c.onScreenTextScaling = "window";
break;
case Parameters::Scaling::Framebuffer:
c.onScreenTextScaling = "framebuffer";
break;
default:
throw ghoul::MissingCaseException();
}
}
c.usePerSceneCache = p.perSceneCache.value_or(c.usePerSceneCache);
c.isRenderingOnMasterDisabled =
p.disableRenderingOnMaster.value_or(c.isRenderingOnMasterDisabled);
c.globalRotation = p.globalRotation.value_or(c.globalRotation);
c.masterRotation = p.masterRotation.value_or(c.masterRotation);
c.screenSpaceRotation = p.screenSpaceRotation.value_or(c.screenSpaceRotation);
if (p.renderingMethod.has_value()) {
switch (*p.renderingMethod) {
case Parameters::RenderingMethod::Framebuffer:
c.renderingMethod = "Framebuffer";
break;
case Parameters::RenderingMethod::ABuffer:
c.renderingMethod = "ABuffer";
break;
default:
throw ghoul::MissingCaseException();
}
}
c.isConsoleDisabled = p.disableInGameConsole.value_or(c.isConsoleDisabled);
if (p.logging.has_value()) {
if (p.logging->logLevel.has_value()) {
switch (*p.logging->logLevel) {
case Parameters::Logging::Level::Trace:
c.logging.level = "Trace";
break;
case Parameters::Logging::Level::Debug:
c.logging.level = "Debug";
break;
case Parameters::Logging::Level::Info:
c.logging.level = "Info";
break;
case Parameters::Logging::Level::Warning:
c.logging.level = "Warning";
break;
case Parameters::Logging::Level::Error:
c.logging.level = "Error";
break;
case Parameters::Logging::Level::Fatal:
c.logging.level = "Fatal";
break;
case Parameters::Logging::Level::None:
c.logging.level = "None";
break;
default:
throw ghoul::MissingCaseException();
}
}
c.logging.forceImmediateFlush =
p.logging->immediateFlush.value_or(c.logging.forceImmediateFlush);
c.logging.logs = p.logging->logs.value_or(c.logging.logs);
if (p.logging->capabilitiesVerbosity.has_value()) {
switch (*p.logging->capabilitiesVerbosity) {
case Parameters::Logging::Verbosity::None:
c.logging.capabilitiesVerbosity = "None";
break;
case Parameters::Logging::Verbosity::Minimal:
c.logging.capabilitiesVerbosity = "Minimal";
break;
case Parameters::Logging::Verbosity::Default:
c.logging.capabilitiesVerbosity = "Default";
break;
case Parameters::Logging::Verbosity::Full:
c.logging.capabilitiesVerbosity = "Full";
break;
default:
throw ghoul::MissingCaseException();
}
}
}
if (p.documentation.has_value()) {
c.documentation.path = p.documentation->path.value_or(c.documentation.path);
}
if (p.loadingScreen.has_value()) {
const Parameters::LoadingScreen& l = *p.loadingScreen;
c.loadingScreen.isShowingMessages =
l.showMessage.value_or(c.loadingScreen.isShowingMessages);
c.loadingScreen.isShowingProgressbar =
l.showProgressbar.value_or(c.loadingScreen.isShowingProgressbar);
c.loadingScreen.isShowingNodeNames =
l.showNodeNames.value_or(c.loadingScreen.isShowingNodeNames);
}
c.moduleConfigurations = p.moduleConfigurations.value_or(c.moduleConfigurations);
if (p.openGLDebugContext.has_value()) {
const Parameters::OpenGLDebugContext& l = *p.openGLDebugContext;
c.openGLDebugContext.isActive = l.activate;
c.openGLDebugContext.isSynchronous = l.synchronous.value_or(
c.openGLDebugContext.isSynchronous
);
if (l.filterIdentifier.has_value()) {
for (const Parameters::OpenGLDebugContext::Filter& f : *l.filterIdentifier) {
Configuration::OpenGLDebugContext::IdentifierFilter filter;
filter.identifier = static_cast<unsigned int>(f.identifier);
switch (f.source) {
case Parameters::OpenGLDebugContext::Filter::Source::API:
filter.source = "API";
break;
case Parameters::OpenGLDebugContext::Filter::Source::WindowSystem:
filter.source = "Window System";
break;
case Parameters::OpenGLDebugContext::Filter::Source::ShaderCompiler:
filter.source = "Shader Compiler";
break;
case Parameters::OpenGLDebugContext::Filter::Source::ThirdParty:
filter.source = "Third Party";
break;
case Parameters::OpenGLDebugContext::Filter::Source::Application:
filter.source = "Application";
break;
case Parameters::OpenGLDebugContext::Filter::Source::Other:
filter.source = "Other";
break;
case Parameters::OpenGLDebugContext::Filter::Source::DontCare:
filter.source = "Don't care";
break;
default:
throw ghoul::MissingCaseException();
}
switch (f.type) {
case Parameters::OpenGLDebugContext::Filter::Type::Error:
filter.type = "Error";
break;
case Parameters::OpenGLDebugContext::Filter::Type::Deprecated:
filter.type = "Deprecated";
break;
case Parameters::OpenGLDebugContext::Filter::Type::Undefined:
filter.type = "Undefined";
break;
case Parameters::OpenGLDebugContext::Filter::Type::Portability:
filter.type = "Portability";
break;
case Parameters::OpenGLDebugContext::Filter::Type::Performance:
filter.type = "Performance";
break;
case Parameters::OpenGLDebugContext::Filter::Type::Marker:
filter.type = "Marker";
break;
case Parameters::OpenGLDebugContext::Filter::Type::PushGroup:
filter.type = "Push group";
break;
case Parameters::OpenGLDebugContext::Filter::Type::PopGroup:
filter.type = "Pop group";
break;
case Parameters::OpenGLDebugContext::Filter::Type::Other:
filter.type = "Other";
break;
case Parameters::OpenGLDebugContext::Filter::Type::DontCare:
filter.type = "Don't care";
break;
default:
throw ghoul::MissingCaseException();
}
c.openGLDebugContext.identifierFilters.push_back(filter);
}
}
if (l.filterSeverity.has_value()) {
for (Parameters::OpenGLDebugContext::Severity sev : *l.filterSeverity) {
std::string severity;
switch (sev) {
case Parameters::OpenGLDebugContext::Severity::High:
severity = "High";
break;
case Parameters::OpenGLDebugContext::Severity::Medium:
severity = "Medium";
break;
case Parameters::OpenGLDebugContext::Severity::Low:
severity = "Low";
break;
case Parameters::OpenGLDebugContext::Severity::Notification:
severity = "Notification";
break;
default:
throw ghoul::MissingCaseException();
}
c.openGLDebugContext.severityFilters.push_back(severity);
}
}
}
if (p.httpProxy.has_value()) {
c.httpProxy.usingHttpProxy =
p.httpProxy->activate.value_or(c.httpProxy.usingHttpProxy);
c.httpProxy.address = p.httpProxy->address;
c.httpProxy.port = static_cast<unsigned int>(p.httpProxy->port);
if (p.httpProxy->authentication.has_value()) {
switch (*p.httpProxy->authentication) {
case Parameters::HttpProxy::Authentication::Basic:
c.httpProxy.authentication = "basic";
break;
case Parameters::HttpProxy::Authentication::Ntlm:
c.httpProxy.authentication = "ntlm";
break;
case Parameters::HttpProxy::Authentication::Digest:
c.httpProxy.authentication = "digest";
break;
case Parameters::HttpProxy::Authentication::Any:
c.httpProxy.authentication = "any";
break;
default:
throw ghoul::MissingCaseException();
}
}
c.httpProxy.user = p.httpProxy->user.value_or(c.httpProxy.user);
c.httpProxy.password = p.httpProxy->password.value_or(c.httpProxy.password);
}
c.readOnlyProfiles = p.readOnlyProfiles.value_or(c.readOnlyProfiles);
c.bypassLauncher = p.bypassLauncher.value_or(c.bypassLauncher);
}
documentation::Documentation Configuration::Documentation = codegen::doc<Parameters>();
std::string findConfiguration(const std::string& filename) {
using ghoul::filesystem::Directory;
@@ -383,16 +637,14 @@ std::string findConfiguration(const std::string& filename) {
}
}
Configuration loadConfigurationFromFile(const std::string& filename) {
Configuration loadConfigurationFromFile(const std::string& filename,
const std::string& overrideScript)
{
ghoul_assert(!filename.empty(), "Filename must not be empty");
ghoul_assert(FileSys.fileExists(filename), "File must exist");
Configuration result;
// Register the base path as the directory where 'filename' lives
std::string basePath = ghoul::filesystem::File(filename).directoryName();
FileSys.registerPathToken(BasePathToken, basePath);
// If there is an initial config helper file, load it into the state
if (FileSys.fileExists(absPath(InitialConfigHelper))) {
ghoul::lua::runScriptFile(result.state, absPath(InitialConfigHelper));
@@ -401,6 +653,12 @@ Configuration loadConfigurationFromFile(const std::string& filename) {
// Load the configuration file into the state
ghoul::lua::runScriptFile(result.state, filename);
if (!overrideScript.empty()) {
LDEBUGC("Configuration", "Executing Lua script passed through the commandline:");
LDEBUGC("Configuration", overrideScript);
ghoul::lua::runScript(result.state, overrideScript);
}
parseLuaState(result);
return result;

View File

@@ -1,450 +0,0 @@
/*****************************************************************************************
* *
* OpenSpace *
* *
* Copyright (c) 2014-2021 *
* *
* Permission is hereby granted, free of charge, to any person obtaining a copy of this *
* software and associated documentation files (the "Software"), to deal in the Software *
* without restriction, including without limitation the rights to use, copy, modify, *
* merge, publish, distribute, sublicense, and/or sell copies of the Software, and to *
* permit persons to whom the Software is furnished to do so, subject to the following *
* conditions: *
* *
* The above copyright notice and this permission notice shall be included in all copies *
* or substantial portions of the Software. *
* *
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, *
* INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A *
* PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT *
* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF *
* CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE *
* OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. *
****************************************************************************************/
#include <openspace/documentation/documentation.h>
#include <openspace/documentation/verifier.h>
namespace openspace::configuration {
using namespace documentation;
documentation::Documentation Configuration::Documentation = {
"OpenSpace Configuration",
"openspace_configuraion",
{
{
KeySGCTConfig,
new StringAnnotationVerifier("A valid SGCT configuration file"),
Optional::Yes,
"The SGCT configuration file that determines the window and view frustum "
"settings that are being used when OpenSpace is started."
},
{
KeySgctConfigNameInitialized,
new StringAnnotationVerifier("The type of SGCT autogen function (if called)"),
Optional::Yes,
"The SGCT configuration can be defined from an .xml file, or auto-generated "
"by an sgct.config.* lua function. If a lua function is used to generate the "
"SGCT configuration, then this key contains the name of the function, "
"otherwise is blank."
},
{
KeyAsset,
new StringAnnotationVerifier(
"A valid scene file as described in the Scene documentation"
),
Optional::Yes,
"The scene description that is used to populate the application after "
"startup. The scene determines which objects are loaded, the startup "
"time and other scene-specific settings. More information is provided in "
"the Scene documentation."
},
{
KeyGlobalCustomizationScripts,
new StringListVerifier,
Optional::Yes,
"This value names a list of scripts that get executed after initialization "
"of any scene. These scripts can be used for user-specific customization, "
"such as a global rebinding of keys from the default."
},
{
KeyPaths,
new StringListVerifier,
Optional::No,
"A list of paths that are automatically registered with the file system. "
"If a key X is used in the table, it is then useable by referencing ${X} "
"in all other configuration files or scripts."
},
{
KeyFonts,
new StringListVerifier("Font paths loadable by FreeType"),
Optional::Yes,
"A list of all fonts that will automatically be loaded on startup. Each "
"key-value pair contained in the table will become the name and the file "
"for a font."
},
{
KeyLogging,
new TableVerifier({
{
KeyLogDir,
new StringVerifier,
Optional::Yes,
"The directory for logs. Default value is \"${BASE}\""
},
{
KeyPerformancePrefix,
new StringVerifier,
Optional::Yes,
"A string to prefix PerformanceMeasurement logfiles."
"Default value is \"PM-\""
},
{
KeyLogLevel,
new StringInListVerifier(
// List from logmanager.cpp::levelFromString
{ "Trace", "Debug", "Info", "Warning", "Error", "Fatal", "None" }
),
Optional::Yes,
"The severity of log messages that will be displayed. Only "
"messages of the selected level or higher will be displayed. All "
"levels below will be silently discarded. The order of "
"severities is: Debug < Info < Warning < Error < Fatal < None."
},
{
KeyImmediateFlush,
new BoolVerifier,
Optional::Yes,
"Determines whether error messages will be displayed immediately "
"or if it is acceptable to have a short delay, but being more "
"performant. If the delay is allowed ('true'), messages might "
"get lost if the application crashes shortly after a message was "
"logged."
},
{
KeyLogs,
new TableVerifier({
{
"*",
new ReferencingVerifier("core_logfactory"),
Optional::No,
"Additional log files"
}
}),
Optional::Yes,
"Per default, log messages are written to the console, the "
"onscreen text, and (if available) the Visual Studio output "
"window. This table can define other logging methods that will "
"be used additionally."
},
{
KeyCapabilitiesVerbosity,
new StringInListVerifier(
// List from OpenspaceEngine::initialize
{ "None", "Minimal", "Default", "Full" }
),
Optional::Yes,
"At startup, a list of system capabilities is created and logged."
"This value determines how verbose this listing should be."
}
}),
Optional::Yes,
"Configurations for the logging of messages that are generated "
"throughout the code and are useful for debugging potential errors or "
"other information."
},
{
KeyScriptLog,
new StringVerifier,
Optional::Yes,
"The file that will be created on startup containing the log of all Lua "
"scripts that are executed in the last session. Any existing file (including "
"the results from previous runs) will be silently overwritten."
},
{
KeyDocumentationPath,
new TableVerifier({
{
KeyDocumentationPath,
new StringVerifier,
Optional::Yes,
"The path where the documentation files will be stored."
},
}),
Optional::Yes,
"Right now only contains the path where the documentation is written to."
},
{
KeyShutdownCountdown,
new DoubleGreaterEqualVerifier(0.0),
Optional::Yes,
"The countdown that the application will wait between pressing ESC and "
"actually shutting down. If ESC is pressed again in this time, the "
"shutdown is aborted."
},
{
KeyPerSceneCache,
new BoolVerifier,
Optional::Yes,
"If this is set to 'true', the name of the scene will be appended to the "
"cache directory, thus not reusing the same directory. This is useful in "
"cases where the same instance of OpenSpace is run with multiple scenes, but "
"the caches should be retained. This value defaults to 'false'."
},
{
KeyOnScreenTextScaling,
new StringInListVerifier({
// Values from RenderEngine:updateRenderer
"window", "framebuffer"
}),
Optional::Yes,
"The method for scaling the onscreen text in the window. As the resolution "
"of the rendering can be different from the size of the window, the onscreen "
"text can either be scaled according to the window size ('window'), or the "
"rendering resolution ('framebuffer'). This value defaults to 'window'."
},
{
KeyRenderingMethod,
new StringInListVerifier(
// List from RenderEngine::setRendererFromString
{ "Framebuffer", "ABuffer" }
),
Optional::Yes,
"The renderer that is use after startup. The renderer 'ABuffer' requires "
"support for at least OpenGL 4.3"
},
{
KeyDisableRenderingOnMaster,
new BoolVerifier,
Optional::Yes,
"Toggles whether the master in a multi-application setup should be rendering "
"or just managing the state of the network. This is desired in cases where "
"the master computer does not have the resources to render a scene."
},
{
KeyGlobalRotation,
new DoubleVector3Verifier,
Optional::Yes,
"Applies a global view rotation. Use this to rotate the position of the "
"focus node away from the default location on the screen. This setting "
"persists even when a new focus node is selected. Defined using roll, pitch, "
"yaw in radians"
},
{
KeyMasterRotation,
new DoubleVector3Verifier,
Optional::Yes,
"Applies a view rotation for only the master node, defined using "
"roll, pitch yaw in radians. This can be used to compensate the master view "
"direction for tilted display systems in clustered immersive environments."
},
{
KeyScreenSpaceRotation,
new DoubleVector3Verifier,
Optional::Yes,
"Applies a global rotation for all screenspace renderables. Defined using "
"roll, pitch, yaw in radians."
},
{
KeyScreenshotUseDate,
new BoolVerifier,
Optional::Yes,
"Toggles whether screenshots generated by OpenSpace contain the date when "
"the concrete OpenSpace instance was started. This value is enabled by "
"default, but it is advised to disable this value if rendering sessions of "
"individual frames pass beyond local midnight."
},
{
KeyHttpProxy,
new TableVerifier({
{
KeyActivate,
new BoolVerifier,
Optional::Yes,
"Determines whether the proxy is being used"
},
{
KeyAddress,
new StringVerifier,
Optional::No,
"The address of the http proxy"
},
{
KeyPort,
new IntVerifier,
Optional::No,
"The port of the http proxy"
},
{
KeyAuthentication,
new StringInListVerifier(
{ "basic", "ntlm", "digest", "any" }
),
Optional::Yes,
"The authentication method of the http proxy"
},
{
KeyUser,
new StringVerifier,
Optional::Yes,
"The user of the http proxy"
},
{
KeyPassword,
new StringVerifier,
Optional::Yes,
"The password of the http proxy"
}
}),
Optional::Yes,
"This defines the use for a proxy when fetching data over http."
"No proxy will be used if this is left out."
},
{
KeyOpenGLDebugContext,
new TableVerifier({
{
KeyActivate,
new BoolVerifier,
Optional::No,
"Determines whether the OpenGL context should be a debug context"
},
{
KeySynchronous,
new BoolVerifier,
Optional::Yes,
"Determines whether the OpenGL debug callbacks are performed "
"synchronously. If set to <True> the callbacks are in the same "
"thread as the context and in the scope of the OpenGL function that "
"triggered the message. The default value is <True>."
},
{
KeyFilterIdentifier,
new TableVerifier({{
"*",
new TableVerifier({
{
KeyIdentifier,
new IntVerifier,
Optional::No,
"The identifier that is to be filtered"
},
{
KeySource,
new StringInListVerifier({
// Taken from ghoul::debugcontext.cpp
"API", "Window System", "Shader Compiler",
"Third Party", "Application", "Other", "Don't care"
}),
Optional::No,
"The source of the identifier to be filtered"
},
{
KeyType,
new StringInListVerifier({
// Taken from ghoul::debugcontext.cpp
"Error", "Deprecated", "Undefined", "Portability",
"Performance", "Marker", "Push group", "Pop group",
"Other", "Don't care"
}),
Optional::No,
"The type of the identifier to be filtered"
}
}),
Optional::No,
"Individual OpenGL debug message identifiers"
}}),
Optional::Yes,
"A list of OpenGL debug messages identifiers that are filtered"
},
{
KeyFilterSeverity,
new TableVerifier({
{
"*",
new StringInListVerifier(
// ghoul::debugcontext.cpp
{ "High", "Medium", "Low", "Notification" }
),
Optional::No
}
}),
Optional::Yes,
"A list of severities that can are filtered out"
}
}),
Optional::Yes,
"Determines the settings for the creation of an OpenGL debug context.",
},
{
KeyCheckOpenGLState,
new BoolVerifier,
Optional::Yes,
"Determines whether the OpenGL state is checked after each OpenGL function "
"call. This will dramatically slow down the rendering, but will make finding "
"OpenGL errors easier. This defaults to 'false'."
},
{
KeyLogEachOpenGLCall,
new BoolVerifier,
Optional::Yes,
"Determines whether each OpenGL call that happens should be logged using the "
"'TRACE' loglevel. This will bring the rendering to a crawl but provides "
"useful debugging features for the order in which OpenGL calls occur. This "
"defaults to 'false'."
},
{
KeyUseMultithreadedInitialization,
new BoolVerifier,
Optional::Yes,
"This value determines whether the initialization of the scene graph should "
"occur multithreaded, that is, whether multiple scene graph nodes should "
"initialize in parallel. The only use for this value is to disable it for "
"debugging support."
},
{
KeyLoadingScreen,
new TableVerifier({
{
KeyShowMessage,
new BoolVerifier,
Optional::Yes,
"If this value is set to 'true', the loading screen will display a "
"message information about the current phase the loading is in."
},
{
KeyShowNodeNames,
new BoolVerifier,
Optional::Yes,
"If this value is set to 'true', the loading screen will display a "
"list of all of the nodes with their respective status (created, "
"loaded, initialized)."
},
{
KeyShowProgressbar,
new BoolVerifier,
Optional::Yes,
"If this value is set to 'true', the loading screen will contain a "
"progress bar that gives an estimate of the loading progression."
}
}),
Optional::Yes,
"Values in this table describe the behavior of the loading screen that is "
"displayed while the scene graph is created and initialized."
},
{
KeyModuleConfigurations,
new TableVerifier,
Optional::Yes,
"Configurations for each module"
},
{
KeyReadOnlyProfiles,
new StringListVerifier,
Optional::Yes,
"List of profiles that cannot be overwritten by user"
}
}
};
} // namespace openspace::configuration

View File

@@ -32,186 +32,130 @@
#include <ghoul/logging/textlog.h>
#include <ghoul/misc/dictionary.h>
#include <ghoul/misc/exception.h>
#include <optional>
namespace {
constexpr const char* KeyType = "Type";
constexpr const char* KeyFilename = "File";
constexpr const char* KeyAppend = "Append";
constexpr const char* KeyTimeStamping = "TimeStamping";
constexpr const char* KeyDateStamping = "DateStamping";
constexpr const char* KeyCategoryStamping = "CategoryStamping";
constexpr const char* KeyLogLevelStamping = "LogLevelStamping";
constexpr const char* KeyLogLevel = "LogLevel";
constexpr const char* ValueHtmlLog = "html";
constexpr const char* ValueTextLog = "Text";
constexpr const char* BootstrapPath = "${WEB}/common/bootstrap.min.css";
constexpr const char* CssPath = "${WEB}/log/style.css";
constexpr const char* JsPath = "${WEB}/log/script.js";
struct [[codegen::Dictionary(LogFactory)]] Parameters {
enum class Type {
Html [[codegen::key("html")]],
Text
};
// The type of the new log to be generated
Type type;
// The filename to which the log will be written
std::string file;
// Determines whether the file will be cleared at startup or if the contents will
// be appended to previous runs
std::optional<bool> append;
// Determines whether the log entires should be stamped with the time at which the
// message was logged
std::optional<bool> timeStamping;
// Determines whether the log entries should be stamped with the date at which the
// message was logged
std::optional<bool> dateStamping;
// Determines whether the log entries should be stamped with the category that
// creates the log message
std::optional<bool> categoryStamping;
// Determines whether the log entries should be stamped with the log level that
// was used to create the log message
std::optional<bool> logLevelStamping;
enum class LogLevel {
AllLogging,
Trace,
Debug,
Info,
Warning,
Error,
Fatal,
NoLogging
};
// The log level for this specific text-based log
std::optional<LogLevel> logLevel;
};
#include "logfactory_codegen.cpp"
} // namespace
namespace openspace {
documentation::Documentation LogFactoryDocumentation() {
using namespace documentation;
return {
"LogFactory",
"core_logfactory",
{
{
KeyType,
new StringInListVerifier({
// List from createLog
ValueTextLog, ValueHtmlLog
}),
Optional::No,
"The type of the new log to be generated."
},
{
KeyFilename,
new StringVerifier,
Optional::No,
"The filename to which the log will be written."
},
{
KeyAppend,
new BoolVerifier,
Optional::Yes,
"Determines whether the file will be cleared at startup or if the "
"contents will be appended to previous runs."
},
{
KeyTimeStamping,
new BoolVerifier,
Optional::Yes,
"Determines whether the log entires should be stamped with the time at "
"which the message was logged."
},
{
KeyDateStamping,
new BoolVerifier,
Optional::Yes,
"Determines whether the log entries should be stamped with the date at "
"which the message was logged."
},
{
KeyCategoryStamping,
new BoolVerifier,
Optional::Yes,
"Determines whether the log entries should be stamped with the "
"category that creates the log message."
},
{
KeyLogLevelStamping,
new BoolVerifier,
Optional::Yes,
"Determines whether the log entries should be stamped with the log level "
"that was used to create the log message."
}
}
};
documentation::Documentation doc = codegen::doc<Parameters>();
doc.id = "core_logfactory";
return doc;
}
std::unique_ptr<ghoul::logging::Log> createLog(const ghoul::Dictionary& dictionary) {
documentation::testSpecificationAndThrow(
LogFactoryDocumentation(),
dictionary,
"LogFactory"
);
const Parameters p = codegen::bake<Parameters>(dictionary);
// 'type' and 'filename' are required keys
const std::string& type = dictionary.value<std::string>(KeyType);
const std::string& filename = absPath(dictionary.value<std::string>(KeyFilename));
// the rest are optional
bool append = true;
if (dictionary.hasValue<bool>(KeyAppend)) {
append = dictionary.value<bool>(KeyAppend);
}
bool timeStamp = true;
if (dictionary.hasValue<bool>(KeyTimeStamping)) {
timeStamp = dictionary.value<bool>(KeyTimeStamping);
}
bool dateStamp = true;
if (dictionary.hasValue<bool>(KeyDateStamping)) {
dateStamp = dictionary.value<bool>(KeyDateStamping);
}
bool categoryStamp = true;
if (dictionary.hasValue<bool>(KeyCategoryStamping)) {
categoryStamp = dictionary.value<bool>(KeyCategoryStamping);
}
bool logLevelStamp = true;
if (dictionary.hasValue<bool>(KeyLogLevelStamping)) {
logLevelStamp = dictionary.value<bool>(KeyLogLevelStamping);
}
std::string logLevel;
if (dictionary.hasValue<std::string>(KeyLogLevel)) {
logLevel = dictionary.value<std::string>(KeyLogLevel);
}
using Append = ghoul::logging::TextLog::Append;
using TimeStamping = ghoul::logging::Log::TimeStamping;
using DateStamping = ghoul::logging::Log::DateStamping;
using CategoryStamping = ghoul::logging::Log::CategoryStamping;
using LogLevelStamping = ghoul::logging::Log::LogLevelStamping;
if (type == ValueHtmlLog) {
std::vector<std::string> cssFiles{absPath(BootstrapPath), absPath(CssPath)};
std::vector<std::string> jsFiles{absPath(JsPath)};
if (logLevel.empty()) {
return std::make_unique<ghoul::logging::HTMLLog>(
filename,
Append(append),
TimeStamping(timeStamp),
DateStamping(dateStamp),
CategoryStamping(categoryStamp),
LogLevelStamping(logLevelStamp),
cssFiles,
jsFiles
);
std::string filename = absPath(p.file);
bool append = p.append.value_or(true);
bool timeStamp = p.timeStamping.value_or(true);
bool dateStamp = p.dateStamping.value_or(true);
bool categoryStamp = p.categoryStamping.value_or(true);
bool logLevelStamp = p.logLevelStamping.value_or(true);
ghoul::logging::LogLevel level = [](Parameters::LogLevel l) {
switch (l) {
case Parameters::LogLevel::AllLogging:
return ghoul::logging::LogLevel::AllLogging;
case Parameters::LogLevel::Trace:
return ghoul::logging::LogLevel::Trace;
case Parameters::LogLevel::Debug:
return ghoul::logging::LogLevel::Debug;
case Parameters::LogLevel::Info:
return ghoul::logging::LogLevel::Info;
case Parameters::LogLevel::Warning:
return ghoul::logging::LogLevel::Warning;
case Parameters::LogLevel::Error:
return ghoul::logging::LogLevel::Error;
case Parameters::LogLevel::Fatal:
return ghoul::logging::LogLevel::Fatal;
case Parameters::LogLevel::NoLogging:
return ghoul::logging::LogLevel::NoLogging;
default:
throw ghoul::MissingCaseException();
}
else {
}(p.logLevel.value_or(Parameters::LogLevel::AllLogging));
switch (p.type) {
case Parameters::Type::Html:
{
std::vector<std::string> cssFiles{ absPath(BootstrapPath), absPath(CssPath) };
std::vector<std::string> jsFiles{ absPath(JsPath) };
return std::make_unique<ghoul::logging::HTMLLog>(
filename,
Append(append),
TimeStamping(timeStamp),
DateStamping(dateStamp),
CategoryStamping(categoryStamp),
LogLevelStamping(logLevelStamp),
ghoul::logging::TextLog::Append(append),
ghoul::logging::Log::TimeStamping(timeStamp),
ghoul::logging::Log::DateStamping(dateStamp),
ghoul::logging::Log::CategoryStamping(categoryStamp),
ghoul::logging::Log::LogLevelStamping(logLevelStamp),
cssFiles,
jsFiles,
ghoul::from_string<ghoul::logging::LogLevel>(logLevel)
);
level
);
}
}
else if (type == ValueTextLog) {
if (logLevel.empty()) {
case Parameters::Type::Text:
return std::make_unique<ghoul::logging::TextLog>(
filename,
Append(append),
TimeStamping(timeStamp),
DateStamping(dateStamp),
CategoryStamping(categoryStamp),
LogLevelStamping(logLevelStamp)
ghoul::logging::TextLog::Append(append),
ghoul::logging::Log::TimeStamping(timeStamp),
ghoul::logging::Log::DateStamping(dateStamp),
ghoul::logging::Log::CategoryStamping(categoryStamp),
ghoul::logging::Log::LogLevelStamping(logLevelStamp),
level
);
}
else {
return std::make_unique<ghoul::logging::TextLog>(
filename,
Append(append),
TimeStamping(timeStamp),
DateStamping(dateStamp),
CategoryStamping(categoryStamp),
LogLevelStamping(logLevelStamp),
ghoul::from_string<ghoul::logging::LogLevel>(logLevel)
);
}
}
else {
throw ghoul::MissingCaseException();
default:
throw new ghoul::MissingCaseException();
}
}

View File

@@ -1609,8 +1609,8 @@ scripting::LuaLibrary OpenSpaceEngine::luaLibrary() {
"Removes a tag (second argument) from a scene graph node (first argument)"
},
{
"createSingeColorImage",
&luascriptfunctions::createSingeColorImage,
"createSingleColorImage",
&luascriptfunctions::createSingleColorImage,
{},
"string, vec3",
"Creates a 1 pixel image with a certain color in the cache folder and "

View File

@@ -294,11 +294,11 @@ int downloadFile(lua_State* L) {
/**
* \ingroup LuaScripts
* createSingeColorImage():
* createSingleColorImage():
* Creates a one pixel image with a given color and returns the path to the cached file
*/
int createSingeColorImage(lua_State* L) {
ghoul::lua::checkArgumentsAndThrow(L, 2, "lua::createSingeColorImage");
int createSingleColorImage(lua_State* L) {
ghoul::lua::checkArgumentsAndThrow(L, 2, "lua::createSingleColorImage");
const std::string& name = ghoul::lua::value<std::string>(L, 1);
const ghoul::Dictionary& d = ghoul::lua::value<ghoul::Dictionary>(L, 2);

View File

@@ -28,8 +28,8 @@
#include <openspace/documentation/documentation.h>
#include <openspace/documentation/verifier.h>
#include <openspace/util/factorymanager.h>
#include <ghoul/font/fontmanager.h>
#include <ghoul/misc/templatefactory.h>
#include <optional>
namespace {
constexpr const char* KeyType = "Type";
@@ -40,12 +40,6 @@ namespace {
"If this value is set to 'true' this dashboard item is shown in the dashboard"
};
constexpr openspace::properties::Property::PropertyInfo TypeInfo = {
"Type",
"Type",
""
};
constexpr openspace::properties::Property::PropertyInfo IdentifierInfo = {
"Identifier",
"Identifier",
@@ -57,36 +51,25 @@ namespace {
"Gui Name",
""
};
struct [[codegen::Dictionary(DashboardItem)]] Parameters {
std::string type;
// [[codegen::verbatim(IdentifierInfo.description)]]
std::string identifier;
// [[codegen::verbatim(GuiNameInfo.description)]]
std::optional<std::string> guiName;
};
#include "dashboarditem_codegen.cpp"
} // namespace
namespace openspace {
documentation::Documentation DashboardItem::Documentation() {
using namespace documentation;
return {
"DashboardItem",
"dashboarditem",
{
{
TypeInfo.identifier,
new StringVerifier,
Optional::No,
TypeInfo.description
},
{
IdentifierInfo.identifier,
new StringVerifier,
Optional::No,
IdentifierInfo.description
},
{
GuiNameInfo.identifier,
new StringVerifier,
Optional::Yes,
GuiNameInfo.description
}
}
};
documentation::Documentation doc = codegen::doc<Parameters>();
doc.id = "dashboarditem";
return doc;
}
std::unique_ptr<DashboardItem> DashboardItem::createFromDictionary(
@@ -105,18 +88,11 @@ DashboardItem::DashboardItem(const ghoul::Dictionary& dictionary)
: properties::PropertyOwner({ "", "" })
, _isEnabled(EnabledInfo, true)
{
documentation::testSpecificationAndThrow(
Documentation(),
dictionary,
"DashboardItem"
);
std::string identifier = dictionary.value<std::string>(IdentifierInfo.identifier);
setIdentifier(std::move(identifier));
if (dictionary.hasValue<std::string>(GuiNameInfo.identifier)) {
std::string guiName = dictionary.value<std::string>(GuiNameInfo.identifier);
setGuiName(std::move(guiName));
const Parameters p = codegen::bake<Parameters>(dictionary);
setIdentifier(p.identifier);
if (p.guiName.has_value()) {
setGuiName(*p.guiName);
}
addProperty(_isEnabled);
@@ -126,73 +102,4 @@ bool DashboardItem::isEnabled() const {
return _isEnabled;
}
namespace {
constexpr openspace::properties::Property::PropertyInfo FontNameInfo = {
"FontName",
"Font Name",
"This value is the name of the font that is used. It can either refer to an "
"internal name registered previously, or it can refer to a path that is used."
};
constexpr openspace::properties::Property::PropertyInfo FontSizeInfo = {
"FontSize",
"Font Size",
"This value determines the size of the font that is used to render the distance."
};
} // namespace
documentation::Documentation DashboardTextItem::Documentation() {
using namespace documentation;
return {
"DashboardTextItem",
"dashboardtextitem",
{
{
FontNameInfo.identifier,
new StringVerifier,
Optional::Yes,
FontNameInfo.description
},
{
FontSizeInfo.identifier,
new IntVerifier,
Optional::Yes,
FontSizeInfo.description
}
}
};
}
DashboardTextItem::DashboardTextItem(const ghoul::Dictionary& dictionary, float fontSize,
const std::string& fontName)
: DashboardItem(dictionary)
, _fontName(FontNameInfo, fontName)
, _fontSize(FontSizeInfo, fontSize, 6.f, 144.f, 1.f)
{
documentation::testSpecificationAndThrow(
Documentation(),
dictionary,
"DashboardTextItem"
);
if (dictionary.hasKey(FontNameInfo.identifier)) {
_fontName = dictionary.value<std::string>(FontNameInfo.identifier);
}
_fontName.onChange([this]() {
_font = global::fontManager->font(_fontName, _fontSize);
});
addProperty(_fontName);
if (dictionary.hasKey(FontSizeInfo.identifier)) {
_fontSize = static_cast<float>(dictionary.value<double>(FontSizeInfo.identifier));
}
_fontSize.onChange([this]() {
_font = global::fontManager->font(_fontName, _fontSize);
});
addProperty(_fontSize);
_font = global::fontManager->font(_fontName, _fontSize);
}
} // namespace openspace

View File

@@ -0,0 +1,88 @@
/*****************************************************************************************
* *
* OpenSpace *
* *
* Copyright (c) 2014-2021 *
* *
* Permission is hereby granted, free of charge, to any person obtaining a copy of this *
* software and associated documentation files (the "Software"), to deal in the Software *
* without restriction, including without limitation the rights to use, copy, modify, *
* merge, publish, distribute, sublicense, and/or sell copies of the Software, and to *
* permit persons to whom the Software is furnished to do so, subject to the following *
* conditions: *
* *
* The above copyright notice and this permission notice shall be included in all copies *
* or substantial portions of the Software. *
* *
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, *
* INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A *
* PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT *
* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF *
* CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE *
* OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. *
****************************************************************************************/
#include <openspace/rendering/dashboardtextitem.h>
#include <openspace/documentation/documentation.h>
#include <openspace/documentation/verifier.h>
#include <openspace/engine/globals.h>
#include <ghoul/font/fontmanager.h>
#include <optional>
namespace {
constexpr openspace::properties::Property::PropertyInfo FontNameInfo = {
"FontName",
"Font Name",
"This value is the name of the font that is used. It can either refer to an "
"internal name registered previously, or it can refer to a path that is used."
};
constexpr openspace::properties::Property::PropertyInfo FontSizeInfo = {
"FontSize",
"Font Size",
"This value determines the size of the font that is used to render the distance."
};
struct [[codegen::Dictionary(DashboardTextItem)]] Parameters {
// [[codegen::verbatim(FontNameInfo.description)]]
std::optional<std::string> fontName;
// [[codegen::verbatim(FontSizeInfo.description)]]
std::optional<float> fontSize;
};
#include "dashboardtextitem_codegen.cpp"
} // namespace
namespace openspace {
documentation::Documentation DashboardTextItem::Documentation() {
documentation::Documentation doc = codegen::doc<Parameters>();
doc.id = "dashboardtextitem";
return doc;
}
DashboardTextItem::DashboardTextItem(const ghoul::Dictionary& dictionary, float fontSize,
const std::string& fontName)
: DashboardItem(dictionary)
, _fontName(FontNameInfo, fontName)
, _fontSize(FontSizeInfo, fontSize, 6.f, 144.f, 1.f)
{
const Parameters p = codegen::bake<Parameters>(dictionary);
_fontName = p.fontName.value_or(_fontName);
_fontName.onChange([this]() {
_font = global::fontManager->font(_fontName, _fontSize);
});
addProperty(_fontName);
_fontSize = p.fontSize.value_or(_fontSize);
_fontSize.onChange([this]() {
_font = global::fontManager->font(_fontName, _fontSize);
});
addProperty(_fontSize);
_font = global::fontManager->font(_fontName, _fontSize);
}
} // namespace openspace

View File

@@ -134,6 +134,13 @@ namespace {
"interface."
};
constexpr openspace::properties::Property::PropertyInfo ScreenshotUseDateInfo = {
"ScreenshotUseDate",
"Screenshot Folder uses Date",
"If this value is set to 'true', screenshots will be saved to a folder that "
"contains the time at which this value was enabled"
};
constexpr openspace::properties::Property::PropertyInfo ShowFrameNumberInfo = {
"ShowFrameInformation",
"Show Frame Information",
@@ -255,6 +262,7 @@ RenderEngine::RenderEngine()
, _showVersionInfo(ShowVersionInfo, true)
, _showCameraInfo(ShowCameraInfo, true)
, _applyWarping(ApplyWarpingInfo, false)
, _screenshotUseDate(ScreenshotUseDateInfo, false)
, _showFrameInformation(ShowFrameNumberInfo, false)
, _disableMasterRendering(DisableMasterInfo, false)
, _globalBlackOutFactor(GlobalBlackoutFactorInfo, 1.f, 0.f, 1.f)
@@ -348,6 +356,44 @@ RenderEngine::RenderEngine()
addProperty(_globalBlackOutFactor);
addProperty(_applyWarping);
_screenshotUseDate.onChange([this]() {
// If there is no screenshot folder, don't bother with handling the change
if (!FileSys.hasRegisteredToken("${STARTUP_SCREENSHOT}")) {
return;
}
if (_screenshotUseDate) {
// Going from 'false' -> 'true'
// We might need to create the folder first
std::time_t now = std::time(nullptr);
std::tm* nowTime = std::localtime(&now);
char date[128];
strftime(date, sizeof(date), "%Y-%m-%d-%H-%M", nowTime);
std::string newFolder = absPath("${STARTUP_SCREENSHOT}/" + std::string(date));
if (!FileSys.directoryExists(newFolder)) {
FileSys.createDirectory(newFolder);
}
FileSys.registerPathToken(
"${SCREENSHOTS}",
newFolder,
ghoul::filesystem::FileSystem::Override::Yes
);
}
else {
// Going from 'true' -> 'false'
// We reset the screenshot folder back to what it was in the beginning
FileSys.registerPathToken(
"${SCREENSHOTS}",
absPath("${STARTUP_SCREENSHOT}"),
ghoul::filesystem::FileSystem::Override::Yes
);
}
global::windowDelegate->setScreenshotFolder(absPath("${SCREENSHOTS}"));
});
addProperty(_screenshotUseDate);
_horizFieldOfView.onChange([this]() {
if (global::windowDelegate->isMaster()) {
global::windowDelegate->setHorizFieldOfView(_horizFieldOfView);
@@ -447,6 +493,8 @@ void RenderEngine::initialize() {
);
}
}
_screenshotUseDate = global::configuration->shouldUseScreenshotDate;
}
void RenderEngine::initializeGL() {

View File

@@ -29,6 +29,7 @@ add_executable(
test_concurrentjobmanager.cpp
test_concurrentqueue.cpp
test_distanceconversion.cpp
test_configuration.cpp
test_documentation.cpp
test_iswamanager.cpp
test_latlonpatch.cpp

View File

@@ -44,7 +44,7 @@ int main(int argc, char** argv) {
using namespace openspace;
ghoul::logging::LogManager::initialize(
ghoul::logging::LogLevel::Debug,
ghoul::logging::LogLevel::Info,
ghoul::logging::LogManager::ImmediateFlush::Yes
);
ghoul::initialize();
@@ -59,10 +59,21 @@ int main(int argc, char** argv) {
);
std::string configFile = configuration::findConfiguration();
*global::configuration = configuration::loadConfigurationFromFile(configFile);
// Register the base path as the directory where 'filename' lives
std::string base = ghoul::filesystem::File(configFile).directoryName();
constexpr const char* BasePathToken = "${BASE}";
FileSys.registerPathToken(BasePathToken, base);
*global::configuration = configuration::loadConfigurationFromFile(configFile, "");
global::openSpaceEngine->registerPathTokens();
global::openSpaceEngine->initialize();
ghoul::logging::LogManager::deinitialize();
ghoul::logging::LogManager::initialize(
ghoul::logging::LogLevel::Info,
ghoul::logging::LogManager::ImmediateFlush::Yes
);
FileSys.registerPathToken("${TESTDIR}", "${BASE}/tests");
// All of the relevant tests initialize the SpiceManager

View File

@@ -0,0 +1,640 @@
/*****************************************************************************************
* *
* OpenSpace *
* *
* Copyright (c) 2014-2021 *
* *
* Permission is hereby granted, free of charge, to any person obtaining a copy of this *
* software and associated documentation files (the "Software"), to deal in the Software *
* without restriction, including without limitation the rights to use, copy, modify, *
* merge, publish, distribute, sublicense, and/or sell copies of the Software, and to *
* permit persons to whom the Software is furnished to do so, subject to the following *
* conditions: *
* *
* The above copyright notice and this permission notice shall be included in all copies *
* or substantial portions of the Software. *
* *
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, *
* INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A *
* PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT *
* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF *
* CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE *
* OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. *
****************************************************************************************/
#include "catch2/catch.hpp"
#include <openspace/engine/configuration.h>
#include <ghoul/fmt.h>
#include <filesystem>
#include <fstream>
using namespace openspace::configuration;
namespace {
std::string MinimalConfig = R"(
Paths = {}
)";
void writeConfig(const std::string& filename, const std::string& content) {
std::string config = MinimalConfig + content;
std::ofstream f(filename);
f << MinimalConfig << '\n' << content;
}
Configuration loadConfiguration(const std::string& tag, const std::string& content) {
std::string filename = fmt::format("test_configuration_{}.cfg", tag);
std::filesystem::path path = std::filesystem::temp_directory_path();
std::string configFile = (path / filename).string();
writeConfig(configFile, content);
Configuration conf = loadConfigurationFromFile(configFile, content);
std::filesystem::remove(configFile);
return conf;
}
} // namespace
TEST_CASE("Configuration: minimal", "[configuration]") {
loadConfiguration("minimal", "");
}
TEST_CASE("Configuration: windowConfiguration", "[configuration]") {
constexpr const char Extra[] = R"(SGCTConfig = "foobar")";
const Configuration c = loadConfiguration("windowConfiguration", Extra);
REQUIRE(c.windowConfiguration == "foobar");
}
TEST_CASE("Configuration: asset", "[configuration]") {
constexpr const char Extra[] = R"(Asset = "foobar")";
const Configuration c = loadConfiguration("asset", Extra);
REQUIRE(c.asset == "foobar");
}
TEST_CASE("Configuration: profile", "[configuration]") {
constexpr const char Extra[] = R"(Profile = "foobar")";
const Configuration c = loadConfiguration("profile", Extra);
REQUIRE(c.profile == "foobar");
}
TEST_CASE("Configuration: globalCustomizationScripts", "[configuration]") {
constexpr const char Extra[] = R"(GlobalCustomizationScripts = { "foo", "bar" })";
const Configuration c = loadConfiguration("globalCustomization", Extra);
REQUIRE(c.globalCustomizationScripts.size() == 2);
CHECK(c.globalCustomizationScripts == std::vector<std::string>{ "foo", "bar" });
}
TEST_CASE("Configuration: paths", "[configuration]") {
constexpr const char Extra[] = R"(Paths = { foo = "1", bar = "2" })";
const Configuration c = loadConfiguration("paths", Extra);
REQUIRE(c.pathTokens.size() == 2);
CHECK(
c.pathTokens ==
std::map<std::string, std::string>{ { "foo", "1" }, { "bar", "2" } }
);
}
TEST_CASE("Configuration: fonts", "[configuration]") {
constexpr const char Extra[] = R"(Fonts = { foo = "1", bar = "2" })";
const Configuration c = loadConfiguration("fonts", Extra);
REQUIRE(c.fonts.size() == 2);
CHECK(
c.fonts ==
std::map<std::string, std::string>{ { "foo", "1" }, { "bar", "2" } }
);
}
TEST_CASE("Configuration: logging", "[configuration]") {
Configuration defaultConf;
{
// Empty
constexpr const char Extra[] = R"(Logging = {})";
const Configuration c = loadConfiguration("logging1", Extra);
CHECK(c.logging.level == defaultConf.logging.level);
CHECK(c.logging.forceImmediateFlush == defaultConf.logging.forceImmediateFlush);
CHECK(
c.logging.capabilitiesVerbosity ==
defaultConf.logging.capabilitiesVerbosity
);
CHECK(c.logging.logs == defaultConf.logging.logs);
}
{
// level
constexpr const char Extra[] = R"(Logging = { LogLevel = "Fatal" })";
const Configuration c = loadConfiguration("logging2", Extra);
CHECK(c.logging.level == "Fatal");
CHECK(c.logging.forceImmediateFlush == defaultConf.logging.forceImmediateFlush);
CHECK(
c.logging.capabilitiesVerbosity ==
defaultConf.logging.capabilitiesVerbosity
);
CHECK(c.logging.logs == defaultConf.logging.logs);
}
{
// forceimmediate
constexpr const char Extra[] = R"(Logging = { ImmediateFlush = false })";
const Configuration c = loadConfiguration("logging3", Extra);
CHECK(c.logging.level == defaultConf.logging.level);
CHECK(c.logging.forceImmediateFlush == false);
CHECK(
c.logging.capabilitiesVerbosity ==
defaultConf.logging.capabilitiesVerbosity
);
CHECK(c.logging.logs == defaultConf.logging.logs);
}
{
// logs
constexpr const char Extra[] = R"(
Logging = {
Logs = {
{ Type = "html", File = "foobar", Append = false }
}
}
)";
const Configuration c = loadConfiguration("logging4", Extra);
CHECK(c.logging.level == defaultConf.logging.level);
CHECK(c.logging.forceImmediateFlush == defaultConf.logging.forceImmediateFlush);
CHECK(
c.logging.capabilitiesVerbosity ==
defaultConf.logging.capabilitiesVerbosity
);
REQUIRE(c.logging.logs.size() == 1);
const ghoul::Dictionary& d = c.logging.logs[0];
REQUIRE(d.hasValue<std::string>("Type"));
CHECK(d.value<std::string>("Type") == "html");
REQUIRE(d.hasValue<std::string>("File"));
CHECK(d.value<std::string>("File") == "foobar");
REQUIRE(d.hasValue<bool>("Append"));
CHECK(d.value<bool>("Append") == false);
}
{
// capabilities verbosity
constexpr const char Extra[] = R"(Logging = { CapabilitiesVerbosity = "Full" })";
const Configuration c = loadConfiguration("logging5", Extra);
CHECK(c.logging.level == defaultConf.logging.level);
CHECK(c.logging.forceImmediateFlush == defaultConf.logging.forceImmediateFlush);
CHECK(c.logging.capabilitiesVerbosity == "Full");
CHECK(c.logging.logs == defaultConf.logging.logs);
}
}
TEST_CASE("Configuration: scriptlog", "[configuration]") {
constexpr const char Extra[] = R"(ScriptLog = "foobar")";
const Configuration c = loadConfiguration("scriptlog", Extra);
CHECK(c.scriptLog == "foobar");
}
TEST_CASE("Configuration: documentationpath", "[configuration]") {
constexpr const char Extra[] = R"(Documentation = { Path = "foobar" })";
const Configuration c = loadConfiguration("documentationpath", Extra);
CHECK(c.documentation.path == "foobar");
}
TEST_CASE("Configuration: versioncheckurl", "[configuration]") {
constexpr const char Extra[] = R"(VersionCheckUrl = "foobar")";
const Configuration c = loadConfiguration("versioncheckurl", Extra);
CHECK(c.versionCheckUrl == "foobar");
}
TEST_CASE("Configuration: useMultithreadedInit", "[configuration]") {
constexpr const char Extra[] = R"(UseMultithreadedInitialization = true)";
const Configuration c = loadConfiguration("useMultithreadedInit", Extra);
CHECK(c.useMultithreadedInitialization == true);
}
TEST_CASE("Configuration: loadingscreen", "[configuration]") {
Configuration defaultConf;
{
// empty
constexpr const char Extra[] = R"(LoadingScreen = {})";
const Configuration c = loadConfiguration("loadingscreen1", Extra);
CHECK(
c.loadingScreen.isShowingMessages ==
defaultConf.loadingScreen.isShowingMessages
);
CHECK(
c.loadingScreen.isShowingProgressbar ==
defaultConf.loadingScreen.isShowingProgressbar
);
CHECK(
c.loadingScreen.isShowingNodeNames ==
defaultConf.loadingScreen.isShowingNodeNames
);
}
{
// isShowingMessages
constexpr const char Extra[] = R"(LoadingScreen = { ShowMessage = true })";
const Configuration c = loadConfiguration("loadingscreen2", Extra);
CHECK(c.loadingScreen.isShowingMessages == true);
CHECK(
c.loadingScreen.isShowingProgressbar ==
defaultConf.loadingScreen.isShowingProgressbar
);
CHECK(
c.loadingScreen.isShowingNodeNames ==
defaultConf.loadingScreen.isShowingNodeNames
);
}
{
// isShowingProgressbar
constexpr const char Extra[] = R"(LoadingScreen = { ShowProgressbar = true })";
const Configuration c = loadConfiguration("loadingscreen3", Extra);
CHECK(
c.loadingScreen.isShowingMessages ==
defaultConf.loadingScreen.isShowingMessages
);
CHECK(c.loadingScreen.isShowingProgressbar == true);
CHECK(
c.loadingScreen.isShowingNodeNames ==
defaultConf.loadingScreen.isShowingNodeNames
);
}
{
// isShowingNodeNames
constexpr const char Extra[] = R"(LoadingScreen = { ShowNodeNames = true })";
const Configuration c = loadConfiguration("loadingscreen4", Extra);
CHECK(
c.loadingScreen.isShowingMessages ==
defaultConf.loadingScreen.isShowingMessages
);
CHECK(
c.loadingScreen.isShowingProgressbar ==
defaultConf.loadingScreen.isShowingProgressbar
);
CHECK(c.loadingScreen.isShowingNodeNames == true);
}
}
TEST_CASE("Configuration: isCheckingOpenGLState", "[configuration]") {
constexpr const char Extra[] = R"(CheckOpenGLState = true)";
const Configuration c = loadConfiguration("isCheckingOpenGLState", Extra);
CHECK(c.isCheckingOpenGLState == true);
}
TEST_CASE("Configuration: isLoggingOpenGLCalls", "[configuration]") {
constexpr const char Extra[] = R"(LogEachOpenGLCall = true)";
const Configuration c = loadConfiguration("isLoggingOpenGLCalls", Extra);
CHECK(c.isLoggingOpenGLCalls == true);
}
TEST_CASE("Configuration: shutdownCountdown", "[configuration]") {
constexpr const char Extra[] = R"(ShutdownCountdown = 0.5)";
const Configuration c = loadConfiguration("shutdownCountdown", Extra);
CHECK(c.shutdownCountdown == 0.5f);
}
TEST_CASE("Configuration: shouldUseScreenshotDate", "[configuration]") {
constexpr const char Extra[] = R"(ScreenshotUseDate = true)";
const Configuration c = loadConfiguration("shouldUseScreenshotDate", Extra);
CHECK(c.shouldUseScreenshotDate == true);
}
TEST_CASE("Configuration: onScreenTextScaling", "[configuration]") {
constexpr const char Extra[] = R"(OnScreenTextScaling = "framebuffer")";
const Configuration c = loadConfiguration("onScreenTextScaling", Extra);
CHECK(c.onScreenTextScaling == "framebuffer");
}
TEST_CASE("Configuration: usePerSceneCache", "[configuration]") {
constexpr const char Extra[] = R"(PerSceneCache = true)";
const Configuration c = loadConfiguration("usePerSceneCache", Extra);
CHECK(c.usePerSceneCache == true);
}
TEST_CASE("Configuration: isRenderingOnMasterDisabled", "[configuration]") {
constexpr const char Extra[] = R"(DisableRenderingOnMaster = true)";
const Configuration c = loadConfiguration("isRenderingOnMasterDisabled", Extra);
CHECK(c.isRenderingOnMasterDisabled == true);
}
TEST_CASE("Configuration: globalRotation", "[configuration]") {
constexpr const char Extra[] = R"(GlobalRotation = { 1.0, 2.0, 3.0 })";
const Configuration c = loadConfiguration("globalRotation", Extra);
CHECK(c.globalRotation == glm::dvec3(1.0, 2.0, 3.0));
}
TEST_CASE("Configuration: screenSpaceRotation", "[configuration]") {
constexpr const char Extra[] = R"(ScreenSpaceRotation = { 1.0, 2.0, 3.0 })";
const Configuration c = loadConfiguration("screenSpaceRotation", Extra);
CHECK(c.screenSpaceRotation == glm::dvec3(1.0, 2.0, 3.0));
}
TEST_CASE("Configuration: masterRotation", "[configuration]") {
constexpr const char Extra[] = R"(MasterRotation = { 1.0, 2.0, 3.0 })";
const Configuration c = loadConfiguration("masterRotation", Extra);
CHECK(c.masterRotation == glm::dvec3(1.0, 2.0, 3.0));
}
TEST_CASE("Configuration: isConsoleDisabled", "[configuration]") {
constexpr const char Extra[] = R"(DisableInGameConsole = true)";
const Configuration c = loadConfiguration("isConsoleDisabled", Extra);
CHECK(c.isConsoleDisabled == true);
}
TEST_CASE("Configuration: bypassLauncher", "[configuration]") {
constexpr const char Extra[] = R"(BypassLauncher = true)";
const Configuration c = loadConfiguration("bypassLauncher", Extra);
CHECK(c.bypassLauncher == true);
}
TEST_CASE("Configuration: moduleConfigurations", "[configuration]") {
{
// empty
constexpr const char Extra[] = R"(ModuleConfigurations = {})";
const Configuration c = loadConfiguration("moduleConfigurations", Extra);
CHECK(c.moduleConfigurations.empty());
}
{
// values
constexpr const char Extra[] = R"(
ModuleConfigurations = {
Foo = {
Foo2 = 1.0,
Foo3 = "abc"
},
Bar = {
Bar2 = true,
Bar3 = { 1.0, 2.0, 3.0 }
}
}
)";
const Configuration c = loadConfiguration("moduleConfigurations", Extra);
REQUIRE(c.moduleConfigurations.size() == 2);
ghoul::Dictionary foo = c.moduleConfigurations.at("Foo");
REQUIRE(foo.size() == 2);
REQUIRE(foo.hasValue<double>("Foo2"));
CHECK(foo.value<double>("Foo2") == 1.0);
REQUIRE(foo.hasValue<std::string>("Foo3"));
CHECK(foo.value<std::string>("Foo3") == std::string("abc"));
ghoul::Dictionary bar = c.moduleConfigurations.at("Bar");
REQUIRE(bar.size() == 2);
REQUIRE(bar.hasValue<bool>("Bar2"));
CHECK(bar.value<bool>("Bar2") == true);
REQUIRE(bar.hasValue<glm::dvec3>("Bar3"));
CHECK(bar.value<glm::dvec3>("Bar3") == glm::dvec3(1.0, 2.0, 3.0));
}
}
TEST_CASE("Configuration: renderingMethod", "[configuration]") {
constexpr const char Extra[] = R"(RenderingMethod = "ABuffer")";
const Configuration c = loadConfiguration("renderingMethod", Extra);
CHECK(c.renderingMethod == "ABuffer");
}
TEST_CASE("Configuration: openGLDebugContext", "[configuration]") {
Configuration defaultConf;
{
// empty-ish / activate
constexpr const char Extra[] = R"(OpenGLDebugContext = { Activate = true })";
const Configuration c = loadConfiguration("openGLDebugContext1", Extra);
CHECK(c.openGLDebugContext.isActive == true);
CHECK(
c.openGLDebugContext.isSynchronous ==
defaultConf.openGLDebugContext.isSynchronous
);
REQUIRE(
c.openGLDebugContext.identifierFilters.size() ==
defaultConf.openGLDebugContext.identifierFilters.size()
);
for (size_t i = 0; i < c.openGLDebugContext.identifierFilters.size(); i += 1) {
CHECK(
c.openGLDebugContext.identifierFilters[i].identifier ==
defaultConf.openGLDebugContext.identifierFilters[i].identifier
);
CHECK(
c.openGLDebugContext.identifierFilters[i].source ==
defaultConf.openGLDebugContext.identifierFilters[i].source
);
CHECK(
c.openGLDebugContext.identifierFilters[i].type ==
defaultConf.openGLDebugContext.identifierFilters[i].type
);
}
CHECK(
c.openGLDebugContext.severityFilters ==
defaultConf.openGLDebugContext.severityFilters
);
}
{
// isSynchronous
constexpr const char Extra[] = R"(
OpenGLDebugContext = { Activate = true, Synchronous = true }
)";
const Configuration c = loadConfiguration("openGLDebugContext2", Extra);
CHECK(c.openGLDebugContext.isActive == true);
CHECK(c.openGLDebugContext.isSynchronous == true);
REQUIRE(
c.openGLDebugContext.identifierFilters.size() ==
defaultConf.openGLDebugContext.identifierFilters.size()
);
for (size_t i = 0; i < c.openGLDebugContext.identifierFilters.size(); i += 1) {
CHECK(
c.openGLDebugContext.identifierFilters[i].identifier ==
defaultConf.openGLDebugContext.identifierFilters[i].identifier
);
CHECK(
c.openGLDebugContext.identifierFilters[i].source ==
defaultConf.openGLDebugContext.identifierFilters[i].source
);
CHECK(
c.openGLDebugContext.identifierFilters[i].type ==
defaultConf.openGLDebugContext.identifierFilters[i].type
);
}
CHECK(
c.openGLDebugContext.severityFilters ==
defaultConf.openGLDebugContext.severityFilters
);
}
{
// identifierFilters
constexpr const char Extra[] = R"(
OpenGLDebugContext = {
Activate = true,
FilterIdentifier = {
{ Identifier = 1, Source = "API", Type = "Error" },
{ Identifier = 2, Source = "Window System", Type = "Deprecated" },
{ Identifier = 3, Source = "Shader Compiler", Type = "Undefined" },
{ Identifier = 4, Source = "Third Party", Type = "Portability" },
{ Identifier = 5, Source = "Application", Type = "Performance" },
{ Identifier = 6, Source = "Other", Type = "Marker" },
{ Identifier = 7, Source = "Don't care", Type = "Push group" },
{ Identifier = 8, Source = "API", Type = "Pop group" },
{ Identifier = 9, Source = "Window System", Type = "Other" },
{ Identifier = 10, Source = "Shader Compiler", Type = "Don't care" }
}
}
)";
const Configuration c = loadConfiguration("openGLDebugContext3", Extra);
CHECK(c.openGLDebugContext.isActive == true);
CHECK(
c.openGLDebugContext.isSynchronous ==
defaultConf.openGLDebugContext.isSynchronous
);
REQUIRE(c.openGLDebugContext.identifierFilters.size() == 10);
CHECK(c.openGLDebugContext.identifierFilters[0].identifier == 1);
CHECK(c.openGLDebugContext.identifierFilters[0].source == "API");
CHECK(c.openGLDebugContext.identifierFilters[0].type == "Error");
CHECK(c.openGLDebugContext.identifierFilters[1].identifier == 2);
CHECK(c.openGLDebugContext.identifierFilters[1].source == "Window System");
CHECK(c.openGLDebugContext.identifierFilters[1].type == "Deprecated");
CHECK(c.openGLDebugContext.identifierFilters[2].identifier == 3);
CHECK(c.openGLDebugContext.identifierFilters[2].source == "Shader Compiler");
CHECK(c.openGLDebugContext.identifierFilters[2].type == "Undefined");
CHECK(c.openGLDebugContext.identifierFilters[3].identifier == 4);
CHECK(c.openGLDebugContext.identifierFilters[3].source == "Third Party");
CHECK(c.openGLDebugContext.identifierFilters[3].type == "Portability");
CHECK(c.openGLDebugContext.identifierFilters[4].identifier == 5);
CHECK(c.openGLDebugContext.identifierFilters[4].source == "Application");
CHECK(c.openGLDebugContext.identifierFilters[4].type == "Performance");
CHECK(c.openGLDebugContext.identifierFilters[5].identifier == 6);
CHECK(c.openGLDebugContext.identifierFilters[5].source == "Other");
CHECK(c.openGLDebugContext.identifierFilters[5].type == "Marker");
CHECK(c.openGLDebugContext.identifierFilters[6].identifier == 7);
CHECK(c.openGLDebugContext.identifierFilters[6].source == "Don't care");
CHECK(c.openGLDebugContext.identifierFilters[6].type == "Push group");
CHECK(c.openGLDebugContext.identifierFilters[7].identifier == 8);
CHECK(c.openGLDebugContext.identifierFilters[7].source == "API");
CHECK(c.openGLDebugContext.identifierFilters[7].type == "Pop group");
CHECK(c.openGLDebugContext.identifierFilters[8].identifier == 9);
CHECK(c.openGLDebugContext.identifierFilters[8].source == "Window System");
CHECK(c.openGLDebugContext.identifierFilters[8].type == "Other");
CHECK(c.openGLDebugContext.identifierFilters[9].identifier == 10);
CHECK(c.openGLDebugContext.identifierFilters[9].source == "Shader Compiler");
CHECK(c.openGLDebugContext.identifierFilters[9].type == "Don't care");
CHECK(
c.openGLDebugContext.severityFilters ==
defaultConf.openGLDebugContext.severityFilters
);
}
{
// filterSeverity
constexpr const char Extra[] = R"(
OpenGLDebugContext = { Activate = true, FilterSeverity = { "High", "Medium" } }
)";
const Configuration c = loadConfiguration("openGLDebugContext4", Extra);
CHECK(c.openGLDebugContext.isActive == true);
CHECK(
c.openGLDebugContext.isSynchronous ==
defaultConf.openGLDebugContext.isSynchronous
);
REQUIRE(
c.openGLDebugContext.identifierFilters.size() ==
defaultConf.openGLDebugContext.identifierFilters.size()
);
for (size_t i = 0; i < c.openGLDebugContext.identifierFilters.size(); i += 1) {
CHECK(
c.openGLDebugContext.identifierFilters[i].identifier ==
defaultConf.openGLDebugContext.identifierFilters[i].identifier
);
CHECK(
c.openGLDebugContext.identifierFilters[i].source ==
defaultConf.openGLDebugContext.identifierFilters[i].source
);
CHECK(
c.openGLDebugContext.identifierFilters[i].type ==
defaultConf.openGLDebugContext.identifierFilters[i].type
);
}
REQUIRE(c.openGLDebugContext.severityFilters.size() == 2);
CHECK(
c.openGLDebugContext.severityFilters ==
std::vector<std::string>{ "High", "Medium" }
);
}
}
TEST_CASE("Configuration: httpProxy", "[configuration]") {
Configuration defaultConf;
{
// empty-ish / address + port
constexpr const char Extra[] = R"(
HttpProxy = {
Address = "foobar",
Port = 1234
}
)";
const Configuration c = loadConfiguration("httpProxy1", Extra);
CHECK(c.httpProxy.usingHttpProxy == defaultConf.httpProxy.usingHttpProxy);
CHECK(c.httpProxy.address == "foobar");
CHECK(c.httpProxy.port == 1234);
CHECK(c.httpProxy.authentication == defaultConf.httpProxy.authentication);
CHECK(c.httpProxy.user == defaultConf.httpProxy.user);
CHECK(c.httpProxy.password == defaultConf.httpProxy.password);
}
{
// activate
constexpr const char Extra[] = R"(
HttpProxy = {
Activate = true,
Address = "foobar",
Port = 1234
}
)";
const Configuration c = loadConfiguration("httpProxy2", Extra);
CHECK(c.httpProxy.usingHttpProxy == true);
CHECK(c.httpProxy.address == "foobar");
CHECK(c.httpProxy.port == 1234);
CHECK(c.httpProxy.authentication == defaultConf.httpProxy.authentication);
CHECK(c.httpProxy.user == defaultConf.httpProxy.user);
CHECK(c.httpProxy.password == defaultConf.httpProxy.password);
}
{
// authentication
constexpr const char Extra[] = R"(
HttpProxy = {
Address = "foobar",
Port = 1234,
Authentication = "ntlm"
}
)";
const Configuration c = loadConfiguration("httpProxy3", Extra);
CHECK(c.httpProxy.usingHttpProxy == defaultConf.httpProxy.usingHttpProxy);
CHECK(c.httpProxy.address == "foobar");
CHECK(c.httpProxy.port == 1234);
CHECK(c.httpProxy.authentication == "ntlm");
CHECK(c.httpProxy.user == defaultConf.httpProxy.user);
CHECK(c.httpProxy.password == defaultConf.httpProxy.password);
}
{
// user
constexpr const char Extra[] = R"(
HttpProxy = {
Address = "foobar",
Port = 1234,
User = "user-bar"
}
)";
const Configuration c = loadConfiguration("httpProxy4", Extra);
CHECK(c.httpProxy.usingHttpProxy == defaultConf.httpProxy.usingHttpProxy);
CHECK(c.httpProxy.address == "foobar");
CHECK(c.httpProxy.port == 1234);
CHECK(c.httpProxy.authentication == defaultConf.httpProxy.authentication);
CHECK(c.httpProxy.user == "user-bar");
CHECK(c.httpProxy.password == defaultConf.httpProxy.password);
}
{
// password
constexpr const char Extra[] = R"(
HttpProxy = {
Address = "foobar",
Port = 1234,
Password = "password-bar"
}
)";
const Configuration c = loadConfiguration("httpProxy5", Extra);
CHECK(c.httpProxy.usingHttpProxy == defaultConf.httpProxy.usingHttpProxy);
CHECK(c.httpProxy.address == "foobar");
CHECK(c.httpProxy.port == 1234);
CHECK(c.httpProxy.authentication == defaultConf.httpProxy.authentication);
CHECK(c.httpProxy.user == defaultConf.httpProxy.user);
CHECK(c.httpProxy.password == "password-bar");
}
}

View File

@@ -38,7 +38,7 @@ TEST_CASE("CreateSingleColorImage: Create image and check return value",
ghoul::lua::push(L, "colorFile");
ghoul::lua::push(L, std::vector{ 1.0, 0.0, 0.0 });
int res = openspace::luascriptfunctions::createSingeColorImage(L);
int res = openspace::luascriptfunctions::createSingleColorImage(L);
// One return value
CHECK(res == 1);
@@ -58,7 +58,7 @@ TEST_CASE("CreateSingleColorImage: Faulty 1st input type", "[createsinglecolorim
ghoul::lua::push(L, std::vector{ 1.0, 0.0, 0.0 });
CHECK_THROWS_WITH(
openspace::luascriptfunctions::createSingeColorImage(L),
openspace::luascriptfunctions::createSingleColorImage(L),
Catch::Matchers::Contains("parameter 1 was not the expected type")
);
}
@@ -69,7 +69,7 @@ TEST_CASE("CreateSingleColorImage: Faulty 2nd input type", "[createsinglecolorim
ghoul::lua::push(L, "not a vector");
CHECK_THROWS_WITH(
openspace::luascriptfunctions::createSingeColorImage(L),
openspace::luascriptfunctions::createSingleColorImage(L),
Catch::Matchers::Contains("parameter 2 was not the expected type")
);
}
@@ -80,7 +80,7 @@ TEST_CASE("CreateSingleColorImage: Invalid number of inputs", "[createsinglecolo
ghoul::lua::push(L, std::vector{ 1.0, 0.0, 0.0 });
CHECK_THROWS_WITH(
openspace::luascriptfunctions::createSingeColorImage(L),
openspace::luascriptfunctions::createSingleColorImage(L),
Catch::Matchers::Contains("Expected 2 arguments, got 1")
);
}
@@ -93,7 +93,7 @@ TEST_CASE("CreateSingleColorImage: Faulty color value (vec4)",
ghoul::lua::push(L, std::vector{ 1.0, 0.0, 0.0, 0.0 });
CHECK_THROWS_WITH(
openspace::luascriptfunctions::createSingeColorImage(L),
openspace::luascriptfunctions::createSingleColorImage(L),
Catch::Matchers::Contains(
"Invalid color. Expected three double values {r, g, b} in range 0 to 1"
)
@@ -108,7 +108,7 @@ TEST_CASE("CreateSingleColorImage: Faulty color value (invalid values)",
ghoul::lua::push(L, std::vector{ 255.0, 0.0, 0.0 }); // not a valid color
CHECK_THROWS_WITH(
openspace::luascriptfunctions::createSingeColorImage(L),
openspace::luascriptfunctions::createSingleColorImage(L),
Catch::Matchers::Contains(
"Invalid color. Expected three double values {r, g, b} in range 0 to 1"
)
@@ -122,7 +122,7 @@ TEST_CASE("CreateSingleColorImage: Check if file was created",
ghoul::lua::push(L, "colorFile2");
ghoul::lua::push(L, std::vector{ 0.0, 1.0, 0.0 });
int res = openspace::luascriptfunctions::createSingeColorImage(L);
int res = openspace::luascriptfunctions::createSingleColorImage(L);
CHECK(res == 1);
std::string path = ghoul::lua::value<std::string>(L, 1);
@@ -135,7 +135,7 @@ TEST_CASE("CreateSingleColorImage: Load created image", "[createsinglecolorimage
ghoul::lua::push(L, std::vector{ 1.0, 0.0, 0.0 });
// Loads the same file that was created in a previous test case
int res = openspace::luascriptfunctions::createSingeColorImage(L);
int res = openspace::luascriptfunctions::createSingleColorImage(L);
CHECK(res == 1);
CHECK(lua_gettop(L) == 1);