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:
Alexander Bock
2021-02-09 09:12:43 +01:00
committed by GitHub
parent 78c0b23194
commit 6d821d4f91
104 changed files with 2939 additions and 4769 deletions
+1
View File
@@ -38,3 +38,4 @@ Thumbs.db
customization.lua
# The COMMIT info is generated everytime CMake is run
COMMIT.md
*_codegen.cpp
+3
View File
@@ -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
View File
@@ -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
View File
@@ -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__
+58 -3
View File
@@ -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 } }, {} };
+1 -1
View File
@@ -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;
+2
View File
@@ -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);
+64 -101
View File
@@ -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(
+15 -35
View File
@@ -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);
}
+71 -113
View File
@@ -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);
}
+12 -26
View File
@@ -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);
}
+12 -27
View File
@@ -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);
+12 -30
View File
@@ -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);
}
+23 -53
View File
@@ -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);
}
+199 -291
View File
@@ -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);
}
+28 -55
View File
@@ -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);
}
+26 -39
View File
@@ -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);
}
+75 -114
View File
@@ -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 {
+17 -29
View File
@@ -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
+17 -34
View File
@@ -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 {
+82 -147
View File
@@ -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;
}
+11 -24
View File
@@ -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 {
+18 -41
View File
@@ -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({
+11 -17
View File
@@ -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 {
+11 -16
View File
@@ -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
+11 -16
View File
@@ -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
+21 -34
View File
@@ -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);
}
+38 -59
View File
@@ -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
+13 -22
View File
@@ -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);
+11 -27
View File
@@ -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 {
+11 -26
View File
@@ -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,
-5
View File
@@ -327,11 +327,6 @@ documentation::Documentation ReadFitsTask::Documentation() {
"ReadFitsFile",
"gaiamission_fitsfiletorawdata",
{
{
"Type",
new StringEqualVerifier("ReadFitsTask"),
Optional::No
},
{
KeyInFileOrFolderPath,
new StringVerifier,
-5
View File
@@ -98,11 +98,6 @@ documentation::Documentation ReadSpeckTask::Documentation() {
"ReadSpeckTask",
"gaiamission_speckfiletorawdata",
{
{
"Type",
new StringEqualVerifier("ReadSpeckTask"),
Optional::No
},
{
KeyInFilePath,
new StringVerifier,
+32 -25
View File
@@ -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
View File
@@ -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 }),
@@ -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"),
+10 -21
View 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(),
+28 -62
View File
@@ -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)) {
+26 -43
View File
@@ -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);
}
+101 -190
View File
@@ -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
+31 -59
View File
@@ -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());
}
-1
View File
@@ -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 {
+39 -74
View File
@@ -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
);
}
+34 -66
View File
@@ -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 {
+18 -40
View File
@@ -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
)
);
}
}
-6
View File
@@ -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>
+2
View File
@@ -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
+1 -1
View File
@@ -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);
}
}
+116 -2
View File
@@ -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