From afd484044d1810841f5f2d4e461b8d548fbac108 Mon Sep 17 00:00:00 2001 From: Alexander Bock Date: Fri, 12 Feb 2021 12:59:00 +0100 Subject: [PATCH] Better support for colors in dictionaries (closes #1489) - Add a new Color3Verifier and Color4Verifier that checks components to be in [0,1] - Update codegen to add a new attribute [[codegen::color()]] to mark a vec3/vec4 to be a color value - Update RenderableTrail to use the new verion --- include/openspace/documentation/verifier.h | 128 +++++++++---------- modules/base/rendering/renderabletrail.cpp | 136 ++++++++------------- src/documentation/verifier.cpp | 67 ++++++++++ support/coding/codegen | 2 +- 4 files changed, 179 insertions(+), 154 deletions(-) diff --git a/include/openspace/documentation/verifier.h b/include/openspace/documentation/verifier.h index 4817be5492..f4af4228a9 100644 --- a/include/openspace/documentation/verifier.h +++ b/include/openspace/documentation/verifier.h @@ -243,39 +243,48 @@ struct IntListVerifier : public TableVerifier { */ struct VectorVerifier {}; -/** - * This Verifier checks whether the value is of type glm::tvec2 - */ +/// This Verifier checks whether the value is of type glm::tvec2 template struct Vector2Verifier : public TemplateVerifier>, public VectorVerifier { std::string type() const override; }; -/** - * This Verifier checks whether the value is of type glm::tvec3 - */ +/// This Verifier checks whether the value is of type glm::tvec3 template struct Vector3Verifier : public TemplateVerifier>, public VectorVerifier { std::string type() const override; }; -/** - * This Verifier checks whether the value is of type glm::tvec4 - */ +/// This Verifier checks whether the value is of type glm::tvec4 template struct Vector4Verifier : public TemplateVerifier>, public VectorVerifier { std::string type() const override; }; +struct Color3Verifier : public Vector3Verifier { + TestResult operator()(const ghoul::Dictionary& dictionary, + const std::string& key) const override; + + std::string type() const override; +}; + +struct Color4Verifier : public Vector4Verifier { + TestResult operator()(const ghoul::Dictionary& dictionary, + const std::string& key) const override; + + std::string type() const override; +}; + /** * A Verifier that checks whether all values contained in a Table are of * type glm::tvec2 */ template struct Vector2ListVerifier : public TableVerifier { - Vector2ListVerifier(std::string elementDocumentation = "") : TableVerifier({ + Vector2ListVerifier(std::string elementDocumentation = "") + : TableVerifier({ { "*", new Vector2Verifier, Optional::No, std::move(elementDocumentation) } - }) + }) {} std::string type() const override { @@ -289,9 +298,10 @@ struct Vector2ListVerifier : public TableVerifier { */ template struct Vector3ListVerifier : public TableVerifier { - Vector3ListVerifier(std::string elementDocumentation = "") : TableVerifier({ - { "*", new Vector3Verifier, Optional::No, std::move(elementDocumentation) } - }) + Vector3ListVerifier(std::string elementDocumentation = "") + : TableVerifier({ + { "*", new Vector3Verifier, Optional::No, std::move(elementDocumentation) } + }) {} std::string type() const override { @@ -305,15 +315,17 @@ struct Vector3ListVerifier : public TableVerifier { */ template struct Vector4ListVerifier : public TableVerifier { - Vector4ListVerifier(std::string elementDocumentation = "") : TableVerifier({ - { "*", new Vector4Verifier, Optional::No, std::move(elementDocumentation) } - }) + Vector4ListVerifier(std::string elementDocumentation = "") + : TableVerifier({ + { "*", new Vector4Verifier, Optional::No, std::move(elementDocumentation) } + }) {} std::string type() const override { return "List of ints"; } }; + //---------------------------------------------------------------------------------------- // Matrix verifiers //---------------------------------------------------------------------------------------- @@ -330,8 +342,7 @@ struct MatrixVerifier {}; * This Verifier checks whether the value is of type glm::mat2x2 */ template -struct Matrix2x2Verifier : - public TemplateVerifier>, public MatrixVerifier +struct Matrix2x2Verifier : public TemplateVerifier>, public MatrixVerifier { std::string type() const override; }; @@ -340,8 +351,8 @@ struct Matrix2x2Verifier : * This Verifier checks whether the value is of type glm::mat2x3 */ template -struct Matrix2x3Verifier : - public TemplateVerifier>, public MatrixVerifier { +struct Matrix2x3Verifier : public TemplateVerifier>, public MatrixVerifier +{ std::string type() const override; }; @@ -349,8 +360,8 @@ struct Matrix2x3Verifier : * This Verifier checks whether the value is of type glm::mat2x4 */ template -struct Matrix2x4Verifier : - public TemplateVerifier>, public MatrixVerifier { +struct Matrix2x4Verifier : public TemplateVerifier>, public MatrixVerifier +{ std::string type() const override; }; @@ -358,8 +369,8 @@ struct Matrix2x4Verifier : * This Verifier checks whether the value is of type glm::mat3x2 */ template -struct Matrix3x2Verifier : - public TemplateVerifier>, public MatrixVerifier { +struct Matrix3x2Verifier : public TemplateVerifier>, public MatrixVerifier +{ std::string type() const override; }; @@ -367,8 +378,8 @@ struct Matrix3x2Verifier : * This Verifier checks whether the value is of type glm::mat3x3 */ template -struct Matrix3x3Verifier : - public TemplateVerifier>, public MatrixVerifier { +struct Matrix3x3Verifier : public TemplateVerifier>, public MatrixVerifier +{ std::string type() const override; }; @@ -376,8 +387,8 @@ struct Matrix3x3Verifier : * This Verifier checks whether the value is of type glm::mat3x4 */ template -struct Matrix3x4Verifier : - public TemplateVerifier>, public MatrixVerifier { +struct Matrix3x4Verifier : public TemplateVerifier>, public MatrixVerifier +{ std::string type() const override; }; @@ -385,8 +396,8 @@ struct Matrix3x4Verifier : * This Verifier checks whether the value is of type glm::mat4x2 */ template -struct Matrix4x2Verifier : - public TemplateVerifier>, public MatrixVerifier { +struct Matrix4x2Verifier : public TemplateVerifier>, public MatrixVerifier +{ std::string type() const override; }; @@ -394,8 +405,8 @@ struct Matrix4x2Verifier : * This Verifier checks whether the value is of type glm::mat4x3 */ template -struct Matrix4x3Verifier : - public TemplateVerifier>, public MatrixVerifier { +struct Matrix4x3Verifier : public TemplateVerifier>, public MatrixVerifier +{ std::string type() const override; }; @@ -403,8 +414,8 @@ struct Matrix4x3Verifier : * This Verifier checks whether the value is of type glm::mat4x4 */ template -struct Matrix4x4Verifier : - public TemplateVerifier>, public MatrixVerifier { +struct Matrix4x4Verifier : public TemplateVerifier>, public MatrixVerifier +{ std::string type() const override; }; @@ -465,18 +476,11 @@ struct OperatorVerifier : public T { */ template struct LessVerifier : public OperatorVerifier> { + static_assert(!std::is_base_of::value, "T cannot be BoolVerifier"); static_assert( - !std::is_base_of::value, - "T cannot be BoolVerifier" - ); - static_assert( - !std::is_base_of::value, - "T cannot be StringVerifier" - ); - static_assert( - !std::is_base_of::value, - "T cannot be TableVerifier" + !std::is_base_of::value, "T cannot be StringVerifier" ); + static_assert(!std::is_base_of::value, "T cannot be TableVerifier"); static_assert( !std::is_base_of::value, "T cannot be VectorVerifier" @@ -496,18 +500,12 @@ struct LessVerifier : public OperatorVerifier> { */ template struct LessEqualVerifier : public OperatorVerifier> { - static_assert( - !std::is_base_of::value, - "T cannot be BoolVerifier" - ); + static_assert(!std::is_base_of::value, "T cannot be BoolVerifier"); static_assert( !std::is_base_of::value, "T cannot be StringVerifier" ); - static_assert( - !std::is_base_of::value, - "T cannot be TableVerifier" - ); + static_assert(!std::is_base_of::value, "T cannot be TableVerifier"); static_assert( !std::is_base_of::value, "T cannot be VectorVerifier" @@ -527,22 +525,16 @@ struct LessEqualVerifier : public OperatorVerifier struct GreaterVerifier : public OperatorVerifier> { - static_assert( - !std::is_base_of::value, - "T cannot be BoolVerifier" - ); + static_assert(!std::is_base_of::value, "T cannot be BoolVerifier"); static_assert( !std::is_base_of::value, "T cannot be StringVerifier" - ); - static_assert( - !std::is_base_of::value, - "T cannot be TableVerifier" - ); + ); + static_assert(!std::is_base_of::value, "T cannot be TableVerifier"); static_assert( !std::is_base_of::value, "T cannot be VectorVerifier" - ); + ); using OperatorVerifier>::OperatorVerifier; @@ -560,18 +552,12 @@ template struct GreaterEqualVerifier : public OperatorVerifier> { - static_assert( - !std::is_base_of::value, - "T cannot be BoolVerifier" - ); + static_assert(!std::is_base_of::value, "T cannot be BoolVerifier"); static_assert( !std::is_base_of::value, "T cannot be StringVerifier" ); - static_assert( - !std::is_base_of::value, - "T cannot be TableVerifier" - ); + static_assert(!std::is_base_of::value, "T cannot be TableVerifier"); static_assert( !std::is_base_of::value, "T cannot be VectorVerifier" diff --git a/modules/base/rendering/renderabletrail.cpp b/modules/base/rendering/renderabletrail.cpp index 12fd349498..42147ba54e 100644 --- a/modules/base/rendering/renderabletrail.cpp +++ b/modules/base/rendering/renderabletrail.cpp @@ -35,6 +35,7 @@ #include #include #include +#include namespace { constexpr const char* ProgramName = "EphemerisProgram"; @@ -144,64 +145,44 @@ namespace { "atmospheres if needed." }; + struct [[codegen::Dictionary(RenderableTrail)]] Parameters { + // This object is used to compute locations along the path. Any Translation object + // can be used here + std::monostate translation [[codegen::reference("core_transform_translation")]]; + + // [[codegen::verbatim(LineColorInfo.description)]] + glm::vec3 color [[codegen::color()]]; + + // [[codegen::verbatim(EnableFadeInfo.description)]] + std::optional enableFade; + + // [[codegen::verbatim(FadeInfo.description)]] + std::optional fade; + + // [[codegen::verbatim(LineWidthInfo.description)]] + std::optional lineWidth; + + // [[codegen::verbatim(PointSizeInfo.description)]] + std::optional pointSize; + + enum class RenderingMode { + Lines, + Points, + LinesPoints [[codegen::key("Lines+Points")]], + PointsLines [[codegen::key("Lines+Points")]] + }; + // [[codegen::verbatim(RenderingModeInfo.description)]] + std::optional renderingMode [[codegen::key("Rendering")]]; + }; +#include "renderabletrail_codegen.cpp" } // namespace namespace openspace { documentation::Documentation RenderableTrail::Documentation() { - using namespace documentation; - return { - "RenderableTrail", - "base_renderable_renderabletrail", - { - { - KeyTranslation, - new ReferencingVerifier("core_transform_translation"), - Optional::No, - "This object is used to compute locations along the path. Any " - "Translation object can be used here." - }, - { - LineColorInfo.identifier, - new DoubleVector3Verifier, - Optional::No, - LineColorInfo.description - }, - { - EnableFadeInfo.identifier, - new BoolVerifier, - Optional::Yes, - EnableFadeInfo.description - }, - { - FadeInfo.identifier, - new DoubleVerifier, - Optional::Yes, - FadeInfo.description - }, - { - LineWidthInfo.identifier, - new DoubleVerifier, - Optional::Yes, - LineWidthInfo.description - }, - { - PointSizeInfo.identifier, - new DoubleVerifier, - Optional::Yes, - PointSizeInfo.description - }, - { - RenderingModeInfo.identifier, - new StringInListVerifier( - // Taken from the RenderingModeConversion map above - { "Lines", "Points", "Lines+Points", "Points+Lines" } - ), - Optional::Yes, - RenderingModeInfo.description - } - } - }; + documentation::Documentation doc = codegen::doc(); + doc.id = "base_renderable_renderabletrail"; + return doc; } RenderableTrail::Appearance::Appearance() @@ -233,6 +214,8 @@ RenderableTrail::Appearance::Appearance() RenderableTrail::RenderableTrail(const ghoul::Dictionary& dictionary) : Renderable(dictionary) { + const Parameters p = codegen::bake(dictionary); + setRenderBin(RenderBin::Overlay); addProperty(_opacity); @@ -241,36 +224,25 @@ RenderableTrail::RenderableTrail(const ghoul::Dictionary& dictionary) ); addPropertySubOwner(_translation.get()); - _appearance.lineColor = dictionary.value(LineColorInfo.identifier); + _appearance.lineColor = p.color; + _appearance.useLineFade = p.enableFade.value_or(_appearance.useLineFade); + _appearance.lineFade = p.fade.value_or(_appearance.lineFade); + _appearance.lineWidth = p.lineWidth.value_or(_appearance.lineWidth); + _appearance.pointSize = p.pointSize.value_or(_appearance.pointSize); - if (dictionary.hasValue(EnableFadeInfo.identifier)) { - _appearance.useLineFade = dictionary.value(EnableFadeInfo.identifier); - } - - if (dictionary.hasValue(FadeInfo.identifier)) { - _appearance.lineFade = static_cast( - dictionary.value(FadeInfo.identifier) - ); - } - - if (dictionary.hasValue(LineWidthInfo.identifier)) { - _appearance.lineWidth = static_cast(dictionary.value( - LineWidthInfo.identifier - )); - } - - if (dictionary.hasValue(PointSizeInfo.identifier)) { - _appearance.pointSize = static_cast( - dictionary.value(PointSizeInfo.identifier) - ); - } - - // This map is not accessed out of order as long as the Documentation is adapted - // whenever the map changes. The documentation will check for valid values - if (dictionary.hasValue(RenderingModeInfo.identifier)) { - _appearance.renderingModes = RenderingModeConversion.at( - dictionary.value(RenderingModeInfo.identifier) - ); + if (p.renderingMode.has_value()) { + switch (*p.renderingMode) { + case Parameters::RenderingMode::Lines: + _appearance.renderingModes = RenderingModeLines; + break; + case Parameters::RenderingMode::Points: + _appearance.renderingModes = RenderingModePoints; + break; + case Parameters::RenderingMode::LinesPoints: + case Parameters::RenderingMode::PointsLines: + _appearance.renderingModes = RenderingModeLinesPoints; + break; + } } else { _appearance.renderingModes = RenderingModeLines; diff --git a/src/documentation/verifier.cpp b/src/documentation/verifier.cpp index 3cea6786bc..780b5ea14f 100644 --- a/src/documentation/verifier.cpp +++ b/src/documentation/verifier.cpp @@ -177,6 +177,73 @@ std::string StringVerifier::type() const { return "String"; } +TestResult Color3Verifier::operator()(const ghoul::Dictionary& dictionary, + const std::string& key) const +{ + TestResult res = Vector3Verifier::operator()(dictionary, key); + if (!res.success) { + return res; + } + + glm::dvec3 values = dictionary.value(key); + if (values.x < 0.0 || values.x > 1.0) { + res.success = false; + res.offenses.push_back({ key + ".x", TestResult::Offense::Reason::Verification }); + } + + if (values.y < 0.0 || values.y > 1.0) { + res.success = false; + res.offenses.push_back({ key + ".y", TestResult::Offense::Reason::Verification }); + } + + if (values.z < 0.0 || values.z > 1.0) { + res.success = false; + res.offenses.push_back({ key + ".z", TestResult::Offense::Reason::Verification }); + } + + return res; +} + +std::string Color3Verifier::type() const { + return std::string("Color3"); +} + +TestResult Color4Verifier::operator()(const ghoul::Dictionary& dictionary, + const std::string& key) const +{ + TestResult res = Vector4Verifier::operator()(dictionary, key); + if (!res.success) { + return res; + } + + std::vector values = dictionary.value>(key); + if (values[0] < 0.0 || values[0] > 1.0) { + res.success = false; + res.offenses.push_back({ key + ".x", TestResult::Offense::Reason::Verification }); + } + + if (values[1] < 0.0 || values[1] > 1.0) { + res.success = false; + res.offenses.push_back({ key + ".y", TestResult::Offense::Reason::Verification }); + } + + if (values[2] < 0.0 || values[2] > 1.0) { + res.success = false; + res.offenses.push_back({ key + ".z", TestResult::Offense::Reason::Verification }); + } + + if (values[3] < 0.0 || values[3] > 1.0) { + res.success = false; + res.offenses.push_back({ key + ".a", TestResult::Offense::Reason::Verification }); + } + + return res; +} + +std::string Color4Verifier::type() const { + return std::string("Color4"); +} + template <> TestResult TemplateVerifier::operator()(const ghoul::Dictionary& dict, const std::string& key) const diff --git a/support/coding/codegen b/support/coding/codegen index 1e942f53f1..14ed29d516 160000 --- a/support/coding/codegen +++ b/support/coding/codegen @@ -1 +1 @@ -Subproject commit 1e942f53f1e9543bc5040c2a8d52eeea1559b788 +Subproject commit 14ed29d516c47151e5601a119ed68e7151c12ef5