#ifndef CPROPERTY #define CPROPERTY /* * This header file declares some classes used to track script object properties * CPropertyBase, __CProperty (and typedefs), CPropertyStruct * It's a bit hard to read, should be reorganized at some point */ #include "../CResource.h" #include "CScriptTemplate.h" #include "EPropertyType.h" #include #include #include #include #include /* * CPropertyBase is the base class, containing just some virtual function definitions * Virtual destructor is mainly there to make cleanup easy; don't need to cast to delete */ class CPropertyBase { friend class CScriptLoader; protected: CPropertyTemplate *tmp; public: virtual ~CPropertyBase() {} virtual EPropertyType Type() = 0; CPropertyTemplate *Template() { return tmp; } void SetTemplate(CPropertyTemplate *_tmp) { tmp = _tmp; } std::string Name() { return tmp->Name(); } u32 ID() { return tmp->PropertyID(); } }; /* * __CProperty is a template subclass for actual properties. * Don't use this class directly. Typedefs are provided for every possible property type. */ template class __CProperty : public CPropertyBase { friend class CScriptLoader; t Value; public: __CProperty() {} __CProperty(t v) { Set(v); } ~__CProperty() {} EPropertyType Type() { return type; } t Get() { return Value; } void Set(t v) { Value = v; } }; typedef __CProperty CBoolProperty; typedef __CProperty CByteProperty; typedef __CProperty CShortProperty; typedef __CProperty CLongProperty; typedef __CProperty CFloatProperty; typedef __CProperty CStringProperty; typedef __CProperty CVector3Property; typedef __CProperty CColorProperty; typedef __CProperty CFileProperty; typedef __CProperty, eUnknownProperty> CUnknownProperty; /* * Template specialization for CFileProperty to allow a token for resources */ template <> class __CProperty : public CPropertyBase { CResource *Value; CToken mToken; public: __CProperty() { Value = nullptr; } __CProperty(CResource* v) { Value = v; mToken = CToken(v); } ~__CProperty() {} EPropertyType Type() { return eFileProperty; } CResource* Get() { return Value; } void Set(CResource *v) { if (Value != v) { Value = v; mToken = CToken(v); } } const CStringList& AllowedExtensions() { return static_cast(Template())->Extensions(); } }; /* * CPropertyStruct is for defining structs of properties. */ class CPropertyStruct : public CPropertyBase { friend class CScriptLoader; std::vector Properties; public: // Destructor simply iterates through the list and deletes them. Nothing complicated. ~CPropertyStruct() { for (auto it = Properties.begin(); it != Properties.end(); it++) delete *it; } EPropertyType Type() { return eStructProperty; } u32 Count() { return Properties.size(); } void Reserve(u32 amount) { Properties.reserve(amount); } CPropertyBase* PropertyByIndex(u32 index) { return Properties[index]; } CPropertyBase* PropertyByName(std::string name) { // Resolve namespace std::string::size_type NsStart = name.find_first_of("::"); std::string::size_type PropStart = NsStart + 2; // Namespace; the requested property is within a struct if (NsStart != std::string::npos) { std::string StructName = name.substr(0, NsStart); std::string PropName = name.substr(PropStart, name.length() - PropStart); CPropertyStruct *Struct = StructByName(StructName); if (!Struct) return nullptr; else return Struct->PropertyByName(PropName); } // No namespace; fetch the property from this struct else { // ID string lookup if (StringUtil::IsHexString(name)) return PropertyByID(std::stoul(name, 0, 16)); // Name lookup else { for (auto it = Properties.begin(); it != Properties.end(); it++) { if ((*it)->Name() == name) return *it; } return nullptr; } } } CPropertyBase* PropertyByID(u32 ID) { for (auto it = Properties.begin(); it != Properties.end(); it++) { if ((*it)->ID() == ID) return *it; } return nullptr; } CPropertyStruct* StructByIndex(u32 index) { CPropertyBase *prop = PropertyByIndex(index); if (prop->Type() == eStructProperty) return static_cast(prop); else return nullptr; } CPropertyStruct* StructByName(std::string name) { CPropertyBase *prop = PropertyByName(name); if (prop->Type() == eStructProperty) return static_cast(prop); else return nullptr; } CPropertyStruct* StructByID(u32 ID) { CPropertyBase *prop = PropertyByID(ID); if (prop->Type() == eStructProperty) return static_cast(prop); else return nullptr; } inline CPropertyBase* operator[](u32 index) { return Properties[index]; } static CPropertyStruct* CopyFromTemplate(CStructTemplate *pTemp) { CPropertyStruct *pStruct = new CPropertyStruct(); pStruct->tmp = pTemp; pStruct->Reserve(pTemp->Count()); for (u32 iProp = 0; iProp < pTemp->Count(); iProp++) { CPropertyTemplate *pPropTemp = pTemp->PropertyByIndex(iProp); CPropertyBase *pProp = nullptr; switch (pPropTemp->Type()) { case eBoolProperty: pProp = new CBoolProperty(false); break; case eByteProperty: pProp = new CByteProperty(0); break; case eShortProperty: pProp = new CShortProperty(0); break; case eLongProperty: pProp = new CLongProperty(0); break; case eFloatProperty: pProp = new CFloatProperty(0.f); break; case eStringProperty: pProp = new CStringProperty(""); break; case eVector3Property: pProp = new CVector3Property(CVector3f::skZero); break; case eColorProperty: pProp = new CColorProperty(CColor::skBlack); break; case eFileProperty: pProp = new CFileProperty(); break; case eUnknownProperty: pProp = new CUnknownProperty(); break; case eStructProperty: pProp = CPropertyStruct::CopyFromTemplate(static_cast(pPropTemp)); break; } if (pProp) { pProp->SetTemplate(pPropTemp); pStruct->Properties.push_back(pProp); } } return pStruct; } }; #endif // CPROPERTY