1/* 2 * Copyright (C) 2023-2024 Huawei Device Co., Ltd. 3 * Licensed under the Apache License, Version 2.0 (the "License"); 4 * you may not use this file except in compliance with the License. 5 * You may obtain a copy of the License at 6 * 7 * http://www.apache.org/licenses/LICENSE-2.0 8 * 9 * Unless required by applicable law or agreed to in writing, software 10 * distributed under the License is distributed on an "AS IS" BASIS, 11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 * See the License for the specific language governing permissions and 13 * limitations under the License. 14 */ 15 16#include <base/containers/type_traits.h> 17#include <base/containers/vector.h> 18#include <base/math/matrix.h> 19#include <base/math/quaternion.h> 20#include <base/math/vector.h> 21#include <base/util/compile_time_hashes.h> 22#include <base/util/uid.h> 23#include <core/ecs/entity.h> 24#include <core/ecs/entity_reference.h> 25#include <core/property/property_types.h> 26 27CORE_BEGIN_NAMESPACE() 28DECLARE_PROPERTY_TYPE(bool); 29DECLARE_PROPERTY_TYPE(char); 30DECLARE_PROPERTY_TYPE(int8_t); 31DECLARE_PROPERTY_TYPE(int16_t); 32DECLARE_PROPERTY_TYPE(int32_t); 33DECLARE_PROPERTY_TYPE(int64_t); 34DECLARE_PROPERTY_TYPE(uint8_t); 35DECLARE_PROPERTY_TYPE(uint16_t); 36DECLARE_PROPERTY_TYPE(uint32_t); 37DECLARE_PROPERTY_TYPE(uint64_t); 38#ifdef __APPLE__ 39DECLARE_PROPERTY_TYPE(size_t); 40#endif 41DECLARE_PROPERTY_TYPE(float); 42DECLARE_PROPERTY_TYPE(double); 43 44// The "non-primitive" property declarations should be moved to their respective headers/implementations. 45// (to remove un-necessary "leakage") 46 47DECLARE_PROPERTY_TYPE(BASE_NS::Math::Vec2); 48DECLARE_PROPERTY_TYPE(BASE_NS::Math::Vec3); 49DECLARE_PROPERTY_TYPE(BASE_NS::Math::Vec4); 50DECLARE_PROPERTY_TYPE(BASE_NS::Math::UVec2); 51DECLARE_PROPERTY_TYPE(BASE_NS::Math::UVec3); 52DECLARE_PROPERTY_TYPE(BASE_NS::Math::UVec4); 53DECLARE_PROPERTY_TYPE(BASE_NS::Math::IVec2); 54DECLARE_PROPERTY_TYPE(BASE_NS::Math::IVec3); 55DECLARE_PROPERTY_TYPE(BASE_NS::Math::IVec4); 56DECLARE_PROPERTY_TYPE(BASE_NS::Math::Quat); 57DECLARE_PROPERTY_TYPE(BASE_NS::Math::Mat3X3); 58DECLARE_PROPERTY_TYPE(BASE_NS::Math::Mat4X4); 59DECLARE_PROPERTY_TYPE(BASE_NS::Uid); 60DECLARE_PROPERTY_TYPE(Entity); 61DECLARE_PROPERTY_TYPE(EntityReference); 62DECLARE_PROPERTY_TYPE(BASE_NS::string); 63DECLARE_PROPERTY_TYPE(BASE_NS::vector<float>); 64DECLARE_PROPERTY_TYPE(BASE_NS::vector<Entity>); 65DECLARE_PROPERTY_TYPE(BASE_NS::vector<EntityReference>); 66DECLARE_PROPERTY_TYPE(BASE_NS::vector<BASE_NS::Math::Mat4X4>); 67 68namespace PropertyType { 69// Declare metadatas for some basic types. 70template<class T> 71inline constexpr BASE_NS::array_view<const CORE_NS::Property> MetaDataFromType(const T*) 72{ 73 return {}; 74} 75// clang-format off 76template<typename T> 77inline constexpr CORE_NS::ContainerApi vectorArrayMeta{ nullptr, nullptr, nullptr, nullptr, nullptr, 78 { "", 0, CORE_NS::PropertySystem::PropertyTypeDeclFromType<BASE_NS::remove_extent_t<T>, BASE_NS::is_array_t<T>>(), 79 (sizeof(T) / sizeof(BASE_NS::remove_extent_t<T>)), sizeof(T), 0, "", 0, 80 { MetaDataFromType((T*)0), nullptr, {} } } }; 81// clang-format on 82 83template<class T> 84inline constexpr const ContainerApi* ContainerApiFromType(const T*) 85{ 86 if constexpr (BASE_NS::is_array_v<T>) { 87 return &vectorArrayMeta<BASE_NS::remove_extent_t<T>>; 88 } 89 // non array/vector types 90 return nullptr; 91} 92 93template<class T> 94inline constexpr const ContainerApi* ContainerApiFromType(const BASE_NS::vector<T>*) 95{ 96 // vector types.. 97 return nullptr; 98} 99 100template<class T> 101inline constexpr CORE_NS::MetaData MetaDataFrom(const T* dummy) 102{ 103 return { MetaDataFromType(dummy), ContainerApiFromType(dummy), {} }; 104} 105 106// primitive types have no metadata, so just return empty. 107template<> 108inline constexpr BASE_NS::array_view<const CORE_NS::Property> MetaDataFromType(const bool*) 109{ 110 return {}; 111} 112template<> 113inline constexpr BASE_NS::array_view<const CORE_NS::Property> MetaDataFromType(const char*) 114{ 115 return {}; 116} 117template<> 118inline constexpr BASE_NS::array_view<const CORE_NS::Property> MetaDataFromType(const int8_t*) 119{ 120 return {}; 121} 122template<> 123inline constexpr BASE_NS::array_view<const CORE_NS::Property> MetaDataFromType(const int16_t*) 124{ 125 return {}; 126} 127template<> 128inline constexpr BASE_NS::array_view<const CORE_NS::Property> MetaDataFromType(const int32_t*) 129{ 130 return {}; 131} 132template<> 133inline constexpr BASE_NS::array_view<const CORE_NS::Property> MetaDataFromType(const int64_t*) 134{ 135 return {}; 136} 137template<> 138inline constexpr BASE_NS::array_view<const CORE_NS::Property> MetaDataFromType(const uint8_t*) 139{ 140 return {}; 141} 142template<> 143inline constexpr BASE_NS::array_view<const CORE_NS::Property> MetaDataFromType(const uint16_t*) 144{ 145 return {}; 146} 147template<> 148inline constexpr BASE_NS::array_view<const CORE_NS::Property> MetaDataFromType(const uint32_t*) 149{ 150 return {}; 151} 152template<> 153inline constexpr BASE_NS::array_view<const CORE_NS::Property> MetaDataFromType(const uint64_t*) 154{ 155 return {}; 156} 157template<> 158inline constexpr BASE_NS::array_view<const CORE_NS::Property> MetaDataFromType(const float*) 159{ 160 return {}; 161} 162template<> 163inline constexpr BASE_NS::array_view<const CORE_NS::Property> MetaDataFromType(const BASE_NS::string*) 164{ 165 return {}; 166} 167} // namespace PropertyType 168 169// clang-format off 170#define PROPERTYTYPE_GET(b) \ 171 CORE_NS::PropertySystem::PropertyTypeDeclFromType<BASE_NS::remove_extent_t<b>, BASE_NS::is_array_t<b>>() 172 173#define BEGIN_PROPERTY(TYPE, NAME) \ 174 using COMPTYPE = TYPE; \ 175 static constexpr CORE_NS::Property NAME[] = { 176#define DECL_NAMED_PROPERTY_METADATA(structName, prop_name, name, displayname, flags, metadata) \ 177 { \ 178 #prop_name, \ 179 BASE_NS::CompileTime::FNV1aHash(#prop_name), \ 180 PROPERTYTYPE_GET(BASE_NS::remove_reference_t<decltype(structName::name)>), \ 181 BASE_NS::is_array_v<decltype(structName::name)> ? \ 182 BASE_NS::extent_v<BASE_NS::remove_reference_t<decltype(structName::name)>> : 1U, \ 183 sizeof(structName::name), offsetof(structName, name), displayname, (uint32_t)flags, \ 184 metadata \ 185 }, 186#define DECL_NAMED_PROPERTY(structName, prop_name, name, displayname, flags) \ 187 DECL_NAMED_PROPERTY_METADATA( \ 188 structName, prop_name, name, displayname, flags, \ 189 CORE_NS::PropertyType::MetaDataFrom((BASE_NS::remove_reference_t<decltype(structName::name)>*)0) \ 190 ) 191#define DECL_BITFIELD_PROPERTY(structName, name, displayname, flags, enumeration) \ 192 DECL_NAMED_PROPERTY_METADATA(structName, name, name, displayname, flags, \ 193 CORE_NS::PropertyType::MetaDataFrom((const enumeration*)0) \ 194) 195#define DECL_NAMED_PROPERTY2(prop_name, name, displayname, flags) \ 196 DECL_NAMED_PROPERTY(COMPTYPE, prop_name, name, displayname, flags) 197#define DECL_PROPERTY2(structName, name, displayname, flags) \ 198 DECL_NAMED_PROPERTY(structName, name, name, displayname, flags) 199#define DECL_PROPERTY3(name, displayname, flags) DECL_PROPERTY2(COMPTYPE, name, displayname, flags) 200#define END_PROPERTY() } 201 202#define BEGIN_METADATA(structName, dataType) \ 203 namespace PropertyType { namespace MetaData { inline constexpr CORE_NS::Property MagicData_##structName[] = { 204#define END_METADATA(structName, dataType) }; }; template<> \ 205 inline constexpr BASE_NS::array_view<const CORE_NS::Property> MetaDataFromType(const dataType*) \ 206 { \ 207 return { MetaData::MagicData_##structName, BASE_NS::countof(MetaData::MagicData_##structName) }; \ 208 } \ 209 template<> \ 210 inline constexpr const ContainerApi* ContainerApiFromType(const dataType*) \ 211 { \ 212 if constexpr (BASE_NS::is_array_v<dataType>) {return &vectorArrayMeta<dataType>;} \ 213 return nullptr; \ 214 }} 215 216#define DECL_ENUM_VALUE(structName, flags) \ 217 { \ 218 "value", BASE_NS::CompileTime::FNV1aHash("value"), PROPERTYTYPE_GET(BASE_NS::underlying_type_t<structName>), \ 219 sizeof(structName), sizeof(structName), 0, "", (uint32_t)flags, {} \ 220 } 221 222#define BEGIN_ENUM(structName, dataType) \ 223 namespace PropertyType { namespace MetaData { \ 224 inline constexpr Property MagicData_##structName[] = { DECL_ENUM_VALUE(dataType, 0) }; \ 225 inline constexpr EnumMetaData MagicEnum_##structName[] = { 226#define DECL_ENUM(dataType, name, displayName) { #name, displayName, (int64_t)dataType::name }, 227#define END_ENUM(structName, dataType) }; }; template<> \ 228inline constexpr CORE_NS::MetaData MetaDataFrom(const dataType* /* dummy */) \ 229{ \ 230 return { { MetaData::MagicData_##structName, BASE_NS::countof(MetaData::MagicData_##structName) }, \ 231 nullptr, \ 232 { MetaData::MagicEnum_##structName, BASE_NS::countof(MetaData::MagicEnum_##structName) }}; \ 233}} 234 235// clang-format on 236 237// Declare metadata for these basic types.. 238BEGIN_METADATA(UVec2MetaData, BASE_NS::Math::UVec2) 239DECL_PROPERTY2(BASE_NS::Math::UVec2, x, "", 0) 240DECL_PROPERTY2(BASE_NS::Math::UVec2, y, "", 0) 241END_METADATA(UVec2MetaData, BASE_NS::Math::UVec2) 242 243BEGIN_METADATA(UVec3MetaData, BASE_NS::Math::UVec3) 244DECL_PROPERTY2(BASE_NS::Math::UVec3, x, "", 0) 245DECL_PROPERTY2(BASE_NS::Math::UVec3, y, "", 0) 246DECL_PROPERTY2(BASE_NS::Math::UVec3, z, "", 0) 247END_METADATA(UVec3MetaData, BASE_NS::Math::UVec3) 248 249BEGIN_METADATA(UVec4MetaData, BASE_NS::Math::UVec4) 250DECL_PROPERTY2(BASE_NS::Math::UVec4, x, "", 0) 251DECL_PROPERTY2(BASE_NS::Math::UVec4, y, "", 0) 252DECL_PROPERTY2(BASE_NS::Math::UVec4, z, "", 0) 253DECL_PROPERTY2(BASE_NS::Math::UVec4, w, "", 0) 254END_METADATA(UVec4MetaData, BASE_NS::Math::UVec4) 255 256BEGIN_METADATA(IVec2MetaData, BASE_NS::Math::IVec2) 257DECL_PROPERTY2(BASE_NS::Math::IVec2, x, "", 0) 258DECL_PROPERTY2(BASE_NS::Math::IVec2, y, "", 0) 259END_METADATA(IVec2MetaData, BASE_NS::Math::IVec2) 260 261BEGIN_METADATA(IVec3MetaData, BASE_NS::Math::IVec3) 262DECL_PROPERTY2(BASE_NS::Math::IVec3, x, "", 0) 263DECL_PROPERTY2(BASE_NS::Math::IVec3, y, "", 0) 264DECL_PROPERTY2(BASE_NS::Math::IVec3, z, "", 0) 265END_METADATA(IVec3MetaData, BASE_NS::Math::IVec3) 266 267BEGIN_METADATA(IVec4MetaData, BASE_NS::Math::IVec4) 268DECL_PROPERTY2(BASE_NS::Math::IVec4, x, "", 0) 269DECL_PROPERTY2(BASE_NS::Math::IVec4, y, "", 0) 270DECL_PROPERTY2(BASE_NS::Math::IVec4, z, "", 0) 271DECL_PROPERTY2(BASE_NS::Math::IVec4, w, "", 0) 272END_METADATA(IVec4MetaData, BASE_NS::Math::IVec4) 273 274BEGIN_METADATA(Vec2MetaData, BASE_NS::Math::Vec2) 275DECL_PROPERTY2(BASE_NS::Math::Vec2, x, "", 0) 276DECL_PROPERTY2(BASE_NS::Math::Vec2, y, "", 0) 277END_METADATA(Vec2MetaData, BASE_NS::Math::Vec2) 278 279BEGIN_METADATA(Vec3MetaData, BASE_NS::Math::Vec3) 280DECL_PROPERTY2(BASE_NS::Math::Vec3, x, "", 0) 281DECL_PROPERTY2(BASE_NS::Math::Vec3, y, "", 0) 282DECL_PROPERTY2(BASE_NS::Math::Vec3, z, "", 0) 283END_METADATA(Vec3MetaData, BASE_NS::Math::Vec3) 284 285BEGIN_METADATA(Vec4MetaData, BASE_NS::Math::Vec4) 286DECL_PROPERTY2(BASE_NS::Math::Vec4, x, "", 0) 287DECL_PROPERTY2(BASE_NS::Math::Vec4, y, "", 0) 288DECL_PROPERTY2(BASE_NS::Math::Vec4, z, "", 0) 289DECL_PROPERTY2(BASE_NS::Math::Vec4, w, "", 0) 290END_METADATA(Vec4MetaData, BASE_NS::Math::Vec4) 291 292BEGIN_METADATA(QuatMetaData, BASE_NS::Math::Quat) 293DECL_PROPERTY2(BASE_NS::Math::Quat, x, "", 0) 294DECL_PROPERTY2(BASE_NS::Math::Quat, y, "", 0) 295DECL_PROPERTY2(BASE_NS::Math::Quat, z, "", 0) 296DECL_PROPERTY2(BASE_NS::Math::Quat, w, "", 0) 297END_METADATA(QuatMetaData, BASE_NS::Math::Quat) 298 299BEGIN_METADATA(Mat3x3MetaData, BASE_NS::Math::Mat3X3) 300DECL_PROPERTY2(BASE_NS::Math::Mat3X3, data, "", 0) 301END_METADATA(Mat3x3MetaData, BASE_NS::Math::Mat3X3) 302 303BEGIN_METADATA(Mat4x4MetaData, BASE_NS::Math::Mat4X4) 304DECL_PROPERTY2(BASE_NS::Math::Mat4X4, data, "", 0) 305END_METADATA(Mat4x4MetaData, BASE_NS::Math::Mat4X4) 306 307BEGIN_METADATA(EntityMetaData, Entity) 308DECL_PROPERTY2(Entity, id, "", 0) 309END_METADATA(EntityMetaData, Entity) 310 311BEGIN_METADATA(UIDMetaData, BASE_NS::Uid) 312DECL_PROPERTY2(BASE_NS::Uid, data, "", 0) 313END_METADATA(UIDMetaData, BASE_NS::Uid) 314 315// helpers for "vector" containers. 316namespace PropertyType { 317template<typename T> 318size_t size(uintptr_t container) 319{ 320 auto& vec = *(BASE_NS::vector<T>*)(container); 321 return vec.size(); 322} 323template<typename T> 324void resize(uintptr_t container, size_t newsize) 325{ 326 auto& vec = *(BASE_NS::vector<T>*)(container); 327 vec.resize(newsize); 328} 329 330template<typename T> 331void erase(uintptr_t container, size_t index) 332{ 333 auto& vec = *(BASE_NS::vector<T>*)(container); 334 vec.erase(vec.begin() + static_cast<typename BASE_NS::vector<T>::difference_type>(index)); 335} 336template<typename T> 337uintptr_t insert(uintptr_t container, size_t index) 338{ 339 auto& vec = *(BASE_NS::vector<T>*)(container); 340 vec.insert(vec.begin() + static_cast<typename BASE_NS::vector<T>::difference_type>(index), {}); 341 return (uintptr_t)&vec[index]; 342} 343 344template<typename T> 345uintptr_t get(uintptr_t container, size_t index) 346{ 347 auto& vec = *(BASE_NS::vector<T>*)(container); 348 return (uintptr_t)&vec[index]; 349} 350 351template<class T> 352inline constexpr CORE_NS::MetaData MetaDataFromT { MetaDataFromType((T*)nullptr), ContainerApiFromType((T*)nullptr), 353 {} }; 354 355template<typename T> 356inline constexpr CORE_NS::Property containerElementProperty { "", 0, 357 CORE_NS::PropertySystem::PropertyTypeDeclFromType<BASE_NS::remove_extent_t<T>, BASE_NS::is_array_t<T>>(), 358 (sizeof(T) / sizeof(BASE_NS::remove_extent_t<T>)), sizeof(T), 0, "", 0, 359 MetaDataFromT<BASE_NS::remove_extent_t<T>> }; 360 361template<typename T> 362inline constexpr CORE_NS::ContainerApi data { size<T>, resize<T>, erase<T>, insert<T>, get<T>, 363 containerElementProperty<T> }; 364} // namespace PropertyType 365 366#define DECLARE_CONTAINER_API(blob, type) \ 367 namespace PropertyType { \ 368 template<> \ 369 inline constexpr const ContainerApi* ContainerApiFromType(const BASE_NS::vector<type>*) \ 370 { \ 371 return &data<type>; \ 372 } \ 373 template<> \ 374 inline constexpr BASE_NS::array_view<const CORE_NS::Property> MetaDataFromType(const BASE_NS::vector<type>*) \ 375 { \ 376 return {}; \ 377 } \ 378 } 379 380// Declare vector style container for these primitive types. 381DECLARE_CONTAINER_API(uint8_t, uint8_t); 382DECLARE_CONTAINER_API(uint16_t, uint16_t); 383DECLARE_CONTAINER_API(uint32_t, uint32_t); 384DECLARE_CONTAINER_API(MathVec4, BASE_NS::Math::Vec4); 385DECLARE_CONTAINER_API(MathMath4X4, BASE_NS::Math::Mat4X4); 386DECLARE_CONTAINER_API(float, float); 387DECLARE_CONTAINER_API(string, BASE_NS::string); 388DECLARE_CONTAINER_API(Entity, Entity); 389DECLARE_CONTAINER_API(EntityReference, EntityReference); 390 391CORE_END_NAMESPACE() 392