#include "Def.h" #include "Generated.h" namespace Gen { bool Save(const PuzzleElementType::Enum* obj, uint32_t count, Serializer& serializer) { bool isOk = true; for (uint32_t i = 0; i < count; ++i) { auto val = (uint8_t)obj[i]; isOk = Save(&val, 1, serializer) && isOk; } return isOk; } bool Load(PuzzleElementType::Enum* obj, uint32_t count, Deserializer& serializer) { bool isOk = true; for (int32_t i = 0; i < count; ++i) { uint8_t& val = (uint8_t&)obj[i]; isOk = Load(&val, 1, serializer) && isOk; } return isOk; } bool Save(const PlacedPuzzleCardFlags::Enum* obj, uint32_t count, Serializer& serializer) { bool isOk = true; for (uint32_t i = 0; i < count; ++i) { auto val = (uint8_t)obj[i]; isOk = Save(&val, 1, serializer) && isOk; } return isOk; } bool Load(PlacedPuzzleCardFlags::Enum* obj, uint32_t count, Deserializer& serializer) { bool isOk = true; for (int32_t i = 0; i < count; ++i) { uint8_t& val = (uint8_t&)obj[i]; isOk = Load(&val, 1, serializer) && isOk; } return isOk; } bool Save(const EMaterial::Enum* obj, uint32_t count, Serializer& serializer) { bool isOk = true; for (uint32_t i = 0; i < count; ++i) { auto val = (int32_t)obj[i]; isOk = Save(&val, 1, serializer) && isOk; } return isOk; } bool Load(EMaterial::Enum* obj, uint32_t count, Deserializer& serializer) { bool isOk = true; for (int32_t i = 0; i < count; ++i) { int32_t& val = (int32_t&)obj[i]; isOk = Load(&val, 1, serializer) && isOk; } return isOk; } bool Save(const int8_t* obj, uint32_t count, Serializer& serializer) { bool isOk = true; for (uint32_t i = 0; i < count; ++i) { isOk = serializer.Write(&obj[i], sizeof(obj[i])) && isOk; } return isOk; } bool Load(int8_t* obj, uint32_t count, Deserializer& serializer) { bool isOk = true; for (int32_t i = 0; i < count; ++i) { isOk = serializer.Read(&obj[i], sizeof(obj[i])) && isOk; } return isOk; } bool Save(const int16_t* obj, uint32_t count, Serializer& serializer) { bool isOk = true; for (uint32_t i = 0; i < count; ++i) { isOk = serializer.Write(&obj[i], sizeof(obj[i])) && isOk; } return isOk; } bool Load(int16_t* obj, uint32_t count, Deserializer& serializer) { bool isOk = true; for (int32_t i = 0; i < count; ++i) { isOk = serializer.Read(&obj[i], sizeof(obj[i])) && isOk; } return isOk; } bool Save(const int32_t* obj, uint32_t count, Serializer& serializer) { bool isOk = true; for (uint32_t i = 0; i < count; ++i) { isOk = serializer.Write(&obj[i], sizeof(obj[i])) && isOk; } return isOk; } bool Load(int32_t* obj, uint32_t count, Deserializer& serializer) { bool isOk = true; for (int32_t i = 0; i < count; ++i) { isOk = serializer.Read(&obj[i], sizeof(obj[i])) && isOk; } return isOk; } bool Save(const int64_t* obj, uint32_t count, Serializer& serializer) { bool isOk = true; for (uint32_t i = 0; i < count; ++i) { isOk = serializer.Write(&obj[i], sizeof(obj[i])) && isOk; } return isOk; } bool Load(int64_t* obj, uint32_t count, Deserializer& serializer) { bool isOk = true; for (int32_t i = 0; i < count; ++i) { isOk = serializer.Read(&obj[i], sizeof(obj[i])) && isOk; } return isOk; } bool Save(const uint8_t* obj, uint32_t count, Serializer& serializer) { bool isOk = true; for (uint32_t i = 0; i < count; ++i) { isOk = serializer.Write(&obj[i], sizeof(obj[i])) && isOk; } return isOk; } bool Load(uint8_t* obj, uint32_t count, Deserializer& serializer) { bool isOk = true; for (int32_t i = 0; i < count; ++i) { isOk = serializer.Read(&obj[i], sizeof(obj[i])) && isOk; } return isOk; } bool Save(const uint16_t* obj, uint32_t count, Serializer& serializer) { bool isOk = true; for (uint32_t i = 0; i < count; ++i) { isOk = serializer.Write(&obj[i], sizeof(obj[i])) && isOk; } return isOk; } bool Load(uint16_t* obj, uint32_t count, Deserializer& serializer) { bool isOk = true; for (int32_t i = 0; i < count; ++i) { isOk = serializer.Read(&obj[i], sizeof(obj[i])) && isOk; } return isOk; } bool Save(const uint32_t* obj, uint32_t count, Serializer& serializer) { bool isOk = true; for (uint32_t i = 0; i < count; ++i) { isOk = serializer.Write(&obj[i], sizeof(obj[i])) && isOk; } return isOk; } bool Load(uint32_t* obj, uint32_t count, Deserializer& serializer) { bool isOk = true; for (int32_t i = 0; i < count; ++i) { isOk = serializer.Read(&obj[i], sizeof(obj[i])) && isOk; } return isOk; } bool Save(const uint64_t* obj, uint32_t count, Serializer& serializer) { bool isOk = true; for (uint32_t i = 0; i < count; ++i) { isOk = serializer.Write(&obj[i], sizeof(obj[i])) && isOk; } return isOk; } bool Load(uint64_t* obj, uint32_t count, Deserializer& serializer) { bool isOk = true; for (int32_t i = 0; i < count; ++i) { isOk = serializer.Read(&obj[i], sizeof(obj[i])) && isOk; } return isOk; } bool Save(const bool* obj, uint32_t count, Serializer& serializer) { bool isOk = true; for (uint32_t i = 0; i < count; ++i) { isOk = serializer.Write(&obj[i], sizeof(obj[i])) && isOk; } return isOk; } bool Load(bool* obj, uint32_t count, Deserializer& serializer) { bool isOk = true; for (int32_t i = 0; i < count; ++i) { isOk = serializer.Read(&obj[i], sizeof(obj[i])) && isOk; } return isOk; } bool Save(const float* obj, uint32_t count, Serializer& serializer) { bool isOk = true; for (uint32_t i = 0; i < count; ++i) { isOk = serializer.Write(&obj[i], sizeof(obj[i])) && isOk; } return isOk; } bool Load(float* obj, uint32_t count, Deserializer& serializer) { bool isOk = true; for (int32_t i = 0; i < count; ++i) { isOk = serializer.Read(&obj[i], sizeof(obj[i])) && isOk; } return isOk; } bool Save(const double* obj, uint32_t count, Serializer& serializer) { bool isOk = true; for (uint32_t i = 0; i < count; ++i) { isOk = serializer.Write(&obj[i], sizeof(obj[i])) && isOk; } return isOk; } bool Load(double* obj, uint32_t count, Deserializer& serializer) { bool isOk = true; for (int32_t i = 0; i < count; ++i) { isOk = serializer.Read(&obj[i], sizeof(obj[i])) && isOk; } return isOk; } bool Save(const char* obj, uint32_t count, Serializer& serializer) { bool isOk = true; for (uint32_t i = 0; i < count; ++i) { isOk = serializer.Write(&obj[i], sizeof(obj[i])) && isOk; } return isOk; } bool Load(char* obj, uint32_t count, Deserializer& serializer) { bool isOk = true; for (int32_t i = 0; i < count; ++i) { isOk = serializer.Read(&obj[i], sizeof(obj[i])) && isOk; } return isOk; } bool Save(const Vec2* obj, uint32_t count, Serializer& serializer) { bool isOk = true; for (uint32_t i = 0; i < count; ++i) { isOk = Save(&obj[i].x, 1, serializer) && isOk; isOk = Save(&obj[i].y, 1, serializer) && isOk; } return isOk; } bool Load(Vec2* obj, uint32_t count, Deserializer& serializer) { const char* typeName = Meta::Metadata.TypeDefinitions[Vec2::TypeIdx].Name; // Quick match int32_t matchedHashIdx = serializer.TypeBuf.FindHash(Meta::Metadata.TypeDefinitions[Vec2::TypeIdx].Hash); if (matchedHashIdx >= 0) { assert(bx::strCmp(serializer.TypeBuf.Defs[matchedHashIdx].Name, typeName) == 0); bool isOk = true; for (uint32_t i = 0; i < count; ++i) { isOk = Load(&obj[i].x, 1, serializer) && isOk; isOk = Load(&obj[i].y, 1, serializer) && isOk; } // if we're not ok here, something went really wrong assert(isOk); return isOk; } // Failed to resolve hash, the type definition chaned since the file was saved! try to match by name. *obj = {}; int32_t nameMatchIdx = serializer.TypeBuf.FindDefByName(typeName); if (nameMatchIdx < 0) { // Name match failed, caller has to handle this and potentially skip some bytes return false; } // Successfully matched name, but we need to follow the definition of the file now! const Meta::TypeDef& matchedDef = serializer.TypeBuf.Defs[nameMatchIdx]; // Figure out new member mapping uint64_t WriteDestinations[64]; for (int32_t i = 0; i < BX_COUNTOF(WriteDestinations); ++i) { WriteDestinations[i] = UINT64_MAX; } for (uint32_t i = 0; i < matchedDef.ChildCount; ++i) { const bx::StringView memberName = {&serializer.MemberNameBuf[matchedDef.MemberNameIndices[i].Offset], matchedDef.MemberNameIndices[i].Size}; const char* memberTypeName = serializer.TypeBuf.Defs[matchedDef.ChildIndices[i]].Name; if (bx::strCmp(memberName, "x") == 0 && bx::strCmp(memberTypeName, "f32") == 0) { WriteDestinations[i] = offsetof(Vec2, x); } if (bx::strCmp(memberName, "y") == 0 && bx::strCmp(memberTypeName, "f32") == 0) { WriteDestinations[i] = offsetof(Vec2, y); } } // Start reading in file order, skipping things that we don't know by name and type bool isOk = true; for (uint32_t i = 0; i < count; ++i) { uint8_t* objBasePtr = reinterpret_cast(&obj[i]); for (uint32_t j = 0; j < matchedDef.ChildCount; ++j) { const Meta::TypeDef& childDef = serializer.TypeBuf.Defs[matchedDef.ChildIndices[j]]; const bx::StringView memberName = {&serializer.MemberNameBuf[matchedDef.MemberNameIndices[j].Offset], matchedDef.MemberNameIndices[j].Size}; if (WriteDestinations[j] == UINT64_MAX) { // Unknown member name or type changed uint16_t count = bx::max(1, matchedDef.ChildArraySizes[matchedDef.ChildIndices[j]]); serializer.Skip(childDef.Size * count); continue; } if (bx::strCmp(memberName, "x") == 0) { auto* fieldPtr = reinterpret_cast(objBasePtr + WriteDestinations[j]); isOk = Load(fieldPtr, 1, serializer) && isOk; continue; } if (bx::strCmp(memberName, "y") == 0) { auto* fieldPtr = reinterpret_cast(objBasePtr + WriteDestinations[j]); isOk = Load(fieldPtr, 1, serializer) && isOk; continue; } assert(false); } } assert(isOk); return isOk; } bool Save(const Vec3* obj, uint32_t count, Serializer& serializer) { bool isOk = true; for (uint32_t i = 0; i < count; ++i) { isOk = Save(&obj[i].x, 1, serializer) && isOk; isOk = Save(&obj[i].y, 1, serializer) && isOk; isOk = Save(&obj[i].z, 1, serializer) && isOk; } return isOk; } bool Load(Vec3* obj, uint32_t count, Deserializer& serializer) { const char* typeName = Meta::Metadata.TypeDefinitions[Vec3::TypeIdx].Name; // Quick match int32_t matchedHashIdx = serializer.TypeBuf.FindHash(Meta::Metadata.TypeDefinitions[Vec3::TypeIdx].Hash); if (matchedHashIdx >= 0) { assert(bx::strCmp(serializer.TypeBuf.Defs[matchedHashIdx].Name, typeName) == 0); bool isOk = true; for (uint32_t i = 0; i < count; ++i) { isOk = Load(&obj[i].x, 1, serializer) && isOk; isOk = Load(&obj[i].y, 1, serializer) && isOk; isOk = Load(&obj[i].z, 1, serializer) && isOk; } // if we're not ok here, something went really wrong assert(isOk); return isOk; } // Failed to resolve hash, the type definition chaned since the file was saved! try to match by name. *obj = {}; int32_t nameMatchIdx = serializer.TypeBuf.FindDefByName(typeName); if (nameMatchIdx < 0) { // Name match failed, caller has to handle this and potentially skip some bytes return false; } // Successfully matched name, but we need to follow the definition of the file now! const Meta::TypeDef& matchedDef = serializer.TypeBuf.Defs[nameMatchIdx]; // Figure out new member mapping uint64_t WriteDestinations[64]; for (int32_t i = 0; i < BX_COUNTOF(WriteDestinations); ++i) { WriteDestinations[i] = UINT64_MAX; } for (uint32_t i = 0; i < matchedDef.ChildCount; ++i) { const bx::StringView memberName = {&serializer.MemberNameBuf[matchedDef.MemberNameIndices[i].Offset], matchedDef.MemberNameIndices[i].Size}; const char* memberTypeName = serializer.TypeBuf.Defs[matchedDef.ChildIndices[i]].Name; if (bx::strCmp(memberName, "x") == 0 && bx::strCmp(memberTypeName, "f32") == 0) { WriteDestinations[i] = offsetof(Vec3, x); } if (bx::strCmp(memberName, "y") == 0 && bx::strCmp(memberTypeName, "f32") == 0) { WriteDestinations[i] = offsetof(Vec3, y); } if (bx::strCmp(memberName, "z") == 0 && bx::strCmp(memberTypeName, "f32") == 0) { WriteDestinations[i] = offsetof(Vec3, z); } } // Start reading in file order, skipping things that we don't know by name and type bool isOk = true; for (uint32_t i = 0; i < count; ++i) { uint8_t* objBasePtr = reinterpret_cast(&obj[i]); for (uint32_t j = 0; j < matchedDef.ChildCount; ++j) { const Meta::TypeDef& childDef = serializer.TypeBuf.Defs[matchedDef.ChildIndices[j]]; const bx::StringView memberName = {&serializer.MemberNameBuf[matchedDef.MemberNameIndices[j].Offset], matchedDef.MemberNameIndices[j].Size}; if (WriteDestinations[j] == UINT64_MAX) { // Unknown member name or type changed uint16_t count = bx::max(1, matchedDef.ChildArraySizes[matchedDef.ChildIndices[j]]); serializer.Skip(childDef.Size * count); continue; } if (bx::strCmp(memberName, "x") == 0) { auto* fieldPtr = reinterpret_cast(objBasePtr + WriteDestinations[j]); isOk = Load(fieldPtr, 1, serializer) && isOk; continue; } if (bx::strCmp(memberName, "y") == 0) { auto* fieldPtr = reinterpret_cast(objBasePtr + WriteDestinations[j]); isOk = Load(fieldPtr, 1, serializer) && isOk; continue; } if (bx::strCmp(memberName, "z") == 0) { auto* fieldPtr = reinterpret_cast(objBasePtr + WriteDestinations[j]); isOk = Load(fieldPtr, 1, serializer) && isOk; continue; } assert(false); } } assert(isOk); return isOk; } bool Save(const Vec4* obj, uint32_t count, Serializer& serializer) { bool isOk = true; for (uint32_t i = 0; i < count; ++i) { isOk = Save(&obj[i].x, 1, serializer) && isOk; isOk = Save(&obj[i].y, 1, serializer) && isOk; isOk = Save(&obj[i].z, 1, serializer) && isOk; isOk = Save(&obj[i].w, 1, serializer) && isOk; } return isOk; } bool Load(Vec4* obj, uint32_t count, Deserializer& serializer) { const char* typeName = Meta::Metadata.TypeDefinitions[Vec4::TypeIdx].Name; // Quick match int32_t matchedHashIdx = serializer.TypeBuf.FindHash(Meta::Metadata.TypeDefinitions[Vec4::TypeIdx].Hash); if (matchedHashIdx >= 0) { assert(bx::strCmp(serializer.TypeBuf.Defs[matchedHashIdx].Name, typeName) == 0); bool isOk = true; for (uint32_t i = 0; i < count; ++i) { isOk = Load(&obj[i].x, 1, serializer) && isOk; isOk = Load(&obj[i].y, 1, serializer) && isOk; isOk = Load(&obj[i].z, 1, serializer) && isOk; isOk = Load(&obj[i].w, 1, serializer) && isOk; } // if we're not ok here, something went really wrong assert(isOk); return isOk; } // Failed to resolve hash, the type definition chaned since the file was saved! try to match by name. *obj = {}; int32_t nameMatchIdx = serializer.TypeBuf.FindDefByName(typeName); if (nameMatchIdx < 0) { // Name match failed, caller has to handle this and potentially skip some bytes return false; } // Successfully matched name, but we need to follow the definition of the file now! const Meta::TypeDef& matchedDef = serializer.TypeBuf.Defs[nameMatchIdx]; // Figure out new member mapping uint64_t WriteDestinations[64]; for (int32_t i = 0; i < BX_COUNTOF(WriteDestinations); ++i) { WriteDestinations[i] = UINT64_MAX; } for (uint32_t i = 0; i < matchedDef.ChildCount; ++i) { const bx::StringView memberName = {&serializer.MemberNameBuf[matchedDef.MemberNameIndices[i].Offset], matchedDef.MemberNameIndices[i].Size}; const char* memberTypeName = serializer.TypeBuf.Defs[matchedDef.ChildIndices[i]].Name; if (bx::strCmp(memberName, "x") == 0 && bx::strCmp(memberTypeName, "f32") == 0) { WriteDestinations[i] = offsetof(Vec4, x); } if (bx::strCmp(memberName, "y") == 0 && bx::strCmp(memberTypeName, "f32") == 0) { WriteDestinations[i] = offsetof(Vec4, y); } if (bx::strCmp(memberName, "z") == 0 && bx::strCmp(memberTypeName, "f32") == 0) { WriteDestinations[i] = offsetof(Vec4, z); } if (bx::strCmp(memberName, "w") == 0 && bx::strCmp(memberTypeName, "f32") == 0) { WriteDestinations[i] = offsetof(Vec4, w); } } // Start reading in file order, skipping things that we don't know by name and type bool isOk = true; for (uint32_t i = 0; i < count; ++i) { uint8_t* objBasePtr = reinterpret_cast(&obj[i]); for (uint32_t j = 0; j < matchedDef.ChildCount; ++j) { const Meta::TypeDef& childDef = serializer.TypeBuf.Defs[matchedDef.ChildIndices[j]]; const bx::StringView memberName = {&serializer.MemberNameBuf[matchedDef.MemberNameIndices[j].Offset], matchedDef.MemberNameIndices[j].Size}; if (WriteDestinations[j] == UINT64_MAX) { // Unknown member name or type changed uint16_t count = bx::max(1, matchedDef.ChildArraySizes[matchedDef.ChildIndices[j]]); serializer.Skip(childDef.Size * count); continue; } if (bx::strCmp(memberName, "x") == 0) { auto* fieldPtr = reinterpret_cast(objBasePtr + WriteDestinations[j]); isOk = Load(fieldPtr, 1, serializer) && isOk; continue; } if (bx::strCmp(memberName, "y") == 0) { auto* fieldPtr = reinterpret_cast(objBasePtr + WriteDestinations[j]); isOk = Load(fieldPtr, 1, serializer) && isOk; continue; } if (bx::strCmp(memberName, "z") == 0) { auto* fieldPtr = reinterpret_cast(objBasePtr + WriteDestinations[j]); isOk = Load(fieldPtr, 1, serializer) && isOk; continue; } if (bx::strCmp(memberName, "w") == 0) { auto* fieldPtr = reinterpret_cast(objBasePtr + WriteDestinations[j]); isOk = Load(fieldPtr, 1, serializer) && isOk; continue; } assert(false); } } assert(isOk); return isOk; } bool Save(const Mat3* obj, uint32_t count, Serializer& serializer) { bool isOk = true; for (uint32_t i = 0; i < count; ++i) { isOk = Save(obj[i].M, 9, serializer) && isOk; } return isOk; } bool Load(Mat3* obj, uint32_t count, Deserializer& serializer) { const char* typeName = Meta::Metadata.TypeDefinitions[Mat3::TypeIdx].Name; // Quick match int32_t matchedHashIdx = serializer.TypeBuf.FindHash(Meta::Metadata.TypeDefinitions[Mat3::TypeIdx].Hash); if (matchedHashIdx >= 0) { assert(bx::strCmp(serializer.TypeBuf.Defs[matchedHashIdx].Name, typeName) == 0); bool isOk = true; for (uint32_t i = 0; i < count; ++i) { isOk = Load(obj[i].M, 9, serializer) && isOk; } // if we're not ok here, something went really wrong assert(isOk); return isOk; } // Failed to resolve hash, the type definition chaned since the file was saved! try to match by name. *obj = {}; int32_t nameMatchIdx = serializer.TypeBuf.FindDefByName(typeName); if (nameMatchIdx < 0) { // Name match failed, caller has to handle this and potentially skip some bytes return false; } // Successfully matched name, but we need to follow the definition of the file now! const Meta::TypeDef& matchedDef = serializer.TypeBuf.Defs[nameMatchIdx]; // Figure out new member mapping uint64_t WriteDestinations[64]; for (int32_t i = 0; i < BX_COUNTOF(WriteDestinations); ++i) { WriteDestinations[i] = UINT64_MAX; } for (uint32_t i = 0; i < matchedDef.ChildCount; ++i) { const bx::StringView memberName = {&serializer.MemberNameBuf[matchedDef.MemberNameIndices[i].Offset], matchedDef.MemberNameIndices[i].Size}; const char* memberTypeName = serializer.TypeBuf.Defs[matchedDef.ChildIndices[i]].Name; if (bx::strCmp(memberName, "M") == 0 && bx::strCmp(memberTypeName, "f32") == 0) { WriteDestinations[i] = offsetof(Mat3, M); } } // Start reading in file order, skipping things that we don't know by name and type bool isOk = true; for (uint32_t i = 0; i < count; ++i) { uint8_t* objBasePtr = reinterpret_cast(&obj[i]); for (uint32_t j = 0; j < matchedDef.ChildCount; ++j) { const Meta::TypeDef& childDef = serializer.TypeBuf.Defs[matchedDef.ChildIndices[j]]; const bx::StringView memberName = {&serializer.MemberNameBuf[matchedDef.MemberNameIndices[j].Offset], matchedDef.MemberNameIndices[j].Size}; if (WriteDestinations[j] == UINT64_MAX) { // Unknown member name or type changed uint16_t count = bx::max(1, matchedDef.ChildArraySizes[matchedDef.ChildIndices[j]]); serializer.Skip(childDef.Size * count); continue; } if (bx::strCmp(memberName, "M") == 0) { auto* fieldPtr = reinterpret_cast(objBasePtr + WriteDestinations[j]); isOk = Load(fieldPtr, 9, serializer) && isOk; continue; } assert(false); } } assert(isOk); return isOk; } bool Save(const Mat4* obj, uint32_t count, Serializer& serializer) { bool isOk = true; for (uint32_t i = 0; i < count; ++i) { isOk = Save(obj[i].M, 16, serializer) && isOk; } return isOk; } bool Load(Mat4* obj, uint32_t count, Deserializer& serializer) { const char* typeName = Meta::Metadata.TypeDefinitions[Mat4::TypeIdx].Name; // Quick match int32_t matchedHashIdx = serializer.TypeBuf.FindHash(Meta::Metadata.TypeDefinitions[Mat4::TypeIdx].Hash); if (matchedHashIdx >= 0) { assert(bx::strCmp(serializer.TypeBuf.Defs[matchedHashIdx].Name, typeName) == 0); bool isOk = true; for (uint32_t i = 0; i < count; ++i) { isOk = Load(obj[i].M, 16, serializer) && isOk; } // if we're not ok here, something went really wrong assert(isOk); return isOk; } // Failed to resolve hash, the type definition chaned since the file was saved! try to match by name. *obj = {}; int32_t nameMatchIdx = serializer.TypeBuf.FindDefByName(typeName); if (nameMatchIdx < 0) { // Name match failed, caller has to handle this and potentially skip some bytes return false; } // Successfully matched name, but we need to follow the definition of the file now! const Meta::TypeDef& matchedDef = serializer.TypeBuf.Defs[nameMatchIdx]; // Figure out new member mapping uint64_t WriteDestinations[64]; for (int32_t i = 0; i < BX_COUNTOF(WriteDestinations); ++i) { WriteDestinations[i] = UINT64_MAX; } for (uint32_t i = 0; i < matchedDef.ChildCount; ++i) { const bx::StringView memberName = {&serializer.MemberNameBuf[matchedDef.MemberNameIndices[i].Offset], matchedDef.MemberNameIndices[i].Size}; const char* memberTypeName = serializer.TypeBuf.Defs[matchedDef.ChildIndices[i]].Name; if (bx::strCmp(memberName, "M") == 0 && bx::strCmp(memberTypeName, "f32") == 0) { WriteDestinations[i] = offsetof(Mat4, M); } } // Start reading in file order, skipping things that we don't know by name and type bool isOk = true; for (uint32_t i = 0; i < count; ++i) { uint8_t* objBasePtr = reinterpret_cast(&obj[i]); for (uint32_t j = 0; j < matchedDef.ChildCount; ++j) { const Meta::TypeDef& childDef = serializer.TypeBuf.Defs[matchedDef.ChildIndices[j]]; const bx::StringView memberName = {&serializer.MemberNameBuf[matchedDef.MemberNameIndices[j].Offset], matchedDef.MemberNameIndices[j].Size}; if (WriteDestinations[j] == UINT64_MAX) { // Unknown member name or type changed uint16_t count = bx::max(1, matchedDef.ChildArraySizes[matchedDef.ChildIndices[j]]); serializer.Skip(childDef.Size * count); continue; } if (bx::strCmp(memberName, "M") == 0) { auto* fieldPtr = reinterpret_cast(objBasePtr + WriteDestinations[j]); isOk = Load(fieldPtr, 16, serializer) && isOk; continue; } assert(false); } } assert(isOk); return isOk; } bool Save(const Transform* obj, uint32_t count, Serializer& serializer) { bool isOk = true; for (uint32_t i = 0; i < count; ++i) { isOk = Save(&obj[i].M, 1, serializer) && isOk; isOk = Save(&obj[i].MI, 1, serializer) && isOk; isOk = Save(&obj[i].Position, 1, serializer) && isOk; isOk = Save(&obj[i].Rotation, 1, serializer) && isOk; isOk = Save(&obj[i].Scale, 1, serializer) && isOk; } return isOk; } bool Load(Transform* obj, uint32_t count, Deserializer& serializer) { const char* typeName = Meta::Metadata.TypeDefinitions[Transform::TypeIdx].Name; // Quick match int32_t matchedHashIdx = serializer.TypeBuf.FindHash(Meta::Metadata.TypeDefinitions[Transform::TypeIdx].Hash); if (matchedHashIdx >= 0) { assert(bx::strCmp(serializer.TypeBuf.Defs[matchedHashIdx].Name, typeName) == 0); bool isOk = true; for (uint32_t i = 0; i < count; ++i) { isOk = Load(&obj[i].M, 1, serializer) && isOk; isOk = Load(&obj[i].MI, 1, serializer) && isOk; isOk = Load(&obj[i].Position, 1, serializer) && isOk; isOk = Load(&obj[i].Rotation, 1, serializer) && isOk; isOk = Load(&obj[i].Scale, 1, serializer) && isOk; } // if we're not ok here, something went really wrong assert(isOk); return isOk; } // Failed to resolve hash, the type definition chaned since the file was saved! try to match by name. *obj = {}; int32_t nameMatchIdx = serializer.TypeBuf.FindDefByName(typeName); if (nameMatchIdx < 0) { // Name match failed, caller has to handle this and potentially skip some bytes return false; } // Successfully matched name, but we need to follow the definition of the file now! const Meta::TypeDef& matchedDef = serializer.TypeBuf.Defs[nameMatchIdx]; // Figure out new member mapping uint64_t WriteDestinations[64]; for (int32_t i = 0; i < BX_COUNTOF(WriteDestinations); ++i) { WriteDestinations[i] = UINT64_MAX; } for (uint32_t i = 0; i < matchedDef.ChildCount; ++i) { const bx::StringView memberName = {&serializer.MemberNameBuf[matchedDef.MemberNameIndices[i].Offset], matchedDef.MemberNameIndices[i].Size}; const char* memberTypeName = serializer.TypeBuf.Defs[matchedDef.ChildIndices[i]].Name; if (bx::strCmp(memberName, "M") == 0 && bx::strCmp(memberTypeName, "Mat4") == 0) { WriteDestinations[i] = offsetof(Transform, M); } if (bx::strCmp(memberName, "MI") == 0 && bx::strCmp(memberTypeName, "Mat4") == 0) { WriteDestinations[i] = offsetof(Transform, MI); } if (bx::strCmp(memberName, "Position") == 0 && bx::strCmp(memberTypeName, "Vec3") == 0) { WriteDestinations[i] = offsetof(Transform, Position); } if (bx::strCmp(memberName, "Rotation") == 0 && bx::strCmp(memberTypeName, "Mat4") == 0) { WriteDestinations[i] = offsetof(Transform, Rotation); } if (bx::strCmp(memberName, "Scale") == 0 && bx::strCmp(memberTypeName, "Vec3") == 0) { WriteDestinations[i] = offsetof(Transform, Scale); } } // Start reading in file order, skipping things that we don't know by name and type bool isOk = true; for (uint32_t i = 0; i < count; ++i) { uint8_t* objBasePtr = reinterpret_cast(&obj[i]); for (uint32_t j = 0; j < matchedDef.ChildCount; ++j) { const Meta::TypeDef& childDef = serializer.TypeBuf.Defs[matchedDef.ChildIndices[j]]; const bx::StringView memberName = {&serializer.MemberNameBuf[matchedDef.MemberNameIndices[j].Offset], matchedDef.MemberNameIndices[j].Size}; if (WriteDestinations[j] == UINT64_MAX) { // Unknown member name or type changed uint16_t count = bx::max(1, matchedDef.ChildArraySizes[matchedDef.ChildIndices[j]]); serializer.Skip(childDef.Size * count); continue; } if (bx::strCmp(memberName, "M") == 0) { auto* fieldPtr = reinterpret_cast(objBasePtr + WriteDestinations[j]); isOk = Load(fieldPtr, 1, serializer) && isOk; continue; } if (bx::strCmp(memberName, "MI") == 0) { auto* fieldPtr = reinterpret_cast(objBasePtr + WriteDestinations[j]); isOk = Load(fieldPtr, 1, serializer) && isOk; continue; } if (bx::strCmp(memberName, "Position") == 0) { auto* fieldPtr = reinterpret_cast(objBasePtr + WriteDestinations[j]); isOk = Load(fieldPtr, 1, serializer) && isOk; continue; } if (bx::strCmp(memberName, "Rotation") == 0) { auto* fieldPtr = reinterpret_cast(objBasePtr + WriteDestinations[j]); isOk = Load(fieldPtr, 1, serializer) && isOk; continue; } if (bx::strCmp(memberName, "Scale") == 0) { auto* fieldPtr = reinterpret_cast(objBasePtr + WriteDestinations[j]); isOk = Load(fieldPtr, 1, serializer) && isOk; continue; } assert(false); } } assert(isOk); return isOk; } bool Save(const AssetHandle* obj, uint32_t count, Serializer& serializer) { bool isOk = true; for (uint32_t i = 0; i < count; ++i) { isOk = Save(&obj[i].Idx, 1, serializer) && isOk; } return isOk; } bool Load(AssetHandle* obj, uint32_t count, Deserializer& serializer) { const char* typeName = Meta::Metadata.TypeDefinitions[AssetHandle::TypeIdx].Name; // Quick match int32_t matchedHashIdx = serializer.TypeBuf.FindHash(Meta::Metadata.TypeDefinitions[AssetHandle::TypeIdx].Hash); if (matchedHashIdx >= 0) { assert(bx::strCmp(serializer.TypeBuf.Defs[matchedHashIdx].Name, typeName) == 0); bool isOk = true; for (uint32_t i = 0; i < count; ++i) { isOk = Load(&obj[i].Idx, 1, serializer) && isOk; } // if we're not ok here, something went really wrong assert(isOk); return isOk; } // Failed to resolve hash, the type definition chaned since the file was saved! try to match by name. *obj = {}; int32_t nameMatchIdx = serializer.TypeBuf.FindDefByName(typeName); if (nameMatchIdx < 0) { // Name match failed, caller has to handle this and potentially skip some bytes return false; } // Successfully matched name, but we need to follow the definition of the file now! const Meta::TypeDef& matchedDef = serializer.TypeBuf.Defs[nameMatchIdx]; // Figure out new member mapping uint64_t WriteDestinations[64]; for (int32_t i = 0; i < BX_COUNTOF(WriteDestinations); ++i) { WriteDestinations[i] = UINT64_MAX; } for (uint32_t i = 0; i < matchedDef.ChildCount; ++i) { const bx::StringView memberName = {&serializer.MemberNameBuf[matchedDef.MemberNameIndices[i].Offset], matchedDef.MemberNameIndices[i].Size}; const char* memberTypeName = serializer.TypeBuf.Defs[matchedDef.ChildIndices[i]].Name; if (bx::strCmp(memberName, "Idx") == 0 && bx::strCmp(memberTypeName, "u32") == 0) { WriteDestinations[i] = offsetof(AssetHandle, Idx); } } // Start reading in file order, skipping things that we don't know by name and type bool isOk = true; for (uint32_t i = 0; i < count; ++i) { uint8_t* objBasePtr = reinterpret_cast(&obj[i]); for (uint32_t j = 0; j < matchedDef.ChildCount; ++j) { const Meta::TypeDef& childDef = serializer.TypeBuf.Defs[matchedDef.ChildIndices[j]]; const bx::StringView memberName = {&serializer.MemberNameBuf[matchedDef.MemberNameIndices[j].Offset], matchedDef.MemberNameIndices[j].Size}; if (WriteDestinations[j] == UINT64_MAX) { // Unknown member name or type changed uint16_t count = bx::max(1, matchedDef.ChildArraySizes[matchedDef.ChildIndices[j]]); serializer.Skip(childDef.Size * count); continue; } if (bx::strCmp(memberName, "Idx") == 0) { auto* fieldPtr = reinterpret_cast(objBasePtr + WriteDestinations[j]); isOk = Load(fieldPtr, 1, serializer) && isOk; continue; } assert(false); } } assert(isOk); return isOk; } bool Save(const ModelHandle* obj, uint32_t count, Serializer& serializer) { bool isOk = true; for (uint32_t i = 0; i < count; ++i) { isOk = Save(&obj[i].ModelIdx, 1, serializer) && isOk; isOk = Save(&obj[i].Asset, 1, serializer) && isOk; } return isOk; } bool Load(ModelHandle* obj, uint32_t count, Deserializer& serializer) { const char* typeName = Meta::Metadata.TypeDefinitions[ModelHandle::TypeIdx].Name; // Quick match int32_t matchedHashIdx = serializer.TypeBuf.FindHash(Meta::Metadata.TypeDefinitions[ModelHandle::TypeIdx].Hash); if (matchedHashIdx >= 0) { assert(bx::strCmp(serializer.TypeBuf.Defs[matchedHashIdx].Name, typeName) == 0); bool isOk = true; for (uint32_t i = 0; i < count; ++i) { isOk = Load(&obj[i].ModelIdx, 1, serializer) && isOk; isOk = Load(&obj[i].Asset, 1, serializer) && isOk; } // if we're not ok here, something went really wrong assert(isOk); return isOk; } // Failed to resolve hash, the type definition chaned since the file was saved! try to match by name. *obj = {}; int32_t nameMatchIdx = serializer.TypeBuf.FindDefByName(typeName); if (nameMatchIdx < 0) { // Name match failed, caller has to handle this and potentially skip some bytes return false; } // Successfully matched name, but we need to follow the definition of the file now! const Meta::TypeDef& matchedDef = serializer.TypeBuf.Defs[nameMatchIdx]; // Figure out new member mapping uint64_t WriteDestinations[64]; for (int32_t i = 0; i < BX_COUNTOF(WriteDestinations); ++i) { WriteDestinations[i] = UINT64_MAX; } for (uint32_t i = 0; i < matchedDef.ChildCount; ++i) { const bx::StringView memberName = {&serializer.MemberNameBuf[matchedDef.MemberNameIndices[i].Offset], matchedDef.MemberNameIndices[i].Size}; const char* memberTypeName = serializer.TypeBuf.Defs[matchedDef.ChildIndices[i]].Name; if (bx::strCmp(memberName, "ModelIdx") == 0 && bx::strCmp(memberTypeName, "u16") == 0) { WriteDestinations[i] = offsetof(ModelHandle, ModelIdx); } if (bx::strCmp(memberName, "Asset") == 0 && bx::strCmp(memberTypeName, "AssetHandle") == 0) { WriteDestinations[i] = offsetof(ModelHandle, Asset); } } // Start reading in file order, skipping things that we don't know by name and type bool isOk = true; for (uint32_t i = 0; i < count; ++i) { uint8_t* objBasePtr = reinterpret_cast(&obj[i]); for (uint32_t j = 0; j < matchedDef.ChildCount; ++j) { const Meta::TypeDef& childDef = serializer.TypeBuf.Defs[matchedDef.ChildIndices[j]]; const bx::StringView memberName = {&serializer.MemberNameBuf[matchedDef.MemberNameIndices[j].Offset], matchedDef.MemberNameIndices[j].Size}; if (WriteDestinations[j] == UINT64_MAX) { // Unknown member name or type changed uint16_t count = bx::max(1, matchedDef.ChildArraySizes[matchedDef.ChildIndices[j]]); serializer.Skip(childDef.Size * count); continue; } if (bx::strCmp(memberName, "ModelIdx") == 0) { auto* fieldPtr = reinterpret_cast(objBasePtr + WriteDestinations[j]); isOk = Load(fieldPtr, 1, serializer) && isOk; continue; } if (bx::strCmp(memberName, "Asset") == 0) { auto* fieldPtr = reinterpret_cast(objBasePtr + WriteDestinations[j]); isOk = Load(fieldPtr, 1, serializer) && isOk; continue; } assert(false); } } assert(isOk); return isOk; } bool Save(const TextureHandle* obj, uint32_t count, Serializer& serializer) { bool isOk = true; for (uint32_t i = 0; i < count; ++i) { isOk = Save(&obj[i].TextureIdx, 1, serializer) && isOk; isOk = Save(&obj[i].Asset, 1, serializer) && isOk; } return isOk; } bool Load(TextureHandle* obj, uint32_t count, Deserializer& serializer) { const char* typeName = Meta::Metadata.TypeDefinitions[TextureHandle::TypeIdx].Name; // Quick match int32_t matchedHashIdx = serializer.TypeBuf.FindHash(Meta::Metadata.TypeDefinitions[TextureHandle::TypeIdx].Hash); if (matchedHashIdx >= 0) { assert(bx::strCmp(serializer.TypeBuf.Defs[matchedHashIdx].Name, typeName) == 0); bool isOk = true; for (uint32_t i = 0; i < count; ++i) { isOk = Load(&obj[i].TextureIdx, 1, serializer) && isOk; isOk = Load(&obj[i].Asset, 1, serializer) && isOk; } // if we're not ok here, something went really wrong assert(isOk); return isOk; } // Failed to resolve hash, the type definition chaned since the file was saved! try to match by name. *obj = {}; int32_t nameMatchIdx = serializer.TypeBuf.FindDefByName(typeName); if (nameMatchIdx < 0) { // Name match failed, caller has to handle this and potentially skip some bytes return false; } // Successfully matched name, but we need to follow the definition of the file now! const Meta::TypeDef& matchedDef = serializer.TypeBuf.Defs[nameMatchIdx]; // Figure out new member mapping uint64_t WriteDestinations[64]; for (int32_t i = 0; i < BX_COUNTOF(WriteDestinations); ++i) { WriteDestinations[i] = UINT64_MAX; } for (uint32_t i = 0; i < matchedDef.ChildCount; ++i) { const bx::StringView memberName = {&serializer.MemberNameBuf[matchedDef.MemberNameIndices[i].Offset], matchedDef.MemberNameIndices[i].Size}; const char* memberTypeName = serializer.TypeBuf.Defs[matchedDef.ChildIndices[i]].Name; if (bx::strCmp(memberName, "TextureIdx") == 0 && bx::strCmp(memberTypeName, "u16") == 0) { WriteDestinations[i] = offsetof(TextureHandle, TextureIdx); } if (bx::strCmp(memberName, "Asset") == 0 && bx::strCmp(memberTypeName, "AssetHandle") == 0) { WriteDestinations[i] = offsetof(TextureHandle, Asset); } } // Start reading in file order, skipping things that we don't know by name and type bool isOk = true; for (uint32_t i = 0; i < count; ++i) { uint8_t* objBasePtr = reinterpret_cast(&obj[i]); for (uint32_t j = 0; j < matchedDef.ChildCount; ++j) { const Meta::TypeDef& childDef = serializer.TypeBuf.Defs[matchedDef.ChildIndices[j]]; const bx::StringView memberName = {&serializer.MemberNameBuf[matchedDef.MemberNameIndices[j].Offset], matchedDef.MemberNameIndices[j].Size}; if (WriteDestinations[j] == UINT64_MAX) { // Unknown member name or type changed uint16_t count = bx::max(1, matchedDef.ChildArraySizes[matchedDef.ChildIndices[j]]); serializer.Skip(childDef.Size * count); continue; } if (bx::strCmp(memberName, "TextureIdx") == 0) { auto* fieldPtr = reinterpret_cast(objBasePtr + WriteDestinations[j]); isOk = Load(fieldPtr, 1, serializer) && isOk; continue; } if (bx::strCmp(memberName, "Asset") == 0) { auto* fieldPtr = reinterpret_cast(objBasePtr + WriteDestinations[j]); isOk = Load(fieldPtr, 1, serializer) && isOk; continue; } assert(false); } } assert(isOk); return isOk; } bool Save(const PuzPos* obj, uint32_t count, Serializer& serializer) { bool isOk = true; for (uint32_t i = 0; i < count; ++i) { isOk = Save(&obj[i].X, 1, serializer) && isOk; isOk = Save(&obj[i].Y, 1, serializer) && isOk; } return isOk; } bool Load(PuzPos* obj, uint32_t count, Deserializer& serializer) { const char* typeName = Meta::Metadata.TypeDefinitions[PuzPos::TypeIdx].Name; // Quick match int32_t matchedHashIdx = serializer.TypeBuf.FindHash(Meta::Metadata.TypeDefinitions[PuzPos::TypeIdx].Hash); if (matchedHashIdx >= 0) { assert(bx::strCmp(serializer.TypeBuf.Defs[matchedHashIdx].Name, typeName) == 0); bool isOk = true; for (uint32_t i = 0; i < count; ++i) { isOk = Load(&obj[i].X, 1, serializer) && isOk; isOk = Load(&obj[i].Y, 1, serializer) && isOk; } // if we're not ok here, something went really wrong assert(isOk); return isOk; } // Failed to resolve hash, the type definition chaned since the file was saved! try to match by name. *obj = {}; int32_t nameMatchIdx = serializer.TypeBuf.FindDefByName(typeName); if (nameMatchIdx < 0) { // Name match failed, caller has to handle this and potentially skip some bytes return false; } // Successfully matched name, but we need to follow the definition of the file now! const Meta::TypeDef& matchedDef = serializer.TypeBuf.Defs[nameMatchIdx]; // Figure out new member mapping uint64_t WriteDestinations[64]; for (int32_t i = 0; i < BX_COUNTOF(WriteDestinations); ++i) { WriteDestinations[i] = UINT64_MAX; } for (uint32_t i = 0; i < matchedDef.ChildCount; ++i) { const bx::StringView memberName = {&serializer.MemberNameBuf[matchedDef.MemberNameIndices[i].Offset], matchedDef.MemberNameIndices[i].Size}; const char* memberTypeName = serializer.TypeBuf.Defs[matchedDef.ChildIndices[i]].Name; if (bx::strCmp(memberName, "X") == 0 && bx::strCmp(memberTypeName, "i8") == 0) { WriteDestinations[i] = offsetof(PuzPos, X); } if (bx::strCmp(memberName, "Y") == 0 && bx::strCmp(memberTypeName, "i8") == 0) { WriteDestinations[i] = offsetof(PuzPos, Y); } } // Start reading in file order, skipping things that we don't know by name and type bool isOk = true; for (uint32_t i = 0; i < count; ++i) { uint8_t* objBasePtr = reinterpret_cast(&obj[i]); for (uint32_t j = 0; j < matchedDef.ChildCount; ++j) { const Meta::TypeDef& childDef = serializer.TypeBuf.Defs[matchedDef.ChildIndices[j]]; const bx::StringView memberName = {&serializer.MemberNameBuf[matchedDef.MemberNameIndices[j].Offset], matchedDef.MemberNameIndices[j].Size}; if (WriteDestinations[j] == UINT64_MAX) { // Unknown member name or type changed uint16_t count = bx::max(1, matchedDef.ChildArraySizes[matchedDef.ChildIndices[j]]); serializer.Skip(childDef.Size * count); continue; } if (bx::strCmp(memberName, "X") == 0) { auto* fieldPtr = reinterpret_cast(objBasePtr + WriteDestinations[j]); isOk = Load(fieldPtr, 1, serializer) && isOk; continue; } if (bx::strCmp(memberName, "Y") == 0) { auto* fieldPtr = reinterpret_cast(objBasePtr + WriteDestinations[j]); isOk = Load(fieldPtr, 1, serializer) && isOk; continue; } assert(false); } } assert(isOk); return isOk; } bool Save(const CardSocket* obj, uint32_t count, Serializer& serializer) { bool isOk = true; for (uint32_t i = 0; i < count; ++i) { isOk = Save(&obj[i].Model, 1, serializer) && isOk; isOk = Save(&obj[i].ConnectionDirection, 1, serializer) && isOk; } return isOk; } bool Load(CardSocket* obj, uint32_t count, Deserializer& serializer) { const char* typeName = Meta::Metadata.TypeDefinitions[CardSocket::TypeIdx].Name; // Quick match int32_t matchedHashIdx = serializer.TypeBuf.FindHash(Meta::Metadata.TypeDefinitions[CardSocket::TypeIdx].Hash); if (matchedHashIdx >= 0) { assert(bx::strCmp(serializer.TypeBuf.Defs[matchedHashIdx].Name, typeName) == 0); bool isOk = true; for (uint32_t i = 0; i < count; ++i) { isOk = Load(&obj[i].Model, 1, serializer) && isOk; isOk = Load(&obj[i].ConnectionDirection, 1, serializer) && isOk; } // if we're not ok here, something went really wrong assert(isOk); return isOk; } // Failed to resolve hash, the type definition chaned since the file was saved! try to match by name. *obj = {}; int32_t nameMatchIdx = serializer.TypeBuf.FindDefByName(typeName); if (nameMatchIdx < 0) { // Name match failed, caller has to handle this and potentially skip some bytes return false; } // Successfully matched name, but we need to follow the definition of the file now! const Meta::TypeDef& matchedDef = serializer.TypeBuf.Defs[nameMatchIdx]; // Figure out new member mapping uint64_t WriteDestinations[64]; for (int32_t i = 0; i < BX_COUNTOF(WriteDestinations); ++i) { WriteDestinations[i] = UINT64_MAX; } for (uint32_t i = 0; i < matchedDef.ChildCount; ++i) { const bx::StringView memberName = {&serializer.MemberNameBuf[matchedDef.MemberNameIndices[i].Offset], matchedDef.MemberNameIndices[i].Size}; const char* memberTypeName = serializer.TypeBuf.Defs[matchedDef.ChildIndices[i]].Name; if (bx::strCmp(memberName, "Model") == 0 && bx::strCmp(memberTypeName, "ModelHandle") == 0) { WriteDestinations[i] = offsetof(CardSocket, Model); } if (bx::strCmp(memberName, "ConnectionDirection") == 0 && bx::strCmp(memberTypeName, "u8") == 0) { WriteDestinations[i] = offsetof(CardSocket, ConnectionDirection); } } // Start reading in file order, skipping things that we don't know by name and type bool isOk = true; for (uint32_t i = 0; i < count; ++i) { uint8_t* objBasePtr = reinterpret_cast(&obj[i]); for (uint32_t j = 0; j < matchedDef.ChildCount; ++j) { const Meta::TypeDef& childDef = serializer.TypeBuf.Defs[matchedDef.ChildIndices[j]]; const bx::StringView memberName = {&serializer.MemberNameBuf[matchedDef.MemberNameIndices[j].Offset], matchedDef.MemberNameIndices[j].Size}; if (WriteDestinations[j] == UINT64_MAX) { // Unknown member name or type changed uint16_t count = bx::max(1, matchedDef.ChildArraySizes[matchedDef.ChildIndices[j]]); serializer.Skip(childDef.Size * count); continue; } if (bx::strCmp(memberName, "Model") == 0) { auto* fieldPtr = reinterpret_cast(objBasePtr + WriteDestinations[j]); isOk = Load(fieldPtr, 1, serializer) && isOk; continue; } if (bx::strCmp(memberName, "ConnectionDirection") == 0) { auto* fieldPtr = reinterpret_cast(objBasePtr + WriteDestinations[j]); isOk = Load(fieldPtr, 1, serializer) && isOk; continue; } assert(false); } } assert(isOk); return isOk; } bool Save(const StaticPuzzleCard* obj, uint32_t count, Serializer& serializer) { bool isOk = true; for (uint32_t i = 0; i < count; ++i) { isOk = Save(obj[i].Elements, 4, serializer) && isOk; isOk = Save(&obj[i].BaseModelHandle, 1, serializer) && isOk; isOk = Save(&obj[i].NorthCoverHandle, 1, serializer) && isOk; isOk = Save(&obj[i].EastCoverHandle, 1, serializer) && isOk; isOk = Save(&obj[i].SouthCoverHandle, 1, serializer) && isOk; isOk = Save(&obj[i].WestCoverHandle, 1, serializer) && isOk; isOk = Save(obj[i].Sockets, 16, serializer) && isOk; isOk = Save(&obj[i].ModelTextureHandle, 1, serializer) && isOk; isOk = Save(&obj[i].BoardTextureHandle, 1, serializer) && isOk; } return isOk; } bool Load(StaticPuzzleCard* obj, uint32_t count, Deserializer& serializer) { const char* typeName = Meta::Metadata.TypeDefinitions[StaticPuzzleCard::TypeIdx].Name; // Quick match int32_t matchedHashIdx = serializer.TypeBuf.FindHash(Meta::Metadata.TypeDefinitions[StaticPuzzleCard::TypeIdx].Hash); if (matchedHashIdx >= 0) { assert(bx::strCmp(serializer.TypeBuf.Defs[matchedHashIdx].Name, typeName) == 0); bool isOk = true; for (uint32_t i = 0; i < count; ++i) { isOk = Load(obj[i].Elements, 4, serializer) && isOk; isOk = Load(&obj[i].BaseModelHandle, 1, serializer) && isOk; isOk = Load(&obj[i].NorthCoverHandle, 1, serializer) && isOk; isOk = Load(&obj[i].EastCoverHandle, 1, serializer) && isOk; isOk = Load(&obj[i].SouthCoverHandle, 1, serializer) && isOk; isOk = Load(&obj[i].WestCoverHandle, 1, serializer) && isOk; isOk = Load(obj[i].Sockets, 16, serializer) && isOk; isOk = Load(&obj[i].ModelTextureHandle, 1, serializer) && isOk; isOk = Load(&obj[i].BoardTextureHandle, 1, serializer) && isOk; } // if we're not ok here, something went really wrong assert(isOk); return isOk; } // Failed to resolve hash, the type definition chaned since the file was saved! try to match by name. *obj = {}; int32_t nameMatchIdx = serializer.TypeBuf.FindDefByName(typeName); if (nameMatchIdx < 0) { // Name match failed, caller has to handle this and potentially skip some bytes return false; } // Successfully matched name, but we need to follow the definition of the file now! const Meta::TypeDef& matchedDef = serializer.TypeBuf.Defs[nameMatchIdx]; // Figure out new member mapping uint64_t WriteDestinations[64]; for (int32_t i = 0; i < BX_COUNTOF(WriteDestinations); ++i) { WriteDestinations[i] = UINT64_MAX; } for (uint32_t i = 0; i < matchedDef.ChildCount; ++i) { const bx::StringView memberName = {&serializer.MemberNameBuf[matchedDef.MemberNameIndices[i].Offset], matchedDef.MemberNameIndices[i].Size}; const char* memberTypeName = serializer.TypeBuf.Defs[matchedDef.ChildIndices[i]].Name; if (bx::strCmp(memberName, "Elements") == 0 && bx::strCmp(memberTypeName, "PuzzleElementType") == 0) { WriteDestinations[i] = offsetof(StaticPuzzleCard, Elements); } if (bx::strCmp(memberName, "BaseModelHandle") == 0 && bx::strCmp(memberTypeName, "ModelHandle") == 0) { WriteDestinations[i] = offsetof(StaticPuzzleCard, BaseModelHandle); } if (bx::strCmp(memberName, "NorthCoverHandle") == 0 && bx::strCmp(memberTypeName, "ModelHandle") == 0) { WriteDestinations[i] = offsetof(StaticPuzzleCard, NorthCoverHandle); } if (bx::strCmp(memberName, "EastCoverHandle") == 0 && bx::strCmp(memberTypeName, "ModelHandle") == 0) { WriteDestinations[i] = offsetof(StaticPuzzleCard, EastCoverHandle); } if (bx::strCmp(memberName, "SouthCoverHandle") == 0 && bx::strCmp(memberTypeName, "ModelHandle") == 0) { WriteDestinations[i] = offsetof(StaticPuzzleCard, SouthCoverHandle); } if (bx::strCmp(memberName, "WestCoverHandle") == 0 && bx::strCmp(memberTypeName, "ModelHandle") == 0) { WriteDestinations[i] = offsetof(StaticPuzzleCard, WestCoverHandle); } if (bx::strCmp(memberName, "Sockets") == 0 && bx::strCmp(memberTypeName, "CardSocket") == 0) { WriteDestinations[i] = offsetof(StaticPuzzleCard, Sockets); } if (bx::strCmp(memberName, "ModelTextureHandle") == 0 && bx::strCmp(memberTypeName, "TextureHandle") == 0) { WriteDestinations[i] = offsetof(StaticPuzzleCard, ModelTextureHandle); } if (bx::strCmp(memberName, "BoardTextureHandle") == 0 && bx::strCmp(memberTypeName, "TextureHandle") == 0) { WriteDestinations[i] = offsetof(StaticPuzzleCard, BoardTextureHandle); } } // Start reading in file order, skipping things that we don't know by name and type bool isOk = true; for (uint32_t i = 0; i < count; ++i) { uint8_t* objBasePtr = reinterpret_cast(&obj[i]); for (uint32_t j = 0; j < matchedDef.ChildCount; ++j) { const Meta::TypeDef& childDef = serializer.TypeBuf.Defs[matchedDef.ChildIndices[j]]; const bx::StringView memberName = {&serializer.MemberNameBuf[matchedDef.MemberNameIndices[j].Offset], matchedDef.MemberNameIndices[j].Size}; if (WriteDestinations[j] == UINT64_MAX) { // Unknown member name or type changed uint16_t count = bx::max(1, matchedDef.ChildArraySizes[matchedDef.ChildIndices[j]]); serializer.Skip(childDef.Size * count); continue; } if (bx::strCmp(memberName, "Elements") == 0) { auto* fieldPtr = reinterpret_cast(objBasePtr + WriteDestinations[j]); isOk = Load(fieldPtr, 4, serializer) && isOk; continue; } if (bx::strCmp(memberName, "BaseModelHandle") == 0) { auto* fieldPtr = reinterpret_cast(objBasePtr + WriteDestinations[j]); isOk = Load(fieldPtr, 1, serializer) && isOk; continue; } if (bx::strCmp(memberName, "NorthCoverHandle") == 0) { auto* fieldPtr = reinterpret_cast(objBasePtr + WriteDestinations[j]); isOk = Load(fieldPtr, 1, serializer) && isOk; continue; } if (bx::strCmp(memberName, "EastCoverHandle") == 0) { auto* fieldPtr = reinterpret_cast(objBasePtr + WriteDestinations[j]); isOk = Load(fieldPtr, 1, serializer) && isOk; continue; } if (bx::strCmp(memberName, "SouthCoverHandle") == 0) { auto* fieldPtr = reinterpret_cast(objBasePtr + WriteDestinations[j]); isOk = Load(fieldPtr, 1, serializer) && isOk; continue; } if (bx::strCmp(memberName, "WestCoverHandle") == 0) { auto* fieldPtr = reinterpret_cast(objBasePtr + WriteDestinations[j]); isOk = Load(fieldPtr, 1, serializer) && isOk; continue; } if (bx::strCmp(memberName, "Sockets") == 0) { auto* fieldPtr = reinterpret_cast(objBasePtr + WriteDestinations[j]); isOk = Load(fieldPtr, 16, serializer) && isOk; continue; } if (bx::strCmp(memberName, "ModelTextureHandle") == 0) { auto* fieldPtr = reinterpret_cast(objBasePtr + WriteDestinations[j]); isOk = Load(fieldPtr, 1, serializer) && isOk; continue; } if (bx::strCmp(memberName, "BoardTextureHandle") == 0) { auto* fieldPtr = reinterpret_cast(objBasePtr + WriteDestinations[j]); isOk = Load(fieldPtr, 1, serializer) && isOk; continue; } assert(false); } } assert(isOk); return isOk; } bool Save(const StaticPuzzleCardHandle* obj, uint32_t count, Serializer& serializer) { bool isOk = true; for (uint32_t i = 0; i < count; ++i) { isOk = Save(&obj[i].Idx, 1, serializer) && isOk; } return isOk; } bool Load(StaticPuzzleCardHandle* obj, uint32_t count, Deserializer& serializer) { const char* typeName = Meta::Metadata.TypeDefinitions[StaticPuzzleCardHandle::TypeIdx].Name; // Quick match int32_t matchedHashIdx = serializer.TypeBuf.FindHash(Meta::Metadata.TypeDefinitions[StaticPuzzleCardHandle::TypeIdx].Hash); if (matchedHashIdx >= 0) { assert(bx::strCmp(serializer.TypeBuf.Defs[matchedHashIdx].Name, typeName) == 0); bool isOk = true; for (uint32_t i = 0; i < count; ++i) { isOk = Load(&obj[i].Idx, 1, serializer) && isOk; } // if we're not ok here, something went really wrong assert(isOk); return isOk; } // Failed to resolve hash, the type definition chaned since the file was saved! try to match by name. *obj = {}; int32_t nameMatchIdx = serializer.TypeBuf.FindDefByName(typeName); if (nameMatchIdx < 0) { // Name match failed, caller has to handle this and potentially skip some bytes return false; } // Successfully matched name, but we need to follow the definition of the file now! const Meta::TypeDef& matchedDef = serializer.TypeBuf.Defs[nameMatchIdx]; // Figure out new member mapping uint64_t WriteDestinations[64]; for (int32_t i = 0; i < BX_COUNTOF(WriteDestinations); ++i) { WriteDestinations[i] = UINT64_MAX; } for (uint32_t i = 0; i < matchedDef.ChildCount; ++i) { const bx::StringView memberName = {&serializer.MemberNameBuf[matchedDef.MemberNameIndices[i].Offset], matchedDef.MemberNameIndices[i].Size}; const char* memberTypeName = serializer.TypeBuf.Defs[matchedDef.ChildIndices[i]].Name; if (bx::strCmp(memberName, "Idx") == 0 && bx::strCmp(memberTypeName, "u16") == 0) { WriteDestinations[i] = offsetof(StaticPuzzleCardHandle, Idx); } } // Start reading in file order, skipping things that we don't know by name and type bool isOk = true; for (uint32_t i = 0; i < count; ++i) { uint8_t* objBasePtr = reinterpret_cast(&obj[i]); for (uint32_t j = 0; j < matchedDef.ChildCount; ++j) { const Meta::TypeDef& childDef = serializer.TypeBuf.Defs[matchedDef.ChildIndices[j]]; const bx::StringView memberName = {&serializer.MemberNameBuf[matchedDef.MemberNameIndices[j].Offset], matchedDef.MemberNameIndices[j].Size}; if (WriteDestinations[j] == UINT64_MAX) { // Unknown member name or type changed uint16_t count = bx::max(1, matchedDef.ChildArraySizes[matchedDef.ChildIndices[j]]); serializer.Skip(childDef.Size * count); continue; } if (bx::strCmp(memberName, "Idx") == 0) { auto* fieldPtr = reinterpret_cast(objBasePtr + WriteDestinations[j]); isOk = Load(fieldPtr, 1, serializer) && isOk; continue; } assert(false); } } assert(isOk); return isOk; } bool Save(const PuzzleVisualSettings* obj, uint32_t count, Serializer& serializer) { bool isOk = true; for (uint32_t i = 0; i < count; ++i) { isOk = Save(&obj[i].TileBaseColor, 1, serializer) && isOk; isOk = Save(&obj[i].TileDotColor, 1, serializer) && isOk; isOk = Save(&obj[i].Test, 1, serializer) && isOk; isOk = Save(&obj[i].DisabledCardTint, 1, serializer) && isOk; } return isOk; } bool Load(PuzzleVisualSettings* obj, uint32_t count, Deserializer& serializer) { const char* typeName = Meta::Metadata.TypeDefinitions[PuzzleVisualSettings::TypeIdx].Name; // Quick match int32_t matchedHashIdx = serializer.TypeBuf.FindHash(Meta::Metadata.TypeDefinitions[PuzzleVisualSettings::TypeIdx].Hash); if (matchedHashIdx >= 0) { assert(bx::strCmp(serializer.TypeBuf.Defs[matchedHashIdx].Name, typeName) == 0); bool isOk = true; for (uint32_t i = 0; i < count; ++i) { isOk = Load(&obj[i].TileBaseColor, 1, serializer) && isOk; isOk = Load(&obj[i].TileDotColor, 1, serializer) && isOk; isOk = Load(&obj[i].Test, 1, serializer) && isOk; isOk = Load(&obj[i].DisabledCardTint, 1, serializer) && isOk; } // if we're not ok here, something went really wrong assert(isOk); return isOk; } // Failed to resolve hash, the type definition chaned since the file was saved! try to match by name. *obj = {}; int32_t nameMatchIdx = serializer.TypeBuf.FindDefByName(typeName); if (nameMatchIdx < 0) { // Name match failed, caller has to handle this and potentially skip some bytes return false; } // Successfully matched name, but we need to follow the definition of the file now! const Meta::TypeDef& matchedDef = serializer.TypeBuf.Defs[nameMatchIdx]; // Figure out new member mapping uint64_t WriteDestinations[64]; for (int32_t i = 0; i < BX_COUNTOF(WriteDestinations); ++i) { WriteDestinations[i] = UINT64_MAX; } for (uint32_t i = 0; i < matchedDef.ChildCount; ++i) { const bx::StringView memberName = {&serializer.MemberNameBuf[matchedDef.MemberNameIndices[i].Offset], matchedDef.MemberNameIndices[i].Size}; const char* memberTypeName = serializer.TypeBuf.Defs[matchedDef.ChildIndices[i]].Name; if (bx::strCmp(memberName, "TileBaseColor") == 0 && bx::strCmp(memberTypeName, "Vec4") == 0) { WriteDestinations[i] = offsetof(PuzzleVisualSettings, TileBaseColor); } if (bx::strCmp(memberName, "TileDotColor") == 0 && bx::strCmp(memberTypeName, "Vec4") == 0) { WriteDestinations[i] = offsetof(PuzzleVisualSettings, TileDotColor); } if (bx::strCmp(memberName, "Test") == 0 && bx::strCmp(memberTypeName, "Vec3") == 0) { WriteDestinations[i] = offsetof(PuzzleVisualSettings, Test); } if (bx::strCmp(memberName, "DisabledCardTint") == 0 && bx::strCmp(memberTypeName, "Vec4") == 0) { WriteDestinations[i] = offsetof(PuzzleVisualSettings, DisabledCardTint); } } // Start reading in file order, skipping things that we don't know by name and type bool isOk = true; for (uint32_t i = 0; i < count; ++i) { uint8_t* objBasePtr = reinterpret_cast(&obj[i]); for (uint32_t j = 0; j < matchedDef.ChildCount; ++j) { const Meta::TypeDef& childDef = serializer.TypeBuf.Defs[matchedDef.ChildIndices[j]]; const bx::StringView memberName = {&serializer.MemberNameBuf[matchedDef.MemberNameIndices[j].Offset], matchedDef.MemberNameIndices[j].Size}; if (WriteDestinations[j] == UINT64_MAX) { // Unknown member name or type changed uint16_t count = bx::max(1, matchedDef.ChildArraySizes[matchedDef.ChildIndices[j]]); serializer.Skip(childDef.Size * count); continue; } if (bx::strCmp(memberName, "TileBaseColor") == 0) { auto* fieldPtr = reinterpret_cast(objBasePtr + WriteDestinations[j]); isOk = Load(fieldPtr, 1, serializer) && isOk; continue; } if (bx::strCmp(memberName, "TileDotColor") == 0) { auto* fieldPtr = reinterpret_cast(objBasePtr + WriteDestinations[j]); isOk = Load(fieldPtr, 1, serializer) && isOk; continue; } if (bx::strCmp(memberName, "Test") == 0) { auto* fieldPtr = reinterpret_cast(objBasePtr + WriteDestinations[j]); isOk = Load(fieldPtr, 1, serializer) && isOk; continue; } if (bx::strCmp(memberName, "DisabledCardTint") == 0) { auto* fieldPtr = reinterpret_cast(objBasePtr + WriteDestinations[j]); isOk = Load(fieldPtr, 1, serializer) && isOk; continue; } assert(false); } } assert(isOk); return isOk; } bool Save(const StaticPuzzleData* obj, uint32_t count, Serializer& serializer) { bool isOk = true; for (uint32_t i = 0; i < count; ++i) { isOk = Save(obj[i].Cards, 64, serializer) && isOk; isOk = Save(&obj[i].Visuals, 1, serializer) && isOk; } return isOk; } bool Load(StaticPuzzleData* obj, uint32_t count, Deserializer& serializer) { const char* typeName = Meta::Metadata.TypeDefinitions[StaticPuzzleData::TypeIdx].Name; // Quick match int32_t matchedHashIdx = serializer.TypeBuf.FindHash(Meta::Metadata.TypeDefinitions[StaticPuzzleData::TypeIdx].Hash); if (matchedHashIdx >= 0) { assert(bx::strCmp(serializer.TypeBuf.Defs[matchedHashIdx].Name, typeName) == 0); bool isOk = true; for (uint32_t i = 0; i < count; ++i) { isOk = Load(obj[i].Cards, 64, serializer) && isOk; isOk = Load(&obj[i].Visuals, 1, serializer) && isOk; } // if we're not ok here, something went really wrong assert(isOk); return isOk; } // Failed to resolve hash, the type definition chaned since the file was saved! try to match by name. *obj = {}; int32_t nameMatchIdx = serializer.TypeBuf.FindDefByName(typeName); if (nameMatchIdx < 0) { // Name match failed, caller has to handle this and potentially skip some bytes return false; } // Successfully matched name, but we need to follow the definition of the file now! const Meta::TypeDef& matchedDef = serializer.TypeBuf.Defs[nameMatchIdx]; // Figure out new member mapping uint64_t WriteDestinations[64]; for (int32_t i = 0; i < BX_COUNTOF(WriteDestinations); ++i) { WriteDestinations[i] = UINT64_MAX; } for (uint32_t i = 0; i < matchedDef.ChildCount; ++i) { const bx::StringView memberName = {&serializer.MemberNameBuf[matchedDef.MemberNameIndices[i].Offset], matchedDef.MemberNameIndices[i].Size}; const char* memberTypeName = serializer.TypeBuf.Defs[matchedDef.ChildIndices[i]].Name; if (bx::strCmp(memberName, "Cards") == 0 && bx::strCmp(memberTypeName, "StaticPuzzleCard") == 0) { WriteDestinations[i] = offsetof(StaticPuzzleData, Cards); } if (bx::strCmp(memberName, "Visuals") == 0 && bx::strCmp(memberTypeName, "PuzzleVisualSettings") == 0) { WriteDestinations[i] = offsetof(StaticPuzzleData, Visuals); } } // Start reading in file order, skipping things that we don't know by name and type bool isOk = true; for (uint32_t i = 0; i < count; ++i) { uint8_t* objBasePtr = reinterpret_cast(&obj[i]); for (uint32_t j = 0; j < matchedDef.ChildCount; ++j) { const Meta::TypeDef& childDef = serializer.TypeBuf.Defs[matchedDef.ChildIndices[j]]; const bx::StringView memberName = {&serializer.MemberNameBuf[matchedDef.MemberNameIndices[j].Offset], matchedDef.MemberNameIndices[j].Size}; if (WriteDestinations[j] == UINT64_MAX) { // Unknown member name or type changed uint16_t count = bx::max(1, matchedDef.ChildArraySizes[matchedDef.ChildIndices[j]]); serializer.Skip(childDef.Size * count); continue; } if (bx::strCmp(memberName, "Cards") == 0) { auto* fieldPtr = reinterpret_cast(objBasePtr + WriteDestinations[j]); isOk = Load(fieldPtr, 64, serializer) && isOk; continue; } if (bx::strCmp(memberName, "Visuals") == 0) { auto* fieldPtr = reinterpret_cast(objBasePtr + WriteDestinations[j]); isOk = Load(fieldPtr, 1, serializer) && isOk; continue; } assert(false); } } assert(isOk); return isOk; } bool Save(const PuzzleCardStack* obj, uint32_t count, Serializer& serializer) { bool isOk = true; for (uint32_t i = 0; i < count; ++i) { isOk = Save(&obj[i].RefCard, 1, serializer) && isOk; isOk = Save(&obj[i].MaxAvailableCount, 1, serializer) && isOk; isOk = Save(&obj[i].UsedCount, 1, serializer) && isOk; } return isOk; } bool Load(PuzzleCardStack* obj, uint32_t count, Deserializer& serializer) { const char* typeName = Meta::Metadata.TypeDefinitions[PuzzleCardStack::TypeIdx].Name; // Quick match int32_t matchedHashIdx = serializer.TypeBuf.FindHash(Meta::Metadata.TypeDefinitions[PuzzleCardStack::TypeIdx].Hash); if (matchedHashIdx >= 0) { assert(bx::strCmp(serializer.TypeBuf.Defs[matchedHashIdx].Name, typeName) == 0); bool isOk = true; for (uint32_t i = 0; i < count; ++i) { isOk = Load(&obj[i].RefCard, 1, serializer) && isOk; isOk = Load(&obj[i].MaxAvailableCount, 1, serializer) && isOk; isOk = Load(&obj[i].UsedCount, 1, serializer) && isOk; } // if we're not ok here, something went really wrong assert(isOk); return isOk; } // Failed to resolve hash, the type definition chaned since the file was saved! try to match by name. *obj = {}; int32_t nameMatchIdx = serializer.TypeBuf.FindDefByName(typeName); if (nameMatchIdx < 0) { // Name match failed, caller has to handle this and potentially skip some bytes return false; } // Successfully matched name, but we need to follow the definition of the file now! const Meta::TypeDef& matchedDef = serializer.TypeBuf.Defs[nameMatchIdx]; // Figure out new member mapping uint64_t WriteDestinations[64]; for (int32_t i = 0; i < BX_COUNTOF(WriteDestinations); ++i) { WriteDestinations[i] = UINT64_MAX; } for (uint32_t i = 0; i < matchedDef.ChildCount; ++i) { const bx::StringView memberName = {&serializer.MemberNameBuf[matchedDef.MemberNameIndices[i].Offset], matchedDef.MemberNameIndices[i].Size}; const char* memberTypeName = serializer.TypeBuf.Defs[matchedDef.ChildIndices[i]].Name; if (bx::strCmp(memberName, "RefCard") == 0 && bx::strCmp(memberTypeName, "StaticPuzzleCardHandle") == 0) { WriteDestinations[i] = offsetof(PuzzleCardStack, RefCard); } if (bx::strCmp(memberName, "MaxAvailableCount") == 0 && bx::strCmp(memberTypeName, "u8") == 0) { WriteDestinations[i] = offsetof(PuzzleCardStack, MaxAvailableCount); } if (bx::strCmp(memberName, "UsedCount") == 0 && bx::strCmp(memberTypeName, "u8") == 0) { WriteDestinations[i] = offsetof(PuzzleCardStack, UsedCount); } } // Start reading in file order, skipping things that we don't know by name and type bool isOk = true; for (uint32_t i = 0; i < count; ++i) { uint8_t* objBasePtr = reinterpret_cast(&obj[i]); for (uint32_t j = 0; j < matchedDef.ChildCount; ++j) { const Meta::TypeDef& childDef = serializer.TypeBuf.Defs[matchedDef.ChildIndices[j]]; const bx::StringView memberName = {&serializer.MemberNameBuf[matchedDef.MemberNameIndices[j].Offset], matchedDef.MemberNameIndices[j].Size}; if (WriteDestinations[j] == UINT64_MAX) { // Unknown member name or type changed uint16_t count = bx::max(1, matchedDef.ChildArraySizes[matchedDef.ChildIndices[j]]); serializer.Skip(childDef.Size * count); continue; } if (bx::strCmp(memberName, "RefCard") == 0) { auto* fieldPtr = reinterpret_cast(objBasePtr + WriteDestinations[j]); isOk = Load(fieldPtr, 1, serializer) && isOk; continue; } if (bx::strCmp(memberName, "MaxAvailableCount") == 0) { auto* fieldPtr = reinterpret_cast(objBasePtr + WriteDestinations[j]); isOk = Load(fieldPtr, 1, serializer) && isOk; continue; } if (bx::strCmp(memberName, "UsedCount") == 0) { auto* fieldPtr = reinterpret_cast(objBasePtr + WriteDestinations[j]); isOk = Load(fieldPtr, 1, serializer) && isOk; continue; } assert(false); } } assert(isOk); return isOk; } bool Save(const PlacedPuzzleCard* obj, uint32_t count, Serializer& serializer) { bool isOk = true; for (uint32_t i = 0; i < count; ++i) { isOk = Save(&obj[i].RefCard, 1, serializer) && isOk; isOk = Save(&obj[i].Position, 1, serializer) && isOk; isOk = Save(&obj[i].Rotation, 1, serializer) && isOk; isOk = Save(&obj[i].Flags, 1, serializer) && isOk; } return isOk; } bool Load(PlacedPuzzleCard* obj, uint32_t count, Deserializer& serializer) { const char* typeName = Meta::Metadata.TypeDefinitions[PlacedPuzzleCard::TypeIdx].Name; // Quick match int32_t matchedHashIdx = serializer.TypeBuf.FindHash(Meta::Metadata.TypeDefinitions[PlacedPuzzleCard::TypeIdx].Hash); if (matchedHashIdx >= 0) { assert(bx::strCmp(serializer.TypeBuf.Defs[matchedHashIdx].Name, typeName) == 0); bool isOk = true; for (uint32_t i = 0; i < count; ++i) { isOk = Load(&obj[i].RefCard, 1, serializer) && isOk; isOk = Load(&obj[i].Position, 1, serializer) && isOk; isOk = Load(&obj[i].Rotation, 1, serializer) && isOk; isOk = Load(&obj[i].Flags, 1, serializer) && isOk; } // if we're not ok here, something went really wrong assert(isOk); return isOk; } // Failed to resolve hash, the type definition chaned since the file was saved! try to match by name. *obj = {}; int32_t nameMatchIdx = serializer.TypeBuf.FindDefByName(typeName); if (nameMatchIdx < 0) { // Name match failed, caller has to handle this and potentially skip some bytes return false; } // Successfully matched name, but we need to follow the definition of the file now! const Meta::TypeDef& matchedDef = serializer.TypeBuf.Defs[nameMatchIdx]; // Figure out new member mapping uint64_t WriteDestinations[64]; for (int32_t i = 0; i < BX_COUNTOF(WriteDestinations); ++i) { WriteDestinations[i] = UINT64_MAX; } for (uint32_t i = 0; i < matchedDef.ChildCount; ++i) { const bx::StringView memberName = {&serializer.MemberNameBuf[matchedDef.MemberNameIndices[i].Offset], matchedDef.MemberNameIndices[i].Size}; const char* memberTypeName = serializer.TypeBuf.Defs[matchedDef.ChildIndices[i]].Name; if (bx::strCmp(memberName, "RefCard") == 0 && bx::strCmp(memberTypeName, "StaticPuzzleCardHandle") == 0) { WriteDestinations[i] = offsetof(PlacedPuzzleCard, RefCard); } if (bx::strCmp(memberName, "Position") == 0 && bx::strCmp(memberTypeName, "PuzPos") == 0) { WriteDestinations[i] = offsetof(PlacedPuzzleCard, Position); } if (bx::strCmp(memberName, "Rotation") == 0 && bx::strCmp(memberTypeName, "u8") == 0) { WriteDestinations[i] = offsetof(PlacedPuzzleCard, Rotation); } if (bx::strCmp(memberName, "Flags") == 0 && bx::strCmp(memberTypeName, "PlacedPuzzleCardFlags") == 0) { WriteDestinations[i] = offsetof(PlacedPuzzleCard, Flags); } } // Start reading in file order, skipping things that we don't know by name and type bool isOk = true; for (uint32_t i = 0; i < count; ++i) { uint8_t* objBasePtr = reinterpret_cast(&obj[i]); for (uint32_t j = 0; j < matchedDef.ChildCount; ++j) { const Meta::TypeDef& childDef = serializer.TypeBuf.Defs[matchedDef.ChildIndices[j]]; const bx::StringView memberName = {&serializer.MemberNameBuf[matchedDef.MemberNameIndices[j].Offset], matchedDef.MemberNameIndices[j].Size}; if (WriteDestinations[j] == UINT64_MAX) { // Unknown member name or type changed uint16_t count = bx::max(1, matchedDef.ChildArraySizes[matchedDef.ChildIndices[j]]); serializer.Skip(childDef.Size * count); continue; } if (bx::strCmp(memberName, "RefCard") == 0) { auto* fieldPtr = reinterpret_cast(objBasePtr + WriteDestinations[j]); isOk = Load(fieldPtr, 1, serializer) && isOk; continue; } if (bx::strCmp(memberName, "Position") == 0) { auto* fieldPtr = reinterpret_cast(objBasePtr + WriteDestinations[j]); isOk = Load(fieldPtr, 1, serializer) && isOk; continue; } if (bx::strCmp(memberName, "Rotation") == 0) { auto* fieldPtr = reinterpret_cast(objBasePtr + WriteDestinations[j]); isOk = Load(fieldPtr, 1, serializer) && isOk; continue; } if (bx::strCmp(memberName, "Flags") == 0) { auto* fieldPtr = reinterpret_cast(objBasePtr + WriteDestinations[j]); isOk = Load(fieldPtr, 1, serializer) && isOk; continue; } assert(false); } } assert(isOk); return isOk; } bool Save(const PuzzleData* obj, uint32_t count, Serializer& serializer) { bool isOk = true; for (uint32_t i = 0; i < count; ++i) { isOk = Save(&obj[i].ID, 1, serializer) && isOk; isOk = Save(obj[i].PuzzleName, 64, serializer) && isOk; isOk = Save(&obj[i].WidthTiles, 1, serializer) && isOk; isOk = Save(&obj[i].HeightTiles, 1, serializer) && isOk; isOk = Save(&obj[i].AvailableCardCount, 1, serializer) && isOk; isOk = Save(obj[i].AvailableCards, 16, serializer) && isOk; isOk = Save(obj[i].PlacedCards, 256, serializer) && isOk; isOk = Save(obj[i].InitialPlacedCards, 256, serializer) && isOk; isOk = Save(obj[i].BackgroundTiles, 1024, serializer) && isOk; isOk = Save(&obj[i].GoalPositionCount, 1, serializer) && isOk; isOk = Save(obj[i].GoalPositions, 16, serializer) && isOk; } return isOk; } bool Load(PuzzleData* obj, uint32_t count, Deserializer& serializer) { const char* typeName = Meta::Metadata.TypeDefinitions[PuzzleData::TypeIdx].Name; // Quick match int32_t matchedHashIdx = serializer.TypeBuf.FindHash(Meta::Metadata.TypeDefinitions[PuzzleData::TypeIdx].Hash); if (matchedHashIdx >= 0) { assert(bx::strCmp(serializer.TypeBuf.Defs[matchedHashIdx].Name, typeName) == 0); bool isOk = true; for (uint32_t i = 0; i < count; ++i) { isOk = Load(&obj[i].ID, 1, serializer) && isOk; isOk = Load(obj[i].PuzzleName, 64, serializer) && isOk; isOk = Load(&obj[i].WidthTiles, 1, serializer) && isOk; isOk = Load(&obj[i].HeightTiles, 1, serializer) && isOk; isOk = Load(&obj[i].AvailableCardCount, 1, serializer) && isOk; isOk = Load(obj[i].AvailableCards, 16, serializer) && isOk; isOk = Load(obj[i].PlacedCards, 256, serializer) && isOk; isOk = Load(obj[i].InitialPlacedCards, 256, serializer) && isOk; isOk = Load(obj[i].BackgroundTiles, 1024, serializer) && isOk; isOk = Load(&obj[i].GoalPositionCount, 1, serializer) && isOk; isOk = Load(obj[i].GoalPositions, 16, serializer) && isOk; } // if we're not ok here, something went really wrong assert(isOk); return isOk; } // Failed to resolve hash, the type definition chaned since the file was saved! try to match by name. *obj = {}; int32_t nameMatchIdx = serializer.TypeBuf.FindDefByName(typeName); if (nameMatchIdx < 0) { // Name match failed, caller has to handle this and potentially skip some bytes return false; } // Successfully matched name, but we need to follow the definition of the file now! const Meta::TypeDef& matchedDef = serializer.TypeBuf.Defs[nameMatchIdx]; // Figure out new member mapping uint64_t WriteDestinations[64]; for (int32_t i = 0; i < BX_COUNTOF(WriteDestinations); ++i) { WriteDestinations[i] = UINT64_MAX; } for (uint32_t i = 0; i < matchedDef.ChildCount; ++i) { const bx::StringView memberName = {&serializer.MemberNameBuf[matchedDef.MemberNameIndices[i].Offset], matchedDef.MemberNameIndices[i].Size}; const char* memberTypeName = serializer.TypeBuf.Defs[matchedDef.ChildIndices[i]].Name; if (bx::strCmp(memberName, "ID") == 0 && bx::strCmp(memberTypeName, "u16") == 0) { WriteDestinations[i] = offsetof(PuzzleData, ID); } if (bx::strCmp(memberName, "PuzzleName") == 0 && bx::strCmp(memberTypeName, "str") == 0) { WriteDestinations[i] = offsetof(PuzzleData, PuzzleName); } if (bx::strCmp(memberName, "WidthTiles") == 0 && bx::strCmp(memberTypeName, "u8") == 0) { WriteDestinations[i] = offsetof(PuzzleData, WidthTiles); } if (bx::strCmp(memberName, "HeightTiles") == 0 && bx::strCmp(memberTypeName, "u8") == 0) { WriteDestinations[i] = offsetof(PuzzleData, HeightTiles); } if (bx::strCmp(memberName, "AvailableCardCount") == 0 && bx::strCmp(memberTypeName, "u32") == 0) { WriteDestinations[i] = offsetof(PuzzleData, AvailableCardCount); } if (bx::strCmp(memberName, "AvailableCards") == 0 && bx::strCmp(memberTypeName, "PuzzleCardStack") == 0) { WriteDestinations[i] = offsetof(PuzzleData, AvailableCards); } if (bx::strCmp(memberName, "PlacedCards") == 0 && bx::strCmp(memberTypeName, "PlacedPuzzleCard") == 0) { WriteDestinations[i] = offsetof(PuzzleData, PlacedCards); } if (bx::strCmp(memberName, "InitialPlacedCards") == 0 && bx::strCmp(memberTypeName, "PlacedPuzzleCard") == 0) { WriteDestinations[i] = offsetof(PuzzleData, InitialPlacedCards); } if (bx::strCmp(memberName, "BackgroundTiles") == 0 && bx::strCmp(memberTypeName, "PuzzleElementType") == 0) { WriteDestinations[i] = offsetof(PuzzleData, BackgroundTiles); } if (bx::strCmp(memberName, "GoalPositionCount") == 0 && bx::strCmp(memberTypeName, "u32") == 0) { WriteDestinations[i] = offsetof(PuzzleData, GoalPositionCount); } if (bx::strCmp(memberName, "GoalPositions") == 0 && bx::strCmp(memberTypeName, "PuzPos") == 0) { WriteDestinations[i] = offsetof(PuzzleData, GoalPositions); } } // Start reading in file order, skipping things that we don't know by name and type bool isOk = true; for (uint32_t i = 0; i < count; ++i) { uint8_t* objBasePtr = reinterpret_cast(&obj[i]); for (uint32_t j = 0; j < matchedDef.ChildCount; ++j) { const Meta::TypeDef& childDef = serializer.TypeBuf.Defs[matchedDef.ChildIndices[j]]; const bx::StringView memberName = {&serializer.MemberNameBuf[matchedDef.MemberNameIndices[j].Offset], matchedDef.MemberNameIndices[j].Size}; if (WriteDestinations[j] == UINT64_MAX) { // Unknown member name or type changed uint16_t count = bx::max(1, matchedDef.ChildArraySizes[matchedDef.ChildIndices[j]]); serializer.Skip(childDef.Size * count); continue; } if (bx::strCmp(memberName, "ID") == 0) { auto* fieldPtr = reinterpret_cast(objBasePtr + WriteDestinations[j]); isOk = Load(fieldPtr, 1, serializer) && isOk; continue; } if (bx::strCmp(memberName, "PuzzleName") == 0) { auto* fieldPtr = reinterpret_cast(objBasePtr + WriteDestinations[j]); isOk = Load(fieldPtr, 64, serializer) && isOk; continue; } if (bx::strCmp(memberName, "WidthTiles") == 0) { auto* fieldPtr = reinterpret_cast(objBasePtr + WriteDestinations[j]); isOk = Load(fieldPtr, 1, serializer) && isOk; continue; } if (bx::strCmp(memberName, "HeightTiles") == 0) { auto* fieldPtr = reinterpret_cast(objBasePtr + WriteDestinations[j]); isOk = Load(fieldPtr, 1, serializer) && isOk; continue; } if (bx::strCmp(memberName, "AvailableCardCount") == 0) { auto* fieldPtr = reinterpret_cast(objBasePtr + WriteDestinations[j]); isOk = Load(fieldPtr, 1, serializer) && isOk; continue; } if (bx::strCmp(memberName, "AvailableCards") == 0) { auto* fieldPtr = reinterpret_cast(objBasePtr + WriteDestinations[j]); isOk = Load(fieldPtr, 16, serializer) && isOk; continue; } if (bx::strCmp(memberName, "PlacedCards") == 0) { auto* fieldPtr = reinterpret_cast(objBasePtr + WriteDestinations[j]); isOk = Load(fieldPtr, 256, serializer) && isOk; continue; } if (bx::strCmp(memberName, "InitialPlacedCards") == 0) { auto* fieldPtr = reinterpret_cast(objBasePtr + WriteDestinations[j]); isOk = Load(fieldPtr, 256, serializer) && isOk; continue; } if (bx::strCmp(memberName, "BackgroundTiles") == 0) { auto* fieldPtr = reinterpret_cast(objBasePtr + WriteDestinations[j]); isOk = Load(fieldPtr, 1024, serializer) && isOk; continue; } if (bx::strCmp(memberName, "GoalPositionCount") == 0) { auto* fieldPtr = reinterpret_cast(objBasePtr + WriteDestinations[j]); isOk = Load(fieldPtr, 1, serializer) && isOk; continue; } if (bx::strCmp(memberName, "GoalPositions") == 0) { auto* fieldPtr = reinterpret_cast(objBasePtr + WriteDestinations[j]); isOk = Load(fieldPtr, 16, serializer) && isOk; continue; } assert(false); } } assert(isOk); return isOk; } bool Save(const SavedEntityRenderData* obj, uint32_t count, Serializer& serializer) { bool isOk = true; for (uint32_t i = 0; i < count; ++i) { isOk = Save(&obj[i].BaseColor, 1, serializer) && isOk; isOk = Save(&obj[i].HighlightColor, 1, serializer) && isOk; isOk = Save(&obj[i].TF, 1, serializer) && isOk; isOk = Save(&obj[i].Material, 1, serializer) && isOk; isOk = Save(&obj[i].Texture, 1, serializer) && isOk; isOk = Save(&obj[i].Model, 1, serializer) && isOk; isOk = Save(&obj[i].Visible, 1, serializer) && isOk; } return isOk; } bool Load(SavedEntityRenderData* obj, uint32_t count, Deserializer& serializer) { const char* typeName = Meta::Metadata.TypeDefinitions[SavedEntityRenderData::TypeIdx].Name; // Quick match int32_t matchedHashIdx = serializer.TypeBuf.FindHash(Meta::Metadata.TypeDefinitions[SavedEntityRenderData::TypeIdx].Hash); if (matchedHashIdx >= 0) { assert(bx::strCmp(serializer.TypeBuf.Defs[matchedHashIdx].Name, typeName) == 0); bool isOk = true; for (uint32_t i = 0; i < count; ++i) { isOk = Load(&obj[i].BaseColor, 1, serializer) && isOk; isOk = Load(&obj[i].HighlightColor, 1, serializer) && isOk; isOk = Load(&obj[i].TF, 1, serializer) && isOk; isOk = Load(&obj[i].Material, 1, serializer) && isOk; isOk = Load(&obj[i].Texture, 1, serializer) && isOk; isOk = Load(&obj[i].Model, 1, serializer) && isOk; isOk = Load(&obj[i].Visible, 1, serializer) && isOk; } // if we're not ok here, something went really wrong assert(isOk); return isOk; } // Failed to resolve hash, the type definition chaned since the file was saved! try to match by name. *obj = {}; int32_t nameMatchIdx = serializer.TypeBuf.FindDefByName(typeName); if (nameMatchIdx < 0) { // Name match failed, caller has to handle this and potentially skip some bytes return false; } // Successfully matched name, but we need to follow the definition of the file now! const Meta::TypeDef& matchedDef = serializer.TypeBuf.Defs[nameMatchIdx]; // Figure out new member mapping uint64_t WriteDestinations[64]; for (int32_t i = 0; i < BX_COUNTOF(WriteDestinations); ++i) { WriteDestinations[i] = UINT64_MAX; } for (uint32_t i = 0; i < matchedDef.ChildCount; ++i) { const bx::StringView memberName = {&serializer.MemberNameBuf[matchedDef.MemberNameIndices[i].Offset], matchedDef.MemberNameIndices[i].Size}; const char* memberTypeName = serializer.TypeBuf.Defs[matchedDef.ChildIndices[i]].Name; if (bx::strCmp(memberName, "BaseColor") == 0 && bx::strCmp(memberTypeName, "Vec4") == 0) { WriteDestinations[i] = offsetof(SavedEntityRenderData, BaseColor); } if (bx::strCmp(memberName, "HighlightColor") == 0 && bx::strCmp(memberTypeName, "Vec4") == 0) { WriteDestinations[i] = offsetof(SavedEntityRenderData, HighlightColor); } if (bx::strCmp(memberName, "TF") == 0 && bx::strCmp(memberTypeName, "Transform") == 0) { WriteDestinations[i] = offsetof(SavedEntityRenderData, TF); } if (bx::strCmp(memberName, "Material") == 0 && bx::strCmp(memberTypeName, "EMaterial") == 0) { WriteDestinations[i] = offsetof(SavedEntityRenderData, Material); } if (bx::strCmp(memberName, "Texture") == 0 && bx::strCmp(memberTypeName, "TextureHandle") == 0) { WriteDestinations[i] = offsetof(SavedEntityRenderData, Texture); } if (bx::strCmp(memberName, "Model") == 0 && bx::strCmp(memberTypeName, "ModelHandle") == 0) { WriteDestinations[i] = offsetof(SavedEntityRenderData, Model); } if (bx::strCmp(memberName, "Visible") == 0 && bx::strCmp(memberTypeName, "b") == 0) { WriteDestinations[i] = offsetof(SavedEntityRenderData, Visible); } } // Start reading in file order, skipping things that we don't know by name and type bool isOk = true; for (uint32_t i = 0; i < count; ++i) { uint8_t* objBasePtr = reinterpret_cast(&obj[i]); for (uint32_t j = 0; j < matchedDef.ChildCount; ++j) { const Meta::TypeDef& childDef = serializer.TypeBuf.Defs[matchedDef.ChildIndices[j]]; const bx::StringView memberName = {&serializer.MemberNameBuf[matchedDef.MemberNameIndices[j].Offset], matchedDef.MemberNameIndices[j].Size}; if (WriteDestinations[j] == UINT64_MAX) { // Unknown member name or type changed uint16_t count = bx::max(1, matchedDef.ChildArraySizes[matchedDef.ChildIndices[j]]); serializer.Skip(childDef.Size * count); continue; } if (bx::strCmp(memberName, "BaseColor") == 0) { auto* fieldPtr = reinterpret_cast(objBasePtr + WriteDestinations[j]); isOk = Load(fieldPtr, 1, serializer) && isOk; continue; } if (bx::strCmp(memberName, "HighlightColor") == 0) { auto* fieldPtr = reinterpret_cast(objBasePtr + WriteDestinations[j]); isOk = Load(fieldPtr, 1, serializer) && isOk; continue; } if (bx::strCmp(memberName, "TF") == 0) { auto* fieldPtr = reinterpret_cast(objBasePtr + WriteDestinations[j]); isOk = Load(fieldPtr, 1, serializer) && isOk; continue; } if (bx::strCmp(memberName, "Material") == 0) { auto* fieldPtr = reinterpret_cast(objBasePtr + WriteDestinations[j]); isOk = Load(fieldPtr, 1, serializer) && isOk; continue; } if (bx::strCmp(memberName, "Texture") == 0) { auto* fieldPtr = reinterpret_cast(objBasePtr + WriteDestinations[j]); isOk = Load(fieldPtr, 1, serializer) && isOk; continue; } if (bx::strCmp(memberName, "Model") == 0) { auto* fieldPtr = reinterpret_cast(objBasePtr + WriteDestinations[j]); isOk = Load(fieldPtr, 1, serializer) && isOk; continue; } if (bx::strCmp(memberName, "Visible") == 0) { auto* fieldPtr = reinterpret_cast(objBasePtr + WriteDestinations[j]); isOk = Load(fieldPtr, 1, serializer) && isOk; continue; } assert(false); } } assert(isOk); return isOk; } bool Save(const SavedPlayerConfig* obj, uint32_t count, Serializer& serializer) { bool isOk = true; for (uint32_t i = 0; i < count; ++i) { isOk = Save(&obj[i].TabletBackgroundRenderData, 1, serializer) && isOk; isOk = Save(&obj[i].TabletStatusRenderData, 1, serializer) && isOk; isOk = Save(&obj[i].TabletStatusNotSolvedTexture, 1, serializer) && isOk; isOk = Save(&obj[i].TabletStatusSolvedTexture, 1, serializer) && isOk; isOk = Save(&obj[i].TabletResetRenderData, 1, serializer) && isOk; } return isOk; } bool Load(SavedPlayerConfig* obj, uint32_t count, Deserializer& serializer) { const char* typeName = Meta::Metadata.TypeDefinitions[SavedPlayerConfig::TypeIdx].Name; // Quick match int32_t matchedHashIdx = serializer.TypeBuf.FindHash(Meta::Metadata.TypeDefinitions[SavedPlayerConfig::TypeIdx].Hash); if (matchedHashIdx >= 0) { assert(bx::strCmp(serializer.TypeBuf.Defs[matchedHashIdx].Name, typeName) == 0); bool isOk = true; for (uint32_t i = 0; i < count; ++i) { isOk = Load(&obj[i].TabletBackgroundRenderData, 1, serializer) && isOk; isOk = Load(&obj[i].TabletStatusRenderData, 1, serializer) && isOk; isOk = Load(&obj[i].TabletStatusNotSolvedTexture, 1, serializer) && isOk; isOk = Load(&obj[i].TabletStatusSolvedTexture, 1, serializer) && isOk; isOk = Load(&obj[i].TabletResetRenderData, 1, serializer) && isOk; } // if we're not ok here, something went really wrong assert(isOk); return isOk; } // Failed to resolve hash, the type definition chaned since the file was saved! try to match by name. *obj = {}; int32_t nameMatchIdx = serializer.TypeBuf.FindDefByName(typeName); if (nameMatchIdx < 0) { // Name match failed, caller has to handle this and potentially skip some bytes return false; } // Successfully matched name, but we need to follow the definition of the file now! const Meta::TypeDef& matchedDef = serializer.TypeBuf.Defs[nameMatchIdx]; // Figure out new member mapping uint64_t WriteDestinations[64]; for (int32_t i = 0; i < BX_COUNTOF(WriteDestinations); ++i) { WriteDestinations[i] = UINT64_MAX; } for (uint32_t i = 0; i < matchedDef.ChildCount; ++i) { const bx::StringView memberName = {&serializer.MemberNameBuf[matchedDef.MemberNameIndices[i].Offset], matchedDef.MemberNameIndices[i].Size}; const char* memberTypeName = serializer.TypeBuf.Defs[matchedDef.ChildIndices[i]].Name; if (bx::strCmp(memberName, "TabletBackgroundRenderData") == 0 && bx::strCmp(memberTypeName, "SavedEntityRenderData") == 0) { WriteDestinations[i] = offsetof(SavedPlayerConfig, TabletBackgroundRenderData); } if (bx::strCmp(memberName, "TabletStatusRenderData") == 0 && bx::strCmp(memberTypeName, "SavedEntityRenderData") == 0) { WriteDestinations[i] = offsetof(SavedPlayerConfig, TabletStatusRenderData); } if (bx::strCmp(memberName, "TabletStatusNotSolvedTexture") == 0 && bx::strCmp(memberTypeName, "TextureHandle") == 0) { WriteDestinations[i] = offsetof(SavedPlayerConfig, TabletStatusNotSolvedTexture); } if (bx::strCmp(memberName, "TabletStatusSolvedTexture") == 0 && bx::strCmp(memberTypeName, "TextureHandle") == 0) { WriteDestinations[i] = offsetof(SavedPlayerConfig, TabletStatusSolvedTexture); } if (bx::strCmp(memberName, "TabletResetRenderData") == 0 && bx::strCmp(memberTypeName, "SavedEntityRenderData") == 0) { WriteDestinations[i] = offsetof(SavedPlayerConfig, TabletResetRenderData); } } // Start reading in file order, skipping things that we don't know by name and type bool isOk = true; for (uint32_t i = 0; i < count; ++i) { uint8_t* objBasePtr = reinterpret_cast(&obj[i]); for (uint32_t j = 0; j < matchedDef.ChildCount; ++j) { const Meta::TypeDef& childDef = serializer.TypeBuf.Defs[matchedDef.ChildIndices[j]]; const bx::StringView memberName = {&serializer.MemberNameBuf[matchedDef.MemberNameIndices[j].Offset], matchedDef.MemberNameIndices[j].Size}; if (WriteDestinations[j] == UINT64_MAX) { // Unknown member name or type changed uint16_t count = bx::max(1, matchedDef.ChildArraySizes[matchedDef.ChildIndices[j]]); serializer.Skip(childDef.Size * count); continue; } if (bx::strCmp(memberName, "TabletBackgroundRenderData") == 0) { auto* fieldPtr = reinterpret_cast(objBasePtr + WriteDestinations[j]); isOk = Load(fieldPtr, 1, serializer) && isOk; continue; } if (bx::strCmp(memberName, "TabletStatusRenderData") == 0) { auto* fieldPtr = reinterpret_cast(objBasePtr + WriteDestinations[j]); isOk = Load(fieldPtr, 1, serializer) && isOk; continue; } if (bx::strCmp(memberName, "TabletStatusNotSolvedTexture") == 0) { auto* fieldPtr = reinterpret_cast(objBasePtr + WriteDestinations[j]); isOk = Load(fieldPtr, 1, serializer) && isOk; continue; } if (bx::strCmp(memberName, "TabletStatusSolvedTexture") == 0) { auto* fieldPtr = reinterpret_cast(objBasePtr + WriteDestinations[j]); isOk = Load(fieldPtr, 1, serializer) && isOk; continue; } if (bx::strCmp(memberName, "TabletResetRenderData") == 0) { auto* fieldPtr = reinterpret_cast(objBasePtr + WriteDestinations[j]); isOk = Load(fieldPtr, 1, serializer) && isOk; continue; } assert(false); } } assert(isOk); return isOk; } }