mirror of
https://github.com/OpenSpace/OpenSpace.git
synced 2026-05-06 19:39:56 -05:00
Feature/codegen (#1480)
* Add the ability to automatically generate code to extract values out of a Dictionary (see https://github.com/openspace/codegen for more information on how to use this) * Applied this technique to a large number of cases in the codebase * Don't add _codegen files to the repository Co-authored-by: Emma Broman <emma.broman@liu.se>
This commit is contained in:
@@ -38,3 +38,4 @@ Thumbs.db
|
||||
customization.lua
|
||||
# The COMMIT info is generated everytime CMake is run
|
||||
COMMIT.md
|
||||
*_codegen.cpp
|
||||
|
||||
@@ -29,3 +29,6 @@
|
||||
[submodule "ext/date"]
|
||||
path = ext/date
|
||||
url = https://github.com/HowardHinnant/date
|
||||
[submodule "support/coding/codegen"]
|
||||
path = support/coding/codegen
|
||||
url = https://github.com/OpenSpace/codegen
|
||||
|
||||
+26
-3
@@ -139,12 +139,29 @@ if (UNIX AND CMAKE_CXX_COMPILER_ID MATCHES "Clang")
|
||||
set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -stdlib=libc++ -lc++ -lc++abi")
|
||||
endif ()
|
||||
|
||||
# Add external dependencies
|
||||
add_subdirectory(${OPENSPACE_BASE_DIR}/ext)
|
||||
add_subdirectory(ext)
|
||||
|
||||
# include(src/CMakeLists.txt)
|
||||
add_subdirectory(src)
|
||||
|
||||
add_subdirectory(support/coding/codegen)
|
||||
# It is important that the __codegen.h do not actually exist so
|
||||
# that this target is never considered as finished
|
||||
add_custom_target(
|
||||
run_codegen
|
||||
ALL DEPENDS
|
||||
"${CMAKE_CURRENT_BINARY_DIR}/__codegen.h"
|
||||
)
|
||||
add_dependencies(run_codegen codegen)
|
||||
add_custom_command(
|
||||
OUTPUT "${CMAKE_CURRENT_BINARY_DIR}/__codegen.h"
|
||||
COMMAND codegen ARGS "${OPENSPACE_BASE_DIR}/modules" "${OPENSPACE_BASE_DIR}/src"
|
||||
VERBATIM
|
||||
)
|
||||
set_folder_location(codegen-lib "support")
|
||||
set_folder_location(codegen "support")
|
||||
set_folder_location(run_codegen "support")
|
||||
|
||||
|
||||
# Qt
|
||||
# Unfortunately, we have to set this value manually; sigh
|
||||
# In the future, if the Qt version is updated, just add to this variable ---abock
|
||||
@@ -176,6 +193,12 @@ begin_header("Configuring Modules")
|
||||
add_subdirectory("${CMAKE_CURRENT_SOURCE_DIR}/modules")
|
||||
end_header("End: Configuring Modules")
|
||||
|
||||
|
||||
add_subdirectory(support/coding/codegen/tests)
|
||||
set_folder_location(run_test_codegen "Unit Tests/support")
|
||||
set_folder_location(codegentest "Unit Tests")
|
||||
|
||||
|
||||
begin_header("Configuring Applications")
|
||||
add_subdirectory("${OPENSPACE_APPS_DIR}")
|
||||
end_header("End: Configuring Applications")
|
||||
|
||||
Vendored
+5
@@ -114,6 +114,7 @@ linux_gcc_make: {
|
||||
}
|
||||
stage('linux-gcc-make/test') {
|
||||
// testHelper.runUnitTests('build/OpenSpaceTest');
|
||||
// testHelper.runUnitTests('bin/codegentest')
|
||||
}
|
||||
cleanWs()
|
||||
} // node('linux')
|
||||
@@ -134,6 +135,7 @@ linux_gcc_ninja: {
|
||||
}
|
||||
stage('linux-gcc-ninja/test') {
|
||||
// testHelper.runUnitTests('build/OpenSpaceTest');
|
||||
// testHelper.runUnitTests('bin/codegentest')
|
||||
}
|
||||
cleanWs()
|
||||
} // node('linux')
|
||||
@@ -155,6 +157,7 @@ linux_clang_make: {
|
||||
}
|
||||
stage('linux-clang-make/test') {
|
||||
// testHelper.runUnitTests('build/OpenSpaceTest');
|
||||
// testHelper.runUnitTests('bin/codegentest')
|
||||
}
|
||||
cleanWs()
|
||||
} // node('linux')
|
||||
@@ -175,6 +178,7 @@ linux_clang_ninja: {
|
||||
}
|
||||
stage('linux-clang-ninja/test') {
|
||||
// testHelper.runUnitTests('build/OpenSpaceTest');
|
||||
// testHelper.runUnitTests('bin/codegentest')
|
||||
}
|
||||
cleanWs()
|
||||
} // node('linux')
|
||||
@@ -194,6 +198,7 @@ windows_msvc: {
|
||||
stage('windows-msvc/test') {
|
||||
// Currently, the unit tests are failing on Windows
|
||||
// testHelper.runUnitTests('bin\\Debug\\OpenSpaceTest')
|
||||
testHelper.runUnitTests('bin\\Debug\\codegentest')
|
||||
}
|
||||
cleanWs()
|
||||
} // node('windows')
|
||||
|
||||
@@ -90,3 +90,11 @@ set_openspace_compile_settings(openspace-ui-launcher)
|
||||
target_include_directories(openspace-ui-launcher PUBLIC include)
|
||||
target_link_libraries(openspace-ui-launcher PUBLIC Qt5::Core Qt5::Gui Qt5::Widgets openspace-core)
|
||||
|
||||
if (MSVC)
|
||||
set(MSVC_WARNINGS
|
||||
"/wd4619" # #pragma warning: there is no warning number (raised by Qt headers)
|
||||
"/wd4946" # reinterpret_cast used between related classes:
|
||||
)
|
||||
target_compile_options(openspace-ui-launcher INTERFACE ${MSVC_WARNINGS})
|
||||
|
||||
endif ()
|
||||
|
||||
@@ -323,4 +323,11 @@ std::string to_string(const openspace::documentation::TestResult::Warning::Reaso
|
||||
|
||||
} // namespace ghoul
|
||||
|
||||
// The verifier header depends on the classes defined in here, but we want to make it
|
||||
// easier for consumers of this header to just have access to all verifiers without
|
||||
// needing to include this file separately. Particularly with the use of the codegen, it
|
||||
// might lead to some unexcepted error messages about recognized identifiers in the
|
||||
// generated code which look scary
|
||||
#include <openspace/documentation/verifier.h>
|
||||
|
||||
#endif // __OPENSPACE_CORE___DOCUMENTATION___H__
|
||||
|
||||
@@ -29,6 +29,18 @@
|
||||
|
||||
namespace openspace::documentation {
|
||||
|
||||
template <>
|
||||
TestResult TemplateVerifier<glm::ivec2>::operator()(const ghoul::Dictionary& dict,
|
||||
const std::string& key) const;
|
||||
|
||||
template <>
|
||||
TestResult TemplateVerifier<glm::ivec3>::operator()(const ghoul::Dictionary& dict,
|
||||
const std::string& key) const;
|
||||
|
||||
template <>
|
||||
TestResult TemplateVerifier<glm::ivec4>::operator()(const ghoul::Dictionary& dict,
|
||||
const std::string& key) const;
|
||||
|
||||
template <typename T>
|
||||
TestResult TemplateVerifier<T>::operator()(const ghoul::Dictionary& dict,
|
||||
const std::string& key) const
|
||||
@@ -122,7 +134,22 @@ TestResult OperatorVerifier<T, Operator>::operator()(const ghoul::Dictionary& di
|
||||
{
|
||||
TestResult res = T::operator()(dict, key);
|
||||
if (res.success) {
|
||||
if (Operator()(dict.value<typename T::Type>(key), value)) {
|
||||
typename T::Type val;
|
||||
if constexpr (std::is_same_v<typename T::Type, int>) {
|
||||
const double d = dict.value<double>(key);
|
||||
double intPart;
|
||||
bool isInt = modf(d, &intPart) == 0.0;
|
||||
if (isInt) {
|
||||
val = static_cast<int>(d);
|
||||
}
|
||||
else {
|
||||
return { false, { { key, TestResult::Offense::Reason::WrongType } }, {} };
|
||||
}
|
||||
}
|
||||
else {
|
||||
val = dict.value<typename T::Type>(key);
|
||||
}
|
||||
if (Operator()(val, value)) {
|
||||
return { true, {}, {} };
|
||||
}
|
||||
else {
|
||||
@@ -270,7 +297,21 @@ TestResult InRangeVerifier<T>::operator()(const ghoul::Dictionary& dict,
|
||||
{
|
||||
TestResult res = T::operator()(dict, key);
|
||||
if (res.success) {
|
||||
typename T::Type val = dict.value<typename T::Type>(key);
|
||||
typename T::Type val;
|
||||
if constexpr (std::is_same_v<typename T::Type, int>) {
|
||||
const double d = dict.value<double>(key);
|
||||
double intPart;
|
||||
bool isInt = modf(d, &intPart) == 0.0;
|
||||
if (isInt) {
|
||||
val = static_cast<int>(d);
|
||||
}
|
||||
else {
|
||||
return { false, { { key, TestResult::Offense::Reason::WrongType } }, {} };
|
||||
}
|
||||
}
|
||||
else {
|
||||
val = dict.value<typename T::Type>(key);
|
||||
}
|
||||
|
||||
if (val >= lower && val <= upper) {
|
||||
return { true, {}, {} };
|
||||
@@ -303,7 +344,21 @@ TestResult NotInRangeVerifier<T>::operator()(const ghoul::Dictionary& dict,
|
||||
const std::string& key) const {
|
||||
TestResult res = T::operator()(dict, key);
|
||||
if (res.success) {
|
||||
typename T::Type val = dict.value<typename T::Type>(key);
|
||||
typename T::Type val;
|
||||
if constexpr (std::is_same_v<typename T::Type, int>) {
|
||||
const double d = dict.value<double>(key);
|
||||
double intPart;
|
||||
bool isInt = modf(d, &intPart) == 0.0;
|
||||
if (isInt) {
|
||||
val = static_cast<int>(d);
|
||||
}
|
||||
else {
|
||||
return { false, { { key, TestResult::Offense::Reason::WrongType } }, {} };
|
||||
}
|
||||
}
|
||||
else {
|
||||
val = dict.value<typename T::Type>(key);
|
||||
}
|
||||
|
||||
if (val >= lower && val <= upper) {
|
||||
return { false, { { key, TestResult::Offense::Reason::Verification } }, {} };
|
||||
|
||||
@@ -61,7 +61,7 @@ public:
|
||||
};
|
||||
|
||||
static ghoul::mm_unique_ptr<Renderable> createFromDictionary(
|
||||
const ghoul::Dictionary& dictionary);
|
||||
ghoul::Dictionary dictionary);
|
||||
|
||||
Renderable(const ghoul::Dictionary& dictionary);
|
||||
virtual ~Renderable() = default;
|
||||
|
||||
@@ -288,6 +288,8 @@ foreach (val RANGE ${enabled_module_count})
|
||||
list(APPEND all_enabled_modules "${library_name}")
|
||||
begin_header("Module ${name} (${library_name})")
|
||||
add_subdirectory(${path})
|
||||
# Make sure that the code generator always runs before a module
|
||||
add_dependencies(${library_name} run_codegen)
|
||||
end_header("End: Module ${name}")
|
||||
message(STATUS "")
|
||||
|
||||
|
||||
@@ -47,6 +47,7 @@
|
||||
#include <glm/gtx/string_cast.hpp>
|
||||
#include <fstream>
|
||||
#include <memory>
|
||||
#include <optional>
|
||||
|
||||
#ifdef WIN32
|
||||
#define _USE_MATH_DEFINES
|
||||
@@ -54,27 +55,6 @@
|
||||
#include <math.h>
|
||||
|
||||
namespace {
|
||||
static const char* _loggerCat = "RenderableAtmosphere";
|
||||
|
||||
constexpr const char* KeyShadowGroup = "ShadowGroup";
|
||||
constexpr const char* KeyShadowSource = "Source";
|
||||
constexpr const char* KeyShadowCaster = "Caster";
|
||||
|
||||
constexpr const char* KeyPlanetRadius = "PlanetRadius";
|
||||
constexpr const char* KeyAverageGroundReflectance = "PlanetAverageGroundReflectance";
|
||||
constexpr const char* KeyRayleigh = "Rayleigh";
|
||||
constexpr const char* KeyRayleighHeightScale = "H_R";
|
||||
constexpr const char* KeyOzone = "Ozone";
|
||||
constexpr const char* KeyOzoneHeightScale = "H_O";
|
||||
constexpr const char* KeyMie = "Mie";
|
||||
constexpr const char* KeyMieHeightScale = "H_M";
|
||||
constexpr const char* KeyMiePhaseConstant = "G";
|
||||
constexpr const char* KeyImage = "Image";
|
||||
constexpr const char* KeyToneMappingOp = "ToneMapping";
|
||||
constexpr const char* KeyATMDebug = "Debug";
|
||||
constexpr const char* KeyTextureScale = "PreCalculatedTextureScale";
|
||||
constexpr const char* KeySaveTextures = "SaveCalculatedTextures";
|
||||
|
||||
constexpr openspace::properties::Property::PropertyInfo AtmosphereHeightInfo = {
|
||||
"AtmosphereHeight",
|
||||
"Atmosphere Height (KM)",
|
||||
@@ -174,238 +154,97 @@ namespace {
|
||||
"Enable Hard Shadows for Eclipses",
|
||||
"Enable/Disables hard shadows through the atmosphere"
|
||||
};
|
||||
|
||||
|
||||
struct [[codegen::Dictionary(RenderableAtmosphere)]] Parameters {
|
||||
struct ShadowGroup {
|
||||
// Individual light sources
|
||||
struct SourceElement {
|
||||
// The scene graph node name of the source
|
||||
std::string name;
|
||||
// The radius of the object in meters
|
||||
double radius;
|
||||
};
|
||||
// A list of light sources
|
||||
std::vector<SourceElement> sources;
|
||||
|
||||
// Individual shadow casters
|
||||
struct CasterElement {
|
||||
// The scene graph node name of the source
|
||||
std::string name;
|
||||
// The radius of the object in meters
|
||||
double radius;
|
||||
};
|
||||
|
||||
// A list of objects that cast light on this atmosphere
|
||||
std::vector<CasterElement> casters;
|
||||
};
|
||||
// Declares shadow groups, meaning which nodes are considered in shadow calculations
|
||||
std::optional<ShadowGroup> shadowGroup;
|
||||
|
||||
// [[codegen::verbatim(AtmosphereHeightInfo.description)]]
|
||||
float atmosphereHeight;
|
||||
|
||||
// The radius of the planet in meters
|
||||
float planetRadius;
|
||||
|
||||
float planetAverageGroundReflectance;
|
||||
|
||||
// [[codegen::verbatim(SunIntensityInfo.description)]]
|
||||
std::optional<float> sunIntensity;
|
||||
|
||||
// [[codegen::verbatim(MieScatteringExtinctionPropCoeffInfo.description)]]
|
||||
std::optional<float> mieScatteringExtinctionPropCoefficient;
|
||||
|
||||
// [[codegen::verbatim(GroundRadianceEmittioninfo.description)]]
|
||||
float groundRadianceEmission;
|
||||
|
||||
struct Rayleigh {
|
||||
struct Coefficients {
|
||||
glm::dvec3 wavelengths;
|
||||
glm::dvec3 scattering;
|
||||
};
|
||||
Coefficients coefficients;
|
||||
float heightScale [[codegen::key("H_R")]];
|
||||
};
|
||||
Rayleigh rayleigh;
|
||||
|
||||
struct Ozone {
|
||||
struct Coefficients {
|
||||
std::optional<glm::vec3> extinction;
|
||||
};
|
||||
std::optional<Coefficients> coefficients;
|
||||
std::optional<float> heightScale [[codegen::key("H_O")]];
|
||||
};
|
||||
std::optional<Ozone> ozone;
|
||||
|
||||
struct Mie {
|
||||
struct Coefficients {
|
||||
glm::dvec3 scattering;
|
||||
glm::dvec3 extinction;
|
||||
};
|
||||
Coefficients coefficients;
|
||||
float heightScale [[codegen::key("H_M")]];
|
||||
float phaseConstant [[codegen::key("G"), codegen::inrange(-1.0, 1.0)]];
|
||||
};
|
||||
Mie mie;
|
||||
|
||||
struct ATMDebug {
|
||||
std::optional<float> preCalculatedTextureScale [[codegen::inrange(0.0, 1.0)]];
|
||||
std::optional<bool> saveCalculatedTextures;
|
||||
};
|
||||
std::optional<ATMDebug> debug;
|
||||
};
|
||||
#include "renderableatmosphere_codegen.cpp"
|
||||
|
||||
} // namespace
|
||||
|
||||
namespace openspace {
|
||||
|
||||
documentation::Documentation RenderableAtmosphere::Documentation() {
|
||||
using namespace documentation;
|
||||
|
||||
TableVerifier* shadowGroupTable = new TableVerifier({
|
||||
{
|
||||
"Sources",
|
||||
new TableVerifier({
|
||||
{
|
||||
"*",
|
||||
new TableVerifier({
|
||||
{
|
||||
"Name",
|
||||
new StringVerifier,
|
||||
Optional::No,
|
||||
"The scene graph node name of the source"
|
||||
},
|
||||
{
|
||||
"Radius",
|
||||
new DoubleVerifier,
|
||||
Optional::No,
|
||||
"The radius of the object in meters"
|
||||
}
|
||||
}),
|
||||
Optional::Yes,
|
||||
"Individual light sources"
|
||||
}
|
||||
}),
|
||||
Optional::No,
|
||||
"A list of light sources"
|
||||
},
|
||||
{
|
||||
"Casters",
|
||||
new TableVerifier({
|
||||
{
|
||||
"*",
|
||||
new TableVerifier({
|
||||
{
|
||||
"Name",
|
||||
new StringVerifier,
|
||||
Optional::No,
|
||||
"The scene graph node name of the caster"
|
||||
},
|
||||
{
|
||||
"Radius",
|
||||
new DoubleVerifier,
|
||||
Optional::No,
|
||||
"The radius of the object in meters"
|
||||
}
|
||||
}),
|
||||
Optional::Yes,
|
||||
"Individual shadow casters"
|
||||
}
|
||||
}),
|
||||
Optional::No,
|
||||
"A list of objects that cast light on this atmosphere"
|
||||
}
|
||||
});
|
||||
|
||||
TableVerifier* rayleighTable = new TableVerifier({
|
||||
{
|
||||
"Coefficients",
|
||||
new TableVerifier({
|
||||
{
|
||||
"Wavelengths",
|
||||
new DoubleVector3Verifier,
|
||||
Optional::Yes,
|
||||
""
|
||||
},
|
||||
{
|
||||
"Scattering",
|
||||
new DoubleVector3Verifier,
|
||||
Optional::No,
|
||||
""
|
||||
}
|
||||
}),
|
||||
Optional::No,
|
||||
""
|
||||
},
|
||||
{
|
||||
KeyRayleighHeightScale,
|
||||
new DoubleVerifier,
|
||||
Optional::No,
|
||||
""
|
||||
},
|
||||
});
|
||||
|
||||
TableVerifier* ozoneTable = new TableVerifier({
|
||||
{
|
||||
KeyOzoneHeightScale,
|
||||
new DoubleVerifier,
|
||||
Optional::Yes,
|
||||
""
|
||||
},
|
||||
{
|
||||
"Coefficients",
|
||||
new TableVerifier({
|
||||
{
|
||||
"Extinction",
|
||||
new DoubleVector4Verifier,
|
||||
Optional::Yes,
|
||||
""
|
||||
}
|
||||
}),
|
||||
Optional::Yes,
|
||||
""
|
||||
}
|
||||
});
|
||||
|
||||
TableVerifier* mieTable = new TableVerifier({
|
||||
{
|
||||
KeyMieHeightScale,
|
||||
new DoubleVerifier,
|
||||
Optional::No,
|
||||
""
|
||||
},
|
||||
{
|
||||
"Coefficients",
|
||||
new TableVerifier({
|
||||
{
|
||||
"Scattering",
|
||||
new DoubleVector3Verifier,
|
||||
Optional::No,
|
||||
""
|
||||
},
|
||||
{
|
||||
"Extinction",
|
||||
new DoubleVector3Verifier,
|
||||
Optional::No,
|
||||
""
|
||||
}
|
||||
}),
|
||||
Optional::No,
|
||||
""
|
||||
},
|
||||
{
|
||||
KeyMiePhaseConstant,
|
||||
new DoubleInRangeVerifier(-1.0, 1.0),
|
||||
Optional::No,
|
||||
""
|
||||
}
|
||||
});
|
||||
|
||||
return {
|
||||
"RenderableAtmosphere",
|
||||
"atmosphere_renderable_atmosphere",
|
||||
{
|
||||
{
|
||||
KeyShadowGroup,
|
||||
shadowGroupTable,
|
||||
Optional::Yes,
|
||||
"Declares shadow groups, meaning which nodes are considered in shadow "
|
||||
"calculations"
|
||||
},
|
||||
{
|
||||
AtmosphereHeightInfo.identifier,
|
||||
new DoubleVerifier,
|
||||
Optional::No,
|
||||
AtmosphereHeightInfo.description
|
||||
},
|
||||
{
|
||||
KeyPlanetRadius,
|
||||
new DoubleVerifier,
|
||||
Optional::No,
|
||||
"The radius of the planet in meters"
|
||||
},
|
||||
{
|
||||
KeyAverageGroundReflectance,
|
||||
new DoubleVerifier,
|
||||
Optional::No,
|
||||
""
|
||||
},
|
||||
{
|
||||
SunIntensityInfo.identifier,
|
||||
new DoubleVerifier,
|
||||
Optional::Yes,
|
||||
SunIntensityInfo.description
|
||||
},
|
||||
{
|
||||
MieScatteringExtinctionPropCoeffInfo.identifier,
|
||||
new DoubleVerifier,
|
||||
Optional::Yes,
|
||||
MieScatteringExtinctionPropCoeffInfo.description
|
||||
},
|
||||
{
|
||||
GroundRadianceEmittioninfo.identifier,
|
||||
new DoubleVerifier,
|
||||
Optional::No,
|
||||
GroundRadianceEmittioninfo.description
|
||||
},
|
||||
{
|
||||
KeyRayleigh,
|
||||
rayleighTable,
|
||||
Optional::No,
|
||||
""
|
||||
},
|
||||
{
|
||||
KeyOzone,
|
||||
ozoneTable,
|
||||
Optional::Yes,
|
||||
""
|
||||
},
|
||||
{
|
||||
KeyMie,
|
||||
mieTable,
|
||||
Optional::No,
|
||||
""
|
||||
},
|
||||
{
|
||||
KeyATMDebug,
|
||||
new TableVerifier({
|
||||
{
|
||||
KeyTextureScale,
|
||||
new DoubleInRangeVerifier(0.0, 1.0),
|
||||
Optional::Yes,
|
||||
""
|
||||
},
|
||||
{
|
||||
KeySaveTextures,
|
||||
new BoolVerifier,
|
||||
Optional::Yes,
|
||||
""
|
||||
}
|
||||
}),
|
||||
Optional::Yes,
|
||||
""
|
||||
}
|
||||
}
|
||||
};
|
||||
documentation::Documentation doc = codegen::doc<Parameters>();
|
||||
doc.id = "atmosphere_renderable_atmosphere";
|
||||
return doc;
|
||||
}
|
||||
|
||||
RenderableAtmosphere::RenderableAtmosphere(const ghoul::Dictionary& dictionary)
|
||||
@@ -438,139 +277,6 @@ RenderableAtmosphere::RenderableAtmosphere(const ghoul::Dictionary& dictionary)
|
||||
, _sunFollowingCameraEnabled(EnableSunOnCameraPositionInfo, false)
|
||||
, _hardShadowsEnabled(EclipseHardShadowsInfo, false)
|
||||
{
|
||||
documentation::testSpecificationAndThrow(
|
||||
Documentation(),
|
||||
dictionary,
|
||||
"RenderableAtmosphere"
|
||||
);
|
||||
|
||||
//================================================================
|
||||
//======== Reads Shadow (Eclipses) Entries in asset file =========
|
||||
//================================================================
|
||||
if (dictionary.hasKey(KeyShadowGroup)) {
|
||||
ghoul::Dictionary shadowDictionary =
|
||||
dictionary.value<ghoul::Dictionary>(KeyShadowGroup);
|
||||
|
||||
std::vector<std::pair<std::string, double>> sourceArray;
|
||||
ghoul::Dictionary sources = shadowDictionary.value<ghoul::Dictionary>("Sources");
|
||||
for (std::string_view k : sources.keys()) {
|
||||
ghoul::Dictionary source = sources.value<ghoul::Dictionary>(k);
|
||||
|
||||
std::string name = source.value<std::string>("Name");
|
||||
double radius = source.value<double>("Radius");
|
||||
sourceArray.emplace_back(name, radius);
|
||||
}
|
||||
|
||||
std::vector<std::pair<std::string, double>> casterArray;
|
||||
ghoul::Dictionary casters = shadowDictionary.value<ghoul::Dictionary>("Casters");
|
||||
for (std::string_view k : casters.keys()) {
|
||||
ghoul::Dictionary caster = casters.value<ghoul::Dictionary>(k);
|
||||
|
||||
std::string name = caster.value<std::string>("Name");
|
||||
double radius = caster.value<double>("Radius");
|
||||
casterArray.emplace_back(name, radius);
|
||||
}
|
||||
|
||||
_shadowEnabled = !sourceArray.empty() && !casterArray.empty();
|
||||
for (const std::pair<std::string, double>& source : sourceArray) {
|
||||
for (const std::pair<std::string, double>& caster : casterArray) {
|
||||
ShadowConfiguration sc;
|
||||
sc.source = source;
|
||||
sc.caster = caster;
|
||||
_shadowConfArray.push_back(sc);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//================================================================
|
||||
//========== Reads Atmosphere Entries from asset file ============
|
||||
//================================================================
|
||||
_atmosphereHeight = static_cast<float>(
|
||||
dictionary.value<double>(AtmosphereHeightInfo.identifier)
|
||||
);
|
||||
_planetRadius = static_cast<float>(dictionary.value<double>(KeyPlanetRadius));
|
||||
_groundAverageReflectance = static_cast<float>(
|
||||
dictionary.value<double>(KeyAverageGroundReflectance)
|
||||
);
|
||||
_groundRadianceEmission = static_cast<float>(
|
||||
dictionary.value<double>(GroundRadianceEmittioninfo.identifier)
|
||||
);
|
||||
|
||||
if (dictionary.hasKey(SunIntensityInfo.identifier)) {
|
||||
_sunIntensity = static_cast<float>(
|
||||
dictionary.value<double>(SunIntensityInfo.identifier)
|
||||
);
|
||||
}
|
||||
|
||||
if (dictionary.hasKey(MieScatteringExtinctionPropCoeffInfo.identifier)) {
|
||||
_mieScattExtPropCoefProp = static_cast<float>(
|
||||
dictionary.value<double>(MieScatteringExtinctionPropCoeffInfo.identifier)
|
||||
);
|
||||
}
|
||||
|
||||
{
|
||||
ghoul::Dictionary rayleighDict = dictionary.value<ghoul::Dictionary>(KeyRayleigh);
|
||||
|
||||
ghoul::Dictionary coeffs = rayleighDict.value<ghoul::Dictionary>("Coefficients");
|
||||
_rayleighScatteringCoeff = coeffs.value<glm::dvec3>("Scattering");
|
||||
|
||||
_rayleighHeightScale = static_cast<float>(
|
||||
rayleighDict.value<double>(KeyRayleighHeightScale)
|
||||
);
|
||||
}
|
||||
|
||||
if (dictionary.hasValue<ghoul::Dictionary>(KeyOzone)) {
|
||||
ghoul::Dictionary ozoneDict = dictionary.value<ghoul::Dictionary>(KeyOzone);
|
||||
|
||||
if (ozoneDict.hasValue<double>(KeyOzoneHeightScale)) {
|
||||
_ozoneHeightScale = static_cast<float>(
|
||||
ozoneDict.value<double>(KeyOzoneHeightScale)
|
||||
);
|
||||
_ozoneEnabled = true;
|
||||
}
|
||||
|
||||
if (ozoneDict.hasValue<ghoul::Dictionary>("Coefficients")) {
|
||||
ghoul::Dictionary coeff = ozoneDict.value<ghoul::Dictionary>("Coefficients");
|
||||
if (coeff.hasValue<glm::dvec3>("Extinction")) {
|
||||
_ozoneCoeff = coeff.value<glm::dvec3>("Extinction");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
{
|
||||
ghoul::Dictionary mieDict = dictionary.value<ghoul::Dictionary>(KeyMie);
|
||||
_mieHeightScale = static_cast<float>(mieDict.value<double>(KeyMieHeightScale));
|
||||
|
||||
ghoul::Dictionary coeffs = mieDict.value<ghoul::Dictionary>("Coefficients");
|
||||
|
||||
_mieScatteringCoeff = coeffs.value<glm::dvec3>("Scattering");
|
||||
_mieExtinctionCoeff = coeffs.value<glm::dvec3>("Extinction");
|
||||
|
||||
_miePhaseConstant = static_cast<float>(
|
||||
mieDict.value<double>(KeyMiePhaseConstant)
|
||||
);
|
||||
}
|
||||
|
||||
if (dictionary.hasValue<ghoul::Dictionary>(KeyATMDebug)) {
|
||||
ghoul::Dictionary debugDict = dictionary.value<ghoul::Dictionary>(KeyATMDebug);
|
||||
if (debugDict.hasKey(KeyTextureScale)) {
|
||||
_preCalculatedTexturesScale = static_cast<float>(
|
||||
debugDict.value<double>(KeyTextureScale)
|
||||
);
|
||||
LDEBUG(fmt::format(
|
||||
"Atmosphere Texture Scaled to {}", _preCalculatedTexturesScale
|
||||
));
|
||||
}
|
||||
|
||||
if (debugDict.hasKey(KeySaveTextures)) {
|
||||
_saveCalculationsToTexture = debugDict.value<bool>(KeySaveTextures);
|
||||
LDEBUG("Saving Precalculated Atmosphere Textures");
|
||||
}
|
||||
}
|
||||
|
||||
//========================================================
|
||||
//============== Atmosphere Properties ===================
|
||||
//========================================================
|
||||
auto updateWithCalculation = [this]() {
|
||||
_deferredCasterNeedsUpdate = true;
|
||||
_deferredCasterNeedsCalculation = true;
|
||||
@@ -579,48 +285,93 @@ RenderableAtmosphere::RenderableAtmosphere(const ghoul::Dictionary& dictionary)
|
||||
_deferredCasterNeedsUpdate = true;
|
||||
};
|
||||
|
||||
const Parameters p = codegen::bake<Parameters>(dictionary);
|
||||
|
||||
_shadowEnabled = p.shadowGroup.has_value();
|
||||
if (_shadowEnabled) {
|
||||
for (const Parameters::ShadowGroup::SourceElement& s : p.shadowGroup->sources) {
|
||||
for (const Parameters::ShadowGroup::CasterElement& c :
|
||||
p.shadowGroup->casters)
|
||||
{
|
||||
ShadowConfiguration sc;
|
||||
sc.source = std::pair(s.name, s.radius);
|
||||
sc.caster = std::pair(c.name, c.radius);
|
||||
_shadowConfArray.push_back(sc);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
_atmosphereHeight = p.atmosphereHeight;
|
||||
_atmosphereHeight.onChange(updateWithCalculation);
|
||||
addProperty(_atmosphereHeight);
|
||||
|
||||
_planetRadius = p.planetRadius;
|
||||
|
||||
_groundAverageReflectance = p.planetAverageGroundReflectance;
|
||||
_groundAverageReflectance.onChange(updateWithCalculation);
|
||||
addProperty(_groundAverageReflectance);
|
||||
|
||||
_groundRadianceEmission.onChange(updateWithoutCalculation);
|
||||
addProperty(_groundRadianceEmission);
|
||||
_sunIntensity = p.sunIntensity.value_or(_sunIntensity);
|
||||
_sunIntensity.onChange(updateWithoutCalculation);
|
||||
addProperty(_sunIntensity);
|
||||
|
||||
_rayleighHeightScale.onChange(updateWithCalculation);
|
||||
addProperty(_rayleighHeightScale);
|
||||
_mieScattExtPropCoefProp =
|
||||
p.mieScatteringExtinctionPropCoefficient.value_or(_mieScattExtPropCoefProp);
|
||||
|
||||
_rayleighScatteringCoeff = p.rayleigh.coefficients.scattering;
|
||||
_rayleighScatteringCoeff.onChange(updateWithCalculation);
|
||||
addProperty(_rayleighScatteringCoeff);
|
||||
|
||||
_rayleighHeightScale = p.rayleigh.heightScale;
|
||||
_rayleighHeightScale.onChange(updateWithCalculation);
|
||||
addProperty(_rayleighHeightScale);
|
||||
|
||||
if (p.ozone.has_value()) {
|
||||
_ozoneHeightScale = p.ozone->heightScale.value_or(_ozoneHeightScale);
|
||||
_ozoneEnabled = p.ozone->heightScale.has_value();
|
||||
|
||||
if (p.ozone->coefficients.has_value()) {
|
||||
_ozoneCoeff = p.ozone->coefficients->extinction.value_or(_ozoneCoeff);
|
||||
}
|
||||
}
|
||||
_ozoneEnabled.onChange(updateWithCalculation);
|
||||
addProperty(_ozoneEnabled);
|
||||
|
||||
_ozoneHeightScale.onChange(updateWithCalculation);
|
||||
addProperty(_ozoneHeightScale);
|
||||
|
||||
_ozoneCoeff.onChange(updateWithCalculation);
|
||||
addProperty(_ozoneCoeff);
|
||||
|
||||
_mieHeightScale = p.mie.heightScale;
|
||||
_mieHeightScale.onChange(updateWithCalculation);
|
||||
addProperty(_mieHeightScale);
|
||||
|
||||
_mieScatteringCoeff = p.mie.coefficients.scattering;
|
||||
_mieScatteringCoeff.onChange(updateWithCalculation);
|
||||
addProperty(_mieScatteringCoeff);
|
||||
|
||||
_mieExtinctionCoeff = p.mie.coefficients.extinction;
|
||||
_miePhaseConstant = p.mie.phaseConstant;
|
||||
_miePhaseConstant.onChange(updateWithCalculation);
|
||||
addProperty(_miePhaseConstant);
|
||||
|
||||
_mieScatteringExtinctionPropCoefficient =
|
||||
_mieScattExtPropCoefProp != 1.f ? _mieScattExtPropCoefProp :
|
||||
_mieScatteringCoeff.value().x / _mieExtinctionCoeff.x;
|
||||
|
||||
_mieScatteringExtinctionPropCoefficient.onChange(updateWithCalculation);
|
||||
addProperty(_mieScatteringExtinctionPropCoefficient);
|
||||
|
||||
if (p.debug.has_value()) {
|
||||
_preCalculatedTexturesScale =
|
||||
p.debug->preCalculatedTextureScale.value_or(_preCalculatedTexturesScale);
|
||||
|
||||
_miePhaseConstant.onChange(updateWithCalculation);
|
||||
addProperty(_miePhaseConstant);
|
||||
_saveCalculationsToTexture =
|
||||
p.debug->saveCalculatedTextures.value_or(_saveCalculationsToTexture);
|
||||
}
|
||||
|
||||
_sunIntensity.onChange(updateWithoutCalculation);
|
||||
addProperty(_sunIntensity);
|
||||
_groundRadianceEmission = p.groundRadianceEmission;
|
||||
_groundRadianceEmission.onChange(updateWithoutCalculation);
|
||||
addProperty(_groundRadianceEmission);
|
||||
|
||||
_sunFollowingCameraEnabled.onChange(updateWithoutCalculation);
|
||||
addProperty(_sunFollowingCameraEnabled);
|
||||
|
||||
@@ -85,66 +85,36 @@ namespace {
|
||||
"If a scene graph node is selected as type, this value specifies the name of the "
|
||||
"node that is to be used as the destination for computing the angle."
|
||||
};
|
||||
|
||||
struct [[codegen::Dictionary(DashboardItemAngle)]] Parameters {
|
||||
enum class Type {
|
||||
Node,
|
||||
Focus,
|
||||
Camera
|
||||
};
|
||||
|
||||
// [[codegen::verbatim(SourceTypeInfo.description)]]
|
||||
std::optional<Type> sourceType;
|
||||
// [[codegen::verbatim(SourceNodeNameInfo.description)]]
|
||||
std::optional<std::string> sourceNodeName;
|
||||
// [[codegen::verbatim(ReferenceTypeInfo.description)]]
|
||||
Type referenceType;
|
||||
// [[codegen::verbatim(ReferenceNodeNameInfo.description)]]
|
||||
std::optional<std::string> referenceNodeName;
|
||||
// [[codegen::verbatim(DestinationTypeInfo.description)]]
|
||||
std::optional<Type> destinationType;
|
||||
// [[codegen::verbatim(DestinationNodeNameInfo.description)]]
|
||||
std::optional<std::string> destinationNodeName;
|
||||
};
|
||||
#include "dashboarditemangle_codegen.cpp"
|
||||
} // namespace
|
||||
|
||||
namespace openspace {
|
||||
|
||||
documentation::Documentation DashboardItemAngle::Documentation() {
|
||||
using namespace documentation;
|
||||
|
||||
return {
|
||||
"DashboardItem Angle",
|
||||
"base_dashboarditem_angle",
|
||||
{
|
||||
{
|
||||
"Type",
|
||||
new StringEqualVerifier("DashboardItemAngle"),
|
||||
Optional::No
|
||||
},
|
||||
{
|
||||
SourceTypeInfo.identifier,
|
||||
new StringInListVerifier({
|
||||
"Node", "Focus", "Camera"
|
||||
}),
|
||||
Optional::Yes,
|
||||
SourceTypeInfo.description
|
||||
},
|
||||
{
|
||||
SourceNodeNameInfo.identifier,
|
||||
new StringVerifier,
|
||||
Optional::Yes,
|
||||
SourceNodeNameInfo.description
|
||||
},
|
||||
{
|
||||
ReferenceTypeInfo.identifier,
|
||||
new StringInListVerifier({
|
||||
"Node", "Focus", "Camera"
|
||||
}),
|
||||
Optional::No,
|
||||
ReferenceTypeInfo.description
|
||||
},
|
||||
{
|
||||
ReferenceNodeNameInfo.identifier,
|
||||
new StringVerifier,
|
||||
Optional::Yes,
|
||||
ReferenceNodeNameInfo.description
|
||||
},
|
||||
{
|
||||
DestinationTypeInfo.identifier,
|
||||
new StringInListVerifier({
|
||||
"Node", "Focus", "Camera"
|
||||
}),
|
||||
Optional::Yes,
|
||||
DestinationTypeInfo.description
|
||||
},
|
||||
{
|
||||
DestinationNodeNameInfo.identifier,
|
||||
new StringVerifier,
|
||||
Optional::Yes,
|
||||
DestinationNodeNameInfo.description
|
||||
}
|
||||
}
|
||||
};
|
||||
documentation::Documentation doc = codegen::doc<Parameters>();
|
||||
doc.id = "base_dashboarditem_angle";
|
||||
return doc;
|
||||
}
|
||||
|
||||
DashboardItemAngle::DashboardItemAngle(const ghoul::Dictionary& dictionary)
|
||||
@@ -174,11 +144,7 @@ DashboardItemAngle::DashboardItemAngle(const ghoul::Dictionary& dictionary)
|
||||
nullptr
|
||||
}
|
||||
{
|
||||
documentation::testSpecificationAndThrow(
|
||||
Documentation(),
|
||||
dictionary,
|
||||
"DashboardItemAngle"
|
||||
);
|
||||
const Parameters p = codegen::bake<Parameters>(dictionary);
|
||||
|
||||
_source.type.addOptions({
|
||||
{ Type::Node, "Node" },
|
||||
@@ -190,16 +156,17 @@ DashboardItemAngle::DashboardItemAngle(const ghoul::Dictionary& dictionary)
|
||||
properties::Property::Visibility(_source.type == Type::Node)
|
||||
);
|
||||
});
|
||||
if (dictionary.hasKey(SourceTypeInfo.identifier)) {
|
||||
std::string value = dictionary.value<std::string>(SourceTypeInfo.identifier);
|
||||
if (value == "Node") {
|
||||
_source.type = Type::Node;
|
||||
}
|
||||
else if (value == "Focus") {
|
||||
_source.type = Type::Focus;
|
||||
}
|
||||
else {
|
||||
_source.type = Type::Camera;
|
||||
if (p.sourceType.has_value()) {
|
||||
switch (*p.sourceType) {
|
||||
case Parameters::Type::Node:
|
||||
_source.type = Type::Node;
|
||||
break;
|
||||
case Parameters::Type::Focus:
|
||||
_source.type = Type::Focus;
|
||||
break;
|
||||
default:
|
||||
_source.type = Type::Camera;
|
||||
break;
|
||||
}
|
||||
}
|
||||
else {
|
||||
@@ -209,10 +176,8 @@ DashboardItemAngle::DashboardItemAngle(const ghoul::Dictionary& dictionary)
|
||||
|
||||
_source.nodeName.onChange([this]() { _source.node = nullptr; });
|
||||
if (_source.type == Type::Node) {
|
||||
if (dictionary.hasKey(SourceNodeNameInfo.identifier)) {
|
||||
_source.nodeName = dictionary.value<std::string>(
|
||||
SourceNodeNameInfo.identifier
|
||||
);
|
||||
if (p.sourceNodeName.has_value()) {
|
||||
_source.nodeName = *p.sourceNodeName;
|
||||
}
|
||||
else {
|
||||
LERRORC(
|
||||
@@ -234,24 +199,23 @@ DashboardItemAngle::DashboardItemAngle(const ghoul::Dictionary& dictionary)
|
||||
properties::Property::Visibility(_reference.type == Type::Node)
|
||||
);
|
||||
});
|
||||
std::string value = dictionary.value<std::string>(ReferenceTypeInfo.identifier);
|
||||
if (value == "Node") {
|
||||
_reference.type = Type::Node;
|
||||
}
|
||||
else if (value == "Focus") {
|
||||
_reference.type = Type::Focus;
|
||||
}
|
||||
else {
|
||||
_reference.type = Type::Camera;
|
||||
switch (p.referenceType) {
|
||||
case Parameters::Type::Node:
|
||||
_reference.type = Type::Node;
|
||||
break;
|
||||
case Parameters::Type::Focus:
|
||||
_reference.type = Type::Focus;
|
||||
break;
|
||||
default:
|
||||
_reference.type = Type::Camera;
|
||||
break;
|
||||
}
|
||||
addProperty(_reference.type);
|
||||
|
||||
_reference.nodeName.onChange([this]() { _reference.node = nullptr; });
|
||||
if (_reference.type == Type::Node) {
|
||||
if (dictionary.hasKey(ReferenceNodeNameInfo.identifier)) {
|
||||
_reference.nodeName = dictionary.value<std::string>(
|
||||
ReferenceNodeNameInfo.identifier
|
||||
);
|
||||
if (p.referenceNodeName.has_value()) {
|
||||
_reference.nodeName = *p.referenceNodeName;
|
||||
}
|
||||
else {
|
||||
LERRORC(
|
||||
@@ -272,16 +236,17 @@ DashboardItemAngle::DashboardItemAngle(const ghoul::Dictionary& dictionary)
|
||||
properties::Property::Visibility(_source.type == Type::Node)
|
||||
);
|
||||
});
|
||||
if (dictionary.hasKey(DestinationTypeInfo.identifier)) {
|
||||
std::string type = dictionary.value<std::string>(DestinationTypeInfo.identifier);
|
||||
if (type == "Node") {
|
||||
_destination.type = Type::Node;
|
||||
}
|
||||
else if (type == "Focus") {
|
||||
_destination.type = Type::Focus;
|
||||
}
|
||||
else {
|
||||
_destination.type = Type::Camera;
|
||||
if (p.destinationType.has_value()) {
|
||||
switch (*p.destinationType) {
|
||||
case Parameters::Type::Node:
|
||||
_destination.type = Type::Node;
|
||||
break;
|
||||
case Parameters::Type::Focus:
|
||||
_destination.type = Type::Focus;
|
||||
break;
|
||||
default:
|
||||
_destination.type = Type::Camera;
|
||||
break;
|
||||
}
|
||||
}
|
||||
else {
|
||||
@@ -290,10 +255,8 @@ DashboardItemAngle::DashboardItemAngle(const ghoul::Dictionary& dictionary)
|
||||
addProperty(_destination.type);
|
||||
_destination.nodeName.onChange([this]() { _destination.node = nullptr; });
|
||||
if (_destination.type == Type::Node) {
|
||||
if (dictionary.hasKey(DestinationNodeNameInfo.identifier)) {
|
||||
_destination.nodeName = dictionary.value<std::string>(
|
||||
DestinationNodeNameInfo.identifier
|
||||
);
|
||||
if (p.destinationNodeName.has_value()) {
|
||||
_destination.nodeName = *p.destinationNodeName;
|
||||
}
|
||||
else {
|
||||
LERRORC(
|
||||
|
||||
@@ -51,35 +51,23 @@ namespace {
|
||||
"https://naif.jpl.nasa.gov/pub/naif/toolkit_docs/C/cspice/timout_c.html for full "
|
||||
"information about how to structure this format"
|
||||
};
|
||||
|
||||
struct [[codegen::Dictionary(DashboardItemDate)]] Parameters {
|
||||
// [[codegen::verbatim(FormatStringInfo.description)]]
|
||||
std::optional<std::string> formatString;
|
||||
|
||||
// [[codegen::verbatim(TimeFormatInfo.description)]]
|
||||
std::optional<std::string> timeFormat;
|
||||
};
|
||||
#include "dashboarditemdate_codegen.cpp"
|
||||
} // namespace
|
||||
|
||||
namespace openspace {
|
||||
|
||||
documentation::Documentation DashboardItemDate::Documentation() {
|
||||
using namespace documentation;
|
||||
return {
|
||||
"DashboardItem Date",
|
||||
"base_dashboarditem_date",
|
||||
{
|
||||
{
|
||||
"Type",
|
||||
new StringEqualVerifier("DashboardItemDate"),
|
||||
Optional::No
|
||||
},
|
||||
{
|
||||
FormatStringInfo.identifier,
|
||||
new StringVerifier,
|
||||
Optional::Yes,
|
||||
FormatStringInfo.description
|
||||
},
|
||||
{
|
||||
TimeFormatInfo.identifier,
|
||||
new StringVerifier,
|
||||
Optional::Yes,
|
||||
TimeFormatInfo.description
|
||||
}
|
||||
}
|
||||
};
|
||||
documentation::Documentation doc = codegen::doc<Parameters>();
|
||||
doc.id = "base_dashboarditem_date";
|
||||
return doc;
|
||||
}
|
||||
|
||||
DashboardItemDate::DashboardItemDate(const ghoul::Dictionary& dictionary)
|
||||
@@ -87,20 +75,12 @@ DashboardItemDate::DashboardItemDate(const ghoul::Dictionary& dictionary)
|
||||
, _formatString(FormatStringInfo, "Date: {} UTC")
|
||||
, _timeFormat(TimeFormatInfo, "YYYY MON DDTHR:MN:SC.### ::RND")
|
||||
{
|
||||
documentation::testSpecificationAndThrow(
|
||||
Documentation(),
|
||||
dictionary,
|
||||
"DashboardItemDate"
|
||||
);
|
||||
const Parameters p = codegen::bake<Parameters>(dictionary);
|
||||
|
||||
if (dictionary.hasKey(FormatStringInfo.identifier)) {
|
||||
_formatString = dictionary.value<std::string>(FormatStringInfo.identifier);
|
||||
}
|
||||
_formatString = p.formatString.value_or(_formatString);
|
||||
addProperty(_formatString);
|
||||
|
||||
if (dictionary.hasKey(TimeFormatInfo.identifier)) {
|
||||
_timeFormat = dictionary.value<std::string>(TimeFormatInfo.identifier);
|
||||
}
|
||||
_timeFormat = p.timeFormat.value_or(_timeFormat);
|
||||
addProperty(_timeFormat);
|
||||
}
|
||||
|
||||
|
||||
@@ -104,69 +104,45 @@ namespace {
|
||||
);
|
||||
return res;
|
||||
}
|
||||
|
||||
struct [[codegen::Dictionary(DashboardItemDistance)]] Parameters {
|
||||
enum class TypeInfo {
|
||||
Node,
|
||||
NodeSurface [[codegen::key("Node Surface")]],
|
||||
Focus,
|
||||
Camera
|
||||
};
|
||||
|
||||
// [[codegen::verbatim(SourceTypeInfo.description)]]
|
||||
std::optional<TypeInfo> sourceType;
|
||||
|
||||
// [[codegen::verbatim(SourceNodeNameInfo.description)]]
|
||||
std::optional<std::string> sourceNodeName;
|
||||
|
||||
// [[codegen::verbatim(DestinationTypeInfo.description)]]
|
||||
std::optional<TypeInfo> destinationType;
|
||||
|
||||
// [[codegen::verbatim(DestinationNodeNameInfo.description)]]
|
||||
std::optional<std::string> destinationNodeName;
|
||||
|
||||
// [[codegen::verbatim(SimplificationInfo.description)]]
|
||||
std::optional<bool> simplification;
|
||||
|
||||
// [[codegen::verbatim(RequestedUnitInfo.description)]]
|
||||
std::optional<std::string> requestedUnit [[codegen::inlist(unitList())]];
|
||||
|
||||
// [[codegen::verbatim(FormatStringInfo.description)]]
|
||||
std::optional<std::string> formatString;
|
||||
};
|
||||
#include "dashboarditemdistance_codegen.cpp"
|
||||
} // namespace
|
||||
|
||||
namespace openspace {
|
||||
|
||||
documentation::Documentation DashboardItemDistance::Documentation() {
|
||||
using namespace documentation;
|
||||
return {
|
||||
"DashboardItem Distance",
|
||||
"base_dashboarditem_distance",
|
||||
{
|
||||
{
|
||||
"Type",
|
||||
new StringEqualVerifier("DashboardItemDistance"),
|
||||
Optional::No
|
||||
},
|
||||
{
|
||||
SourceTypeInfo.identifier,
|
||||
new StringInListVerifier({
|
||||
"Node", "Node Surface", "Focus", "Camera"
|
||||
}),
|
||||
Optional::Yes,
|
||||
SourceTypeInfo.description
|
||||
},
|
||||
{
|
||||
SourceNodeNameInfo.identifier,
|
||||
new StringVerifier,
|
||||
Optional::Yes,
|
||||
SourceNodeNameInfo.description
|
||||
},
|
||||
{
|
||||
DestinationTypeInfo.identifier,
|
||||
new StringInListVerifier({
|
||||
"Node", "Node Surface", "Focus", "Camera"
|
||||
}),
|
||||
Optional::Yes,
|
||||
DestinationTypeInfo.description
|
||||
},
|
||||
{
|
||||
DestinationNodeNameInfo.identifier,
|
||||
new StringVerifier,
|
||||
Optional::Yes,
|
||||
DestinationNodeNameInfo.description
|
||||
},
|
||||
{
|
||||
SimplificationInfo.identifier,
|
||||
new BoolVerifier,
|
||||
Optional::Yes,
|
||||
SimplificationInfo.description
|
||||
},
|
||||
{
|
||||
RequestedUnitInfo.identifier,
|
||||
new StringInListVerifier(unitList()),
|
||||
Optional::Yes,
|
||||
RequestedUnitInfo.description
|
||||
},
|
||||
{
|
||||
FormatStringInfo.identifier,
|
||||
new StringVerifier,
|
||||
Optional::Yes,
|
||||
FormatStringInfo.description
|
||||
}
|
||||
}
|
||||
};
|
||||
documentation::Documentation doc = codegen::doc<Parameters>();
|
||||
doc.id = "base_dashboarditem_distance";
|
||||
return doc;
|
||||
}
|
||||
|
||||
DashboardItemDistance::DashboardItemDistance(const ghoul::Dictionary& dictionary)
|
||||
@@ -191,11 +167,7 @@ DashboardItemDistance::DashboardItemDistance(const ghoul::Dictionary& dictionary
|
||||
nullptr
|
||||
}
|
||||
{
|
||||
documentation::testSpecificationAndThrow(
|
||||
Documentation(),
|
||||
dictionary,
|
||||
"DashboardItemDistance"
|
||||
);
|
||||
const Parameters p = codegen::bake<Parameters>(dictionary);
|
||||
|
||||
_source.type.addOptions({
|
||||
{ Type::Node, "Node" },
|
||||
@@ -210,22 +182,20 @@ DashboardItemDistance::DashboardItemDistance(const ghoul::Dictionary& dictionary
|
||||
)
|
||||
);
|
||||
});
|
||||
if (dictionary.hasKey(SourceTypeInfo.identifier)) {
|
||||
const std::string& value = dictionary.value<std::string>(
|
||||
SourceTypeInfo.identifier
|
||||
);
|
||||
|
||||
if (value == "Node") {
|
||||
_source.type = Type::Node;
|
||||
}
|
||||
else if (value == "Node Surface") {
|
||||
_source.type = Type::NodeSurface;
|
||||
}
|
||||
else if (value == "Focus") {
|
||||
_source.type = Type::Focus;
|
||||
}
|
||||
else {
|
||||
_source.type = Type::Camera;
|
||||
if (p.sourceType.has_value()) {
|
||||
switch (*p.sourceType) {
|
||||
case Parameters::TypeInfo::Node:
|
||||
_source.type = Type::Node;
|
||||
break;
|
||||
case Parameters::TypeInfo::NodeSurface:
|
||||
_source.type = Type::NodeSurface;
|
||||
break;
|
||||
case Parameters::TypeInfo::Focus:
|
||||
_source.type = Type::Focus;
|
||||
break;
|
||||
case Parameters::TypeInfo::Camera:
|
||||
_source.type = Type::Camera;
|
||||
break;
|
||||
}
|
||||
}
|
||||
else {
|
||||
@@ -235,10 +205,8 @@ DashboardItemDistance::DashboardItemDistance(const ghoul::Dictionary& dictionary
|
||||
|
||||
_source.nodeName.onChange([this]() { _source.node = nullptr; });
|
||||
if (_source.type == Type::Node || _source.type == Type::NodeSurface) {
|
||||
if (dictionary.hasKey(SourceNodeNameInfo.identifier)) {
|
||||
_source.nodeName = dictionary.value<std::string>(
|
||||
SourceNodeNameInfo.identifier
|
||||
);
|
||||
if (p.sourceNodeName.has_value()) {
|
||||
_source.nodeName = *p.sourceNodeName;
|
||||
}
|
||||
else {
|
||||
LERRORC(
|
||||
@@ -262,21 +230,20 @@ DashboardItemDistance::DashboardItemDistance(const ghoul::Dictionary& dictionary
|
||||
)
|
||||
);
|
||||
});
|
||||
if (dictionary.hasKey(DestinationTypeInfo.identifier)) {
|
||||
const std::string& value = dictionary.value<std::string>(
|
||||
DestinationTypeInfo.identifier
|
||||
);
|
||||
if (value == "Node") {
|
||||
_destination.type = Type::Node;
|
||||
}
|
||||
else if (value == "Node Surface") {
|
||||
_destination.type = Type::NodeSurface;
|
||||
}
|
||||
else if (value == "Focus") {
|
||||
_destination.type = Type::Focus;
|
||||
}
|
||||
else {
|
||||
_destination.type = Type::Camera;
|
||||
if (p.destinationType.has_value()) {
|
||||
switch (*p.destinationType) {
|
||||
case Parameters::TypeInfo::Node:
|
||||
_destination.type = Type::Node;
|
||||
break;
|
||||
case Parameters::TypeInfo::NodeSurface:
|
||||
_destination.type = Type::NodeSurface;
|
||||
break;
|
||||
case Parameters::TypeInfo::Focus:
|
||||
_destination.type = Type::Focus;
|
||||
break;
|
||||
case Parameters::TypeInfo::Camera:
|
||||
_destination.type = Type::Camera;
|
||||
break;
|
||||
}
|
||||
}
|
||||
else {
|
||||
@@ -285,10 +252,8 @@ DashboardItemDistance::DashboardItemDistance(const ghoul::Dictionary& dictionary
|
||||
addProperty(_destination.type);
|
||||
_destination.nodeName.onChange([this]() { _destination.node = nullptr; });
|
||||
if (_destination.type == Type::Node || _destination.type == Type::NodeSurface) {
|
||||
if (dictionary.hasKey(DestinationNodeNameInfo.identifier)) {
|
||||
_destination.nodeName = dictionary.value<std::string>(
|
||||
DestinationNodeNameInfo.identifier
|
||||
);
|
||||
if (p.destinationNodeName.has_value()) {
|
||||
_destination.nodeName = *p.destinationNodeName;
|
||||
}
|
||||
else {
|
||||
LERRORC(
|
||||
@@ -299,9 +264,7 @@ DashboardItemDistance::DashboardItemDistance(const ghoul::Dictionary& dictionary
|
||||
}
|
||||
addProperty(_destination.nodeName);
|
||||
|
||||
if (dictionary.hasKey(SimplificationInfo.identifier)) {
|
||||
_doSimplification = dictionary.value<bool>(SimplificationInfo.identifier);
|
||||
}
|
||||
_doSimplification = p.simplification.value_or(_doSimplification);
|
||||
_doSimplification.onChange([this]() {
|
||||
_requestedUnit.setVisibility(
|
||||
_doSimplification ?
|
||||
@@ -315,19 +278,14 @@ DashboardItemDistance::DashboardItemDistance(const ghoul::Dictionary& dictionary
|
||||
_requestedUnit.addOption(static_cast<int>(u), nameForDistanceUnit(u));
|
||||
}
|
||||
_requestedUnit = static_cast<int>(DistanceUnit::Meter);
|
||||
if (dictionary.hasKey(RequestedUnitInfo.identifier)) {
|
||||
const std::string& value = dictionary.value<std::string>(
|
||||
RequestedUnitInfo.identifier
|
||||
);
|
||||
DistanceUnit unit = distanceUnitFromString(value.c_str());
|
||||
if (p.requestedUnit.has_value()) {
|
||||
DistanceUnit unit = distanceUnitFromString(p.requestedUnit->c_str());
|
||||
_requestedUnit = static_cast<int>(unit);
|
||||
}
|
||||
_requestedUnit.setVisibility(properties::Property::Visibility::Hidden);
|
||||
addProperty(_requestedUnit);
|
||||
|
||||
if (dictionary.hasKey(FormatStringInfo.identifier)) {
|
||||
_formatString = dictionary.value<std::string>(FormatStringInfo.identifier);
|
||||
}
|
||||
_formatString = p.formatString.value_or(_formatString);
|
||||
addProperty(_formatString);
|
||||
|
||||
_buffer.resize(256);
|
||||
|
||||
@@ -32,6 +32,7 @@
|
||||
#include <ghoul/font/fontmanager.h>
|
||||
#include <ghoul/font/fontrenderer.h>
|
||||
#include <ghoul/misc/profiling.h>
|
||||
#include <optional>
|
||||
|
||||
namespace {
|
||||
constexpr openspace::properties::Property::PropertyInfo FrametimeInfo = {
|
||||
@@ -47,14 +48,6 @@ namespace {
|
||||
"does not use any caching, this trigger does not do anything."
|
||||
};
|
||||
|
||||
constexpr const char* ValueDtAvg = "Average Deltatime";
|
||||
constexpr const char* ValueDtExtremes = "Deltatime extremes";
|
||||
constexpr const char* ValueDtStandardDeviation = "Deltatime standard deviation";
|
||||
constexpr const char* ValueDtCov = "Deltatime coefficient of variation";
|
||||
constexpr const char* ValueFps = "Frames per second";
|
||||
constexpr const char* ValueFpsAvg = "Average frames per second";
|
||||
constexpr const char* ValueNone = "None";
|
||||
|
||||
[[ nodiscard ]] char* formatDt(std::vector<char>& buffer) {
|
||||
return fmt::format_to(
|
||||
buffer.data(),
|
||||
@@ -133,32 +126,30 @@ namespace {
|
||||
throw ghoul::MissingCaseException();
|
||||
}
|
||||
}
|
||||
|
||||
struct [[codegen::Dictionary(DashboardItemFramerate)]] Parameters {
|
||||
enum class Type {
|
||||
DtAvg [[codegen::key("Average Deltatime")]],
|
||||
DtExtremes [[codegen::key("Deltatime extremes")]],
|
||||
DtStandardDeviation [[codegen::key("Deltatime standard deviation")]],
|
||||
DtCoefficientOfVariation [[codegen::key("Deltatime coefficient of variation")]],
|
||||
FPS [[codegen::key("Frames per second")]],
|
||||
FPSAvg [[codegen::key("Average frames per second")]]
|
||||
};
|
||||
|
||||
// [[codegen::verbatim(FrametimeInfo.description)]]
|
||||
std::optional<Type> frametimeType;
|
||||
};
|
||||
#include "dashboarditemframerate_codegen.cpp"
|
||||
|
||||
} // namespace
|
||||
|
||||
namespace openspace {
|
||||
|
||||
documentation::Documentation DashboardItemFramerate::Documentation() {
|
||||
using namespace documentation;
|
||||
|
||||
return {
|
||||
"DashboardItem Framerate",
|
||||
"base_dashboarditem_framerate",
|
||||
{
|
||||
{
|
||||
"Type",
|
||||
new StringEqualVerifier("DashboardItemFramerate"),
|
||||
Optional::No
|
||||
},
|
||||
{
|
||||
FrametimeInfo.identifier,
|
||||
new StringInListVerifier({ ValueDtAvg, ValueDtExtremes,
|
||||
ValueDtStandardDeviation, ValueDtCov, ValueFps, ValueFpsAvg, ValueNone
|
||||
}),
|
||||
Optional::Yes,
|
||||
FrametimeInfo.description
|
||||
}
|
||||
}
|
||||
};
|
||||
documentation::Documentation doc = codegen::doc<Parameters>();
|
||||
doc.id = "base_dashboarditem_framerate";
|
||||
return doc;
|
||||
}
|
||||
|
||||
DashboardItemFramerate::DashboardItemFramerate(const ghoul::Dictionary& dictionary)
|
||||
@@ -166,52 +157,44 @@ DashboardItemFramerate::DashboardItemFramerate(const ghoul::Dictionary& dictiona
|
||||
, _frametimeType(FrametimeInfo, properties::OptionProperty::DisplayType::Dropdown)
|
||||
, _clearCache(ClearCacheInfo)
|
||||
{
|
||||
documentation::testSpecificationAndThrow(
|
||||
Documentation(),
|
||||
dictionary,
|
||||
"DashboardItemFramerate"
|
||||
);
|
||||
const Parameters p = codegen::bake<Parameters>(dictionary);
|
||||
|
||||
_frametimeType.addOptions({
|
||||
{ static_cast<int>(FrametimeType::DtTimeAvg), ValueDtAvg },
|
||||
{ static_cast<int>(FrametimeType::DtTimeExtremes), ValueDtExtremes },
|
||||
{ static_cast<int>(FrametimeType::DtTimeAvg), "Average Deltatime" },
|
||||
{ static_cast<int>(FrametimeType::DtTimeExtremes), "Deltatime extremes" },
|
||||
{
|
||||
static_cast<int>(FrametimeType::DtStandardDeviation),
|
||||
ValueDtStandardDeviation
|
||||
"Deltatime standard deviation"
|
||||
},
|
||||
{
|
||||
static_cast<int>(FrametimeType::DtCoefficientOfVariation),
|
||||
ValueDtCov
|
||||
"Deltatime coefficient of variation"
|
||||
},
|
||||
{ static_cast<int>(FrametimeType::FPS), ValueFps },
|
||||
{ static_cast<int>(FrametimeType::FPSAvg), ValueFpsAvg },
|
||||
{ static_cast<int>(FrametimeType::None), ValueNone }
|
||||
{ static_cast<int>(FrametimeType::FPS), "Frames per second" },
|
||||
{ static_cast<int>(FrametimeType::FPSAvg), "Average frames per second" },
|
||||
{ static_cast<int>(FrametimeType::None), "None" }
|
||||
});
|
||||
|
||||
if (dictionary.hasKey(FrametimeInfo.identifier)) {
|
||||
const std::string& v = dictionary.value<std::string>(FrametimeInfo.identifier);
|
||||
if (v == ValueDtAvg) {
|
||||
_frametimeType = static_cast<int>(FrametimeType::DtTimeAvg);
|
||||
}
|
||||
else if (v == ValueDtExtremes) {
|
||||
_frametimeType = static_cast<int>(FrametimeType::DtTimeExtremes);
|
||||
}
|
||||
else if (v == ValueDtStandardDeviation) {
|
||||
_frametimeType =
|
||||
static_cast<int>(FrametimeType::DtStandardDeviation);
|
||||
}
|
||||
else if (v == ValueDtCov) {
|
||||
_frametimeType =
|
||||
static_cast<int>(FrametimeType::DtCoefficientOfVariation);
|
||||
}
|
||||
else if (v == ValueFps) {
|
||||
_frametimeType = static_cast<int>(FrametimeType::FPS);
|
||||
}
|
||||
else if (v == ValueFpsAvg) {
|
||||
_frametimeType = static_cast<int>(FrametimeType::FPSAvg);
|
||||
}
|
||||
else {
|
||||
_frametimeType = static_cast<int>(FrametimeType::None);
|
||||
if (p.frametimeType.has_value()) {
|
||||
switch (*p.frametimeType) {
|
||||
case Parameters::Type::DtAvg:
|
||||
_frametimeType = static_cast<int>(FrametimeType::DtTimeAvg);
|
||||
break;
|
||||
case Parameters::Type::DtExtremes:
|
||||
_frametimeType = static_cast<int>(FrametimeType::DtTimeExtremes);
|
||||
break;
|
||||
case Parameters::Type::DtStandardDeviation:
|
||||
_frametimeType = static_cast<int>(FrametimeType::DtStandardDeviation);
|
||||
break;
|
||||
case Parameters::Type::DtCoefficientOfVariation:
|
||||
_frametimeType = static_cast<int>(FrametimeType::DtCoefficientOfVariation);
|
||||
break;
|
||||
case Parameters::Type::FPS:
|
||||
_frametimeType = static_cast<int>(FrametimeType::FPS);
|
||||
break;
|
||||
case Parameters::Type::FPSAvg:
|
||||
_frametimeType = static_cast<int>(FrametimeType::FPSAvg);
|
||||
break;
|
||||
}
|
||||
}
|
||||
else {
|
||||
|
||||
@@ -51,7 +51,6 @@ namespace {
|
||||
progress.append("|");
|
||||
return progress;
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
namespace openspace {
|
||||
|
||||
@@ -48,35 +48,23 @@ namespace {
|
||||
"the value itself will be displayed), or it must contain extact one instance of "
|
||||
"{}, which will be replaced with the value of the property during rendering."
|
||||
};
|
||||
|
||||
struct [[codegen::Dictionary(DashboardItemPropertyValue)]] Parameters {
|
||||
// [[codegen::verbatim(PropertyUriInfo.description)]]
|
||||
std::optional<std::string> uri [[codegen::key("URI")]];
|
||||
|
||||
// [[codegen::verbatim(DisplayStringInfo.description)]]
|
||||
std::optional<std::string> displayString;
|
||||
};
|
||||
#include "dashboarditempropertyvalue_codegen.cpp"
|
||||
} // namespace
|
||||
|
||||
namespace openspace {
|
||||
|
||||
documentation::Documentation DashboardItemPropertyValue::Documentation() {
|
||||
using namespace documentation;
|
||||
return {
|
||||
"DashboardItem PropertyValue",
|
||||
"base_dashboarditem_propertyvalue",
|
||||
{
|
||||
{
|
||||
"Type",
|
||||
new StringEqualVerifier("DashboardItemPropertyValue"),
|
||||
Optional::No
|
||||
},
|
||||
{
|
||||
PropertyUriInfo.identifier,
|
||||
new StringVerifier,
|
||||
Optional::Yes,
|
||||
PropertyUriInfo.description
|
||||
},
|
||||
{
|
||||
DisplayStringInfo.identifier,
|
||||
new StringVerifier,
|
||||
Optional::Yes,
|
||||
DisplayStringInfo.description
|
||||
}
|
||||
}
|
||||
};
|
||||
documentation::Documentation doc = codegen::doc<Parameters>();
|
||||
doc.id = "base_dashboarditem_propertyvalue";
|
||||
return doc;
|
||||
}
|
||||
|
||||
DashboardItemPropertyValue::DashboardItemPropertyValue(
|
||||
@@ -85,21 +73,13 @@ DashboardItemPropertyValue::DashboardItemPropertyValue(
|
||||
, _propertyUri(PropertyUriInfo)
|
||||
, _displayString(DisplayStringInfo)
|
||||
{
|
||||
documentation::testSpecificationAndThrow(
|
||||
Documentation(),
|
||||
dictionary,
|
||||
"DashboardItemPropertyValue"
|
||||
);
|
||||
const Parameters p = codegen::bake<Parameters>(dictionary);
|
||||
|
||||
if (dictionary.hasKey(PropertyUriInfo.identifier)) {
|
||||
_propertyUri = dictionary.value<std::string>(PropertyUriInfo.identifier);
|
||||
}
|
||||
_propertyUri = p.uri.value_or(_propertyUri);
|
||||
_propertyUri.onChange([this]() { _propertyIsDirty = true; });
|
||||
addProperty(_propertyUri);
|
||||
|
||||
if (dictionary.hasKey(DisplayStringInfo.identifier)) {
|
||||
_displayString = dictionary.value<std::string>(DisplayStringInfo.identifier);
|
||||
}
|
||||
_displayString = p.displayString.value_or(_displayString);
|
||||
addProperty(_displayString);
|
||||
}
|
||||
|
||||
|
||||
@@ -81,47 +81,29 @@ namespace {
|
||||
);
|
||||
return res;
|
||||
}
|
||||
|
||||
struct [[codegen::Dictionary(DashboardItemSimulationIncrement)]] Parameters {
|
||||
// [[codegen::verbatim(SimplificationInfo.description)]]
|
||||
std::optional<bool> simplification;
|
||||
|
||||
// [[codegen::verbatim(RequestedUnitInfo.description)]]
|
||||
std::optional<std::string> requestedUnit [[codegen::inlist(unitList())]];
|
||||
|
||||
// [[codegen::verbatim(TransitionFormatInfo.description)]]
|
||||
std::optional<std::string> transitionFormat;
|
||||
|
||||
// [[codegen::verbatim(RegularFormatInfo.description)]]
|
||||
std::optional<std::string> regularFormat;
|
||||
};
|
||||
#include "dashboarditemsimulationincrement_codegen.cpp"
|
||||
} // namespace
|
||||
|
||||
namespace openspace {
|
||||
|
||||
documentation::Documentation DashboardItemSimulationIncrement::Documentation() {
|
||||
using namespace documentation;
|
||||
return {
|
||||
"DashboardItem Simulation Increment",
|
||||
"base_dashboarditem_simulationincrement",
|
||||
{
|
||||
{
|
||||
"Type",
|
||||
new StringEqualVerifier("DashboardItemSimulationIncrement"),
|
||||
Optional::No
|
||||
},
|
||||
{
|
||||
SimplificationInfo.identifier,
|
||||
new BoolVerifier,
|
||||
Optional::Yes,
|
||||
SimplificationInfo.description
|
||||
},
|
||||
{
|
||||
RequestedUnitInfo.identifier,
|
||||
new StringInListVerifier(unitList()),
|
||||
Optional::Yes,
|
||||
RequestedUnitInfo.description
|
||||
},
|
||||
{
|
||||
TransitionFormatInfo.identifier,
|
||||
new StringVerifier,
|
||||
Optional::Yes,
|
||||
TransitionFormatInfo.description
|
||||
},
|
||||
{
|
||||
RegularFormatInfo.identifier,
|
||||
new StringVerifier,
|
||||
Optional::Yes,
|
||||
RegularFormatInfo.description
|
||||
}
|
||||
}
|
||||
};
|
||||
documentation::Documentation doc = codegen::doc<Parameters>();
|
||||
doc.id = "base_dashboarditem_simulationincrement";
|
||||
return doc;
|
||||
}
|
||||
|
||||
DashboardItemSimulationIncrement::DashboardItemSimulationIncrement(
|
||||
@@ -135,15 +117,9 @@ DashboardItemSimulationIncrement::DashboardItemSimulationIncrement(
|
||||
)
|
||||
, _regularFormat(RegularFormatInfo, "Simulation increment: {:.1f} {:s} / second{:s}")
|
||||
{
|
||||
documentation::testSpecificationAndThrow(
|
||||
Documentation(),
|
||||
dictionary,
|
||||
"DashboardItemSimulationIncrement"
|
||||
);
|
||||
const Parameters p = codegen::bake<Parameters>(dictionary);
|
||||
|
||||
if (dictionary.hasKey(SimplificationInfo.identifier)) {
|
||||
_doSimplification = dictionary.value<bool>(SimplificationInfo.identifier);
|
||||
}
|
||||
_doSimplification = p.simplification.value_or(_doSimplification);
|
||||
_doSimplification.onChange([this]() {
|
||||
_requestedUnit.setVisibility(
|
||||
_doSimplification ?
|
||||
@@ -157,24 +133,17 @@ DashboardItemSimulationIncrement::DashboardItemSimulationIncrement(
|
||||
_requestedUnit.addOption(static_cast<int>(u), nameForTimeUnit(u));
|
||||
}
|
||||
_requestedUnit = static_cast<int>(TimeUnit::Second);
|
||||
if (dictionary.hasKey(RequestedUnitInfo.identifier)) {
|
||||
std::string value = dictionary.value<std::string>(RequestedUnitInfo.identifier);
|
||||
TimeUnit unit = timeUnitFromString(value.c_str());
|
||||
if (p.requestedUnit.has_value()) {
|
||||
TimeUnit unit = timeUnitFromString(p.requestedUnit->c_str());
|
||||
_requestedUnit = static_cast<int>(unit);
|
||||
}
|
||||
_requestedUnit.setVisibility(properties::Property::Visibility::Hidden);
|
||||
addProperty(_requestedUnit);
|
||||
|
||||
if (dictionary.hasKey(TransitionFormatInfo.identifier)) {
|
||||
_transitionFormat = dictionary.value<std::string>(
|
||||
TransitionFormatInfo.identifier
|
||||
);
|
||||
}
|
||||
_transitionFormat = p.transitionFormat.value_or(_transitionFormat);
|
||||
addProperty(_transitionFormat);
|
||||
|
||||
if (dictionary.hasKey(RegularFormatInfo.identifier)) {
|
||||
_regularFormat = dictionary.value<std::string>(RegularFormatInfo.identifier);
|
||||
}
|
||||
_regularFormat = p.regularFormat.value_or(_regularFormat);
|
||||
addProperty(_regularFormat);
|
||||
}
|
||||
|
||||
|
||||
@@ -26,6 +26,7 @@
|
||||
|
||||
#include <openspace/documentation/documentation.h>
|
||||
#include <openspace/documentation/verifier.h>
|
||||
#include <optional>
|
||||
|
||||
namespace {
|
||||
constexpr openspace::properties::Property::PropertyInfo SpacingInfo = {
|
||||
@@ -34,44 +35,29 @@ namespace {
|
||||
"This value determines the spacing (in pixels) that this item represents. The "
|
||||
"default value is 15."
|
||||
};
|
||||
|
||||
struct [[codegen::Dictionary(DashboardItemSpacing)]] Parameters {
|
||||
// [[codegen::verbatim(SpacingInfo.description)]]
|
||||
std::optional<float> spacing;
|
||||
};
|
||||
#include "dashboarditemspacing_codegen.cpp"
|
||||
} // namespace
|
||||
|
||||
namespace openspace {
|
||||
|
||||
documentation::Documentation DashboardItemSpacing::Documentation() {
|
||||
using namespace documentation;
|
||||
return {
|
||||
"DashboardItem Spacing",
|
||||
"base_dashboarditem_spacing",
|
||||
{
|
||||
{
|
||||
"Type",
|
||||
new StringEqualVerifier("DashboardItemSpacing"),
|
||||
Optional::No
|
||||
},
|
||||
{
|
||||
SpacingInfo.identifier,
|
||||
new DoubleVerifier,
|
||||
Optional::Yes,
|
||||
SpacingInfo.description
|
||||
}
|
||||
}
|
||||
};
|
||||
documentation::Documentation doc = codegen::doc<Parameters>();
|
||||
doc.id = "base_dashboarditem_spacing";
|
||||
return doc;
|
||||
}
|
||||
|
||||
DashboardItemSpacing::DashboardItemSpacing(const ghoul::Dictionary& dictionary)
|
||||
: DashboardItem(dictionary)
|
||||
, _spacing(SpacingInfo, 15.f, 0.f, 2048.f)
|
||||
{
|
||||
documentation::testSpecificationAndThrow(
|
||||
Documentation(),
|
||||
dictionary,
|
||||
"DashboardItemSpacing"
|
||||
);
|
||||
const Parameters p = codegen::bake<Parameters>(dictionary);
|
||||
|
||||
if (dictionary.hasKey(SpacingInfo.identifier)) {
|
||||
_spacing = static_cast<float>(dictionary.value<double>(SpacingInfo.identifier));
|
||||
}
|
||||
_spacing = p.spacing.value_or(_spacing);
|
||||
addProperty(_spacing);
|
||||
}
|
||||
|
||||
|
||||
@@ -31,6 +31,7 @@
|
||||
#include <ghoul/font/fontmanager.h>
|
||||
#include <ghoul/font/fontrenderer.h>
|
||||
#include <ghoul/misc/profiling.h>
|
||||
#include <optional>
|
||||
|
||||
namespace {
|
||||
constexpr openspace::properties::Property::PropertyInfo TextInfo = {
|
||||
@@ -38,44 +39,28 @@ namespace {
|
||||
"Text",
|
||||
"The text to be displayed"
|
||||
};
|
||||
|
||||
struct [[codegen::Dictionary(DashboardItemText)]] Parameters {
|
||||
// [[codegen::verbatim(TextInfo.description)]]
|
||||
std::optional<std::string> text;
|
||||
};
|
||||
#include "dashboarditemtext_codegen.cpp"
|
||||
} // namespace
|
||||
|
||||
namespace openspace {
|
||||
|
||||
documentation::Documentation DashboardItemText::Documentation() {
|
||||
using namespace documentation;
|
||||
return {
|
||||
"DashboardItem Text",
|
||||
"base_dashboarditem_text",
|
||||
{
|
||||
{
|
||||
"Type",
|
||||
new StringEqualVerifier("DashboardItemText"),
|
||||
Optional::No
|
||||
},
|
||||
{
|
||||
TextInfo.identifier,
|
||||
new StringVerifier,
|
||||
Optional::Yes,
|
||||
TextInfo.description
|
||||
}
|
||||
}
|
||||
};
|
||||
documentation::Documentation doc = codegen::doc<Parameters>();
|
||||
doc.id = "base_dashboarditem_text";
|
||||
return doc;
|
||||
}
|
||||
|
||||
DashboardItemText::DashboardItemText(const ghoul::Dictionary& dictionary)
|
||||
: DashboardTextItem(dictionary)
|
||||
, _text(TextInfo, "")
|
||||
{
|
||||
documentation::testSpecificationAndThrow(
|
||||
Documentation(),
|
||||
dictionary,
|
||||
"DashboardItemText"
|
||||
);
|
||||
|
||||
if (dictionary.hasKey(TextInfo.identifier)) {
|
||||
_text = dictionary.value<std::string>(TextInfo.identifier);
|
||||
};
|
||||
const Parameters p = codegen::bake<Parameters>(dictionary);
|
||||
_text = p.text.value_or(_text);
|
||||
addProperty(_text);
|
||||
}
|
||||
|
||||
|
||||
@@ -68,35 +68,24 @@ namespace {
|
||||
);
|
||||
return res;
|
||||
}
|
||||
|
||||
struct [[codegen::Dictionary(DashboardItemVelocity)]] Parameters {
|
||||
// [[codegen::verbatim(SimplificationInfo.description)]]
|
||||
std::optional<bool> simplification;
|
||||
|
||||
// [[codegen::verbatim(RequestedUnitInfo.description)]]
|
||||
std::optional<std::string> requestedUnit [[codegen::inlist(unitList())]];
|
||||
};
|
||||
#include "dashboarditemvelocity_codegen.cpp"
|
||||
|
||||
} // namespace
|
||||
|
||||
namespace openspace {
|
||||
|
||||
documentation::Documentation DashboardItemVelocity::Documentation() {
|
||||
using namespace documentation;
|
||||
return {
|
||||
"DashboardItem Velocity",
|
||||
"base_dashboarditem_velocity",
|
||||
{
|
||||
{
|
||||
"Type",
|
||||
new StringEqualVerifier("DashboardItemVelocity"),
|
||||
Optional::No
|
||||
},
|
||||
{
|
||||
SimplificationInfo.identifier,
|
||||
new BoolVerifier,
|
||||
Optional::Yes,
|
||||
SimplificationInfo.description
|
||||
},
|
||||
{
|
||||
RequestedUnitInfo.identifier,
|
||||
new StringInListVerifier(unitList()),
|
||||
Optional::Yes,
|
||||
RequestedUnitInfo.description
|
||||
}
|
||||
}
|
||||
};
|
||||
documentation::Documentation doc = codegen::doc<Parameters>();
|
||||
doc.id = "base_dashboarditem_velocity";
|
||||
return doc;
|
||||
}
|
||||
|
||||
DashboardItemVelocity::DashboardItemVelocity(const ghoul::Dictionary& dictionary)
|
||||
@@ -104,15 +93,8 @@ DashboardItemVelocity::DashboardItemVelocity(const ghoul::Dictionary& dictionary
|
||||
, _doSimplification(SimplificationInfo, true)
|
||||
, _requestedUnit(RequestedUnitInfo, properties::OptionProperty::DisplayType::Dropdown)
|
||||
{
|
||||
documentation::testSpecificationAndThrow(
|
||||
Documentation(),
|
||||
dictionary,
|
||||
"DashboardItemVelocity"
|
||||
);
|
||||
|
||||
if (dictionary.hasKey(SimplificationInfo.identifier)) {
|
||||
_doSimplification = dictionary.value<bool>(SimplificationInfo.identifier);
|
||||
}
|
||||
const Parameters p = codegen::bake<Parameters>(dictionary);
|
||||
_doSimplification = p.simplification.value_or(_doSimplification);
|
||||
_doSimplification.onChange([this]() {
|
||||
_requestedUnit.setVisibility(
|
||||
_doSimplification ?
|
||||
@@ -126,11 +108,8 @@ DashboardItemVelocity::DashboardItemVelocity(const ghoul::Dictionary& dictionary
|
||||
_requestedUnit.addOption(static_cast<int>(u), nameForDistanceUnit(u));
|
||||
}
|
||||
_requestedUnit = static_cast<int>(DistanceUnit::Meter);
|
||||
if (dictionary.hasKey(RequestedUnitInfo.identifier)) {
|
||||
const std::string& value = dictionary.value<std::string>(
|
||||
RequestedUnitInfo.identifier
|
||||
);
|
||||
DistanceUnit unit = distanceUnitFromString(value.c_str());
|
||||
if (p.requestedUnit.has_value()) {
|
||||
DistanceUnit unit = distanceUnitFromString(p.requestedUnit->c_str());
|
||||
_requestedUnit = static_cast<int>(unit);
|
||||
}
|
||||
_requestedUnit.setVisibility(properties::Property::Visibility::Hidden);
|
||||
|
||||
@@ -27,6 +27,7 @@
|
||||
#include <openspace/documentation/documentation.h>
|
||||
#include <openspace/documentation/verifier.h>
|
||||
#include <openspace/util/updatestructures.h>
|
||||
#include <optional>
|
||||
|
||||
namespace {
|
||||
constexpr openspace::properties::Property::PropertyInfo IntensityInfo = {
|
||||
@@ -34,30 +35,20 @@ namespace {
|
||||
"Intensity",
|
||||
"The intensity of this light source"
|
||||
};
|
||||
|
||||
struct [[codegen::Dictionary(CameraLightSource)]] Parameters {
|
||||
// [[codegen::verbatim(IntensityInfo.description)]]
|
||||
std::optional<float> intensity;
|
||||
};
|
||||
#include "cameralightsource_codegen.cpp"
|
||||
} // namespace
|
||||
|
||||
namespace openspace {
|
||||
|
||||
documentation::Documentation CameraLightSource::Documentation() {
|
||||
using namespace openspace::documentation;
|
||||
return {
|
||||
"Camera Light Source",
|
||||
"base_camera_light_source",
|
||||
{
|
||||
{
|
||||
"Type",
|
||||
new StringEqualVerifier("CameraLightSource"),
|
||||
Optional::No,
|
||||
"The type of this light source"
|
||||
},
|
||||
{
|
||||
IntensityInfo.identifier,
|
||||
new DoubleVerifier,
|
||||
Optional::Yes,
|
||||
IntensityInfo.description
|
||||
}
|
||||
}
|
||||
};
|
||||
documentation::Documentation doc = codegen::doc<Parameters>();
|
||||
doc.id = "base_camera_light_source";
|
||||
return doc;
|
||||
}
|
||||
|
||||
CameraLightSource::CameraLightSource()
|
||||
@@ -70,18 +61,9 @@ CameraLightSource::CameraLightSource(const ghoul::Dictionary& dictionary)
|
||||
: LightSource(dictionary)
|
||||
, _intensity(IntensityInfo, 1.f, 0.f, 1.f)
|
||||
{
|
||||
const Parameters p = codegen::bake<Parameters>(dictionary);
|
||||
_intensity = p.intensity.value_or(_intensity);
|
||||
addProperty(_intensity);
|
||||
|
||||
documentation::testSpecificationAndThrow(Documentation(),
|
||||
dictionary,
|
||||
"CameraLightSource");
|
||||
|
||||
|
||||
if (dictionary.hasValue<double>(IntensityInfo.identifier)) {
|
||||
_intensity = static_cast<float>(
|
||||
dictionary.value<double>(IntensityInfo.identifier)
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
float CameraLightSource::intensity() const {
|
||||
|
||||
@@ -31,6 +31,7 @@
|
||||
#include <openspace/scene/scene.h>
|
||||
#include <openspace/util/updatestructures.h>
|
||||
#include <ghoul/misc/profiling.h>
|
||||
#include <optional>
|
||||
|
||||
namespace {
|
||||
constexpr openspace::properties::Property::PropertyInfo IntensityInfo = {
|
||||
@@ -44,36 +45,23 @@ namespace {
|
||||
"Node",
|
||||
"The identifier of the scene graph node to follow"
|
||||
};
|
||||
|
||||
struct [[codegen::Dictionary(SceneGraphLightSource)]] Parameters {
|
||||
// [[codegen::verbatim(IntensityInfo.description)]]
|
||||
std::optional<float> intensity;
|
||||
|
||||
// [[codegen::verbatim(NodeInfo.description)]]
|
||||
std::string node;
|
||||
};
|
||||
#include "scenegraphlightsource_codegen.cpp"
|
||||
} // namespace
|
||||
|
||||
namespace openspace {
|
||||
|
||||
documentation::Documentation SceneGraphLightSource::Documentation() {
|
||||
using namespace openspace::documentation;
|
||||
return {
|
||||
"Scene Graph Light Source",
|
||||
"base_scene_graph_light_source",
|
||||
{
|
||||
{
|
||||
"Type",
|
||||
new StringEqualVerifier("SceneGraphLightSource"),
|
||||
Optional::No,
|
||||
"The type of this light source"
|
||||
},
|
||||
{
|
||||
IntensityInfo.identifier,
|
||||
new DoubleVerifier,
|
||||
Optional::Yes,
|
||||
IntensityInfo.description
|
||||
},
|
||||
{
|
||||
NodeInfo.identifier,
|
||||
new StringVerifier,
|
||||
Optional::No,
|
||||
NodeInfo.description
|
||||
},
|
||||
}
|
||||
};
|
||||
documentation::Documentation doc = codegen::doc<Parameters>();
|
||||
doc.id = "base_scene_graph_light_source";
|
||||
return doc;
|
||||
}
|
||||
|
||||
SceneGraphLightSource::SceneGraphLightSource()
|
||||
@@ -89,30 +77,17 @@ SceneGraphLightSource::SceneGraphLightSource(const ghoul::Dictionary& dictionary
|
||||
, _intensity(IntensityInfo, 1.f, 0.f, 1.f)
|
||||
, _sceneGraphNodeReference(NodeInfo, "")
|
||||
{
|
||||
const Parameters p = codegen::bake<Parameters>(dictionary);
|
||||
|
||||
_intensity = p.intensity.value_or(_intensity);
|
||||
addProperty(_intensity);
|
||||
addProperty(_sceneGraphNodeReference);
|
||||
|
||||
documentation::testSpecificationAndThrow(Documentation(),
|
||||
dictionary,
|
||||
"SceneGraphLightSource");
|
||||
|
||||
|
||||
if (dictionary.hasValue<double>(IntensityInfo.identifier)) {
|
||||
_intensity = static_cast<float>(
|
||||
dictionary.value<double>(IntensityInfo.identifier)
|
||||
);
|
||||
}
|
||||
|
||||
if (dictionary.hasValue<std::string>(NodeInfo.identifier)) {
|
||||
_sceneGraphNodeReference =
|
||||
dictionary.value<std::string>(NodeInfo.identifier);
|
||||
}
|
||||
|
||||
_sceneGraphNodeReference = p.node;
|
||||
_sceneGraphNodeReference.onChange([this]() {
|
||||
_sceneGraphNode =
|
||||
global::renderEngine->scene()->sceneGraphNode(_sceneGraphNodeReference);
|
||||
});
|
||||
|
||||
addProperty(_sceneGraphNodeReference);
|
||||
}
|
||||
|
||||
bool SceneGraphLightSource::initialize() {
|
||||
|
||||
@@ -55,36 +55,26 @@ namespace {
|
||||
"Grid Size",
|
||||
"This value species the size of each dimensions of the box"
|
||||
};
|
||||
|
||||
struct [[codegen::Dictionary(RenderableBoxGrid)]] Parameters {
|
||||
// [[codegen::verbatim(ColorInfo.description)]]
|
||||
std::optional<glm::vec3> color;
|
||||
|
||||
// [[codegen::verbatim(LineWidthInfo.description)]]
|
||||
std::optional<float> lineWidth;
|
||||
|
||||
// [[codegen::verbatim(SizeInfo.description)]]
|
||||
std::optional<glm::vec3> size;
|
||||
};
|
||||
#include "renderableboxgrid_codegen.cpp"
|
||||
} // namespace
|
||||
|
||||
namespace openspace {
|
||||
|
||||
documentation::Documentation RenderableBoxGrid::Documentation() {
|
||||
using namespace documentation;
|
||||
return {
|
||||
"RenderableBoxGrid",
|
||||
"base_renderable_boxgrid",
|
||||
{
|
||||
{
|
||||
ColorInfo.identifier,
|
||||
new DoubleVector3Verifier,
|
||||
Optional::Yes,
|
||||
ColorInfo.description
|
||||
},
|
||||
{
|
||||
LineWidthInfo.identifier,
|
||||
new DoubleVerifier,
|
||||
Optional::Yes,
|
||||
LineWidthInfo.description
|
||||
},
|
||||
{
|
||||
SizeInfo.identifier,
|
||||
new DoubleVector3Verifier,
|
||||
Optional::Yes,
|
||||
SizeInfo.description
|
||||
}
|
||||
}
|
||||
};
|
||||
documentation::Documentation doc = codegen::doc<Parameters>();
|
||||
doc.id = "base_renderable_boxgrid";
|
||||
return doc;
|
||||
}
|
||||
|
||||
RenderableBoxGrid::RenderableBoxGrid(const ghoul::Dictionary& dictionary)
|
||||
@@ -93,31 +83,19 @@ RenderableBoxGrid::RenderableBoxGrid(const ghoul::Dictionary& dictionary)
|
||||
, _lineWidth(LineWidthInfo, 0.5f, 0.f, 20.f)
|
||||
, _size(SizeInfo, glm::vec3(1.f), glm::vec3(1.f), glm::vec3(100.f))
|
||||
{
|
||||
documentation::testSpecificationAndThrow(
|
||||
Documentation(),
|
||||
dictionary,
|
||||
"RenderableBoxGrid"
|
||||
);
|
||||
const Parameters p = codegen::bake<Parameters>(dictionary);
|
||||
|
||||
addProperty(_opacity);
|
||||
registerUpdateRenderBinFromOpacity();
|
||||
|
||||
if (dictionary.hasKey(ColorInfo.identifier)) {
|
||||
_color = dictionary.value<glm::dvec3>(ColorInfo.identifier);
|
||||
}
|
||||
_color = p.color.value_or(_color);
|
||||
_color.setViewOption(properties::Property::ViewOptions::Color);
|
||||
addProperty(_color);
|
||||
|
||||
if (dictionary.hasKey(LineWidthInfo.identifier)) {
|
||||
_lineWidth = static_cast<float>(
|
||||
dictionary.value<double>(LineWidthInfo.identifier)
|
||||
);
|
||||
}
|
||||
_lineWidth = p.lineWidth.value_or(_lineWidth);
|
||||
addProperty(_lineWidth);
|
||||
|
||||
if (dictionary.hasKey(SizeInfo.identifier)) {
|
||||
_size = dictionary.value<glm::dvec3>(SizeInfo.identifier);
|
||||
}
|
||||
_size = p.size.value_or(_size);
|
||||
_size.onChange([&]() { _gridIsDirty = true; });
|
||||
addProperty(_size);
|
||||
}
|
||||
|
||||
@@ -62,43 +62,29 @@ namespace {
|
||||
"Grid Size",
|
||||
"This value species the size of each dimensions of the grid"
|
||||
};
|
||||
|
||||
struct [[codegen::Dictionary(RenderableGrid)]] Parameters {
|
||||
// [[codegen::verbatim(ColorInfo.description)]]
|
||||
std::optional<glm::vec3> color;
|
||||
|
||||
// [[codegen::verbatim(SegmentsInfo.description)]]
|
||||
std::optional<glm::ivec2> segments;
|
||||
|
||||
// [[codegen::verbatim(LineWidthInfo.description)]]
|
||||
std::optional<float> lineWidth;
|
||||
|
||||
// [[codegen::verbatim(SizeInfo.description)]]
|
||||
std::optional<glm::vec2> size;
|
||||
};
|
||||
#include "renderablegrid_codegen.cpp"
|
||||
} // namespace
|
||||
|
||||
namespace openspace {
|
||||
|
||||
documentation::Documentation RenderableGrid::Documentation() {
|
||||
using namespace documentation;
|
||||
return {
|
||||
"RenderableGrid",
|
||||
"base_renderable_grid",
|
||||
{
|
||||
{
|
||||
ColorInfo.identifier,
|
||||
new DoubleVector3Verifier,
|
||||
Optional::Yes,
|
||||
ColorInfo.description
|
||||
},
|
||||
{
|
||||
SegmentsInfo.identifier,
|
||||
// @TODO (emmbr 2020-07-07): should be Int, but specification test fails..
|
||||
new DoubleVector2Verifier,
|
||||
Optional::Yes,
|
||||
SegmentsInfo.description
|
||||
},
|
||||
{
|
||||
LineWidthInfo.identifier,
|
||||
new DoubleVerifier,
|
||||
Optional::Yes,
|
||||
LineWidthInfo.description
|
||||
},
|
||||
{
|
||||
SizeInfo.identifier,
|
||||
new DoubleVector2Verifier,
|
||||
Optional::Yes,
|
||||
SizeInfo.description
|
||||
}
|
||||
}
|
||||
};
|
||||
documentation::Documentation doc = codegen::doc<Parameters>();
|
||||
doc.id = "base_renderable_grid";
|
||||
return doc;
|
||||
}
|
||||
|
||||
RenderableGrid::RenderableGrid(const ghoul::Dictionary& dictionary)
|
||||
@@ -108,39 +94,23 @@ RenderableGrid::RenderableGrid(const ghoul::Dictionary& dictionary)
|
||||
, _lineWidth(LineWidthInfo, 0.5f, 0.f, 20.f)
|
||||
, _size(SizeInfo, glm::vec2(1e20f), glm::vec2(1.f), glm::vec2(1e35f))
|
||||
{
|
||||
documentation::testSpecificationAndThrow(
|
||||
Documentation(),
|
||||
dictionary,
|
||||
"RenderableGrid"
|
||||
);
|
||||
const Parameters p = codegen::bake<Parameters>(dictionary);
|
||||
|
||||
addProperty(_opacity);
|
||||
registerUpdateRenderBinFromOpacity();
|
||||
|
||||
if (dictionary.hasKey(ColorInfo.identifier)) {
|
||||
_color = dictionary.value<glm::dvec3>(ColorInfo.identifier);
|
||||
}
|
||||
_color = p.color.value_or(_color);
|
||||
_color.setViewOption(properties::Property::ViewOptions::Color);
|
||||
addProperty(_color);
|
||||
|
||||
if (dictionary.hasKey(SegmentsInfo.identifier)) {
|
||||
_segments = static_cast<glm::uvec2>(
|
||||
dictionary.value<glm::dvec2>(SegmentsInfo.identifier)
|
||||
);
|
||||
}
|
||||
_segments = p.segments.value_or(_segments);
|
||||
_segments.onChange([&]() { _gridIsDirty = true; });
|
||||
addProperty(_segments);
|
||||
|
||||
if (dictionary.hasKey(LineWidthInfo.identifier)) {
|
||||
_lineWidth = static_cast<float>(
|
||||
dictionary.value<double>(LineWidthInfo.identifier)
|
||||
);
|
||||
}
|
||||
_lineWidth = p.lineWidth.value_or(_lineWidth);
|
||||
addProperty(_lineWidth);
|
||||
|
||||
if (dictionary.hasKey(SizeInfo.identifier)) {
|
||||
_size = dictionary.value<glm::dvec2>(SizeInfo.identifier);
|
||||
}
|
||||
_size = p.size.value_or(_size);
|
||||
_size.onChange([&]() { _gridIsDirty = true; });
|
||||
addProperty(_size);
|
||||
}
|
||||
|
||||
@@ -28,8 +28,8 @@
|
||||
#include <openspace/rendering/renderable.h>
|
||||
|
||||
#include <openspace/properties/stringproperty.h>
|
||||
#include <openspace/properties/vector/ivec2property.h>
|
||||
#include <openspace/properties/scalar/floatproperty.h>
|
||||
#include <openspace/properties/vector/uvec2property.h>
|
||||
#include <openspace/properties/vector/vec2property.h>
|
||||
#include <openspace/properties/vector/vec3property.h>
|
||||
#include <ghoul/opengl/ghoul_gl.h>
|
||||
@@ -61,7 +61,9 @@ protected:
|
||||
ghoul::opengl::ProgramObject* _gridProgram = nullptr;
|
||||
|
||||
properties::Vec3Property _color;
|
||||
properties::UVec2Property _segments;
|
||||
// @TODO (abock, 2021-01-28) This was a UVec2Property before, but it wasn't supported
|
||||
// be the codegen. As soon as it does, this should be changed back
|
||||
properties::IVec2Property _segments;
|
||||
properties::FloatProperty _lineWidth;
|
||||
properties::Vec2Property _size;
|
||||
|
||||
|
||||
@@ -34,6 +34,7 @@
|
||||
#include <ghoul/filesystem/filesystem.h>
|
||||
#include <ghoul/opengl/openglstatecache.h>
|
||||
#include <ghoul/opengl/programobject.h>
|
||||
#include <optional>
|
||||
|
||||
namespace {
|
||||
constexpr const char* ProgramName = "GridProgram";
|
||||
@@ -76,54 +77,35 @@ namespace {
|
||||
"The inner radius of the circular grid, that is the radius of the inmost ring. "
|
||||
"Must be smaller than the outer radius."
|
||||
};
|
||||
|
||||
struct [[codegen::Dictionary(RenderableRadialGrid)]] Parameters {
|
||||
// [[codegen::verbatim(ColorInfo.description)]]
|
||||
std::optional<glm::vec3> color;
|
||||
|
||||
// [[codegen::verbatim(GridSegmentsInfo.description)]]
|
||||
std::optional<glm::ivec2> gridSegments;
|
||||
|
||||
// [[codegen::verbatim(CircleSegmentsInfo.description)]]
|
||||
std::optional<int> circleSegments;
|
||||
|
||||
// [[codegen::verbatim(LineWidthInfo.description)]]
|
||||
std::optional<float> lineWidth;
|
||||
|
||||
// [[codegen::verbatim(OuterRadiusInfo.description)]]
|
||||
std::optional<float> outerRadius;
|
||||
|
||||
// [[codegen::verbatim(InnerRadiusInfo.description)]]
|
||||
std::optional<float> innerRadius;
|
||||
};
|
||||
#include "renderableradialgrid_codegen.cpp"
|
||||
} // namespace
|
||||
|
||||
namespace openspace {
|
||||
|
||||
documentation::Documentation RenderableRadialGrid::Documentation() {
|
||||
using namespace documentation;
|
||||
return {
|
||||
"RenderableRadialGrid",
|
||||
"base_renderable_radialgrid",
|
||||
{
|
||||
{
|
||||
ColorInfo.identifier,
|
||||
new DoubleVector3Verifier,
|
||||
Optional::Yes,
|
||||
ColorInfo.description
|
||||
},
|
||||
{
|
||||
GridSegmentsInfo.identifier,
|
||||
new DoubleVector2Verifier,
|
||||
Optional::Yes,
|
||||
GridSegmentsInfo.description
|
||||
},
|
||||
{
|
||||
CircleSegmentsInfo.identifier,
|
||||
new IntVerifier,
|
||||
Optional::Yes,
|
||||
CircleSegmentsInfo.description
|
||||
},
|
||||
{
|
||||
LineWidthInfo.identifier,
|
||||
new DoubleVerifier,
|
||||
Optional::Yes,
|
||||
LineWidthInfo.description
|
||||
},
|
||||
{
|
||||
OuterRadiusInfo.identifier,
|
||||
new DoubleVerifier,
|
||||
Optional::Yes,
|
||||
OuterRadiusInfo.description
|
||||
},
|
||||
{
|
||||
InnerRadiusInfo.identifier,
|
||||
new DoubleVerifier,
|
||||
Optional::Yes,
|
||||
InnerRadiusInfo.description
|
||||
}
|
||||
}
|
||||
};
|
||||
documentation::Documentation doc = codegen::doc<Parameters>();
|
||||
doc.id = "base_renderable_radialgrid";
|
||||
return doc;
|
||||
}
|
||||
|
||||
RenderableRadialGrid::RenderableRadialGrid(const ghoul::Dictionary& dictionary)
|
||||
@@ -135,34 +117,20 @@ RenderableRadialGrid::RenderableRadialGrid(const ghoul::Dictionary& dictionary)
|
||||
, _maxRadius(OuterRadiusInfo, 1.f, 0.f, 20.f)
|
||||
, _minRadius(InnerRadiusInfo, 0.f, 0.f, 20.f)
|
||||
{
|
||||
documentation::testSpecificationAndThrow(
|
||||
Documentation(),
|
||||
dictionary,
|
||||
"RenderableRadialGrid"
|
||||
);
|
||||
const Parameters p = codegen::bake<Parameters>(dictionary);
|
||||
|
||||
addProperty(_opacity);
|
||||
registerUpdateRenderBinFromOpacity();
|
||||
|
||||
if (dictionary.hasKey(ColorInfo.identifier)) {
|
||||
_color = dictionary.value<glm::dvec3>(ColorInfo.identifier);
|
||||
}
|
||||
_color = p.color.value_or(_color);
|
||||
_color.setViewOption(properties::Property::ViewOptions::Color);
|
||||
addProperty(_color);
|
||||
|
||||
if (dictionary.hasKey(GridSegmentsInfo.identifier)) {
|
||||
_gridSegments = static_cast<glm::ivec2>(
|
||||
dictionary.value<glm::dvec2>(GridSegmentsInfo.identifier)
|
||||
);
|
||||
}
|
||||
_gridSegments = p.gridSegments.value_or(_gridSegments);
|
||||
_gridSegments.onChange([&]() { _gridIsDirty = true; });
|
||||
addProperty(_gridSegments);
|
||||
|
||||
if (dictionary.hasKey(CircleSegmentsInfo.identifier)) {
|
||||
_circleSegments = static_cast<int>(
|
||||
dictionary.value<double>(CircleSegmentsInfo.identifier)
|
||||
);
|
||||
}
|
||||
_circleSegments = p.circleSegments.value_or(_circleSegments);
|
||||
_circleSegments.onChange([&]() {
|
||||
if (_circleSegments.value() % 2 == 1) {
|
||||
_circleSegments = _circleSegments - 1;
|
||||
@@ -171,24 +139,11 @@ RenderableRadialGrid::RenderableRadialGrid(const ghoul::Dictionary& dictionary)
|
||||
});
|
||||
addProperty(_circleSegments);
|
||||
|
||||
if (dictionary.hasKey(LineWidthInfo.identifier)) {
|
||||
_lineWidth = static_cast<float>(
|
||||
dictionary.value<double>(LineWidthInfo.identifier)
|
||||
);
|
||||
}
|
||||
_lineWidth = p.lineWidth.value_or(_lineWidth);
|
||||
addProperty(_lineWidth);
|
||||
|
||||
if (dictionary.hasKey(OuterRadiusInfo.identifier)) {
|
||||
_maxRadius = static_cast<float>(
|
||||
dictionary.value<double>(OuterRadiusInfo.identifier)
|
||||
);
|
||||
}
|
||||
|
||||
if (dictionary.hasKey(InnerRadiusInfo.identifier)) {
|
||||
_minRadius = static_cast<float>(
|
||||
dictionary.value<double>(InnerRadiusInfo.identifier)
|
||||
);
|
||||
}
|
||||
_minRadius = p.innerRadius.value_or(_minRadius);
|
||||
_maxRadius = p.outerRadius.value_or(_maxRadius);
|
||||
|
||||
_maxRadius.setMinValue(_minRadius);
|
||||
_minRadius.setMaxValue(_maxRadius);
|
||||
|
||||
@@ -33,6 +33,7 @@
|
||||
#include <ghoul/filesystem/filesystem.h>
|
||||
#include <ghoul/opengl/openglstatecache.h>
|
||||
#include <ghoul/opengl/programobject.h>
|
||||
#include <optional>
|
||||
|
||||
namespace {
|
||||
constexpr const char* ProgramName = "GridProgram";
|
||||
@@ -55,36 +56,26 @@ namespace {
|
||||
"Line Width",
|
||||
"This value specifies the line width of the spherical grid."
|
||||
};
|
||||
|
||||
struct [[codegen::Dictionary(RenderableSphericalGrid)]] Parameters {
|
||||
// [[codegen::verbatim(ColorInfo.description)]]
|
||||
std::optional<glm::vec3> color;
|
||||
|
||||
// [[codegen::verbatim(SegmentsInfo.description)]]
|
||||
std::optional<int> segments;
|
||||
|
||||
// [[codegen::verbatim(LineWidthInfo.description)]]
|
||||
std::optional<float> lineWidth;
|
||||
};
|
||||
#include "renderablesphericalgrid_codegen.cpp"
|
||||
} // namespace
|
||||
|
||||
namespace openspace {
|
||||
|
||||
documentation::Documentation RenderableSphericalGrid::Documentation() {
|
||||
using namespace documentation;
|
||||
return {
|
||||
"RenderableSphericalGrid",
|
||||
"base_renderable_sphericalgrid",
|
||||
{
|
||||
{
|
||||
ColorInfo.identifier,
|
||||
new DoubleVector3Verifier,
|
||||
Optional::Yes,
|
||||
ColorInfo.description
|
||||
},
|
||||
{
|
||||
SegmentsInfo.identifier,
|
||||
new IntVerifier,
|
||||
Optional::Yes,
|
||||
SegmentsInfo.description
|
||||
},
|
||||
{
|
||||
LineWidthInfo.identifier,
|
||||
new DoubleVerifier,
|
||||
Optional::Yes,
|
||||
LineWidthInfo.description
|
||||
}
|
||||
}
|
||||
};
|
||||
documentation::Documentation doc = codegen::doc<Parameters>();
|
||||
doc.id = "base_renderable_sphericalgrid";
|
||||
return doc;
|
||||
}
|
||||
|
||||
RenderableSphericalGrid::RenderableSphericalGrid(const ghoul::Dictionary& dictionary)
|
||||
@@ -94,24 +85,16 @@ RenderableSphericalGrid::RenderableSphericalGrid(const ghoul::Dictionary& dictio
|
||||
, _segments(SegmentsInfo, 36, 4, 200)
|
||||
, _lineWidth(LineWidthInfo, 0.5f, 0.f, 20.f)
|
||||
{
|
||||
documentation::testSpecificationAndThrow(
|
||||
Documentation(),
|
||||
dictionary,
|
||||
"RenderableSphericalGrid"
|
||||
);
|
||||
const Parameters p = codegen::bake<Parameters>(dictionary);
|
||||
|
||||
addProperty(_opacity);
|
||||
registerUpdateRenderBinFromOpacity();
|
||||
|
||||
if (dictionary.hasKey(ColorInfo.identifier)) {
|
||||
_color = dictionary.value<glm::dvec3>(ColorInfo.identifier);
|
||||
}
|
||||
_color = p.color.value_or(_color);
|
||||
_color.setViewOption(properties::Property::ViewOptions::Color);
|
||||
addProperty(_color);
|
||||
|
||||
if (dictionary.hasKey(SegmentsInfo.identifier)) {
|
||||
_segments = static_cast<int>(dictionary.value<double>(SegmentsInfo.identifier));
|
||||
}
|
||||
_segments = p.segments.value_or(_segments);
|
||||
_segments.onChange([&]() {
|
||||
if (_segments.value() % 2 == 1) {
|
||||
_segments = _segments - 1;
|
||||
@@ -120,11 +103,7 @@ RenderableSphericalGrid::RenderableSphericalGrid(const ghoul::Dictionary& dictio
|
||||
});
|
||||
addProperty(_segments);
|
||||
|
||||
if (dictionary.hasKey(LineWidthInfo.identifier)) {
|
||||
_lineWidth = static_cast<float>(
|
||||
dictionary.value<double>(LineWidthInfo.identifier)
|
||||
);
|
||||
}
|
||||
_lineWidth = p.lineWidth.value_or(_lineWidth);
|
||||
addProperty(_lineWidth);
|
||||
}
|
||||
|
||||
|
||||
@@ -34,6 +34,7 @@
|
||||
#include <ghoul/filesystem/filesystem.h>
|
||||
#include <ghoul/opengl/openglstatecache.h>
|
||||
#include <ghoul/opengl/programobject.h>
|
||||
#include <optional>
|
||||
|
||||
namespace {
|
||||
constexpr const char* ProgramName = "CartesianAxesProgram";
|
||||
@@ -56,39 +57,29 @@ namespace {
|
||||
"Z Color",
|
||||
"This value determines the color of the z axis."
|
||||
};
|
||||
|
||||
struct [[codegen::Dictionary(RenderableCartesianAxes)]] Parameters {
|
||||
// [[codegen::verbatim(XColorInfo.description)]]
|
||||
std::optional<glm::vec3> xColor;
|
||||
|
||||
// [[codegen::verbatim(YColorInfo.description)]]
|
||||
std::optional<glm::vec3> yColor;
|
||||
|
||||
// [[codegen::verbatim(ZColorInfo.description)]]
|
||||
std::optional<glm::vec3> zColor;
|
||||
|
||||
};
|
||||
#include "renderablecartesianaxes_codegen.cpp"
|
||||
} // namespace
|
||||
|
||||
namespace openspace {
|
||||
|
||||
documentation::Documentation RenderableCartesianAxes::Documentation() {
|
||||
using namespace documentation;
|
||||
return {
|
||||
"CartesianAxesProgram",
|
||||
"base_renderable_cartesianaxes",
|
||||
{
|
||||
{
|
||||
XColorInfo.identifier,
|
||||
new DoubleVector3Verifier,
|
||||
Optional::Yes,
|
||||
XColorInfo.description
|
||||
},
|
||||
{
|
||||
YColorInfo.identifier,
|
||||
new DoubleVector3Verifier,
|
||||
Optional::Yes,
|
||||
YColorInfo.description
|
||||
},
|
||||
{
|
||||
ZColorInfo.identifier,
|
||||
new DoubleVector3Verifier,
|
||||
Optional::Yes,
|
||||
ZColorInfo.description
|
||||
}
|
||||
}
|
||||
};
|
||||
documentation::Documentation doc = codegen::doc<Parameters>();
|
||||
doc.id = "base_renderable_cartesianaxes";
|
||||
return doc;
|
||||
}
|
||||
|
||||
|
||||
RenderableCartesianAxes::RenderableCartesianAxes(const ghoul::Dictionary& dictionary)
|
||||
: Renderable(dictionary)
|
||||
, _program(nullptr)
|
||||
@@ -111,27 +102,16 @@ RenderableCartesianAxes::RenderableCartesianAxes(const ghoul::Dictionary& dictio
|
||||
glm::vec3(1.f)
|
||||
)
|
||||
{
|
||||
documentation::testSpecificationAndThrow(
|
||||
Documentation(),
|
||||
dictionary,
|
||||
"RenderableCartesianAxes"
|
||||
);
|
||||
|
||||
if (dictionary.hasKey(XColorInfo.identifier)) {
|
||||
_xColor = dictionary.value<glm::dvec3>(XColorInfo.identifier);
|
||||
}
|
||||
const Parameters p = codegen::bake<Parameters>(dictionary);
|
||||
_xColor = p.xColor.value_or(_xColor);
|
||||
_xColor.setViewOption(properties::Property::ViewOptions::Color);
|
||||
addProperty(_xColor);
|
||||
|
||||
if (dictionary.hasKey(XColorInfo.identifier)) {
|
||||
_yColor = dictionary.value<glm::dvec3>(YColorInfo.identifier);
|
||||
}
|
||||
_yColor = p.yColor.value_or(_yColor);
|
||||
_yColor.setViewOption(properties::Property::ViewOptions::Color);
|
||||
addProperty(_yColor);
|
||||
|
||||
if (dictionary.hasKey(ZColorInfo.identifier)) {
|
||||
_zColor = dictionary.value<glm::dvec3>(ZColorInfo.identifier);
|
||||
}
|
||||
_zColor = p.zColor.value_or(_zColor);
|
||||
_zColor.setViewOption(properties::Property::ViewOptions::Color);
|
||||
addProperty(_zColor);
|
||||
}
|
||||
|
||||
@@ -46,10 +46,9 @@
|
||||
#include <ghoul/opengl/texture.h>
|
||||
#include <ghoul/opengl/textureunit.h>
|
||||
#include <glm/gtx/string_cast.hpp>
|
||||
#include <optional>
|
||||
|
||||
namespace {
|
||||
constexpr const char* _loggerCat = "base::RenderableLabels";
|
||||
|
||||
constexpr const char* MeterUnit = "m";
|
||||
constexpr const char* KilometerUnit = "Km";
|
||||
constexpr const char* MegameterUnit = "Mm";
|
||||
@@ -176,122 +175,91 @@ namespace {
|
||||
"Fade-In/-Out ending speed.",
|
||||
"Fade-In/-Out ending speed."
|
||||
};
|
||||
|
||||
struct [[codegen::Dictionary(RenderableLabels)]] Parameters {
|
||||
enum class BlendMode {
|
||||
Normal,
|
||||
Additive
|
||||
};
|
||||
|
||||
// [[codegen::verbatim(BlendModeInfo.description)]]
|
||||
std::optional<BlendMode> blendMode;
|
||||
|
||||
enum class Orientation {
|
||||
ViewDirection [[codegen::key("Camera View Direction")]],
|
||||
PositionNormal [[codegen::key("Camera Position Normal")]]
|
||||
};
|
||||
|
||||
// [[codegen::verbatim(LabelOrientationOptionInfo.description)]]
|
||||
std::optional<Orientation> labelOrientationOption;
|
||||
|
||||
// [[codegen::verbatim(LabelColorInfo.description)]]
|
||||
std::optional<glm::vec3> labelColor;
|
||||
|
||||
// [[codegen::verbatim(LabelTextInfo.description)]]
|
||||
std::optional<std::string> labelText;
|
||||
|
||||
// [[codegen::verbatim(FontSizeInfo.description)]]
|
||||
std::optional<float> fontSize;
|
||||
|
||||
// [[codegen::verbatim(LabelSizeInfo.description)]]
|
||||
std::optional<float> labelSize;
|
||||
|
||||
// [[codegen::verbatim(LabelMinSizeInfo.description)]]
|
||||
std::optional<float> labelMinSize;
|
||||
|
||||
// [[codegen::verbatim(LabelMaxSizeInfo.description)]]
|
||||
std::optional<float> labelMaxSize;
|
||||
|
||||
// [[codegen::verbatim(EnableFadingEffectInfo.description)]]
|
||||
std::optional<bool> enableFading;
|
||||
|
||||
// [[codegen::verbatim(PixelSizeControlInfo.description)]]
|
||||
std::optional<bool> enablePixelControl;
|
||||
|
||||
// [[codegen::verbatim(TransformationMatrixInfo.description)]]
|
||||
std::optional<glm::dmat4x4> transformationMatrix;
|
||||
|
||||
enum class Unit {
|
||||
Meter [[codegen::key("m")]],
|
||||
Kilometer [[codegen::key("Km")]],
|
||||
Megameter [[codegen::key("Mm")]],
|
||||
Gigameter [[codegen::key("Gm")]],
|
||||
Terameter [[codegen::key("Tm")]],
|
||||
Petameter [[codegen::key("Pm")]],
|
||||
AstronomicalUnit [[codegen::key("au")]],
|
||||
Parsec [[codegen::key("pc")]],
|
||||
KiloParsec [[codegen::key("Kpc")]],
|
||||
MegaParsec [[codgen::key("Mpc")]],
|
||||
GigaParsec [[codegen::key("Gpc")]],
|
||||
GigaLightyear [[codegen::key("Gly")]]
|
||||
};
|
||||
|
||||
// [[codegen::verbatim(FadeStartUnitOptionInfo.description)]]
|
||||
std::optional<Unit> fadeStartUnit;
|
||||
|
||||
// [[codegen::verbatim(FadeEndUnitOptionInfo.description)]]
|
||||
std::optional<Unit> fadeEndUnit;
|
||||
|
||||
// [[codegen::verbatim(FadeStartDistInfo.description)]]
|
||||
std::optional<float> fadeStartDistance;
|
||||
|
||||
// [[codegen::verbatim(FadeEndDistInfo.description)]]
|
||||
std::optional<float> fadeEndDistance;
|
||||
|
||||
// [[codegen::verbatim(FadeStartSpeedInfo.description)]]
|
||||
std::optional<float> fadeStartSpeed;
|
||||
|
||||
// [[codegen::verbatim(FadeEndSpeedInfo.description)]]
|
||||
std::optional<float> fadeEndSpeed;
|
||||
};
|
||||
#include "renderablelabels_codegen.cpp"
|
||||
} // namespace
|
||||
|
||||
namespace openspace {
|
||||
|
||||
documentation::Documentation RenderableLabels::Documentation() {
|
||||
using namespace documentation;
|
||||
return {
|
||||
"Renderable Labels",
|
||||
"base_renderable_labels",
|
||||
{
|
||||
{
|
||||
BlendModeInfo.identifier,
|
||||
new StringInListVerifier({ "Normal", "Additive" }),
|
||||
Optional::Yes,
|
||||
BlendModeInfo.description, // + " The default value is 'Normal'.",
|
||||
},
|
||||
{
|
||||
LabelOrientationOptionInfo.identifier,
|
||||
new StringInListVerifier(
|
||||
{ "Camera View Direction", "Camera Position Normal" }
|
||||
),
|
||||
Optional::Yes,
|
||||
LabelOrientationOptionInfo.description,
|
||||
},
|
||||
{
|
||||
LabelColorInfo.identifier,
|
||||
new DoubleVector3Verifier,
|
||||
Optional::Yes,
|
||||
LabelColorInfo.description,
|
||||
},
|
||||
{
|
||||
LabelTextInfo.identifier,
|
||||
new StringVerifier,
|
||||
Optional::Yes,
|
||||
LabelTextInfo.description
|
||||
},
|
||||
{
|
||||
FontSizeInfo.identifier,
|
||||
new DoubleVerifier,
|
||||
Optional::Yes,
|
||||
FontSizeInfo.description
|
||||
},
|
||||
{
|
||||
LabelSizeInfo.identifier,
|
||||
new DoubleVerifier,
|
||||
Optional::Yes,
|
||||
LabelSizeInfo.description
|
||||
},
|
||||
{
|
||||
LabelMinSizeInfo.identifier,
|
||||
new DoubleVerifier,
|
||||
Optional::Yes,
|
||||
LabelMinSizeInfo.description
|
||||
},
|
||||
{
|
||||
LabelMaxSizeInfo.identifier,
|
||||
new DoubleVerifier,
|
||||
Optional::Yes,
|
||||
LabelMaxSizeInfo.description
|
||||
},
|
||||
{
|
||||
EnableFadingEffectInfo.identifier,
|
||||
new BoolVerifier,
|
||||
Optional::Yes,
|
||||
EnableFadingEffectInfo.description
|
||||
},
|
||||
{
|
||||
PixelSizeControlInfo.identifier,
|
||||
new BoolVerifier,
|
||||
Optional::Yes,
|
||||
PixelSizeControlInfo.description
|
||||
},
|
||||
{
|
||||
FadeStartUnitOptionInfo.identifier,
|
||||
new StringInListVerifier(
|
||||
{ "m", "Km", "Mm", "Gm", "au", "Tm", "Pm", "pc", "Kpc", "Mpc",
|
||||
"Gpc", "Gly"}
|
||||
),
|
||||
Optional::Yes,
|
||||
FadeStartUnitOptionInfo.description,
|
||||
},
|
||||
{
|
||||
FadeEndUnitOptionInfo.identifier,
|
||||
new StringInListVerifier(
|
||||
{"m", "Km", "Mm", "Gm", "au", "Tm", "Pm", "pc", "Kpc", "Mpc",
|
||||
"Gpc", "Gly"}
|
||||
),
|
||||
Optional::Yes,
|
||||
FadeEndUnitOptionInfo.description,
|
||||
},
|
||||
{
|
||||
FadeStartDistInfo.identifier,
|
||||
new DoubleVerifier,
|
||||
Optional::Yes,
|
||||
FadeStartDistInfo.description
|
||||
},
|
||||
{
|
||||
FadeEndDistInfo.identifier,
|
||||
new DoubleVerifier,
|
||||
Optional::Yes,
|
||||
FadeEndDistInfo.description
|
||||
},
|
||||
{
|
||||
FadeStartSpeedInfo.identifier,
|
||||
new DoubleVerifier,
|
||||
Optional::Yes,
|
||||
FadeStartSpeedInfo.description
|
||||
},
|
||||
{
|
||||
FadeEndSpeedInfo.identifier,
|
||||
new DoubleVerifier,
|
||||
Optional::Yes,
|
||||
FadeEndSpeedInfo.description
|
||||
},
|
||||
}
|
||||
};
|
||||
return codegen::doc<Parameters>();
|
||||
}
|
||||
|
||||
RenderableLabels::RenderableLabels(const ghoul::Dictionary& dictionary)
|
||||
@@ -327,11 +295,7 @@ RenderableLabels::RenderableLabels(const ghoul::Dictionary& dictionary)
|
||||
properties::OptionProperty::DisplayType::Dropdown
|
||||
)
|
||||
{
|
||||
documentation::testSpecificationAndThrow(
|
||||
Documentation(),
|
||||
dictionary,
|
||||
"RenderableLabels"
|
||||
);
|
||||
const Parameters p = codegen::bake<Parameters>(dictionary);
|
||||
|
||||
addProperty(_opacity);
|
||||
registerUpdateRenderBinFromOpacity();
|
||||
@@ -353,13 +317,14 @@ RenderableLabels::RenderableLabels(const ghoul::Dictionary& dictionary)
|
||||
}
|
||||
});
|
||||
|
||||
if (dictionary.hasKey(BlendModeInfo.identifier)) {
|
||||
const std::string v = dictionary.value<std::string>(BlendModeInfo.identifier);
|
||||
if (v == "Normal") {
|
||||
_blendMode = BlendModeNormal;
|
||||
}
|
||||
else if (v == "Additive") {
|
||||
_blendMode = BlendModeAdditive;
|
||||
if (p.blendMode.has_value()) {
|
||||
switch (*p.blendMode) {
|
||||
case Parameters::BlendMode::Normal:
|
||||
_blendMode = BlendModeNormal;
|
||||
break;
|
||||
case Parameters::BlendMode::Additive:
|
||||
_blendMode = BlendModeAdditive;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -369,35 +334,26 @@ RenderableLabels::RenderableLabels(const ghoul::Dictionary& dictionary)
|
||||
_labelOrientationOption.addOption(NormalDirection, "Camera Position Normal");
|
||||
|
||||
_labelOrientationOption = NormalDirection;
|
||||
if (dictionary.hasValue<std::string>(LabelOrientationOptionInfo.identifier)) {
|
||||
const std::string o = dictionary.value<std::string>(
|
||||
LabelOrientationOptionInfo.identifier
|
||||
);
|
||||
|
||||
if (o == "Camera View Direction") {
|
||||
_labelOrientationOption = ViewDirection;
|
||||
}
|
||||
else if (o == "Camera Position Normal") {
|
||||
_labelOrientationOption = NormalDirection;
|
||||
if (p.labelOrientationOption.has_value()) {
|
||||
switch (*p.labelOrientationOption) {
|
||||
case Parameters::Orientation::ViewDirection:
|
||||
_labelOrientationOption = ViewDirection;
|
||||
break;
|
||||
case Parameters::Orientation::PositionNormal:
|
||||
_labelOrientationOption = NormalDirection;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (dictionary.hasKey(LabelTextInfo.identifier)) {
|
||||
_labelText = dictionary.value<std::string>(LabelTextInfo.identifier);
|
||||
}
|
||||
addProperty(_labelText);
|
||||
|
||||
addProperty(_labelOrientationOption);
|
||||
|
||||
_labelText = p.labelText.value_or(_labelText);
|
||||
addProperty(_labelText);
|
||||
|
||||
_labelColor = p.labelColor.value_or(_labelColor);
|
||||
_labelColor.setViewOption(properties::Property::ViewOptions::Color);
|
||||
if (dictionary.hasKey(LabelColorInfo.identifier)) {
|
||||
_labelColor = dictionary.value<glm::dvec3>(LabelColorInfo.identifier);
|
||||
}
|
||||
addProperty(_labelColor);
|
||||
|
||||
if (dictionary.hasKey(FontSizeInfo.identifier)) {
|
||||
_fontSize = static_cast<float>(dictionary.value<double>(FontSizeInfo.identifier));
|
||||
}
|
||||
_fontSize = p.fontSize.value_or(_fontSize);
|
||||
_fontSize.onChange([&]() {
|
||||
_font = global::fontManager->font(
|
||||
"Mono",
|
||||
@@ -408,49 +364,28 @@ RenderableLabels::RenderableLabels(const ghoul::Dictionary& dictionary)
|
||||
});
|
||||
addProperty(_fontSize);
|
||||
|
||||
if (dictionary.hasKey(LabelSizeInfo.identifier)) {
|
||||
_labelSize = static_cast<float>(
|
||||
dictionary.value<double>(LabelSizeInfo.identifier)
|
||||
);
|
||||
}
|
||||
_labelSize = p.labelSize.value_or(_labelSize);
|
||||
addProperty(_labelSize);
|
||||
|
||||
if (dictionary.hasKey(LabelMinSizeInfo.identifier)) {
|
||||
_labelMinSize = static_cast<float>(
|
||||
dictionary.value<double>(LabelMinSizeInfo.identifier)
|
||||
);
|
||||
}
|
||||
_labelMinSize = p.labelMinSize.value_or(_labelMinSize);
|
||||
addProperty(_labelMinSize);
|
||||
|
||||
if (dictionary.hasKey(LabelMaxSizeInfo.identifier)) {
|
||||
_labelMaxSize = static_cast<float>(
|
||||
dictionary.value<double>(LabelMaxSizeInfo.identifier)
|
||||
);
|
||||
}
|
||||
_labelMaxSize = p.labelMaxSize.value_or(_labelMaxSize);
|
||||
addProperty(_labelMaxSize);
|
||||
|
||||
if (dictionary.hasKey(TransformationMatrixInfo.identifier)) {
|
||||
_transformationMatrix = dictionary.value<glm::dmat4>(
|
||||
TransformationMatrixInfo.identifier
|
||||
);
|
||||
}
|
||||
_transformationMatrix = p.transformationMatrix.value_or(_transformationMatrix);
|
||||
|
||||
if (dictionary.hasKey(PixelSizeControlInfo.identifier)) {
|
||||
_pixelSizeControl = dictionary.value<bool>(PixelSizeControlInfo.identifier);
|
||||
_pixelSizeControl = p.enablePixelControl.value_or(_pixelSizeControl);
|
||||
if (_pixelSizeControl) {
|
||||
// @TODO (abock, 2021-01-28) I don't know why we only add the property if the
|
||||
// pixel control is enabled, but I think this is an error
|
||||
addProperty(_pixelSizeControl);
|
||||
}
|
||||
|
||||
if (dictionary.hasKey(EnableFadingEffectInfo.identifier)) {
|
||||
_enableFadingEffect = dictionary.value<bool>(EnableFadingEffectInfo.identifier);
|
||||
}
|
||||
_enableFadingEffect = p.enableFading.value_or(_enableFadingEffect);
|
||||
addProperty(_enableFadingEffect);
|
||||
|
||||
if (dictionary.hasKey(FadeStartDistInfo.identifier)) {
|
||||
_fadeStartDistance = static_cast<float>(
|
||||
dictionary.value<double>(FadeStartDistInfo.identifier)
|
||||
);
|
||||
}
|
||||
|
||||
_fadeStartDistance = p.fadeStartDistance.value_or(_fadeStartDistance);
|
||||
addProperty(_fadeStartDistance);
|
||||
|
||||
_fadeStartUnitOption.addOption(Meter, MeterUnit);
|
||||
@@ -466,72 +401,56 @@ RenderableLabels::RenderableLabels(const ghoul::Dictionary& dictionary)
|
||||
_fadeStartUnitOption.addOption(Gigaparsec, GigaparsecUnit);
|
||||
_fadeStartUnitOption.addOption(GigalightYears, GigalightyearUnit);
|
||||
|
||||
_fadeStartUnitOption = AU;
|
||||
|
||||
if (dictionary.hasKey(FadeStartUnitOptionInfo.identifier)) {
|
||||
std::string unit = dictionary.value<std::string>(
|
||||
FadeStartUnitOptionInfo.identifier
|
||||
);
|
||||
if (unit == MeterUnit) {
|
||||
_fadeStartUnitOption = Meter;
|
||||
}
|
||||
else if (unit == KilometerUnit) {
|
||||
_fadeStartUnitOption = Kilometer;
|
||||
}
|
||||
else if (unit == MegameterUnit) {
|
||||
_fadeStartUnitOption = Megameter;
|
||||
}
|
||||
else if (unit == GigameterUnit) {
|
||||
_fadeStartUnitOption = Gigameter;
|
||||
}
|
||||
else if (unit == AstronomicalUnit) {
|
||||
_fadeStartUnitOption = AU;
|
||||
}
|
||||
else if (unit == TerameterUnit) {
|
||||
_fadeStartUnitOption = Terameter;
|
||||
}
|
||||
else if (unit == PetameterUnit) {
|
||||
_fadeStartUnitOption = Petameter;
|
||||
}
|
||||
else if (unit == ParsecUnit) {
|
||||
_fadeStartUnitOption = Parsec;
|
||||
}
|
||||
else if (unit == KiloparsecUnit) {
|
||||
_fadeStartUnitOption = Kiloparsec;
|
||||
}
|
||||
else if (unit == MegaparsecUnit) {
|
||||
_fadeStartUnitOption = Megaparsec;
|
||||
}
|
||||
else if (unit == GigaparsecUnit) {
|
||||
_fadeStartUnitOption = Gigaparsec;
|
||||
}
|
||||
else if (unit == GigalightyearUnit) {
|
||||
_fadeStartUnitOption = GigalightYears;
|
||||
}
|
||||
else {
|
||||
LWARNING(
|
||||
"No unit given for RenderableLabels. Using kilometer as units."
|
||||
);
|
||||
_fadeStartUnitOption = Kilometer;
|
||||
if (p.fadeStartUnit.has_value()) {
|
||||
switch (*p.fadeStartUnit) {
|
||||
case Parameters::Unit::Meter:
|
||||
_fadeStartUnitOption = Meter;
|
||||
break;
|
||||
case Parameters::Unit::Kilometer:
|
||||
_fadeStartUnitOption = Kilometer;
|
||||
break;
|
||||
case Parameters::Unit::Megameter:
|
||||
_fadeStartUnitOption = Megameter;
|
||||
break;
|
||||
case Parameters::Unit::Gigameter:
|
||||
_fadeStartUnitOption = Gigameter;
|
||||
break;
|
||||
case Parameters::Unit::Terameter:
|
||||
_fadeStartUnitOption = Terameter;
|
||||
break;
|
||||
case Parameters::Unit::Petameter:
|
||||
_fadeStartUnitOption = Petameter;
|
||||
break;
|
||||
case Parameters::Unit::AstronomicalUnit:
|
||||
_fadeStartUnitOption = AU;
|
||||
break;
|
||||
case Parameters::Unit::Parsec:
|
||||
_fadeStartUnitOption = Parsec;
|
||||
break;
|
||||
case Parameters::Unit::KiloParsec:
|
||||
_fadeStartUnitOption = Kiloparsec;
|
||||
break;
|
||||
case Parameters::Unit::MegaParsec:
|
||||
_fadeStartUnitOption = Megaparsec;
|
||||
break;
|
||||
case Parameters::Unit::GigaParsec:
|
||||
_fadeStartUnitOption = Gigaparsec;
|
||||
break;
|
||||
case Parameters::Unit::GigaLightyear:
|
||||
_fadeStartUnitOption = GigalightYears;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
else {
|
||||
_fadeStartUnitOption = AU;
|
||||
}
|
||||
addProperty(_fadeStartUnitOption);
|
||||
|
||||
if (dictionary.hasKey(FadeStartSpeedInfo.identifier)) {
|
||||
_fadeStartSpeed = static_cast<float>(
|
||||
dictionary.value<double>(FadeStartSpeedInfo.identifier)
|
||||
);
|
||||
}
|
||||
|
||||
_fadeStartSpeed = p.fadeStartSpeed.value_or(_fadeStartSpeed);
|
||||
addProperty(_fadeStartSpeed);
|
||||
|
||||
if (dictionary.hasKey(FadeEndDistInfo.identifier)) {
|
||||
_fadeEndDistance = static_cast<float>(
|
||||
dictionary.value<double>(FadeEndDistInfo.identifier)
|
||||
);
|
||||
}
|
||||
|
||||
_fadeEndDistance = p.fadeEndDistance.value_or(_fadeEndDistance);
|
||||
addProperty(_fadeEndDistance);
|
||||
|
||||
_fadeEndUnitOption.addOption(Meter, MeterUnit);
|
||||
@@ -547,64 +466,53 @@ RenderableLabels::RenderableLabels(const ghoul::Dictionary& dictionary)
|
||||
_fadeEndUnitOption.addOption(Gigaparsec, GigaparsecUnit);
|
||||
_fadeEndUnitOption.addOption(GigalightYears, GigalightyearUnit);
|
||||
|
||||
_fadeEndUnitOption = AU;
|
||||
|
||||
if (dictionary.hasKey(FadeEndUnitOptionInfo.identifier)) {
|
||||
std::string unit = dictionary.value<std::string>(
|
||||
FadeEndUnitOptionInfo.identifier
|
||||
);
|
||||
if (unit == MeterUnit) {
|
||||
_fadeEndUnitOption = Meter;
|
||||
}
|
||||
else if (unit == KilometerUnit) {
|
||||
_fadeEndUnitOption = Kilometer;
|
||||
}
|
||||
else if (unit == MegameterUnit) {
|
||||
_fadeEndUnitOption = Megameter;
|
||||
}
|
||||
else if (unit == GigameterUnit) {
|
||||
_fadeEndUnitOption = Gigameter;
|
||||
}
|
||||
else if (unit == AstronomicalUnit) {
|
||||
_fadeEndUnitOption = AU;
|
||||
}
|
||||
else if (unit == TerameterUnit) {
|
||||
_fadeEndUnitOption = Terameter;
|
||||
}
|
||||
else if (unit == PetameterUnit) {
|
||||
_fadeEndUnitOption = Petameter;
|
||||
}
|
||||
else if (unit == ParsecUnit) {
|
||||
_fadeEndUnitOption = Parsec;
|
||||
}
|
||||
else if (unit == KiloparsecUnit) {
|
||||
_fadeEndUnitOption = Kiloparsec;
|
||||
}
|
||||
else if (unit == MegaparsecUnit) {
|
||||
_fadeEndUnitOption = Megaparsec;
|
||||
}
|
||||
else if (unit == GigaparsecUnit) {
|
||||
_fadeEndUnitOption = Gigaparsec;
|
||||
}
|
||||
else if (unit == GigalightyearUnit) {
|
||||
_fadeEndUnitOption = GigalightYears;
|
||||
}
|
||||
else {
|
||||
LWARNING(
|
||||
"No unit given for RenderableLabels. Using kilometer as units."
|
||||
);
|
||||
_fadeEndUnitOption = Kilometer;
|
||||
if (p.fadeEndUnit.has_value()) {
|
||||
switch (*p.fadeEndUnit) {
|
||||
case Parameters::Unit::Meter:
|
||||
_fadeStartUnitOption = Meter;
|
||||
break;
|
||||
case Parameters::Unit::Kilometer:
|
||||
_fadeStartUnitOption = Kilometer;
|
||||
break;
|
||||
case Parameters::Unit::Megameter:
|
||||
_fadeStartUnitOption = Megameter;
|
||||
break;
|
||||
case Parameters::Unit::Gigameter:
|
||||
_fadeStartUnitOption = Gigameter;
|
||||
break;
|
||||
case Parameters::Unit::Terameter:
|
||||
_fadeStartUnitOption = Terameter;
|
||||
break;
|
||||
case Parameters::Unit::Petameter:
|
||||
_fadeStartUnitOption = Petameter;
|
||||
break;
|
||||
case Parameters::Unit::AstronomicalUnit:
|
||||
_fadeStartUnitOption = AU;
|
||||
break;
|
||||
case Parameters::Unit::Parsec:
|
||||
_fadeStartUnitOption = Parsec;
|
||||
break;
|
||||
case Parameters::Unit::KiloParsec:
|
||||
_fadeEndUnitOption = Kiloparsec;
|
||||
break;
|
||||
case Parameters::Unit::MegaParsec:
|
||||
_fadeEndUnitOption = Megaparsec;
|
||||
break;
|
||||
case Parameters::Unit::GigaParsec:
|
||||
_fadeEndUnitOption = Gigaparsec;
|
||||
break;
|
||||
case Parameters::Unit::GigaLightyear:
|
||||
_fadeEndUnitOption = GigalightYears;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
else {
|
||||
_fadeEndUnitOption = AU;
|
||||
}
|
||||
addProperty(_fadeEndUnitOption);
|
||||
|
||||
if (dictionary.hasKey(FadeEndSpeedInfo.identifier)) {
|
||||
_fadeEndSpeed = static_cast<float>(
|
||||
dictionary.value<double>(FadeEndSpeedInfo.identifier)
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
_fadeEndSpeed = p.fadeEndSpeed.value_or(_fadeEndSpeed);
|
||||
addProperty(_fadeEndSpeed);
|
||||
}
|
||||
|
||||
|
||||
@@ -84,42 +84,29 @@ namespace {
|
||||
glm::dvec3 diffPos = worldPos - anchorNodePos;
|
||||
return diffPos;
|
||||
}
|
||||
|
||||
struct [[codegen::Dictionary(RenderableNodeLine)]] Parameters {
|
||||
// [[codegen::verbatim(StartNodeInfo.description)]]
|
||||
std::optional<std::string> startNode;
|
||||
|
||||
// [[codegen::verbatim(EndNodeInfo.description)]]
|
||||
std::optional<std::string> endNode;
|
||||
|
||||
// [[codegen::verbatim(LineColorInfo.description)]]
|
||||
std::optional<glm::vec3> color;
|
||||
|
||||
// [[codegen::verbatim(LineWidthInfo.description)]]
|
||||
std::optional<float> lineWidth;
|
||||
};
|
||||
#include "renderablenodeline_codegen.cpp"
|
||||
} // namespace
|
||||
|
||||
namespace openspace {
|
||||
|
||||
documentation::Documentation RenderableNodeLine::Documentation() {
|
||||
using namespace documentation;
|
||||
return {
|
||||
"Renderable Node Line",
|
||||
"base_renderable_renderablenodeline",
|
||||
{
|
||||
{
|
||||
StartNodeInfo.identifier,
|
||||
new StringVerifier,
|
||||
Optional::Yes,
|
||||
StartNodeInfo.description
|
||||
},
|
||||
{
|
||||
EndNodeInfo.identifier,
|
||||
new StringVerifier,
|
||||
Optional::Yes,
|
||||
EndNodeInfo.description
|
||||
},
|
||||
{
|
||||
LineColorInfo.identifier,
|
||||
new DoubleVector3Verifier,
|
||||
Optional::Yes,
|
||||
LineColorInfo.description
|
||||
},
|
||||
{
|
||||
LineWidthInfo.identifier,
|
||||
new DoubleVerifier,
|
||||
Optional::Yes,
|
||||
LineWidthInfo.description
|
||||
}
|
||||
}
|
||||
};
|
||||
documentation::Documentation doc = codegen::doc<Parameters>();
|
||||
doc.id = "base_renderable_renderablenodeline";
|
||||
return doc;
|
||||
}
|
||||
|
||||
RenderableNodeLine::RenderableNodeLine(const ghoul::Dictionary& dictionary)
|
||||
@@ -129,36 +116,22 @@ RenderableNodeLine::RenderableNodeLine(const ghoul::Dictionary& dictionary)
|
||||
, _lineColor(LineColorInfo, glm::vec3(1.f), glm::vec3(0.f), glm::vec3(1.f))
|
||||
, _lineWidth(LineWidthInfo, 2.f, 1.f, 20.f)
|
||||
{
|
||||
documentation::testSpecificationAndThrow(
|
||||
Documentation(),
|
||||
dictionary,
|
||||
"RenderableNodeLine"
|
||||
);
|
||||
|
||||
if (dictionary.hasKey(StartNodeInfo.identifier)) {
|
||||
_start = dictionary.value<std::string>(StartNodeInfo.identifier);
|
||||
}
|
||||
|
||||
if (dictionary.hasKey(EndNodeInfo.identifier)) {
|
||||
_end = dictionary.value<std::string>(EndNodeInfo.identifier);
|
||||
}
|
||||
|
||||
if (dictionary.hasKey(LineColorInfo.identifier)) {
|
||||
_lineColor = dictionary.value<glm::dvec3>(LineColorInfo.identifier);
|
||||
}
|
||||
if (dictionary.hasKey(LineWidthInfo.identifier)) {
|
||||
_lineWidth = static_cast<float>(
|
||||
dictionary.value<double>(LineWidthInfo.identifier)
|
||||
);
|
||||
}
|
||||
const Parameters p = codegen::bake<Parameters>(dictionary);
|
||||
|
||||
_start = p.startNode.value_or(_start);
|
||||
_start.onChange([&]() { validateNodes(); });
|
||||
_end.onChange([&]() { validateNodes(); });
|
||||
|
||||
addProperty(_start);
|
||||
|
||||
_end = p.endNode.value_or(_end);
|
||||
_end.onChange([&]() { validateNodes(); });
|
||||
addProperty(_end);
|
||||
|
||||
_lineColor = p.color.value_or(_lineColor);
|
||||
addProperty(_lineColor);
|
||||
|
||||
_lineWidth = p.lineWidth.value_or(_lineWidth);
|
||||
addProperty(_lineWidth);
|
||||
|
||||
addProperty(_opacity);
|
||||
}
|
||||
|
||||
|
||||
@@ -40,6 +40,7 @@
|
||||
#include <ghoul/opengl/textureunit.h>
|
||||
#include <ghoul/glm.h>
|
||||
#include <glm/gtx/string_cast.hpp>
|
||||
#include <optional>
|
||||
|
||||
namespace {
|
||||
constexpr const char* ProgramName = "Plane";
|
||||
@@ -68,36 +69,30 @@ namespace {
|
||||
"Blending Mode",
|
||||
"This determines the blending mode that is applied to this plane."
|
||||
};
|
||||
|
||||
struct [[codegen::Dictionary(RenderablePlane)]] Parameters {
|
||||
// [[codegen::verbatim(BillboardInfo.description)]]
|
||||
std::optional<bool> billboard;
|
||||
|
||||
// [[codegen::verbatim(SizeInfo.description)]]
|
||||
float size;
|
||||
|
||||
enum class BlendMode {
|
||||
Normal,
|
||||
Additive
|
||||
};
|
||||
// [[codegen::verbatim(BlendModeInfo.description)]]
|
||||
std::optional<BlendMode> blendMode;
|
||||
};
|
||||
#include "renderableplane_codegen.cpp"
|
||||
} // namespace
|
||||
|
||||
namespace openspace {
|
||||
|
||||
documentation::Documentation RenderablePlane::Documentation() {
|
||||
using namespace documentation;
|
||||
return {
|
||||
"Renderable Plane",
|
||||
"base_renderable_plane",
|
||||
{
|
||||
{
|
||||
SizeInfo.identifier,
|
||||
new DoubleVerifier,
|
||||
Optional::No,
|
||||
SizeInfo.description
|
||||
},
|
||||
{
|
||||
BillboardInfo.identifier,
|
||||
new BoolVerifier,
|
||||
Optional::Yes,
|
||||
BillboardInfo.description
|
||||
},
|
||||
{
|
||||
BlendModeInfo.identifier,
|
||||
new StringInListVerifier({ "Normal", "Additive" }),
|
||||
Optional::Yes,
|
||||
BlendModeInfo.description, // + " The default value is 'Normal'.",
|
||||
}
|
||||
}
|
||||
};
|
||||
documentation::Documentation doc = codegen::doc<Parameters>();
|
||||
doc.id = "base_renderable_plane";
|
||||
return doc;
|
||||
}
|
||||
|
||||
RenderablePlane::RenderablePlane(const ghoul::Dictionary& dictionary)
|
||||
@@ -106,20 +101,13 @@ RenderablePlane::RenderablePlane(const ghoul::Dictionary& dictionary)
|
||||
, _billboard(BillboardInfo, false)
|
||||
, _size(SizeInfo, 10.f, 0.f, 1e25f)
|
||||
{
|
||||
documentation::testSpecificationAndThrow(
|
||||
Documentation(),
|
||||
dictionary,
|
||||
"RenderablePlane"
|
||||
);
|
||||
Parameters p = codegen::bake<Parameters>(dictionary);
|
||||
|
||||
addProperty(_opacity);
|
||||
registerUpdateRenderBinFromOpacity();
|
||||
|
||||
_size = static_cast<float>(dictionary.value<double>(SizeInfo.identifier));
|
||||
|
||||
if (dictionary.hasKey(BillboardInfo.identifier)) {
|
||||
_billboard = dictionary.value<bool>(BillboardInfo.identifier);
|
||||
}
|
||||
_size = p.size;
|
||||
_billboard = p.billboard.value_or(_billboard);
|
||||
|
||||
_blendMode.addOptions({
|
||||
{ BlendModeNormal, "Normal" },
|
||||
@@ -144,12 +132,11 @@ RenderablePlane::RenderablePlane(const ghoul::Dictionary& dictionary)
|
||||
}
|
||||
});
|
||||
|
||||
if (dictionary.hasKey(BlendModeInfo.identifier)) {
|
||||
const std::string v = dictionary.value<std::string>(BlendModeInfo.identifier);
|
||||
if (v == "Normal") {
|
||||
if (p.blendMode.has_value()) {
|
||||
if (*p.blendMode == Parameters::BlendMode::Normal) {
|
||||
_blendMode = BlendModeNormal;
|
||||
}
|
||||
else if (v == "Additive") {
|
||||
else if (*p.blendMode == Parameters::BlendMode::Additive) {
|
||||
_blendMode = BlendModeAdditive;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -35,10 +35,9 @@
|
||||
#include <ghoul/misc/profiling.h>
|
||||
#include <ghoul/opengl/texture.h>
|
||||
#include <fstream>
|
||||
#include <optional>
|
||||
|
||||
namespace {
|
||||
constexpr const char* KeyLazyLoading = "LazyLoading";
|
||||
|
||||
constexpr openspace::properties::Property::PropertyInfo TextureInfo = {
|
||||
"Texture",
|
||||
"Texture",
|
||||
@@ -52,54 +51,47 @@ namespace {
|
||||
"This value specifies if the plane should be rendered in the Background,"
|
||||
"Opaque, Transparent, or Overlay rendering step."
|
||||
};
|
||||
|
||||
struct [[codegen::Dictionary(RenderablePlaneImageLocal)]] Parameters {
|
||||
// [[codegen::verbatim(TextureInfo.description)]]
|
||||
std::string texture;
|
||||
|
||||
enum class RenderType {
|
||||
Background,
|
||||
Opaque,
|
||||
PreDeferredTransparency,
|
||||
PostDeferredTransparency,
|
||||
Overlay
|
||||
};
|
||||
|
||||
// [[codegen::verbatim(RenderableTypeInfo.description)]]
|
||||
std::optional<RenderType> renderType [[codegen::key("RenderableType")]];
|
||||
|
||||
// If this value is set to 'true', the image for this plane will not be loaded at
|
||||
// startup but rather when image is shown for the first time. Additionally, if the
|
||||
// plane is hidden, the image will automatically be unloaded
|
||||
std::optional<bool> lazyLoading;
|
||||
};
|
||||
#include "renderableplaneimagelocal_codegen.cpp"
|
||||
} // namespace
|
||||
|
||||
namespace openspace {
|
||||
|
||||
documentation::Documentation RenderablePlaneImageLocal::Documentation() {
|
||||
using namespace documentation;
|
||||
return {
|
||||
"Renderable Plane Image Local",
|
||||
"base_renderable_plane_image_local",
|
||||
{
|
||||
{
|
||||
TextureInfo.identifier,
|
||||
new StringVerifier,
|
||||
Optional::No,
|
||||
TextureInfo.description
|
||||
},
|
||||
{
|
||||
RenderableTypeInfo.identifier,
|
||||
new StringVerifier,
|
||||
Optional::Yes,
|
||||
RenderableTypeInfo.description
|
||||
},
|
||||
{
|
||||
KeyLazyLoading,
|
||||
new BoolVerifier,
|
||||
Optional::Yes,
|
||||
"If this value is set to 'true', the image for this plane will not be "
|
||||
"loaded at startup but rather when image is shown for the first time. "
|
||||
"Additionally, if the plane is hidden, the image will automatically be "
|
||||
"unloaded"
|
||||
}
|
||||
}
|
||||
};
|
||||
documentation::Documentation doc = codegen::doc<Parameters>();
|
||||
doc.id = "base_renderable_plane_image_local";
|
||||
return doc;
|
||||
}
|
||||
|
||||
RenderablePlaneImageLocal::RenderablePlaneImageLocal(const ghoul::Dictionary& dictionary)
|
||||
: RenderablePlane(dictionary)
|
||||
, _texturePath(TextureInfo)
|
||||
{
|
||||
documentation::testSpecificationAndThrow(
|
||||
Documentation(),
|
||||
dictionary,
|
||||
"RenderablePlaneImageLocal"
|
||||
);
|
||||
const Parameters p = codegen::bake<Parameters>(dictionary);
|
||||
|
||||
addProperty(_blendMode);
|
||||
|
||||
_texturePath = absPath(dictionary.value<std::string>(TextureInfo.identifier));
|
||||
_texturePath = absPath(p.texture);
|
||||
_textureFile = std::make_unique<ghoul::filesystem::File>(_texturePath);
|
||||
|
||||
addProperty(_texturePath);
|
||||
@@ -108,44 +100,40 @@ RenderablePlaneImageLocal::RenderablePlaneImageLocal(const ghoul::Dictionary& di
|
||||
[this](const ghoul::filesystem::File&) { _textureIsDirty = true; }
|
||||
);
|
||||
|
||||
if (dictionary.hasKey(RenderableTypeInfo.identifier)) {
|
||||
std::string renderType = dictionary.value<std::string>(
|
||||
RenderableTypeInfo.identifier
|
||||
);
|
||||
if (renderType == "Background") {
|
||||
setRenderBin(Renderable::RenderBin::Background);
|
||||
}
|
||||
else if (renderType == "Opaque") {
|
||||
setRenderBin(Renderable::RenderBin::Opaque);
|
||||
}
|
||||
else if (renderType == "PreDeferredTransparent") {
|
||||
setRenderBin(Renderable::RenderBin::PreDeferredTransparent);
|
||||
}
|
||||
else if (renderType == "PostDeferredTransparent") {
|
||||
setRenderBin(Renderable::RenderBin::PostDeferredTransparent);
|
||||
}
|
||||
else if (renderType == "Overlay") {
|
||||
setRenderBin(Renderable::RenderBin::Overlay);
|
||||
if (p.renderType.has_value()) {
|
||||
switch (*p.renderType) {
|
||||
case Parameters::RenderType::Background:
|
||||
setRenderBin(Renderable::RenderBin::Background);
|
||||
break;
|
||||
case Parameters::RenderType::Opaque:
|
||||
setRenderBin(Renderable::RenderBin::Opaque);
|
||||
break;
|
||||
case Parameters::RenderType::PreDeferredTransparency:
|
||||
setRenderBin(Renderable::RenderBin::PreDeferredTransparent);
|
||||
break;
|
||||
case Parameters::RenderType::PostDeferredTransparency:
|
||||
setRenderBin(Renderable::RenderBin::PostDeferredTransparent);
|
||||
break;
|
||||
case Parameters::RenderType::Overlay:
|
||||
setRenderBin(Renderable::RenderBin::Overlay);
|
||||
break;
|
||||
}
|
||||
}
|
||||
else {
|
||||
setRenderBin(Renderable::RenderBin::Opaque);
|
||||
}
|
||||
|
||||
if (dictionary.hasKey(KeyLazyLoading)) {
|
||||
_isLoadingLazily = dictionary.value<bool>(KeyLazyLoading);
|
||||
|
||||
if (_isLoadingLazily) {
|
||||
_enabled.onChange([this]() {
|
||||
if (!_enabled) {
|
||||
BaseModule::TextureManager.release(_texture);
|
||||
_texture = nullptr;
|
||||
}
|
||||
if (_enabled) {
|
||||
_textureIsDirty = true;
|
||||
}
|
||||
});
|
||||
}
|
||||
_isLoadingLazily = p.lazyLoading.value_or(_isLoadingLazily);
|
||||
if (_isLoadingLazily) {
|
||||
_enabled.onChange([this]() {
|
||||
if (!_enabled) {
|
||||
BaseModule::TextureManager.release(_texture);
|
||||
_texture = nullptr;
|
||||
}
|
||||
if (_enabled) {
|
||||
_textureIsDirty = true;
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -41,24 +41,20 @@ namespace {
|
||||
"this value is changed, the image at the new path will automatically be loaded "
|
||||
"and displayed."
|
||||
};
|
||||
|
||||
struct [[codegen::Dictionary(RenderablePlaneImageOnline)]] Parameters {
|
||||
// [[codegen::verbatim(TextureInfo.description)]]
|
||||
std::string url [[codegen::key("URL")]];
|
||||
};
|
||||
#include "renderableplaneimageonline_codegen.cpp"
|
||||
} // namespace
|
||||
|
||||
namespace openspace {
|
||||
|
||||
documentation::Documentation RenderablePlaneImageOnline::Documentation() {
|
||||
using namespace documentation;
|
||||
return {
|
||||
"Renderable Plane Image Online",
|
||||
"base_renderable_plane_image_online",
|
||||
{
|
||||
{
|
||||
TextureInfo.identifier,
|
||||
new StringVerifier,
|
||||
Optional::No,
|
||||
TextureInfo.description,
|
||||
}
|
||||
}
|
||||
};
|
||||
documentation::Documentation doc = codegen::doc<Parameters>();
|
||||
doc.id = "base_renderable_plane_image_online";
|
||||
return doc;
|
||||
}
|
||||
|
||||
RenderablePlaneImageOnline::RenderablePlaneImageOnline(
|
||||
@@ -66,20 +62,12 @@ RenderablePlaneImageOnline::RenderablePlaneImageOnline(
|
||||
: RenderablePlane(dictionary)
|
||||
, _texturePath(TextureInfo)
|
||||
{
|
||||
documentation::testSpecificationAndThrow(
|
||||
Documentation(),
|
||||
dictionary,
|
||||
"RenderablePlaneImageOnline"
|
||||
);
|
||||
const Parameters p = codegen::bake<Parameters>(dictionary);
|
||||
|
||||
_texturePath.onChange([this]() { _textureIsDirty = true; });
|
||||
addProperty(_texturePath);
|
||||
|
||||
std::string texturePath;
|
||||
if (dictionary.hasKey(TextureInfo.identifier)) {
|
||||
_texturePath = dictionary.value<std::string>(TextureInfo.identifier);
|
||||
}
|
||||
|
||||
_texturePath = p.url;
|
||||
addProperty(_texturePath);
|
||||
}
|
||||
|
||||
|
||||
@@ -38,6 +38,7 @@
|
||||
#include <ghoul/opengl/texture.h>
|
||||
#include <ghoul/opengl/textureunit.h>
|
||||
#include <ghoul/opengl/programobject.h>
|
||||
#include <optional>
|
||||
|
||||
namespace {
|
||||
constexpr const char* ProgramName = "Sphere";
|
||||
@@ -117,81 +118,55 @@ namespace {
|
||||
"Sets the current sphere rendering as a background rendering type",
|
||||
"Enables/Disables background rendering."
|
||||
};
|
||||
|
||||
struct [[codegen::Dictionary(RenderableSphere)]] Parameters {
|
||||
// [[codegen::verbatim(SizeInfo.description)]]
|
||||
float size;
|
||||
|
||||
// [[codegen::verbatim(SegmentsInfo.description)]]
|
||||
int segments;
|
||||
|
||||
// [[codegen::verbatim(TextureInfo.description)]]
|
||||
std::string texture;
|
||||
|
||||
enum class Orientation {
|
||||
Outside,
|
||||
Inside,
|
||||
Both
|
||||
};
|
||||
|
||||
// [[codegen::verbatim(OrientationInfo.description)]]
|
||||
std::optional<Orientation> orientation;
|
||||
|
||||
// [[codegen::verbatim(UseAdditiveBlendingInfo.description)]]
|
||||
std::optional<bool> useAdditiveBlending;
|
||||
|
||||
// [[codegen::verbatim(MirrorTextureInfo.description)]]
|
||||
std::optional<bool> mirrorTexture;
|
||||
|
||||
// [[codegen::verbatim(FadeOutThresholdInfo.description)]]
|
||||
std::optional<float> fadeOutThreshold [[codegen::inrange(0.0, 1.0)]];
|
||||
|
||||
// [[codegen::verbatim(FadeInThresholdInfo.description)]]
|
||||
std::optional<float> fadeInThreshold;
|
||||
|
||||
// [[codegen::verbatim(DisableFadeInOutInfo.description)]]
|
||||
std::optional<bool> disableFadeInOut;
|
||||
|
||||
// [[codegen::verbatim(BackgroundInfo.description)]]
|
||||
std::optional<bool> background;
|
||||
};
|
||||
#include "renderablesphere_codegen.cpp"
|
||||
} // namespace
|
||||
|
||||
namespace openspace {
|
||||
|
||||
documentation::Documentation RenderableSphere::Documentation() {
|
||||
using namespace documentation;
|
||||
return {
|
||||
"RenderableSphere",
|
||||
"base_renderable_sphere",
|
||||
{
|
||||
{
|
||||
SizeInfo.identifier,
|
||||
new DoubleVerifier,
|
||||
Optional::No,
|
||||
SizeInfo.description
|
||||
},
|
||||
{
|
||||
SegmentsInfo.identifier,
|
||||
new IntVerifier,
|
||||
Optional::No,
|
||||
SegmentsInfo.description
|
||||
},
|
||||
{
|
||||
TextureInfo.identifier,
|
||||
new StringVerifier,
|
||||
Optional::No,
|
||||
TextureInfo.description
|
||||
},
|
||||
{
|
||||
OrientationInfo.identifier,
|
||||
new StringInListVerifier({ "Inside", "Outside", "Both" }),
|
||||
Optional::Yes,
|
||||
OrientationInfo.description
|
||||
},
|
||||
{
|
||||
UseAdditiveBlendingInfo.identifier,
|
||||
new BoolVerifier,
|
||||
Optional::Yes,
|
||||
UseAdditiveBlendingInfo.description
|
||||
},
|
||||
{
|
||||
MirrorTextureInfo.identifier,
|
||||
new BoolVerifier,
|
||||
Optional::Yes,
|
||||
MirrorTextureInfo.description
|
||||
},
|
||||
{
|
||||
FadeOutThresholdInfo.identifier,
|
||||
new DoubleInRangeVerifier(0.0, 1.0),
|
||||
Optional::Yes,
|
||||
FadeOutThresholdInfo.description
|
||||
},
|
||||
{
|
||||
FadeInThresholdInfo.identifier,
|
||||
new DoubleVerifier,
|
||||
Optional::Yes,
|
||||
FadeInThresholdInfo.description
|
||||
},
|
||||
{
|
||||
DisableFadeInOutInfo.identifier,
|
||||
new BoolVerifier,
|
||||
Optional::Yes,
|
||||
DisableFadeInOutInfo.description
|
||||
},
|
||||
{
|
||||
BackgroundInfo.identifier,
|
||||
new BoolVerifier,
|
||||
Optional::Yes,
|
||||
BackgroundInfo.description
|
||||
},
|
||||
}
|
||||
};
|
||||
documentation::Documentation doc = codegen::doc<Parameters>();
|
||||
doc.id = "base_renderable_sphere";
|
||||
return doc;
|
||||
}
|
||||
|
||||
|
||||
RenderableSphere::RenderableSphere(const ghoul::Dictionary& dictionary)
|
||||
: Renderable(dictionary)
|
||||
, _texturePath(TextureInfo)
|
||||
@@ -205,18 +180,14 @@ RenderableSphere::RenderableSphere(const ghoul::Dictionary& dictionary)
|
||||
, _fadeInThreshold(FadeInThresholdInfo, -1.f, 0.f, 1.f)
|
||||
, _fadeOutThreshold(FadeOutThresholdInfo, -1.f, 0.f, 1.f)
|
||||
{
|
||||
documentation::testSpecificationAndThrow(
|
||||
Documentation(),
|
||||
dictionary,
|
||||
"RenderableSphere"
|
||||
);
|
||||
const Parameters p = codegen::bake<Parameters>(dictionary);
|
||||
|
||||
addProperty(_opacity);
|
||||
registerUpdateRenderBinFromOpacity();
|
||||
|
||||
_size = static_cast<float>(dictionary.value<double>(SizeInfo.identifier));
|
||||
_segments = static_cast<int>(dictionary.value<double>(SegmentsInfo.identifier));
|
||||
_texturePath = absPath(dictionary.value<std::string>(TextureInfo.identifier));
|
||||
_size = p.size;
|
||||
_segments = p.segments;
|
||||
_texturePath = p.texture;
|
||||
|
||||
_orientation.addOptions({
|
||||
{ static_cast<int>(Orientation::Outside), "Outside" },
|
||||
@@ -224,19 +195,19 @@ RenderableSphere::RenderableSphere(const ghoul::Dictionary& dictionary)
|
||||
{ static_cast<int>(Orientation::Both), "Both" }
|
||||
});
|
||||
|
||||
if (dictionary.hasKey(OrientationInfo.identifier)) {
|
||||
const std::string& v = dictionary.value<std::string>(OrientationInfo.identifier);
|
||||
if (v == "Inside") {
|
||||
_orientation = static_cast<int>(Orientation::Inside);
|
||||
}
|
||||
else if (v == "Outside") {
|
||||
_orientation = static_cast<int>(Orientation::Outside);
|
||||
}
|
||||
else if (v == "Both") {
|
||||
_orientation = static_cast<int>(Orientation::Both);
|
||||
}
|
||||
else {
|
||||
throw ghoul::MissingCaseException();
|
||||
if (p.orientation.has_value()) {
|
||||
switch (*p.orientation) {
|
||||
case Parameters::Orientation::Inside:
|
||||
_orientation = static_cast<int>(Orientation::Inside);
|
||||
break;
|
||||
case Parameters::Orientation::Outside:
|
||||
_orientation = static_cast<int>(Orientation::Outside);
|
||||
break;
|
||||
case Parameters::Orientation::Both:
|
||||
_orientation = static_cast<int>(Orientation::Both);
|
||||
break;
|
||||
default:
|
||||
throw ghoul::MissingCaseException();
|
||||
}
|
||||
}
|
||||
else {
|
||||
@@ -256,44 +227,34 @@ RenderableSphere::RenderableSphere(const ghoul::Dictionary& dictionary)
|
||||
addProperty(_mirrorTexture);
|
||||
addProperty(_useAdditiveBlending);
|
||||
|
||||
_mirrorTexture = p.mirrorTexture.value_or(_mirrorTexture);
|
||||
_useAdditiveBlending = p.useAdditiveBlending.value_or(_useAdditiveBlending);
|
||||
|
||||
if (dictionary.hasKey(MirrorTextureInfo.identifier)) {
|
||||
_mirrorTexture = dictionary.value<bool>(MirrorTextureInfo.identifier);
|
||||
}
|
||||
if (dictionary.hasKey(UseAdditiveBlendingInfo.identifier)) {
|
||||
_useAdditiveBlending = dictionary.value<bool>(UseAdditiveBlendingInfo.identifier);
|
||||
|
||||
if (_useAdditiveBlending) {
|
||||
setRenderBin(Renderable::RenderBin::PreDeferredTransparent);
|
||||
}
|
||||
if (_useAdditiveBlending) {
|
||||
setRenderBin(Renderable::RenderBin::PreDeferredTransparent);
|
||||
}
|
||||
|
||||
if (dictionary.hasKey(FadeOutThresholdInfo.identifier)) {
|
||||
_fadeOutThreshold = static_cast<float>(
|
||||
dictionary.value<double>(FadeOutThresholdInfo.identifier)
|
||||
);
|
||||
bool hasGivenFadeOut = p.fadeOutThreshold.has_value();
|
||||
if (hasGivenFadeOut) {
|
||||
_fadeOutThreshold = *p.fadeOutThreshold;
|
||||
addProperty(_fadeOutThreshold);
|
||||
}
|
||||
|
||||
if (dictionary.hasKey(FadeInThresholdInfo.identifier)) {
|
||||
_fadeInThreshold = static_cast<float>(
|
||||
dictionary.value<double>(FadeInThresholdInfo.identifier)
|
||||
);
|
||||
bool hasGivenFadeIn = p.fadeInThreshold.has_value();
|
||||
if (hasGivenFadeIn) {
|
||||
_fadeInThreshold = *p.fadeInThreshold;
|
||||
addProperty(_fadeInThreshold);
|
||||
}
|
||||
|
||||
if (dictionary.hasKey(FadeInThresholdInfo.identifier) ||
|
||||
dictionary.hasKey(FadeOutThresholdInfo.identifier)) {
|
||||
_disableFadeInDistance.set(false);
|
||||
if (hasGivenFadeIn || hasGivenFadeOut) {
|
||||
_disableFadeInDistance = false;
|
||||
addProperty(_disableFadeInDistance);
|
||||
}
|
||||
|
||||
if (dictionary.hasKey(BackgroundInfo.identifier)) {
|
||||
_backgroundRendering = dictionary.value<bool>(BackgroundInfo.identifier);
|
||||
_backgroundRendering = p.background.value_or(_backgroundRendering);
|
||||
|
||||
if (_backgroundRendering) {
|
||||
setRenderBin(Renderable::RenderBin::Background);
|
||||
}
|
||||
if (_backgroundRendering) {
|
||||
setRenderBin(Renderable::RenderBin::Background);
|
||||
}
|
||||
|
||||
setRenderBinFromOpacity();
|
||||
|
||||
@@ -34,7 +34,6 @@
|
||||
#include <ghoul/filesystem/filesystem.h>
|
||||
#include <ghoul/misc/profiling.h>
|
||||
#include <ghoul/opengl/programobject.h>
|
||||
|
||||
#include <cmath>
|
||||
|
||||
namespace {
|
||||
|
||||
@@ -34,6 +34,7 @@
|
||||
#include <ghoul/font/fontmanager.h>
|
||||
#include <ghoul/font/fontrenderer.h>
|
||||
#include <ghoul/logging/logmanager.h>
|
||||
#include <optional>
|
||||
|
||||
namespace {
|
||||
constexpr openspace::properties::Property::PropertyInfo UseMainInfo = {
|
||||
@@ -42,6 +43,15 @@ namespace {
|
||||
"If this value is set to 'true', this ScreenSpaceDashboard will use the "
|
||||
"main dashboard instead of creating an independent one."
|
||||
};
|
||||
|
||||
struct [[codegen::Dictionary(ScreenSpaceDashboard)]] Parameters {
|
||||
// Specifies the GUI name of the ScreenSpaceDashboard
|
||||
std::optional<std::string> name;
|
||||
|
||||
// [[codegen::verbatim(UseMainInfo.description)]]
|
||||
std::optional<bool> useMainDashboard;
|
||||
};
|
||||
#include "screenspacedashboard_codegen.cpp"
|
||||
} // namespace
|
||||
|
||||
namespace openspace {
|
||||
@@ -115,42 +125,22 @@ int removeDashboardItemsFromScreenSpace(lua_State* L) {
|
||||
dash->dashboard().clearDashboardItems();
|
||||
return 0;
|
||||
}
|
||||
|
||||
} // namespace luascriptfunctions
|
||||
|
||||
|
||||
documentation::Documentation ScreenSpaceDashboard::Documentation() {
|
||||
using namespace openspace::documentation;
|
||||
return {
|
||||
"ScreenSpace Dashboard",
|
||||
"base_screenspace_dashboard",
|
||||
{
|
||||
{
|
||||
KeyName,
|
||||
new StringVerifier,
|
||||
Optional::Yes,
|
||||
"Specifies the GUI name of the ScreenSpaceDashboard"
|
||||
},
|
||||
{
|
||||
UseMainInfo.identifier,
|
||||
new BoolVerifier,
|
||||
Optional::Yes,
|
||||
UseMainInfo.description
|
||||
}
|
||||
}
|
||||
};
|
||||
documentation::Documentation doc = codegen::doc<Parameters>();
|
||||
doc.id = "base_screenspace_dashboard";
|
||||
return doc;
|
||||
}
|
||||
|
||||
ScreenSpaceDashboard::ScreenSpaceDashboard(const ghoul::Dictionary& dictionary)
|
||||
: ScreenSpaceFramebuffer(dictionary)
|
||||
, _useMainDashboard(UseMainInfo, false)
|
||||
{
|
||||
documentation::testSpecificationAndThrow(
|
||||
Documentation(),
|
||||
dictionary,
|
||||
"ScreenSpaceDashboard"
|
||||
);
|
||||
const Parameters p = codegen::bake<Parameters>(dictionary);
|
||||
|
||||
// @TODO (abock, 2021-01-29) Should this be the name variable? The identifier wasn't
|
||||
// declared in the documentation
|
||||
std::string identifier;
|
||||
if (dictionary.hasValue<std::string>(KeyIdentifier)) {
|
||||
identifier = dictionary.value<std::string>(KeyIdentifier);
|
||||
@@ -161,9 +151,7 @@ ScreenSpaceDashboard::ScreenSpaceDashboard(const ghoul::Dictionary& dictionary)
|
||||
identifier = makeUniqueIdentifier(identifier);
|
||||
setIdentifier(std::move(identifier));
|
||||
|
||||
if (dictionary.hasKey(UseMainInfo.identifier)) {
|
||||
_useMainDashboard = dictionary.value<bool>(UseMainInfo.identifier);
|
||||
}
|
||||
_useMainDashboard = p.useMainDashboard.value_or(_useMainDashboard);
|
||||
addProperty(_useMainDashboard);
|
||||
|
||||
_scale = 1.f;
|
||||
|
||||
@@ -32,6 +32,7 @@
|
||||
#include <ghoul/opengl/programobject.h>
|
||||
#include <ghoul/opengl/texture.h>
|
||||
#include <ghoul/opengl/textureconversion.h>
|
||||
#include <optional>
|
||||
|
||||
namespace {
|
||||
constexpr openspace::properties::Property::PropertyInfo TexturePathInfo = {
|
||||
@@ -42,42 +43,33 @@ namespace {
|
||||
"and displayed. The size of the image will also automatically set the default "
|
||||
"size of this plane."
|
||||
};
|
||||
|
||||
struct [[codegen::Dictionary(ScreenSpaceImageLocal)]] Parameters {
|
||||
// Specifies the GUI name of the ScreenspaceImage
|
||||
std::optional<std::string> name;
|
||||
|
||||
// [[codegen::verbatim(TexturePathInfo.description)]]
|
||||
std::optional<std::string> texturePath;
|
||||
};
|
||||
#include "screenspaceimagelocal_codegen.cpp"
|
||||
} // namespace
|
||||
|
||||
namespace openspace {
|
||||
|
||||
documentation::Documentation ScreenSpaceImageLocal::Documentation() {
|
||||
using namespace openspace::documentation;
|
||||
return {
|
||||
"ScreenSpace Local Image",
|
||||
"base_screenspace_image_local",
|
||||
{
|
||||
{
|
||||
KeyName,
|
||||
new StringVerifier,
|
||||
Optional::Yes,
|
||||
"Specifies the GUI name of the ScreenspaceImage"
|
||||
},
|
||||
{
|
||||
TexturePathInfo.identifier,
|
||||
new StringVerifier,
|
||||
Optional::Yes,
|
||||
TexturePathInfo.description
|
||||
}
|
||||
}
|
||||
};
|
||||
documentation::Documentation doc = codegen::doc<Parameters>();
|
||||
doc.id = "base_screenspace_image_local";
|
||||
return doc;
|
||||
}
|
||||
|
||||
ScreenSpaceImageLocal::ScreenSpaceImageLocal(const ghoul::Dictionary& dictionary)
|
||||
: ScreenSpaceRenderable(dictionary)
|
||||
, _texturePath(TexturePathInfo)
|
||||
{
|
||||
documentation::testSpecificationAndThrow(
|
||||
Documentation(),
|
||||
dictionary,
|
||||
"ScreenSpaceImageLocal"
|
||||
);
|
||||
const Parameters p = codegen::bake<Parameters>(dictionary);
|
||||
|
||||
// @TODO (abock, 2021-02-02) Should this be the name variable? The identifier wasn't
|
||||
// declared in the documentation
|
||||
std::string identifier;
|
||||
if (dictionary.hasValue<std::string>(KeyIdentifier)) {
|
||||
identifier = dictionary.value<std::string>(KeyIdentifier);
|
||||
@@ -101,16 +93,15 @@ ScreenSpaceImageLocal::ScreenSpaceImageLocal(const ghoul::Dictionary& dictionary
|
||||
});
|
||||
addProperty(_texturePath);
|
||||
|
||||
if (dictionary.hasKey(TexturePathInfo.identifier)) {
|
||||
std::string path = dictionary.value<std::string>(TexturePathInfo.identifier);
|
||||
if (!FileSys.fileExists(FileSys.absolutePath(path))) {
|
||||
LWARNINGC(
|
||||
"ScreenSpaceImageLocal",
|
||||
fmt::format("Image {} did not exist for {}", path, _identifier)
|
||||
);
|
||||
if (p.texturePath.has_value()) {
|
||||
if (FileSys.fileExists(FileSys.absolutePath(*p.texturePath))) {
|
||||
_texturePath = FileSys.absolutePath(*p.texturePath);
|
||||
}
|
||||
else {
|
||||
_texturePath = path;
|
||||
LWARNINGC(
|
||||
"ScreenSpaceImageLocal",
|
||||
fmt::format("Image {} did not exist for {}", *p.texturePath, _identifier)
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -33,6 +33,7 @@
|
||||
#include <ghoul/logging/logmanager.h>
|
||||
#include <ghoul/opengl/texture.h>
|
||||
#include <ghoul/opengl/programobject.h>
|
||||
#include <optional>
|
||||
|
||||
namespace {
|
||||
constexpr openspace::properties::Property::PropertyInfo TextureInfo = {
|
||||
@@ -43,30 +44,23 @@ namespace {
|
||||
"and displayed. The size of the image will also automatically set the default "
|
||||
"size of this plane."
|
||||
};
|
||||
|
||||
struct [[codegen::Dictionary(ScreenSpaceImageOnline)]] Parameters {
|
||||
// Specifies the GUI name of the ScreenspaceImage
|
||||
std::optional<std::string> name;
|
||||
|
||||
// [[codegen::verbatim(TextureInfo.description)]]
|
||||
std::optional<std::string> url [[codegen::key("URL")]];
|
||||
};
|
||||
#include "screenspaceimageonline_codegen.cpp"
|
||||
} // namespace
|
||||
|
||||
namespace openspace {
|
||||
|
||||
documentation::Documentation ScreenSpaceImageOnline::Documentation() {
|
||||
using namespace openspace::documentation;
|
||||
return {
|
||||
"ScreenSpace Online Image",
|
||||
"base_screenspace_image_online",
|
||||
{
|
||||
{
|
||||
KeyName,
|
||||
new StringVerifier,
|
||||
Optional::Yes,
|
||||
"Specifies the GUI name of the ScreenspaceImage"
|
||||
},
|
||||
{
|
||||
TextureInfo.identifier,
|
||||
new StringVerifier,
|
||||
Optional::Yes,
|
||||
TextureInfo.description
|
||||
}
|
||||
}
|
||||
};
|
||||
documentation::Documentation doc = codegen::doc<Parameters>();
|
||||
doc.id = "base_screenspace_image_online";
|
||||
return doc;
|
||||
}
|
||||
|
||||
ScreenSpaceImageOnline::ScreenSpaceImageOnline(const ghoul::Dictionary& dictionary)
|
||||
@@ -74,11 +68,7 @@ ScreenSpaceImageOnline::ScreenSpaceImageOnline(const ghoul::Dictionary& dictiona
|
||||
, _textureIsDirty(false)
|
||||
, _texturePath(TextureInfo)
|
||||
{
|
||||
documentation::testSpecificationAndThrow(
|
||||
Documentation(),
|
||||
dictionary,
|
||||
"ScreenSpaceImageOnline"
|
||||
);
|
||||
const Parameters p = codegen::bake<Parameters>(dictionary);
|
||||
|
||||
std::string identifier;
|
||||
if (dictionary.hasValue<std::string>(KeyIdentifier)) {
|
||||
@@ -92,11 +82,7 @@ ScreenSpaceImageOnline::ScreenSpaceImageOnline(const ghoul::Dictionary& dictiona
|
||||
|
||||
_texturePath.onChange([this]() { _textureIsDirty = true; });
|
||||
addProperty(_texturePath);
|
||||
|
||||
std::string texturePath;
|
||||
if (dictionary.hasKey(TextureInfo.identifier)) {
|
||||
_texturePath = dictionary.value<std::string>(TextureInfo.identifier);
|
||||
}
|
||||
_texturePath = p.url.value_or(_texturePath);
|
||||
}
|
||||
|
||||
ScreenSpaceImageOnline::~ScreenSpaceImageOnline() {} // NOLINT
|
||||
|
||||
@@ -28,6 +28,7 @@
|
||||
#include <openspace/documentation/verifier.h>
|
||||
#include <openspace/util/updatestructures.h>
|
||||
#include <glm/gtx/quaternion.hpp>
|
||||
#include <optional>
|
||||
|
||||
namespace {
|
||||
constexpr openspace::properties::Property::PropertyInfo RotationInfo = {
|
||||
@@ -41,35 +42,22 @@ namespace {
|
||||
"Rotation Rate",
|
||||
"This value determines the number of revolutions per in-game second"
|
||||
};
|
||||
|
||||
struct [[codegen::Dictionary(ConstantRotation)]] Parameters {
|
||||
// [[codegen::verbatim(RotationInfo.description)]]
|
||||
std::optional<glm::dvec3> rotationAxis;
|
||||
// [[codegen::verbatim(RotationRateInfo.description)]]
|
||||
std::optional<float> rotationRate;
|
||||
};
|
||||
#include "constantrotation_codegen.cpp"
|
||||
} // namespace
|
||||
|
||||
namespace openspace {
|
||||
|
||||
documentation::Documentation ConstantRotation::Documentation() {
|
||||
using namespace openspace::documentation;
|
||||
return {
|
||||
"Static Rotation",
|
||||
"base_transform_rotation_constant",
|
||||
{
|
||||
{
|
||||
"Type",
|
||||
new StringEqualVerifier("ConstantRotation"),
|
||||
Optional::No
|
||||
},
|
||||
{
|
||||
RotationInfo.identifier,
|
||||
new DoubleVector3Verifier(),
|
||||
Optional::Yes,
|
||||
RotationInfo.description
|
||||
},
|
||||
{
|
||||
RotationRateInfo.identifier,
|
||||
new DoubleVerifier(),
|
||||
Optional::Yes,
|
||||
RotationRateInfo.description
|
||||
}
|
||||
}
|
||||
};
|
||||
documentation::Documentation doc = codegen::doc<Parameters>();
|
||||
doc.id = "base_transform_rotation_constant";
|
||||
return doc;
|
||||
}
|
||||
|
||||
ConstantRotation::ConstantRotation(const ghoul::Dictionary& dictionary)
|
||||
@@ -81,18 +69,13 @@ ConstantRotation::ConstantRotation(const ghoul::Dictionary& dictionary)
|
||||
)
|
||||
, _rotationRate(RotationRateInfo, 1.f, -1000.f, 1000.f)
|
||||
{
|
||||
const Parameters p = codegen::bake<Parameters>(dictionary);
|
||||
|
||||
_rotationAxis = p.rotationAxis.value_or(_rotationAxis);
|
||||
addProperty(_rotationAxis);
|
||||
|
||||
_rotationRate = p.rotationRate.value_or(_rotationRate);
|
||||
addProperty(_rotationRate);
|
||||
|
||||
if (dictionary.hasKey(RotationInfo.identifier)) {
|
||||
_rotationAxis = dictionary.value<glm::dvec3>(RotationInfo.identifier);
|
||||
}
|
||||
|
||||
if (dictionary.hasKey(RotationRateInfo.identifier)) {
|
||||
_rotationRate = static_cast<float>(
|
||||
dictionary.value<double>(RotationRateInfo.identifier)
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
glm::dmat3 ConstantRotation::matrix(const UpdateData& data) const {
|
||||
|
||||
@@ -32,16 +32,11 @@
|
||||
#include <ghoul/logging/logmanager.h>
|
||||
#include <ghoul/misc/assert.h>
|
||||
#include <ghoul/misc/profiling.h>
|
||||
#include <optional>
|
||||
#include <string>
|
||||
#include <variant>
|
||||
|
||||
namespace {
|
||||
constexpr const char* KeyXAxis = "XAxis";
|
||||
constexpr const char* KeyXAxisOrthogonal = "XAxisOrthogonal";
|
||||
constexpr const char* KeyYAxis = "YAxis";
|
||||
constexpr const char* KeyYAxisOrthogonal = "YAxisOrthogonal";
|
||||
constexpr const char* KeyZAxis = "ZAxis";
|
||||
constexpr const char* KeyZAxisOrthogonal = "ZAxisOrthogonal";
|
||||
|
||||
constexpr const openspace::properties::Property::PropertyInfo EnableInfo = {
|
||||
"Enable",
|
||||
"Enabled",
|
||||
@@ -186,98 +181,59 @@ namespace {
|
||||
"only needed if any of the three axis uses the Object type. In this case, the "
|
||||
"location of the attached node is required to compute the relative direction."
|
||||
};
|
||||
|
||||
struct [[codegen::Dictionary(FixedRotation)]] Parameters {
|
||||
// This value specifies the direction of the new X axis. If this value is not
|
||||
// specified, it will be computed by completing a right handed coordinate system
|
||||
// from the Y and Z axis, which must be specified instead. If this value is a
|
||||
// string, it is interpreted as the identifier of another scenegraph node. If this
|
||||
// value is a 3-vector, it is interpreted as a direction vector
|
||||
std::optional<std::variant<std::string, glm::vec3>> xAxis;
|
||||
|
||||
// [[codegen::verbatim(XAxisOrthogonalVectorInfo.description)]]
|
||||
std::optional<bool> xAxisOrthogonal;
|
||||
|
||||
// [[codegen::verbatim(XAxisInvertObjectInfo.description)]]
|
||||
std::optional<bool> xAxisInvert [[codegen::key("xAxis - InvertObject")]];
|
||||
|
||||
// This value specifies the direction of the new Y axis. If this value is not
|
||||
// specified, it will be computed by completing a right handed coordinate system
|
||||
// from the X and Z axis, which must be specified instead. If this value is a
|
||||
// string, it is interpreted as the identifier of another scenegraph node. If this
|
||||
// value is a 3-vector, it is interpreted as a direction vector
|
||||
std::optional<std::variant<std::string, glm::vec3>> yAxis;
|
||||
|
||||
// [[codegen::verbatim(YAxisOrthogonalVectorInfo.description)]]
|
||||
std::optional<bool> yAxisOrthogonal;
|
||||
|
||||
// [[codegen::verbatim(YAxisInvertObjectInfo.description)]]
|
||||
std::optional<bool> yAxisInvert [[codegen::key("yAxis - InvertObject")]];
|
||||
|
||||
// This value specifies the direction of the new Z axis. If this value is not
|
||||
// specified, it will be computed by completing a right handed coordinate system
|
||||
// from the X and Y axis, which must be specified instead. If this value is a
|
||||
// string, it is interpreted as the identifier of another scenegraph node. If this
|
||||
// value is a 3-vector, it is interpreted as a direction vector
|
||||
std::optional<std::variant<std::string, glm::vec3>> zAxis;
|
||||
|
||||
// [[codegen::verbatim(ZAxisOrthogonalVectorInfo.description)]]
|
||||
std::optional<bool> zAxisOrthogonal;
|
||||
|
||||
// [[codegen::verbatim(ZAxisInvertObjectInfo.description)]]
|
||||
std::optional<bool> zAxisInvert [[codegen::key("zAxis - InvertObject")]];
|
||||
|
||||
// [[codegen::verbatim(AttachedInfo.description)]]
|
||||
std::optional<std::string> attached;
|
||||
};
|
||||
#include "fixedrotation_codegen.cpp"
|
||||
} // namespace
|
||||
|
||||
namespace openspace {
|
||||
|
||||
documentation::Documentation FixedRotation::Documentation() {
|
||||
using namespace openspace::documentation;
|
||||
return {
|
||||
"Fixed Rotation",
|
||||
"base_transform_rotation_fixed",
|
||||
{
|
||||
{
|
||||
"Type",
|
||||
new StringEqualVerifier("FixedRotation"),
|
||||
Optional::No
|
||||
},
|
||||
{
|
||||
KeyXAxis,
|
||||
new OrVerifier({ new StringVerifier, new DoubleVector3Verifier, }),
|
||||
Optional::Yes,
|
||||
"This value specifies the direction of the new X axis. If this value is "
|
||||
"not specified, it will be computed by completing a right handed "
|
||||
"coordinate system from the Y and Z axis, which must be specified "
|
||||
"instead. If this value is a string, it is interpreted as the identifier "
|
||||
"of another scenegraph node. If this value is a 3-vector, it is "
|
||||
"interpreted as a direction vector."
|
||||
},
|
||||
{
|
||||
KeyXAxisOrthogonal,
|
||||
new BoolVerifier,
|
||||
Optional::Yes,
|
||||
XAxisOrthogonalVectorInfo.description
|
||||
},
|
||||
{
|
||||
XAxisInvertObjectInfo.identifier,
|
||||
new BoolVerifier,
|
||||
Optional::Yes,
|
||||
XAxisInvertObjectInfo.description
|
||||
},
|
||||
{
|
||||
KeyYAxis,
|
||||
new OrVerifier({ new StringVerifier, new DoubleVector3Verifier, }),
|
||||
Optional::Yes,
|
||||
"This value specifies the direction of the new Y axis. If this value is "
|
||||
"not specified, it will be computed by completing a right handed "
|
||||
"coordinate system from the X and Z axis, which must be specified "
|
||||
"instead. If this value is a string, it is interpreted as the identifier "
|
||||
"of another scenegraph node. If this value is a 3-vector, it is "
|
||||
"interpreted as a direction vector."
|
||||
},
|
||||
{
|
||||
KeyYAxisOrthogonal,
|
||||
new BoolVerifier,
|
||||
Optional::Yes,
|
||||
YAxisOrthogonalVectorInfo.description
|
||||
},
|
||||
{
|
||||
YAxisInvertObjectInfo.identifier,
|
||||
new BoolVerifier,
|
||||
Optional::Yes,
|
||||
YAxisInvertObjectInfo.description
|
||||
},
|
||||
{
|
||||
KeyZAxis,
|
||||
new OrVerifier({ new StringVerifier, new DoubleVector3Verifier, }),
|
||||
Optional::Yes,
|
||||
"This value specifies the direction of the new Z axis. If this value is "
|
||||
"not specified, it will be computed by completing a right handed "
|
||||
"coordinate system from the X and Y axis, which must be specified "
|
||||
"instead. If this value is a string, it is interpreted as the identifier "
|
||||
"of another scenegraph node. If this value is a 3-vector, it is "
|
||||
"interpreted as a direction vector."
|
||||
},
|
||||
{
|
||||
KeyZAxisOrthogonal,
|
||||
new BoolVerifier,
|
||||
Optional::Yes,
|
||||
ZAxisOrthogonalVectorInfo.description
|
||||
},
|
||||
{
|
||||
ZAxisInvertObjectInfo.identifier,
|
||||
new BoolVerifier,
|
||||
Optional::Yes,
|
||||
ZAxisInvertObjectInfo.description
|
||||
},
|
||||
{
|
||||
AttachedInfo.identifier,
|
||||
new StringVerifier,
|
||||
Optional::Yes,
|
||||
AttachedInfo.description
|
||||
}
|
||||
}
|
||||
};
|
||||
documentation::Documentation doc = codegen::doc<Parameters>();
|
||||
doc.id = "base_transform_rotation_fixed";
|
||||
return doc;
|
||||
}
|
||||
|
||||
FixedRotation::FixedRotation(const ghoul::Dictionary& dictionary)
|
||||
@@ -332,6 +288,9 @@ FixedRotation::FixedRotation(const ghoul::Dictionary& dictionary)
|
||||
}
|
||||
, _attachedObject(AttachedInfo, "")
|
||||
{
|
||||
// We check the Dictionary here in order to detect the errors early
|
||||
codegen::bake<Parameters>(dictionary);
|
||||
|
||||
documentation::testSpecificationAndThrow(
|
||||
Documentation(),
|
||||
dictionary,
|
||||
@@ -447,103 +406,79 @@ FixedRotation::FixedRotation(const ghoul::Dictionary& dictionary)
|
||||
bool FixedRotation::initialize() {
|
||||
ZoneScoped
|
||||
|
||||
// We have already checked this before, but still
|
||||
const Parameters p = codegen::bake<Parameters>(_constructorDictionary);
|
||||
|
||||
// We need to do this in the initialize and not the constructor as the scene graph
|
||||
// nodes referenced in the dictionary might not exist yet at construction time. At
|
||||
// initialization time, however, we know that they already have been created
|
||||
|
||||
const bool res = Rotation::initialize();
|
||||
|
||||
if (_constructorDictionary.hasKey(AttachedInfo.identifier)) {
|
||||
_attachedObject = _constructorDictionary.value<std::string>(
|
||||
AttachedInfo.identifier
|
||||
);
|
||||
}
|
||||
_attachedObject = p.attached.value_or(_attachedObject);
|
||||
|
||||
const bool hasXAxis = _constructorDictionary.hasKey(KeyXAxis);
|
||||
if (hasXAxis) {
|
||||
if (_constructorDictionary.hasValue<std::string>(KeyXAxis)) {
|
||||
if (p.xAxis.has_value()) {
|
||||
if (std::holds_alternative<std::string>(*p.xAxis)) {
|
||||
_xAxis.type = Axis::Type::Object;
|
||||
_xAxis.object = _constructorDictionary.value<std::string>(KeyXAxis);
|
||||
_xAxis.object = std::get<std::string>(*p.xAxis);
|
||||
}
|
||||
else {
|
||||
// We know it has to be a vector now
|
||||
ghoul_assert(std::holds_alternative<glm::vec3>(*p.xAxis), "");
|
||||
_xAxis.type = Axis::Type::Vector;
|
||||
_xAxis.vector = _constructorDictionary.value<glm::dvec3>(KeyXAxis);
|
||||
_xAxis.vector = std::get<glm::vec3>(*p.xAxis);
|
||||
}
|
||||
}
|
||||
|
||||
if (_constructorDictionary.hasKey(KeyXAxisOrthogonal)) {
|
||||
_xAxis.isOrthogonal = _constructorDictionary.value<bool>(KeyXAxisOrthogonal);
|
||||
}
|
||||
if (_constructorDictionary.hasKey(XAxisInvertObjectInfo.identifier)) {
|
||||
_xAxis.invertObject = _constructorDictionary.value<bool>(
|
||||
XAxisInvertObjectInfo.identifier
|
||||
);
|
||||
}
|
||||
_xAxis.isOrthogonal = p.xAxisOrthogonal.value_or(_xAxis.isOrthogonal);
|
||||
if (_xAxis.isOrthogonal) {
|
||||
_xAxis.type = Axis::Type::OrthogonalVector;
|
||||
}
|
||||
_xAxis.invertObject = p.xAxisInvert.value_or(_xAxis.invertObject);
|
||||
|
||||
const bool hasYAxis = _constructorDictionary.hasKey(KeyYAxis);
|
||||
if (hasYAxis) {
|
||||
if (_constructorDictionary.hasValue<std::string>(KeyYAxis)) {
|
||||
if (p.yAxis.has_value()) {
|
||||
if (std::holds_alternative<std::string>(*p.yAxis)) {
|
||||
_yAxis.type = Axis::Type::Object;
|
||||
_yAxis.object = _constructorDictionary.value<std::string>(KeyYAxis);
|
||||
_yAxis.object = std::get<std::string>(*p.yAxis);
|
||||
}
|
||||
else {
|
||||
// We know it has to be a vector now
|
||||
ghoul_assert(std::holds_alternative<glm::vec3>(*p.yAxis), "");
|
||||
_yAxis.type = Axis::Type::Vector;
|
||||
_yAxis.vector = _constructorDictionary.value<glm::dvec3>(KeyYAxis);
|
||||
_yAxis.vector = std::get<glm::vec3>(*p.yAxis);
|
||||
}
|
||||
}
|
||||
|
||||
if (_constructorDictionary.hasKey(KeyYAxisOrthogonal)) {
|
||||
_yAxis.isOrthogonal = _constructorDictionary.value<bool>(KeyYAxisOrthogonal);
|
||||
}
|
||||
if (_constructorDictionary.hasKey(YAxisInvertObjectInfo.identifier)) {
|
||||
_yAxis.invertObject = _constructorDictionary.value<bool>(
|
||||
YAxisInvertObjectInfo.identifier
|
||||
);
|
||||
}
|
||||
_yAxis.isOrthogonal = p.yAxisOrthogonal.value_or(_yAxis.isOrthogonal);
|
||||
if (_yAxis.isOrthogonal) {
|
||||
_yAxis.type = Axis::Type::OrthogonalVector;
|
||||
}
|
||||
_yAxis.invertObject = p.yAxisInvert.value_or(_yAxis.invertObject);
|
||||
|
||||
const bool hasZAxis = _constructorDictionary.hasKey(KeyZAxis);
|
||||
if (hasZAxis) {
|
||||
if (_constructorDictionary.hasValue<std::string>(KeyZAxis)) {
|
||||
if (p.zAxis.has_value()) {
|
||||
if (std::holds_alternative<std::string>(*p.zAxis)) {
|
||||
_zAxis.type = Axis::Type::Object;
|
||||
_zAxis.object = _constructorDictionary.value<std::string>(KeyZAxis);
|
||||
_zAxis.object = std::get<std::string>(*p.zAxis);
|
||||
}
|
||||
else {
|
||||
// We know it has to be a vector now
|
||||
ghoul_assert(std::holds_alternative<glm::vec3>(*p.zAxis), "");
|
||||
_zAxis.type = Axis::Type::Vector;
|
||||
_zAxis.vector = _constructorDictionary.value<glm::dvec3>(KeyZAxis);
|
||||
_zAxis.vector = std::get<glm::vec3>(*p.zAxis);
|
||||
}
|
||||
}
|
||||
|
||||
if (_constructorDictionary.hasKey(KeyZAxisOrthogonal)) {
|
||||
_zAxis.isOrthogonal = _constructorDictionary.value<bool>(KeyZAxisOrthogonal);
|
||||
}
|
||||
if (_constructorDictionary.hasKey(ZAxisInvertObjectInfo.identifier)) {
|
||||
_yAxis.invertObject = _constructorDictionary.value<bool>(
|
||||
ZAxisInvertObjectInfo.identifier
|
||||
);
|
||||
}
|
||||
_zAxis.isOrthogonal = p.zAxisOrthogonal.value_or(_zAxis.isOrthogonal);
|
||||
if (_zAxis.isOrthogonal) {
|
||||
_zAxis.type = Axis::Type::OrthogonalVector;
|
||||
}
|
||||
_zAxis.invertObject = p.zAxisInvert.value_or(_zAxis.invertObject);
|
||||
|
||||
|
||||
if (!hasXAxis && hasYAxis && hasZAxis) {
|
||||
|
||||
if (!p.xAxis.has_value() && p.yAxis.has_value() && p.zAxis.has_value()) {
|
||||
_xAxis.type = Axis::Type::CoordinateSystemCompletion;
|
||||
}
|
||||
|
||||
if (hasXAxis && !hasYAxis && hasZAxis) {
|
||||
if (p.xAxis.has_value() && !p.yAxis.has_value() && p.zAxis.has_value()) {
|
||||
_yAxis.type = Axis::Type::CoordinateSystemCompletion;
|
||||
}
|
||||
|
||||
if (hasXAxis && hasYAxis && !hasZAxis) {
|
||||
if (p.xAxis.has_value() && p.yAxis.has_value() && !p.zAxis.has_value()) {
|
||||
_zAxis.type = Axis::Type::CoordinateSystemCompletion;
|
||||
}
|
||||
|
||||
|
||||
@@ -45,29 +45,20 @@ namespace {
|
||||
"J2000 epoch as the second argument and computes the rotation returned as 9 "
|
||||
"values."
|
||||
};
|
||||
|
||||
struct [[codegen::Dictionary(LuaRotation)]] Parameters {
|
||||
// [[codegen::verbatim(ScriptInfo.description)]]
|
||||
std::string script;
|
||||
};
|
||||
#include "luarotation_codegen.cpp"
|
||||
} // namespace
|
||||
|
||||
namespace openspace {
|
||||
|
||||
documentation::Documentation LuaRotation::Documentation() {
|
||||
using namespace openspace::documentation;
|
||||
return {
|
||||
"Lua Rotation",
|
||||
"base_transform_rotation_lua",
|
||||
{
|
||||
{
|
||||
"Type",
|
||||
new StringEqualVerifier("LuaRotation"),
|
||||
Optional::No
|
||||
},
|
||||
{
|
||||
ScriptInfo.identifier,
|
||||
new StringVerifier,
|
||||
Optional::No,
|
||||
ScriptInfo.description
|
||||
}
|
||||
}
|
||||
};
|
||||
documentation::Documentation doc = codegen::doc<Parameters>();
|
||||
doc.id = "base_transform_rotation_lua";
|
||||
return doc;
|
||||
}
|
||||
|
||||
LuaRotation::LuaRotation()
|
||||
@@ -86,13 +77,9 @@ LuaRotation::LuaRotation()
|
||||
}
|
||||
|
||||
LuaRotation::LuaRotation(const ghoul::Dictionary& dictionary) : LuaRotation() {
|
||||
documentation::testSpecificationAndThrow(
|
||||
Documentation(),
|
||||
dictionary,
|
||||
"LuaRotation"
|
||||
);
|
||||
const Parameters p = codegen::bake<Parameters>(dictionary);
|
||||
|
||||
_luaScriptFile = absPath(dictionary.value<std::string>(ScriptInfo.identifier));
|
||||
_luaScriptFile = absPath(p.script);
|
||||
}
|
||||
|
||||
glm::dmat3 LuaRotation::matrix(const UpdateData& data) const {
|
||||
|
||||
@@ -55,34 +55,21 @@ namespace {
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
struct [[codegen::Dictionary(StaticRotation)]] Parameters {
|
||||
// Stores the static rotation as a vector containing Euler angles, a quaternion
|
||||
// or a rotation matrix
|
||||
std::variant<glm::dvec3, glm::dvec4, glm::dmat3x3> rotation;
|
||||
};
|
||||
#include "staticrotation_codegen.cpp"
|
||||
} // namespace
|
||||
|
||||
namespace openspace {
|
||||
|
||||
documentation::Documentation StaticRotation::Documentation() {
|
||||
using namespace openspace::documentation;
|
||||
return {
|
||||
"Static Rotation",
|
||||
"base_transform_rotation_static",
|
||||
{
|
||||
{
|
||||
"Type",
|
||||
new StringEqualVerifier("StaticRotation"),
|
||||
Optional::No
|
||||
},
|
||||
{
|
||||
RotationInfo.identifier,
|
||||
new OrVerifier({
|
||||
new DoubleVector3Verifier(),
|
||||
new DoubleVector4Verifier(),
|
||||
new DoubleMatrix3Verifier()
|
||||
}),
|
||||
Optional::No,
|
||||
"Stores the static rotation as a vector containing Euler angles, "
|
||||
" a quaternion or a rotation matrix."
|
||||
}
|
||||
}
|
||||
};
|
||||
documentation::Documentation doc = codegen::doc<Parameters>();
|
||||
doc.id = "base_transform_rotation_static";
|
||||
return doc;
|
||||
}
|
||||
|
||||
StaticRotation::StaticRotation()
|
||||
@@ -101,31 +88,21 @@ StaticRotation::StaticRotation()
|
||||
}
|
||||
|
||||
StaticRotation::StaticRotation(const ghoul::Dictionary& dictionary) : StaticRotation() {
|
||||
documentation::testSpecificationAndThrow(
|
||||
Documentation(),
|
||||
dictionary,
|
||||
"StaticRotation"
|
||||
);
|
||||
const Parameters p = codegen::bake<Parameters>(dictionary);
|
||||
|
||||
if (dictionary.hasValue<glm::dvec3>(RotationInfo.identifier)) {
|
||||
_eulerRotation = static_cast<glm::vec3>(
|
||||
dictionary.value<glm::dvec3>(RotationInfo.identifier)
|
||||
);
|
||||
_matrixIsDirty = true;
|
||||
if (std::holds_alternative<glm::dvec3>(p.rotation)) {
|
||||
_eulerRotation = std::get<glm::dvec3>(p.rotation);
|
||||
}
|
||||
else if (dictionary.hasValue<glm::dvec4>(RotationInfo.identifier)) {
|
||||
glm::dvec4 data = dictionary.value<glm::dvec4>(RotationInfo.identifier);
|
||||
else if (std::holds_alternative<glm::dvec4>(p.rotation)) {
|
||||
glm::dvec4 data = std::get<glm::dvec4>(p.rotation);
|
||||
_eulerRotation = rotationMatrixToEulerAngles(
|
||||
glm::mat3_cast(glm::dquat(data.w, data.x, data.y, data.z))
|
||||
);
|
||||
_matrixIsDirty = true;
|
||||
}
|
||||
else if (dictionary.hasValue<glm::dmat3>(RotationInfo.identifier)) {
|
||||
_eulerRotation = rotationMatrixToEulerAngles(
|
||||
dictionary.value<glm::dmat3>(RotationInfo.identifier)
|
||||
);
|
||||
_matrixIsDirty = true;
|
||||
else if (std::holds_alternative<glm::dmat3>(p.rotation)) {
|
||||
_eulerRotation = rotationMatrixToEulerAngles(std::get<glm::dmat3>(p.rotation));
|
||||
}
|
||||
_matrixIsDirty = true;
|
||||
}
|
||||
|
||||
glm::dmat3 StaticRotation::matrix(const UpdateData&) const {
|
||||
|
||||
@@ -30,7 +30,6 @@
|
||||
#include <openspace/util/time.h>
|
||||
|
||||
namespace {
|
||||
constexpr const char* KeyType = "Type";
|
||||
constexpr const char* KeyKeyframes = "Keyframes";
|
||||
} // namespace
|
||||
|
||||
@@ -42,11 +41,6 @@ documentation::Documentation TimelineRotation::Documentation() {
|
||||
"Timeline Rotation",
|
||||
"base_transform_rotation_keyframe",
|
||||
{
|
||||
{
|
||||
KeyType,
|
||||
new StringEqualVerifier("TimelineRotation"),
|
||||
Optional::No
|
||||
},
|
||||
{
|
||||
KeyKeyframes,
|
||||
new TableVerifier({
|
||||
|
||||
@@ -32,7 +32,6 @@
|
||||
#include <ghoul/logging/logmanager.h>
|
||||
#include <ghoul/lua/ghoul_lua.h>
|
||||
#include <ghoul/lua/lua_helper.h>
|
||||
|
||||
#include <chrono>
|
||||
|
||||
namespace {
|
||||
@@ -45,24 +44,20 @@ namespace {
|
||||
"as the first argument, the current wall time as milliseconds past the J2000 "
|
||||
"epoch the second argument and computes the three scaling factors."
|
||||
};
|
||||
|
||||
struct [[codegen::Dictionary(LuaScale)]] Parameters {
|
||||
// [[codegen::verbatim(ScriptInfo.description)]]
|
||||
std::string script;
|
||||
};
|
||||
#include "luascale_codegen.cpp"
|
||||
} // namespace
|
||||
|
||||
namespace openspace {
|
||||
|
||||
documentation::Documentation LuaScale::Documentation() {
|
||||
using namespace openspace::documentation;
|
||||
return {
|
||||
"Lua Scaling",
|
||||
"base_scale_lua",
|
||||
{
|
||||
{
|
||||
ScriptInfo.identifier,
|
||||
new StringVerifier,
|
||||
Optional::No,
|
||||
ScriptInfo.description
|
||||
}
|
||||
}
|
||||
};
|
||||
documentation::Documentation doc = codegen::doc<Parameters>();
|
||||
doc.id = "base_scale_lua";
|
||||
return doc;
|
||||
}
|
||||
|
||||
LuaScale::LuaScale()
|
||||
@@ -81,9 +76,8 @@ LuaScale::LuaScale()
|
||||
}
|
||||
|
||||
LuaScale::LuaScale(const ghoul::Dictionary& dictionary) : LuaScale() {
|
||||
documentation::testSpecificationAndThrow(Documentation(), dictionary, "LuaScale");
|
||||
|
||||
_luaScriptFile = absPath(dictionary.value<std::string>(ScriptInfo.identifier));
|
||||
const Parameters p = codegen::bake<Parameters>(dictionary);
|
||||
_luaScriptFile = absPath(p.script);
|
||||
}
|
||||
|
||||
glm::dvec3 LuaScale::scaleValue(const UpdateData& data) const {
|
||||
|
||||
@@ -34,24 +34,20 @@ namespace {
|
||||
"These values are used as scaling factors for the scene graph node that this "
|
||||
"transformation is attached to relative to its parent."
|
||||
};
|
||||
|
||||
struct [[codegen::Dictionary(NonUniformStaticScale)]] Parameters {
|
||||
// [[codegen::verbatim(ScaleInfo.description)]]
|
||||
glm::dvec3 scale;
|
||||
};
|
||||
#include "nonuniformstaticscale_codegen.cpp"
|
||||
} // namespace
|
||||
|
||||
namespace openspace {
|
||||
|
||||
documentation::Documentation NonUniformStaticScale::Documentation() {
|
||||
using namespace openspace::documentation;
|
||||
return {
|
||||
"Static Scaling",
|
||||
"base_scale_static",
|
||||
{
|
||||
{
|
||||
ScaleInfo.identifier,
|
||||
new DoubleVector3Verifier,
|
||||
Optional::No,
|
||||
ScaleInfo.description
|
||||
}
|
||||
}
|
||||
};
|
||||
documentation::Documentation doc = codegen::doc<Parameters>();
|
||||
doc.id = "base_scale_nonuniformstatic";
|
||||
return doc;
|
||||
}
|
||||
|
||||
glm::dvec3 NonUniformStaticScale::scaleValue(const UpdateData&) const {
|
||||
@@ -71,9 +67,8 @@ NonUniformStaticScale::NonUniformStaticScale()
|
||||
NonUniformStaticScale::NonUniformStaticScale(const ghoul::Dictionary& dictionary)
|
||||
: NonUniformStaticScale()
|
||||
{
|
||||
documentation::testSpecificationAndThrow(Documentation(), dictionary, "StaticScale");
|
||||
|
||||
_scaleValue = dictionary.value<glm::dvec3>(ScaleInfo.identifier);
|
||||
const Parameters p = codegen::bake<Parameters>(dictionary);
|
||||
_scaleValue = p.scale;
|
||||
}
|
||||
|
||||
} // namespace openspace
|
||||
|
||||
@@ -34,24 +34,20 @@ namespace {
|
||||
"This value is used as a scaling factor for the scene graph node that this "
|
||||
"transformation is attached to relative to its parent."
|
||||
};
|
||||
|
||||
struct [[codegen::Dictionary(StaticScale)]] Parameters {
|
||||
// [[codegen::verbatim(ScaleInfo.description)]]
|
||||
float scale;
|
||||
};
|
||||
#include "staticscale_codegen.cpp"
|
||||
} // namespace
|
||||
|
||||
namespace openspace {
|
||||
|
||||
documentation::Documentation StaticScale::Documentation() {
|
||||
using namespace openspace::documentation;
|
||||
return {
|
||||
"Static Scaling",
|
||||
"base_scale_static",
|
||||
{
|
||||
{
|
||||
ScaleInfo.identifier,
|
||||
new DoubleVerifier,
|
||||
Optional::No,
|
||||
ScaleInfo.description
|
||||
}
|
||||
}
|
||||
};
|
||||
documentation::Documentation doc = codegen::doc<Parameters>();
|
||||
doc.id = "base_scale_static";
|
||||
return doc;
|
||||
}
|
||||
|
||||
glm::dvec3 StaticScale::scaleValue(const UpdateData&) const {
|
||||
@@ -67,9 +63,8 @@ StaticScale::StaticScale() : _scaleValue(ScaleInfo, 1.f, 0.1f, 100.f) {
|
||||
}
|
||||
|
||||
StaticScale::StaticScale(const ghoul::Dictionary& dictionary) : StaticScale() {
|
||||
documentation::testSpecificationAndThrow(Documentation(), dictionary, "StaticScale");
|
||||
|
||||
_scaleValue = static_cast<float>(dictionary.value<double>(ScaleInfo.identifier));
|
||||
const Parameters p = codegen::bake<Parameters>(dictionary);
|
||||
_scaleValue = p.scale;
|
||||
}
|
||||
|
||||
} // namespace openspace
|
||||
|
||||
@@ -28,6 +28,7 @@
|
||||
#include <openspace/documentation/verifier.h>
|
||||
#include <openspace/util/time.h>
|
||||
#include <openspace/util/updatestructures.h>
|
||||
#include <optional>
|
||||
|
||||
namespace {
|
||||
constexpr openspace::properties::Property::PropertyInfo ReferenceDateInfo = {
|
||||
@@ -53,36 +54,26 @@ namespace {
|
||||
"negative values. This is useful for instantaneous events that only propagate "
|
||||
"forwards. The default value is 'true'."
|
||||
};
|
||||
|
||||
struct [[codegen::Dictionary(TimeDependentScale)]] Parameters {
|
||||
// [[codegen::verbatim(ReferenceDateInfo.description)]]
|
||||
std::string referenceDate;
|
||||
|
||||
// [[codegen::verbatim(SpeedInfo.description)]]
|
||||
std::optional<double> speed;
|
||||
|
||||
// [[codegen::verbatim(ClampToPositiveInfo.description)]]
|
||||
std::optional<bool> clampToPositive;
|
||||
};
|
||||
#include "timedependentscale_codegen.cpp"
|
||||
} // namespace
|
||||
|
||||
namespace openspace {
|
||||
|
||||
documentation::Documentation TimeDependentScale::Documentation() {
|
||||
using namespace openspace::documentation;
|
||||
return {
|
||||
"Timedependent Scaling",
|
||||
"base_scale_timedependent",
|
||||
{
|
||||
{
|
||||
ReferenceDateInfo.identifier,
|
||||
new StringVerifier,
|
||||
Optional::No,
|
||||
ReferenceDateInfo.description
|
||||
},
|
||||
{
|
||||
SpeedInfo.identifier,
|
||||
new DoubleVerifier,
|
||||
Optional::Yes,
|
||||
SpeedInfo.description
|
||||
},
|
||||
{
|
||||
ClampToPositiveInfo.identifier,
|
||||
new BoolVerifier,
|
||||
Optional::Yes,
|
||||
ClampToPositiveInfo.description
|
||||
}
|
||||
}
|
||||
};
|
||||
documentation::Documentation doc = codegen::doc<Parameters>();
|
||||
doc.id = "base_scale_timedependent";
|
||||
return doc;
|
||||
}
|
||||
|
||||
TimeDependentScale::TimeDependentScale(const ghoul::Dictionary& dictionary)
|
||||
@@ -90,21 +81,17 @@ TimeDependentScale::TimeDependentScale(const ghoul::Dictionary& dictionary)
|
||||
, _speed(SpeedInfo, 1.0, 0.0, 1e12)
|
||||
, _clampToPositive(ClampToPositiveInfo, true)
|
||||
{
|
||||
documentation::testSpecificationAndThrow(
|
||||
Documentation(),
|
||||
dictionary,
|
||||
"TimeDependentScale"
|
||||
);
|
||||
const Parameters p = codegen::bake<Parameters>(dictionary);
|
||||
|
||||
_referenceDate = dictionary.value<std::string>(ReferenceDateInfo.identifier);
|
||||
_referenceDate = p.referenceDate;
|
||||
_referenceDate.onChange([this]() { _cachedReferenceDirty = true; });
|
||||
addProperty(_referenceDate);
|
||||
|
||||
if (dictionary.value<double>(SpeedInfo.identifier)) {
|
||||
_speed = dictionary.value<double>(SpeedInfo.identifier);
|
||||
}
|
||||
_speed = p.speed.value_or(_speed);
|
||||
addProperty(_speed);
|
||||
|
||||
// @TODO (abock, 2021-01-09) The clamp to positive value from the dictionary was never
|
||||
// actually read. I think this should probably be done here?
|
||||
addProperty(_clampToPositive);
|
||||
}
|
||||
|
||||
|
||||
@@ -28,6 +28,7 @@
|
||||
#include <openspace/documentation/verifier.h>
|
||||
#include <openspace/util/spicemanager.h>
|
||||
#include <openspace/util/time.h>
|
||||
#include <optional>
|
||||
|
||||
namespace {
|
||||
constexpr const openspace::properties::Property::PropertyInfo HasStartInfo = {
|
||||
@@ -53,42 +54,23 @@ namespace {
|
||||
"End",
|
||||
"Specifies the time when this TimeFrame becomes inactive"
|
||||
};
|
||||
|
||||
struct [[codegen::Dictionary(TimeFrameInterval)]] Parameters {
|
||||
// [[codegen::verbatim(StartInfo.description)]]
|
||||
std::optional<std::variant<double, std::string>> start;
|
||||
|
||||
// [[codegen::verbatim(EndInfo.description)]]
|
||||
std::optional<std::variant<double, std::string>> end;
|
||||
};
|
||||
#include "timeframeinterval_codegen.cpp"
|
||||
} // namespace
|
||||
|
||||
namespace openspace {
|
||||
|
||||
documentation::Documentation TimeFrameInterval::Documentation() {
|
||||
using namespace openspace::documentation;
|
||||
return {
|
||||
"Time Frame Interval",
|
||||
"base_time_frame_interval",
|
||||
{
|
||||
{
|
||||
HasStartInfo.identifier,
|
||||
new BoolVerifier,
|
||||
Optional::Yes,
|
||||
HasStartInfo.description
|
||||
},
|
||||
{
|
||||
StartInfo.identifier,
|
||||
new OrVerifier({ new DoubleVerifier, new StringVerifier }),
|
||||
Optional::Yes,
|
||||
StartInfo.description
|
||||
},
|
||||
{
|
||||
HasEndInfo.identifier,
|
||||
new BoolVerifier,
|
||||
Optional::Yes,
|
||||
HasEndInfo.description
|
||||
},
|
||||
{
|
||||
EndInfo.identifier,
|
||||
new OrVerifier({ new DoubleVerifier, new StringVerifier }),
|
||||
Optional::Yes,
|
||||
EndInfo.description
|
||||
},
|
||||
}
|
||||
};
|
||||
documentation::Documentation doc = codegen::doc<Parameters>();
|
||||
doc.id = "base_time_frame_interval";
|
||||
return doc;
|
||||
}
|
||||
|
||||
bool TimeFrameInterval::isActive(const Time& time) const {
|
||||
@@ -119,38 +101,35 @@ TimeFrameInterval::TimeFrameInterval(const ghoul::Dictionary& dictionary)
|
||||
, _hasEnd(HasEndInfo, false)
|
||||
, _end(EndInfo, 0, 0, 1E9)
|
||||
{
|
||||
const Parameters p = codegen::bake<Parameters>(dictionary);
|
||||
|
||||
if (p.start.has_value()) {
|
||||
if (std::holds_alternative<double>(*p.start)) {
|
||||
_start = std::get<double>(*p.start);
|
||||
}
|
||||
else {
|
||||
_start = SpiceManager::ref().ephemerisTimeFromDate(
|
||||
std::get<std::string>(*p.start)
|
||||
);
|
||||
}
|
||||
}
|
||||
_hasStart = p.start.has_value();
|
||||
addProperty(_hasStart);
|
||||
addProperty(_start);
|
||||
|
||||
if (p.end.has_value()) {
|
||||
if (std::holds_alternative<double>(*p.end)) {
|
||||
_end = std::get<double>(*p.end);
|
||||
}
|
||||
else {
|
||||
_end = SpiceManager::ref().ephemerisTimeFromDate(
|
||||
std::get<std::string>(*p.end)
|
||||
);
|
||||
}
|
||||
}
|
||||
_hasEnd = p.end.has_value();
|
||||
addProperty(_hasEnd);
|
||||
addProperty(_end);
|
||||
|
||||
documentation::testSpecificationAndThrow(
|
||||
Documentation(),
|
||||
dictionary,
|
||||
"TimeFrameInterval"
|
||||
);
|
||||
|
||||
if (dictionary.hasValue<std::string>(StartInfo.identifier)) {
|
||||
_start = SpiceManager::ref().ephemerisTimeFromDate(
|
||||
dictionary.value<std::string>(StartInfo.identifier)
|
||||
);
|
||||
_hasStart = true;
|
||||
}
|
||||
else if (dictionary.hasValue<double>(StartInfo.identifier)) {
|
||||
_start = dictionary.value<double>(StartInfo.identifier);
|
||||
_hasStart = true;
|
||||
}
|
||||
|
||||
if (dictionary.hasValue<std::string>(EndInfo.identifier)) {
|
||||
_end = SpiceManager::ref().ephemerisTimeFromDate(
|
||||
dictionary.value<std::string>(EndInfo.identifier)
|
||||
);
|
||||
_hasEnd = true;
|
||||
}
|
||||
else if (dictionary.hasValue<double>(EndInfo.identifier)) {
|
||||
_end = dictionary.value<double>(EndInfo.identifier);
|
||||
_hasEnd = true;
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace openspace
|
||||
|
||||
@@ -38,30 +38,20 @@ namespace {
|
||||
"The time frame is active when any of the contained time frames are, "
|
||||
"but not in gaps between contained time frames."
|
||||
};
|
||||
|
||||
struct [[codegen::Dictionary(TimeFrameUnion)]] Parameters {
|
||||
// [[codegen::verbatim(TimeFramesInfo.description)]]
|
||||
std::vector<std::monostate> timeFrames [[codegen::reference("core_time_frame")]];
|
||||
};
|
||||
#include "timeframeunion_codegen.cpp"
|
||||
} // namespace
|
||||
|
||||
namespace openspace {
|
||||
|
||||
documentation::Documentation TimeFrameUnion::Documentation() {
|
||||
using namespace openspace::documentation;
|
||||
return {
|
||||
"Time Frame Union",
|
||||
"base_time_frame_union",
|
||||
{
|
||||
{
|
||||
TimeFramesInfo.identifier,
|
||||
new TableVerifier({
|
||||
{
|
||||
"*",
|
||||
new ReferencingVerifier("core_time_frame"),
|
||||
Optional::Yes
|
||||
}
|
||||
}),
|
||||
Optional::No,
|
||||
TimeFramesInfo.description
|
||||
},
|
||||
}
|
||||
};
|
||||
documentation::Documentation doc = codegen::doc<Parameters>();
|
||||
doc.id = "base_time_frame_union";
|
||||
return doc;
|
||||
}
|
||||
|
||||
bool TimeFrameUnion::isActive(const Time& time) const {
|
||||
@@ -76,9 +66,10 @@ bool TimeFrameUnion::isActive(const Time& time) const {
|
||||
TimeFrameUnion::TimeFrameUnion(const ghoul::Dictionary& dictionary)
|
||||
: TimeFrame()
|
||||
{
|
||||
documentation::testSpecificationAndThrow(Documentation(),
|
||||
dictionary,
|
||||
"TimeFrameUnion");
|
||||
// I don't know how we can actually help the reference attribute properly. Since the
|
||||
// Parameter list only contains the monostate, there is no need to actually create
|
||||
// the object here
|
||||
codegen::bake<Parameters>(dictionary);
|
||||
|
||||
ghoul::Dictionary frames =
|
||||
dictionary.value<ghoul::Dictionary>(TimeFramesInfo.identifier);
|
||||
|
||||
@@ -33,7 +33,6 @@
|
||||
#include <ghoul/logging/logmanager.h>
|
||||
#include <ghoul/lua/ghoul_lua.h>
|
||||
#include <ghoul/lua/lua_helper.h>
|
||||
|
||||
#include <chrono>
|
||||
|
||||
namespace {
|
||||
@@ -46,32 +45,22 @@ namespace {
|
||||
"epoch as the first argument, the current wall time as milliseconds past the "
|
||||
"J2000 epoch as the second argument and computes the translation."
|
||||
};
|
||||
|
||||
struct [[codegen::Dictionary(LuaTranslation)]] Parameters {
|
||||
// [[codegen::verbatim(ScriptInfo.description)]]
|
||||
std::string script;
|
||||
};
|
||||
#include "luatranslation_codegen.cpp"
|
||||
} // namespace
|
||||
|
||||
namespace openspace {
|
||||
|
||||
documentation::Documentation LuaTranslation::Documentation() {
|
||||
using namespace documentation;
|
||||
return {
|
||||
"Lua Translation",
|
||||
"base_transform_translation_lua",
|
||||
{
|
||||
{
|
||||
"Type",
|
||||
new StringEqualVerifier("LuaTranslation"),
|
||||
Optional::No
|
||||
},
|
||||
{
|
||||
ScriptInfo.identifier,
|
||||
new StringVerifier,
|
||||
Optional::No,
|
||||
ScriptInfo.description
|
||||
}
|
||||
}
|
||||
};
|
||||
documentation::Documentation doc = codegen::doc<Parameters>();
|
||||
doc.id = "base_transform_translation_lua";
|
||||
return doc;
|
||||
}
|
||||
|
||||
|
||||
LuaTranslation::LuaTranslation()
|
||||
: _luaScriptFile(ScriptInfo)
|
||||
, _state(ghoul::lua::LuaState::IncludeStandardLibrary::No)
|
||||
@@ -89,13 +78,8 @@ LuaTranslation::LuaTranslation()
|
||||
}
|
||||
|
||||
LuaTranslation::LuaTranslation(const ghoul::Dictionary& dictionary) : LuaTranslation() {
|
||||
documentation::testSpecificationAndThrow(
|
||||
Documentation(),
|
||||
dictionary,
|
||||
"StaticTranslation"
|
||||
);
|
||||
|
||||
_luaScriptFile = absPath(dictionary.value<std::string>(ScriptInfo.identifier));
|
||||
const Parameters p = codegen::bake<Parameters>(dictionary);
|
||||
_luaScriptFile = absPath(p.script);
|
||||
}
|
||||
|
||||
glm::dvec3 LuaTranslation::position(const UpdateData& data) const {
|
||||
|
||||
@@ -34,32 +34,22 @@ namespace {
|
||||
"This value is used as a static offset (in meters) that is applied to the scene "
|
||||
"graph node that this transformation is attached to relative to its parent."
|
||||
};
|
||||
|
||||
struct [[codegen::Dictionary(StaticTranslation)]] Parameters {
|
||||
// [[codegen::verbatim(PositionInfo.description)]]
|
||||
glm::dvec3 position;
|
||||
};
|
||||
#include "statictranslation_codegen.cpp"
|
||||
} // namespace
|
||||
|
||||
namespace openspace {
|
||||
|
||||
documentation::Documentation StaticTranslation::Documentation() {
|
||||
using namespace documentation;
|
||||
return {
|
||||
"Static Translation",
|
||||
"base_transform_translation_static",
|
||||
{
|
||||
{
|
||||
"Type",
|
||||
new StringEqualVerifier("StaticTranslation"),
|
||||
Optional::No
|
||||
},
|
||||
{
|
||||
PositionInfo.identifier,
|
||||
new DoubleVector3Verifier,
|
||||
Optional::No,
|
||||
PositionInfo.description
|
||||
}
|
||||
}
|
||||
};
|
||||
documentation::Documentation doc = codegen::doc<Parameters>();
|
||||
doc.id = "base_transform_translation_static";
|
||||
return doc;
|
||||
}
|
||||
|
||||
|
||||
StaticTranslation::StaticTranslation()
|
||||
: _position(
|
||||
PositionInfo,
|
||||
@@ -79,13 +69,8 @@ StaticTranslation::StaticTranslation()
|
||||
StaticTranslation::StaticTranslation(const ghoul::Dictionary& dictionary)
|
||||
: StaticTranslation()
|
||||
{
|
||||
documentation::testSpecificationAndThrow(
|
||||
Documentation(),
|
||||
dictionary,
|
||||
"StaticTranslation"
|
||||
);
|
||||
|
||||
_position = dictionary.value<glm::dvec3>(PositionInfo.identifier);
|
||||
const Parameters p = codegen::bake<Parameters>(dictionary);
|
||||
_position = p.position;
|
||||
}
|
||||
|
||||
glm::dvec3 StaticTranslation::position(const UpdateData&) const {
|
||||
|
||||
@@ -30,7 +30,6 @@
|
||||
#include <openspace/util/time.h>
|
||||
|
||||
namespace {
|
||||
constexpr const char* KeyType = "Type";
|
||||
constexpr const char* KeyKeyframes = "Keyframes";
|
||||
} // namespace
|
||||
|
||||
@@ -42,11 +41,6 @@ documentation::Documentation TimelineTranslation::Documentation() {
|
||||
"Timeline Translation",
|
||||
"base_transform_translation_keyframe",
|
||||
{
|
||||
{
|
||||
KeyType,
|
||||
new StringEqualVerifier("TimelineTranslation"),
|
||||
Optional::No
|
||||
},
|
||||
{
|
||||
KeyKeyframes,
|
||||
new TableVerifier({
|
||||
|
||||
@@ -50,6 +50,7 @@
|
||||
#include <fstream>
|
||||
#include <cstdint>
|
||||
#include <locale>
|
||||
#include <optional>
|
||||
#include <string>
|
||||
|
||||
namespace {
|
||||
@@ -65,17 +66,6 @@ namespace {
|
||||
"hasColorMap", "enabledRectSizeControl", "hasDvarScaling"
|
||||
};
|
||||
|
||||
constexpr const char* KeyFile = "File";
|
||||
constexpr const char* keyColor = "Color";
|
||||
constexpr const char* keyUnit = "Unit";
|
||||
constexpr const char* MeterUnit = "m";
|
||||
constexpr const char* KilometerUnit = "Km";
|
||||
constexpr const char* ParsecUnit = "pc";
|
||||
constexpr const char* KiloparsecUnit = "Kpc";
|
||||
constexpr const char* MegaparsecUnit = "Mpc";
|
||||
constexpr const char* GigaparsecUnit = "Gpc";
|
||||
constexpr const char* GigalightyearUnit = "Gly";
|
||||
|
||||
constexpr int8_t CurrentCacheVersion = 1;
|
||||
constexpr double PARSEC = 0.308567756E17;
|
||||
|
||||
@@ -107,26 +97,6 @@ namespace {
|
||||
"The path to the color map file of the astronomical object."
|
||||
};
|
||||
|
||||
constexpr openspace::properties::Property::PropertyInfo ExactColorMapInfo = {
|
||||
"ExactColorMap",
|
||||
"Exact Color Map File",
|
||||
"Set a 1 to 1 relationship between the color index variable and the colormap"
|
||||
" entrered value."
|
||||
};
|
||||
|
||||
constexpr openspace::properties::Property::PropertyInfo ColorRangeInfo = {
|
||||
"ColorRange",
|
||||
"Color Range",
|
||||
"This value determines the colormap ranges for the color parameters of the "
|
||||
"astronomical objects."
|
||||
};
|
||||
|
||||
constexpr openspace::properties::Property::PropertyInfo PolygonSidesInfo = {
|
||||
"PolygonSides",
|
||||
"Polygon Sides",
|
||||
"The number of sides for the polygon used to represent the astronomical object."
|
||||
};
|
||||
|
||||
constexpr openspace::properties::Property::PropertyInfo TextColorInfo = {
|
||||
"TextColor",
|
||||
"Text Color",
|
||||
@@ -146,13 +116,6 @@ namespace {
|
||||
"The text size for the astronomical object labels."
|
||||
};
|
||||
|
||||
constexpr openspace::properties::Property::PropertyInfo LabelFileInfo = {
|
||||
"LabelFile",
|
||||
"Label File",
|
||||
"The path to the label file that contains information about the astronomical "
|
||||
"objects being rendered."
|
||||
};
|
||||
|
||||
constexpr openspace::properties::Property::PropertyInfo LabelMinSizeInfo = {
|
||||
"TextMinSize",
|
||||
"Text Min Size",
|
||||
@@ -199,12 +162,6 @@ namespace {
|
||||
"of the astronomical objects."
|
||||
};
|
||||
|
||||
constexpr openspace::properties::Property::PropertyInfo TransformationMatrixInfo = {
|
||||
"TransformationMatrix",
|
||||
"Transformation Matrix",
|
||||
"Transformation matrix to be applied to each astronomical object."
|
||||
};
|
||||
|
||||
constexpr openspace::properties::Property::PropertyInfo RenderOptionInfo = {
|
||||
"RenderOption",
|
||||
"Render Option",
|
||||
@@ -270,180 +227,120 @@ namespace {
|
||||
"Set Data Range from Data",
|
||||
"Set the data range based on the available data"
|
||||
};
|
||||
|
||||
struct [[codegen::Dictionary(RenderableBillboardsCloud)]] Parameters {
|
||||
// The path to the SPECK file that contains information about the astronomical
|
||||
// object being rendered
|
||||
std::optional<std::string> file;
|
||||
|
||||
// [[codegen::verbatim(ColorInfo.description)]]
|
||||
glm::vec3 color;
|
||||
|
||||
// [[codegen::verbatim(SpriteTextureInfo.description)]]
|
||||
std::optional<std::string> texture;
|
||||
|
||||
// [[codegen::verbatim(DrawElementsInfo.description)]]
|
||||
std::optional<bool> drawElements;
|
||||
|
||||
enum class RenderOption {
|
||||
ViewDirection [[codegen::key("Camera View Direction")]],
|
||||
PositionNormal [[codegen::key("Camera Position Normal")]]
|
||||
};
|
||||
// [[codegen::verbatim(RenderOptionInfo.description)]]
|
||||
std::optional<RenderOption> renderOption;
|
||||
|
||||
enum class Unit {
|
||||
Meter [[codegen::key("m")]],
|
||||
Kilometer [[codegen::key("Km")]],
|
||||
Parsec [[codegen::key("pc")]],
|
||||
Kiloparsec [[codegen::key("Kpc")]],
|
||||
Megaparsec [[codegen::key("Mpc")]],
|
||||
Gigaparsec [[codegen::key("Gpc")]],
|
||||
GigalightYears [[codegen::key("Gly")]]
|
||||
};
|
||||
std::optional<Unit> unit;
|
||||
|
||||
// [[codegen::verbatim(ScaleFactorInfo.description)]]
|
||||
std::optional<float> scaleFactor;
|
||||
|
||||
// [[codegen::verbatim(ColorMapInfo.description)]]
|
||||
std::optional<std::string> colorMap;
|
||||
|
||||
// Set a 1 to 1 relationship between the color index variable and the colormap
|
||||
// entrered value
|
||||
std::optional<bool> exactColorMap;
|
||||
|
||||
// The number of sides for the polygon used to represent the astronomical object
|
||||
std::optional<int> polygonSides;
|
||||
|
||||
// [[codgen::verbatim(DrawLabelInfo.description)]]
|
||||
std::optional<bool> drawLabels;
|
||||
|
||||
// [[codgen::verbatim(TextColorInfo.description)]]
|
||||
std::optional<glm::vec3> textColor;
|
||||
|
||||
// [[codgen::verbatim(TextOpacityInfo.description)]]
|
||||
std::optional<float> textOpacity;
|
||||
|
||||
// [[codgen::verbatim(TextSizeInfo.description)]]
|
||||
std::optional<float> textSize;
|
||||
|
||||
// The path to the label file that contains information about the astronomical
|
||||
// objects being rendered
|
||||
std::optional<std::string> labelFile;
|
||||
|
||||
// [[codgen::verbatim(LabelMinSizeInfo.description)]]
|
||||
std::optional<float> textMinSize;
|
||||
|
||||
// [[codgen::verbatim(LabelMaxSizeInfo.description)]]
|
||||
std::optional<float> textMaxSize;
|
||||
|
||||
// [[codgen::verbatim(ColorOptionInfo.description)]]
|
||||
std::optional<std::vector<std::string>> colorOption;
|
||||
|
||||
// [[codgen::verbatim(SizeOptionInfo.description)]]
|
||||
std::optional<std::vector<std::string>> sizeOption;
|
||||
|
||||
// This value determines the colormap ranges for the color parameters of the
|
||||
// astronomical objects
|
||||
std::optional<std::vector<glm::vec2>> colorRange;
|
||||
|
||||
// Transformation matrix to be applied to each astronomical object
|
||||
std::optional<glm::dmat4x4> transformationMatrix;
|
||||
|
||||
// [[codgen::verbatim(FadeInDistancesInfo.description)]]
|
||||
std::optional<glm::dvec2> fadeInDistances;
|
||||
|
||||
// [[codgen::verbatim(DisableFadeInInfo.description)]]
|
||||
std::optional<bool> disableFadeIn;
|
||||
|
||||
// [[codgen::verbatim(BillboardMaxSizeInfo.description)]]
|
||||
std::optional<float> billboardMaxSize;
|
||||
|
||||
// [[codgen::verbatim(BillboardMinSizeInfo.description)]]
|
||||
std::optional<float> billboardMinSize;
|
||||
|
||||
// [[codgen::verbatim(CorrectionSizeEndDistanceInfo.description)]]
|
||||
std::optional<float> correctionSizeEndDistance;
|
||||
|
||||
// [[codgen::verbatim(CorrectionSizeFactorInfo.description)]]
|
||||
std::optional<float> correctionSizeFactor;
|
||||
|
||||
// [[codgen::verbatim(PixelSizeControlInfo.description)]]
|
||||
std::optional<bool> enablePixelSizeControl;
|
||||
|
||||
// [[codgen::verbatim(UseLinearFiltering.description)]]
|
||||
std::optional<bool> useLinearFiltering;
|
||||
};
|
||||
#include "renderablebillboardscloud_codegen.cpp"
|
||||
} // namespace
|
||||
|
||||
namespace openspace {
|
||||
|
||||
documentation::Documentation RenderableBillboardsCloud::Documentation() {
|
||||
using namespace documentation;
|
||||
return {
|
||||
"RenderableBillboardsCloud",
|
||||
"digitaluniverse_RenderableBillboardsCloud",
|
||||
{
|
||||
{
|
||||
"Type",
|
||||
new StringEqualVerifier("RenderableBillboardsCloud"),
|
||||
Optional::No
|
||||
},
|
||||
{
|
||||
KeyFile,
|
||||
new StringVerifier,
|
||||
Optional::Yes,
|
||||
"The path to the SPECK file that contains information about the "
|
||||
"astronomical object being rendered."
|
||||
},
|
||||
{
|
||||
keyColor,
|
||||
new DoubleVector3Verifier,
|
||||
Optional::No,
|
||||
"Astronomical Object Color (r,g,b)."
|
||||
},
|
||||
{
|
||||
SpriteTextureInfo.identifier,
|
||||
new StringVerifier,
|
||||
Optional::Yes,
|
||||
SpriteTextureInfo.description
|
||||
},
|
||||
{
|
||||
ScaleFactorInfo.identifier,
|
||||
new DoubleVerifier,
|
||||
Optional::Yes,
|
||||
ScaleFactorInfo.description
|
||||
},
|
||||
{
|
||||
ColorMapInfo.identifier,
|
||||
new StringVerifier,
|
||||
Optional::Yes,
|
||||
ColorMapInfo.description
|
||||
},
|
||||
{
|
||||
ExactColorMapInfo.identifier,
|
||||
new BoolVerifier,
|
||||
Optional::Yes,
|
||||
ExactColorMapInfo.description
|
||||
},
|
||||
{
|
||||
PolygonSidesInfo.identifier,
|
||||
new IntVerifier,
|
||||
Optional::Yes,
|
||||
PolygonSidesInfo.description
|
||||
},
|
||||
{
|
||||
DrawLabelInfo.identifier,
|
||||
new BoolVerifier,
|
||||
Optional::Yes,
|
||||
DrawLabelInfo.description
|
||||
},
|
||||
{
|
||||
TextColorInfo.identifier,
|
||||
new DoubleVector3Verifier,
|
||||
Optional::Yes,
|
||||
TextColorInfo.description
|
||||
},
|
||||
{
|
||||
TextOpacityInfo.identifier,
|
||||
new DoubleVerifier,
|
||||
Optional::Yes,
|
||||
TextOpacityInfo.description
|
||||
},
|
||||
{
|
||||
TextSizeInfo.identifier,
|
||||
new DoubleVerifier,
|
||||
Optional::Yes,
|
||||
TextSizeInfo.description
|
||||
},
|
||||
{
|
||||
LabelFileInfo.identifier,
|
||||
new StringVerifier,
|
||||
Optional::Yes,
|
||||
LabelFileInfo.description
|
||||
},
|
||||
{
|
||||
LabelMinSizeInfo.identifier,
|
||||
new DoubleVerifier,
|
||||
Optional::Yes,
|
||||
LabelMinSizeInfo.description
|
||||
},
|
||||
{
|
||||
LabelMaxSizeInfo.identifier,
|
||||
new DoubleVerifier,
|
||||
Optional::Yes,
|
||||
LabelMaxSizeInfo.description
|
||||
},
|
||||
{
|
||||
ColorOptionInfo.identifier,
|
||||
new StringListVerifier,
|
||||
Optional::Yes,
|
||||
ColorOptionInfo.description
|
||||
},
|
||||
{
|
||||
SizeOptionInfo.identifier,
|
||||
new StringListVerifier,
|
||||
Optional::Yes,
|
||||
SizeOptionInfo.description
|
||||
},
|
||||
{
|
||||
ColorRangeInfo.identifier,
|
||||
new Vector2ListVerifier<double>,
|
||||
Optional::Yes,
|
||||
ColorRangeInfo.description
|
||||
},
|
||||
{
|
||||
TransformationMatrixInfo.identifier,
|
||||
new Matrix4x4Verifier<double>,
|
||||
Optional::Yes,
|
||||
TransformationMatrixInfo.description
|
||||
},
|
||||
{
|
||||
FadeInDistancesInfo.identifier,
|
||||
new Vector2Verifier<double>,
|
||||
Optional::Yes,
|
||||
FadeInDistancesInfo.description
|
||||
},
|
||||
{
|
||||
DisableFadeInInfo.identifier,
|
||||
new BoolVerifier,
|
||||
Optional::Yes,
|
||||
DisableFadeInInfo.description
|
||||
},
|
||||
{
|
||||
BillboardMaxSizeInfo.identifier,
|
||||
new DoubleVerifier,
|
||||
Optional::Yes,
|
||||
BillboardMaxSizeInfo.description
|
||||
},
|
||||
{
|
||||
BillboardMinSizeInfo.identifier,
|
||||
new DoubleVerifier,
|
||||
Optional::Yes,
|
||||
BillboardMinSizeInfo.description
|
||||
},
|
||||
{
|
||||
CorrectionSizeEndDistanceInfo.identifier,
|
||||
new DoubleVerifier,
|
||||
Optional::Yes,
|
||||
CorrectionSizeEndDistanceInfo.description
|
||||
},
|
||||
{
|
||||
CorrectionSizeFactorInfo.identifier,
|
||||
new DoubleVerifier,
|
||||
Optional::Yes,
|
||||
CorrectionSizeFactorInfo.description
|
||||
},
|
||||
{
|
||||
PixelSizeControlInfo.identifier,
|
||||
new BoolVerifier,
|
||||
Optional::Yes,
|
||||
PixelSizeControlInfo.description
|
||||
},
|
||||
{
|
||||
UseLinearFiltering.identifier,
|
||||
new BoolVerifier,
|
||||
Optional::Yes,
|
||||
UseLinearFiltering.description
|
||||
}
|
||||
}
|
||||
};
|
||||
documentation::Documentation doc = codegen::doc<Parameters>();
|
||||
doc.id = "digitaluniverse_RenderableBillboardsCloud";
|
||||
return doc;
|
||||
}
|
||||
|
||||
RenderableBillboardsCloud::RenderableBillboardsCloud(const ghoul::Dictionary& dictionary)
|
||||
@@ -481,98 +378,87 @@ RenderableBillboardsCloud::RenderableBillboardsCloud(const ghoul::Dictionary& di
|
||||
, _setRangeFromData(SetRangeFromData)
|
||||
, _renderOption(RenderOptionInfo, properties::OptionProperty::DisplayType::Dropdown)
|
||||
{
|
||||
documentation::testSpecificationAndThrow(
|
||||
Documentation(),
|
||||
dictionary,
|
||||
"RenderableBillboardsCloud"
|
||||
);
|
||||
const Parameters p = codegen::bake<Parameters>(dictionary);
|
||||
|
||||
if (dictionary.hasKey(KeyFile)) {
|
||||
_speckFile = absPath(dictionary.value<std::string>(KeyFile));
|
||||
_hasSpeckFile = true;
|
||||
}
|
||||
|
||||
if (dictionary.hasKey(DrawElementsInfo.identifier)) {
|
||||
_drawElements = dictionary.value<bool>(DrawElementsInfo.identifier);
|
||||
if (p.file.has_value()) {
|
||||
_speckFile = absPath(*p.file);
|
||||
}
|
||||
_hasSpeckFile = p.file.has_value();
|
||||
|
||||
_drawElements = p.drawElements.value_or(_drawElements);
|
||||
_drawElements.onChange([&]() { _hasSpeckFile = !_hasSpeckFile; });
|
||||
addProperty(_drawElements);
|
||||
|
||||
_renderOption.addOption(RenderOptionViewDirection, "Camera View Direction");
|
||||
_renderOption.addOption(RenderOptionPositionNormal, "Camera Position Normal");
|
||||
|
||||
_renderOption = RenderOptionViewDirection;
|
||||
if (dictionary.hasValue<std::string>(RenderOptionInfo.identifier)) {
|
||||
const std::string o = dictionary.value<std::string>(RenderOptionInfo.identifier);
|
||||
|
||||
if (o == "Camera View Direction") {
|
||||
_renderOption = RenderOptionViewDirection;
|
||||
}
|
||||
else if (o == "Camera Position Normal") {
|
||||
_renderOption = RenderOptionPositionNormal;
|
||||
if (p.renderOption.has_value()) {
|
||||
switch (*p.renderOption) {
|
||||
case Parameters::RenderOption::ViewDirection:
|
||||
_renderOption = RenderOptionViewDirection;
|
||||
break;
|
||||
case Parameters::RenderOption::PositionNormal:
|
||||
_renderOption = RenderOptionPositionNormal;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
else {
|
||||
_renderOption = RenderOptionViewDirection;
|
||||
}
|
||||
addProperty(_renderOption);
|
||||
|
||||
if (dictionary.hasKey(keyUnit)) {
|
||||
std::string unit = dictionary.value<std::string>(keyUnit);
|
||||
if (unit == MeterUnit) {
|
||||
_unit = Meter;
|
||||
}
|
||||
else if (unit == KilometerUnit) {
|
||||
_unit = Kilometer;
|
||||
}
|
||||
else if (unit == ParsecUnit) {
|
||||
_unit = Parsec;
|
||||
}
|
||||
else if (unit == KiloparsecUnit) {
|
||||
_unit = Kiloparsec;
|
||||
}
|
||||
else if (unit == MegaparsecUnit) {
|
||||
_unit = Megaparsec;
|
||||
}
|
||||
else if (unit == GigaparsecUnit) {
|
||||
_unit = Gigaparsec;
|
||||
}
|
||||
else if (unit == GigalightyearUnit) {
|
||||
_unit = GigalightYears;
|
||||
}
|
||||
else {
|
||||
LWARNING(
|
||||
"No unit given for RenderableBillboardsCloud. Using meters as units."
|
||||
);
|
||||
_unit = Meter;
|
||||
if (p.unit.has_value()) {
|
||||
switch (*p.unit) {
|
||||
case Parameters::Unit::Meter:
|
||||
_unit = Meter;
|
||||
break;
|
||||
case Parameters::Unit::Kilometer:
|
||||
_unit = Kilometer;
|
||||
break;
|
||||
case Parameters::Unit::Parsec:
|
||||
_unit = Parsec;
|
||||
break;
|
||||
case Parameters::Unit::Kiloparsec:
|
||||
_unit = Kiloparsec;
|
||||
break;
|
||||
case Parameters::Unit::Megaparsec:
|
||||
_unit = Megaparsec;
|
||||
break;
|
||||
case Parameters::Unit::Gigaparsec:
|
||||
_unit = Gigaparsec;
|
||||
break;
|
||||
case Parameters::Unit::GigalightYears:
|
||||
_unit = GigalightYears;
|
||||
break;
|
||||
}
|
||||
}
|
||||
else {
|
||||
LWARNING("No unit given for RenderableBillboardsCloud. Using meters as units.");
|
||||
_unit = Meter;
|
||||
}
|
||||
|
||||
if (dictionary.hasKey(SpriteTextureInfo.identifier)) {
|
||||
_spriteTexturePath = absPath(dictionary.value<std::string>(
|
||||
SpriteTextureInfo.identifier
|
||||
));
|
||||
|
||||
if (p.texture.has_value()) {
|
||||
_spriteTexturePath = absPath(*p.texture);
|
||||
_spriteTexturePath.onChange([&]() { _spriteTextureIsDirty = true; });
|
||||
|
||||
// @TODO (abock, 2021-01-31) I don't know why we only add this property if the
|
||||
// texture is given, but I think it's a bug
|
||||
addProperty(_spriteTexturePath);
|
||||
|
||||
_hasSpriteTexture = true;
|
||||
}
|
||||
_hasSpriteTexture = p.texture.has_value();
|
||||
|
||||
if (dictionary.hasKey(ColorMapInfo.identifier)) {
|
||||
_colorMapFile = absPath(dictionary.value<std::string>(ColorMapInfo.identifier));
|
||||
|
||||
if (p.colorMap.has_value()) {
|
||||
_colorMapFile = absPath(*p.colorMap);
|
||||
_hasColorMapFile = true;
|
||||
|
||||
if (dictionary.hasKey(ColorOptionInfo.identifier)) {
|
||||
ghoul::Dictionary colorOptionDataDic = dictionary.value<ghoul::Dictionary>(
|
||||
ColorOptionInfo.identifier
|
||||
);
|
||||
for (int i = 0; i < static_cast<int>(colorOptionDataDic.size()); ++i) {
|
||||
std::string colorMapInUseName(
|
||||
colorOptionDataDic.value<std::string>(std::to_string(i + 1))
|
||||
);
|
||||
_colorOption.addOption(i, colorMapInUseName);
|
||||
_optionConversionMap.insert({ i, colorMapInUseName });
|
||||
_colorOptionString = colorMapInUseName;
|
||||
if (p.colorOption.has_value()) {
|
||||
std::vector<std::string> opts = *p.colorOption;
|
||||
for (size_t i = 0; i < opts.size(); ++i) {
|
||||
_colorOption.addOption(static_cast<int>(i), opts[i]);
|
||||
_optionConversionMap.insert({ static_cast<int>(i), opts[i] });
|
||||
_colorOptionString = opts[i];
|
||||
}
|
||||
}
|
||||
_colorOption.onChange([&]() {
|
||||
@@ -583,15 +469,8 @@ RenderableBillboardsCloud::RenderableBillboardsCloud(const ghoul::Dictionary& di
|
||||
});
|
||||
addProperty(_colorOption);
|
||||
|
||||
if (dictionary.hasKey(ColorRangeInfo.identifier)) {
|
||||
ghoul::Dictionary rangeDataDict = dictionary.value<ghoul::Dictionary>(
|
||||
ColorRangeInfo.identifier
|
||||
);
|
||||
for (size_t i = 0; i < rangeDataDict.size(); ++i) {
|
||||
_colorRangeData.push_back(
|
||||
rangeDataDict.value<glm::dvec2>(std::to_string(i + 1))
|
||||
);
|
||||
}
|
||||
_colorRangeData = p.colorRange.value_or(_colorRangeData);
|
||||
if (!_colorRangeData.empty()) {
|
||||
_optionColorRangeData = _colorRangeData[_colorRangeData.size() - 1];
|
||||
}
|
||||
_optionColorRangeData.onChange([&]() {
|
||||
@@ -601,36 +480,25 @@ RenderableBillboardsCloud::RenderableBillboardsCloud(const ghoul::Dictionary& di
|
||||
});
|
||||
addProperty(_optionColorRangeData);
|
||||
|
||||
if (dictionary.hasKey(ExactColorMapInfo.identifier)) {
|
||||
_isColorMapExact = dictionary.value<bool>(ExactColorMapInfo.identifier);
|
||||
}
|
||||
_isColorMapExact = p.exactColorMap.value_or(_isColorMapExact);
|
||||
}
|
||||
else if (dictionary.hasKey(keyColor)) {
|
||||
_pointColor = dictionary.value<glm::dvec3>(keyColor);
|
||||
else {
|
||||
_pointColor = p.color;
|
||||
_pointColor.setViewOption(properties::Property::ViewOptions::Color);
|
||||
addProperty(_pointColor);
|
||||
}
|
||||
|
||||
addProperty(_opacity);
|
||||
|
||||
if (dictionary.hasKey(ScaleFactorInfo.identifier)) {
|
||||
_scaleFactor = static_cast<float>(
|
||||
dictionary.value<double>(ScaleFactorInfo.identifier)
|
||||
);
|
||||
}
|
||||
_scaleFactor = p.scaleFactor.value_or(_scaleFactor);
|
||||
addProperty(_scaleFactor);
|
||||
|
||||
if (dictionary.hasKey(SizeOptionInfo.identifier)) {
|
||||
ghoul::Dictionary sizeOptionDataDic = dictionary.value<ghoul::Dictionary>(
|
||||
SizeOptionInfo.identifier
|
||||
);
|
||||
for (int i = 0; i < static_cast<int>(sizeOptionDataDic.size()); ++i) {
|
||||
std::string datavarSizeInUseName(
|
||||
sizeOptionDataDic.value<std::string>(std::to_string(i + 1))
|
||||
);
|
||||
_datavarSizeOption.addOption(i, datavarSizeInUseName);
|
||||
_optionConversionSizeMap.insert({ i, datavarSizeInUseName });
|
||||
_datavarSizeOptionString = datavarSizeInUseName;
|
||||
if (p.sizeOption.has_value()) {
|
||||
std::vector<std::string> opts = *p.sizeOption;
|
||||
for (size_t i = 0; i < opts.size(); ++i) {
|
||||
_datavarSizeOption.addOption(static_cast<int>(i), opts[i]);
|
||||
_optionConversionSizeMap.insert({ static_cast<int>(i), opts[i] });
|
||||
_datavarSizeOptionString = opts[i];
|
||||
}
|
||||
|
||||
_datavarSizeOption.onChange([&]() {
|
||||
@@ -642,104 +510,62 @@ RenderableBillboardsCloud::RenderableBillboardsCloud(const ghoul::Dictionary& di
|
||||
_hasDatavarSize = true;
|
||||
}
|
||||
|
||||
if (dictionary.hasKey(PolygonSidesInfo.identifier)) {
|
||||
_polygonSides = static_cast<int>(
|
||||
dictionary.value<double>(PolygonSidesInfo.identifier)
|
||||
);
|
||||
_hasPolygon = true;
|
||||
}
|
||||
_polygonSides = p.polygonSides.value_or(_polygonSides);
|
||||
_hasPolygon = p.polygonSides.has_value();
|
||||
|
||||
if (dictionary.hasKey(LabelFileInfo.identifier)) {
|
||||
if (dictionary.hasKey(DrawLabelInfo.identifier)) {
|
||||
_drawLabels = dictionary.value<bool>(DrawLabelInfo.identifier);
|
||||
}
|
||||
if (p.labelFile.has_value()) {
|
||||
_drawLabels = p.drawLabels.value_or(_drawLabels);
|
||||
addProperty(_drawLabels);
|
||||
|
||||
_labelFile = absPath(dictionary.value<std::string>(LabelFileInfo.identifier));
|
||||
_labelFile = absPath(*p.labelFile);
|
||||
_hasLabel = true;
|
||||
|
||||
if (dictionary.hasKey(TextColorInfo.identifier)) {
|
||||
_textColor = dictionary.value<glm::dvec3>(TextColorInfo.identifier);
|
||||
_hasLabel = true;
|
||||
}
|
||||
_textColor = p.textColor.value_or(_textColor);
|
||||
_hasLabel = p.textColor.has_value();
|
||||
_textColor.setViewOption(properties::Property::ViewOptions::Color);
|
||||
addProperty(_textColor);
|
||||
_textColor.onChange([&]() { _textColorIsDirty = true; });
|
||||
|
||||
if (dictionary.hasKey(TextOpacityInfo.identifier)) {
|
||||
_textOpacity = static_cast<float>(
|
||||
dictionary.value<double>(TextOpacityInfo.identifier)
|
||||
);
|
||||
}
|
||||
_textOpacity = p.textOpacity.value_or(_textOpacity);
|
||||
addProperty(_textOpacity);
|
||||
|
||||
if (dictionary.hasKey(TextSizeInfo.identifier)) {
|
||||
_textSize = static_cast<float>(
|
||||
dictionary.value<double>(TextSizeInfo.identifier)
|
||||
);
|
||||
}
|
||||
_textSize = p.textSize.value_or(_textSize);
|
||||
addProperty(_textSize);
|
||||
|
||||
if (dictionary.hasKey(LabelMinSizeInfo.identifier)) {
|
||||
_textMinSize = static_cast<float>(
|
||||
dictionary.value<double>(LabelMinSizeInfo.identifier)
|
||||
);
|
||||
}
|
||||
_textMinSize = p.textMinSize.value_or(_textMinSize);
|
||||
addProperty(_textMinSize);
|
||||
|
||||
if (dictionary.hasKey(LabelMaxSizeInfo.identifier)) {
|
||||
_textMaxSize = static_cast<float>(
|
||||
dictionary.value<double>(LabelMaxSizeInfo.identifier)
|
||||
);
|
||||
}
|
||||
_textMaxSize = p.textMaxSize.value_or(_textMaxSize);
|
||||
addProperty(_textMaxSize);
|
||||
}
|
||||
|
||||
if (dictionary.hasKey(TransformationMatrixInfo.identifier)) {
|
||||
_transformationMatrix = dictionary.value<glm::dmat4>(
|
||||
TransformationMatrixInfo.identifier
|
||||
);
|
||||
}
|
||||
_transformationMatrix = p.transformationMatrix.value_or(_transformationMatrix);
|
||||
|
||||
if (dictionary.hasKey(FadeInDistancesInfo.identifier)) {
|
||||
glm::dvec2 v = dictionary.value<glm::dvec2>(FadeInDistancesInfo.identifier);
|
||||
_fadeInDistance = v;
|
||||
_disableFadeInDistance = false;
|
||||
if (p.fadeInDistances.has_value()) {
|
||||
_fadeInDistance = *p.fadeInDistances;
|
||||
addProperty(_fadeInDistance);
|
||||
|
||||
_disableFadeInDistance = false;
|
||||
addProperty(_disableFadeInDistance);
|
||||
}
|
||||
|
||||
if (dictionary.hasKey(BillboardMaxSizeInfo.identifier)) {
|
||||
_billboardMaxSize = static_cast<float>(
|
||||
dictionary.value<double>(BillboardMaxSizeInfo.identifier)
|
||||
);
|
||||
}
|
||||
_billboardMaxSize = p.billboardMaxSize.value_or(_billboardMaxSize);
|
||||
addProperty(_billboardMaxSize);
|
||||
|
||||
if (dictionary.hasKey(BillboardMinSizeInfo.identifier)) {
|
||||
_billboardMinSize = static_cast<float>(
|
||||
dictionary.value<double>(BillboardMinSizeInfo.identifier)
|
||||
);
|
||||
}
|
||||
_billboardMinSize = p.billboardMinSize.value_or(_billboardMinSize);
|
||||
addProperty(_billboardMinSize);
|
||||
|
||||
if (dictionary.hasKey(CorrectionSizeEndDistanceInfo.identifier)) {
|
||||
_correctionSizeEndDistance = static_cast<float>(
|
||||
dictionary.value<double>(CorrectionSizeEndDistanceInfo.identifier)
|
||||
);
|
||||
}
|
||||
_correctionSizeEndDistance =
|
||||
p.correctionSizeEndDistance.value_or(_correctionSizeEndDistance);
|
||||
addProperty(_correctionSizeEndDistance);
|
||||
|
||||
if (dictionary.hasKey(CorrectionSizeFactorInfo.identifier)) {
|
||||
_correctionSizeFactor = static_cast<float>(
|
||||
dictionary.value<double>(CorrectionSizeFactorInfo.identifier)
|
||||
);
|
||||
|
||||
_correctionSizeFactor = p.correctionSizeFactor.value_or(_correctionSizeFactor);
|
||||
if (p.correctionSizeFactor.has_value()) {
|
||||
addProperty(_correctionSizeFactor);
|
||||
}
|
||||
|
||||
if (dictionary.hasKey(PixelSizeControlInfo.identifier)) {
|
||||
_pixelSizeControl = dictionary.value<bool>(PixelSizeControlInfo.identifier);
|
||||
_pixelSizeControl = p.enablePixelSizeControl.value_or(_pixelSizeControl);
|
||||
if (p.enablePixelSizeControl.has_value()) {
|
||||
addProperty(_pixelSizeControl);
|
||||
}
|
||||
|
||||
@@ -759,9 +585,7 @@ RenderableBillboardsCloud::RenderableBillboardsCloud(const ghoul::Dictionary& di
|
||||
});
|
||||
addProperty(_setRangeFromData);
|
||||
|
||||
if (dictionary.hasKey(UseLinearFiltering.identifier)) {
|
||||
_useLinearFiltering = dictionary.value<bool>(UseLinearFiltering.identifier);
|
||||
}
|
||||
_useLinearFiltering = p.useLinearFiltering.value_or(_useLinearFiltering);
|
||||
_useLinearFiltering.onChange([&]() { _dataIsDirty = true; });
|
||||
addProperty(_useLinearFiltering);
|
||||
}
|
||||
|
||||
@@ -43,8 +43,9 @@
|
||||
#include <ghoul/opengl/texture.h>
|
||||
#include <ghoul/opengl/textureunit.h>
|
||||
#include <array>
|
||||
#include <fstream>
|
||||
#include <cstdint>
|
||||
#include <fstream>
|
||||
#include <optional>
|
||||
|
||||
namespace {
|
||||
constexpr const char* _loggerCat = "RenderableDUMeshes";
|
||||
@@ -54,16 +55,6 @@ namespace {
|
||||
"modelViewTransform", "projectionTransform", "alphaValue", "color"
|
||||
};
|
||||
|
||||
constexpr const char* KeyFile = "File";
|
||||
constexpr const char* keyUnit = "Unit";
|
||||
constexpr const char* MeterUnit = "m";
|
||||
constexpr const char* KilometerUnit = "Km";
|
||||
constexpr const char* ParsecUnit = "pc";
|
||||
constexpr const char* KiloparsecUnit = "Kpc";
|
||||
constexpr const char* MegaparsecUnit = "Mpc";
|
||||
constexpr const char* GigaparsecUnit = "Gpc";
|
||||
constexpr const char* GigalightyearUnit = "Gly";
|
||||
|
||||
constexpr const int RenderOptionViewDirection = 0;
|
||||
constexpr const int RenderOptionPositionNormal = 1;
|
||||
|
||||
@@ -139,84 +130,59 @@ namespace {
|
||||
"Render Option",
|
||||
"Debug option for rendering of billboards and texts."
|
||||
};
|
||||
|
||||
struct [[codegen::Dictionary(RenderableDUMeshes)]] Parameters {
|
||||
// The path to the SPECK file that contains information about the astronomical
|
||||
// object being rendered
|
||||
std::string file;
|
||||
|
||||
// [[codegen::verbatim(DrawLabelInfo.description)]]
|
||||
std::optional<bool> drawLabels;
|
||||
|
||||
enum class Unit {
|
||||
Meter [[codegen::key("m")]],
|
||||
Kilometer [[codegen::key("Km")]],
|
||||
Parsec [[codegen::key("pc")]],
|
||||
Kiloparsec [[codegen::key("Kpc")]],
|
||||
MegaParsec [[codegen::key("Mpc")]],
|
||||
Gigaparsec [[codegen::key("Gpc")]],
|
||||
Gigalightyears [[codegen::key("Gly")]]
|
||||
};
|
||||
std::optional<Unit> unit;
|
||||
|
||||
// [[codegen::verbatim(TextColorInfo.description)]]
|
||||
std::optional<glm::vec3> textColor;
|
||||
|
||||
// [[codegen::verbatim(TextOpacityInfo.description)]]
|
||||
std::optional<float> textOpacity;
|
||||
|
||||
// [[codegen::verbatim(TextSizeInfo.description)]]
|
||||
std::optional<float> textSize;
|
||||
|
||||
// [[codegen::verbatim(LabelFileInfo.description)]]
|
||||
std::optional<std::string> labelFile;
|
||||
|
||||
// [[codegen::verbatim(LabelMinSizeInfo.description)]]
|
||||
std::optional<float> textMinSize;
|
||||
|
||||
// [[codegen::verbatim(LabelMaxSizeInfo.description)]]
|
||||
std::optional<float> textMaxSize;
|
||||
|
||||
// [[codegen::verbatim(LineWidthInfo.description)]]
|
||||
std::optional<float> lineWidth;
|
||||
|
||||
// [[codegen::verbatim(MeshColorInfo.description)]]
|
||||
std::optional<std::vector<glm::vec3>> meshColor;
|
||||
};
|
||||
#include "renderabledumeshes_codegen.cpp"
|
||||
} // namespace
|
||||
|
||||
namespace openspace {
|
||||
|
||||
documentation::Documentation RenderableDUMeshes::Documentation() {
|
||||
using namespace documentation;
|
||||
return {
|
||||
"RenderableDUMeshes",
|
||||
"digitaluniverse_renderabledumeshes",
|
||||
{
|
||||
{
|
||||
"Type",
|
||||
new StringEqualVerifier("RenderableDUMeshes"),
|
||||
Optional::No
|
||||
},
|
||||
{
|
||||
KeyFile,
|
||||
new StringVerifier,
|
||||
Optional::No,
|
||||
"The path to the SPECK file that contains information about the "
|
||||
"astronomical object being rendered."
|
||||
},
|
||||
{
|
||||
DrawLabelInfo.identifier,
|
||||
new BoolVerifier,
|
||||
Optional::Yes,
|
||||
DrawLabelInfo.description
|
||||
},
|
||||
{
|
||||
TextColorInfo.identifier,
|
||||
new DoubleVector3Verifier,
|
||||
Optional::Yes,
|
||||
TextColorInfo.description
|
||||
},
|
||||
{
|
||||
TextOpacityInfo.identifier,
|
||||
new DoubleVerifier,
|
||||
Optional::Yes,
|
||||
TextOpacityInfo.description
|
||||
},
|
||||
{
|
||||
TextSizeInfo.identifier,
|
||||
new DoubleVerifier,
|
||||
Optional::Yes,
|
||||
TextSizeInfo.description
|
||||
},
|
||||
{
|
||||
LabelFileInfo.identifier,
|
||||
new StringVerifier,
|
||||
Optional::Yes,
|
||||
LabelFileInfo.description
|
||||
},
|
||||
{
|
||||
LabelMinSizeInfo.identifier,
|
||||
new DoubleVerifier,
|
||||
Optional::Yes,
|
||||
LabelMinSizeInfo.description
|
||||
},
|
||||
{
|
||||
LabelMaxSizeInfo.identifier,
|
||||
new DoubleVerifier,
|
||||
Optional::Yes,
|
||||
LabelMaxSizeInfo.description
|
||||
},
|
||||
{
|
||||
LineWidthInfo.identifier,
|
||||
new DoubleVerifier,
|
||||
Optional::Yes,
|
||||
LineWidthInfo.description
|
||||
},
|
||||
{
|
||||
MeshColorInfo.identifier,
|
||||
new Vector3ListVerifier<double>,
|
||||
Optional::No,
|
||||
MeshColorInfo.description
|
||||
},
|
||||
}
|
||||
};
|
||||
documentation::Documentation doc = codegen::doc<Parameters>();
|
||||
doc.id = "digitaluniverse_renderabledumeshes";
|
||||
return doc;
|
||||
}
|
||||
|
||||
RenderableDUMeshes::RenderableDUMeshes(const ghoul::Dictionary& dictionary)
|
||||
@@ -231,24 +197,20 @@ RenderableDUMeshes::RenderableDUMeshes(const ghoul::Dictionary& dictionary)
|
||||
, _lineWidth(LineWidthInfo, 2.f, 0.f, 16.f)
|
||||
, _renderOption(RenderOptionInfo, properties::OptionProperty::DisplayType::Dropdown)
|
||||
{
|
||||
documentation::testSpecificationAndThrow(
|
||||
Documentation(),
|
||||
dictionary,
|
||||
"RenderableDUMeshes"
|
||||
);
|
||||
const Parameters p = codegen::bake<Parameters>(dictionary);
|
||||
|
||||
addProperty(_opacity);
|
||||
registerUpdateRenderBinFromOpacity();
|
||||
|
||||
if (dictionary.hasKey(KeyFile)) {
|
||||
_speckFile = absPath(dictionary.value<std::string>(KeyFile));
|
||||
_hasSpeckFile = true;
|
||||
_drawElements.onChange([&]() { _hasSpeckFile = !_hasSpeckFile; });
|
||||
addProperty(_drawElements);
|
||||
}
|
||||
_speckFile = absPath(p.file);
|
||||
_hasSpeckFile = true;
|
||||
_drawElements.onChange([&]() { _hasSpeckFile = !_hasSpeckFile; });
|
||||
addProperty(_drawElements);
|
||||
|
||||
_renderOption.addOption(RenderOptionViewDirection, "Camera View Direction");
|
||||
_renderOption.addOption(RenderOptionPositionNormal, "Camera Position Normal");
|
||||
// @TODO (abock. 2021-01-31) In the other DU classes, this is done with an enum, and
|
||||
// doing it based on the fisheye rendering seems a bit brittle?
|
||||
if (global::windowDelegate->isFisheyeRendering()) {
|
||||
_renderOption = RenderOptionPositionNormal;
|
||||
}
|
||||
@@ -257,96 +219,69 @@ RenderableDUMeshes::RenderableDUMeshes(const ghoul::Dictionary& dictionary)
|
||||
}
|
||||
addProperty(_renderOption);
|
||||
|
||||
if (dictionary.hasKey(keyUnit)) {
|
||||
std::string unit = dictionary.value<std::string>(keyUnit);
|
||||
if (unit == MeterUnit) {
|
||||
_unit = Meter;
|
||||
}
|
||||
else if (unit == KilometerUnit) {
|
||||
_unit = Kilometer;
|
||||
}
|
||||
else if (unit == ParsecUnit) {
|
||||
_unit = Parsec;
|
||||
}
|
||||
else if (unit == KiloparsecUnit) {
|
||||
_unit = Kiloparsec;
|
||||
}
|
||||
else if (unit == MegaparsecUnit) {
|
||||
_unit = Megaparsec;
|
||||
}
|
||||
else if (unit == GigaparsecUnit) {
|
||||
_unit = Gigaparsec;
|
||||
}
|
||||
else if (unit == GigalightyearUnit) {
|
||||
_unit = GigalightYears;
|
||||
}
|
||||
else {
|
||||
LWARNING("No unit given for RenderableDUMeshes. Using meters as units.");
|
||||
_unit = Meter;
|
||||
if (p.unit.has_value()) {
|
||||
switch (*p.unit) {
|
||||
case Parameters::Unit::Meter:
|
||||
_unit = Meter;
|
||||
break;
|
||||
case Parameters::Unit::Kilometer:
|
||||
_unit = Kilometer;
|
||||
break;
|
||||
case Parameters::Unit::Parsec:
|
||||
_unit = Parsec;
|
||||
break;
|
||||
case Parameters::Unit::Kiloparsec:
|
||||
_unit = Kiloparsec;
|
||||
break;
|
||||
case Parameters::Unit::MegaParsec:
|
||||
_unit = Megaparsec;
|
||||
break;
|
||||
case Parameters::Unit::Gigaparsec:
|
||||
_unit = Gigaparsec;
|
||||
break;
|
||||
case Parameters::Unit::Gigalightyears:
|
||||
_unit = GigalightYears;
|
||||
break;
|
||||
}
|
||||
}
|
||||
else {
|
||||
LWARNING("No unit given for RenderableDUMeshes. Using meters as units.");
|
||||
_unit = Meter;
|
||||
}
|
||||
|
||||
if (dictionary.hasValue<double>(LineWidthInfo.identifier)) {
|
||||
_lineWidth = static_cast<float>(
|
||||
dictionary.value<double>(LineWidthInfo.identifier)
|
||||
);
|
||||
}
|
||||
_lineWidth = p.lineWidth.value_or(_lineWidth);
|
||||
addProperty(_lineWidth);
|
||||
|
||||
if (dictionary.hasKey(DrawLabelInfo.identifier)) {
|
||||
_drawLabels = dictionary.value<bool>(DrawLabelInfo.identifier);
|
||||
}
|
||||
_drawLabels = p.drawLabels.value_or(_drawLabels);
|
||||
addProperty(_drawLabels);
|
||||
|
||||
if (dictionary.hasKey(LabelFileInfo.identifier)) {
|
||||
_labelFile = absPath(dictionary.value<std::string>(LabelFileInfo.identifier));
|
||||
if (p.labelFile.has_value()) {
|
||||
_labelFile = absPath(*p.labelFile);
|
||||
_hasLabel = true;
|
||||
|
||||
if (dictionary.hasKey(TextColorInfo.identifier)) {
|
||||
_textColor = dictionary.value<glm::dvec3>(TextColorInfo.identifier);
|
||||
_hasLabel = true;
|
||||
}
|
||||
_textColor = p.textColor.value_or(_textColor);
|
||||
_hasLabel = p.textColor.has_value();
|
||||
_textColor.setViewOption(properties::Property::ViewOptions::Color);
|
||||
addProperty(_textColor);
|
||||
_textColor.onChange([&]() { _textColorIsDirty = true; });
|
||||
|
||||
if (dictionary.hasKey(TextOpacityInfo.identifier)) {
|
||||
_textOpacity = static_cast<float>(
|
||||
dictionary.value<double>(TextOpacityInfo.identifier)
|
||||
);
|
||||
}
|
||||
_textOpacity = p.textOpacity.value_or(_textOpacity);
|
||||
addProperty(_textOpacity);
|
||||
|
||||
if (dictionary.hasKey(TextSizeInfo.identifier)) {
|
||||
_textSize = static_cast<float>(
|
||||
dictionary.value<double>(TextSizeInfo.identifier)
|
||||
);
|
||||
}
|
||||
_textSize = p.textSize.value_or(_textSize);
|
||||
addProperty(_textSize);
|
||||
|
||||
if (dictionary.hasKey(LabelMinSizeInfo.identifier)) {
|
||||
_textMinSize = static_cast<float>(
|
||||
floor(dictionary.value<double>(LabelMinSizeInfo.identifier))
|
||||
);
|
||||
}
|
||||
_textMinSize = p.textMinSize.value_or(_textMinSize);
|
||||
addProperty(_textMinSize);
|
||||
|
||||
if (dictionary.hasKey(LabelMaxSizeInfo.identifier)) {
|
||||
_textMaxSize = static_cast<float>(
|
||||
floor(dictionary.value<double>(LabelMaxSizeInfo.identifier))
|
||||
);
|
||||
}
|
||||
_textMaxSize = p.textMaxSize.value_or(_textMaxSize);
|
||||
addProperty(_textMaxSize);
|
||||
}
|
||||
|
||||
if (dictionary.hasKey(MeshColorInfo.identifier)) {
|
||||
ghoul::Dictionary colorDict = dictionary.value<ghoul::Dictionary>(
|
||||
MeshColorInfo.identifier
|
||||
);
|
||||
for (int i = 0; i < static_cast<int>(colorDict.size()); ++i) {
|
||||
_meshColorMap.insert(
|
||||
{ i + 1, colorDict.value<glm::dvec3>(std::to_string(i + 1)) }
|
||||
);
|
||||
if (p.meshColor.has_value()) {
|
||||
std::vector<glm::vec3> ops = *p.meshColor;
|
||||
for (size_t i = 0; i < ops.size(); ++i) {
|
||||
_meshColorMap.insert({ static_cast<int>(i) + 1, ops[i] });
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -42,6 +42,7 @@
|
||||
#include <ghoul/opengl/textureunit.h>
|
||||
#include <array>
|
||||
#include <fstream>
|
||||
#include <optional>
|
||||
#include <string>
|
||||
|
||||
namespace {
|
||||
@@ -52,16 +53,6 @@ namespace {
|
||||
"modelViewProjectionTransform", "alphaValue", "fadeInValue", "galaxyTexture"
|
||||
};
|
||||
|
||||
constexpr const char* KeyFile = "File";
|
||||
constexpr const char* keyUnit = "Unit";
|
||||
constexpr const char* MeterUnit = "m";
|
||||
constexpr const char* KilometerUnit = "Km";
|
||||
constexpr const char* ParsecUnit = "pc";
|
||||
constexpr const char* KiloparsecUnit = "Kpc";
|
||||
constexpr const char* MegaparsecUnit = "Mpc";
|
||||
constexpr const char* GigaparsecUnit = "Gpc";
|
||||
constexpr const char* GigalightyearUnit = "Gly";
|
||||
|
||||
constexpr int8_t CurrentCacheVersion = 2;
|
||||
constexpr double PARSEC = 0.308567756E17;
|
||||
|
||||
@@ -180,123 +171,83 @@ namespace {
|
||||
"object."
|
||||
};
|
||||
|
||||
struct [[codegen::Dictionary(RenderablePlanesCloud)]] Parameters {
|
||||
// The path to the SPECK file that contains information about the astronomical
|
||||
// object being rendered
|
||||
std::optional<std::string> file;
|
||||
|
||||
// [[codegen::verbatim(ScaleFactorInfo.description)]]
|
||||
std::optional<float> scaleFactor;
|
||||
|
||||
// [[codegen::verbatim(TextColorInfo.description)]]
|
||||
std::optional<glm::vec3> textColor;
|
||||
|
||||
// [[codegen::verbatim(TextOpacityInfo.description)]]
|
||||
std::optional<float> textOpacity;
|
||||
|
||||
// [[codegen::verbatim(TextSizeInfo.description)]]
|
||||
std::optional<float> textSize;
|
||||
|
||||
// [[codegen::verbatim(LabelFileInfo.description)]]
|
||||
std::optional<std::string> labelFile;
|
||||
|
||||
// [[codegen::verbatim(LabelMinSizeInfo.description)]]
|
||||
std::optional<int> textMinSize;
|
||||
|
||||
// [[codegen::verbatim(LabelMaxSizeInfo.description)]]
|
||||
std::optional<int> textMaxSize;
|
||||
|
||||
// [[codegen::verbatim(TransformationMatrixInfo.description)]]
|
||||
std::optional<glm::dmat4x4> transformationMatrix;
|
||||
|
||||
enum class BlendMode {
|
||||
Normal,
|
||||
Additive
|
||||
};
|
||||
|
||||
// [[codegen::verbatim(BlendModeInfo.description)]]
|
||||
std::optional<BlendMode> blendMode;
|
||||
|
||||
enum class Unit {
|
||||
Meter [[codegen::key("m")]],
|
||||
Kilometer [[codegen::key("Km")]],
|
||||
Parsec [[codegen::key("pc")]],
|
||||
Kiloparsec [[codegen::key("Kpc")]],
|
||||
Megaparsec [[codegen::key("Mpc")]],
|
||||
Gigaparsec [[codegen::key("Gpc")]],
|
||||
Gigalightyears [[codegen::key("Gly")]]
|
||||
};
|
||||
std::optional<Unit> unit;
|
||||
|
||||
// [[codegen::verbatim(TexturePathInfo.description)]]
|
||||
std::string texturePath;
|
||||
|
||||
// [[codegen::verbatim(LuminosityInfo.description)]]
|
||||
std::optional<std::string> luminosity;
|
||||
|
||||
// [[codegen::verbatim(ScaleLuminosityInfo.description)]]
|
||||
std::optional<float> scaleLuminosity;
|
||||
|
||||
// [[codegen::verbatim(FadeInDistancesInfo.description)]]
|
||||
std::optional<glm::vec2> fadeInDistances;
|
||||
|
||||
// [[codegen::verbatim(DisableFadeInInfo.description)]]
|
||||
std::optional<bool> disableFadeIn;
|
||||
|
||||
// [[codegen::verbatim(PlaneMinSizeInfo.description)]]
|
||||
std::optional<float> planeMinSize;
|
||||
};
|
||||
#include "renderableplanescloud_codegen.cpp"
|
||||
} // namespace
|
||||
|
||||
namespace openspace {
|
||||
|
||||
documentation::Documentation RenderablePlanesCloud::Documentation() {
|
||||
using namespace documentation;
|
||||
return {
|
||||
"RenderablePlanesCloud",
|
||||
"digitaluniverse_RenderablePlanesCloud",
|
||||
{
|
||||
{
|
||||
"Type",
|
||||
new StringEqualVerifier("RenderablePlanesCloud"),
|
||||
Optional::No
|
||||
},
|
||||
{
|
||||
KeyFile,
|
||||
new StringVerifier,
|
||||
Optional::Yes,
|
||||
"The path to the SPECK file that contains information about the "
|
||||
"astronomical object being rendered."
|
||||
},
|
||||
{
|
||||
ScaleFactorInfo.identifier,
|
||||
new DoubleVerifier,
|
||||
Optional::Yes,
|
||||
ScaleFactorInfo.description
|
||||
},
|
||||
{
|
||||
TextColorInfo.identifier,
|
||||
new DoubleVector3Verifier,
|
||||
Optional::Yes,
|
||||
TextColorInfo.description
|
||||
},
|
||||
{
|
||||
TextOpacityInfo.identifier,
|
||||
new DoubleVerifier,
|
||||
Optional::Yes,
|
||||
TextOpacityInfo.description
|
||||
},
|
||||
{
|
||||
TextSizeInfo.identifier,
|
||||
new DoubleVerifier,
|
||||
Optional::Yes,
|
||||
TextSizeInfo.description
|
||||
},
|
||||
{
|
||||
LabelFileInfo.identifier,
|
||||
new StringVerifier,
|
||||
Optional::Yes,
|
||||
LabelFileInfo.description
|
||||
},
|
||||
{
|
||||
LabelMinSizeInfo.identifier,
|
||||
new IntVerifier,
|
||||
Optional::Yes,
|
||||
LabelMinSizeInfo.description
|
||||
},
|
||||
{
|
||||
LabelMaxSizeInfo.identifier,
|
||||
new IntVerifier,
|
||||
Optional::Yes,
|
||||
LabelMaxSizeInfo.description
|
||||
},
|
||||
{
|
||||
TransformationMatrixInfo.identifier,
|
||||
new Matrix4x4Verifier<double>,
|
||||
Optional::Yes,
|
||||
TransformationMatrixInfo.description
|
||||
},
|
||||
{
|
||||
BlendModeInfo.identifier,
|
||||
new StringInListVerifier({ "Normal", "Additive" }),
|
||||
Optional::Yes,
|
||||
BlendModeInfo.description, // + " The default value is 'Normal'.",
|
||||
},
|
||||
{
|
||||
TexturePathInfo.identifier,
|
||||
new StringVerifier,
|
||||
Optional::No,
|
||||
TexturePathInfo.description,
|
||||
},
|
||||
{
|
||||
LuminosityInfo.identifier,
|
||||
new StringVerifier,
|
||||
Optional::Yes,
|
||||
LuminosityInfo.description,
|
||||
},
|
||||
{
|
||||
ScaleFactorInfo.identifier,
|
||||
new DoubleVerifier,
|
||||
Optional::Yes,
|
||||
ScaleFactorInfo.description,
|
||||
},
|
||||
{
|
||||
FadeInDistancesInfo.identifier,
|
||||
new DoubleVector2Verifier,
|
||||
Optional::Yes,
|
||||
FadeInDistancesInfo.description
|
||||
},
|
||||
{
|
||||
DisableFadeInInfo.identifier,
|
||||
new BoolVerifier,
|
||||
Optional::Yes,
|
||||
DisableFadeInInfo.description
|
||||
},
|
||||
{
|
||||
PlaneMinSizeInfo.identifier,
|
||||
new DoubleVerifier,
|
||||
Optional::Yes,
|
||||
PlaneMinSizeInfo.description
|
||||
},
|
||||
}
|
||||
};
|
||||
documentation::Documentation doc = codegen::doc<Parameters>();
|
||||
doc.id = "digitaluniverse_RenderablePlanesCloud";
|
||||
return doc;
|
||||
}
|
||||
|
||||
|
||||
RenderablePlanesCloud::RenderablePlanesCloud(const ghoul::Dictionary& dictionary)
|
||||
: Renderable(dictionary)
|
||||
, _scaleFactor(ScaleFactorInfo, 1.f, 0.f, 300000.f)
|
||||
@@ -315,16 +266,12 @@ RenderablePlanesCloud::RenderablePlanesCloud(const ghoul::Dictionary& dictionary
|
||||
, _planeMinSize(PlaneMinSizeInfo, 0.5, 0.0, 500.0)
|
||||
, _renderOption(RenderOptionInfo, properties::OptionProperty::DisplayType::Dropdown)
|
||||
{
|
||||
documentation::testSpecificationAndThrow(
|
||||
Documentation(),
|
||||
dictionary,
|
||||
"RenderablePlanesCloud"
|
||||
);
|
||||
const Parameters p = codegen::bake<Parameters>(dictionary);
|
||||
|
||||
addProperty(_opacity);
|
||||
|
||||
if (dictionary.hasKey(KeyFile)) {
|
||||
_speckFile = absPath(dictionary.value<std::string>(KeyFile));
|
||||
if (p.file.has_value()) {
|
||||
_speckFile = absPath(*p.file);
|
||||
_hasSpeckFile = true;
|
||||
_drawElements.onChange([&]() { _hasSpeckFile = !_hasSpeckFile; });
|
||||
addProperty(_drawElements);
|
||||
@@ -337,32 +284,29 @@ RenderablePlanesCloud::RenderablePlanesCloud(const ghoul::Dictionary& dictionary
|
||||
addProperty(_renderOption);
|
||||
//_renderOption.set(1);
|
||||
|
||||
if (dictionary.hasKey(keyUnit)) {
|
||||
const std::string& unit = dictionary.value<std::string>(keyUnit);
|
||||
if (unit == MeterUnit) {
|
||||
_unit = Meter;
|
||||
}
|
||||
else if (unit == KilometerUnit) {
|
||||
_unit = Kilometer;
|
||||
}
|
||||
else if (unit == ParsecUnit) {
|
||||
_unit = Parsec;
|
||||
}
|
||||
else if (unit == KiloparsecUnit) {
|
||||
_unit = Kiloparsec;
|
||||
}
|
||||
else if (unit == MegaparsecUnit) {
|
||||
_unit = Megaparsec;
|
||||
}
|
||||
else if (unit == GigaparsecUnit) {
|
||||
_unit = Gigaparsec;
|
||||
}
|
||||
else if (unit == GigalightyearUnit) {
|
||||
_unit = GigalightYears;
|
||||
}
|
||||
else {
|
||||
LWARNING("No unit given for RenderablePlanesCloud. Using meters as units.");
|
||||
_unit = Meter;
|
||||
if (p.unit.has_value()) {
|
||||
switch (*p.unit) {
|
||||
case Parameters::Unit::Meter:
|
||||
_unit = Meter;
|
||||
break;
|
||||
case Parameters::Unit::Kilometer:
|
||||
_unit = Kilometer;
|
||||
break;
|
||||
case Parameters::Unit::Parsec:
|
||||
_unit = Parsec;
|
||||
break;
|
||||
case Parameters::Unit::Kiloparsec:
|
||||
_unit = Kiloparsec;
|
||||
break;
|
||||
case Parameters::Unit::Megaparsec:
|
||||
_unit = Megaparsec;
|
||||
break;
|
||||
case Parameters::Unit::Gigaparsec:
|
||||
_unit = Gigaparsec;
|
||||
break;
|
||||
case Parameters::Unit::Gigalightyears:
|
||||
_unit = GigalightYears;
|
||||
break;
|
||||
}
|
||||
}
|
||||
else {
|
||||
@@ -370,60 +314,30 @@ RenderablePlanesCloud::RenderablePlanesCloud(const ghoul::Dictionary& dictionary
|
||||
_unit = Meter;
|
||||
}
|
||||
|
||||
if (dictionary.hasKey(ScaleFactorInfo.identifier)) {
|
||||
_scaleFactor = static_cast<float>(
|
||||
dictionary.value<double>(ScaleFactorInfo.identifier)
|
||||
);
|
||||
}
|
||||
_scaleFactor = p.scaleFactor.value_or(_scaleFactor);
|
||||
addProperty(_scaleFactor);
|
||||
_scaleFactor.onChange([&]() {
|
||||
_dataIsDirty = true;
|
||||
});
|
||||
_scaleFactor.onChange([&]() { _dataIsDirty = true; });
|
||||
|
||||
if (dictionary.hasKey(LabelFileInfo.identifier)) {
|
||||
_labelFile = absPath(dictionary.value<std::string>(LabelFileInfo.identifier));
|
||||
if (p.labelFile.has_value()) {
|
||||
_labelFile = absPath(*p.labelFile);
|
||||
_hasLabel = true;
|
||||
|
||||
if (dictionary.hasKey(TextColorInfo.identifier)) {
|
||||
_textColor = dictionary.value<glm::dvec3>(TextColorInfo.identifier);
|
||||
_hasLabel = true;
|
||||
}
|
||||
_textColor = p.textColor.value_or(_textColor);
|
||||
_textColor.setViewOption(properties::Property::ViewOptions::Color);
|
||||
addProperty(_textColor);
|
||||
_textColor.onChange([&]() { _textColorIsDirty = true; });
|
||||
|
||||
if (dictionary.hasKey(TextOpacityInfo.identifier)) {
|
||||
_textOpacity = static_cast<float>(
|
||||
dictionary.value<double>(TextOpacityInfo.identifier)
|
||||
);
|
||||
}
|
||||
_textOpacity = p.textOpacity.value_or(_textOpacity);
|
||||
addProperty(_textOpacity);
|
||||
|
||||
if (dictionary.hasKey(TextSizeInfo.identifier)) {
|
||||
_textSize = static_cast<float>(
|
||||
dictionary.value<double>(TextSizeInfo.identifier)
|
||||
);
|
||||
}
|
||||
_textSize = p.textSize.value_or(_textSize);
|
||||
addProperty(_textSize);
|
||||
|
||||
if (dictionary.hasKey(LabelMinSizeInfo.identifier)) {
|
||||
_textMinSize = static_cast<int>(
|
||||
dictionary.value<double>(LabelMinSizeInfo.identifier)
|
||||
);
|
||||
}
|
||||
|
||||
if (dictionary.hasKey(LabelMaxSizeInfo.identifier)) {
|
||||
_textMaxSize = static_cast<int>(
|
||||
dictionary.value<double>(LabelMaxSizeInfo.identifier)
|
||||
);
|
||||
}
|
||||
_textMinSize = p.textMinSize.value_or(_textMinSize);
|
||||
_textMaxSize = p.textMaxSize.value_or(_textMaxSize);
|
||||
}
|
||||
|
||||
if (dictionary.hasKey(TransformationMatrixInfo.identifier)) {
|
||||
_transformationMatrix = dictionary.value<glm::dmat4>(
|
||||
TransformationMatrixInfo.identifier
|
||||
);
|
||||
}
|
||||
_transformationMatrix = p.transformationMatrix.value_or(_transformationMatrix);
|
||||
|
||||
_blendMode.addOptions({
|
||||
{ BlendModeNormal, "Normal" },
|
||||
@@ -442,39 +356,33 @@ RenderablePlanesCloud::RenderablePlanesCloud(const ghoul::Dictionary& dictionary
|
||||
}
|
||||
});
|
||||
|
||||
if (dictionary.hasKey(BlendModeInfo.identifier)) {
|
||||
const std::string& v = dictionary.value<std::string>(BlendModeInfo.identifier);
|
||||
if (v == "Normal") {
|
||||
_blendMode = BlendModeNormal;
|
||||
}
|
||||
else if (v == "Additive") {
|
||||
_blendMode = BlendModeAdditive;
|
||||
if (p.blendMode.has_value()) {
|
||||
switch (*p.blendMode) {
|
||||
case Parameters::BlendMode::Normal:
|
||||
_blendMode = BlendModeNormal;
|
||||
break;
|
||||
case Parameters::BlendMode::Additive:
|
||||
_blendMode = BlendModeAdditive;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
_texturesPath = absPath(dictionary.value<std::string>(TexturePathInfo.identifier));
|
||||
_texturesPath = absPath(p.texturePath);
|
||||
|
||||
if (dictionary.hasKey(LuminosityInfo.identifier)) {
|
||||
_luminosityVar = dictionary.value<std::string>(LuminosityInfo.identifier);
|
||||
}
|
||||
_luminosityVar = p.luminosity.value_or(_luminosityVar);
|
||||
_sluminosity = p.scaleLuminosity.value_or(_sluminosity);
|
||||
|
||||
if (dictionary.hasKey(ScaleLuminosityInfo.identifier)) {
|
||||
_sluminosity = static_cast<float>(
|
||||
dictionary.value<double>(ScaleLuminosityInfo.identifier)
|
||||
);
|
||||
}
|
||||
|
||||
if (dictionary.hasKey(FadeInDistancesInfo.identifier)) {
|
||||
_fadeInDistance = dictionary.value<glm::dvec2>(FadeInDistancesInfo.identifier);
|
||||
if (p.fadeInDistances.has_value()) {
|
||||
_fadeInDistance = *p.fadeInDistances;
|
||||
_disableFadeInDistance = false;
|
||||
addProperty(_fadeInDistance);
|
||||
addProperty(_disableFadeInDistance);
|
||||
}
|
||||
|
||||
if (dictionary.hasKey(PlaneMinSizeInfo.identifier)) {
|
||||
_planeMinSize = static_cast<float>(
|
||||
dictionary.value<double>(PlaneMinSizeInfo.identifier)
|
||||
);
|
||||
_planeMinSize = p.planeMinSize.value_or(_planeMinSize);
|
||||
|
||||
if (p.planeMinSize.has_value()) {
|
||||
addProperty(_planeMinSize);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -44,6 +44,7 @@
|
||||
#include <locale>
|
||||
#include <cstdint>
|
||||
#include <string>
|
||||
#include <optional>
|
||||
|
||||
namespace {
|
||||
constexpr const char* _loggerCat = "RenderablePoints";
|
||||
@@ -53,17 +54,6 @@ namespace {
|
||||
"spriteTexture", "hasColorMap"
|
||||
};
|
||||
|
||||
constexpr const char* KeyFile = "File";
|
||||
constexpr const char* keyColor = "Color";
|
||||
constexpr const char* keyUnit = "Unit";
|
||||
constexpr const char* MeterUnit = "m";
|
||||
constexpr const char* KilometerUnit = "Km";
|
||||
constexpr const char* ParsecUnit = "pc";
|
||||
constexpr const char* KiloparsecUnit = "Kpc";
|
||||
constexpr const char* MegaparsecUnit = "Mpc";
|
||||
constexpr const char* GigaparsecUnit = "Gpc";
|
||||
constexpr const char* GigalightyearUnit = "Gly";
|
||||
|
||||
constexpr int8_t CurrentCacheVersion = 1;
|
||||
constexpr double PARSEC = 0.308567756E17;
|
||||
|
||||
@@ -91,58 +81,46 @@ namespace {
|
||||
"Color Map File",
|
||||
"The path to the color map file of the astronomical onject."
|
||||
};
|
||||
|
||||
struct [[codegen::Dictionary(RenderablePoints)]] Parameters {
|
||||
// The path to the SPECK file that contains information about the astronomical
|
||||
// object being rendered
|
||||
std::string file;
|
||||
|
||||
// Astronomical Object Color (r,g,b)
|
||||
glm::vec3 color;
|
||||
|
||||
enum class Unit {
|
||||
Meter [[codegen::key("m")]],
|
||||
Kilometer [[codegen::key("Km")]],
|
||||
Parsec [[codegen::key("pc")]],
|
||||
Kiloparsec [[codegen::key("Kpc")]],
|
||||
Megaparsec [[codegen::key("Mpc")]],
|
||||
Gigaparsec [[codegen::key("Gpc")]],
|
||||
Gigalightyears [[codegen::key("Gly")]]
|
||||
};
|
||||
std::optional<Unit> unit;
|
||||
|
||||
// [[codegen::verbatim(SpriteTextureInfo.description)]]
|
||||
std::optional<std::string> texture;
|
||||
|
||||
// [[codegen::verbatim(ScaleFactorInfo.description)]]
|
||||
std::optional<float> scaleFactor;
|
||||
|
||||
// [[codegen::verbatim(ColorMapInfo.description)]]
|
||||
std::optional<std::string> colorMap;
|
||||
};
|
||||
#include "renderablepoints_codegen.cpp"
|
||||
} // namespace
|
||||
|
||||
namespace openspace {
|
||||
|
||||
documentation::Documentation RenderablePoints::Documentation() {
|
||||
using namespace documentation;
|
||||
return {
|
||||
"RenderablePoints",
|
||||
"digitaluniverse_renderablepoints",
|
||||
{
|
||||
{
|
||||
"Type",
|
||||
new StringEqualVerifier("RenderablePoints"),
|
||||
Optional::No
|
||||
},
|
||||
{
|
||||
KeyFile,
|
||||
new StringVerifier,
|
||||
Optional::No,
|
||||
"The path to the SPECK file that contains information about the "
|
||||
"astronomical object being rendered."
|
||||
},
|
||||
{
|
||||
keyColor,
|
||||
new Vector3Verifier<double>,
|
||||
Optional::No,
|
||||
"Astronomical Object Color (r,g,b)."
|
||||
},
|
||||
{
|
||||
SpriteTextureInfo.identifier,
|
||||
new StringVerifier,
|
||||
Optional::Yes,
|
||||
SpriteTextureInfo.description
|
||||
},
|
||||
{
|
||||
ScaleFactorInfo.identifier,
|
||||
new DoubleVerifier,
|
||||
Optional::Yes,
|
||||
ScaleFactorInfo.description
|
||||
},
|
||||
{
|
||||
ColorMapInfo.identifier,
|
||||
new StringVerifier,
|
||||
Optional::Yes,
|
||||
ColorMapInfo.description
|
||||
},
|
||||
|
||||
}
|
||||
};
|
||||
documentation::Documentation doc = codegen::doc<Parameters>();
|
||||
doc.id = "digitaluniverse_renderablepoints";
|
||||
return doc;
|
||||
}
|
||||
|
||||
|
||||
RenderablePoints::RenderablePoints(const ghoul::Dictionary& dictionary)
|
||||
: Renderable(dictionary)
|
||||
, _scaleFactor(ScaleFactorInfo, 1.f, 0.f, 64.f)
|
||||
@@ -150,59 +128,52 @@ RenderablePoints::RenderablePoints(const ghoul::Dictionary& dictionary)
|
||||
ColorInfo,
|
||||
glm::vec3(1.f, 0.4f, 0.2f),
|
||||
glm::vec3(0.f, 0.f, 0.f),
|
||||
glm::vec3(1.0f, 1.0f, 1.0f)
|
||||
glm::vec3(1.f, 1.f, 1.f)
|
||||
)
|
||||
, _spriteTexturePath(SpriteTextureInfo)
|
||||
{
|
||||
documentation::testSpecificationAndThrow(
|
||||
Documentation(),
|
||||
dictionary,
|
||||
"RenderablePoints"
|
||||
);
|
||||
const Parameters p = codegen::bake<Parameters>(dictionary);
|
||||
|
||||
addProperty(_opacity);
|
||||
registerUpdateRenderBinFromOpacity();
|
||||
|
||||
_speckFile = absPath(dictionary.value<std::string>(KeyFile));
|
||||
_speckFile = absPath(p.file);
|
||||
|
||||
if (dictionary.hasKey(keyUnit)) {
|
||||
const std::string& unit = dictionary.value<std::string>(keyUnit);
|
||||
if (unit == MeterUnit) {
|
||||
_unit = Meter;
|
||||
}
|
||||
else if (unit == KilometerUnit) {
|
||||
_unit = Kilometer;
|
||||
}
|
||||
else if (unit == ParsecUnit) {
|
||||
_unit = Parsec;
|
||||
}
|
||||
else if (unit == KiloparsecUnit) {
|
||||
_unit = Kiloparsec;
|
||||
}
|
||||
else if (unit == MegaparsecUnit) {
|
||||
_unit = Megaparsec;
|
||||
}
|
||||
else if (unit == GigaparsecUnit) {
|
||||
_unit = Gigaparsec;
|
||||
}
|
||||
else if (unit == GigalightyearUnit) {
|
||||
_unit = GigalightYears;
|
||||
}
|
||||
else {
|
||||
LWARNING("No unit given for RenderablePoints. Using meters as units.");
|
||||
_unit = Meter;
|
||||
if (p.unit.has_value()) {
|
||||
switch (*p.unit) {
|
||||
case Parameters::Unit::Meter:
|
||||
_unit = Meter;
|
||||
break;
|
||||
case Parameters::Unit::Kilometer:
|
||||
_unit = Kilometer;
|
||||
break;
|
||||
case Parameters::Unit::Parsec:
|
||||
_unit = Parsec;
|
||||
break;
|
||||
case Parameters::Unit::Kiloparsec:
|
||||
_unit = Kiloparsec;
|
||||
break;
|
||||
case Parameters::Unit::Megaparsec:
|
||||
_unit = Megaparsec;
|
||||
break;
|
||||
case Parameters::Unit::Gigaparsec:
|
||||
_unit = Gigaparsec;
|
||||
break;
|
||||
case Parameters::Unit::Gigalightyears:
|
||||
_unit = GigalightYears;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (dictionary.hasKey(keyColor)) {
|
||||
_pointColor = dictionary.value<glm::dvec3>(keyColor);
|
||||
else {
|
||||
LWARNING("No unit given for RenderablePoints. Using meters as units.");
|
||||
_unit = Meter;
|
||||
}
|
||||
|
||||
_pointColor = p.color;
|
||||
addProperty(_pointColor);
|
||||
|
||||
if (dictionary.hasKey(SpriteTextureInfo.identifier)) {
|
||||
_spriteTexturePath = absPath(dictionary.value<std::string>(
|
||||
SpriteTextureInfo.identifier
|
||||
));
|
||||
if (p.texture.has_value()) {
|
||||
_spriteTexturePath = absPath(*p.texture);
|
||||
_spriteTextureFile = std::make_unique<ghoul::filesystem::File>(
|
||||
_spriteTexturePath
|
||||
);
|
||||
@@ -216,18 +187,12 @@ RenderablePoints::RenderablePoints(const ghoul::Dictionary& dictionary)
|
||||
_hasSpriteTexture = true;
|
||||
}
|
||||
|
||||
if (dictionary.hasKey(ColorMapInfo.identifier)) {
|
||||
_colorMapFile = absPath(dictionary.value<std::string>(
|
||||
ColorMapInfo.identifier
|
||||
));
|
||||
if (p.colorMap.has_value()) {
|
||||
_colorMapFile = absPath(*p.colorMap);
|
||||
_hasColorMapFile = true;
|
||||
}
|
||||
|
||||
if (dictionary.hasKey(ScaleFactorInfo.identifier)) {
|
||||
_scaleFactor = static_cast<float>(
|
||||
dictionary.value<double>(ScaleFactorInfo.identifier)
|
||||
);
|
||||
}
|
||||
_scaleFactor = p.scaleFactor.value_or(_scaleFactor);
|
||||
addProperty(_scaleFactor);
|
||||
}
|
||||
|
||||
|
||||
@@ -81,11 +81,6 @@ documentation::Documentation RenderableOrbitDisc::Documentation() {
|
||||
"Renderable Orbit Disc",
|
||||
"exoplanets_renderable_orbit_disc",
|
||||
{
|
||||
{
|
||||
"Type",
|
||||
new StringEqualVerifier("RenderableOrbitDisc"),
|
||||
Optional::No
|
||||
},
|
||||
{
|
||||
TextureInfo.identifier,
|
||||
new StringVerifier,
|
||||
|
||||
@@ -447,12 +447,6 @@ documentation::Documentation ExoplanetsDataPreparationTask::documentation() {
|
||||
"ExoplanetsDataPreparationTask",
|
||||
"exoplanets_data_preparation_task",
|
||||
{
|
||||
{
|
||||
"Type",
|
||||
new StringEqualVerifier("ExoplanetsDataPreparationTask"),
|
||||
Optional::No,
|
||||
""
|
||||
},
|
||||
{
|
||||
KeyInputDataFile,
|
||||
new StringAnnotationVerifier("A valid filepath"),
|
||||
|
||||
@@ -310,11 +310,6 @@ documentation::Documentation RenderableGaiaStars::Documentation() {
|
||||
"RenderableGaiaStars",
|
||||
"gaiamission_renderablegaiastars",
|
||||
{
|
||||
{
|
||||
"Type",
|
||||
new StringEqualVerifier("RenderableGaiaStars"),
|
||||
Optional::No
|
||||
},
|
||||
{
|
||||
FilePathInfo.identifier,
|
||||
new StringVerifier,
|
||||
|
||||
@@ -548,11 +548,6 @@ documentation::Documentation ConstructOctreeTask::Documentation() {
|
||||
"ConstructOctreeTask",
|
||||
"gaiamission_constructoctreefrombin",
|
||||
{
|
||||
{
|
||||
"Type",
|
||||
new StringEqualVerifier("ConstructOctreeTask"),
|
||||
Optional::No
|
||||
},
|
||||
{
|
||||
KeyInFileOrFolderPath,
|
||||
new StringVerifier,
|
||||
|
||||
@@ -327,11 +327,6 @@ documentation::Documentation ReadFitsTask::Documentation() {
|
||||
"ReadFitsFile",
|
||||
"gaiamission_fitsfiletorawdata",
|
||||
{
|
||||
{
|
||||
"Type",
|
||||
new StringEqualVerifier("ReadFitsTask"),
|
||||
Optional::No
|
||||
},
|
||||
{
|
||||
KeyInFileOrFolderPath,
|
||||
new StringVerifier,
|
||||
|
||||
@@ -98,11 +98,6 @@ documentation::Documentation ReadSpeckTask::Documentation() {
|
||||
"ReadSpeckTask",
|
||||
"gaiamission_speckfiletorawdata",
|
||||
{
|
||||
{
|
||||
"Type",
|
||||
new StringEqualVerifier("ReadSpeckTask"),
|
||||
Optional::No
|
||||
},
|
||||
{
|
||||
KeyInFilePath,
|
||||
new StringVerifier,
|
||||
|
||||
@@ -35,9 +35,10 @@
|
||||
#include <modules/globebrowsing/src/layermanager.h>
|
||||
#include <modules/globebrowsing/src/memoryawaretilecache.h>
|
||||
#include <modules/globebrowsing/src/tileprovider.h>
|
||||
#include <openspace/documentation/verifier.h>
|
||||
#include <openspace/engine/globalscallbacks.h>
|
||||
#include <openspace/interaction/navigationhandler.h>
|
||||
#include <openspace/interaction/orbitalnavigator.h>
|
||||
#include <openspace/engine/globalscallbacks.h>
|
||||
#include <openspace/scripting/lualibrary.h>
|
||||
#include <openspace/util/factorymanager.h>
|
||||
#include <ghoul/filesystem/filesystem.h>
|
||||
@@ -158,6 +159,29 @@ namespace {
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
struct [[codegen::Dictionary(GlobeBrowsingModule)]] Parameters {
|
||||
// [[codegen::verbatim(WMSCacheEnabledInfo.description)]]
|
||||
std::optional<bool> cacheEnabled [[codegen::key("WMSCacheEnabled")]];
|
||||
|
||||
// [[codegen::verbatim(OfflineModeInfo.description)]]
|
||||
std::optional<bool> offlineMode;
|
||||
|
||||
// [[codegen::verbatim(WMSCacheLocationInfo.description)]]
|
||||
std::optional<std::string> cacheLocation [[codegen::key("WMSCacheLocation")]];
|
||||
|
||||
// [[codegen::verbatim(WMSCacheSizeInfo.description)]]
|
||||
std::optional<int> wmsCacheSize [[codegen::key("WMSCacheSize")]];
|
||||
|
||||
// [[codegen::verbatim(TileCacheSizeInfo.description)]]
|
||||
std::optional<int> tileCacheSize;
|
||||
|
||||
// If you know what you are doing and you have WMS caching *disabled* but offline
|
||||
// mode *enabled*, you can set this value to 'true' to silence a warning that you
|
||||
// would otherwise get at startup
|
||||
std::optional<bool> noWarning;
|
||||
};
|
||||
#include "globebrowsingmodule_codegen.cpp"
|
||||
} // namespace
|
||||
|
||||
namespace openspace {
|
||||
@@ -180,30 +204,13 @@ GlobeBrowsingModule::GlobeBrowsingModule()
|
||||
void GlobeBrowsingModule::internalInitialize(const ghoul::Dictionary& dict) {
|
||||
using namespace globebrowsing;
|
||||
|
||||
if (dict.hasValue<bool>(WMSCacheEnabledInfo.identifier)) {
|
||||
_wmsCacheEnabled = dict.value<bool>(WMSCacheEnabledInfo.identifier);
|
||||
}
|
||||
if (dict.hasValue<bool>(OfflineModeInfo.identifier)) {
|
||||
_offlineMode = dict.value<bool>(OfflineModeInfo.identifier);
|
||||
}
|
||||
if (dict.hasValue<std::string>(WMSCacheLocationInfo.identifier)) {
|
||||
_wmsCacheLocation = dict.value<std::string>(WMSCacheLocationInfo.identifier);
|
||||
}
|
||||
if (dict.hasValue<double>(WMSCacheSizeInfo.identifier)) {
|
||||
_wmsCacheSizeMB = static_cast<int>(
|
||||
dict.value<double>(WMSCacheSizeInfo.identifier)
|
||||
);
|
||||
}
|
||||
if (dict.hasValue<double>(TileCacheSizeInfo.identifier)) {
|
||||
_tileCacheSizeMB = static_cast<int>(
|
||||
dict.value<double>(TileCacheSizeInfo.identifier)
|
||||
);
|
||||
}
|
||||
|
||||
// Sanity check
|
||||
const bool noWarning = dict.hasValue<bool>("NoWarning") ?
|
||||
dict.value<bool>("NoWarning") :
|
||||
false;
|
||||
const Parameters p = codegen::bake<Parameters>(dict);
|
||||
_wmsCacheEnabled = p.cacheEnabled.value_or(_wmsCacheEnabled);
|
||||
_offlineMode = p.offlineMode.value_or(_offlineMode);
|
||||
_wmsCacheLocation = p.cacheLocation.value_or(_wmsCacheLocation);
|
||||
_wmsCacheSizeMB = p.wmsCacheSize.value_or(_wmsCacheSizeMB);
|
||||
_tileCacheSizeMB = p.tileCacheSize.value_or(_tileCacheSizeMB);
|
||||
const bool noWarning = p.noWarning.value_or(false);
|
||||
|
||||
if (!_wmsCacheEnabled && _offlineMode && !noWarning) {
|
||||
LWARNINGC(
|
||||
|
||||
@@ -72,11 +72,6 @@ documentation::Documentation DashboardItemGlobeLocation::Documentation() {
|
||||
"DashboardItem Globe Location",
|
||||
"globebrowsing_dashboarditem_globelocation",
|
||||
{
|
||||
{
|
||||
"Type",
|
||||
new StringEqualVerifier("DashboardItemGlobeLocation"),
|
||||
Optional::No
|
||||
},
|
||||
{
|
||||
FontNameInfo.identifier,
|
||||
new StringVerifier,
|
||||
|
||||
@@ -85,11 +85,6 @@ documentation::Documentation GlobeTranslation::Documentation() {
|
||||
"Globe Translation",
|
||||
"space_translation_globetranslation",
|
||||
{
|
||||
{
|
||||
"Type",
|
||||
new StringEqualVerifier("GlobeTranslation"),
|
||||
Optional::No
|
||||
},
|
||||
{
|
||||
GlobeInfo.identifier,
|
||||
new StringAnnotationVerifier(
|
||||
|
||||
+118
-152
@@ -42,15 +42,7 @@ namespace {
|
||||
constexpr const char* KeyName = "Name";
|
||||
constexpr const char* KeyDesc = "Description";
|
||||
constexpr const char* KeyLayerGroupID = "LayerGroupID";
|
||||
constexpr const char* KeySettings = "Settings";
|
||||
constexpr const char* KeyAdjustment = "Adjustment";
|
||||
constexpr const char* KeyPadTiles = "PadTiles";
|
||||
|
||||
constexpr const char* KeyOpacity = "Opacity";
|
||||
constexpr const char* KeyGamma = "Gamma";
|
||||
constexpr const char* KeyMultiplier = "Multiplier";
|
||||
constexpr const char* KeyOffset = "Offset";
|
||||
|
||||
|
||||
constexpr openspace::properties::Property::PropertyInfo TypeInfo = {
|
||||
"Type",
|
||||
@@ -102,114 +94,94 @@ namespace {
|
||||
"example: Earth is a special place",
|
||||
openspace::properties::Property::Visibility::Hidden
|
||||
};
|
||||
|
||||
struct [[codegen::Dictionary(Layer), codegen::noexhaustive()]] Parameters {
|
||||
// The unique identifier for this layer. May not contain '.' or spaces
|
||||
std::string identifier;
|
||||
|
||||
// A human-readable name for the user interface. If this is omitted, the
|
||||
// identifier is used instead
|
||||
std::optional<std::string> name;
|
||||
|
||||
// A human-readable description of the layer to be used in informational texts
|
||||
// presented to the user
|
||||
std::optional<std::string> description;
|
||||
|
||||
// [[codegen::verbatim(ColorInfo.description)]]
|
||||
std::optional<glm::vec3> color;
|
||||
|
||||
// Specifies the type of layer that is to be added. If this value is not
|
||||
// specified, the layer is a DefaultTileLayer
|
||||
std::optional<std::string> type [[codegen::inlist("DefaultTileLayer",
|
||||
"SingleImageTileLayer", "SizeReferenceTileLayer", "TemporalTileLayer",
|
||||
"TileIndexTileLayer", "ByIndexTileLayer", "ByLevelTileLayer", "SolidColor")]];
|
||||
|
||||
// Determine whether the layer is enabled or not. If this value is not specified,
|
||||
// the layer is disabled
|
||||
std::optional<bool> enabled;
|
||||
|
||||
// Determines whether the downloaded tiles should have a padding added to the
|
||||
// borders
|
||||
std::optional<bool> padTiles;
|
||||
|
||||
struct Settings {
|
||||
// The opacity value of the layer
|
||||
std::optional<float> opacity [[codegen::inrange(0.0, 1.0)]];
|
||||
|
||||
// The gamma value that is applied to each pixel of the layer
|
||||
std::optional<float> gamma;
|
||||
|
||||
// The multiplicative factor that is applied to each pixel of the layer
|
||||
std::optional<float> multiplier;
|
||||
|
||||
// An additive offset that is applied to each pixel of the layer
|
||||
std::optional<float> offset;
|
||||
};
|
||||
// Specifies the render settings that should be applied to this layer
|
||||
std::optional<Settings> settings;
|
||||
|
||||
struct LayerAdjustment {
|
||||
enum class Type {
|
||||
None,
|
||||
ChromaKey,
|
||||
TransferFunction
|
||||
};
|
||||
|
||||
// Specifies the type of the adjustment that is applied
|
||||
std::optional<Type> type;
|
||||
|
||||
// Specifies the chroma key used when selecting 'ChromaKey' for the 'Type'
|
||||
std::optional<glm::dvec3> chromaKeyColor;
|
||||
|
||||
// Specifies the tolerance to match the color to the chroma key when the
|
||||
// 'ChromaKey' type is selected for the 'Type'
|
||||
std::optional<double> chromaKeyTolerance;
|
||||
};
|
||||
// Parameters that set individual adjustment parameters for this layer
|
||||
std::optional<LayerAdjustment> adjustment;
|
||||
|
||||
enum class BlendMode {
|
||||
Normal,
|
||||
Multiply,
|
||||
Add,
|
||||
Subtract,
|
||||
Color
|
||||
};
|
||||
// Sets the blend mode of this layer to determine how it interacts with other
|
||||
// layers on top of this
|
||||
std::optional<BlendMode> blendMode;
|
||||
|
||||
// If the primary layer creation fails, this layer is used as a fallback
|
||||
std::optional<std::monostate>
|
||||
fallback [[codegen::reference("globebrowsing_layer")]];
|
||||
};
|
||||
#include "layer_codegen.cpp"
|
||||
} // namespace
|
||||
|
||||
documentation::Documentation Layer::Documentation() {
|
||||
using namespace documentation;
|
||||
return {
|
||||
"Layer",
|
||||
"globebrowsing_layer",
|
||||
{
|
||||
{
|
||||
KeyIdentifier,
|
||||
new StringVerifier,
|
||||
Optional::No,
|
||||
"The unique identifier for this layer. May not contain '.' or spaces."
|
||||
},
|
||||
{
|
||||
KeyName,
|
||||
new StringVerifier,
|
||||
Optional::Yes,
|
||||
"A human-readable name for the user interface. If this is omitted, the "
|
||||
"identifier is used instead."
|
||||
},
|
||||
{
|
||||
KeyDesc,
|
||||
new StringVerifier,
|
||||
Optional::Yes,
|
||||
"A human-readable description of the layer to be used in informational "
|
||||
"texts presented to the user."
|
||||
},
|
||||
{
|
||||
"Type",
|
||||
new StringInListVerifier({
|
||||
"DefaultTileLayer", "SingleImageTileLayer", "SizeReferenceTileLayer",
|
||||
"TemporalTileLayer", "TileIndexTileLayer", "ByIndexTileLayer",
|
||||
"ByLevelTileLayer", "SolidColor"
|
||||
}),
|
||||
Optional::Yes,
|
||||
"Specifies the type of layer that is to be added. If this value is not "
|
||||
"specified, the layer is a DefaultTileLayer."
|
||||
},
|
||||
{
|
||||
EnabledInfo.identifier,
|
||||
new BoolVerifier,
|
||||
Optional::Yes,
|
||||
"Determine whether the layer is enabled or not. If this value is not "
|
||||
"specified, the layer is disabled."
|
||||
},
|
||||
{
|
||||
KeyPadTiles,
|
||||
new BoolVerifier,
|
||||
Optional::Yes,
|
||||
"Determines whether the downloaded tiles should have a padding added to "
|
||||
"the borders."
|
||||
},
|
||||
{
|
||||
KeySettings,
|
||||
new TableVerifier({
|
||||
{
|
||||
KeyOpacity,
|
||||
new DoubleInRangeVerifier(0.0, 1.0),
|
||||
Optional::Yes,
|
||||
"The opacity value of the layer."
|
||||
},
|
||||
{
|
||||
KeyGamma,
|
||||
new DoubleVerifier,
|
||||
Optional::Yes,
|
||||
"The gamma value that is applied to each pixel of the layer."
|
||||
},
|
||||
{
|
||||
KeyMultiplier,
|
||||
new DoubleVerifier,
|
||||
Optional::Yes,
|
||||
"The multiplicative factor that is applied to each pixel of the "
|
||||
"layer."
|
||||
},
|
||||
{
|
||||
KeyOffset,
|
||||
new DoubleVerifier,
|
||||
Optional::Yes,
|
||||
"An additive offset that is applied to each pixel of the layer."
|
||||
}
|
||||
}),
|
||||
Optional::Yes,
|
||||
"Specifies the render settings that should be applied to this layer."
|
||||
},
|
||||
{
|
||||
KeyAdjustment,
|
||||
new ReferencingVerifier("globebrowsing_layeradjustment"),
|
||||
Optional::Yes,
|
||||
""
|
||||
},
|
||||
{
|
||||
BlendModeInfo.identifier,
|
||||
new StringInListVerifier({
|
||||
"Normal", "Multiply", "Add", "Subtract", "Color"
|
||||
}),
|
||||
Optional::Yes,
|
||||
"Sets the blend mode of this layer to determine how it interacts with "
|
||||
"other layers on top of this."
|
||||
},
|
||||
{
|
||||
"Fallback",
|
||||
new ReferencingVerifier("globebrowsing_layer"),
|
||||
Optional::Yes,
|
||||
"If the primary layer creation fails, this layer is used as a fallback"
|
||||
}
|
||||
}
|
||||
};
|
||||
documentation::Documentation doc = codegen::doc<Parameters>();
|
||||
doc.id = "globebrowsing_layer";
|
||||
return doc;
|
||||
}
|
||||
|
||||
Layer::Layer(layergroupid::GroupID id, const ghoul::Dictionary& layerDict,
|
||||
@@ -230,59 +202,40 @@ Layer::Layer(layergroupid::GroupID id, const ghoul::Dictionary& layerDict,
|
||||
, _layerGroupId(id)
|
||||
|
||||
{
|
||||
documentation::testSpecificationAndThrow(Documentation(), layerDict, "Layer");
|
||||
const Parameters p = codegen::bake<Parameters>(layerDict);
|
||||
|
||||
layergroupid::TypeID typeID;
|
||||
if (layerDict.hasValue<std::string>("Type")) {
|
||||
const std::string& typeString = layerDict.value<std::string>("Type");
|
||||
typeID = ghoul::from_string<layergroupid::TypeID>(typeString);
|
||||
if (p.type.has_value()) {
|
||||
typeID = ghoul::from_string<layergroupid::TypeID>(*p.type);
|
||||
if (typeID == layergroupid::TypeID::Unknown) {
|
||||
throw ghoul::RuntimeError("Unknown layer type!");
|
||||
}
|
||||
}
|
||||
else {
|
||||
typeID = layergroupid::TypeID::DefaultTileLayer;
|
||||
}
|
||||
if (typeID == layergroupid::TypeID::Unknown) {
|
||||
throw ghoul::RuntimeError("Unknown layer type!");
|
||||
}
|
||||
|
||||
initializeBasedOnType(typeID, layerDict);
|
||||
|
||||
if (layerDict.hasValue<bool>(EnabledInfo.identifier)) {
|
||||
_enabled = layerDict.value<bool>(EnabledInfo.identifier);
|
||||
}
|
||||
_enabled = p.enabled.value_or(_enabled);
|
||||
|
||||
if (layerDict.hasKey(KeyDesc)) {
|
||||
if (p.description.has_value()) {
|
||||
_guiDescription = description();
|
||||
addProperty(_guiDescription);
|
||||
}
|
||||
|
||||
bool padTiles = true;
|
||||
if (layerDict.hasValue<bool>(KeyPadTiles)) {
|
||||
padTiles = layerDict.value<bool>(KeyPadTiles);
|
||||
}
|
||||
const bool padTiles = p.padTiles.value_or(true);
|
||||
|
||||
TileTextureInitData initData = tileTextureInitData(_layerGroupId, padTiles);
|
||||
_padTilePixelStartOffset = initData.tilePixelStartOffset;
|
||||
_padTilePixelSizeDifference = initData.tilePixelSizeDifference;
|
||||
|
||||
if (layerDict.hasValue<ghoul::Dictionary>(KeySettings)) {
|
||||
ghoul::Dictionary dict = layerDict.value<ghoul::Dictionary>(KeySettings);
|
||||
if (dict.hasValue<double>(KeyOpacity)) {
|
||||
_renderSettings.opacity = static_cast<float>(dict.value<double>(KeyOpacity));
|
||||
}
|
||||
|
||||
if (dict.hasValue<double>(KeyGamma)) {
|
||||
_renderSettings.gamma = static_cast<float>(dict.value<double>(KeyGamma));
|
||||
}
|
||||
|
||||
if (dict.hasValue<double>(KeyMultiplier)) {
|
||||
_renderSettings.multiplier = static_cast<float>(
|
||||
dict.value<double>(KeyMultiplier)
|
||||
);
|
||||
}
|
||||
|
||||
if (dict.hasValue<double>(KeyOffset)) {
|
||||
_renderSettings.offset = static_cast<float>(dict.value<double>(KeyOffset));
|
||||
}
|
||||
if (p.settings.has_value()) {
|
||||
_renderSettings.opacity = p.settings->opacity.value_or(_renderSettings.opacity);
|
||||
_renderSettings.gamma = p.settings->gamma.value_or(_renderSettings.gamma);
|
||||
_renderSettings.multiplier =
|
||||
p.settings->multiplier.value_or(_renderSettings.multiplier);
|
||||
_renderSettings.offset = p.settings->offset.value_or(_renderSettings.offset);
|
||||
}
|
||||
if (layerDict.hasValue<ghoul::Dictionary>(KeyAdjustment)) {
|
||||
_layerAdjustment.setValuesFromDictionary(
|
||||
@@ -302,11 +255,24 @@ Layer::Layer(layergroupid::GroupID id, const ghoul::Dictionary& layerDict,
|
||||
}
|
||||
|
||||
// Initialize blend mode
|
||||
if (layerDict.hasValue<std::string>(BlendModeInfo.identifier)) {
|
||||
using namespace layergroupid;
|
||||
std::string blendMode = layerDict.value<std::string>(BlendModeInfo.identifier);
|
||||
BlendModeID blendModeID = ghoul::from_string<BlendModeID>(blendMode);
|
||||
_blendModeOption = static_cast<int>(blendModeID);
|
||||
if (p.blendMode.has_value()) {
|
||||
switch (*p.blendMode) {
|
||||
case Parameters::BlendMode::Normal:
|
||||
_blendModeOption = static_cast<int>(layergroupid::BlendModeID::Normal);
|
||||
break;
|
||||
case Parameters::BlendMode::Multiply:
|
||||
_blendModeOption = static_cast<int>(layergroupid::BlendModeID::Multiply);
|
||||
break;
|
||||
case Parameters::BlendMode::Add:
|
||||
_blendModeOption = static_cast<int>(layergroupid::BlendModeID::Add);
|
||||
break;
|
||||
case Parameters::BlendMode::Subtract:
|
||||
_blendModeOption = static_cast<int>(layergroupid::BlendModeID::Subtract);
|
||||
break;
|
||||
case Parameters::BlendMode::Color:
|
||||
_blendModeOption = static_cast<int>(layergroupid::BlendModeID::Color);
|
||||
break;
|
||||
}
|
||||
}
|
||||
else {
|
||||
_blendModeOption = static_cast<int>(layergroupid::BlendModeID::Normal);
|
||||
|
||||
@@ -82,8 +82,6 @@ namespace {
|
||||
constexpr const char* KeyRadii = "Radii";
|
||||
constexpr const char* KeyLayers = "Layers";
|
||||
constexpr const char* KeyShadowGroup = "ShadowGroup";
|
||||
constexpr const char* KeyShadowSource = "Source";
|
||||
constexpr const char* KeyShadowCaster = "Caster";
|
||||
constexpr const char* KeyLabels = "Labels";
|
||||
|
||||
const openspace::globebrowsing::AABB3 CullingFrustum{
|
||||
@@ -468,12 +466,6 @@ documentation::Documentation RenderableGlobe::Documentation() {
|
||||
"RenderableGlobe",
|
||||
"globebrowsing_renderableglobe",
|
||||
{
|
||||
{
|
||||
"Type",
|
||||
new StringEqualVerifier("RenderableGlobe"),
|
||||
Optional::No,
|
||||
""
|
||||
},
|
||||
{
|
||||
KeyRadii,
|
||||
new OrVerifier({ new DoubleVector3Verifier, new DoubleVerifier }),
|
||||
|
||||
Submodule modules/kameleon/ext/kameleon updated: 8a5e966659...606edb945b
@@ -152,12 +152,6 @@ documentation::Documentation KameleonDocumentationTask::documentation() {
|
||||
"KameleonDocumentationTask",
|
||||
"kameleon_documentation_task",
|
||||
{
|
||||
{
|
||||
"Type",
|
||||
new StringEqualVerifier("KameleonDocumentationTask"),
|
||||
Optional::No,
|
||||
"The type of this task"
|
||||
},
|
||||
{
|
||||
KeyInput,
|
||||
new StringAnnotationVerifier("A file path to a cdf file"),
|
||||
|
||||
@@ -75,12 +75,6 @@ documentation::Documentation KameleonMetadataToJsonTask::documentation() {
|
||||
"KameleonMetadataToJsonTask",
|
||||
"kameleon_metadata_to_json_task",
|
||||
{
|
||||
{
|
||||
"Type",
|
||||
new StringEqualVerifier("KameleonMetadataToJsonTask"),
|
||||
Optional::No,
|
||||
"The type of this task"
|
||||
},
|
||||
{
|
||||
KeyInput,
|
||||
new StringAnnotationVerifier("A file path to a cdf file"),
|
||||
|
||||
@@ -56,12 +56,6 @@ documentation::Documentation KameleonVolumeToRawTask::documentation() {
|
||||
"KameleonVolumeToRawTask",
|
||||
"kameleon_metadata_to_json_task",
|
||||
{
|
||||
{
|
||||
"Type",
|
||||
new StringEqualVerifier("KameleonVolumeToRawTask"),
|
||||
Optional::No,
|
||||
"The type of this task",
|
||||
},
|
||||
{
|
||||
KeyInput,
|
||||
new StringAnnotationVerifier("A file path to a cdf file"),
|
||||
|
||||
@@ -30,40 +30,29 @@
|
||||
#include <ghoul/misc/templatefactory.h>
|
||||
|
||||
namespace {
|
||||
constexpr const char* KeyType = "Type";
|
||||
struct [[codegen::Dictionary(PlanetGeometry)]] Parameters {
|
||||
// The type of the PlanetGeometry that will can be constructed
|
||||
std::string type;
|
||||
};
|
||||
#include "planetgeometry_codegen.cpp"
|
||||
} // namespace
|
||||
|
||||
namespace openspace::planetgeometry {
|
||||
|
||||
documentation::Documentation PlanetGeometry::Documentation() {
|
||||
using namespace documentation;
|
||||
return {
|
||||
"Planet Geometry",
|
||||
"space_geometry_planet",
|
||||
{
|
||||
{
|
||||
KeyType,
|
||||
new StringVerifier,
|
||||
Optional::No,
|
||||
"The type of the PlanetGeometry that will can be constructed."
|
||||
}
|
||||
}
|
||||
};
|
||||
documentation::Documentation doc = codegen::doc<Parameters>();
|
||||
doc.id = "space_geometry_planet";
|
||||
return doc;
|
||||
}
|
||||
|
||||
std::unique_ptr<PlanetGeometry> PlanetGeometry::createFromDictionary(
|
||||
const ghoul::Dictionary& dictionary)
|
||||
{
|
||||
documentation::testSpecificationAndThrow(
|
||||
Documentation(),
|
||||
dictionary,
|
||||
"PlanetGeometry"
|
||||
);
|
||||
const Parameters p = codegen::bake<Parameters>(dictionary);
|
||||
|
||||
std::string geometryType = dictionary.value<std::string>(KeyType);
|
||||
auto factory = FactoryManager::ref().factory<PlanetGeometry>();
|
||||
|
||||
PlanetGeometry* result = factory->create(geometryType, dictionary);
|
||||
PlanetGeometry* result = factory->create(p.type, dictionary);
|
||||
return std::unique_ptr<PlanetGeometry>(result);
|
||||
}
|
||||
|
||||
|
||||
@@ -33,6 +33,7 @@
|
||||
#include <ghoul/logging/logmanager.h>
|
||||
#include <ghoul/opengl/programobject.h>
|
||||
#include <fstream>
|
||||
#include <optional>
|
||||
#include "SpiceUsr.h"
|
||||
|
||||
namespace {
|
||||
@@ -74,51 +75,33 @@ namespace {
|
||||
"Constellation Selection",
|
||||
"The constellations that are selected are displayed on the celestial sphere."
|
||||
};
|
||||
|
||||
struct [[codegen::Dictionary(RenderableConstellationBounds)]] Parameters {
|
||||
// [[codegen::verbatim(VertexInfo.description)]]
|
||||
std::string file;
|
||||
|
||||
// [[codegen::verbatim(ConstellationInfo.description)]]
|
||||
std::optional<std::string> constellationFile;
|
||||
|
||||
// [[codegen::verbatim(ColorInfo.description)]]
|
||||
std::optional<glm::vec3> color;
|
||||
|
||||
// [[codegen::verbatim(LineWidthInfo.description)]]
|
||||
std::optional<float> lineWidth;
|
||||
|
||||
// [[codegen::verbatim(SelectionInfo.description)]]
|
||||
std::optional<std::vector<std::string>> constellationSelection;
|
||||
};
|
||||
#include "renderableconstellationbounds_codegen.cpp"
|
||||
} // namespace
|
||||
|
||||
namespace openspace {
|
||||
|
||||
documentation::Documentation RenderableConstellationBounds::Documentation() {
|
||||
using namespace documentation;
|
||||
return {
|
||||
"RenderableConstellationBounds",
|
||||
"space_renderable_constellationbounds",
|
||||
{
|
||||
{
|
||||
VertexInfo.identifier,
|
||||
new StringVerifier,
|
||||
Optional::No,
|
||||
VertexInfo.description
|
||||
},
|
||||
{
|
||||
ConstellationInfo.identifier,
|
||||
new StringVerifier,
|
||||
Optional::Yes,
|
||||
"Specifies the file that contains the mapping between constellation "
|
||||
"abbreviations and full name of the constellation. If the file is "
|
||||
"omitted, the abbreviations are used as the full names."
|
||||
},
|
||||
{
|
||||
ColorInfo.identifier,
|
||||
new DoubleVector3Verifier,
|
||||
Optional::Yes,
|
||||
ColorInfo.description
|
||||
},
|
||||
{
|
||||
LineWidthInfo.identifier,
|
||||
new DoubleVerifier,
|
||||
Optional::Yes,
|
||||
LineWidthInfo.description
|
||||
},
|
||||
{
|
||||
SelectionInfo.identifier,
|
||||
new StringListVerifier,
|
||||
Optional::Yes,
|
||||
SelectionInfo.description
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
documentation::Documentation doc = codegen::doc<Parameters>();
|
||||
doc.id = "space_renderable_constellationbounds";
|
||||
return doc;
|
||||
} // namespace
|
||||
|
||||
|
||||
RenderableConstellationBounds::RenderableConstellationBounds(
|
||||
@@ -130,53 +113,33 @@ RenderableConstellationBounds::RenderableConstellationBounds(
|
||||
, _lineWidth(LineWidthInfo, 2.f, 1.f, 32.f)
|
||||
, _constellationSelection(SelectionInfo)
|
||||
{
|
||||
documentation::testSpecificationAndThrow(
|
||||
Documentation(),
|
||||
dictionary,
|
||||
"RenderableConstellationBounds"
|
||||
);
|
||||
const Parameters p = codegen::bake<Parameters>(dictionary);
|
||||
|
||||
_vertexFilename.onChange([&](){ loadVertexFile(); });
|
||||
addProperty(_vertexFilename);
|
||||
_vertexFilename = dictionary.value<std::string>(VertexInfo.identifier);
|
||||
_vertexFilename = p.file;
|
||||
|
||||
_constellationFilename.onChange([&](){ loadConstellationFile(); });
|
||||
_constellationFilename = p.constellationFile.value_or(_constellationFilename);
|
||||
addProperty(_constellationFilename);
|
||||
if (dictionary.hasKey(ConstellationInfo.identifier)) {
|
||||
_constellationFilename = dictionary.value<std::string>(
|
||||
ConstellationInfo.identifier
|
||||
);
|
||||
}
|
||||
|
||||
_color.setViewOption(properties::Property::ViewOptions::Color);
|
||||
_color = p.color.value_or(_color);
|
||||
addProperty(_color);
|
||||
if (dictionary.hasKey(ColorInfo.identifier)) {
|
||||
_color = glm::vec3(dictionary.value<glm::dvec3>(ColorInfo.identifier));
|
||||
}
|
||||
|
||||
_lineWidth = p.lineWidth.value_or(_lineWidth);
|
||||
addProperty(_lineWidth);
|
||||
if (dictionary.hasKey(LineWidthInfo.identifier)) {
|
||||
_lineWidth = static_cast<float>(
|
||||
dictionary.value<double>(LineWidthInfo.identifier)
|
||||
);
|
||||
}
|
||||
|
||||
fillSelectionProperty();
|
||||
_constellationSelection.onChange([this]() { selectionPropertyHasChanged(); });
|
||||
addProperty(_constellationSelection);
|
||||
|
||||
if (dictionary.hasKey(SelectionInfo.identifier)) {
|
||||
const ghoul::Dictionary& selection = dictionary.value<ghoul::Dictionary>(
|
||||
SelectionInfo.identifier
|
||||
);
|
||||
|
||||
if (p.constellationSelection.has_value()) {
|
||||
std::vector<properties::SelectionProperty::Option> options =
|
||||
_constellationSelection.options();
|
||||
|
||||
std::vector<int> selectedIndices;
|
||||
|
||||
for (size_t i = 1; i <= selection.size(); ++i) {
|
||||
const std::string& s = selection.value<std::string>(std::to_string(i));
|
||||
|
||||
for (const std::string& s : *p.constellationSelection) {
|
||||
const auto it = std::find_if(
|
||||
options.begin(),
|
||||
options.end(),
|
||||
|
||||
@@ -36,6 +36,7 @@
|
||||
#include <ghoul/opengl/programobject.h>
|
||||
#include <ghoul/opengl/texture.h>
|
||||
#include <ghoul/opengl/textureunit.h>
|
||||
#include <optional>
|
||||
|
||||
namespace {
|
||||
constexpr const std::array<const char*, 6> UniformNames = {
|
||||
@@ -79,53 +80,32 @@ namespace {
|
||||
"This value affects the filtering out of part of the rings depending on the "
|
||||
"color values of the texture. The higher value, the more rings are filtered out."
|
||||
};
|
||||
|
||||
struct [[codegen::Dictionary(RenderableRings)]] Parameters {
|
||||
// [[codegen::verbatim(TextureInfo.description)]]
|
||||
std::string texture;
|
||||
|
||||
// [[codegen::verbatim(SizeInfo.description)]]
|
||||
float size;
|
||||
|
||||
// [[codegen::verbatim(OffsetInfo.description)]]
|
||||
std::optional<glm::vec2> offset;
|
||||
|
||||
// [[codegen::verbatim(NightFactorInfo.description)]]
|
||||
std::optional<float> nightFactor;
|
||||
|
||||
// [[codegen::verbatim(ColorFilterInfo.description)]]
|
||||
std::optional<float> colorFilter;
|
||||
};
|
||||
#include "renderablerings_codegen.cpp"
|
||||
} // namespace
|
||||
|
||||
namespace openspace {
|
||||
|
||||
documentation::Documentation RenderableRings::Documentation() {
|
||||
using namespace documentation;
|
||||
return {
|
||||
"Renderable Rings",
|
||||
"space_renderable_rings",
|
||||
{
|
||||
{
|
||||
"Type",
|
||||
new StringEqualVerifier("RenderableRings"),
|
||||
Optional::No
|
||||
},
|
||||
{
|
||||
TextureInfo.identifier,
|
||||
new StringVerifier,
|
||||
Optional::No,
|
||||
TextureInfo.description
|
||||
},
|
||||
{
|
||||
SizeInfo.identifier,
|
||||
new DoubleVerifier,
|
||||
Optional::No,
|
||||
SizeInfo.description
|
||||
},
|
||||
{
|
||||
OffsetInfo.identifier,
|
||||
new DoubleVector2Verifier,
|
||||
Optional::Yes,
|
||||
OffsetInfo.description
|
||||
},
|
||||
{
|
||||
NightFactorInfo.identifier,
|
||||
new DoubleVerifier,
|
||||
Optional::Yes,
|
||||
NightFactorInfo.description
|
||||
},
|
||||
{
|
||||
ColorFilterInfo.identifier,
|
||||
new DoubleVerifier,
|
||||
Optional::Yes,
|
||||
ColorFilterInfo.description
|
||||
}
|
||||
}
|
||||
};
|
||||
documentation::Documentation doc = codegen::doc<Parameters>();
|
||||
doc.id = "space_renderable_rings";
|
||||
return doc;
|
||||
}
|
||||
|
||||
RenderableRings::RenderableRings(const ghoul::Dictionary& dictionary)
|
||||
@@ -138,23 +118,17 @@ RenderableRings::RenderableRings(const ghoul::Dictionary& dictionary)
|
||||
{
|
||||
using ghoul::filesystem::File;
|
||||
|
||||
documentation::testSpecificationAndThrow(
|
||||
Documentation(),
|
||||
dictionary,
|
||||
"RenderableRings"
|
||||
);
|
||||
const Parameters p = codegen::bake<Parameters>(dictionary);
|
||||
|
||||
_size = static_cast<float>(dictionary.value<double>(SizeInfo.identifier));
|
||||
_size = p.size;
|
||||
setBoundingSphere(_size);
|
||||
_size.onChange([&]() { _planeIsDirty = true; });
|
||||
addProperty(_size);
|
||||
|
||||
_texturePath = absPath(dictionary.value<std::string>(TextureInfo.identifier));
|
||||
_texturePath = absPath(p.texture);
|
||||
_textureFile = std::make_unique<File>(_texturePath);
|
||||
|
||||
if (dictionary.hasValue<glm::dvec2>(OffsetInfo.identifier)) {
|
||||
_offset = dictionary.value<glm::dvec2>(OffsetInfo.identifier);
|
||||
}
|
||||
_offset = p.offset.value_or(_offset);
|
||||
addProperty(_offset);
|
||||
|
||||
_texturePath.onChange([&]() { loadTexture(); });
|
||||
@@ -162,18 +136,10 @@ RenderableRings::RenderableRings(const ghoul::Dictionary& dictionary)
|
||||
|
||||
_textureFile->setCallback([&](const File&) { _textureIsDirty = true; });
|
||||
|
||||
if (dictionary.hasValue<double>(NightFactorInfo.identifier)) {
|
||||
_nightFactor = static_cast<float>(
|
||||
dictionary.value<double>(NightFactorInfo.identifier)
|
||||
);
|
||||
}
|
||||
_nightFactor = p.nightFactor.value_or(_nightFactor);
|
||||
addProperty(_nightFactor);
|
||||
|
||||
if (dictionary.hasValue<double>(ColorFilterInfo.identifier)) {
|
||||
_colorFilter = static_cast<float>(
|
||||
dictionary.value<double>(ColorFilterInfo.identifier)
|
||||
);
|
||||
}
|
||||
_colorFilter = p.colorFilter.value_or(_colorFilter);
|
||||
addProperty(_colorFilter);
|
||||
}
|
||||
|
||||
|
||||
@@ -74,53 +74,42 @@ namespace {
|
||||
"Trail Fade",
|
||||
"This value determines how fast the trail fades and is an appearance property. "
|
||||
};
|
||||
|
||||
struct [[codegen::Dictionary(RenderableSatellites)]] Parameters {
|
||||
// [[codegen::verbatim(SegmentsInfo.description)]]
|
||||
double segments;
|
||||
|
||||
// [[codegen::verbatim(PathInfo.description)]]
|
||||
std::string path;
|
||||
|
||||
// [[codegen::verbatim(LineWidthInfo.description)]]
|
||||
std::optional<double> lineWidth;
|
||||
|
||||
// [[codegen::verbatim(LineColorInfo.description)]]
|
||||
glm::dvec3 color;
|
||||
|
||||
// [[codegen::verbatim(TrailFadeInfo.description)]]
|
||||
std::optional<double> trailFade;
|
||||
};
|
||||
#include "renderablesatellites_codegen.cpp"
|
||||
}
|
||||
|
||||
namespace openspace {
|
||||
|
||||
documentation::Documentation RenderableSatellites::Documentation() {
|
||||
using namespace documentation;
|
||||
return {
|
||||
"RenderableSatellites",
|
||||
"space_renderable_satellites",
|
||||
{
|
||||
{
|
||||
SegmentsInfo.identifier,
|
||||
new DoubleVerifier,
|
||||
Optional::No,
|
||||
SegmentsInfo.description
|
||||
},
|
||||
{
|
||||
PathInfo.identifier,
|
||||
new StringVerifier,
|
||||
Optional::No,
|
||||
PathInfo.description
|
||||
},
|
||||
{
|
||||
LineWidthInfo.identifier,
|
||||
new DoubleVerifier,
|
||||
Optional::Yes,
|
||||
LineWidthInfo.description
|
||||
},
|
||||
{
|
||||
LineColorInfo.identifier,
|
||||
new DoubleVector3Verifier,
|
||||
Optional::No,
|
||||
LineColorInfo.description
|
||||
},
|
||||
{
|
||||
TrailFadeInfo.identifier,
|
||||
new DoubleVerifier,
|
||||
Optional::Yes,
|
||||
TrailFadeInfo.description
|
||||
}
|
||||
}
|
||||
};
|
||||
documentation::Documentation doc = codegen::doc<Parameters>();
|
||||
doc.id = "space_renderable_satellites";
|
||||
return doc;
|
||||
}
|
||||
|
||||
RenderableSatellites::RenderableSatellites(const ghoul::Dictionary& dictionary)
|
||||
: RenderableOrbitalKepler(dictionary)
|
||||
{}
|
||||
{
|
||||
// Commented out right now as its not super clear how it works with inheritance. We'd
|
||||
// probably want a codegen::check function that only does the checking without
|
||||
// actually creating a Parameter objects
|
||||
// codegen::bake<Parameters>(dictionary);
|
||||
}
|
||||
|
||||
void RenderableSatellites::readDataFile(const std::string& filename) {
|
||||
if (!FileSys.fileExists(filename)) {
|
||||
|
||||
@@ -104,59 +104,42 @@ namespace {
|
||||
name.erase(name.find_last_not_of(trimChars) + 1);
|
||||
return name;
|
||||
}
|
||||
|
||||
struct [[codegen::Dictionary(RenderableSmallBody)]] Parameters {
|
||||
// [[codegen::verbatim(SegmentQualityInfo.description)]]
|
||||
double segmentQuality;
|
||||
|
||||
// [[codegen::verbatim(UpperLimitInfo.description)]]
|
||||
std::optional<int> upperLimit;
|
||||
|
||||
// [[codegen::verbatim(PathInfo.description)]]
|
||||
std::string path;
|
||||
|
||||
// [[codegen::verbatim(LineWidthInfo.description)]]
|
||||
std::optional<double> lineWidth;
|
||||
|
||||
// [[codegen::verbatim(LineColorInfo.description)]]
|
||||
glm::dvec3 color;
|
||||
|
||||
// [[codegen::verbatim(TrailFadeInfo.description)]]
|
||||
std::optional<double> trailFade;
|
||||
};
|
||||
#include "renderablesmallbody_codegen.cpp"
|
||||
} // namespace
|
||||
|
||||
namespace openspace {
|
||||
|
||||
documentation::Documentation RenderableSmallBody::Documentation() {
|
||||
using namespace documentation;
|
||||
return {
|
||||
"RenderableSmallBody",
|
||||
"space_renderable_small_body",
|
||||
{
|
||||
{
|
||||
SegmentQualityInfo.identifier,
|
||||
new DoubleVerifier,
|
||||
Optional::No,
|
||||
SegmentQualityInfo.description
|
||||
},
|
||||
{
|
||||
UpperLimitInfo.identifier,
|
||||
new IntVerifier,
|
||||
Optional::Yes,
|
||||
UpperLimitInfo.description
|
||||
},
|
||||
{
|
||||
PathInfo.identifier,
|
||||
new StringVerifier,
|
||||
Optional::No,
|
||||
PathInfo.description
|
||||
},
|
||||
{
|
||||
LineWidthInfo.identifier,
|
||||
new DoubleVerifier,
|
||||
Optional::Yes,
|
||||
LineWidthInfo.description
|
||||
},
|
||||
{
|
||||
LineColorInfo.identifier,
|
||||
new DoubleVector3Verifier,
|
||||
Optional::No,
|
||||
LineColorInfo.description
|
||||
},
|
||||
{
|
||||
TrailFadeInfo.identifier,
|
||||
new DoubleVerifier,
|
||||
Optional::Yes,
|
||||
TrailFadeInfo.description
|
||||
}
|
||||
}
|
||||
};
|
||||
documentation::Documentation doc = codegen::doc<Parameters>();
|
||||
doc.id = "space_renderable_small_body";
|
||||
return doc;
|
||||
}
|
||||
|
||||
RenderableSmallBody::RenderableSmallBody(const ghoul::Dictionary& dictionary)
|
||||
: RenderableOrbitalKepler(dictionary)
|
||||
{
|
||||
codegen::bake<Parameters>(dictionary);
|
||||
|
||||
_upperLimitCallbackHandle = _upperLimit.onChange(_reinitializeTrailBuffers);
|
||||
addProperty(_upperLimit);
|
||||
}
|
||||
|
||||
@@ -51,10 +51,6 @@
|
||||
namespace {
|
||||
constexpr const char* _loggerCat = "RenderableStars";
|
||||
|
||||
constexpr const char* KeyFile = "File";
|
||||
constexpr const char* KeyStaticFilterValue = "StaticFilter";
|
||||
constexpr const char* KeyStaticFilterReplacement = "StaticFilterReplacement";
|
||||
|
||||
constexpr const std::array<const char*, 17> UniformNames = {
|
||||
"modelMatrix", "cameraUp", "cameraViewProjectionMatrix",
|
||||
"colorOption", "magnitudeExponent", "eyePosition", "psfParamConf",
|
||||
@@ -309,120 +305,71 @@ namespace {
|
||||
"Disable Fade-in effect",
|
||||
"Enables/Disables the Fade-in effect."
|
||||
};
|
||||
|
||||
struct [[codegen::Dictionary(RenderableStars)]] Parameters {
|
||||
// The path to the SPECK file containing information about the stars being rendered
|
||||
std::string speckFile [[codegen::key("File")]];
|
||||
|
||||
// [[codegen::verbatim(ColorTextureInfo.description)]]
|
||||
std::string colorMap;
|
||||
|
||||
enum class ColorOption {
|
||||
Color,
|
||||
Velocity,
|
||||
Speed,
|
||||
OtherData [[codegen::key("Other Data")]],
|
||||
FixedColor [[codegen::key("Fixed Color")]]
|
||||
};
|
||||
// [[codegen::verbatim(ColorOptionInfo.description)]]
|
||||
std::optional<ColorOption> colorOption;
|
||||
|
||||
// [[codegen::verbatim(OtherDataOptionInfo.description)]]
|
||||
std::optional<std::string> otherData;
|
||||
|
||||
// [[codegen::verbatim(OtherDataColorMapInfo.description)]]
|
||||
std::optional<std::string> otherDataColorMap;
|
||||
|
||||
// [[codegen::verbatim(FilterOutOfRangeInfo.description)]]
|
||||
std::optional<bool> filterOutOfRange;
|
||||
|
||||
// This value specifies a value that is always filtered out of the value ranges on
|
||||
// loading. This can be used to trim the dataset's automatic value range
|
||||
std::optional<float> staticFilter;
|
||||
|
||||
// This is the value that is used to replace statically filtered values. Setting this
|
||||
// value only makes sense if 'StaticFilter' is 'true', as well
|
||||
std::optional<float> staticFilterReplacement;
|
||||
|
||||
// [[codegen::verbatim(MagnitudeExponentInfo.description)]]
|
||||
std::optional<float> magnitudeExponent;
|
||||
|
||||
// [[codegen::verbatim(EnableTestGridInfo.description)]]
|
||||
std::optional<bool> enableTestGrid;
|
||||
|
||||
// [[codegen::verbatim(RenderMethodOptionInfo.description)]]
|
||||
std::string renderMethod;
|
||||
|
||||
// [[codegen::verbatim(PsfTextureInfo.description)]]
|
||||
std::string texture;
|
||||
|
||||
// [[codegen::verbatim(SizeCompositionOptionInfo.description)]]
|
||||
std::optional<std::string> sizeComposition;
|
||||
|
||||
// [[codegen::verbatim(FadeInDistancesInfo.description)]]
|
||||
std::optional<glm::dvec2> fadeInDistances;
|
||||
|
||||
// [[codegen::verbatim(DisableFadeInInfo.description)]]
|
||||
std::optional<bool> distableFadeIn;
|
||||
};
|
||||
#include "renderablestars_codegen.cpp"
|
||||
} // namespace
|
||||
|
||||
namespace openspace {
|
||||
|
||||
documentation::Documentation RenderableStars::Documentation() {
|
||||
using namespace documentation;
|
||||
return {
|
||||
"RenderableStars",
|
||||
"space_renderablestars",
|
||||
{
|
||||
{
|
||||
"Type",
|
||||
new StringEqualVerifier("RenderableStars"),
|
||||
Optional::No
|
||||
},
|
||||
{
|
||||
KeyFile,
|
||||
new StringVerifier,
|
||||
Optional::No,
|
||||
"The path to the SPECK file that contains information about the stars "
|
||||
"being rendered."
|
||||
},
|
||||
{
|
||||
ColorTextureInfo.identifier,
|
||||
new StringVerifier,
|
||||
Optional::No,
|
||||
ColorTextureInfo.description
|
||||
},
|
||||
/*{
|
||||
ShapeTextureInfo.identifier,
|
||||
new StringVerifier,
|
||||
Optional::No,
|
||||
ShapeTextureInfo.description
|
||||
},*/
|
||||
{
|
||||
ColorOptionInfo.identifier,
|
||||
new StringInListVerifier({
|
||||
"Color", "Velocity", "Speed", "Other Data", "Fixed Color"
|
||||
}),
|
||||
Optional::Yes,
|
||||
ColorOptionInfo.description
|
||||
},
|
||||
{
|
||||
OtherDataOptionInfo.identifier,
|
||||
new StringVerifier,
|
||||
Optional::Yes,
|
||||
OtherDataOptionInfo.description
|
||||
},
|
||||
{
|
||||
OtherDataColorMapInfo.identifier,
|
||||
new StringVerifier,
|
||||
Optional::Yes,
|
||||
OtherDataColorMapInfo.description
|
||||
},
|
||||
{
|
||||
FilterOutOfRangeInfo.identifier,
|
||||
new BoolVerifier,
|
||||
Optional::Yes,
|
||||
FilterOutOfRangeInfo.description
|
||||
},
|
||||
{
|
||||
KeyStaticFilterValue,
|
||||
new DoubleVerifier,
|
||||
Optional::Yes,
|
||||
"This value specifies a value that is always filtered out of the value "
|
||||
"ranges on loading. This can be used to trim the dataset's automatic "
|
||||
"value range."
|
||||
},
|
||||
{
|
||||
KeyStaticFilterReplacement,
|
||||
new DoubleVerifier,
|
||||
Optional::Yes,
|
||||
"This is the value that is used to replace statically filtered values. "
|
||||
"Setting this value only makes sense if 'StaticFilter' is 'true', as "
|
||||
"well."
|
||||
},
|
||||
{
|
||||
MagnitudeExponentInfo.identifier,
|
||||
new DoubleVerifier,
|
||||
Optional::Yes,
|
||||
MagnitudeExponentInfo.description
|
||||
},
|
||||
{
|
||||
EnableTestGridInfo.identifier,
|
||||
new BoolVerifier,
|
||||
Optional::Yes,
|
||||
EnableTestGridInfo.description
|
||||
},
|
||||
{
|
||||
RenderMethodOptionInfo.identifier,
|
||||
new StringVerifier,
|
||||
Optional::No,
|
||||
RenderMethodOptionInfo.description
|
||||
},
|
||||
{
|
||||
SizeCompositionOptionInfo.identifier,
|
||||
new StringVerifier,
|
||||
Optional::No,
|
||||
SizeCompositionOptionInfo.description
|
||||
},
|
||||
{
|
||||
FadeInDistancesInfo.identifier,
|
||||
new Vector2Verifier<double>,
|
||||
Optional::Yes,
|
||||
FadeInDistancesInfo.description
|
||||
},
|
||||
{
|
||||
DisableFadeInInfo.identifier,
|
||||
new BoolVerifier,
|
||||
Optional::Yes,
|
||||
DisableFadeInInfo.description
|
||||
},
|
||||
}
|
||||
};
|
||||
documentation::Documentation doc = codegen::doc<Parameters>();
|
||||
doc.id = "space_renderablestars";
|
||||
return doc;
|
||||
}
|
||||
|
||||
RenderableStars::RenderableStars(const ghoul::Dictionary& dictionary)
|
||||
@@ -482,22 +429,16 @@ RenderableStars::RenderableStars(const ghoul::Dictionary& dictionary)
|
||||
{
|
||||
using File = ghoul::filesystem::File;
|
||||
|
||||
documentation::testSpecificationAndThrow(
|
||||
Documentation(),
|
||||
dictionary,
|
||||
"RenderableStars"
|
||||
);
|
||||
const Parameters p = codegen::bake<Parameters>(dictionary);
|
||||
|
||||
addProperty(_opacity);
|
||||
registerUpdateRenderBinFromOpacity();
|
||||
|
||||
_speckFile = absPath(dictionary.value<std::string>(KeyFile));
|
||||
_speckFile = absPath(p.speckFile);
|
||||
_speckFile.onChange([&]() { _speckFileIsDirty = true; });
|
||||
addProperty(_speckFile);
|
||||
|
||||
_colorTexturePath = absPath(
|
||||
dictionary.value<std::string>(ColorTextureInfo.identifier)
|
||||
);
|
||||
_colorTexturePath = absPath(p.colorMap);
|
||||
_colorTextureFile = std::make_unique<File>(_colorTexturePath);
|
||||
|
||||
/*_shapeTexturePath = absPath(dictionary.value<std::string>(
|
||||
@@ -505,10 +446,8 @@ RenderableStars::RenderableStars(const ghoul::Dictionary& dictionary)
|
||||
));
|
||||
_shapeTextureFile = std::make_unique<File>(_shapeTexturePath);*/
|
||||
|
||||
if (dictionary.hasKey(OtherDataColorMapInfo.identifier)) {
|
||||
_otherDataColorMapPath = absPath(
|
||||
dictionary.value<std::string>(OtherDataColorMapInfo.identifier)
|
||||
);
|
||||
if (p.otherDataColorMap.has_value()) {
|
||||
_otherDataColorMapPath = absPath(*p.otherDataColorMap);
|
||||
}
|
||||
|
||||
_fixedColor.setViewOption(properties::Property::ViewOptions::Color, true);
|
||||
@@ -521,24 +460,23 @@ RenderableStars::RenderableStars(const ghoul::Dictionary& dictionary)
|
||||
{ ColorOption::OtherData, "Other Data" },
|
||||
{ ColorOption::FixedColor, "Fixed Color" }
|
||||
});
|
||||
if (dictionary.hasKey(ColorOptionInfo.identifier)) {
|
||||
const std::string colorOption = dictionary.value<std::string>(
|
||||
ColorOptionInfo.identifier
|
||||
);
|
||||
if (colorOption == "Color") {
|
||||
_colorOption = ColorOption::Color;
|
||||
}
|
||||
else if (colorOption == "Velocity") {
|
||||
_colorOption = ColorOption::Velocity;
|
||||
}
|
||||
else if (colorOption == "Speed") {
|
||||
_colorOption = ColorOption::Speed;
|
||||
}
|
||||
else if (colorOption == "OtherData") {
|
||||
_colorOption = ColorOption::OtherData;
|
||||
}
|
||||
else {
|
||||
_colorOption = ColorOption::FixedColor;
|
||||
if (p.colorOption.has_value()) {
|
||||
switch (*p.colorOption) {
|
||||
case Parameters::ColorOption::Color:
|
||||
_colorOption = ColorOption::Color;
|
||||
break;
|
||||
case Parameters::ColorOption::Velocity:
|
||||
_colorOption = ColorOption::Velocity;
|
||||
break;
|
||||
case Parameters::ColorOption::Speed:
|
||||
_colorOption = ColorOption::Speed;
|
||||
break;
|
||||
case Parameters::ColorOption::OtherData:
|
||||
_colorOption = ColorOption::OtherData;
|
||||
break;
|
||||
case Parameters::ColorOption::FixedColor:
|
||||
_colorOption = ColorOption::FixedColor;
|
||||
break;
|
||||
}
|
||||
}
|
||||
_colorOption.onChange([&] { _dataIsDirty = true; });
|
||||
@@ -556,13 +494,8 @@ RenderableStars::RenderableStars(const ghoul::Dictionary& dictionary)
|
||||
});
|
||||
addProperty(_shapeTexturePath);*/
|
||||
|
||||
if (dictionary.hasKey(EnableTestGridInfo.identifier)) {
|
||||
_enableTestGrid = dictionary.value<bool>(EnableTestGridInfo.identifier);
|
||||
}
|
||||
|
||||
if (dictionary.hasKey(OtherDataOptionInfo.identifier)) {
|
||||
_queuedOtherData = dictionary.value<std::string>(OtherDataOptionInfo.identifier);
|
||||
}
|
||||
_enableTestGrid = p.enableTestGrid.value_or(_enableTestGrid);
|
||||
_queuedOtherData = p.otherData.value_or(_queuedOtherData);
|
||||
|
||||
_otherDataOption.onChange([&]() { _dataIsDirty = true; });
|
||||
addProperty(_otherDataOption);
|
||||
@@ -572,16 +505,9 @@ RenderableStars::RenderableStars(const ghoul::Dictionary& dictionary)
|
||||
addProperty(_otherDataColorMapPath);
|
||||
_otherDataColorMapPath.onChange([&]() { _otherDataColorMapIsDirty = true; });
|
||||
|
||||
if (dictionary.hasKey(KeyStaticFilterValue)) {
|
||||
_staticFilterValue = static_cast<float>(
|
||||
dictionary.value<double>(KeyStaticFilterValue)
|
||||
);
|
||||
}
|
||||
if (dictionary.hasKey(KeyStaticFilterReplacement)) {
|
||||
_staticFilterReplacementValue = static_cast<float>(
|
||||
dictionary.value<double>(KeyStaticFilterReplacement)
|
||||
);
|
||||
}
|
||||
_staticFilterValue = p.staticFilter;
|
||||
_staticFilterReplacementValue =
|
||||
p.staticFilterReplacement.value_or(_staticFilterReplacementValue);
|
||||
|
||||
addProperty(_filterOutOfRange);
|
||||
|
||||
@@ -592,23 +518,14 @@ RenderableStars::RenderableStars(const ghoul::Dictionary& dictionary)
|
||||
_renderingMethodOption.addOption(RenderOptionTexture, "Textured Based");
|
||||
addProperty(_renderingMethodOption);
|
||||
|
||||
if (dictionary.hasKey(RenderMethodOptionInfo.identifier)) {
|
||||
std::string renderingMethod =
|
||||
dictionary.value<std::string>(RenderMethodOptionInfo.identifier);
|
||||
if (renderingMethod == "PSF") {
|
||||
_renderingMethodOption = RenderOptionPointSpreadFunction;
|
||||
}
|
||||
else if (renderingMethod == "Texture Based") {
|
||||
_renderingMethodOption = RenderOptionTexture;
|
||||
}
|
||||
if (p.renderMethod == "PSF") {
|
||||
_renderingMethodOption = RenderOptionPointSpreadFunction;
|
||||
}
|
||||
else {
|
||||
else if (p.renderMethod == "Texture Based") {
|
||||
_renderingMethodOption = RenderOptionTexture;
|
||||
}
|
||||
|
||||
_pointSpreadFunctionTexturePath = absPath(dictionary.value<std::string>(
|
||||
PsfTextureInfo.identifier
|
||||
));
|
||||
_pointSpreadFunctionTexturePath = absPath(p.texture);
|
||||
_pointSpreadFunctionFile = std::make_unique<File>(_pointSpreadFunctionTexturePath);
|
||||
_pointSpreadFunctionTexturePath.onChange([&]() {
|
||||
_pointSpreadFunctionTextureIsDirty = true;
|
||||
@@ -631,26 +548,24 @@ RenderableStars::RenderableStars(const ghoul::Dictionary& dictionary)
|
||||
_psfMultiplyOption.addOption(4, "Apparent Magnitude");
|
||||
_psfMultiplyOption.addOption(5, "Distance Modulus");
|
||||
|
||||
if (dictionary.hasKey(MagnitudeExponentInfo.identifier)) {
|
||||
std::string sizeCompositionOption =
|
||||
dictionary.value<std::string>(SizeCompositionOptionInfo.identifier);
|
||||
|
||||
if (sizeCompositionOption == "App Brightness") {
|
||||
if (p.sizeComposition.has_value()) {
|
||||
if (*p.sizeComposition == "App Brightness") {
|
||||
_psfMultiplyOption = 0;
|
||||
}
|
||||
else if (sizeCompositionOption == "Lum and Size") {
|
||||
else if (*p.sizeComposition == "Lum and Size") {
|
||||
_psfMultiplyOption = 1;
|
||||
}
|
||||
else if (sizeCompositionOption == "Lum, Size and App Brightness") {
|
||||
else if (*p.sizeComposition == "Lum, Size and App Brightness") {
|
||||
_psfMultiplyOption = 2;
|
||||
}
|
||||
else if (sizeCompositionOption == "Abs Magnitude") {
|
||||
else if (*p.sizeComposition == "Abs Magnitude") {
|
||||
_psfMultiplyOption = 3;
|
||||
}
|
||||
else if (sizeCompositionOption == "App Maginitude") {
|
||||
else if (*p.sizeComposition == "App Maginitude") {
|
||||
_psfMultiplyOption = 4;
|
||||
}
|
||||
else if (sizeCompositionOption == "Distance Modulus") {
|
||||
else if (*p.sizeComposition == "Distance Modulus") {
|
||||
_psfMultiplyOption = 5;
|
||||
}
|
||||
}
|
||||
@@ -663,11 +578,7 @@ RenderableStars::RenderableStars(const ghoul::Dictionary& dictionary)
|
||||
_parametersOwner.addProperty(_radiusCent);
|
||||
_parametersOwner.addProperty(_brightnessCent);
|
||||
|
||||
if (dictionary.hasKey(MagnitudeExponentInfo.identifier)) {
|
||||
_magnitudeExponent = static_cast<float>(
|
||||
dictionary.value<double>(MagnitudeExponentInfo.identifier)
|
||||
);
|
||||
}
|
||||
_magnitudeExponent = p.magnitudeExponent.value_or(_magnitudeExponent);
|
||||
_parametersOwner.addProperty(_magnitudeExponent);
|
||||
|
||||
auto renderPsf = [&]() { renderPSFToTexture(); };
|
||||
@@ -693,8 +604,8 @@ RenderableStars::RenderableStars(const ghoul::Dictionary& dictionary)
|
||||
addPropertySubOwner(_parametersOwner);
|
||||
addPropertySubOwner(_moffatMethodOwner);
|
||||
|
||||
if (dictionary.hasKey(FadeInDistancesInfo.identifier)) {
|
||||
glm::vec2 v = dictionary.value<glm::dvec2>(FadeInDistancesInfo.identifier);
|
||||
if (p.fadeInDistances.has_value()) {
|
||||
glm::vec2 v = *p.fadeInDistances;
|
||||
_fadeInDistance = v;
|
||||
_disableFadeInDistance = false;
|
||||
addProperty(_fadeInDistance);
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
/****************************************************************************************
|
||||
/****************************************************************************************
|
||||
* *
|
||||
* OpenSpace *
|
||||
* *
|
||||
@@ -41,30 +41,23 @@ namespace {
|
||||
"Segments",
|
||||
"This value specifies the number of segments that this sphere is split into."
|
||||
};
|
||||
|
||||
struct [[codegen::Dictionary(SimpleSphereGeometry)]] Parameters {
|
||||
// [[codegen::verbatim(RadiusInfo.description)]]
|
||||
std::variant<float, glm::vec3> radius;
|
||||
|
||||
// [[codegen::verbatim(SegmentsInfo.description)]]
|
||||
int segments;
|
||||
};
|
||||
#include "simplespheregeometry_codegen.cpp"
|
||||
} // namespace
|
||||
|
||||
namespace openspace::planetgeometry {
|
||||
|
||||
documentation::Documentation SimpleSphereGeometry::Documentation() {
|
||||
using namespace documentation;
|
||||
return {
|
||||
"SimpleSphereGeometry",
|
||||
"space_geometry_simplesphere",
|
||||
{
|
||||
{
|
||||
RadiusInfo.identifier,
|
||||
new OrVerifier({ new DoubleVerifier, new DoubleVector3Verifier }),
|
||||
Optional::No,
|
||||
RadiusInfo.description
|
||||
},
|
||||
{
|
||||
SegmentsInfo.identifier,
|
||||
new IntVerifier,
|
||||
Optional::No,
|
||||
SegmentsInfo.description
|
||||
}
|
||||
}
|
||||
};
|
||||
documentation::Documentation doc = codegen::doc<Parameters>();
|
||||
doc.id = "space_geometry_simplesphere";
|
||||
return doc;
|
||||
}
|
||||
|
||||
SimpleSphereGeometry::SimpleSphereGeometry(const ghoul::Dictionary& dictionary)
|
||||
@@ -72,23 +65,17 @@ SimpleSphereGeometry::SimpleSphereGeometry(const ghoul::Dictionary& dictionary)
|
||||
, _segments(SegmentsInfo, 20, 1, 5000)
|
||||
, _sphere(nullptr)
|
||||
{
|
||||
documentation::testSpecificationAndThrow(
|
||||
Documentation(),
|
||||
dictionary,
|
||||
"SimpleSphereGeometry"
|
||||
);
|
||||
const Parameters p = codegen::bake<Parameters>(dictionary);
|
||||
|
||||
if (dictionary.hasValue<double>(RadiusInfo.identifier)) {
|
||||
const float r = static_cast<float>(
|
||||
dictionary.value<double>(RadiusInfo.identifier)
|
||||
);
|
||||
_radius = { r, r, r };
|
||||
if (std::holds_alternative<float>(p.radius)) {
|
||||
const float radius = std::get<float>(p.radius);
|
||||
_radius = glm::dvec3(radius, radius, radius);
|
||||
}
|
||||
else {
|
||||
_radius = dictionary.value<glm::dvec3>(RadiusInfo.identifier);
|
||||
_radius = std::get<glm::vec3>(p.radius);
|
||||
}
|
||||
|
||||
_segments = static_cast<int>(dictionary.value<double>(SegmentsInfo.identifier));
|
||||
_segments = p.segments;
|
||||
|
||||
// The shader need the radii values but they are not changeable runtime
|
||||
// TODO: Possibly add a scaling property @AA
|
||||
|
||||
@@ -29,10 +29,9 @@
|
||||
#include <openspace/util/spicemanager.h>
|
||||
#include <openspace/util/time.h>
|
||||
#include <openspace/util/updatestructures.h>
|
||||
#include <optional>
|
||||
|
||||
namespace {
|
||||
constexpr const char* KeyKernels = "Kernels";
|
||||
|
||||
constexpr openspace::properties::Property::PropertyInfo SourceInfo = {
|
||||
"SourceFrame",
|
||||
"Source",
|
||||
@@ -52,76 +51,49 @@ namespace {
|
||||
"Time Frame",
|
||||
"The time frame in which the spice kernels are valid."
|
||||
};
|
||||
|
||||
struct [[codegen::Dictionary(SpiceRotation)]] Parameters {
|
||||
// [[codegen::verbatim(SourceInfo.description)]]
|
||||
std::string sourceFrame
|
||||
[[codegen::annotation("A valid SPICE NAIF name or integer")]];
|
||||
|
||||
// [[codegen::verbatim(DestinationInfo.description)]]
|
||||
std::string destinationFrame;
|
||||
|
||||
// [[codegen::verbatim(DestinationInfo.description)]]
|
||||
std::optional<std::variant<std::vector<std::string>, std::string>> kernels;
|
||||
|
||||
// [[codegen::verbatim(TimeFrameInfo.description)]]
|
||||
std::optional<std::monostate> timeFrame [[codegen::reference("core_time_frame")]];
|
||||
};
|
||||
#include "spicerotation_codegen.cpp"
|
||||
} // namespace
|
||||
|
||||
namespace openspace {
|
||||
|
||||
documentation::Documentation SpiceRotation::Documentation() {
|
||||
using namespace openspace::documentation;
|
||||
return {
|
||||
"Spice Rotation",
|
||||
"space_transform_rotation_spice",
|
||||
{
|
||||
{
|
||||
"Type",
|
||||
new StringEqualVerifier("SpiceRotation"),
|
||||
Optional::No
|
||||
},
|
||||
{
|
||||
SourceInfo.identifier,
|
||||
new StringAnnotationVerifier("A valid SPICE NAIF name or integer"),
|
||||
Optional::No,
|
||||
SourceInfo.description
|
||||
},
|
||||
{
|
||||
DestinationInfo.identifier,
|
||||
new StringAnnotationVerifier("A valid SPICE NAIF name or integer"),
|
||||
Optional::No,
|
||||
DestinationInfo.description
|
||||
},
|
||||
{
|
||||
KeyKernels,
|
||||
new OrVerifier({ new StringListVerifier, new StringVerifier }),
|
||||
Optional::Yes,
|
||||
"A single kernel or list of kernels that this SpiceTranslation depends "
|
||||
"on. All provided kernels will be loaded before any other operation is "
|
||||
"performed."
|
||||
},
|
||||
{
|
||||
TimeFrameInfo.identifier,
|
||||
new ReferencingVerifier("core_time_frame"),
|
||||
Optional::Yes,
|
||||
TimeFrameInfo.description
|
||||
},
|
||||
}
|
||||
};
|
||||
documentation::Documentation doc = codegen::doc<Parameters>();
|
||||
doc.id = "space_transform_rotation_spice";
|
||||
return doc;
|
||||
}
|
||||
|
||||
SpiceRotation::SpiceRotation(const ghoul::Dictionary& dictionary)
|
||||
: _sourceFrame(SourceInfo)
|
||||
, _destinationFrame(DestinationInfo)
|
||||
{
|
||||
documentation::testSpecificationAndThrow(
|
||||
Documentation(),
|
||||
dictionary,
|
||||
"SpiceRotation"
|
||||
);
|
||||
const Parameters p = codegen::bake<Parameters>(dictionary);
|
||||
|
||||
_sourceFrame = dictionary.value<std::string>(SourceInfo.identifier);
|
||||
_destinationFrame = dictionary.value<std::string>(DestinationInfo.identifier);
|
||||
_sourceFrame = p.sourceFrame;
|
||||
_destinationFrame = p.destinationFrame;
|
||||
|
||||
if (dictionary.hasValue<std::string>(KeyKernels)) {
|
||||
SpiceManager::ref().loadKernel(dictionary.value<std::string>(KeyKernels));
|
||||
}
|
||||
else if (dictionary.hasValue<ghoul::Dictionary>(KeyKernels)) {
|
||||
ghoul::Dictionary kernels = dictionary.value<ghoul::Dictionary>(KeyKernels);
|
||||
for (size_t i = 1; i <= kernels.size(); ++i) {
|
||||
if (!kernels.hasValue<std::string>(std::to_string(i))) {
|
||||
throw ghoul::RuntimeError("Kernels has to be an array-style table");
|
||||
if (p.kernels.has_value()) {
|
||||
if (std::holds_alternative<std::string>(*p.kernels)) {
|
||||
SpiceManager::ref().loadKernel(std::get<std::string>(*p.kernels));
|
||||
}
|
||||
else {
|
||||
for (const std::string& s : std::get<std::vector<std::string>>(*p.kernels)) {
|
||||
SpiceManager::ref().loadKernel(s);
|
||||
}
|
||||
|
||||
std::string kernel = kernels.value<std::string>(std::to_string(i));
|
||||
SpiceManager::ref().loadKernel(kernel);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -130,7 +102,7 @@ SpiceRotation::SpiceRotation(const ghoul::Dictionary& dictionary)
|
||||
dictionary.value<ghoul::Dictionary>(TimeFrameInfo.identifier);
|
||||
_timeFrame = TimeFrame::createFromDictionary(timeFrameDictionary);
|
||||
if (_timeFrame == nullptr) {
|
||||
throw ghoul::RuntimeError("Invalid dictionary for TimeFrame.");
|
||||
throw ghoul::RuntimeError("Invalid dictionary for TimeFrame");
|
||||
}
|
||||
addPropertySubOwner(_timeFrame.get());
|
||||
}
|
||||
|
||||
@@ -31,7 +31,6 @@
|
||||
#include <modules/space/rendering/renderablesmallbody.h>
|
||||
#include <modules/space/rendering/renderablestars.h>
|
||||
#include <modules/space/rendering/simplespheregeometry.h>
|
||||
//#include <modules/space/tasks/generatedebrisvolumetask.h>
|
||||
#include <modules/space/translation/keplertranslation.h>
|
||||
#include <modules/space/translation/spicetranslation.h>
|
||||
#include <modules/space/translation/tletranslation.h>
|
||||
|
||||
@@ -46,32 +46,22 @@ namespace {
|
||||
"This value is the path to the text file generated by Horizons with observer "
|
||||
"range and Galactiv longitude and latitude for different timestamps."
|
||||
};
|
||||
|
||||
struct [[codegen::Dictionary(HorizonsTranslation)]] Parameters {
|
||||
// [[codegen::verbatim(HorizonsTextFileInfo.description)]]
|
||||
std::string horizonsTextFile;
|
||||
};
|
||||
#include "horizonstranslation_codegen.cpp"
|
||||
} // namespace
|
||||
|
||||
namespace openspace {
|
||||
|
||||
documentation::Documentation HorizonsTranslation::Documentation() {
|
||||
using namespace documentation;
|
||||
return {
|
||||
"Horizons Translation",
|
||||
"base_transform_translation_horizons",
|
||||
{
|
||||
{
|
||||
"Type",
|
||||
new StringEqualVerifier("HorizonsTranslation"),
|
||||
Optional::No
|
||||
},
|
||||
{
|
||||
HorizonsTextFileInfo.identifier,
|
||||
new StringVerifier,
|
||||
Optional::No,
|
||||
HorizonsTextFileInfo.description
|
||||
}
|
||||
}
|
||||
};
|
||||
documentation::Documentation doc = codegen::doc<Parameters>();
|
||||
doc.id = "base_transform_translation_horizons";
|
||||
return doc;
|
||||
}
|
||||
|
||||
|
||||
HorizonsTranslation::HorizonsTranslation()
|
||||
: _horizonsTextFile(HorizonsTextFileInfo)
|
||||
{
|
||||
@@ -91,15 +81,8 @@ HorizonsTranslation::HorizonsTranslation()
|
||||
HorizonsTranslation::HorizonsTranslation(const ghoul::Dictionary& dictionary)
|
||||
: HorizonsTranslation()
|
||||
{
|
||||
documentation::testSpecificationAndThrow(
|
||||
Documentation(),
|
||||
dictionary,
|
||||
"HorizonsTranslation"
|
||||
);
|
||||
|
||||
_horizonsTextFile = absPath(
|
||||
dictionary.value<std::string>(HorizonsTextFileInfo.identifier)
|
||||
);
|
||||
const Parameters p = codegen::bake<Parameters>(dictionary);
|
||||
_horizonsTextFile = absPath(p.horizonsTextFile);
|
||||
}
|
||||
|
||||
glm::dvec3 HorizonsTranslation::position(const UpdateData& data) const {
|
||||
|
||||
@@ -31,7 +31,6 @@
|
||||
#include <glm/gtx/transform.hpp>
|
||||
|
||||
namespace {
|
||||
|
||||
template <typename T, typename Func>
|
||||
T solveIteration(const Func& function, T x0, const T& err = 0.0, int maxIter = 100) {
|
||||
T x2 = x0;
|
||||
@@ -105,6 +104,33 @@ namespace {
|
||||
"Orbit period",
|
||||
"Specifies the orbital period (in seconds)."
|
||||
};
|
||||
|
||||
struct [[codegen::Dictionary(KeplerTranslation)]] Parameters {
|
||||
// [[codegen::verbatim(EccentricityInfo.description)]]
|
||||
double eccentricity [[codegen::inrange(0.0, 1.0)]];
|
||||
|
||||
// [[codegen::verbatim(SemiMajorAxisInfo.description)]]
|
||||
double semiMajorAxis;
|
||||
|
||||
// [[codegen::verbatim(InclinationInfo.description)]]
|
||||
double inclination [[codegen::inrange(0.0, 360.0)]];
|
||||
|
||||
// [[codegen::verbatim(AscendingNodeInfo.description)]]
|
||||
double ascendingNode [[codegen::inrange(0.0, 360.0)]];
|
||||
|
||||
// [[codegen::verbatim(ArgumentOfPeriapsisInfo.description)]]
|
||||
double argumentOfPeriapsis [[codegen::inrange(0.0, 360.0)]];
|
||||
|
||||
// [[codegen::verbatim(MeanAnomalyAtEpochInfo.description)]]
|
||||
double meanAnomaly [[codegen::inrange(0.0, 360.0)]];
|
||||
|
||||
// [[codegen::verbatim(EpochInfo.description)]]
|
||||
std::string epoch;
|
||||
|
||||
// [[codegen::verbatim(PeriodInfo.description)]]
|
||||
double period [[codegen::greater(0.0)]];
|
||||
};
|
||||
#include "keplertranslation_codegen.cpp"
|
||||
} // namespace
|
||||
|
||||
namespace openspace {
|
||||
@@ -115,66 +141,9 @@ KeplerTranslation::RangeError::RangeError(std::string off)
|
||||
{}
|
||||
|
||||
documentation::Documentation KeplerTranslation::Documentation() {
|
||||
using namespace openspace::documentation;
|
||||
return {
|
||||
"Kepler Translation",
|
||||
"space_transform_kepler",
|
||||
{
|
||||
{
|
||||
"Type",
|
||||
new StringEqualVerifier("KeplerTranslation"),
|
||||
Optional::No
|
||||
},
|
||||
{
|
||||
EccentricityInfo.identifier,
|
||||
new DoubleInRangeVerifier(0.0, 1.0),
|
||||
Optional::No,
|
||||
EccentricityInfo.description
|
||||
},
|
||||
{
|
||||
SemiMajorAxisInfo.identifier,
|
||||
new DoubleVerifier,
|
||||
Optional::No,
|
||||
SemiMajorAxisInfo.description
|
||||
},
|
||||
{
|
||||
InclinationInfo.identifier,
|
||||
new DoubleInRangeVerifier(0.0, 360.0),
|
||||
Optional::No,
|
||||
InclinationInfo.description
|
||||
},
|
||||
{
|
||||
AscendingNodeInfo.identifier,
|
||||
new DoubleInRangeVerifier(0.0, 360.0),
|
||||
Optional::No,
|
||||
AscendingNodeInfo.description
|
||||
},
|
||||
{
|
||||
ArgumentOfPeriapsisInfo.identifier,
|
||||
new DoubleInRangeVerifier(0.0, 360.0),
|
||||
Optional::No,
|
||||
ArgumentOfPeriapsisInfo.description
|
||||
},
|
||||
{
|
||||
MeanAnomalyAtEpochInfo.identifier,
|
||||
new DoubleInRangeVerifier(0.0, 360.0),
|
||||
Optional::No,
|
||||
MeanAnomalyAtEpochInfo.description
|
||||
},
|
||||
{
|
||||
EpochInfo.identifier,
|
||||
new StringVerifier,
|
||||
Optional::No,
|
||||
EpochInfo.description
|
||||
},
|
||||
{
|
||||
PeriodInfo.identifier,
|
||||
new DoubleGreaterVerifier(0.0),
|
||||
Optional::No,
|
||||
PeriodInfo.description
|
||||
},
|
||||
}
|
||||
};
|
||||
documentation::Documentation doc = codegen::doc<Parameters>();
|
||||
doc.id = "space_transform_kepler";
|
||||
return doc;
|
||||
}
|
||||
|
||||
KeplerTranslation::KeplerTranslation()
|
||||
@@ -218,21 +187,17 @@ KeplerTranslation::KeplerTranslation()
|
||||
KeplerTranslation::KeplerTranslation(const ghoul::Dictionary& dictionary)
|
||||
: KeplerTranslation()
|
||||
{
|
||||
documentation::testSpecificationAndThrow(
|
||||
Documentation(),
|
||||
dictionary,
|
||||
"KeplerTranslation"
|
||||
);
|
||||
const Parameters p = codegen::bake<Parameters>(dictionary);
|
||||
|
||||
setKeplerElements(
|
||||
dictionary.value<double>(EccentricityInfo.identifier),
|
||||
dictionary.value<double>(SemiMajorAxisInfo.identifier),
|
||||
dictionary.value<double>(InclinationInfo.identifier),
|
||||
dictionary.value<double>(AscendingNodeInfo.identifier),
|
||||
dictionary.value<double>(ArgumentOfPeriapsisInfo.identifier),
|
||||
dictionary.value<double>(MeanAnomalyAtEpochInfo.identifier),
|
||||
dictionary.value<double>(PeriodInfo.identifier),
|
||||
dictionary.value<std::string>(EpochInfo.identifier)
|
||||
p.eccentricity,
|
||||
p.semiMajorAxis,
|
||||
p.inclination,
|
||||
p.ascendingNode,
|
||||
p.argumentOfPeriapsis,
|
||||
p.meanAnomaly,
|
||||
p.period,
|
||||
p.epoch
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
@@ -33,10 +33,9 @@
|
||||
#include <ghoul/filesystem/filesystem.h>
|
||||
#include <ghoul/logging/logmanager.h>
|
||||
#include <ghoul/misc/profiling.h>
|
||||
#include <optional>
|
||||
|
||||
namespace {
|
||||
constexpr const char* KeyKernels = "Kernels";
|
||||
|
||||
constexpr const char* DefaultReferenceFrame = "GALACTIC";
|
||||
|
||||
constexpr openspace::properties::Property::PropertyInfo TargetInfo = {
|
||||
@@ -61,54 +60,32 @@ namespace {
|
||||
"This is the SPICE NAIF name for the reference frame in which the position "
|
||||
"should be retrieved. The default value is GALACTIC."
|
||||
};
|
||||
|
||||
struct [[codegen::Dictionary(SpiceTranslation)]] Parameters {
|
||||
// [[codegen::verbatim(TargetInfo.description)]]
|
||||
std::string target
|
||||
[[codegen::annotation("A valid SPICE NAIF name or identifier")]];
|
||||
|
||||
// [[codegen::verbatim(ObserverInfo.description)]]
|
||||
std::string observer
|
||||
[[codegen::annotation("A valid SPICE NAIF name or identifier")]];
|
||||
|
||||
std::optional<std::string> frame
|
||||
[[codegen::annotation("A valid SPICE NAIF name for a reference frame")]];
|
||||
|
||||
// A single kernel or list of kernels that this SpiceTranslation depends on. All
|
||||
// provided kernels will be loaded before any other operation is performed
|
||||
std::optional<std::variant<std::vector<std::string>, std::string>> kernels;
|
||||
};
|
||||
#include "spicetranslation_codegen.cpp"
|
||||
} // namespace
|
||||
|
||||
namespace openspace {
|
||||
|
||||
documentation::Documentation SpiceTranslation::Documentation() {
|
||||
using namespace openspace::documentation;
|
||||
|
||||
return {
|
||||
"Spice Translation",
|
||||
"space_translation_spicetranslation",
|
||||
{
|
||||
{
|
||||
"Type",
|
||||
new StringEqualVerifier("SpiceTranslation"),
|
||||
Optional::No
|
||||
},
|
||||
{
|
||||
TargetInfo.identifier,
|
||||
new StringAnnotationVerifier("A valid SPICE NAIF name or identifier"),
|
||||
Optional::No,
|
||||
"This is the SPICE NAIF name for the body whose translation is to be "
|
||||
"computed by the SpiceTranslation. It can either be a fully qualified "
|
||||
"name (such as 'EARTH') or a NAIF integer id code (such as '399')."
|
||||
},
|
||||
{
|
||||
ObserverInfo.identifier,
|
||||
new StringAnnotationVerifier("A valid SPICE NAIF name or identifier"),
|
||||
Optional::No,
|
||||
ObserverInfo.description
|
||||
},
|
||||
{
|
||||
FrameInfo.identifier,
|
||||
new StringAnnotationVerifier(
|
||||
"A valid SPICE NAIF name for a reference frame"
|
||||
),
|
||||
Optional::Yes,
|
||||
FrameInfo.description
|
||||
},
|
||||
{
|
||||
KeyKernels,
|
||||
new OrVerifier({ new StringListVerifier, new StringVerifier }),
|
||||
Optional::Yes,
|
||||
"A single kernel or list of kernels that this SpiceTranslation depends "
|
||||
"on. All provided kernels will be loaded before any other operation is "
|
||||
"performed."
|
||||
}
|
||||
}
|
||||
};
|
||||
documentation::Documentation doc = codegen::doc<Parameters>();
|
||||
doc.id = "space_translation_spicetranslation";
|
||||
return doc;
|
||||
}
|
||||
|
||||
SpiceTranslation::SpiceTranslation(const ghoul::Dictionary& dictionary)
|
||||
@@ -117,15 +94,13 @@ SpiceTranslation::SpiceTranslation(const ghoul::Dictionary& dictionary)
|
||||
, _frame(FrameInfo, DefaultReferenceFrame)
|
||||
, _cachedFrame(DefaultReferenceFrame)
|
||||
{
|
||||
documentation::testSpecificationAndThrow(
|
||||
Documentation(),
|
||||
dictionary,
|
||||
"SpiceTranslation"
|
||||
);
|
||||
const Parameters p = codegen::bake<Parameters>(dictionary);
|
||||
|
||||
auto loadKernel = [](const std::string& kernel) {
|
||||
if (!FileSys.fileExists(kernel)) {
|
||||
throw SpiceManager::SpiceException("Kernel '" + kernel + "' does not exist");
|
||||
throw SpiceManager::SpiceException(fmt::format(
|
||||
"Kernel '{}' does not exist", kernel
|
||||
));
|
||||
}
|
||||
|
||||
try {
|
||||
@@ -136,17 +111,13 @@ SpiceTranslation::SpiceTranslation(const ghoul::Dictionary& dictionary)
|
||||
}
|
||||
};
|
||||
|
||||
if (dictionary.hasKey(KeyKernels)) {
|
||||
// Due to the specification, we can be sure it is either a Dictionary or a string
|
||||
if (dictionary.hasValue<std::string>(KeyKernels)) {
|
||||
std::string kernel = dictionary.value<std::string>(KeyKernels);
|
||||
loadKernel(absPath(kernel));
|
||||
if (p.kernels.has_value()) {
|
||||
if (std::holds_alternative<std::string>(*p.kernels)) {
|
||||
loadKernel(absPath(std::get<std::string>(*p.kernels)));
|
||||
}
|
||||
else {
|
||||
ghoul::Dictionary kernels = dictionary.value<ghoul::Dictionary>(KeyKernels);
|
||||
for (size_t i = 1; i <= kernels.size(); ++i) {
|
||||
std::string kernel = kernels.value<std::string>(std::to_string(i));
|
||||
loadKernel(absPath(kernel));
|
||||
for (const std::string& k : std::get<std::vector<std::string>>(*p.kernels)) {
|
||||
loadKernel(absPath(k));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -172,12 +143,9 @@ SpiceTranslation::SpiceTranslation(const ghoul::Dictionary& dictionary)
|
||||
});
|
||||
addProperty(_frame);
|
||||
|
||||
_target = dictionary.value<std::string>(TargetInfo.identifier);
|
||||
_observer = dictionary.value<std::string>(ObserverInfo.identifier);
|
||||
|
||||
if (dictionary.hasKey(FrameInfo.identifier)) {
|
||||
_frame = dictionary.value<std::string>(FrameInfo.identifier);
|
||||
}
|
||||
_target = p.target;
|
||||
_observer = p.observer;
|
||||
_frame = p.frame.value_or(_frame);
|
||||
}
|
||||
|
||||
glm::dvec3 SpiceTranslation::position(const UpdateData& data) const {
|
||||
|
||||
@@ -29,12 +29,10 @@
|
||||
#include <ghoul/filesystem/filesystem.h>
|
||||
#include <chrono>
|
||||
#include <fstream>
|
||||
#include <optional>
|
||||
#include <vector>
|
||||
|
||||
namespace {
|
||||
constexpr const char* KeyFile = "File";
|
||||
constexpr const char* KeyLineNumber = "LineNumber";
|
||||
|
||||
// The list of leap years only goes until 2056 as we need to touch this file then
|
||||
// again anyway ;)
|
||||
const std::vector<int> LeapYears = {
|
||||
@@ -211,52 +209,32 @@ namespace {
|
||||
// We need the semi major axis in km instead of m
|
||||
return semiMajorAxis / 1000.0;
|
||||
}
|
||||
} // namespace
|
||||
|
||||
struct [[codegen::Dictionary(TLETranslation)]] Parameters {
|
||||
// Specifies the filename of the Two-Line-Element file
|
||||
std::string file;
|
||||
|
||||
// Specifies the line number within the file where the group of 3 TLE lines begins
|
||||
// (1-based). Defaults to 1
|
||||
std::optional<int> lineNumber [[codegen::greater(0)]];
|
||||
};
|
||||
#include "tletranslation_codegen.cpp"
|
||||
} // namespace
|
||||
|
||||
namespace openspace {
|
||||
|
||||
documentation::Documentation TLETranslation::Documentation() {
|
||||
using namespace openspace::documentation;
|
||||
return {
|
||||
"TLE Translation",
|
||||
"space_transform_tle",
|
||||
{
|
||||
{
|
||||
"Type",
|
||||
new StringEqualVerifier("TLETranslation"),
|
||||
Optional::No
|
||||
},
|
||||
{
|
||||
KeyFile,
|
||||
new StringVerifier,
|
||||
Optional::No,
|
||||
"Specifies the filename of the Two-Line-Element file"
|
||||
},
|
||||
{
|
||||
KeyLineNumber,
|
||||
new DoubleGreaterVerifier(0),
|
||||
Optional::Yes,
|
||||
"Specifies the line number within the file where the group of 3 TLE "
|
||||
"lines begins (1-based). Defaults to 1."
|
||||
}
|
||||
}
|
||||
};
|
||||
documentation::Documentation doc = codegen::doc<Parameters>();
|
||||
doc.id = "space_transform_tle";
|
||||
return doc;
|
||||
}
|
||||
|
||||
TLETranslation::TLETranslation(const ghoul::Dictionary& dictionary) {
|
||||
documentation::testSpecificationAndThrow(
|
||||
Documentation(),
|
||||
dictionary,
|
||||
"TLETranslation"
|
||||
);
|
||||
const Parameters p = codegen::bake<Parameters>(dictionary);
|
||||
|
||||
const std::string& file = dictionary.value<std::string>(KeyFile);
|
||||
int lineNum = 1;
|
||||
if (dictionary.hasValue<double>(KeyLineNumber)) {
|
||||
lineNum = static_cast<int>(dictionary.value<double>(KeyLineNumber));
|
||||
}
|
||||
readTLEFile(file, lineNum);
|
||||
|
||||
int lineNum = p.lineNumber.value_or(1);
|
||||
readTLEFile(p.file, lineNum);
|
||||
}
|
||||
|
||||
void TLETranslation::readTLEFile(const std::string& filename, int lineNum) {
|
||||
|
||||
@@ -87,47 +87,29 @@ namespace {
|
||||
glm::vec2 addToBoundingbox(glm::vec2 lhs, glm::vec2 rhs) {
|
||||
return { std::max(lhs.x, rhs.x), lhs.y + rhs.y };
|
||||
}
|
||||
|
||||
struct [[codegen::Dictionary(DashboardItemInstruments)]] Parameters {
|
||||
// [[codegen::verbatim(FontNameInfo.description)]]
|
||||
std::optional<std::string> fontName;
|
||||
|
||||
// [[codegen::verbatim(FontSizeInfo.description)]]
|
||||
std::optional<float> fontSize;
|
||||
|
||||
// [[codegen::verbatim(ActiveColorInfo.description)]]
|
||||
std::optional<glm::dvec3> activeColor;
|
||||
|
||||
// [[codegen::verbatim(FlashColorInfo.description)]]
|
||||
std::optional<glm::dvec3> flashColor;
|
||||
};
|
||||
#include "dashboarditeminstruments_codegen.cpp"
|
||||
} // namespace
|
||||
|
||||
namespace openspace {
|
||||
|
||||
documentation::Documentation DashboardItemInstruments::Documentation() {
|
||||
using namespace documentation;
|
||||
return {
|
||||
"DashboardItem Instruments",
|
||||
"spacecraftinstruments_dashboarditem_instuments",
|
||||
{
|
||||
{
|
||||
"Type",
|
||||
new StringEqualVerifier("DashboardItemInstruments"),
|
||||
Optional::No
|
||||
},
|
||||
{
|
||||
FontNameInfo.identifier,
|
||||
new StringVerifier,
|
||||
Optional::Yes,
|
||||
FontNameInfo.description
|
||||
},
|
||||
{
|
||||
FontSizeInfo.identifier,
|
||||
new IntVerifier,
|
||||
Optional::Yes,
|
||||
FontSizeInfo.description
|
||||
},
|
||||
{
|
||||
ActiveColorInfo.identifier,
|
||||
new DoubleVector3Verifier,
|
||||
Optional::Yes,
|
||||
ActiveColorInfo.description
|
||||
},
|
||||
{
|
||||
FlashColorInfo.identifier,
|
||||
new DoubleVector3Verifier,
|
||||
Optional::Yes,
|
||||
FlashColorInfo.description
|
||||
}
|
||||
}
|
||||
};
|
||||
documentation::Documentation doc = codegen::doc<Parameters>();
|
||||
doc.id = "spacecraftinstruments_dashboarditem_instuments";
|
||||
return doc;
|
||||
}
|
||||
|
||||
DashboardItemInstruments::DashboardItemInstruments(const ghoul::Dictionary& dictionary)
|
||||
@@ -147,24 +129,15 @@ DashboardItemInstruments::DashboardItemInstruments(const ghoul::Dictionary& dict
|
||||
)
|
||||
, _font(global::fontManager->font(KeyFontMono, 10))
|
||||
{
|
||||
documentation::testSpecificationAndThrow(
|
||||
Documentation(),
|
||||
dictionary,
|
||||
"DashboardItemInstruments"
|
||||
);
|
||||
|
||||
if (dictionary.hasKey(FontNameInfo.identifier)) {
|
||||
_fontName = dictionary.value<std::string>(FontNameInfo.identifier);
|
||||
}
|
||||
if (dictionary.hasKey(FontSizeInfo.identifier)) {
|
||||
_fontSize = static_cast<float>(dictionary.value<double>(FontSizeInfo.identifier));
|
||||
}
|
||||
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);
|
||||
});
|
||||
|
||||
@@ -152,6 +152,48 @@ namespace {
|
||||
return 0.5 * bisect(p1, half, testFunction, half);
|
||||
}
|
||||
}
|
||||
// Needs support for std::map first for the frameConversions
|
||||
// struct [[codegen::Dictionary(RenderableFov)]] Parameters {
|
||||
// // The SPICE name of the source body for which the field of view should be
|
||||
// // rendered
|
||||
// std::string body;
|
||||
//
|
||||
// // The SPICE name of the source body's frame in which the field of view should be
|
||||
// // rendered
|
||||
// std::string frame;
|
||||
//
|
||||
// struct Instrument {
|
||||
// // The SPICE name of the instrument that is rendered
|
||||
// std::string name;
|
||||
//
|
||||
// // The aberration correction that is used for this field of view. The default
|
||||
// // is 'NONE'
|
||||
// std::optional<std::string> aberration [[codegen::inlist("NONE",
|
||||
// "LT", "LT+S", "CN", "CN+S", "XLT", "XLT+S", "XCN", "XCN+S")]];
|
||||
// };
|
||||
// // A table describing the instrument whose field of view should be rendered
|
||||
// Instrument instrument;
|
||||
//
|
||||
// // A list of potential targets (specified as SPICE names) that the field of view
|
||||
// // should be tested against
|
||||
// std::vector<std::string> potentialTargets;
|
||||
//
|
||||
// // A list of frame conversions that should be registered with the SpiceManager
|
||||
// std::optional<std::vector<std::string>> frameConversions;
|
||||
//
|
||||
// // [[codegen::verbatim(LineWidthInfo.description)]]
|
||||
// std::optional<double> lineWidth;
|
||||
//
|
||||
// // [[codegen::verbatim(StandoffDistanceInfo.description)]]
|
||||
// std::optional<double> standOffDistance;
|
||||
//
|
||||
// // If this value is set to 'true' the field-of-views bounds values will be
|
||||
// // simplified on load. Bound vectors will be removed if they are the strict linear
|
||||
// // interpolation between the two neighboring vectors. This value is disabled on
|
||||
// // default
|
||||
// std::optional<bool> simplifyBounds;
|
||||
// };
|
||||
//#include "renderablefov_codegen.cpp"
|
||||
} // namespace
|
||||
|
||||
namespace openspace {
|
||||
|
||||
@@ -81,11 +81,6 @@ documentation::Documentation RenderableModelProjection::Documentation() {
|
||||
"Renderable Model Projection",
|
||||
"newhorizons_renderable_modelprojection",
|
||||
{
|
||||
{
|
||||
"Type",
|
||||
new StringEqualVerifier("RenderableModelProjection"),
|
||||
Optional::No
|
||||
},
|
||||
{
|
||||
keyGeometry,
|
||||
new ReferencingVerifier("base_geometry_model"),
|
||||
|
||||
@@ -26,6 +26,7 @@
|
||||
|
||||
#include <modules/spacecraftinstruments/spacecraftinstrumentsmodule.h>
|
||||
#include <modules/spacecraftinstruments/util/imagesequencer.h>
|
||||
#include <openspace/documentation/documentation.h>
|
||||
#include <openspace/engine/globals.h>
|
||||
#include <openspace/engine/moduleengine.h>
|
||||
#include <openspace/rendering/renderengine.h>
|
||||
@@ -40,6 +41,7 @@
|
||||
#include <ghoul/opengl/texture.h>
|
||||
#include <ghoul/opengl/textureunit.h>
|
||||
#include <glm/gtx/projection.hpp>
|
||||
#include <optional>
|
||||
|
||||
namespace {
|
||||
constexpr const char* _loggerCat = "RenderablePlaneProjection";
|
||||
@@ -50,6 +52,16 @@ namespace {
|
||||
constexpr const char* KeyName = "Name";
|
||||
constexpr const char* KeyTarget = "DefaultTarget";
|
||||
constexpr const char* GalacticFrame = "GALACTIC";
|
||||
|
||||
struct [[codegen::Dictionary(RenderablePlaneProjection)]] Parameters {
|
||||
std::optional<std::string> spacecraft;
|
||||
std::optional<std::string> instrument;
|
||||
std::optional<bool> moving;
|
||||
std::optional<std::string> name;
|
||||
std::optional<std::string> defaultTarget;
|
||||
std::optional<std::string> texture;
|
||||
};
|
||||
#include "renderableplaneprojection_codegen.cpp"
|
||||
} // namespace
|
||||
|
||||
namespace openspace {
|
||||
@@ -57,24 +69,15 @@ namespace openspace {
|
||||
RenderablePlaneProjection::RenderablePlaneProjection(const ghoul::Dictionary& dict)
|
||||
: Renderable(dict)
|
||||
{
|
||||
if (dict.hasValue<std::string>(KeySpacecraft)) {
|
||||
_spacecraft = dict.value<std::string>(KeySpacecraft);
|
||||
}
|
||||
if (dict.hasValue<std::string>(KeyInstrument)) {
|
||||
_instrument = dict.value<std::string>(KeyInstrument);
|
||||
}
|
||||
if (dict.hasValue<bool>(KeyMoving)) {
|
||||
_moving = dict.value<bool>(KeyMoving);
|
||||
}
|
||||
if (dict.hasValue<std::string>(KeyName)) {
|
||||
_name = dict.value<std::string>(KeyName);
|
||||
}
|
||||
if (dict.hasValue<std::string>(KeyTarget)) {
|
||||
_defaultTarget = dict.value<std::string>(KeyTarget);
|
||||
}
|
||||
if (dict.hasValue<std::string>(KeyTexture)) {
|
||||
_texturePath = dict.value<std::string>(KeyTexture);
|
||||
_texturePath = absPath(_texturePath);
|
||||
const Parameters p = codegen::bake<Parameters>(dict);
|
||||
_spacecraft = p.spacecraft.value_or(_spacecraft);
|
||||
_instrument = p.instrument.value_or(_instrument);
|
||||
_moving = p.moving.value_or(_moving);
|
||||
_name = p.name.value_or(_name);
|
||||
_defaultTarget = p.defaultTarget.value_or(_defaultTarget);
|
||||
|
||||
if (p.texture.has_value()) {
|
||||
_texturePath = absPath(*p.texture);
|
||||
_textureFile = std::make_unique<ghoul::filesystem::File>(_texturePath);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -145,12 +145,6 @@ documentation::Documentation RenderablePlanetProjection::Documentation() {
|
||||
"Renderable Planet Projection",
|
||||
"newhorizons_renderable_planetprojection",
|
||||
{
|
||||
{
|
||||
"Type",
|
||||
new StringEqualVerifier("RenderablePlanetProjection"),
|
||||
Optional::No,
|
||||
""
|
||||
},
|
||||
{
|
||||
KeyGeometry,
|
||||
new ReferencingVerifier("space_geometry_planet"),
|
||||
|
||||
@@ -32,7 +32,7 @@
|
||||
#include <openspace/util/updatestructures.h>
|
||||
#include <ghoul/filesystem/filesystem.h>
|
||||
#include <ghoul/opengl/programobject.h>
|
||||
#include <openspace/util/spicemanager.h>
|
||||
#include <optional>
|
||||
|
||||
namespace {
|
||||
constexpr const char* ProgramName = "ShadowCylinderProgram";
|
||||
@@ -104,85 +104,49 @@ namespace {
|
||||
"Aberration",
|
||||
"This value determines the aberration method that is used to compute the shadow "
|
||||
"cylinder."
|
||||
};
|
||||
|
||||
struct [[codegen::Dictionary(RenderableShadowCylinder)]] Parameters {
|
||||
// [[codegen::verbatim(NumberPointsInfo.description)]]
|
||||
std::optional<int> numberOfPoints [[codegen::key("AmountOfPoints")]];
|
||||
|
||||
// [[codegen::verbatim(ShadowLengthInfo.description)]]
|
||||
std::optional<float> shadowLength;
|
||||
|
||||
// [[codegen::verbatim(ShadowColorInfo.description)]]
|
||||
std::optional<glm::vec3> shadowColor;
|
||||
|
||||
enum class TerminatorType {
|
||||
Umbral [[codegen::key("UMBRAL")]],
|
||||
Penumbral [[codegen::key("PENUMBRAL")]]
|
||||
};
|
||||
// [[codegen::verbatim(TerminatorTypeInfo.description)]]
|
||||
TerminatorType terminatorType;
|
||||
|
||||
// [[codegen::verbatim(LightSourceInfo.description)]]
|
||||
std::string lightSource;
|
||||
|
||||
// [[codegen::verbatim(ObserverInfo.description)]]
|
||||
std::string observer;
|
||||
|
||||
// [[codegen::verbatim(BodyInfo.description)]]
|
||||
std::string body;
|
||||
|
||||
// [[codegen::verbatim(BodyFrameInfo.description)]]
|
||||
std::string bodyFrame;
|
||||
|
||||
// [[codegen::verbatim(AberrationInfo.description)]]
|
||||
std::string aberration [[codegen::inlist("NONE", "LT", "LT+S", "CN", "CN+S")]];
|
||||
};
|
||||
#include "renderableshadowcylinder_codegen.cpp"
|
||||
} // namespace
|
||||
|
||||
namespace openspace {
|
||||
|
||||
documentation::Documentation RenderableShadowCylinder::Documentation() {
|
||||
using namespace documentation;
|
||||
return {
|
||||
"RenderableShadowCylinder",
|
||||
"newhorizons_renderable_shadowcylinder",
|
||||
{
|
||||
{
|
||||
"Type",
|
||||
new StringEqualVerifier("RenderableShadowCylinder"),
|
||||
Optional::No,
|
||||
""
|
||||
},
|
||||
{
|
||||
NumberPointsInfo.identifier,
|
||||
new IntVerifier,
|
||||
Optional::Yes,
|
||||
NumberPointsInfo.description
|
||||
},
|
||||
{
|
||||
ShadowLengthInfo.identifier,
|
||||
new DoubleVerifier,
|
||||
Optional::Yes,
|
||||
ShadowLengthInfo.description
|
||||
},
|
||||
{
|
||||
ShadowColorInfo.identifier,
|
||||
new DoubleVector3Verifier,
|
||||
Optional::Yes,
|
||||
ShadowColorInfo.description
|
||||
},
|
||||
{
|
||||
TerminatorTypeInfo.identifier,
|
||||
new StringInListVerifier({
|
||||
// Synchronized with SpiceManager::terminatorTypeFromString
|
||||
"UMBRAL", "PENUMBRAL"
|
||||
}),
|
||||
Optional::No,
|
||||
TerminatorTypeInfo.description
|
||||
},
|
||||
{
|
||||
LightSourceInfo.identifier,
|
||||
new StringVerifier,
|
||||
Optional::No,
|
||||
LightSourceInfo.description
|
||||
},
|
||||
{
|
||||
ObserverInfo.identifier,
|
||||
new StringVerifier,
|
||||
Optional::No,
|
||||
ObserverInfo.description
|
||||
},
|
||||
{
|
||||
BodyInfo.identifier,
|
||||
new StringVerifier,
|
||||
Optional::No,
|
||||
BodyInfo.description
|
||||
},
|
||||
{
|
||||
BodyFrameInfo.identifier,
|
||||
new StringVerifier,
|
||||
Optional::No,
|
||||
BodyFrameInfo.description
|
||||
},
|
||||
{
|
||||
AberrationInfo.identifier,
|
||||
new StringInListVerifier({
|
||||
// SpiceManager::AberrationCorrection::AberrationCorrection
|
||||
"NONE", "LT", "LT+S", "CN", "CN+S"
|
||||
}),
|
||||
Optional::No,
|
||||
AberrationInfo.description
|
||||
},
|
||||
}
|
||||
};
|
||||
documentation::Documentation doc = codegen::doc<Parameters>();
|
||||
doc.id = "newhorizons_renderable_shadowcylinder";
|
||||
return doc;
|
||||
}
|
||||
|
||||
RenderableShadowCylinder::RenderableShadowCylinder(const ghoul::Dictionary& dictionary)
|
||||
@@ -200,34 +164,18 @@ RenderableShadowCylinder::RenderableShadowCylinder(const ghoul::Dictionary& dict
|
||||
, _bodyFrame(BodyFrameInfo)
|
||||
, _aberration(AberrationInfo)
|
||||
{
|
||||
documentation::testSpecificationAndThrow(
|
||||
Documentation(),
|
||||
dictionary,
|
||||
"RenderableShadowCylinder"
|
||||
);
|
||||
const Parameters p = codegen::bake<Parameters>(dictionary);
|
||||
|
||||
addProperty(_opacity);
|
||||
registerUpdateRenderBinFromOpacity();
|
||||
|
||||
if (dictionary.hasKey(NumberPointsInfo.identifier)) {
|
||||
_numberOfPoints = static_cast<int>(
|
||||
dictionary.value<double>(NumberPointsInfo.identifier)
|
||||
);
|
||||
}
|
||||
_numberOfPoints = p.numberOfPoints.value_or(_numberOfPoints);
|
||||
addProperty(_numberOfPoints);
|
||||
|
||||
|
||||
if (dictionary.hasKey(ShadowLengthInfo.identifier)) {
|
||||
_shadowLength = static_cast<float>(
|
||||
dictionary.value<double>(ShadowLengthInfo.identifier)
|
||||
);
|
||||
}
|
||||
_shadowLength = p.shadowLength.value_or(_shadowLength);
|
||||
addProperty(_shadowLength);
|
||||
|
||||
|
||||
if (dictionary.hasKey(ShadowColorInfo.identifier)) {
|
||||
_shadowColor = dictionary.value<glm::dvec3>(ShadowLengthInfo.identifier);
|
||||
}
|
||||
_shadowColor = p.shadowColor.value_or(_shadowColor);
|
||||
_shadowColor.setViewOption(properties::Property::ViewOptions::Color);
|
||||
addProperty(_shadowColor);
|
||||
|
||||
@@ -236,16 +184,21 @@ RenderableShadowCylinder::RenderableShadowCylinder(const ghoul::Dictionary& dict
|
||||
{ static_cast<int>(SpiceManager::TerminatorType::Umbral), "Umbral" },
|
||||
{ static_cast<int>(SpiceManager::TerminatorType::Penumbral), "Penumbral" }
|
||||
});
|
||||
_terminatorType = static_cast<int>(SpiceManager::terminatorTypeFromString(
|
||||
dictionary.value<std::string>(TerminatorTypeInfo.identifier)
|
||||
));
|
||||
switch (p.terminatorType) {
|
||||
case Parameters::TerminatorType::Umbral:
|
||||
_terminatorType = static_cast<int>(SpiceManager::TerminatorType::Umbral);
|
||||
break;
|
||||
case Parameters::TerminatorType::Penumbral:
|
||||
_terminatorType = static_cast<int>(SpiceManager::TerminatorType::Penumbral);
|
||||
break;
|
||||
}
|
||||
addProperty(_terminatorType);
|
||||
|
||||
|
||||
_lightSource = dictionary.value<std::string>(LightSourceInfo.identifier);
|
||||
_observer = dictionary.value<std::string>(ObserverInfo.identifier);
|
||||
_body = dictionary.value<std::string>(BodyInfo.identifier);
|
||||
_bodyFrame = dictionary.value<std::string>(BodyFrameInfo.identifier);
|
||||
_lightSource = p.lightSource;
|
||||
_observer = p.observer;
|
||||
_body = p.body;
|
||||
_bodyFrame = p.bodyFrame;
|
||||
|
||||
using T = SpiceManager::AberrationCorrection::Type;
|
||||
_aberration.addOptions({
|
||||
@@ -257,7 +210,7 @@ RenderableShadowCylinder::RenderableShadowCylinder(const ghoul::Dictionary& dict
|
||||
|
||||
});
|
||||
SpiceManager::AberrationCorrection aberration = SpiceManager::AberrationCorrection(
|
||||
dictionary.value<std::string>(AberrationInfo.identifier)
|
||||
p.aberration
|
||||
);
|
||||
_aberration = static_cast<int>(aberration.type);
|
||||
}
|
||||
|
||||
@@ -24,53 +24,43 @@
|
||||
|
||||
#include <modules/spacecraftinstruments/util/instrumentdecoder.h>
|
||||
|
||||
#include <openspace/documentation/documentation.h>
|
||||
#include <openspace/documentation/verifier.h>
|
||||
#include <ghoul/misc/assert.h>
|
||||
#include <ghoul/logging/logmanager.h>
|
||||
#include <ghoul/misc/dictionary.h>
|
||||
#include <optional>
|
||||
|
||||
namespace {
|
||||
constexpr const char* _loggerCat = "InstrumentDecoder";
|
||||
constexpr const char* KeyDetector = "DetectorType";
|
||||
constexpr const char* KeySpice = "Spice";
|
||||
constexpr const char* KeyStopCommand = "StopCommand";
|
||||
|
||||
struct [[codegen::Dictionary(InstrumentDecoder)]] Parameters {
|
||||
std::string detectorType;
|
||||
std::optional<std::string> stopCommand;
|
||||
std::vector<std::string> spice;
|
||||
};
|
||||
#include "instrumentdecoder_codegen.cpp"
|
||||
} // namespace
|
||||
|
||||
namespace openspace {
|
||||
|
||||
InstrumentDecoder::InstrumentDecoder(const ghoul::Dictionary& dictionary) {
|
||||
if (dictionary.hasValue<std::string>(KeyDetector)) {
|
||||
_type = dictionary.value<std::string>(KeyDetector);
|
||||
std::for_each(
|
||||
_type.begin(),
|
||||
_type.end(),
|
||||
[](char& in) { in = static_cast<char>(toupper(in)); }
|
||||
);
|
||||
}
|
||||
else {
|
||||
ghoul_assert(false, "Instrument has not provided detector type");
|
||||
throw ghoul::RuntimeError("Instrument has not provided detector type");
|
||||
}
|
||||
const Parameters p = codegen::bake<Parameters>(dictionary);
|
||||
_type = p.detectorType;
|
||||
std::for_each(
|
||||
_type.begin(),
|
||||
_type.end(),
|
||||
[](char& in) { in = static_cast<char>(toupper(in)); }
|
||||
);
|
||||
|
||||
if (dictionary.hasValue<std::string>(KeyStopCommand) && _type == "SCANNER") {
|
||||
_stopCommand = dictionary.value<std::string>(KeyStopCommand);
|
||||
if (p.stopCommand.has_value() && _type == "SCANNER") {
|
||||
_stopCommand = *p.stopCommand;
|
||||
}
|
||||
else {
|
||||
LWARNING("Scanner must provide stop command, please check mod file.");
|
||||
}
|
||||
|
||||
if (dictionary.hasValue<ghoul::Dictionary>(KeySpice)) {
|
||||
ghoul::Dictionary spiceDictionary = dictionary.value<ghoul::Dictionary>(KeySpice);
|
||||
|
||||
_spiceIDs.resize(spiceDictionary.size());
|
||||
for (size_t i = 0; i < _spiceIDs.size(); ++i) {
|
||||
std::string id = spiceDictionary.value<std::string>(std::to_string(i + 1));
|
||||
_spiceIDs[i] = std::move(id);
|
||||
}
|
||||
}
|
||||
else {
|
||||
ghoul_assert(false, "Instrument did not provide spice ids");
|
||||
throw ghoul::RuntimeError("Instrument has not provided detector type");
|
||||
}
|
||||
_spiceIDs = p.spice;
|
||||
}
|
||||
|
||||
const std::string& InstrumentDecoder::stopCommand() {
|
||||
|
||||
@@ -42,36 +42,12 @@
|
||||
#include <ghoul/opengl/textureunit.h>
|
||||
#include <ghoul/opengl/texture.h>
|
||||
#include <ghoul/systemcapabilities/openglcapabilitiescomponent.h>
|
||||
#include <optional>
|
||||
#include <variant>
|
||||
|
||||
namespace {
|
||||
constexpr const char* keyPotentialTargets = "PotentialTargets";
|
||||
|
||||
constexpr const char* keyInstrument = "Instrument.Name";
|
||||
constexpr const char* keyInstrumentFovy = "Instrument.Fovy";
|
||||
constexpr const char* keyInstrumentAspect = "Instrument.Aspect";
|
||||
|
||||
constexpr const char* keyTranslation = "DataInputTranslation";
|
||||
constexpr const char* keyTimesTranslation = "TimesDataInputTranslation";
|
||||
|
||||
constexpr const char* keyProjObserver = "Observer";
|
||||
constexpr const char* keyProjTarget = "Target";
|
||||
constexpr const char* keyProjAberration = "Aberration";
|
||||
|
||||
constexpr const char* keySequenceDir = "Sequence";
|
||||
constexpr const char* keyTimesSequenceDir = "TimesSequence";
|
||||
constexpr const char* keySequenceType = "SequenceType";
|
||||
|
||||
constexpr const char* keyNeedsTextureMapDilation = "TextureMap";
|
||||
constexpr const char* keyNeedsShadowing = "ShadowMap";
|
||||
constexpr const char* keyTextureMapAspectRatio = "AspectRatio";
|
||||
|
||||
constexpr const char* sequenceTypeImage = "image-sequence";
|
||||
constexpr const char* sequenceTypePlaybook = "playbook";
|
||||
constexpr const char* sequenceTypeHybrid = "hybrid";
|
||||
constexpr const char* sequenceTypeInstrumentTimes = "instrument-times";
|
||||
constexpr const char* sequenceTypeImageAndInstrumentTimes =
|
||||
"image-and-instrument-times";
|
||||
|
||||
constexpr const char* placeholderFile = "${DATA}/placeholder.png";
|
||||
|
||||
constexpr const char* _loggerCat = "ProjectionComponent";
|
||||
@@ -113,115 +89,84 @@ namespace {
|
||||
"Triggering this property applies a new size to the underlying projection "
|
||||
"texture. The old texture is resized and interpolated to fit the new size."
|
||||
};
|
||||
|
||||
struct [[codegen::Dictionary(ProjectionComponent)]] Parameters {
|
||||
// This value specifies one or more directories from which images are being used
|
||||
// for image projections. If the sequence type is set to 'playbook', this value is
|
||||
// ignored
|
||||
std::optional<std::variant<std::string, std::vector<std::string>>> sequence;
|
||||
|
||||
struct Instrument {
|
||||
// The instrument that is used to perform the projections
|
||||
std::string name [[codegen::annotation("A SPICE name of an instrument")]];
|
||||
|
||||
// The field of view in degrees along the y axis
|
||||
float fovy;
|
||||
|
||||
// The aspect ratio of the instrument in relation between x and y axis
|
||||
float aspect;
|
||||
};
|
||||
Instrument instrument;
|
||||
|
||||
enum class Type {
|
||||
ImageSequence [[codegen::key("image-sequence")]],
|
||||
Playbook [[codegen::key("playbook")]],
|
||||
Hybrid [[codegen::key("hybrid")]],
|
||||
InstrumentTimes [[codegen::key("instrument-times")]],
|
||||
ImageAndInstrumentTimes [[codegen::key("image-and-instrument-times")]]
|
||||
};
|
||||
// This value determines which type of sequencer is used for generating image
|
||||
// schedules. The 'playbook' is using a custom format designed by the New Horizons
|
||||
// team, the 'image-sequence' uses lbl files from a directory, and the 'hybrid'
|
||||
// uses both methods
|
||||
std::optional<Type> sequenceType;
|
||||
|
||||
std::optional<std::string> eventFile;
|
||||
|
||||
// The observer that is doing the projection. This has to be a valid SPICE name
|
||||
// or SPICE integer
|
||||
std::string observer
|
||||
[[codegen::annotation("A SPICE name of the observing object")]];
|
||||
|
||||
std::optional<std::string> timesSequence;
|
||||
|
||||
// The observed object that is projected on. This has to be a valid SPICE name or
|
||||
// SPICE integer
|
||||
std::string target [[codegen::annotation("A SPICE name of the observed object")]];
|
||||
|
||||
// The aberration correction that is supposed to be used for the projection. The
|
||||
// values for the correction correspond to the SPICE definition as described in
|
||||
// ftp://naif.jpl.nasa.gov/pub/naif/toolkit_docs/IDL/cspice/spkezr_c.html
|
||||
std::string aberration [[codegen::inlist("NONE", "LT", "LT+S", "CN", "CN+S",
|
||||
"XLT", "XLT+S", "XCN", "XCN+S")]];
|
||||
|
||||
// The list of potential targets that are involved with the image projection
|
||||
std::optional<std::vector<std::string>> potentialTargets;
|
||||
|
||||
// Determines whether the object requires a self-shadowing algorithm. This is
|
||||
// necessary if the object is concave and might cast a shadow on itself during
|
||||
// presentation. The default value is 'false'
|
||||
std::optional<bool> textureMap;
|
||||
|
||||
// Determines whether the object requires a self-shadowing algorithm. This is
|
||||
// necessary if the object is concave and might cast a shadow on itself during
|
||||
// presentation. The default value is 'false'
|
||||
std::optional<bool> shadowMap;
|
||||
|
||||
// Sets the desired aspect ratio of the projected texture. This might be necessary
|
||||
// as planets usually have 2x1 aspect ratios, whereas this does not hold for
|
||||
// non-planet objects (comets, asteroids, etc). The default value is '1.0'
|
||||
std::optional<float> aspectRatio;
|
||||
};
|
||||
#include "projectioncomponent_codegen.cpp"
|
||||
} // namespace
|
||||
|
||||
namespace openspace {
|
||||
|
||||
documentation::Documentation ProjectionComponent::Documentation() {
|
||||
using namespace documentation;
|
||||
return {
|
||||
"Projection Component",
|
||||
"newhorizons_projectioncomponent",
|
||||
{
|
||||
{
|
||||
keySequenceDir,
|
||||
new OrVerifier({ new StringVerifier, new StringListVerifier }),
|
||||
Optional::Yes,
|
||||
"This value specifies one or more directories from which images are "
|
||||
"being used for image projections. If the sequence type is set to "
|
||||
"'playbook', this value is ignored"
|
||||
},
|
||||
{
|
||||
keyInstrument,
|
||||
new StringAnnotationVerifier("A SPICE name of an instrument"),
|
||||
Optional::No,
|
||||
"The instrument that is used to perform the projections"
|
||||
},
|
||||
{
|
||||
keyInstrumentFovy,
|
||||
new DoubleVerifier,
|
||||
Optional::No,
|
||||
"The field of view in degrees along the y axis"
|
||||
},
|
||||
{
|
||||
keyInstrumentAspect,
|
||||
new DoubleVerifier,
|
||||
Optional::No,
|
||||
"The aspect ratio of the instrument in relation between x and y axis"
|
||||
},
|
||||
{
|
||||
keySequenceType,
|
||||
new StringInListVerifier(
|
||||
{ sequenceTypeImage, sequenceTypePlaybook, sequenceTypeHybrid,
|
||||
sequenceTypeInstrumentTimes, sequenceTypeImageAndInstrumentTimes }
|
||||
),
|
||||
Optional::Yes,
|
||||
"This value determines which type of sequencer is used for generating "
|
||||
"image schedules. The 'playbook' is using a custom format designed by "
|
||||
"the New Horizons team, the 'image-sequence' uses lbl files from a "
|
||||
"directory, and the 'hybrid' uses both methods."
|
||||
},
|
||||
{
|
||||
keyProjObserver,
|
||||
new StringAnnotationVerifier("A SPICE name of the observing object"),
|
||||
Optional::No,
|
||||
"The observer that is doing the projection. This has to be a valid SPICE "
|
||||
"name or SPICE integer."
|
||||
},
|
||||
{
|
||||
keyProjTarget,
|
||||
new StringAnnotationVerifier("A SPICE name of the observed object"),
|
||||
Optional::No,
|
||||
"The observed object that is projected on. This has to be a valid SPICE "
|
||||
"name or SPICE integer."
|
||||
},
|
||||
{
|
||||
keyProjAberration,
|
||||
new StringInListVerifier({
|
||||
// from SpiceManager::AberrationCorrection::AberrationCorrection
|
||||
"NONE", "LT", "LT+S", "CN", "CN+S", "XLT", "XLT+S", "XCN", "XCN+S"
|
||||
}),
|
||||
Optional::No,
|
||||
"The aberration correction that is supposed to be used for the "
|
||||
"projection. The values for the correction correspond to the SPICE "
|
||||
"definition as described in "
|
||||
"ftp://naif.jpl.nasa.gov/pub/naif/toolkit_docs/IDL/cspice/spkezr_c.html"
|
||||
},
|
||||
{
|
||||
keyPotentialTargets,
|
||||
new StringListVerifier,
|
||||
Optional::Yes,
|
||||
"The list of potential targets that are involved with the image "
|
||||
"projection"
|
||||
},
|
||||
{
|
||||
keyNeedsTextureMapDilation,
|
||||
new BoolVerifier,
|
||||
Optional::Yes,
|
||||
"Determines whether a dilation step of the texture map has to be "
|
||||
"performed after each projection. This is necessary if the texture of "
|
||||
"the projected object is a texture map where the borders are not "
|
||||
"touching. The default value is 'false'."
|
||||
},
|
||||
{
|
||||
keyNeedsShadowing,
|
||||
new BoolVerifier,
|
||||
Optional::Yes,
|
||||
"Determines whether the object requires a self-shadowing algorithm. This "
|
||||
"is necessary if the object is concave and might cast a shadow on itself "
|
||||
"during presentation. The default value is 'false'."
|
||||
},
|
||||
{
|
||||
keyTextureMapAspectRatio,
|
||||
new DoubleVerifier,
|
||||
Optional::Yes,
|
||||
"Sets the desired aspect ratio of the projected texture. This might be "
|
||||
"necessary as planets usually have 2x1 aspect ratios, whereas this does "
|
||||
"not hold for non-planet objects (comets, asteroids, etc). The default "
|
||||
"value is '1.0'."
|
||||
}
|
||||
}
|
||||
};
|
||||
documentation::Documentation doc = codegen::doc<Parameters>();
|
||||
doc.id = "newhorizons_projectioncomponent";
|
||||
return doc;
|
||||
}
|
||||
|
||||
ProjectionComponent::ProjectionComponent()
|
||||
@@ -244,162 +189,143 @@ ProjectionComponent::ProjectionComponent()
|
||||
void ProjectionComponent::initialize(const std::string& identifier,
|
||||
const ghoul::Dictionary& dictionary)
|
||||
{
|
||||
documentation::testSpecificationAndThrow(
|
||||
Documentation(),
|
||||
dictionary,
|
||||
"ProjectionComponent"
|
||||
);
|
||||
_instrumentID = dictionary.value<std::string>(keyInstrument);
|
||||
_projectorID = dictionary.value<std::string>(keyProjObserver);
|
||||
_projecteeID = dictionary.value<std::string>(keyProjTarget);
|
||||
_fovy = static_cast<float>(dictionary.value<double>(keyInstrumentFovy));
|
||||
_aspectRatio = static_cast<float>(dictionary.value<double>(keyInstrumentAspect));
|
||||
const Parameters p = codegen::bake<Parameters>(dictionary);
|
||||
|
||||
_aberration = SpiceManager::AberrationCorrection(
|
||||
dictionary.value<std::string>(keyProjAberration)
|
||||
);
|
||||
_instrumentID = p.instrument.name;
|
||||
_projectorID = p.observer;
|
||||
_projecteeID = p.target;
|
||||
_fovy = p.instrument.fovy;
|
||||
_aspectRatio = p.instrument.aspect;
|
||||
|
||||
if (dictionary.hasValue<ghoul::Dictionary>(keyPotentialTargets)) {
|
||||
const ghoul::Dictionary& potentialTargets = dictionary.value<ghoul::Dictionary>(
|
||||
keyPotentialTargets
|
||||
);
|
||||
_aberration = SpiceManager::AberrationCorrection(p.aberration);
|
||||
|
||||
_potentialTargets.reserve(potentialTargets.size());
|
||||
for (size_t i = 1; i <= potentialTargets.size(); ++i) {
|
||||
_potentialTargets.emplace_back(
|
||||
potentialTargets.value<std::string>(std::to_string(i))
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
if (dictionary.hasValue<bool>(keyNeedsTextureMapDilation)) {
|
||||
_dilation.isEnabled = dictionary.value<bool>(keyNeedsTextureMapDilation);
|
||||
}
|
||||
|
||||
if (dictionary.hasValue<bool>(keyNeedsShadowing)) {
|
||||
_shadowing.isEnabled = dictionary.value<bool>(keyNeedsShadowing);
|
||||
}
|
||||
|
||||
if (dictionary.hasValue<double>(keyTextureMapAspectRatio)) {
|
||||
_projectionTextureAspectRatio =
|
||||
static_cast<float>(dictionary.value<double>(keyTextureMapAspectRatio));
|
||||
}
|
||||
_potentialTargets = p.potentialTargets.value_or(_potentialTargets);
|
||||
_dilation.isEnabled = p.textureMap.value_or(_dilation.isEnabled);
|
||||
_shadowing.isEnabled = p.shadowMap.value_or(_shadowing.isEnabled);
|
||||
_projectionTextureAspectRatio = p.aspectRatio.value_or(_projectionTextureAspectRatio);
|
||||
|
||||
|
||||
if (!dictionary.hasKey(keySequenceDir)) {
|
||||
if (!p.sequence.has_value()) {
|
||||
// we are done here, the rest only applies if we do have a sequence
|
||||
return;
|
||||
}
|
||||
|
||||
std::variant<std::string, std::vector<std::string>> sequence = *p.sequence;
|
||||
|
||||
std::vector<std::string> sequenceSources;
|
||||
// Due to the documentation check above it must either be one or the other
|
||||
if (dictionary.hasValue<std::string>(keySequenceDir)) {
|
||||
sequenceSources.push_back(absPath(dictionary.value<std::string>(keySequenceDir)));
|
||||
if (std::holds_alternative<std::string>(sequence)) {
|
||||
sequenceSources.push_back(absPath(std::get<std::string>(sequence)));
|
||||
}
|
||||
else {
|
||||
ghoul::Dictionary sourcesDict = dictionary.value<ghoul::Dictionary>(
|
||||
keySequenceDir
|
||||
ghoul_assert(
|
||||
std::holds_alternative<std::vector<std::string>>(sequence),
|
||||
"Something is wrong with the generated documentation"
|
||||
);
|
||||
for (int i = 1; i <= static_cast<int>(sourcesDict.size()); ++i) {
|
||||
sequenceSources.push_back(
|
||||
absPath(sourcesDict.value<std::string>(std::to_string(i)))
|
||||
);
|
||||
sequenceSources = std::get<std::vector<std::string>>(sequence);
|
||||
for (std::string& s : sequenceSources) {
|
||||
s = absPath(s);
|
||||
}
|
||||
}
|
||||
|
||||
const std::string& sequenceType = dictionary.value<std::string>(keySequenceType);
|
||||
// Important: client must define translation-list in mod file IFF playbook
|
||||
if (!dictionary.hasKey(keyTranslation)) {
|
||||
LWARNING("No playbook translation provided, spice calls must match playbook!");
|
||||
return;
|
||||
|
||||
if (!p.sequenceType.has_value()) {
|
||||
throw ghoul::RuntimeError("Missing SequenceType");
|
||||
}
|
||||
|
||||
ghoul::Dictionary translationDictionary;
|
||||
if (dictionary.hasValue<ghoul::Dictionary>(keyTranslation)) {
|
||||
translationDictionary = dictionary.value<ghoul::Dictionary>(keyTranslation);
|
||||
}
|
||||
else {
|
||||
LWARNING("No playbook translation provided, spice calls must match playbook!");
|
||||
return;
|
||||
}
|
||||
|
||||
std::vector<std::unique_ptr<SequenceParser>> parsers;
|
||||
for (std::string& sequenceSource : sequenceSources) {
|
||||
if (sequenceType == sequenceTypePlaybook) {
|
||||
parsers.push_back(
|
||||
std::make_unique<HongKangParser>(
|
||||
identifier,
|
||||
std::move(sequenceSource),
|
||||
_projectorID,
|
||||
translationDictionary,
|
||||
_potentialTargets
|
||||
)
|
||||
);
|
||||
}
|
||||
else if (sequenceType == sequenceTypeImage) {
|
||||
parsers.push_back(
|
||||
std::make_unique<LabelParser>(
|
||||
identifier,
|
||||
std::move(sequenceSource),
|
||||
translationDictionary
|
||||
)
|
||||
);
|
||||
}
|
||||
else if (sequenceType == sequenceTypeHybrid) {
|
||||
//first read labels
|
||||
parsers.push_back(
|
||||
std::make_unique<LabelParser>(
|
||||
identifier,
|
||||
std::move(sequenceSource),
|
||||
translationDictionary
|
||||
)
|
||||
);
|
||||
|
||||
if (dictionary.hasKey("EventFile")) {
|
||||
std::string eventFile = dictionary.value<std::string>("EventFile");
|
||||
switch (*p.sequenceType) {
|
||||
case Parameters::Type::Playbook:
|
||||
parsers.push_back(
|
||||
std::make_unique<HongKangParser>(
|
||||
identifier,
|
||||
absPath(eventFile),
|
||||
std::move(sequenceSource),
|
||||
_projectorID,
|
||||
translationDictionary,
|
||||
_potentialTargets
|
||||
)
|
||||
);
|
||||
}
|
||||
else {
|
||||
LWARNING("No eventfile has been provided, please check modfiles");
|
||||
}
|
||||
}
|
||||
else if (sequenceType == sequenceTypeInstrumentTimes) {
|
||||
parsers.push_back(
|
||||
std::make_unique<InstrumentTimesParser>(
|
||||
identifier,
|
||||
std::move(sequenceSource),
|
||||
translationDictionary
|
||||
)
|
||||
);
|
||||
}
|
||||
else if (sequenceType == sequenceTypeImageAndInstrumentTimes) {
|
||||
parsers.push_back(
|
||||
std::make_unique<LabelParser>(
|
||||
identifier,
|
||||
std::move(sequenceSource),
|
||||
translationDictionary
|
||||
break;
|
||||
case Parameters::Type::ImageSequence:
|
||||
parsers.push_back(
|
||||
std::make_unique<LabelParser>(
|
||||
identifier,
|
||||
std::move(sequenceSource),
|
||||
translationDictionary
|
||||
)
|
||||
);
|
||||
);
|
||||
break;
|
||||
case Parameters::Type::Hybrid:
|
||||
// first read labels
|
||||
parsers.push_back(
|
||||
std::make_unique<LabelParser>(
|
||||
identifier,
|
||||
std::move(sequenceSource),
|
||||
translationDictionary
|
||||
)
|
||||
);
|
||||
|
||||
std::string timesSequenceSource = absPath(
|
||||
dictionary.value<std::string>(keyTimesSequenceDir)
|
||||
);
|
||||
ghoul::Dictionary timesTranslationDictionary;
|
||||
if (dictionary.hasValue<ghoul::Dictionary>(keyTimesTranslation)) {
|
||||
timesTranslationDictionary =
|
||||
dictionary.value<ghoul::Dictionary>(keyTimesTranslation);
|
||||
if (p.eventFile.has_value()) {
|
||||
parsers.push_back(
|
||||
std::make_unique<HongKangParser>(
|
||||
identifier,
|
||||
absPath(*p.eventFile),
|
||||
_projectorID,
|
||||
translationDictionary,
|
||||
_potentialTargets
|
||||
)
|
||||
);
|
||||
}
|
||||
else {
|
||||
LWARNING("No eventfile has been provided, please check modfiles");
|
||||
}
|
||||
break;
|
||||
case Parameters::Type::InstrumentTimes:
|
||||
parsers.push_back(
|
||||
std::make_unique<InstrumentTimesParser>(
|
||||
identifier,
|
||||
std::move(sequenceSource),
|
||||
translationDictionary
|
||||
)
|
||||
);
|
||||
break;
|
||||
case Parameters::Type::ImageAndInstrumentTimes:
|
||||
{
|
||||
parsers.push_back(
|
||||
std::make_unique<LabelParser>(
|
||||
identifier,
|
||||
std::move(sequenceSource),
|
||||
translationDictionary
|
||||
)
|
||||
);
|
||||
|
||||
if (!p.timesSequence.has_value()) {
|
||||
throw ghoul::RuntimeError("Could not find required TimesSequence");
|
||||
}
|
||||
ghoul::Dictionary timesTranslationDictionary;
|
||||
if (dictionary.hasValue<ghoul::Dictionary>(keyTimesTranslation)) {
|
||||
timesTranslationDictionary =
|
||||
dictionary.value<ghoul::Dictionary>(keyTimesTranslation);
|
||||
}
|
||||
|
||||
parsers.push_back(
|
||||
std::make_unique<InstrumentTimesParser>(
|
||||
identifier,
|
||||
absPath(*p.timesSequence),
|
||||
timesTranslationDictionary
|
||||
)
|
||||
);
|
||||
break;
|
||||
}
|
||||
|
||||
parsers.push_back(
|
||||
std::make_unique<InstrumentTimesParser>(
|
||||
identifier,
|
||||
std::move(timesSequenceSource),
|
||||
timesTranslationDictionary
|
||||
)
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -56,12 +56,6 @@ documentation::Documentation SyncAssetTask::documentation() {
|
||||
"SyncAssetTask",
|
||||
"sync_asset_task",
|
||||
{
|
||||
{
|
||||
"Type",
|
||||
new StringEqualVerifier("SyncAssetTask"),
|
||||
Optional::No,
|
||||
"The type of this task"
|
||||
},
|
||||
{
|
||||
KeyAsset,
|
||||
new StringAnnotationVerifier("A file path to an asset"),
|
||||
|
||||
@@ -182,12 +182,6 @@ documentation::Documentation GenerateRawVolumeTask::documentation() {
|
||||
"GenerateRawVolumeTask",
|
||||
"generate_raw_volume_task",
|
||||
{
|
||||
{
|
||||
"Type",
|
||||
new StringEqualVerifier("GenerateRawVolumeTask"),
|
||||
Optional::No,
|
||||
"The type of this task",
|
||||
},
|
||||
{
|
||||
KeyValueFunction,
|
||||
new StringAnnotationVerifier("A lua expression that returns a function "
|
||||
|
||||
@@ -0,0 +1,20 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
|
||||
<assembly xmlns="urn:schemas-microsoft-com:asm.v1" manifestVersion="1.0">
|
||||
|
||||
<!--The compatibility section will be merged from build/win/compatibility.manifest -->
|
||||
|
||||
<dependency>
|
||||
<dependentAssembly>
|
||||
<assemblyIdentity type="Win32" name="Microsoft.Windows.Common-Controls" version="6.0.0.0" processorArchitecture="*" publicKeyToken="6595b64144ccf1df" language="*"></assemblyIdentity>
|
||||
</dependentAssembly>
|
||||
</dependency>
|
||||
|
||||
<trustInfo xmlns="urn:schemas-microsoft-com:asm.v3">
|
||||
<security>
|
||||
<requestedPrivileges>
|
||||
<requestedExecutionLevel level="asInvoker" />
|
||||
</requestedPrivileges>
|
||||
</security>
|
||||
</trustInfo>
|
||||
|
||||
</assembly>
|
||||
@@ -476,6 +476,8 @@ target_precompile_headers(openspace-core PRIVATE
|
||||
<vector>
|
||||
)
|
||||
|
||||
add_dependencies(openspace-core run_codegen)
|
||||
|
||||
configure_file(
|
||||
${OPENSPACE_CMAKE_EXT_DIR}/openspace_header.template
|
||||
${CMAKE_BINARY_DIR}/_generated/include/openspace/openspace.h
|
||||
|
||||
@@ -239,7 +239,7 @@ void testSpecificationAndThrow(const Documentation& documentation,
|
||||
// Perform testing against the documentation/specification
|
||||
TestResult testResult = testSpecification(documentation, dictionary);
|
||||
if (!testResult.success) {
|
||||
throw SpecificationError(std::move(testResult), std::move(component));
|
||||
throw SpecificationError(testResult, component);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -133,11 +133,11 @@ std::string DoubleVerifier::type() const {
|
||||
return "Double";
|
||||
}
|
||||
|
||||
TestResult IntVerifier::operator()(const ghoul::Dictionary & dict,
|
||||
TestResult IntVerifier::operator()(const ghoul::Dictionary& dict,
|
||||
const std::string & key) const
|
||||
{
|
||||
if (dict.hasValue<int>(key)) {
|
||||
// We we have a key and the value is int, we are done
|
||||
// We have a key and the value is int, we are done
|
||||
return { true, {}, {} };
|
||||
}
|
||||
else {
|
||||
@@ -177,6 +177,120 @@ std::string StringVerifier::type() const {
|
||||
return "String";
|
||||
}
|
||||
|
||||
template <>
|
||||
TestResult TemplateVerifier<glm::ivec2>::operator()(const ghoul::Dictionary& dict,
|
||||
const std::string& key) const
|
||||
{
|
||||
if (dict.hasValue<glm::ivec2>(key)) {
|
||||
return { true, {}, {} };
|
||||
}
|
||||
else {
|
||||
if (dict.hasKey(key)) {
|
||||
if (dict.hasValue<glm::dvec2>(key)) {
|
||||
glm::dvec2 value = dict.value<glm::dvec2>(key);
|
||||
glm::dvec2 intPart;
|
||||
glm::bvec2 isInt = {
|
||||
modf(value.x, &intPart.x) == 0.0,
|
||||
modf(value.y, &intPart.y) == 0.0
|
||||
};
|
||||
if (isInt.x && isInt.y) {
|
||||
return { true, {}, {} };
|
||||
}
|
||||
else {
|
||||
return {
|
||||
false,
|
||||
{{ key, TestResult::Offense::Reason::WrongType }},
|
||||
{}
|
||||
};
|
||||
}
|
||||
}
|
||||
else {
|
||||
return { false, {{ key, TestResult::Offense::Reason::WrongType }}, {} };
|
||||
}
|
||||
}
|
||||
else {
|
||||
return { false, {{ key, TestResult::Offense::Reason::MissingKey }}, {} };
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
template <>
|
||||
TestResult TemplateVerifier<glm::ivec3>::operator()(const ghoul::Dictionary& dict,
|
||||
const std::string& key) const
|
||||
{
|
||||
if (dict.hasValue<glm::ivec3>(key)) {
|
||||
return { true, {}, {} };
|
||||
}
|
||||
else {
|
||||
if (dict.hasKey(key)) {
|
||||
if (dict.hasValue<glm::dvec3>(key)) {
|
||||
glm::dvec3 value = dict.value<glm::dvec3>(key);
|
||||
glm::dvec3 intPart;
|
||||
glm::bvec3 isInt = {
|
||||
modf(value.x, &intPart.x) == 0.0,
|
||||
modf(value.y, &intPart.y) == 0.0,
|
||||
modf(value.z, &intPart.z) == 0.0
|
||||
};
|
||||
if (isInt.x && isInt.y && isInt.z) {
|
||||
return { true, {}, {} };
|
||||
}
|
||||
else {
|
||||
return {
|
||||
false,
|
||||
{{ key, TestResult::Offense::Reason::WrongType }},
|
||||
{}
|
||||
};
|
||||
}
|
||||
}
|
||||
else {
|
||||
return { false, {{ key, TestResult::Offense::Reason::WrongType }}, {} };
|
||||
}
|
||||
}
|
||||
else {
|
||||
return { false, {{ key, TestResult::Offense::Reason::MissingKey }}, {} };
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
template <>
|
||||
TestResult TemplateVerifier<glm::ivec4>::operator()(const ghoul::Dictionary& dict,
|
||||
const std::string& key) const
|
||||
{
|
||||
if (dict.hasValue<glm::ivec4>(key)) {
|
||||
return { true, {}, {} };
|
||||
}
|
||||
else {
|
||||
if (dict.hasKey(key)) {
|
||||
if (dict.hasValue<glm::dvec4>(key)) {
|
||||
glm::dvec4 value = dict.value<glm::dvec4>(key);
|
||||
glm::dvec4 intPart;
|
||||
glm::bvec4 isInt = {
|
||||
modf(value.x, &intPart.x) == 0.0,
|
||||
modf(value.y, &intPart.y) == 0.0,
|
||||
modf(value.z, &intPart.z) == 0.0,
|
||||
modf(value.w, &intPart.w) == 0.0
|
||||
};
|
||||
if (isInt.x && isInt.y && isInt.z && isInt.w) {
|
||||
return { true, {}, {} };
|
||||
}
|
||||
else {
|
||||
return {
|
||||
false,
|
||||
{{ key, TestResult::Offense::Reason::WrongType }},
|
||||
{}
|
||||
};
|
||||
}
|
||||
}
|
||||
else {
|
||||
return { false, {{ key, TestResult::Offense::Reason::WrongType }}, {} };
|
||||
}
|
||||
}
|
||||
else {
|
||||
return { false, {{ key, TestResult::Offense::Reason::MissingKey }}, {} };
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
TableVerifier::TableVerifier(std::vector<DocumentationEntry> documentationEntries)
|
||||
: documentations(std::move(documentationEntries))
|
||||
{}
|
||||
|
||||
@@ -107,12 +107,6 @@ documentation::Documentation ConvertRecFileVersionTask::documentation() {
|
||||
"ConvertRecFileVersionTask",
|
||||
"convert_file_version_task",
|
||||
{
|
||||
{
|
||||
"Type",
|
||||
new StringEqualVerifier("ConvertRecFileVersionTask"),
|
||||
Optional::No,
|
||||
"The type of this task",
|
||||
},
|
||||
{
|
||||
KeyInFilePath,
|
||||
new StringAnnotationVerifier("A valid filename to convert"),
|
||||
|
||||
@@ -314,12 +314,6 @@ documentation::Documentation ConvertRecFormatTask::documentation() {
|
||||
"ConvertRecFormatTask",
|
||||
"convert_format_task",
|
||||
{
|
||||
{
|
||||
"Type",
|
||||
new StringEqualVerifier("ConvertRecFormatTask"),
|
||||
Optional::No,
|
||||
"The type of this task",
|
||||
},
|
||||
{
|
||||
KeyInFilePath,
|
||||
new StringAnnotationVerifier("A valid filename to convert"),
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user