summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDan Goodliffe <dan@randomdan.homeip.net>2023-03-02 18:18:38 +0000
committerDan Goodliffe <dan@randomdan.homeip.net>2023-03-02 18:18:38 +0000
commit98df33e0a52e086b68df2a62ce2f41cc6b67db63 (patch)
tree196300dbc07855b130e73b92077ff0e1e701a418
parentRemove to specify if the Selection pointer type is shared or not (diff)
downloadilt-98df33e0a52e086b68df2a62ce2f41cc6b67db63.tar.bz2
ilt-98df33e0a52e086b68df2a62ce2f41cc6b67db63.tar.xz
ilt-98df33e0a52e086b68df2a62ce2f41cc6b67db63.zip
Parse colour values as they're read
-rw-r--r--assetFactory/assetFactory.cpp32
-rw-r--r--assetFactory/assetFactory.h4
-rw-r--r--assetFactory/modelFactoryMesh.h3
-rw-r--r--assetFactory/style.cpp72
-rw-r--r--assetFactory/style.h18
-rw-r--r--assetFactory/use.cpp3
-rw-r--r--test/test-assetFactory.cpp14
7 files changed, 83 insertions, 63 deletions
diff --git a/assetFactory/assetFactory.cpp b/assetFactory/assetFactory.cpp
index 016f29e..70f5337 100644
--- a/assetFactory/assetFactory.cpp
+++ b/assetFactory/assetFactory.cpp
@@ -30,12 +30,12 @@ AssetFactory::parseX11RGB(const char * path)
{
filesystem::FileStar rgb {path, "r"};
Colours out;
- glm::u8vec3 colour;
+ Colour colour;
char inname[BUFSIZ];
- while (fscanf(rgb, "%hhu %hhu %hhu %[^\n\r]s", &colour.r, &colour.g, &colour.b, inname) == 4) {
+ while (fscanf(rgb, "%f %f %f %[^\n\r]s", &colour.r, &colour.g, &colour.b, inname) == 4) {
std::string name {inname};
normalizeColourName(name);
- out.emplace(std::move(name), colour);
+ out.emplace(std::move(name), colour / 255.f);
}
return out;
}
@@ -49,6 +49,32 @@ AssetFactory::normalizeColourName(std::string & name)
};
}
+AssetFactory::ColourAlpha
+AssetFactory::parseColour(std::string_view in) const
+{
+ if (in.empty()) {
+ throw std::runtime_error("Empty colour specification");
+ }
+ if (in[0] == '#') {
+ if (in.length() > 9 || in.length() % 2 == 0) {
+ throw std::runtime_error("Invalid hex colour specification");
+ }
+ ColourAlpha out {0, 0, 0, 1};
+ std::generate_n(&out.r, (in.length() - 1) / 2, [in = in.data() + 1]() mutable {
+ uint8_t channel;
+ std::from_chars(in, in + 2, channel, 16);
+ in += 2;
+ return static_cast<float>(channel) / 255.f;
+ });
+ return out;
+ }
+ if (auto mf = std::dynamic_pointer_cast<const AssetFactory>(Persistence::sharedObjects.at("assetFactory"))) {
+ if (const auto colour = mf->colours.find(in); colour != mf->colours.end()) {
+ return {colour->second, 1};
+ }
+ }
+ throw std::runtime_error("No such asset factory colour");
+}
bool
AssetFactory::persist(Persistence::PersistenceStore & store)
{
diff --git a/assetFactory/assetFactory.h b/assetFactory/assetFactory.h
index 42082eb..2bd576b 100644
--- a/assetFactory/assetFactory.h
+++ b/assetFactory/assetFactory.h
@@ -22,11 +22,13 @@ class AssetFactory : public Persistence::Persistable {
public:
using Shapes = std::map<std::string, Shape::Ptr, std::less<>>;
using Assets = std::map<std::string, Asset::Ptr, std::less<>>;
- using Colour = glm::u8vec3;
+ using Colour = glm::vec3;
+ using ColourAlpha = glm::vec4;
using Colours = std::map<std::string, Colour, std::less<>>;
AssetFactory();
[[nodiscard]] static std::shared_ptr<AssetFactory> loadXML(const std::filesystem::path &);
+ [[nodiscard]] ColourAlpha parseColour(std::string_view) const;
Shapes shapes;
Assets assets;
diff --git a/assetFactory/modelFactoryMesh.h b/assetFactory/modelFactoryMesh.h
index b4f5254..258913b 100644
--- a/assetFactory/modelFactoryMesh.h
+++ b/assetFactory/modelFactoryMesh.h
@@ -5,6 +5,7 @@
#include <OpenMesh/Core/Mesh/Traits.hh>
#include <glm/geometric.hpp>
#include <glm/vec3.hpp>
+#include <glm/vec4.hpp>
namespace OpenMesh {
template<typename Scalar, int DIM> struct glmvec : public VectorT<Scalar, DIM> {
@@ -25,7 +26,7 @@ struct ModelFactoryTraits : public OpenMesh::DefaultTraits {
VertexAttributes(OpenMesh::Attributes::Normal | OpenMesh::Attributes::Status);
using Point = OpenMesh::glmvec<float, 3>;
using Normal = OpenMesh::glmvec<float, 3>;
- using Color = OpenMesh::glmvec<float, 4>;
+ using Color = glm::vec4;
};
struct ModelFactoryMesh : public OpenMesh::PolyMesh_ArrayKernelT<ModelFactoryTraits> {
diff --git a/assetFactory/style.cpp b/assetFactory/style.cpp
index d2977a7..b2a2cf7 100644
--- a/assetFactory/style.cpp
+++ b/assetFactory/style.cpp
@@ -1,41 +1,16 @@
#include "style.h"
#include "assetFactory.h"
-ModelFactoryMesh::Color
-Style::parseColour(const std::string_view & in)
-{
- if (in.empty()) {
- throw std::runtime_error("Empty colour specification");
- }
- if (in[0] == '#') {
- if (in.length() > 9 || in.length() % 2 == 0) {
- throw std::runtime_error("Invalid hex colour specification");
- }
- ModelFactoryMesh::Color out {0, 0, 0, 1};
- std::generate_n(out.begin(), (in.length() - 1) / 2, [in = in.data() + 1]() mutable {
- uint8_t channel;
- std::from_chars(in, in + 2, channel, 16);
- in += 2;
- return static_cast<float>(channel) / 256.F;
- });
- return out;
- }
- if (auto mf = std::dynamic_pointer_cast<const AssetFactory>(Persistence::sharedObjects.at("assetFactory"))) {
- if (const auto colour = mf->colours.find(in); colour != mf->colours.end()) {
- const auto out = glm::vec3 {colour->second} / 256.F;
- return {out.r, out.g, out.b, 1.f};
- }
- }
- throw std::runtime_error("No such asset factory colour");
-}
-
void
Style::applyStyle(ModelFactoryMesh & mesh, const StyleStack & parents, const Shape::CreatedFaces & faces) const
{
- if (const auto effectiveColour = getProperty(parents, &Style::colour); !effectiveColour.empty()) {
- const auto parsedColour = parseColour(effectiveColour);
+ if (const auto effectiveColour = getProperty(parents, &Style::colour,
+ [](auto && style) {
+ return style->colour.a > 0;
+ });
+ effectiveColour.has_value()) {
for (const auto & face : faces) {
- mesh.set_color(face.second, parsedColour);
+ mesh.set_color(face.second, effectiveColour->get());
}
}
}
@@ -43,27 +18,30 @@ Style::applyStyle(ModelFactoryMesh & mesh, const StyleStack & parents, const Sha
void
Style::applyStyle(ModelFactoryMesh & mesh, const StyleStack & parents, const ModelFactoryMesh::FaceHandle & face) const
{
- if (const auto effectiveColour = getProperty(parents, &Style::colour); !effectiveColour.empty()) {
- const auto parsedColour = parseColour(effectiveColour);
- mesh.set_color(face, parsedColour);
- }
-}
-
-std::string_view
-Style::getProperty(const StyleStack & parents, std::string Style::*member)
-{
- if (const auto itr = std::find_if(parents.rbegin(), parents.rend(),
- [&member](auto && s) {
- return !(s->*member).empty();
+ if (const auto effectiveColour = getProperty(parents, &Style::colour,
+ [](auto && style) {
+ return style->colour.a > 0;
});
- itr != parents.rend()) {
- return (*itr)->*member;
+ effectiveColour.has_value()) {
+ mesh.set_color(face, effectiveColour->get());
}
- return {};
}
bool
Style::persist(Persistence::PersistenceStore & store)
{
- return STORE_MEMBER(colour);
+ struct ColourParser : public Persistence::SelectionV<ColourAlpha> {
+ using Persistence::SelectionV<ColourAlpha>::SelectionV;
+ using Persistence::SelectionV<ColourAlpha>::setValue;
+ void
+ setValue(std::string && str) override
+ {
+ if (auto mf
+ = std::dynamic_pointer_cast<const AssetFactory>(Persistence::sharedObjects.at("assetFactory"))) {
+ v = mf->parseColour(str);
+ }
+ }
+ };
+
+ return STORE_HELPER(colour, ColourParser);
}
diff --git a/assetFactory/style.h b/assetFactory/style.h
index 0c7ad5a..e8fd012 100644
--- a/assetFactory/style.h
+++ b/assetFactory/style.h
@@ -3,19 +3,31 @@
#include "modelFactoryMesh.h"
#include "persistence.h"
#include "shape.h"
+#include <optional>
#include <string>
+#include <utility>
class Style {
public:
using StyleStack = std::vector<const Style *>;
+ using Colour = glm::vec3;
+ using ColourAlpha = glm::vec4;
- static ModelFactoryMesh::Color parseColour(const std::string_view &);
void applyStyle(ModelFactoryMesh &, const StyleStack & parents, const Shape::CreatedFaces &) const;
void applyStyle(ModelFactoryMesh &, const StyleStack & parents, const ModelFactoryMesh::FaceHandle &) const;
- static std::string_view getProperty(const StyleStack & parents, std::string Style::*member);
+ template<typename T>
+ static std::optional<std::reference_wrapper<const T>>
+ getProperty(const StyleStack & parents, T Style::*member, auto && test)
+ {
+ if (const auto itr = std::find_if(parents.rbegin(), parents.rend(), std::forward<decltype(test)>(test));
+ itr != parents.rend()) {
+ return (*itr)->*member;
+ }
+ return {};
+ }
- std::string colour;
+ ColourAlpha colour {};
protected:
bool persist(Persistence::PersistenceStore & store);
diff --git a/assetFactory/use.cpp b/assetFactory/use.cpp
index a6fac5c..53fc9b9 100644
--- a/assetFactory/use.cpp
+++ b/assetFactory/use.cpp
@@ -18,7 +18,8 @@ struct Lookup : public Persistence::SelectionV<Shape::CPtr> {
void
setValue(std::string && str) override
{
- if (auto mf = std::dynamic_pointer_cast<const AssetFactory>(Persistence::sharedObjects.at("assetFactory"))) {
+ if (auto mf = std::dynamic_pointer_cast<const AssetFactory>(
+ Persistence::sharedObjects.at("assetFactory"))) {
v = mf->shapes.at(str);
}
}
diff --git a/test/test-assetFactory.cpp b/test/test-assetFactory.cpp
index 89f6bf0..8feb831 100644
--- a/test/test-assetFactory.cpp
+++ b/test/test-assetFactory.cpp
@@ -76,7 +76,7 @@ BOOST_AUTO_TEST_CASE(brush47)
wheelCylinder->position = {0, 0, 0.571};
wheelCylinder->scale = {1.142, 1.142, 0.07};
wheelCylinder->rotation = {0, 0, half_pi};
- wheelCylinder->colour = "#2C3539";
+ wheelCylinder->colour = assetFactory.parseColour("#2C3539");
}
assetFactory.shapes.emplace(wheel->id, wheel);
}
@@ -120,10 +120,10 @@ BOOST_AUTO_TEST_CASE(brush47)
bodyLower->type = assetFactory.shapes.at("cuboid");
bodyLower->position = {0, 0, 1.2};
bodyLower->scale = {2.69, 19.38, 1.5};
- bodyLower->colour = "#1111DD";
+ bodyLower->colour = assetFactory.parseColour("#1111DD");
auto & bottom = bodyLower->faceControllers["bottom"];
bottom = std::make_unique<FaceController>();
- bottom->colour = "#2C3539";
+ bottom->colour = assetFactory.parseColour("#2C3539");
auto & bodyUpper = bodyLower->faceControllers["top"];
bodyUpper = std::make_unique<FaceController>();
bodyUpper->type = "extrude";
@@ -140,7 +140,7 @@ BOOST_AUTO_TEST_CASE(brush47)
batteryBox->type = assetFactory.shapes.at("cuboid");
batteryBox->position = {0, 0, .2};
batteryBox->scale = {2.6, 4.5, 1};
- batteryBox->colour = "#2C3539";
+ batteryBox->colour = assetFactory.parseColour("#2C3539");
}
}
std::transform(factoryMeshes.begin(), factoryMeshes.end(), std::back_inserter(meshes.objects),
@@ -206,7 +206,7 @@ BOOST_AUTO_TEST_CASE(parseX11RGB)
{
const auto parsedColours = AssetFactory::parseX11RGB(FIXTURESDIR "rgb.txt");
BOOST_REQUIRE_EQUAL(parsedColours.size(), 20);
- BOOST_CHECK_EQUAL(parsedColours.at("cyan"), AssetFactory::Colour(0, 255, 255));
- BOOST_CHECK_EQUAL(parsedColours.at("slategrey"), AssetFactory::Colour(112, 128, 144));
- BOOST_CHECK_EQUAL(parsedColours.at("lightsteelblue1"), AssetFactory::Colour(202, 225, 255));
+ BOOST_CHECK_CLOSE_VEC(parsedColours.at("cyan"), AssetFactory::Colour(0, 1, 1));
+ BOOST_CHECK_CLOSE_VEC(parsedColours.at("slategrey"), AssetFactory::Colour(0.44F, 0.5, 0.56F));
+ BOOST_CHECK_CLOSE_VEC(parsedColours.at("lightsteelblue1"), AssetFactory::Colour(0.79, 0.88, 1));
}