Wed, 25 May 2022 20:36:34 +0300
Fix pick() picking from weird places on the screen with high DPI scaling
glReadPixels reads data from the frame buffer, which contains data after
high DPI scaling, so any reads to that need to take this scaling into account
#pragma once #include "main.h" #include "colors.h" class Vec3Editor; class MatrixEditor; namespace ldraw { enum CircularPrimitiveType { Circle, Disc }; enum class Property; struct PropertyKeyValue; template<Property property> struct PropertyTraits { static constexpr bool defined = false; }; } Q_DECLARE_METATYPE(ldraw::CircularPrimitiveType) /** * 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 CircularPrimitiveType, // Type of circular primitive (circle, disc, ...) Segments, // Amount of circular segments this primitive covers (numerator) Divisions, // Amount of segments in the circle this primitive fits in (8, 16, 48, ...) }; 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) LDFORGE_DEFINE_PROPERTY_TYPE(CircularPrimitiveType, ldraw::CircularPrimitiveType) LDFORGE_DEFINE_PROPERTY_TYPE(Segments, int) LDFORGE_DEFINE_PROPERTY_TYPE(Divisions, int) #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; constexpr int MAX_POINTS = 4; struct PropertyKeyValue { Property key; QVariant value; }; constexpr Property pointProperty(int n) { Q_ASSERT(n >= 0 and n < MAX_POINTS); 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; } }