/**************************************************************************** ** ** Copyright (C) 1993-2009 NVIDIA Corporation. ** Copyright (C) 2017 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qt 3D Studio. ** ** $QT_BEGIN_LICENSE:GPL-EXCEPT$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 3 as published by the Free Software ** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #pragma once #ifndef QT3DSDM_DATA_H #define QT3DSDM_DATA_H #include #include #include "Qt3DSDMErrors.h" #include "Qt3DSDMStringTable.h" #include "Qt3DSDMWindowsCompatibility.h" #include #include #include #include #include //char8_t, etc. #include #include #include "foundation/StrConvertUTF.h" #include "foundation/Qt3DSDiscriminatedUnion.h" #include namespace qt3dsdm { typedef const wchar_t *TCharPtr; struct Qt3DSDMStr : public eastl::basic_string { typedef qt3ds::foundation::TWCharEASTLConverter::TCharType TCharType; typedef eastl::basic_string TStrType; Qt3DSDMStr() {} Qt3DSDMStr(const wchar_t *inStr) : TStrType(qt3ds::NVUnionCast(inStr)) { } Qt3DSDMStr(const TStrType &inOther) : TStrType(inOther) { } const wchar_t *wide_str() const { return reinterpret_cast(c_str()); } bool operator==(const Qt3DSDMStr &inOther) const { return TStrType::compare(inOther) == 0; } bool operator!=(const Qt3DSDMStr &inOther) const { return TStrType::compare(inOther) != 0; } bool operator==(const wchar_t *inOther) const { return TStrType::compare(reinterpret_cast(inOther)) == 0; } bool operator!=(const wchar_t *inOther) const { return TStrType::compare(reinterpret_cast(inOther)) != 0; } TStrType::size_type find_first_of(const wchar_t *p, size_type position = 0) const { return TStrType::find_first_of(reinterpret_cast(p), position); } TStrType::size_type find_first_not_of(const wchar_t *p, size_type position = 0) const { return TStrType::find_first_not_of(reinterpret_cast(p), position); } TStrType::size_type find_last_not_of(const wchar_t *p, size_type position = TStrType::npos) const { return TStrType::find_last_not_of(reinterpret_cast(p), position); } TStrType::size_type find(const wchar_t *p, size_type position = 0) const { return TStrType::find(reinterpret_cast(p), position); } TStrType::size_type find(wchar_t p, size_type position = 0) const { return TStrType::find(static_cast(p), position); } TStrType::size_type rfind(const wchar_t *p, size_type position = TStrType::npos) const { return TStrType::rfind(reinterpret_cast(p), position); } TStrType::size_type rfind(wchar_t p, size_type position = TStrType::npos) const { return TStrType::rfind(p, position); } Qt3DSDMStr replace(size_type position, size_type length, const wchar_t *inNewStr) { return TStrType::replace(position, length, reinterpret_cast(inNewStr)); } void append(const wchar_t *p) { TStrType::append(reinterpret_cast(p)); } void append(const wchar_t *p, size_type position, size_type n) { TStrType::append(reinterpret_cast(p), position, n); } void append(const Qt3DSDMStr &p) { TStrType::append(p); } void assign(const wchar_t *p) { TStrType::assign(reinterpret_cast(p)); } void assign(const Qt3DSDMStr &p) { TStrType::assign(p); } }; typedef Qt3DSDMStr TCharStr; typedef std::vector TCharList; typedef eastl::vector TCharStrList; typedef std::map TCharStrIntMap; typedef std::map TIntTCharStrMap; typedef std::vector TIntList; typedef std::set TIntSet; typedef eastl::vector TFloatList; template class CImmutableVector : private std::vector { public: typedef std::vector base; CImmutableVector(const std::vector &inSrc) : base(inSrc) { } CImmutableVector(const CImmutableVector &inSrc) : base(inSrc) { } CImmutableVector &operator=(const CImmutableVector &inSrc) { base::operator=(inSrc); return *this; } typename std::vector::const_iterator begin() const { return base::begin(); } typename std::vector::const_iterator end() const { return base::end(); } size_t size() const { return base::size(); } const TDataType &at(int inIndex) const { return base::at(inIndex); } const TDataType &operator[](int inIndex) const { return base::at(inIndex); } }; typedef CImmutableVector TImmutableCharStrList; typedef std::shared_ptr TImmutableCharStrListPtr; class CDataStr { TCharList m_Data; public: CDataStr() {} CDataStr(TCharList &inData) { m_Data.swap(inData); } CDataStr(const wchar_t *inData) { if (inData && *inData) m_Data.insert(m_Data.begin(), inData, inData + wcslen(inData)); m_Data.push_back(0); } CDataStr(const wchar_t *inData, size_t inLen) { if (inData && *inData) m_Data.insert(m_Data.begin(), inData, inData + inLen); if (m_Data.size() > 0 && m_Data.back() != 0) m_Data.push_back(0); } CDataStr(const CDataStr &inOther) : m_Data(inOther.m_Data) { } virtual ~CDataStr() {} CDataStr &operator=(const CDataStr &inOther) { m_Data = inOther.m_Data; return *this; } const wchar_t *GetData() const { return m_Data.size() <= 1 ? L"" : &(*m_Data.begin()); } size_t GetLength() const { return m_Data.size() > 1 ? m_Data.size() - 1 : 0; } bool operator==(const CDataStr &inOther) const { return m_Data == inOther.m_Data; } QString toQString() const { return QString::fromWCharArray(GetData()); } }; typedef std::shared_ptr TDataStrPtr; struct SFloat2 { float m_Floats[2]; SFloat2(float f1 = 0, float f2 = 0) { m_Floats[0] = f1; m_Floats[1] = f2; } SFloat2(const SFloat2 &inOther) { operator=(inOther); } SFloat2 &operator=(const SFloat2 &inOther) { m_Floats[0] = inOther.m_Floats[0]; m_Floats[1] = inOther.m_Floats[1]; return *this; } bool operator==(const SFloat2 &other) const { return m_Floats[0] == other.m_Floats[0] && m_Floats[1] == other.m_Floats[1]; } float &operator[](size_t inIndex) { switch (inIndex) { default: throw std::out_of_range(""); case 0: case 1: return m_Floats[inIndex]; } } const float &operator[](size_t inIndex) const { switch (inIndex) { default: throw std::out_of_range(""); case 0: case 1: return m_Floats[inIndex]; } } }; struct SFloat3 { float m_Floats[3]; SFloat3(float f1 = 0, float f2 = 0, float f3 = 0) { m_Floats[0] = f1; m_Floats[1] = f2; m_Floats[2] = f3; } SFloat3(const SFloat3 &inOther) { operator=(inOther); } SFloat3 &operator=(const SFloat3 &inOther) { m_Floats[0] = inOther.m_Floats[0]; m_Floats[1] = inOther.m_Floats[1]; m_Floats[2] = inOther.m_Floats[2]; return *this; } bool operator==(const SFloat3 &other) const { return m_Floats[0] == other.m_Floats[0] && m_Floats[1] == other.m_Floats[1] && m_Floats[2] == other.m_Floats[2]; } float &operator[](size_t inIndex) { switch (inIndex) { default: throw std::out_of_range(""); case 0: case 1: case 2: return m_Floats[inIndex]; } } const float &operator[](size_t inIndex) const { switch (inIndex) { default: throw std::out_of_range(""); case 0: case 1: case 2: return m_Floats[inIndex]; } } }; struct SFloat4 { float m_Floats[4]; SFloat4(float f1 = 0, float f2 = 0, float f3 = 0, float f4 = 1) { m_Floats[0] = f1; m_Floats[1] = f2; m_Floats[2] = f3; m_Floats[3] = f4; } SFloat4(const SFloat4 &inOther) { operator=(inOther); } SFloat4 &operator=(const SFloat4 &inOther) { m_Floats[0] = inOther.m_Floats[0]; m_Floats[1] = inOther.m_Floats[1]; m_Floats[2] = inOther.m_Floats[2]; m_Floats[3] = inOther.m_Floats[3]; return *this; } bool operator==(const SFloat4 &other) const { return m_Floats[0] == other.m_Floats[0] && m_Floats[1] == other.m_Floats[1] && m_Floats[2] == other.m_Floats[2] && m_Floats[3] == other.m_Floats[3]; } float &operator[](size_t inIndex) { if (inIndex < 4) return m_Floats[inIndex]; throw std::out_of_range(""); } const float &operator[](size_t inIndex) const { if (inIndex < 4) return m_Floats[inIndex]; throw std::out_of_range(""); } }; struct SLong4 { qt3ds::QT3DSU32 m_Longs[4]; SLong4(qt3ds::QT3DSU32 l1 = 0, qt3ds::QT3DSU32 l2 = 0, qt3ds::QT3DSU32 l3 = 0, qt3ds::QT3DSU32 l4 = 0) { m_Longs[0] = l1; m_Longs[1] = l2; m_Longs[2] = l3; m_Longs[3] = l4; } SLong4(const SLong4 &inOther) { operator=(inOther); } SLong4 &operator=(const SLong4 &inOther) { m_Longs[0] = inOther.m_Longs[0]; m_Longs[1] = inOther.m_Longs[1]; m_Longs[2] = inOther.m_Longs[2]; m_Longs[3] = inOther.m_Longs[3]; return *this; } bool operator==(const SLong4 &other) const { return m_Longs[0] == other.m_Longs[0] && m_Longs[1] == other.m_Longs[1] && m_Longs[2] == other.m_Longs[2] && m_Longs[3] == other.m_Longs[3]; } bool operator<(const SLong4 &other) const { if (m_Longs[0] < other.m_Longs[0]) return true; else if (m_Longs[0] == other.m_Longs[0]) { if (m_Longs[1] < other.m_Longs[1]) return true; else if (m_Longs[1] == other.m_Longs[1]) { if (m_Longs[2] < other.m_Longs[2]) return true; else if (m_Longs[3] < other.m_Longs[3]) return true; } } return false; } bool Valid() const { bool retval = false; for (int idx = 0; idx < 4; ++idx) retval = retval || m_Longs[0] > 0; return retval; } }; typedef std::vector TLong4Vec; struct SSizet4 { size_t m_Longs[4]; SSizet4(size_t l1 = 0, size_t l2 = 0, size_t l3 = 0, size_t l4 = 0) { m_Longs[0] = l1; m_Longs[1] = l2; m_Longs[2] = l3; m_Longs[3] = l4; } SSizet4(const SSizet4 &inOther) { operator=(inOther); } SSizet4 &operator=(const SSizet4 &inOther) { m_Longs[0] = inOther.m_Longs[0]; m_Longs[1] = inOther.m_Longs[1]; m_Longs[2] = inOther.m_Longs[2]; m_Longs[3] = inOther.m_Longs[3]; return *this; } bool operator==(const SSizet4 &other) const { return m_Longs[0] == other.m_Longs[0] && m_Longs[1] == other.m_Longs[1] && m_Longs[2] == other.m_Longs[2] && m_Longs[3] == other.m_Longs[3]; } bool operator<(const SSizet4 &other) const { if (m_Longs[0] < other.m_Longs[0]) return true; else if (m_Longs[0] == other.m_Longs[0]) { if (m_Longs[1] < other.m_Longs[1]) return true; else if (m_Longs[1] == other.m_Longs[1]) { if (m_Longs[2] < other.m_Longs[2]) return true; else if (m_Longs[3] < other.m_Longs[3]) return true; } } return false; } bool Valid() const { bool retval = false; for (int idx = 0; idx < 4; ++idx) retval = retval || m_Longs[0] > 0; return retval; } }; inline bool IsTrivial(const wchar_t *inStr) { return inStr == NULL || *inStr == 0; } inline const wchar_t *NonNull(const wchar_t *inStr) { return inStr ? inStr : L""; } inline bool AreEqual(const wchar_t *lhs, const wchar_t *rhs) { return wcscmp(NonNull(lhs), NonNull(rhs)) == 0; } inline bool IsTrivial(const char8_t *inStr) { return inStr == NULL || *inStr == 0; } inline const char8_t *NonNull(const char8_t *inStr) { return inStr ? inStr : ""; } inline bool AreEqual(const char8_t *lhs, const char8_t *rhs) { return strcmp(NonNull(lhs), NonNull(rhs)) == 0; } inline bool AreEqualCaseless(const char8_t *lhs, const char8_t *rhs) { if (IsTrivial(lhs) && IsTrivial(rhs)) return true; if (IsTrivial(lhs) || IsTrivial(rhs)) return false; for (; *lhs && *rhs; ++lhs, ++rhs) if (tolower(*lhs) != tolower(*rhs)) return false; if (*lhs || *rhs) return false; return true; } struct SStringRef { const wchar_t *m_Id; SStringRef(const wchar_t *id = L"") : m_Id(NonNull(id)) { } operator const wchar_t *() const { return m_Id; } bool operator==(const SStringRef &inOther) const { return AreEqual(m_Id, inOther.m_Id); } }; } // Traits specializations have to be in the same namespace as they were first declared. namespace qt3ds { namespace foundation { template <> struct DestructTraits { void destruct(qt3dsdm::SFloat2 &) {} }; template <> struct DestructTraits { void destruct(qt3dsdm::SFloat3 &) {} }; template <> struct DestructTraits { void destruct(qt3dsdm::SFloat4 &) {} }; template <> struct DestructTraits { void destruct(qt3dsdm::SLong4 &) {} }; template <> struct DestructTraits { void destruct(qt3dsdm::SStringRef &) {} }; template <> struct EqualVisitorTraits { bool operator()(const qt3dsdm::TDataStrPtr &lhs, const qt3dsdm::TDataStrPtr &rhs) { if (lhs && rhs) return *lhs == *rhs; if (lhs || rhs) return false; return true; } }; } } namespace qt3dsdm { using qt3ds::NVUnionCast; struct ObjectReferenceType { enum Enum { Unknown = 0, Absolute = 1, Relative = 2, }; }; template struct SObjectRefTypeTraits { }; template <> struct SObjectRefTypeTraits { ObjectReferenceType::Enum getType() { return ObjectReferenceType::Absolute; } }; template <> struct SObjectRefTypeTraits { ObjectReferenceType::Enum getType() { return ObjectReferenceType::Relative; } }; struct SObjectRefUnionTraits { typedef ObjectReferenceType::Enum TIdType; enum { TBufferSize = sizeof(SSizet4), }; static ObjectReferenceType::Enum getNoDataId() { return ObjectReferenceType::Unknown; } template static TIdType getType() { return SObjectRefTypeTraits().getType(); } template static TRetType visit(char *inData, TIdType inType, TVisitorType inVisitor) { switch (inType) { case ObjectReferenceType::Absolute: return inVisitor(*NVUnionCast(inData)); case ObjectReferenceType::Relative: return inVisitor(*NVUnionCast(inData)); default: QT3DS_ASSERT(false); case ObjectReferenceType::Unknown: return inVisitor(); } } template static TRetType visit(const char *inData, TIdType inType, TVisitorType inVisitor) { switch (inType) { case ObjectReferenceType::Absolute: return inVisitor(*NVUnionCast(inData)); case ObjectReferenceType::Relative: return inVisitor(*NVUnionCast(inData)); default: QT3DS_ASSERT(false); case ObjectReferenceType::Unknown: return inVisitor(); } } }; typedef qt3ds::foundation:: DiscriminatedUnion, SObjectRefUnionTraits::TBufferSize> TObjRefUnionType; template struct Qt3DSDMGetter { }; template TRetType get(const TDataType &inType) { return Qt3DSDMGetter().template doGet(inType); } template <> struct Qt3DSDMGetter { template TRetType doGet(const TObjRefUnionType &inValue) { return inValue.getData(); } }; // Either an absolute reference (SLong4) or a relative reference (string) struct SObjectRefType { TObjRefUnionType m_Value; SObjectRefType(const TDataStrPtr &inValue) : m_Value(inValue) { } SObjectRefType(const SLong4 &inValue) : m_Value(inValue) { } SObjectRefType(const SObjectRefType &inOther) : m_Value(inOther.m_Value) { } SObjectRefType() {} SObjectRefType &operator=(const SObjectRefType &inOther) { m_Value = inOther.m_Value; return *this; } ObjectReferenceType::Enum GetReferenceType() const { return m_Value.getType(); } bool operator==(const SObjectRefType &inOther) const { return m_Value == inOther.m_Value; } }; inline bool Equals(const SObjectRefType &lhs, const SObjectRefType &rhs) { return lhs == rhs; } struct SStringOrIntTypes { enum Enum { Unknown = 0, Int, String, }; }; template struct SStringOrIntTypeTraits { }; template <> struct SStringOrIntTypeTraits { SStringOrIntTypes::Enum getType() { return SStringOrIntTypes::Int; } }; template <> struct SStringOrIntTypeTraits { SStringOrIntTypes::Enum getType() { return SStringOrIntTypes::Int; } }; template <> struct SStringOrIntTypeTraits { SStringOrIntTypes::Enum getType() { return SStringOrIntTypes::String; } }; struct SStringOrIntUnionTraits { typedef SStringOrIntTypes::Enum TIdType; enum { TBufferSize = sizeof(TDataStrPtr), }; static SStringOrIntTypes::Enum getNoDataId() { return SStringOrIntTypes::Unknown; } template static TIdType getType() { return SStringOrIntTypeTraits().getType(); } template static TRetType visit(char *inData, TIdType inType, TVisitorType inVisitor) { switch (inType) { case SStringOrIntTypes::Int: return inVisitor(*NVUnionCast(inData)); case SStringOrIntTypes::String: return inVisitor(*NVUnionCast(inData)); default: QT3DS_ASSERT(false); case SStringOrIntTypes::Unknown: return inVisitor(); } } template static TRetType visit(const char *inData, TIdType inType, TVisitorType inVisitor) { switch (inType) { case SStringOrIntTypes::Int: return inVisitor(*NVUnionCast(inData)); case SStringOrIntTypes::String: return inVisitor(*NVUnionCast(inData)); default: QT3DS_ASSERT(false); case SStringOrIntTypes::Unknown: return inVisitor(); } } }; typedef qt3ds::foundation:: DiscriminatedUnion, SStringOrIntUnionTraits::TBufferSize> TStringOrIntUnionType; template <> struct Qt3DSDMGetter { template TRetType doGet(const TStringOrIntUnionType &inValue) { return inValue.getData(); } }; struct SStringOrInt { TStringOrIntUnionType m_Value; SStringOrInt() {} SStringOrInt(int inValue) : m_Value(inValue) { } SStringOrInt(TDataStrPtr inValue) : m_Value(inValue) { } SStringOrInt(const SStringOrInt &inOther) : m_Value(inOther.m_Value) { } SStringOrInt &operator=(const SStringOrInt &inOther) { m_Value = inOther.m_Value; return *this; } SStringOrIntTypes::Enum GetType() const { return m_Value.getType(); } bool operator==(const SStringOrInt &inOther) const { return m_Value == inOther.m_Value; } }; inline bool Equals(const SStringOrInt &lhs, const SStringOrInt &rhs) { return lhs == rhs; } //comes from broken X.h #ifdef None #undef None #endif #ifdef Bool #undef Bool #endif struct DataModelDataType { enum Value { None, Float, Float2, Float3, Float4, Long, String, Bool, Long4, StringRef, ObjectRef, StringOrInt, FloatList, RangedNumber // datainput-specific type for editor only }; Q_ENUM(Value) Q_GADGET }; class IStringTable; template struct Qt3DSDMValueTyper { }; template inline DataModelDataType::Value GetValueType(const TDataType &inValue) { return Qt3DSDMValueTyper().Get(inValue); } template struct SDefaulter { }; template inline bool SetDefault(DataModelDataType::Value inDataType, TDataType &outValue) { return SDefaulter().SetDefault(inDataType, outValue); } typedef void (*Qt3DSDMDebugLogFunction)(const char *message); // UICDMSimpleDataCore.cpp extern Qt3DSDMDebugLogFunction g_DataModelDebugLogger; #define QT3DSDM_DEBUG_LOG(msg) \ { \ if (g_DataModelDebugLogger) { \ g_DataModelDebugLogger(msg); \ } \ } struct Qt3DSDMLogScope { const char *m_EndMessage; Qt3DSDMLogScope(const char *inStartMessage, const char *inEndMessage) : m_EndMessage(inEndMessage) { QT3DSDM_DEBUG_LOG(inStartMessage); } ~Qt3DSDMLogScope() { QT3DSDM_DEBUG_LOG(m_EndMessage); } }; #define QT3DSDM_LOG_FUNCTION(fnname) Qt3DSDMLogScope __fn_scope(fnname " Enter", fnname " Leave"); } #endif