src/linetypes/propertygenerics.h

changeset 89
7abaf1d64719
child 117
121a40d5e34c
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/linetypes/propertygenerics.h	Mon May 11 12:18:59 2020 +0300
@@ -0,0 +1,153 @@
+#pragma once
+#include "main.h"
+#include "colors.h"
+
+class Vec3Editor;
+class MatrixEditor;
+
+namespace ldraw
+{
+	enum class Property;
+	struct PropertyKeyValue;
+	template<Property property>
+	struct PropertyTraits
+	{
+		static constexpr bool defined = false;
+	};
+}
+
+/**
+ * Different properties
+ */
+enum class ldraw::Property
+{
+	Color, // Color of the object
+	Text, // Text contained in a comment
+	Point0, // First vertex in a polygon or edge line
+	Point1, // Second vertex in a polygon or edge line
+	Point2, // Third vertex in a polygon
+	Point3, // Fourth vertex in a quadrilateral
+	Transformation, // 4x4 transformation matrix of a subfile reference
+	ReferenceName, // Subfile reference name
+	IsInverted, // Whether or not the object has been inverted with BFC INVERTNEXT
+	ErrorMessage // For error lines, why parsing failed
+};
+
+Q_DECLARE_METATYPE(ldraw::Property)
+
+// Mapping of properties to types
+#define LDFORGE_DEFINE_PROPERTY_TYPE(PROPERTY, TYPE) \
+	namespace ldraw \
+	{ \
+		template<> struct PropertyTraits<ldraw::Property::PROPERTY> \
+		{ \
+			using type = TYPE; \
+			static constexpr std::array<char, 256> name{#PROPERTY}; \
+			static constexpr bool defined = true; \
+		}; \
+	}
+
+LDFORGE_DEFINE_PROPERTY_TYPE(Color, ldraw::Color)
+LDFORGE_DEFINE_PROPERTY_TYPE(Text, QString)
+LDFORGE_DEFINE_PROPERTY_TYPE(Point0, glm::vec3)
+LDFORGE_DEFINE_PROPERTY_TYPE(Point1, glm::vec3)
+LDFORGE_DEFINE_PROPERTY_TYPE(Point2, glm::vec3)
+LDFORGE_DEFINE_PROPERTY_TYPE(Point3, glm::vec3)
+LDFORGE_DEFINE_PROPERTY_TYPE(Transformation, glm::mat4)
+LDFORGE_DEFINE_PROPERTY_TYPE(ReferenceName, QString)
+LDFORGE_DEFINE_PROPERTY_TYPE(IsInverted, bool)
+LDFORGE_DEFINE_PROPERTY_TYPE(ErrorMessage, QString)
+
+#define LDRAW_OBJECT_HANDLE_SET_PROPERTY(PROPERTY, HANDLER) \
+	{this->handle<ldraw::Property::PROPERTY>(result, pair, \
+		[&](const ldraw::PropertyType<ldraw::Property::PROPERTY>& value) HANDLER);}
+
+// Generics
+namespace ldraw
+{
+	template<ldraw::Property property>
+	using PropertyType = typename PropertyTraits<property>::type;
+
+	template<ldraw::Property property>
+	inline const char* PROPERTY_NAME = PropertyTraits<property>::name;
+
+	struct PropertyKeyValue
+	{
+		Property key;
+		QVariant value;
+	};
+
+	constexpr Property pointProperty(int n)
+	{
+		Q_ASSERT(n >= 0 and n < 4);
+		return static_cast<Property>(static_cast<int>(Property::Point0) + n);
+	}
+
+	struct PropertyTrait
+	{
+		ldraw::Property property;
+		std::array<char, 256> name;
+		int type;
+	};
+
+	namespace detail
+	{
+		template<int N>
+		constexpr int propertyCountHelper()
+		{
+			if constexpr (ldraw::PropertyTraits<static_cast<Property>(N)>::defined)
+			{
+				return propertyCountHelper<N + 1>();
+			}
+			else
+			{
+				return N;
+			}
+		}
+
+		template<int k>
+		constexpr PropertyTrait getPropertyTrait()
+		{
+			constexpr auto property = static_cast<ldraw::Property>(k);
+			using trait = ldraw::PropertyTraits<property>;
+			return PropertyTrait{
+				property,
+				trait::name,
+				qMetaTypeId<typename trait::type>()
+			};
+		}
+
+		template<int... Ints>
+		auto getPropertyTraits(std::integer_sequence<int, Ints...>)
+		{
+			return std::array<PropertyTrait, sizeof...(Ints)>{getPropertyTrait<Ints>()...};
+		}
+	}
+
+	constexpr int NUM_PROPERTIES = detail::propertyCountHelper<0>();
+	inline const auto& traits()
+	{
+		static std::array<PropertyTrait, NUM_PROPERTIES> result =
+			detail::getPropertyTraits(std::make_integer_sequence<int, NUM_PROPERTIES>());
+		return result;
+	}
+
+	inline const auto& traits(ldraw::Property property)
+	{
+		return traits()[static_cast<int>(property)];
+	}
+
+	template<typename T, std::size_t... Ints>
+	constexpr auto makeIndexArray(std::index_sequence<Ints...>)
+	{
+		return std::array{static_cast<T>(Ints)...};
+	}
+
+	constexpr auto ALL_PROPERTIES = makeIndexArray<Property>(std::make_index_sequence<NUM_PROPERTIES>{});
+
+	template<typename T>
+	bool testPropertyType(ldraw::Property property)
+	{
+		return qMetaTypeId<T>() == ldraw::traits(property).type;
+	}
+}

mercurial