From a4b0b108d4e0cbd8c888d3c5fd87389bd5845ba2 Mon Sep 17 00:00:00 2001 From: sippeangelo Date: Sat, 12 Mar 2016 00:38:26 +0100 Subject: [PATCH] Created a wrapper for field types that is able to detect changes to set dirty flags in the future --- include/Engine/Core/ComponentWrapper.h | 161 ++++++++++++++++++++++++- 1 file changed, 157 insertions(+), 4 deletions(-) diff --git a/include/Engine/Core/ComponentWrapper.h b/include/Engine/Core/ComponentWrapper.h index b75e1a00..f7168b8e 100644 --- a/include/Engine/Core/ComponentWrapper.h +++ b/include/Engine/Core/ComponentWrapper.h @@ -4,11 +4,13 @@ #include #include #include "../Common.h" +#include "../GLM.h" #include "Entity.h" #include "ComponentInfo.h" #include "DirtySet.h" #include "Util/Any.h" + struct ComponentWrapper { ComponentWrapper(const ComponentInfo& componentInfo, char* data, ::DirtyBitField* dirtyBitField) @@ -105,7 +107,8 @@ struct ComponentWrapper struct SubscriptProxy { friend struct ComponentWrapper; - private: + + public: SubscriptProxy(ComponentWrapper* component, std::string fieldName) : m_Component(component) , m_FieldName(fieldName) @@ -120,11 +123,53 @@ struct ComponentWrapper bool Dirty(DirtySetType type) { return m_Component->Dirty(type, m_FieldName); } void SetDirty(DirtySetType type, bool dirty = true) { m_Component->SetDirty(type, m_FieldName, dirty); } - template - operator T&() { return m_Component->Field(m_FieldName); } + //template < + // typename T, + // typename = typename std::enable_if::value>::type + //> + // operator const T&() { return m_Component->Field(m_FieldName); } + operator const double&() { return m_Component->Field(m_FieldName); } + operator const float&() { return m_Component->Field(m_FieldName); } + operator const int&() { return m_Component->Field(m_FieldName); } + operator const glm::vec3&() { return m_Component->Field(m_FieldName); } + operator const glm::vec4&() { return m_Component->Field(m_FieldName); } + operator const glm::quat&() { return m_Component->Field(m_FieldName); } + operator const bool&() { return m_Component->Field(m_FieldName); } + operator const std::string&() { return m_Component->Field(m_FieldName); } + + template < + typename T, + typename = typename std::enable_if::value>::type + > + //operator T&() { static_assert(constexpr(false), "FU"); } + operator T&() = delete; + + /* template < + typename T, + typename = typename std::enable_if::value>::type + > + operator T&() { static_assert(constexpr(false), "FU"); }*/ + + //template + //operator typename std::enable_if::value, T>::type() { return m_Component->Field(m_FieldName); } + + //template + //operator Field() + //{ + // return ::Field(m_Component->Field(m_FieldName)); + //} + + //operator std::string() { return m_Component->Field(m_FieldName); } + //operator glm::vec3() { return m_Component->Field(m_FieldName); } + + //template + //operator glm::vec3() { return m_Component->Field(m_FieldName); } + + //template + //operator const T&() { return m_Component->Field(m_FieldName); } template - void operator=(const T val) { m_Component->SetField(m_FieldName, val); } + void operator=(const T& val) { m_Component->SetField(m_FieldName, val); } // TODO: Pass by reference and rvalue (universal reference?) //template //void operator=(T& val) { m_Component->SetField(m_PropertyName, val); } @@ -136,6 +181,114 @@ struct ComponentWrapper SubscriptProxy operator[](const std::string& propertyName) { return SubscriptProxy(this, propertyName); } }; +struct FIELDLOL {}; + +template +struct FieldBase : FIELDLOL +{ + FieldBase(ComponentWrapper::SubscriptProxy& proxy) + : Data(proxy.m_Component->Field(proxy.m_FieldName)) + { } + + FieldBase& operator=(const FieldBase& rhs) { Data = rhs.Data; return *this; } + FieldBase& operator=(const T& rhs) { Data = rhs; return *this; } + + template FieldBase& operator+=(const T2& rhs) { Data += rhs; return *this; } + template FieldBase& operator-=(const T2& rhs) { Data -= rhs; return *this; } + template FieldBase& operator*=(const T2& rhs) { Data *= rhs; return *this; } + template FieldBase& operator/=(const T2& rhs) { Data /= rhs; return *this; } + template FieldBase& operator%=(const T2& rhs) { Data %= rhs; return *this; } + template FieldBase& operator&=(const T2& rhs) { Data &= rhs; return *this; } + template FieldBase& operator|=(const T2& rhs) { Data |= rhs; return *this; } + template FieldBase& operator^=(const T2& rhs) { Data ^= rhs; return *this; } + template FieldBase& operator<<=(const T2& rhs) { Data <<= rhs; return *this; } + template FieldBase& operator>>=(const T2& rhs) { Data >>= rhs; return *this; } + + T operator+() const { return +Data; } + T operator-() const { return -Data; } + T operator~() const { return ~Data; } + + FieldBase& operator++() { Data++; return *this; } + T operator++(int) { T tmp = Data; operator++(); return tmp; } + FieldBase& operator--() { Data--; return *this; } + T operator--(int) { T tmp = Data; operator--(); return tmp; } + + operator const T&() const { return Data; } + const T& operator*() const { return operator const T&(); } + +protected: + T& Data; +}; + +template +struct Field : FieldBase +{ + //Field(T& Data) + // : FieldBase(Data) + //{ } + using FieldBase::FieldBase; + using FieldBase::operator=; +}; + +template <> +struct Field : FieldBase +{ + //Field(glm::vec3& Data) + // : FieldBase(Data) + //{ } + using FieldBase::FieldBase; + using FieldBase::operator=; + + glm::vec3::value_type x() { return Data.x; } + void x(glm::vec3::value_type val) { Data.x = val; } + glm::vec3::value_type y() { return Data.y; } + void y(glm::vec3::value_type val) { Data.y = val; } + glm::vec3::value_type z() { return Data.z; } + void z(glm::vec3::value_type val) { Data.z = val; } + + template friend glm::vec3 operator+(const Field& lhs, const T& rhs) { return static_cast(lhs) + glm::vec3(rhs); } + template friend glm::vec3 operator-(const Field& lhs, const T& rhs) { return static_cast(lhs) - glm::vec3(rhs); } + template friend glm::vec3 operator*(const Field& lhs, const T& rhs) { return static_cast(lhs) * glm::vec3(rhs); } + template friend glm::vec3 operator/(const Field& lhs, const T& rhs) { return static_cast(lhs) / glm::vec3(rhs); } + template friend glm::vec3 operator+(const T& lhs, const Field& rhs) { return glm::vec3(lhs) + static_cast(rhs); } + template friend glm::vec3 operator-(const T& lhs, const Field& rhs) { return glm::vec3(lhs) - static_cast(rhs); } + template friend glm::vec3 operator*(const T& lhs, const Field& rhs) { return glm::vec3(lhs) * static_cast(rhs); } + template friend glm::vec3 operator/(const T& lhs, const Field& rhs) { return glm::vec3(lhs) / static_cast(rhs); } + + friend glm::vec3& operator+=(glm::vec3& lhs, const Field& rhs) { lhs += *rhs; return lhs; } +}; + +template <> +struct Field : FieldBase +{ + //Field(glm::vec4& Data) + // : FieldBase(Data) + //{ } + using FieldBase::FieldBase; + using FieldBase::operator=; + + glm::vec4::value_type x() { return Data.x; } + void x(glm::vec4::value_type val) { Data.x = val; } + glm::vec4::value_type y() { return Data.y; } + void y(glm::vec4::value_type val) { Data.y = val; } + glm::vec4::value_type z() { return Data.z; } + void z(glm::vec4::value_type val) { Data.z = val; } + glm::vec4::value_type w() { return Data.w; } + void w(glm::vec4::value_type val) { Data.w = val; } + + template friend glm::vec4 operator+(const Field& lhs, const T& rhs) { return static_cast(lhs) + glm::vec4(rhs); } + template friend glm::vec4 operator-(const Field& lhs, const T& rhs) { return static_cast(lhs) - glm::vec4(rhs); } + template friend glm::vec4 operator*(const Field& lhs, const T& rhs) { return static_cast(lhs) * glm::vec4(rhs); } + template friend glm::vec4 operator/(const Field& lhs, const T& rhs) { return static_cast(lhs) / glm::vec4(rhs); } + template friend glm::vec4 operator+(const T& lhs, const Field& rhs) { return glm::vec4(lhs) + static_cast(rhs); } + template friend glm::vec4 operator-(const T& lhs, const Field& rhs) { return glm::vec4(lhs) - static_cast(rhs); } + template friend glm::vec4 operator*(const T& lhs, const Field& rhs) { return glm::vec4(lhs) * static_cast(rhs); } + template friend glm::vec4 operator/(const T& lhs, const Field& rhs) { return glm::vec4(lhs) / static_cast(rhs); } + + friend glm::vec4& operator+=(glm::vec4& lhs, const Field& rhs) { lhs += *rhs; return lhs; } +}; + + // A component wrapper that "owns" its data through a shared pointer struct SharedComponentWrapper : ComponentWrapper {