Merge remote-tracking branch 'origin/master' into issue/2645

This commit is contained in:
Ylva Selling
2024-03-04 10:55:49 +01:00
28 changed files with 775 additions and 394 deletions

View File

@@ -189,17 +189,6 @@ if (APPLE)
)
endif ()
if (MSVC)
option(OPENSPACE_NVTOOLS_ENABLED "Include support for Nvidia Tools Extensions" OFF)
set(OPENSPACE_NVTOOLS_PATH "C:/Program Files/NVIDIA Corporation/NvToolsExt")
if (OPENSPACE_NVTOOLS_ENABLED)
begin_dependency("Nvidia Tools Extension")
target_compile_definitions(openspace-core PUBLIC "OPENSPACE_HAS_NVTOOLS")
target_include_directories(openspace-core PUBLIC "${OPENSPACE_NVTOOLS_PATH}/include")
end_dependency()
endif ()
endif ()
begin_header("Configuring Modules")
add_subdirectory("${CMAKE_CURRENT_SOURCE_DIR}/modules")
end_header("End: Configuring Modules")

View File

@@ -110,22 +110,8 @@ namespace {
return std::nullopt;
}
std::ifstream inFile;
try {
inFile.open(filename, std::ifstream::in);
}
catch (const std::ifstream::failure& e) {
throw ghoul::RuntimeError(fmt::format(
"Exception opening {} profile for read: {}", filename, e.what()
));
}
std::string content;
std::string line;
while (std::getline(inFile, line)) {
content += line;
}
try {
return Profile(content);
return Profile(filename);
}
catch (const Profile::ParsingError& e) {
QMessageBox::critical(
@@ -401,8 +387,16 @@ QWidget* LauncherWindow::createCentralWidget() {
connect(
&dialog,
&SettingsDialog::saveSettings,
[](Settings s) {
[this](Settings s) {
saveSettings(s, findSettings());
if (s.profile.has_value()) {
populateProfilesList(*s.profile);
}
if (s.configuration.has_value()) {
populateWindowConfigsList(*s.configuration);
}
}
);

View File

@@ -25,15 +25,18 @@
#include "profile/cameradialog.h"
#include "profile/line.h"
#include <openspace/navigation/navigationstate.h>
#include <QDialogButtonBox>
#include <QDoubleValidator>
#include <QFileDialog>
#include <QFrame>
#include <QGridLayout>
#include <QKeyEvent>
#include <QLabel>
#include <QLineEdit>
#include <QTabWidget>
#include <QPlainTextEdit>
#include <QPushButton>
#include <QTabWidget>
namespace {
constexpr int CameraTypeNode = 0;
@@ -345,6 +348,45 @@ QWidget* CameraDialog::createNavStateWidget() {
mainLayout->addWidget(box);
}
QPushButton* loadFile = new QPushButton("Load state from file");
loadFile->setIcon(loadFile->style()->standardIcon(QStyle::SP_FileIcon));
connect(
loadFile, &QPushButton::clicked,
[this]() {
QString file = QFileDialog::getOpenFileName(
this,
"Select navigate state file"
);
std::ifstream f(file.toStdString());
std::string contents = std::string(
(std::istreambuf_iterator<char>(f)),
std::istreambuf_iterator<char>()
);
nlohmann::json json = nlohmann::json::parse(contents);
using namespace openspace::interaction;
NavigationState state = NavigationState(json);
_navState.anchor->setText(QString::fromStdString(state.anchor));
_navState.aim->setText(QString::fromStdString(state.aim));
_navState.refFrame->setText(QString::fromStdString(state.referenceFrame));
_navState.positionX->setText(QString::number(state.position.x));
_navState.positionY->setText(QString::number(state.position.y));
_navState.positionZ->setText(QString::number(state.position.z));
if (state.up.has_value()) {
_navState.upX->setText(QString::number(state.up->x));
_navState.upY->setText(QString::number(state.up->y));
_navState.upZ->setText(QString::number(state.up->z));
}
_navState.yaw->setText(QString::number(state.yaw));
_navState.pitch->setText(QString::number(state.pitch));
}
);
mainLayout->addWidget(loadFile);
return tab;
}

View File

@@ -71,10 +71,6 @@
#include <modules/spout/spoutwrapper.h>
#endif // OPENSPACE_HAS_SPOUT
#ifdef OPENSPACE_HAS_NVTOOLS
#include "nvToolsExt.h"
#endif // OPENSPACE_HAS_NVTOOLS
#ifdef OPENSPACE_BREAK_ON_FLOATING_POINT_EXCEPTION
#include <float.h>
#endif // OPENSPACE_BREAK_ON_FLOATING_POINT_EXCEPTION
@@ -96,7 +92,6 @@ constexpr std::string_view OpenVRTag = "OpenVR";
const Window* currentWindow = nullptr;
const BaseViewport* currentViewport = nullptr;
Frustum::Mode currentFrustumMode;
glm::mat4 currentModelViewProjectionMatrix;
glm::mat4 currentModelMatrix;
glm::ivec2 currentDrawResolution;
@@ -130,7 +125,6 @@ std::vector<SpoutWindow> SpoutWindows;
#endif // OPENSPACE_HAS_SPOUT
}
//
// MiniDump generation
@@ -417,9 +411,6 @@ void mainPreSyncFunc() {
void mainPostSyncPreDrawFunc() {
ZoneScoped;
#ifdef OPENSPACE_HAS_NVTOOLS
nvtxRangePush("postSyncPreDraw");
#endif // OPENSPACE_HAS_NVTOOLS
LTRACE("main::postSynchronizationPreDraw(begin)");
global::openSpaceEngine->postSynchronizationPreDraw();
@@ -432,10 +423,6 @@ void mainPostSyncPreDrawFunc() {
#endif // OPENVR_SUPPORT
LTRACE("main::postSynchronizationPreDraw(end)");
#ifdef OPENSPACE_HAS_NVTOOLS
nvtxRangePop();
#endif // OPENSPACE_HAS_NVTOOLS
}
@@ -443,9 +430,6 @@ void mainPostSyncPreDrawFunc() {
void mainRenderFunc(const sgct::RenderData& data) {
ZoneScoped;
#ifdef OPENSPACE_HAS_NVTOOLS
nvtxRangePush("render");
#endif // OPENSPACE_HAS_NVTOOLS
LTRACE("main::mainRenderFunc(begin)");
currentWindow = &data.window;
@@ -491,7 +475,6 @@ void mainRenderFunc(const sgct::RenderData& data) {
sizeof(mat4)
);
currentModelMatrix = modelMatrix;
currentModelViewProjectionMatrix = modelMatrix * viewMatrix * projectionMatrix;
global::openSpaceEngine->render(modelMatrix, viewMatrix, projectionMatrix);
#ifdef OPENSPACE_HAS_SPOUT
@@ -522,9 +505,6 @@ void mainRenderFunc(const sgct::RenderData& data) {
}
LTRACE("main::mainRenderFunc(end)");
#ifdef OPENSPACE_HAS_NVTOOLS
nvtxRangePop();
#endif // OPENSPACE_HAS_NVTOOLS
}
@@ -641,6 +621,8 @@ void mainCharCallback(unsigned int codepoint, int modifiers, sgct::Window* windo
void mainDropCallback(int amount, const char** paths) {
ZoneScoped;
ghoul_assert(amount > 0, "Expected at least one file path");
ghoul_assert(paths, "expected non-nullptr");
@@ -651,25 +633,25 @@ void mainDropCallback(int amount, const char** paths) {
std::vector<std::byte> mainEncodeFun() {
std::vector<std::byte> mainEncode() {
ZoneScoped;
LTRACE("main::mainEncodeFun(begin)");
LTRACE("main::mainEncode(begin)");
std::vector<std::byte> data = global::openSpaceEngine->encode();
LTRACE("main::mainEncodeFun(end)");
LTRACE("main::mainEncode(end)");
return data;
}
void mainDecodeFun(const std::vector<std::byte>& data) {
void mainDecode(const std::vector<std::byte>& data) {
ZoneScoped;
LTRACE("main::mainDecodeFun(begin)");
LTRACE("main::mainDecode(begin)");
global::openSpaceEngine->decode(data);
LTRACE("main::mainDecodeFun(end)");
LTRACE("main::mainDecode(end)");
}
@@ -690,10 +672,9 @@ void mainLogCallback(Log::Level level, std::string_view message) {
case Log::Level::Error:
LERRORC("SGCT", message);
break;
}
}
} // namespace
void setSgctDelegateFunctions() {
WindowDelegate& sgctDelegate = *global::windowDelegate;
@@ -1113,6 +1094,9 @@ std::string selectedSgctProfileFromLauncher(LauncherWindow& lw, bool hasCliSGCTC
return config;
}
} // namespace
int main(int argc, char* argv[]) {
#ifdef OPENSPACE_BREAK_ON_FLOATING_POINT_EXCEPTION
_clearfp();
@@ -1379,6 +1363,44 @@ int main(int argc, char* argv[]) {
}
glfwInit();
// We are just reloading the configuration file here in case the user has changed
// anything in the settings panel. In that case want to apply these settings
// immediately rather than waiting for the next startup.
// What follows is some copy-paste code that should be cleaned up at some point
LDEBUG("Reloading configuration from disk");
// Find configuration
std::filesystem::path configurationFilePath;
if (commandlineArguments.configuration.has_value()) {
configurationFilePath = absPath(*commandlineArguments.configuration);
}
else {
LDEBUG("Finding configuration");
configurationFilePath = findConfiguration();
}
// The previous incarnation of this was initializing GLFW to get the primary
// monitor's resolution, but that had some massive performance implications as
// there was some issue with the swap buffer handling inside of GLFW. My
// assumption is that GLFW doesn't like being initialized, destroyed, and then
// initialized again. Therefore we are using the platform specific functions now
glm::ivec2 size = glm::ivec2(1920, 1080);
#ifdef WIN32
DEVMODEW dm = { 0 };
dm.dmSize = sizeof(DEVMODEW);
BOOL success = EnumDisplaySettingsW(nullptr, ENUM_CURRENT_SETTINGS, &dm);
if (success) {
size.x = dm.dmPelsWidth;
size.y = dm.dmPelsHeight;
}
#endif // WIN32
*global::configuration = loadConfigurationFromFile(
configurationFilePath.string(),
findSettings(),
size
);
global::configuration->profile = win.selectedProfile();
windowConfiguration = selectedSgctProfileFromLauncher(
win,
@@ -1421,21 +1443,22 @@ int main(int argc, char* argv[]) {
config::Cluster cluster = loadCluster(absPath(windowConfiguration).string());
LDEBUG("Setting callbacks");
Engine::Callbacks callbacks;
callbacks.initOpenGL = mainInitFunc;
callbacks.preSync = mainPreSyncFunc;
callbacks.postSyncPreDraw = mainPostSyncPreDrawFunc;
callbacks.draw = mainRenderFunc;
callbacks.draw2D = mainDraw2DFunc;
callbacks.postDraw = mainPostDrawFunc;
callbacks.keyboard = mainKeyboardCallback;
callbacks.mouseButton = mainMouseButtonCallback;
callbacks.mousePos = mainMousePosCallback;
callbacks.mouseScroll = mainMouseScrollCallback;
callbacks.character = mainCharCallback;
callbacks.drop = mainDropCallback;
callbacks.encode = mainEncodeFun;
callbacks.decode = mainDecodeFun;
Engine::Callbacks callbacks = {
.initOpenGL = mainInitFunc,
.preSync = mainPreSyncFunc,
.postSyncPreDraw = mainPostSyncPreDrawFunc,
.draw = mainRenderFunc,
.draw2D = mainDraw2DFunc,
.postDraw = mainPostDrawFunc,
.encode = mainEncode,
.decode = mainDecode,
.keyboard = mainKeyboardCallback,
.character = mainCharCallback,
.mouseButton = mainMouseButtonCallback,
.mousePos = mainMousePosCallback,
.mouseScroll = mainMouseScrollCallback,
.drop = mainDropCallback
};
Log::instance().setNotifyLevel(Log::Level::Debug);
try {

View File

@@ -22,8 +22,10 @@
* OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. *
****************************************************************************************/
#include <openspace/engine/openspaceengine.h>
#include <openspace/engine/configuration.h>
#include <openspace/engine/moduleengine.h>
#include <openspace/engine/openspaceengine.h>
#include <openspace/engine/settings.h>
#include <openspace/engine/windowdelegate.h>
#include <openspace/engine/configuration.h>
#include <openspace/util/factorymanager.h>
@@ -44,15 +46,19 @@ int main(int, char**) {
ghoul::initialize();
std::string configFile = configuration::findConfiguration();
global::configuration = configuration::loadConfigurationFromFile(configFile);
global::openSpaceEngine.initialize();
std::filesystem::path configFile = findConfiguration();
std::filesystem::path settings = findSettings();
*global::configuration = loadConfigurationFromFile(
configFile,
settings,
glm::ivec2(0, 0)
);
global::openSpaceEngine->initialize();
TaskLoader taskLoader;
std::vector<std::unique_ptr<Task>> tasks = taskLoader.tasksFromFile(
absPath("${TASKS}/full_sync.task")
);
std::filesystem::path t = absPath("${TASKS}/full_sync.task");
std::vector<std::unique_ptr<Task>> tasks = taskLoader.tasksFromFile(t.string());
for (size_t i = 0; i < tasks.size(); i++) {
Task& task = *tasks[i].get();

View File

@@ -63,14 +63,45 @@ local ToggleTrails = {
IsLocal = false
}
local ToggleTrailsInstant = {
Identifier = "os.ToggleTrailsInstant",
Name = "Toggle all trails instantly",
Command = [[
local capList = openspace.property("*Trail.Renderable.Fade")
local list = openspace.property("*trail.Renderable.Fade")
if (#capList == 0) and (#list == 0) then
openspace.printWarning("No trails to toggle")
else
local prop
if #capList > 0 then
prop = capList[1]
else
prop = list[1]
end
local currentFade = openspace.propertyValue(prop)
local newFade = 0
if currentFade < 1 then
newFade = 1
end
openspace.setPropertyValue("Scene.*Trail.Renderable.Fade", newFade)
openspace.setPropertyValue("Scene.*trail.Renderable.Fade", newFade)
end
]],
Documentation = "Toggle fade instantly for all trails in the Scene",
GuiPath = "/Trails",
IsLocal = false
}
asset.onInitialize(function()
openspace.action.registerAction(FadeUpTrails)
openspace.action.registerAction(FadeDownTrails)
openspace.action.registerAction(ToggleTrails)
openspace.action.registerAction(ToggleTrailsInstant)
end)
asset.onDeinitialize(function()
openspace.action.removeAction(ToggleTrailsInstant)
openspace.action.removeAction(ToggleTrails)
openspace.action.removeAction(FadeDownTrails)
openspace.action.removeAction(FadeUpTrails)
@@ -79,3 +110,4 @@ end)
asset.export("FadeUpTrails", FadeUpTrails.Identifier)
asset.export("FadeDownTrails", FadeDownTrails.Identifier)
asset.export("ToggleTrails", ToggleTrails.Identifier)
asset.export("ToggleTrailsInstant", ToggleTrailsInstant.Identifier)

View File

@@ -1,6 +1,6 @@
asset.require("./base")
local trailAction = asset.require("actions/trails/toggle_trails_planets_moons").ToggleTrails
local allTrailsAction = asset.require("actions/trails/toggle_all_trails").ToggleTrails
local allTrailsInstantAction = asset.require("actions/trails/toggle_all_trails").ToggleTrailsInstant
@@ -22,13 +22,13 @@ asset.onInitialize(function()
openspace.action.registerAction(TogglePlanetLabels)
openspace.bindKey("L", TogglePlanetLabels.Identifier)
openspace.bindKey("H", trailAction)
openspace.bindKey("SHIFT+H", allTrailsAction)
openspace.bindKey("T", allTrailsAction)
openspace.bindKey("SHIFT+T", allTrailsInstantAction)
end)
asset.onDeinitialize(function()
openspace.clearKey("SHIFT+H")
openspace.clearKey("H")
openspace.clearKey("SHIFT+T")
openspace.clearKey("T")
openspace.action.removeAction(TogglePlanetLabels)
openspace.clearKey("L")

View File

@@ -194,7 +194,7 @@ asset.onInitialize(function()
openspace.bindKey("Ctrl+F", ToggleRollFriction.Identifier)
openspace.action.registerAction(FadeToBlack)
openspace.bindKey("W", FadeToBlack.Identifier)
openspace.bindKey("B", FadeToBlack.Identifier)
openspace.action.registerAction(ToggleMainGui)
openspace.bindKey("TAB", ToggleMainGui.Identifier)
@@ -246,7 +246,7 @@ asset.onDeinitialize(function()
openspace.clearKey("TAB")
openspace.action.removeAction(ToggleMainGui)
openspace.clearKey("W")
openspace.clearKey("B")
openspace.action.removeAction(FadeToBlack)
openspace.clearKey("Ctrl+F")

View File

@@ -0,0 +1,153 @@
local transforms = asset.require("scene/solarsystem/planets/earth/transforms")
local sun = asset.require("scene/solarsystem/sun/sun")
local coreKernels = asset.require("spice/core")
local models = asset.resource({
Name = "Tiangong Models",
Type = "HttpSynchronization",
Identifier = "tiangong_model",
Version = 1
})
local omm = asset.resource({
Name = "Satellite OMM Data (Tiangong)",
Type = "UrlSynchronization",
Identifier = "satellite_omm_data_tiangong",
Url = "https://www.celestrak.com/NORAD/elements/gp.php?CATNR=48274&FORMAT=kvn",
Filename = "Tiangong.txt",
SecondsUntilResync = 24 * 60 * 60
})
local TiangongPosition = {
Identifier = "TiangongPosition",
Parent = transforms.EarthInertial.Identifier,
BoundingSphere = 54.5, -- half the width
Transform = {
Translation = {
Type = "GPTranslation",
Observer = transforms.EarthInertial.Identifier,
File = omm .. "Tiangong.txt",
Format = "OMM"
},
Rotation = {
Type = "SpiceRotation",
SourceFrame = coreKernels.Frame.Galactic,
DestinationFrame = coreKernels.Frame.J2000
}
},
Tag = { "earth_satellite" },
GUI = {
Name = "Tiangong Position",
Path = "/Solar System/Planets/Earth/Satellites/Tiangong",
Hidden = true
}
}
local TiangongModel = {
Identifier = "Tiangong",
Parent = TiangongPosition.Identifier,
Transform = {
Rotation = {
Type = "FixedRotation",
Attached = "Tiangong",
XAxis = { 0.01, -0.09, 1.0 },
XAxisOrthogonal = true,
YAxis = transforms.EarthInertial.Identifier
}
},
Renderable = {
Type = "RenderableModel",
GeometryFile = asset.resource(models .. "tiangong.glb"),
LightSources = {
sun.LightSource
},
PerformShading = true
},
Tag = { "earth_satellite" },
GUI = {
Name = "Tiangong",
Path = "/Solar System/Planets/Earth/Satellites/Tiangong"
}
}
local TiangongTrail = {
Identifier = "Tiangong_trail",
Parent = transforms.EarthInertial.Identifier,
Renderable = {
Type = "RenderableTrailOrbit",
Translation = {
Type = "GPTranslation",
Observer = transforms.EarthInertial.Identifier,
File = omm .. "Tiangong.txt",
Format = "OMM"
},
RenderBinMode = "PostDeferredTransparent",
Color = { 0.9, 0.28, 0.33 },
Fade = 1.5,
Resolution = 320
},
Tag = { "earth_satellite" },
GUI = {
Name = "Tiangong Trail",
Path = "/Solar System/Planets/Earth/Satellites/Tiangong"
}
}
-- @TODO (emmbr, 2021-05-27) add to scene when label rendering issues have been fixed
local TiangongLabel = {
Identifier = "TiangongLabel",
Parent = TiangongPosition.Identifier,
Renderable = {
Type = "RenderableLabel",
Enabled = false,
Text = "Tiangong",
FontSize = 70.0,
Size = 3.4,
MinMaxSize = { 1, 100 },
OrientationOption = "Camera View Direction",
BlendMode = "Additive",
EnableFading = true,
FadeDistances = { 0.15, 15.0 },
FadeWidths = { 1.0, 25.0 }
},
Tag = { "solarsystem_labels" },
GUI = {
Name = "Tiangong Label",
Path = "/Solar System/Planets/Earth/Satellites"
}
}
asset.onInitialize(function()
local i = openspace.space.readKeplerFile(omm .. "Tiangong.txt", "OMM")
TiangongTrail.Renderable.Period = i[1].Period / (60 * 60 * 24)
openspace.addSceneGraphNode(TiangongPosition)
openspace.addSceneGraphNode(TiangongModel)
openspace.addSceneGraphNode(TiangongTrail)
openspace.setPropertyValueSingle("Scene.Tiangong.Rotation.yAxisInvertObject", true)
end)
asset.onDeinitialize(function()
openspace.removeSceneGraphNode(TiangongTrail)
openspace.removeSceneGraphNode(TiangongModel)
openspace.removeSceneGraphNode(TiangongPosition)
end)
asset.export(TiangongTrail)
asset.export(TiangongModel)
asset.export(TiangongPosition)
asset.meta = {
Name = "Tiangong",
Version = "2.0",
Description = [[Model and Trail for Tiangong. Model from Turbosquid, trail from
Celestrak.]],
Author = "OpenSpace Team",
URL = "https://celestrak.com/"
}

View File

@@ -3,6 +3,7 @@ asset.require("./communications/geostationary")
asset.require("./navigation/gps")
asset.require("./misc/spacestations")
asset.require("./misc/iss")
asset.require("./misc/tiangong")
asset.require("./misc/tle-new")

View File

@@ -46,5 +46,3 @@ return {
}
}
-- https://astrowebmaps.wr.usgs.gov/webmapatlas/Layers/maps.html

View File

@@ -158,7 +158,6 @@ private:
std::unique_ptr<Scene> _scene;
std::unique_ptr<AssetManager> _assetManager;
bool _shouldAbortLoading = false;
std::unique_ptr<LoadingScreen> _loadingScreen;
std::unique_ptr<VersionChecker> _versionChecker;

View File

@@ -26,6 +26,7 @@
#define __OPENSPACE_CORE___NAVIGATIONSTATE___H__
#include <openspace/documentation/documentation.h>
#include <openspace/json.h>
#include <optional>
namespace openspace {
@@ -37,12 +38,14 @@ namespace openspace::interaction {
struct NavigationState {
NavigationState() = default;
explicit NavigationState(const ghoul::Dictionary& dictionary);
explicit NavigationState(const nlohmann::json& json);
NavigationState(std::string anchor, std::string aim, std::string referenceFrame,
glm::dvec3 position, std::optional<glm::dvec3> up = std::nullopt,
double yaw = 0.0, double pitch = 0.0);
CameraPose cameraPose() const;
ghoul::Dictionary dictionary() const;
nlohmann::json toJson() const;
static documentation::Documentation Documentation();
std::string anchor;

View File

@@ -46,6 +46,9 @@ namespace ghoul::opengl {
namespace openspace {
class AssetManager;
class Scene;
class LoadingScreen {
public:
BooleanType(ShowMessage);
@@ -57,29 +60,11 @@ public:
ShowLogMessages showLogMessages);
~LoadingScreen();
void abort();
void exec(AssetManager& manager, Scene& scene);
void render();
void postMessage(std::string message);
void setCatastrophicError(CatastrophicError catastrophicError);
void finalize();
enum class Phase {
PreStart,
Construction,
Synchronization,
Initialization
};
void setPhase(Phase phase);
enum class ItemStatus {
Started,
Initializing,
Finished,
Failed
};
struct ProgressInfo {
float progress = 0.f;
@@ -87,10 +72,29 @@ public:
int64_t totalSize = -1;
};
enum class ItemStatus {
Started,
Initializing,
Finished,
Failed
};
void updateItem(const std::string& itemIdentifier, const std::string& itemName,
ItemStatus newStatus, ProgressInfo progressInfo);
private:
enum class Phase {
PreStart,
Construction,
Synchronization,
Initialization
};
void postMessage(std::string message);
void setCatastrophicError(CatastrophicError catastrophicError);
void finalize();
void setPhase(Phase phase);
void renderLogMessages() const;
@@ -127,6 +131,8 @@ private:
std::vector<Item> _items;
std::mutex _itemsMutex;
bool _shouldAbortLoading = false;
std::random_device _randomDevice;
std::default_random_engine _randomEngine;

View File

@@ -137,7 +137,7 @@ public:
using CameraType = std::variant<CameraGoToNode, CameraNavState, CameraGoToGeo>;
Profile() = default;
explicit Profile(const std::string& content);
explicit Profile(const std::filesystem::path& path);
std::string serialize() const;
/**

View File

@@ -55,14 +55,14 @@
namespace {
constexpr std::string_view _loggerCat = "RenderablePointCloud";
constexpr std::array<const char*, 29> UniformNames = {
constexpr std::array<const char*, 32> UniformNames = {
"cameraViewMatrix", "projectionMatrix", "modelMatrix", "cameraPosition",
"cameraLookUp", "renderOption", "maxAngularSize", "color", "opacity",
"scaleExponent", "scaleFactor", "up", "right", "fadeInValue", "hasSpriteTexture",
"spriteTexture", "useColorMap", "colorMapTexture", "cmapRangeMin", "cmapRangeMax",
"nanColor", "useNanColor", "hideOutsideRange", "enableMaxSizeControl",
"aboveRangeColor", "useAboveRangeColor", "belowRangeColor", "useBelowRangeColor",
"hasDvarScaling"
"hasDvarScaling", "enableOutline", "outlineColor", "outlineWeight"
};
enum RenderOption {
@@ -229,6 +229,30 @@ namespace {
openspace::properties::Property::Visibility::AdvancedUser
};
constexpr openspace::properties::Property::PropertyInfo EnableOutlineInfo = {
"EnableOutline",
"Enable Point Outline",
"This setting determines if each point should have an outline or not. An outline "
"is only applied when rendering as colored points (not when using textures).",
openspace::properties::Property::Visibility::User
};
constexpr openspace::properties::Property::PropertyInfo OutlineColorInfo = {
"OutlineColor",
"Outline Color",
"This value defines the color of the outline. Darker colors will be "
"less visible if Additive Blending is enabled.",
openspace::properties::Property::Visibility::User
};
constexpr openspace::properties::Property::PropertyInfo OutlineWeightInfo = {
"OutlineWeight",
"Outline Weight",
"This setting determines the thickness of the outline. A value of 0 will "
"not show any outline, while a value of 1 will cover the whole point.",
openspace::properties::Property::Visibility::AdvancedUser
};
// A RenderablePointCloud can be used to render point-based datasets in 3D space,
// optionally including color mapping, a sprite texture and labels. There are several
// properties that affect the visuals of the points, such as settings for scaling,
@@ -336,6 +360,15 @@ namespace {
// Settings related to the choice of color map, parameters, etc.
std::optional<ghoul::Dictionary> colorMapping
[[codegen::reference("colormappingcomponent")]];
// [[codegen::verbatim(EnableOutlineInfo.description)]]
std::optional<bool> enableOutline;
// [[codegen::verbatim(OutlineColorInfo.description)]]
std::optional<glm::vec3> outlineColor;
// [[codegen::verbatim(OutlineColorInfo.description)]]
std::optional<float> outlineWeight;
};
// Settings related to the coloring of the points, such as a fixed color,
// color map, etc.
@@ -419,10 +452,14 @@ RenderablePointCloud::SizeSettings::SizeMapping::SizeMapping()
RenderablePointCloud::ColorSettings::ColorSettings(const ghoul::Dictionary& dictionary)
: properties::PropertyOwner({ "Coloring", "Coloring", "" })
, pointColor(PointColorInfo, glm::vec3(1.f), glm::vec3(0.f), glm::vec3(1.f))
, enableOutline(EnableOutlineInfo, false)
, outlineColor(OutlineColorInfo, glm::vec3(0.23f), glm::vec3(0.f), glm::vec3(1.f))
, outlineWeight(OutlineWeightInfo, 0.2f, 0.f, 1.f)
{
const Parameters p = codegen::bake<Parameters>(dictionary);
if (p.coloring.has_value()) {
const bool hasColoring = p.coloring.has_value();
if (hasColoring) {
const Parameters::ColorSettings settings = *p.coloring;
pointColor = settings.fixedColor.value_or(pointColor);
@@ -432,9 +469,20 @@ RenderablePointCloud::ColorSettings::ColorSettings(const ghoul::Dictionary& dict
);
addPropertySubOwner(colorMapping.get());
}
enableOutline = p.coloring->enableOutline.value_or(enableOutline);
outlineColor = p.coloring->outlineColor.value_or(outlineColor);
outlineWeight = p.coloring->outlineWeight.value_or(outlineWeight);
}
pointColor.setViewOption(properties::Property::ViewOptions::Color);
addProperty(pointColor);
addProperty(enableOutline);
outlineColor.setViewOption(properties::Property::ViewOptions::Color);
addProperty(outlineColor);
addProperty(outlineWeight);
}
RenderablePointCloud::Fading::Fading(const ghoul::Dictionary& dictionary)
@@ -735,6 +783,9 @@ void RenderablePointCloud::bindDataForPointRendering() {
}
_program->setUniform(_uniformCache.color, _colorSettings.pointColor);
_program->setUniform(_uniformCache.enableOutline, _colorSettings.enableOutline);
_program->setUniform(_uniformCache.outlineColor, _colorSettings.outlineColor);
_program->setUniform(_uniformCache.outlineWeight, _colorSettings.outlineWeight);
bool useColorMap = _hasColorMapFile && _colorSettings.colorMapping->enabled &&
_colorSettings.colorMapping->texture();

View File

@@ -132,6 +132,9 @@ protected:
explicit ColorSettings(const ghoul::Dictionary& dictionary);
properties::Vec3Property pointColor;
std::unique_ptr<ColorMappingComponent> colorMapping;
properties::BoolProperty enableOutline;
properties::Vec3Property outlineColor;
properties::FloatProperty outlineWeight;
};
ColorSettings _colorSettings;
@@ -162,7 +165,7 @@ protected:
right, fadeInValue, hasSpriteTexture, spriteTexture, useColormap, colorMapTexture,
cmapRangeMin, cmapRangeMax, nanColor, useNanColor, hideOutsideRange,
enableMaxSizeControl, aboveRangeColor, useAboveRangeColor, belowRangeColor,
useBelowRangeColor, hasDvarScaling
useBelowRangeColor, hasDvarScaling, enableOutline, outlineColor, outlineWeight
) _uniformCache;
std::string _dataFile;

View File

@@ -49,6 +49,9 @@ uniform sampler1D colorMapTexture;
uniform float cmapRangeMin;
uniform float cmapRangeMax;
uniform bool hideOutsideRange;
uniform bool enableOutline;
uniform vec3 outlineColor;
uniform float outlineWeight;
uniform float fadeInValue;
@@ -80,24 +83,26 @@ Fragment getFragment() {
discard;
}
if (!hasSpriteTexture) {
// Moving the origin to the center
vec2 st = (texCoord - vec2(0.5)) * 2.0;
if (length(st) > 1.0) {
// Moving the origin to the center and calculating the length
float lengthFromCenter = length((texCoord - vec2(0.5)) * 2.0);
if (!hasSpriteTexture) {
if (lengthFromCenter > 1.0) {
discard;
}
}
vec4 fullColor = vec4(1.0);
if (hasSpriteTexture) {
fullColor = texture(spriteTexture, texCoord);
}
if (useColorMap) {
fullColor *= sampleColorMap(gs_colorParameter);
fullColor = sampleColorMap(gs_colorParameter);
}
else {
fullColor.rgb *= color;
fullColor.rgb = color;
}
if (hasSpriteTexture) {
fullColor *= texture(spriteTexture, texCoord);
} else if (enableOutline && (lengthFromCenter > (1.0 - outlineWeight))) {
fullColor.rgb = outlineColor;
}
fullColor.a *= opacity * fadeInValue;

View File

@@ -83,6 +83,7 @@
#pragma warning (disable : 4251)
#endif // _MSC_VER
#include <cpl_conv.h>
#include <cpl_string.h>
#ifdef _MSC_VER
@@ -550,10 +551,12 @@ void GlobeBrowsingModule::loadWMSCapabilities(std::string name, std::string glob
{
auto downloadFunction = [](const std::string& downloadUrl) {
LDEBUG("Opening WMS capabilities: " + downloadUrl);
CPLSetConfigOption("GDAL_HTTP_TIMEOUT", "15"); // 3 seconds
GDALDatasetH dataset = GDALOpen(
downloadUrl.c_str(),
GA_ReadOnly
);
CPLSetConfigOption("GDAL_HTTP_TIMEOUT", "3"); // 3 seconds
if (!dataset) {
LWARNING("Could not open dataset: " + downloadUrl);

View File

@@ -112,8 +112,8 @@ namespace {
case Mode::UserControl: return "UserControl";
case Mode::CameraPath: return "CameraPath";
case Mode::SessionRecordingPlayback: return "SessionRecording";
default: throw ghoul::MissingCaseException();
}
throw ghoul::MissingCaseException();
}
constexpr openspace::properties::Property::PropertyInfo PrintEventsInfo = {
@@ -391,21 +391,7 @@ void OpenSpaceEngine::initialize() {
}
// Load the profile
std::ifstream inFile;
try {
inFile.open(profile, std::ifstream::in);
}
catch (const std::ifstream::failure& e) {
throw ghoul::RuntimeError(fmt::format(
"Exception opening profile file for read: {} ({})", profile, e.what()
));
}
std::string content(
(std::istreambuf_iterator<char>(inFile)),
std::istreambuf_iterator<char>()
);
*global::profile = Profile(content);
*global::profile = Profile(profile);
// Set up asset loader
_assetManager = std::make_unique<AssetManager>(
@@ -768,119 +754,10 @@ void OpenSpaceEngine::loadAssets() {
_assetManager->add(a);
}
_loadingScreen->setPhase(LoadingScreen::Phase::Construction);
_loadingScreen->postMessage("Loading assets");
std::unordered_set<const ResourceSynchronization*> finishedSynchronizations;
while (true) {
_loadingScreen->render();
_assetManager->update();
std::vector<const Asset*> allAssets = _assetManager->allAssets();
std::vector<const ResourceSynchronization*> allSyncs =
_assetManager->allSynchronizations();
// Filter already synchronized assets so we don't check them anymore
auto syncIt = std::remove_if(
allSyncs.begin(),
allSyncs.end(),
[&finishedSynchronizations](const ResourceSynchronization* sync) {
return finishedSynchronizations.contains(sync);
}
);
allSyncs.erase(syncIt, allSyncs.end());
auto it = allSyncs.begin();
while (it != allSyncs.end()) {
ZoneScopedN("Update resource synchronization");
if ((*it)->isSyncing()) {
LoadingScreen::ProgressInfo progressInfo;
progressInfo.progress = [](const ResourceSynchronization* sync) {
if (!sync->nTotalBytesIsKnown()) {
return 0.f;
}
if (sync->nTotalBytes() == 0) {
return 1.f;
}
return
static_cast<float>(sync->nSynchronizedBytes()) /
static_cast<float>(sync->nTotalBytes());
}(*it);
progressInfo.currentSize = (*it)->nSynchronizedBytes();
if ((*it)->nTotalBytesIsKnown()) {
progressInfo.totalSize = (*it)->nTotalBytes();
}
_loadingScreen->updateItem(
(*it)->identifier(),
(*it)->name(),
LoadingScreen::ItemStatus::Started,
progressInfo
);
++it;
}
else if ((*it)->isRejected()) {
_loadingScreen->updateItem(
(*it)->identifier(),
(*it)->name(),
LoadingScreen::ItemStatus::Failed,
LoadingScreen::ProgressInfo()
);
++it;
}
else {
LoadingScreen::ProgressInfo progressInfo;
progressInfo.progress = 1.f;
_loadingScreen->updateItem(
(*it)->identifier(),
(*it)->name(),
LoadingScreen::ItemStatus::Finished,
progressInfo
);
finishedSynchronizations.insert(*it);
it = allSyncs.erase(it);
}
}
if (_shouldAbortLoading) {
global::windowDelegate->terminate();
break;
}
bool finishedLoading = std::all_of(
allAssets.begin(),
allAssets.end(),
[](const Asset* asset) { return asset->isInitialized() || asset->isFailed(); }
);
if (finishedLoading) {
break;
}
} // while(true)
if (_shouldAbortLoading) {
_loadingScreen = nullptr;
return;
}
_loadingScreen->setPhase(LoadingScreen::Phase::Initialization);
_loadingScreen->postMessage("Initializing scene");
while (_scene->isInitializing()) {
_loadingScreen->render();
}
_loadingScreen->postMessage("Initializing OpenGL");
_loadingScreen->finalize();
_loadingScreen->exec(*_assetManager, *_scene);
_loadingScreen = nullptr;
global::renderEngine->updateScene();
global::syncEngine->addSyncables(global::timeManager->syncables());
@@ -1308,7 +1185,7 @@ void OpenSpaceEngine::keyboardCallback(Key key, KeyModifier mod, KeyAction actio
// If the loading screen object exists, we are currently loading and want key
// presses to behave differently
if (key == Key::Escape) {
_shouldAbortLoading = true;
_loadingScreen->abort();
}
return;

View File

@@ -557,6 +557,10 @@ void NavigationHandler::saveNavigationState(const std::filesystem::path& filepat
}
std::filesystem::path absolutePath = absPath(filepath);
if (!absolutePath.has_extension()) {
// Adding the .navstate extension to the filepath if it came without one
absolutePath.replace_extension(".navstate");
}
LINFO(fmt::format("Saving camera position: {}", absolutePath));
std::ofstream ofs(absolutePath);
@@ -567,7 +571,7 @@ void NavigationHandler::saveNavigationState(const std::filesystem::path& filepat
));
}
ofs << "return " << ghoul::formatLua(state.dictionary());
ofs << state.toJson().dump(2);
}
void NavigationHandler::loadNavigationState(const std::string& filepath) {
@@ -578,22 +582,15 @@ void NavigationHandler::loadNavigationState(const std::string& filepath) {
throw ghoul::FileNotFoundError(absolutePath.string(), "NavigationState");
}
ghoul::Dictionary navigationStateDictionary;
try {
ghoul::lua::loadDictionaryFromFile(
absolutePath.string(),
navigationStateDictionary
);
openspace::documentation::testSpecificationAndThrow(
NavigationState::Documentation(),
navigationStateDictionary,
"NavigationState"
);
setNavigationStateNextFrame(NavigationState(navigationStateDictionary));
}
catch (ghoul::RuntimeError& e) {
LERROR(fmt::format("Unable to set camera position: {}", e.message));
}
std::ifstream f(filepath);
std::string contents = std::string(
std::istreambuf_iterator<char>(f),
std::istreambuf_iterator<char>()
);
nlohmann::json json = nlohmann::json::parse(contents);
NavigationState state = NavigationState(json);
setNavigationStateNextFrame(state);
}
std::vector<std::string> NavigationHandler::listAllJoysticks() const {

View File

@@ -38,7 +38,7 @@ namespace {
}
/**
* Return the current navigation state as a lua table. The optional argument is the scene
* Return the current navigation state as a Lua table. The optional argument is the scene
* graph node to use as reference frame. By default, the reference frame will picked based
* on whether the orbital navigator is currently following the anchor node rotation. If it
* is, the anchor will be chosen as reference frame. If not, the reference frame will be

View File

@@ -89,11 +89,42 @@ NavigationState::NavigationState(const ghoul::Dictionary& dictionary) {
referenceFrame = p.referenceFrame.value_or(anchor);
aim = p.aim.value_or(aim);
if (p.up.has_value()) {
up = *p.up;
up = p.up;
yaw = p.yaw.value_or(yaw);
pitch = p.pitch.value_or(pitch);
}
yaw = p.yaw.value_or(yaw);
pitch = p.pitch.value_or(pitch);
NavigationState::NavigationState(const nlohmann::json& json) {
position.x = json["position"]["x"].get<double>();
position.y = json["position"]["y"].get<double>();
position.z = json["position"]["z"].get<double>();
anchor = json["anchor"];
if (auto it = json.find("referenceframe"); it != json.end()) {
referenceFrame = it->get<std::string>();
}
else {
referenceFrame = anchor;
}
if (auto it = json.find("aim"); it != json.end()) {
aim = it->get<std::string>();
}
if (auto it = json.find("up"); it != json.end()) {
up = glm::dvec3();
up->x = it->at("x").get<double>();
up->y = it->at("y").get<double>();
up->z = it->at("z").get<double>();
}
if (auto it = json.find("yaw"); it != json.end()) {
yaw = it->get<double>();
}
if (auto it = json.find("pitch"); it != json.end()) {
pitch = it->get<double>();
}
}
@@ -174,16 +205,56 @@ ghoul::Dictionary NavigationState::dictionary() const {
}
if (up.has_value()) {
cameraDict.setValue("Up", *up);
}
if (std::abs(yaw) > Epsilon) {
cameraDict.setValue("Yaw", yaw);
}
if (std::abs(pitch) > Epsilon) {
cameraDict.setValue("Pitch", pitch);
}
return cameraDict;
}
if (std::abs(yaw) > Epsilon) {
cameraDict.setValue("Yaw", yaw);
}
if (std::abs(pitch) > Epsilon) {
cameraDict.setValue("Pitch", pitch);
}
nlohmann::json NavigationState::toJson() const {
nlohmann::json result = nlohmann::json::object();
// Obligatory version number
result["version"] = 1;
{
nlohmann::json posObj = nlohmann::json::object();
posObj["x"] = position.x;
posObj["y"] = position.y;
posObj["z"] = position.z;
result["position"] = posObj;
}
return cameraDict;
result["anchor"] = anchor;
if (anchor != referenceFrame) {
result["referenceframe"] = referenceFrame;
}
if (!aim.empty()) {
result["aim"] = aim;
}
if (up.has_value()) {
nlohmann::json upObj = nlohmann::json::object();
upObj["x"] = up->x;
upObj["y"] = up->y;
upObj["z"] = up->z;
result["up"] = upObj;
}
if (std::abs(yaw) > Epsilon) {
result["yaw"] = yaw;
}
if (std::abs(pitch) > Epsilon) {
result["pitch"] = pitch;
}
return result;
}
documentation::Documentation NavigationState::Documentation() {

View File

@@ -27,6 +27,10 @@
#include <openspace/engine/globals.h>
#include <openspace/engine/windowdelegate.h>
#include <openspace/rendering/helper.h>
#include <openspace/scene/asset.h>
#include <openspace/scene/assetmanager.h>
#include <openspace/scene/scene.h>
#include <openspace/util/resourcesynchronization.h>
#include <ghoul/fmt.h>
#include <ghoul/filesystem/filesystem.h>
#include <ghoul/font/font.h>
@@ -43,6 +47,7 @@
#include <random>
#include <sstream>
#include <thread>
#include <unordered_set>
namespace {
@@ -167,6 +172,117 @@ LoadingScreen::~LoadingScreen() {
_log = nullptr;
}
void LoadingScreen::abort() {
_shouldAbortLoading = true;
}
void LoadingScreen::exec(AssetManager& manager, Scene& scene) {
setPhase(LoadingScreen::Phase::Construction);
postMessage("Loading assets");
std::unordered_set<const ResourceSynchronization*> finishedSynchronizations;
while (true) {
render();
manager.update();
std::vector<const Asset*> allAssets = manager.allAssets();
std::vector<const ResourceSynchronization*> allSyncs =
manager.allSynchronizations();
// Filter already synchronized assets so we don't check them anymore
auto syncIt = std::remove_if(
allSyncs.begin(),
allSyncs.end(),
[&finishedSynchronizations](const ResourceSynchronization* sync) {
return finishedSynchronizations.contains(sync);
}
);
allSyncs.erase(syncIt, allSyncs.end());
auto it = allSyncs.begin();
while (it != allSyncs.end()) {
ZoneScopedN("Update resource synchronization");
if ((*it)->isSyncing()) {
LoadingScreen::ProgressInfo progressInfo;
progressInfo.progress = [](const ResourceSynchronization* sync) {
if (!sync->nTotalBytesIsKnown()) {
return 0.f;
}
if (sync->nTotalBytes() == 0) {
return 1.f;
}
return
static_cast<float>(sync->nSynchronizedBytes()) /
static_cast<float>(sync->nTotalBytes());
}(*it);
progressInfo.currentSize = (*it)->nSynchronizedBytes();
if ((*it)->nTotalBytesIsKnown()) {
progressInfo.totalSize = (*it)->nTotalBytes();
}
updateItem(
(*it)->identifier(),
(*it)->name(),
LoadingScreen::ItemStatus::Started,
progressInfo
);
++it;
}
else if ((*it)->isRejected()) {
updateItem(
(*it)->identifier(),
(*it)->name(),
LoadingScreen::ItemStatus::Failed,
LoadingScreen::ProgressInfo()
);
++it;
}
else {
LoadingScreen::ProgressInfo progressInfo;
progressInfo.progress = 1.f;
updateItem(
(*it)->identifier(),
(*it)->name(),
LoadingScreen::ItemStatus::Finished,
progressInfo
);
finishedSynchronizations.insert(*it);
it = allSyncs.erase(it);
}
}
if (_shouldAbortLoading) {
global::windowDelegate->terminate();
return;
}
bool finishedLoading = std::all_of(
allAssets.begin(),
allAssets.end(),
[](const Asset* asset) { return asset->isInitialized() || asset->isFailed(); }
);
if (finishedLoading) {
break;
}
} // while(true)
setPhase(LoadingScreen::Phase::Initialization);
postMessage("Initializing scene");
while (scene.isInitializing()) {
render();
}
postMessage("Initializing OpenGL");
finalize();
}
void LoadingScreen::render() {
ZoneScoped;
FrameMarkStart("Loading");

View File

@@ -741,7 +741,24 @@ std::string Profile::serialize() const {
return r.dump(2);
}
Profile::Profile(const std::string& content) {
Profile::Profile(const std::filesystem::path& path) {
ghoul_assert(std::filesystem::is_regular_file(path), "Path must exist");
std::ifstream inFile;
try {
inFile.open(path, std::ifstream::in);
}
catch (const std::ifstream::failure& e) {
throw ghoul::RuntimeError(fmt::format(
"Exception opening profile file for read: {} ({})", path, e.what()
));
}
std::string content(
(std::istreambuf_iterator<char>(inFile)),
std::istreambuf_iterator<char>()
);
try {
nlohmann::json profile = nlohmann::json::parse(content);
profile.at("version").get_to(version);

View File

@@ -146,30 +146,13 @@ namespace openspace {
using namespace openspace;
namespace {
/// Loads the contents of the file and creates a profile from it
Profile loadProfile(const std::filesystem::path& filename) {
if (!std::filesystem::exists(filename)) {
throw std::runtime_error("Could not find file)");
}
std::ifstream f(filename);
std::string content(
(std::istreambuf_iterator<char>(f)),
std::istreambuf_iterator<char>()
);
return Profile(content);
}
} // namespace
//
// Minimal
// The absolute minimal profile that can be loaded
//
TEST_CASE("Minimal", "[profile]") {
constexpr std::string_view File = "${TESTDIR}/profile/minimal.profile";
Profile profile = loadProfile(absPath(File));
Profile profile = Profile(absPath(File));
Profile ref;
ref.version = Profile::CurrentVersion;
@@ -182,7 +165,7 @@ TEST_CASE("Minimal", "[profile]") {
//
TEST_CASE("Basic Meta (full)", "[profile]") {
constexpr std::string_view File = "${TESTDIR}/profile/basic/meta_full.profile";
Profile profile = loadProfile(absPath(File));
Profile profile = Profile(absPath(File));
Profile ref;
ref.version = Profile::CurrentVersion;
@@ -201,7 +184,7 @@ TEST_CASE("Basic Meta (full)", "[profile]") {
TEST_CASE("Basic Meta (empty)", "[profile]") {
constexpr std::string_view File = "${TESTDIR}/profile/basic/meta_empty.profile";
Profile profile = loadProfile(absPath(File));
Profile profile = Profile(absPath(File));
Profile ref;
ref.version = Profile::CurrentVersion;
@@ -214,7 +197,7 @@ TEST_CASE("Basic Meta (empty)", "[profile]") {
TEST_CASE("Basic Meta (no name)", "[profile]") {
constexpr std::string_view File = "${TESTDIR}/profile/basic/meta_no_name.profile";
Profile profile = loadProfile(absPath(File));
Profile profile = Profile(absPath(File));
Profile ref;
ref.version = Profile::CurrentVersion;
@@ -232,7 +215,7 @@ TEST_CASE("Basic Meta (no name)", "[profile]") {
TEST_CASE("Basic Meta (no version)", "[profile]") {
constexpr std::string_view File = "${TESTDIR}/profile/basic/meta_no_version.profile";
Profile profile = loadProfile(absPath(File));
Profile profile = Profile(absPath(File));
Profile ref;
ref.version = Profile::CurrentVersion;
@@ -250,7 +233,7 @@ TEST_CASE("Basic Meta (no version)", "[profile]") {
TEST_CASE("Basic Meta (no description)", "[profile]") {
constexpr std::string_view File = "${TESTDIR}/profile/basic/meta_no_description.profile";
Profile profile = loadProfile(absPath(File));
Profile profile = Profile(absPath(File));
Profile ref;
ref.version = Profile::CurrentVersion;
@@ -268,7 +251,7 @@ TEST_CASE("Basic Meta (no description)", "[profile]") {
TEST_CASE("Basic Meta (no author)", "[profile]") {
constexpr std::string_view File = "${TESTDIR}/profile/basic/meta_no_author.profile";
Profile profile = loadProfile(absPath(File));
Profile profile = Profile(absPath(File));
Profile ref;
ref.version = Profile::CurrentVersion;
@@ -286,7 +269,7 @@ TEST_CASE("Basic Meta (no author)", "[profile]") {
TEST_CASE("Basic Meta (no url)", "[profile]") {
constexpr std::string_view File = "${TESTDIR}/profile/basic/meta_no_url.profile";
Profile profile = loadProfile(absPath(File));
Profile profile = Profile(absPath(File));
Profile ref;
ref.version = Profile::CurrentVersion;
@@ -304,7 +287,7 @@ TEST_CASE("Basic Meta (no url)", "[profile]") {
TEST_CASE("Basic Meta (no license)", "[profile]") {
constexpr std::string_view File = "${TESTDIR}/profile/basic/meta_no_license.profile";
Profile profile = loadProfile(absPath(File));
Profile profile = Profile(absPath(File));
Profile ref;
ref.version = Profile::CurrentVersion;
@@ -322,7 +305,7 @@ TEST_CASE("Basic Meta (no license)", "[profile]") {
TEST_CASE("Basic Module", "[profile]") {
constexpr std::string_view File = "${TESTDIR}/profile/basic/modules.profile";
Profile profile = loadProfile(absPath(File));
Profile profile = Profile(absPath(File));
Profile ref;
ref.version = Profile::CurrentVersion;
@@ -357,7 +340,7 @@ TEST_CASE("Basic Module", "[profile]") {
TEST_CASE("Basic Assets", "[profile]") {
constexpr std::string_view File = "${TESTDIR}/profile/basic/assets.profile";
Profile profile = loadProfile(absPath(File));
Profile profile = Profile(absPath(File));
Profile ref;
ref.version = Profile::CurrentVersion;
@@ -371,7 +354,7 @@ TEST_CASE("Basic Assets", "[profile]") {
TEST_CASE("Basic Properties", "[profile]") {
constexpr std::string_view File = "${TESTDIR}/profile/basic/properties.profile";
Profile profile = loadProfile(absPath(File));
Profile profile = Profile(absPath(File));
Profile ref;
ref.version = Profile::CurrentVersion;
@@ -424,7 +407,7 @@ TEST_CASE("Basic Properties", "[profile]") {
TEST_CASE("Basic Keybindings", "[profile]") {
constexpr std::string_view File = "${TESTDIR}/profile/basic/keybindings.profile";
Profile profile = loadProfile(absPath(File));
Profile profile = Profile(absPath(File));
Profile ref;
ref.version = Profile::CurrentVersion;
@@ -480,7 +463,7 @@ TEST_CASE("Basic Keybindings", "[profile]") {
TEST_CASE("Basic Time Relative", "[profile]") {
constexpr std::string_view File = "${TESTDIR}/profile/basic/time_relative.profile";
Profile profile = loadProfile(absPath(File));
Profile profile = Profile(absPath(File));
Profile ref;
ref.version = Profile::CurrentVersion;
@@ -495,7 +478,7 @@ TEST_CASE("Basic Time Relative", "[profile]") {
TEST_CASE("Basic Time Absolute", "[profile]") {
constexpr std::string_view File = "${TESTDIR}/profile/basic/time_absolute.profile";
Profile profile = loadProfile(absPath(File));
Profile profile = Profile(absPath(File));
Profile ref;
ref.version = Profile::CurrentVersion;
@@ -510,7 +493,7 @@ TEST_CASE("Basic Time Absolute", "[profile]") {
TEST_CASE("Basic Delta Times", "[profile]") {
constexpr std::string_view File = "${TESTDIR}/profile/basic/deltatimes.profile";
Profile profile = loadProfile(absPath(File));
Profile profile = Profile(absPath(File));
Profile ref;
ref.version = Profile::CurrentVersion;
@@ -526,7 +509,7 @@ TEST_CASE("Basic Delta Times", "[profile]") {
TEST_CASE("Basic Camera NavState (full)", "[profile]") {
constexpr std::string_view File = "${TESTDIR}/profile/basic/camera_navstate_full.profile";
Profile profile = loadProfile(absPath(File));
Profile profile = Profile(absPath(File));
Profile ref;
ref.version = Profile::CurrentVersion;
@@ -547,7 +530,7 @@ TEST_CASE("Basic Camera NavState (full)", "[profile]") {
TEST_CASE("Basic Camera NavState (no aim)", "[profile]") {
constexpr std::string_view File =
"${TESTDIR}/profile/basic/camera_navstate_no_aim.profile";
Profile profile = loadProfile(absPath(File));
Profile profile = Profile(absPath(File));
Profile ref;
ref.version = Profile::CurrentVersion;
@@ -567,7 +550,7 @@ TEST_CASE("Basic Camera NavState (no aim)", "[profile]") {
TEST_CASE("Basic Camera NavState (no pitch)", "[profile]") {
constexpr std::string_view File =
"${TESTDIR}/profile/basic/camera_navstate_no_pitch.profile";
Profile profile = loadProfile(absPath(File));
Profile profile = Profile(absPath(File));
Profile ref;
ref.version = Profile::CurrentVersion;
@@ -587,7 +570,7 @@ TEST_CASE("Basic Camera NavState (no pitch)", "[profile]") {
TEST_CASE("Basic Camera NavState (no up)", "[profile]") {
constexpr std::string_view File =
"${TESTDIR}/profile/basic/camera_navstate_no_up.profile";
Profile profile = loadProfile(absPath(File));
Profile profile = Profile(absPath(File));
Profile ref;
ref.version = Profile::CurrentVersion;
@@ -607,7 +590,7 @@ TEST_CASE("Basic Camera NavState (no up)", "[profile]") {
TEST_CASE("Basic Camera NavState (no yaw)", "[profile]") {
constexpr std::string_view File =
"${TESTDIR}/profile/basic/camera_navstate_no_yaw.profile";
Profile profile = loadProfile(absPath(File));
Profile profile = Profile(absPath(File));
Profile ref;
ref.version = Profile::CurrentVersion;
@@ -626,7 +609,7 @@ TEST_CASE("Basic Camera NavState (no yaw)", "[profile]") {
TEST_CASE("Basic Camera GoToGeo (full)", "[profile]") {
constexpr std::string_view File = "${TESTDIR}/profile/basic/camera_gotogeo.profile";
Profile profile = loadProfile(absPath(File));
Profile profile = Profile(absPath(File));
Profile ref;
ref.version = Profile::CurrentVersion;
@@ -643,7 +626,7 @@ TEST_CASE("Basic Camera GoToGeo (full)", "[profile]") {
TEST_CASE("Basic Camera GoToGeo (with altitude)", "[profile]") {
constexpr std::string_view File =
"${TESTDIR}/profile/basic/camera_gotogeo_altitude.profile";
Profile profile = loadProfile(absPath(File));
Profile profile = Profile(absPath(File));
Profile ref;
ref.version = Profile::CurrentVersion;
@@ -661,7 +644,7 @@ TEST_CASE("Basic Camera GoToGeo (with altitude)", "[profile]") {
TEST_CASE("Basic Camera GoToNode", "[profile]") {
constexpr std::string_view File =
"${TESTDIR}/profile/basic/camera_gotonode.profile";
Profile profile = loadProfile(absPath(File));
Profile profile = Profile(absPath(File));
Profile ref;
ref.version = Profile::CurrentVersion;
@@ -676,7 +659,7 @@ TEST_CASE("Basic Camera GoToNode", "[profile]") {
TEST_CASE("Basic Camera GoToNode (with height)", "[profile]") {
constexpr std::string_view File =
"${TESTDIR}/profile/basic/camera_gotonode_height.profile";
Profile profile = loadProfile(absPath(File));
Profile profile = Profile(absPath(File));
Profile ref;
ref.version = Profile::CurrentVersion;
@@ -691,7 +674,7 @@ TEST_CASE("Basic Camera GoToNode (with height)", "[profile]") {
TEST_CASE("Basic Mark Nodes", "[profile]") {
constexpr std::string_view File = "${TESTDIR}/profile/basic/mark_nodes.profile";
Profile profile = loadProfile(absPath(File));
Profile profile = Profile(absPath(File));
Profile ref;
ref.version = Profile::CurrentVersion;
@@ -706,7 +689,7 @@ TEST_CASE("Basic Mark Nodes", "[profile]") {
TEST_CASE("Basic Additional Scripts", "[profile]") {
constexpr std::string_view File =
"${TESTDIR}/profile/basic/additional_scripts.profile";
Profile profile = loadProfile(absPath(File));
Profile profile = Profile(absPath(File));
Profile ref;
ref.version = Profile::CurrentVersion;
@@ -723,7 +706,7 @@ TEST_CASE("Basic Additional Scripts", "[profile]") {
//
TEST_CASE("Integration Full Test", "[profile]") {
constexpr std::string_view File = "${TESTDIR}/profile/integration/full_test.profile";
Profile profile = loadProfile(absPath(File));
Profile profile = Profile(absPath(File));
Profile ref;
ref.version = Profile::CurrentVersion;
@@ -1074,7 +1057,7 @@ TEST_CASE("(Error) Version: Missing value 'major'", "[profile]") {
constexpr std::string_view TestFile =
"${TESTDIR}/profile/error/version/missing_major.profile";
CHECK_THROWS_WITH(
loadProfile(absPath(TestFile)),
Profile(absPath(TestFile)),
Catch::Matchers::Equals("(profile) 'version.major' field is missing")
);
}
@@ -1083,7 +1066,7 @@ TEST_CASE("(Error) Version: Missing value 'minor'", "[profile]") {
constexpr std::string_view TestFile =
"${TESTDIR}/profile/error/version/missing_minor.profile";
CHECK_THROWS_WITH(
loadProfile(absPath(TestFile)),
Profile(absPath(TestFile)),
Catch::Matchers::Equals("(profile) 'version.minor' field is missing")
);
}
@@ -1092,7 +1075,7 @@ TEST_CASE("(Error) Version: Wrong type 'major'", "[profile]") {
constexpr std::string_view TestFile =
"${TESTDIR}/profile/error/version/wrongtype_major.profile";
CHECK_THROWS_WITH(
loadProfile(absPath(TestFile)),
Profile(absPath(TestFile)),
Catch::Matchers::Equals("(profile) 'version.major' must be a number")
);
}
@@ -1101,7 +1084,7 @@ TEST_CASE("(Error) Version: Wrong type 'minor'", "[profile]") {
constexpr std::string_view TestFile =
"${TESTDIR}/profile/error/version/wrongtype_minor.profile";
CHECK_THROWS_WITH(
loadProfile(absPath(TestFile)),
Profile(absPath(TestFile)),
Catch::Matchers::Equals("(profile) 'version.minor' must be a number")
);
}
@@ -1110,7 +1093,7 @@ TEST_CASE("(Error) Version: Wrong type 'major' and 'minor'", "[profile]") {
constexpr std::string_view TestFile =
"${TESTDIR}/profile/error/version/wrongtype_major_minor.profile";
CHECK_THROWS_WITH(
loadProfile(absPath(TestFile)),
Profile(absPath(TestFile)),
Catch::Matchers::Equals("(profile) 'version.major' must be a number")
);
}
@@ -1124,7 +1107,7 @@ TEST_CASE("(Error) Module: Missing value 'name'", "[profile]") {
constexpr std::string_view TestFile =
"${TESTDIR}/profile/error/module/missing_name.profile";
CHECK_THROWS_WITH(
loadProfile(absPath(TestFile)),
Profile(absPath(TestFile)),
Catch::Matchers::Equals("(profile) 'module.name' field is missing")
);
}
@@ -1133,7 +1116,7 @@ TEST_CASE("(Error) Module: Wrong type 'name'", "[profile]") {
constexpr std::string_view TestFile =
"${TESTDIR}/profile/error/module/wrongtype_name.profile";
CHECK_THROWS_WITH(
loadProfile(absPath(TestFile)),
Profile(absPath(TestFile)),
Catch::Matchers::Equals("(profile) 'module.name' must be a string")
);
}
@@ -1142,7 +1125,7 @@ TEST_CASE("(Error) Module: Wrong type 'loadedInstruction'", "[profile]") {
constexpr std::string_view TestFile =
"${TESTDIR}/profile/error/module/wrongtype_loadedInstruction.profile";
CHECK_THROWS_WITH(
loadProfile(absPath(TestFile)),
Profile(absPath(TestFile)),
Catch::Matchers::Equals("(profile) 'module.loadedInstruction' must be a string")
);
}
@@ -1151,7 +1134,7 @@ TEST_CASE("(Error) Module: Wrong type 'notLoadedInstruction'", "[profile]") {
constexpr std::string_view TestFile =
"${TESTDIR}/profile/error/module/wrongtype_notLoadedInstruction.profile";
CHECK_THROWS_WITH(
loadProfile(absPath(TestFile)),
Profile(absPath(TestFile)),
Catch::Matchers::Equals("(profile) 'module.notLoadedInstruction' must be a string")
);
}
@@ -1164,7 +1147,7 @@ TEST_CASE("(Error) Property: Missing value 'name'", "[profile]") {
constexpr std::string_view TestFile =
"${TESTDIR}/profile/error/property/missing_name.profile";
CHECK_THROWS_WITH(
loadProfile(absPath(TestFile)),
Profile(absPath(TestFile)),
Catch::Matchers::Equals("(profile) 'property.name' field is missing")
);
}
@@ -1173,7 +1156,7 @@ TEST_CASE("(Error) Property: Missing value 'value'", "[profile]") {
constexpr std::string_view TestFile =
"${TESTDIR}/profile/error/property/missing_value.profile";
CHECK_THROWS_WITH(
loadProfile(absPath(TestFile)),
Profile(absPath(TestFile)),
Catch::Matchers::Equals("(profile) 'property.value' field is missing")
);
}
@@ -1182,7 +1165,7 @@ TEST_CASE("(Error) Property: Missing value 'name' and 'value'", "[profile]") {
constexpr std::string_view TestFile =
"${TESTDIR}/profile/error/property/missing_name_value.profile";
CHECK_THROWS_WITH(
loadProfile(absPath(TestFile)),
Profile(absPath(TestFile)),
Catch::Matchers::Equals("(profile) 'property.name' field is missing")
);
}
@@ -1191,7 +1174,7 @@ TEST_CASE("(Error) Property: Wrong value 'type'", "[profile]") {
constexpr std::string_view TestFile =
"${TESTDIR}/profile/error/property/wrongvalue_type.profile";
CHECK_THROWS_WITH(
loadProfile(absPath(TestFile)),
Profile(absPath(TestFile)),
Catch::Matchers::Equals("(profile) Unknown property set type")
);
}
@@ -1200,7 +1183,7 @@ TEST_CASE("(Error) Property: Wrong type 'name'", "[profile]") {
constexpr std::string_view TestFile =
"${TESTDIR}/profile/error/property/wrongtype_name.profile";
CHECK_THROWS_WITH(
loadProfile(absPath(TestFile)),
Profile(absPath(TestFile)),
Catch::Matchers::Equals("(profile) 'property.name' must be a string")
);
}
@@ -1209,7 +1192,7 @@ TEST_CASE("(Error) Property: Wrong type 'value'", "[profile]") {
constexpr std::string_view TestFile =
"${TESTDIR}/profile/error/property/wrongtype_value.profile";
CHECK_THROWS_WITH(
loadProfile(absPath(TestFile)),
Profile(absPath(TestFile)),
Catch::Matchers::Equals("(profile) 'property.value' must be a string")
);
}
@@ -1222,7 +1205,7 @@ TEST_CASE("(Error) Keybinding: Missing value 'key'", "[profile]") {
constexpr std::string_view TestFile =
"${TESTDIR}/profile/error/keybinding/missing_key.profile";
CHECK_THROWS_WITH(
loadProfile(absPath(TestFile)),
Profile(absPath(TestFile)),
Catch::Matchers::Equals("(profile) 'keybinding.key' field is missing")
);
}
@@ -1231,7 +1214,7 @@ TEST_CASE("(Error) Keybinding: Missing value 'documentation'", "[profile]") {
constexpr std::string_view TestFile =
"${TESTDIR}/profile/error/keybinding/missing_documentation.profile";
CHECK_THROWS_WITH(
loadProfile(absPath(TestFile)),
Profile(absPath(TestFile)),
Catch::Matchers::Equals("(profile) 'keybinding.documentation' field is missing")
);
}
@@ -1240,7 +1223,7 @@ TEST_CASE("(Error) Keybinding: Missing value 'name'", "[profile]") {
constexpr std::string_view TestFile =
"${TESTDIR}/profile/error/keybinding/missing_name.profile";
CHECK_THROWS_WITH(
loadProfile(absPath(TestFile)),
Profile(absPath(TestFile)),
Catch::Matchers::Equals("(profile) 'keybinding.name' field is missing")
);
}
@@ -1249,7 +1232,7 @@ TEST_CASE("(Error) Keybinding: Missing value 'gui_path'", "[profile]") {
constexpr std::string_view TestFile =
"${TESTDIR}/profile/error/keybinding/missing_guipath.profile";
CHECK_THROWS_WITH(
loadProfile(absPath(TestFile)),
Profile(absPath(TestFile)),
Catch::Matchers::Equals("(profile) 'keybinding.gui_path' field is missing")
);
}
@@ -1258,7 +1241,7 @@ TEST_CASE("(Error) Keybinding: Missing value 'is_local'", "[profile]") {
constexpr std::string_view TestFile =
"${TESTDIR}/profile/error/keybinding/missing_islocal.profile";
CHECK_THROWS_WITH(
loadProfile(absPath(TestFile)),
Profile(absPath(TestFile)),
Catch::Matchers::Equals("(profile) 'keybinding.is_local' field is missing")
);
}
@@ -1267,7 +1250,7 @@ TEST_CASE("(Error) Keybinding: Wrong value 'key'", "[profile]") {
constexpr std::string_view TestFile =
"${TESTDIR}/profile/error/keybinding/wrongvalue_key.profile";
CHECK_THROWS_WITH(
loadProfile(absPath(TestFile)),
Profile(absPath(TestFile)),
Catch::Matchers::Equals("Could not find key for 'F50'")
);
}
@@ -1276,7 +1259,7 @@ TEST_CASE("(Error) Keybinding: Wrong value 'key, modifier'", "[profile]") {
constexpr std::string_view TestFile =
"${TESTDIR}/profile/error/keybinding/wrongvalue_modifier.profile";
CHECK_THROWS_WITH(
loadProfile(absPath(TestFile)),
Profile(absPath(TestFile)),
Catch::Matchers::Equals("Unknown modifier key 'KEYKEY'")
);
}
@@ -1285,7 +1268,7 @@ TEST_CASE("(Error) Keybinding: Wrong type 'documentation'", "[profile]") {
constexpr std::string_view TestFile =
"${TESTDIR}/profile/error/keybinding/wrongtype_documentation.profile";
CHECK_THROWS_WITH(
loadProfile(absPath(TestFile)),
Profile(absPath(TestFile)),
Catch::Matchers::Equals("(profile) 'keybinding.documentation' must be a string")
);
}
@@ -1294,7 +1277,7 @@ TEST_CASE("(Error) Keybinding: Wrong type 'gui_path'", "[profile]") {
constexpr std::string_view TestFile =
"${TESTDIR}/profile/error/keybinding/wrongtype_guipath.profile";
CHECK_THROWS_WITH(
loadProfile(absPath(TestFile)),
Profile(absPath(TestFile)),
Catch::Matchers::Equals("(profile) 'keybinding.gui_path' must be a string")
);
}
@@ -1303,7 +1286,7 @@ TEST_CASE("(Error) Keybinding: Wrong type 'is_local'", "[profile]") {
constexpr std::string_view TestFile =
"${TESTDIR}/profile/error/keybinding/wrongtype_islocal.profile";
CHECK_THROWS_WITH(
loadProfile(absPath(TestFile)),
Profile(absPath(TestFile)),
Catch::Matchers::Equals("(profile) 'keybinding.is_local' must be a boolean")
);
}
@@ -1312,7 +1295,7 @@ TEST_CASE("(Error) Keybinding: Wrong type 'name'", "[profile]") {
constexpr std::string_view TestFile =
"${TESTDIR}/profile/error/keybinding/wrongtype_name.profile";
CHECK_THROWS_WITH(
loadProfile(absPath(TestFile)),
Profile(absPath(TestFile)),
Catch::Matchers::Equals("(profile) 'keybinding.name' must be a string")
);
}
@@ -1321,7 +1304,7 @@ TEST_CASE("(Error) Keybinding: Wrong type 'script'", "[profile]") {
constexpr std::string_view TestFile =
"${TESTDIR}/profile/error/keybinding/wrongtype_script.profile";
CHECK_THROWS_WITH(
loadProfile(absPath(TestFile)),
Profile(absPath(TestFile)),
Catch::Matchers::Equals("(profile) 'keybinding.script' must be a string")
);
}
@@ -1334,7 +1317,7 @@ TEST_CASE("(Error) Time: Wrong value 'type'", "[profile]") {
constexpr std::string_view TestFile =
"${TESTDIR}/profile/error/time/wrongvalue_type.profile";
CHECK_THROWS_WITH(
loadProfile(absPath(TestFile)),
Profile(absPath(TestFile)),
Catch::Matchers::Equals("(profile) Unknown time type")
);
}
@@ -1343,7 +1326,7 @@ TEST_CASE("(Error) Time (absolute): Missing value 'type'", "[profile]") {
constexpr std::string_view TestFile =
"${TESTDIR}/profile/error/time/missing_type.profile";
CHECK_THROWS_WITH(
loadProfile(absPath(TestFile)),
Profile(absPath(TestFile)),
Catch::Matchers::Equals("(profile) 'time.type' field is missing")
);
}
@@ -1352,7 +1335,7 @@ TEST_CASE("(Error) Time (relative): Missing value 'value'", "[profile]") {
constexpr std::string_view TestFile =
"${TESTDIR}/profile/error/time/relative_missing_value.profile";
CHECK_THROWS_WITH(
loadProfile(absPath(TestFile)),
Profile(absPath(TestFile)),
Catch::Matchers::Equals("(profile) 'time.value' field is missing")
);
}
@@ -1364,7 +1347,7 @@ TEST_CASE("(Error) Deltatimes: Wrong type", "[profile]") {
constexpr std::string_view TestFile =
"${TESTDIR}/profile/error/deltatimes/wrongtype_value.profile";
CHECK_THROWS_WITH(
loadProfile(absPath(TestFile)),
Profile(absPath(TestFile)),
Catch::Matchers::ContainsSubstring("type must be number, but is string")
);
}
@@ -1376,7 +1359,7 @@ TEST_CASE("(Error) Camera: Wrong value 'type'", "[profile]") {
constexpr std::string_view TestFile =
"${TESTDIR}/profile/error/camera/wrongvalue_type.profile";
CHECK_THROWS_WITH(
loadProfile(absPath(TestFile)),
Profile(absPath(TestFile)),
Catch::Matchers::Equals("(profile) Unknown camera type")
);
}
@@ -1385,7 +1368,7 @@ TEST_CASE("(Error) Camera (NavState): Missing value 'anchor'", "[profile]") {
constexpr std::string_view TestFile =
"${TESTDIR}/profile/error/camera/navstate_missing_anchor.profile";
CHECK_THROWS_WITH(
loadProfile(absPath(TestFile)),
Profile(absPath(TestFile)),
Catch::Matchers::Equals("(profile) 'camera.anchor' field is missing")
);
}
@@ -1394,7 +1377,7 @@ TEST_CASE("(Error) Camera (NavState): Missing value 'frame'", "[profile]") {
constexpr std::string_view TestFile =
"${TESTDIR}/profile/error/camera/navstate_missing_frame.profile";
CHECK_THROWS_WITH(
loadProfile(absPath(TestFile)),
Profile(absPath(TestFile)),
Catch::Matchers::Equals("(profile) 'camera.frame' field is missing")
);
}
@@ -1403,7 +1386,7 @@ TEST_CASE("(Error) Camera (NavState): Missing value 'position'", "[profile]") {
constexpr std::string_view TestFile =
"${TESTDIR}/profile/error/camera/navstate_missing_position.profile";
CHECK_THROWS_WITH(
loadProfile(absPath(TestFile)),
Profile(absPath(TestFile)),
Catch::Matchers::Equals("(profile) 'camera.position' field is missing")
);
}
@@ -1412,7 +1395,7 @@ TEST_CASE("(Error) Camera (NavState): Wrong type 'anchor'", "[profile]") {
constexpr std::string_view TestFile =
"${TESTDIR}/profile/error/camera/navstate_wrongtype_anchor.profile";
CHECK_THROWS_WITH(
loadProfile(absPath(TestFile)),
Profile(absPath(TestFile)),
Catch::Matchers::Equals("(profile) 'camera.anchor' must be a string")
);
}
@@ -1421,7 +1404,7 @@ TEST_CASE("(Error) Camera (NavState): Wrong type 'aim'", "[profile]") {
constexpr std::string_view TestFile =
"${TESTDIR}/profile/error/camera/navstate_wrongtype_aim.profile";
CHECK_THROWS_WITH(
loadProfile(absPath(TestFile)),
Profile(absPath(TestFile)),
Catch::Matchers::Equals("(profile) 'camera.aim' must be a string")
);
}
@@ -1430,7 +1413,7 @@ TEST_CASE("(Error) Camera (NavState): Wrong type 'frame'", "[profile]") {
constexpr std::string_view TestFile =
"${TESTDIR}/profile/error/camera/navstate_wrongtype_frame.profile";
CHECK_THROWS_WITH(
loadProfile(absPath(TestFile)),
Profile(absPath(TestFile)),
Catch::Matchers::Equals("(profile) 'camera.frame' must be a string")
);
}
@@ -1439,7 +1422,7 @@ TEST_CASE("(Error) Camera (NavState): Wrong type 'position'", "[profile]") {
constexpr std::string_view TestFile =
"${TESTDIR}/profile/error/camera/navstate_wrongtype_position.profile";
CHECK_THROWS_WITH(
loadProfile(absPath(TestFile)),
Profile(absPath(TestFile)),
Catch::Matchers::Equals("(profile) 'camera.position' must be an object")
);
}
@@ -1448,7 +1431,7 @@ TEST_CASE("(Error) Camera (NavState): Missing value 'position.x'", "[profile]")
constexpr std::string_view TestFile =
"${TESTDIR}/profile/error/camera/navstate_missing_position_x.profile";
CHECK_THROWS_WITH(
loadProfile(absPath(TestFile)),
Profile(absPath(TestFile)),
Catch::Matchers::Equals("(profile) 'camera.position.x' field is missing")
);
}
@@ -1457,7 +1440,7 @@ TEST_CASE("(Error) Camera (NavState): Wrong type 'position.x'", "[profile]") {
constexpr std::string_view TestFile =
"${TESTDIR}/profile/error/camera/navstate_wrongtype_position_x.profile";
CHECK_THROWS_WITH(
loadProfile(absPath(TestFile)),
Profile(absPath(TestFile)),
Catch::Matchers::Equals("(profile) 'camera.position.x' must be a number")
);
}
@@ -1466,7 +1449,7 @@ TEST_CASE("(Error) Camera (NavState): Missing value 'position.y'", "[profile]")
constexpr std::string_view TestFile =
"${TESTDIR}/profile/error/camera/navstate_missing_position_y.profile";
CHECK_THROWS_WITH(
loadProfile(absPath(TestFile)),
Profile(absPath(TestFile)),
Catch::Matchers::Equals("(profile) 'camera.position.y' field is missing")
);
}
@@ -1475,7 +1458,7 @@ TEST_CASE("(Error) Camera (NavState): Wrong type 'position.y'", "[profile]") {
constexpr std::string_view TestFile =
"${TESTDIR}/profile/error/camera/navstate_wrongtype_position_y.profile";
CHECK_THROWS_WITH(
loadProfile(absPath(TestFile)),
Profile(absPath(TestFile)),
Catch::Matchers::Equals("(profile) 'camera.position.y' must be a number")
);
}
@@ -1484,7 +1467,7 @@ TEST_CASE("(Error) Camera (NavState): Missing value 'position.z'", "[profile]")
constexpr std::string_view TestFile =
"${TESTDIR}/profile/error/camera/navstate_missing_position_z.profile";
CHECK_THROWS_WITH(
loadProfile(absPath(TestFile)),
Profile(absPath(TestFile)),
Catch::Matchers::Equals("(profile) 'camera.position.z' field is missing")
);
}
@@ -1493,7 +1476,7 @@ TEST_CASE("(Error) Camera (NavState): Wrong type 'position.z'", "[profile]") {
constexpr std::string_view TestFile =
"${TESTDIR}/profile/error/camera/navstate_wrongtype_position_z.profile";
CHECK_THROWS_WITH(
loadProfile(absPath(TestFile)),
Profile(absPath(TestFile)),
Catch::Matchers::Equals("(profile) 'camera.position.z' must be a number")
);
}
@@ -1502,7 +1485,7 @@ TEST_CASE("(Error) Camera (NavState): Wrong type 'up'", "[profile]") {
constexpr std::string_view TestFile =
"${TESTDIR}/profile/error/camera/navstate_wrongtype_up.profile";
CHECK_THROWS_WITH(
loadProfile(absPath(TestFile)),
Profile(absPath(TestFile)),
Catch::Matchers::Equals("(profile) 'camera.up' must be an object")
);
}
@@ -1511,7 +1494,7 @@ TEST_CASE("(Error) Camera (NavState): Missing value 'up.x'", "[profile]") {
constexpr std::string_view TestFile =
"${TESTDIR}/profile/error/camera/navstate_missing_up_x.profile";
CHECK_THROWS_WITH(
loadProfile(absPath(TestFile)),
Profile(absPath(TestFile)),
Catch::Matchers::Equals("(profile) 'camera.up.x' field is missing")
);
}
@@ -1520,7 +1503,7 @@ TEST_CASE("(Error) Camera (NavState): Wrong type 'up.x'", "[profile]") {
constexpr std::string_view TestFile =
"${TESTDIR}/profile/error/camera/navstate_wrongtype_up_x.profile";
CHECK_THROWS_WITH(
loadProfile(absPath(TestFile)),
Profile(absPath(TestFile)),
Catch::Matchers::Equals("(profile) 'camera.up.x' must be a number")
);
}
@@ -1529,7 +1512,7 @@ TEST_CASE("(Error) Camera (NavState): Missing value 'up.y'", "[profile]") {
constexpr std::string_view TestFile =
"${TESTDIR}/profile/error/camera/navstate_missing_up_y.profile";
CHECK_THROWS_WITH(
loadProfile(absPath(TestFile)),
Profile(absPath(TestFile)),
Catch::Matchers::Equals("(profile) 'camera.up.y' field is missing")
);
}
@@ -1538,7 +1521,7 @@ TEST_CASE("(Error) Camera (NavState): Wrong type 'up.y'", "[profile]") {
constexpr std::string_view TestFile =
"${TESTDIR}/profile/error/camera/navstate_wrongtype_up_y.profile";
CHECK_THROWS_WITH(
loadProfile(absPath(TestFile)),
Profile(absPath(TestFile)),
Catch::Matchers::Equals("(profile) 'camera.up.y' must be a number")
);
}
@@ -1547,7 +1530,7 @@ TEST_CASE("(Error) Camera (NavState): Missing value 'up.z'", "[profile]") {
constexpr std::string_view TestFile =
"${TESTDIR}/profile/error/camera/navstate_missing_up_z.profile";
CHECK_THROWS_WITH(
loadProfile(absPath(TestFile)),
Profile(absPath(TestFile)),
Catch::Matchers::Equals("(profile) 'camera.up.z' field is missing")
);
}
@@ -1556,7 +1539,7 @@ TEST_CASE("(Error) Camera (NavState): Wrong type 'up.z'", "[profile]") {
constexpr std::string_view TestFile =
"${TESTDIR}/profile/error/camera/navstate_wrongtype_up_z.profile";
CHECK_THROWS_WITH(
loadProfile(absPath(TestFile)),
Profile(absPath(TestFile)),
Catch::Matchers::Equals("(profile) 'camera.up.z' must be a number")
);
}
@@ -1565,7 +1548,7 @@ TEST_CASE("(Error) Camera (NavState): Wrong type 'yaw'", "[profile]") {
constexpr std::string_view TestFile =
"${TESTDIR}/profile/error/camera/navstate_wrongtype_yaw.profile";
CHECK_THROWS_WITH(
loadProfile(absPath(TestFile)),
Profile(absPath(TestFile)),
Catch::Matchers::Equals("(profile) 'camera.yaw' must be a number")
);
}
@@ -1574,7 +1557,7 @@ TEST_CASE("(Error) Camera (NavState): Wrong type 'pitch'", "[profile]") {
constexpr std::string_view TestFile =
"${TESTDIR}/profile/error/camera/navstate_wrongtype_pitch.profile";
CHECK_THROWS_WITH(
loadProfile(absPath(TestFile)),
Profile(absPath(TestFile)),
Catch::Matchers::Equals("(profile) 'camera.pitch' must be a number")
);
}
@@ -1583,7 +1566,7 @@ TEST_CASE("(Error) Camera (GoToGeo): Missing value 'anchor'", "[profile]") {
constexpr std::string_view TestFile =
"${TESTDIR}/profile/error/camera/gotogeo_missing_anchor.profile";
CHECK_THROWS_WITH(
loadProfile(absPath(TestFile)),
Profile(absPath(TestFile)),
Catch::Matchers::Equals("(profile) 'camera.anchor' field is missing")
);
}
@@ -1592,7 +1575,7 @@ TEST_CASE("(Error) Camera (GoToGeo): Missing value 'latitude'", "[profile]") {
constexpr std::string_view TestFile =
"${TESTDIR}/profile/error/camera/gotogeo_missing_latitude.profile";
CHECK_THROWS_WITH(
loadProfile(absPath(TestFile)),
Profile(absPath(TestFile)),
Catch::Matchers::Equals("(profile) 'camera.latitude' field is missing")
);
}
@@ -1601,7 +1584,7 @@ TEST_CASE("(Error) Camera (GoToGeo): Missing value 'longitude'", "[profile]") {
constexpr std::string_view TestFile =
"${TESTDIR}/profile/error/camera/gotogeo_missing_longitude.profile";
CHECK_THROWS_WITH(
loadProfile(absPath(TestFile)),
Profile(absPath(TestFile)),
Catch::Matchers::Equals("(profile) 'camera.longitude' field is missing")
);
}
@@ -1610,7 +1593,7 @@ TEST_CASE("(Error) Camera (GoToGeo): Wrong type 'anchor'", "[profile]") {
constexpr std::string_view TestFile =
"${TESTDIR}/profile/error/camera/gotogeo_wrongtype_anchor.profile";
CHECK_THROWS_WITH(
loadProfile(absPath(TestFile)),
Profile(absPath(TestFile)),
Catch::Matchers::Equals("(profile) 'camera.anchor' must be a string")
);
}
@@ -1619,7 +1602,7 @@ TEST_CASE("(Error) Camera (GoToGeo): Wrong type 'latitude'", "[profile]") {
constexpr std::string_view TestFile =
"${TESTDIR}/profile/error/camera/gotogeo_wrongtype_latitude.profile";
CHECK_THROWS_WITH(
loadProfile(absPath(TestFile)),
Profile(absPath(TestFile)),
Catch::Matchers::Equals("(profile) 'camera.latitude' must be a number")
);
}
@@ -1628,7 +1611,7 @@ TEST_CASE("(Error) Camera (GoToGeo): Wrong type 'longitude'", "[profile]") {
constexpr std::string_view TestFile =
"${TESTDIR}/profile/error/camera/gotogeo_wrongtype_longitude.profile";
CHECK_THROWS_WITH(
loadProfile(absPath(TestFile)),
Profile(absPath(TestFile)),
Catch::Matchers::Equals("(profile) 'camera.longitude' must be a number")
);
}
@@ -1637,7 +1620,7 @@ TEST_CASE("(Error) Camera (GoToGeo): Wrong type 'altitude'", "[profile]") {
constexpr std::string_view TestFile =
"${TESTDIR}/profile/error/camera/gotogeo_wrongtype_altitude.profile";
CHECK_THROWS_WITH(
loadProfile(absPath(TestFile)),
Profile(absPath(TestFile)),
Catch::Matchers::Equals("(profile) 'camera.altitude' must be a number")
);
}
@@ -1646,7 +1629,7 @@ TEST_CASE("(Error) Camera (GoToNode): Wrong type 'anchor'", "[profile]") {
constexpr std::string_view TestFile =
"${TESTDIR}/profile/error/camera/gotonode_wrongtype_anchor.profile";
CHECK_THROWS_WITH(
loadProfile(absPath(TestFile)),
Profile(absPath(TestFile)),
Catch::Matchers::Equals("(profile) 'camera.anchor' must be a string")
);
}
@@ -1655,7 +1638,7 @@ TEST_CASE("(Error) Camera (GoToNode): Wrong type 'height'", "[profile]") {
constexpr std::string_view TestFile =
"${TESTDIR}/profile/error/camera/gotonode_wrongtype_height.profile";
CHECK_THROWS_WITH(
loadProfile(absPath(TestFile)),
Profile(absPath(TestFile)),
Catch::Matchers::Equals("(profile) 'camera.height' must be a number")
);
}
@@ -1664,7 +1647,7 @@ TEST_CASE("(Error) Camera (GoToNode): Missing value 'anchor'", "[profile]") {
constexpr std::string_view TestFile =
"${TESTDIR}/profile/error/camera/gotonode_missing_anchor.profile";
CHECK_THROWS_WITH(
loadProfile(absPath(TestFile)),
Profile(absPath(TestFile)),
Catch::Matchers::Equals("(profile) 'camera.anchor' field is missing")
);
}
@@ -1677,7 +1660,7 @@ TEST_CASE("(Error) Camera (GoToNode): Missing value 'anchor'", "[profile]") {
// constexpr std::string_view TestFile =
// "${TESTDIR}/profile/error/camera/gotonode_invalidvalue_negative_height.profile";
// CHECK_THROWS_WITH(
// loadProfile(absPath(TestFile)),
// Profile(absPath(TestFile)),
// Catch::Matchers::Equals("(profile) 'camera.height' must be a larger than zero")
// );
//}
@@ -1686,7 +1669,7 @@ TEST_CASE("(Error) Camera (GoToNode): Missing value 'anchor'", "[profile]") {
// constexpr std::string_view TestFile =
// "${TESTDIR}/profile/error/camera/gotonode_invalidvalue_zero_height.profile";
// CHECK_THROWS_WITH(
// loadProfile(absPath(TestFile)),
// Profile(absPath(TestFile)),
// Catch::Matchers::Equals("(profile) 'camera.height' must be a larger than zero")
// );
//}

View File

@@ -0,0 +1,12 @@
[
{ "type": "pause",
"value": "true"},
{ "type": "time",
"value": "1966-11-12T14:28:39.00"},
{ "type": "navigationstate",
"value": "{Anchor='Earth',Position={8117064.770626424,-15651002.199110571,-9165703.435119975},Up={-0.39241745239503034,-0.6078072727788707,0.6903469143937023}"},
{ "type": "wait",
"value": "30"},
{ "type": "screenshot",
"value": ""}
]