almost finish CKGroup

This commit is contained in:
2023-09-01 12:19:06 +08:00
parent 3755a2e148
commit fd69914a25
15 changed files with 310 additions and 88 deletions

View File

@ -11,6 +11,9 @@
#include <zlib.h>
#include "ObjImpls/CKObject.hpp"
#include "ObjImpls/CKSceneObject.hpp"
#include "ObjImpls/CKBeObject.hpp"
#include "ObjImpls/CKGroup.hpp"
namespace LibCmo::CK2 {
@ -61,17 +64,23 @@ namespace LibCmo::CK2 {
#pragma region CKClass Registration
static XContainer::XArray<CKClassDesc> g_CKClassInfo;
static std::map<CK_CLASSID, size_t> g_CKClassInfoId2Idx;
static CK_CLASSID g_CKClassInfoMaxID = static_cast<CK_CLASSID>(0);
CK_CLASSID CKClassGetNewIdentifier() {
size_t classsize = g_CKClassInfo.size();
if (classsize < static_cast<size_t>(CK_CLASSID::CKCID_MAXCLASSID)) {
return CK_CLASSID::CKCID_MAXCLASSID;
} else {
return static_cast<CK_CLASSID>(classsize);
}
}
static void ComputeParentsTable(CKClassDesc& desc) {
// if it has done, do not process it again.
if (desc.Done) return;
// find direct parent
auto finder = g_CKClassInfoId2Idx.find(desc.Parent);
if (finder == g_CKClassInfoId2Idx.end()) LIBPANIC("No such CK_CLASSID.");
CKClassDesc& parent = g_CKClassInfo[finder->second];
CKClassDesc& parent = g_CKClassInfo[static_cast<size_t>(desc.Parent)];
if (!parent.IsValid) LIBPANIC("No such CK_CLASSID.");
// if it is not self inheritance, call recursively
if (desc.Self != desc.Parent) {
@ -81,9 +90,7 @@ namespace LibCmo::CK2 {
// copy parent's parents
desc.Parents = parent.Parents;
// and set self as its parent
finder = g_CKClassInfoId2Idx.find(desc.Self);
if (finder == g_CKClassInfoId2Idx.end()) LIBPANIC("No such CK_CLASSID.");
desc.Parents[finder->second] = true;
desc.Parents[static_cast<size_t>(desc.Self)] = true;
// set derivation level
desc.DerivationLevel = parent.DerivationLevel + 1;
@ -95,26 +102,30 @@ namespace LibCmo::CK2 {
// set Done to false and resize all XBitArray
size_t classCount = g_CKClassInfo.size();
for (auto& item : g_CKClassInfo) {
if (!item.IsValid) continue;
item.Done = false;
item.Parents.resize(classCount, false);
item.Children.resize(classCount, false);
}
// compute parents
for (auto& item : g_CKClassInfo) {
if (!item.IsValid) continue;
ComputeParentsTable(item);
}
// compute children by parents table
// iterate CKClassDesc::Parents and register it self to gotten parents
for (auto& item : g_CKClassInfo) {
auto finder = g_CKClassInfoId2Idx.find(item.Self);
if (finder == g_CKClassInfoId2Idx.end()) LIBPANIC("No such CK_CLASSID.");
size_t selfidx = finder->second;
if (!item.IsValid) continue;
for (size_t idx = 0; idx < classCount; ++idx) {
if (!g_CKClassInfo[idx].IsValid) continue;
// if this idx is its parent,
// add self to parent.
if (item.Parents[idx]) {
g_CKClassInfo[idx].Children[selfidx] = true;
g_CKClassInfo[idx].Children[static_cast<size_t>(item.Self)] = true;
}
}
}
@ -122,54 +133,60 @@ namespace LibCmo::CK2 {
void CKClassRegister(CK_CLASSID cid, CK_CLASSID parentCid,
CKClassCreationFct createFct, CKClassReleaseFct relFct, CKClassNameFct nameFct) {
// resize class desc array
size_t intcid = static_cast<size_t>(cid);
if (intcid >= g_CKClassInfo.size()) {
g_CKClassInfo.resize(intcid + 1);
}
// emplace desc
CKClassDesc desc;
desc.IsValid = true;
desc.Self = cid;
desc.Parent = parentCid;
desc.CreationFct = createFct;
desc.ReleaseFct = relFct;
desc.NameFct = nameFct;
g_CKClassInfoId2Idx.emplace(cid, g_CKClassInfo.size());
g_CKClassInfo.emplace_back(std::move(desc));
g_CKClassInfoMaxID = std::max(g_CKClassInfoMaxID, cid);
g_CKClassInfo[intcid] = std::move(desc);
}
#pragma endregion
#pragma region Class Hierarchy Management
CKINT CKGetClassCount() {
return static_cast<CKINT>(g_CKClassInfo.size());
static bool GetClassIdIndex(CK_CLASSID cid, size_t& intcid) {
intcid = static_cast<size_t>(cid);
if (intcid >= g_CKClassInfo.size()) return false;
if (!g_CKClassInfo[intcid].IsValid) return false;
return true;
}
CKDWORD CKGetClassCount() {
return static_cast<CKDWORD>(g_CKClassInfo.size());
}
const CKClassDesc* CKGetClassDesc(CK_CLASSID cid) {
auto finder = g_CKClassInfoId2Idx.find(cid);
if (finder == g_CKClassInfoId2Idx.end()) return nullptr;
return g_CKClassInfo.data() + finder->second;
size_t intcid;
if (!GetClassIdIndex(cid, intcid)) return nullptr;
return &g_CKClassInfo[intcid];
}
CKSTRING CKClassIDToString(CK_CLASSID cid) {
auto finder = g_CKClassInfoId2Idx.find(cid);
if (finder == g_CKClassInfoId2Idx.end() || g_CKClassInfo[finder->second].NameFct == nullptr) return "Invalid Class Identifier";
return g_CKClassInfo[finder->second].NameFct();
const CKClassDesc* desc = CKGetClassDesc(cid);
if (desc == nullptr) return "Undefined Type";
else return desc->NameFct();
}
bool CKIsChildClassOf(CK_CLASSID child, CK_CLASSID parent) {
// get corresponding index first
// if we can't find it, return false anyway.
auto finder = g_CKClassInfoId2Idx.find(child);
if (finder == g_CKClassInfoId2Idx.end()) return false;
size_t child_idx = finder->second;
finder = g_CKClassInfoId2Idx.find(parent);
if (finder == g_CKClassInfoId2Idx.end()) return false;
size_t parent_idx = finder->second;
return g_CKClassInfo[child_idx].Parents[parent_idx];
size_t intchild, intparent;
if (!GetClassIdIndex(child, intchild) || !GetClassIdIndex(parent, intparent)) return false;
return g_CKClassInfo[intchild].Parents[intparent];
}
CK_CLASSID CKGetParentClassID(CK_CLASSID child) {
auto finder = g_CKClassInfoId2Idx.find(child);
if (finder == g_CKClassInfoId2Idx.end()) LIBPANIC("No such CK_CLASSID.");
return g_CKClassInfo[finder->second].Parent;
const CKClassDesc* desc = CKGetClassDesc(child);
if (desc == nullptr) return CK_CLASSID::CKCID_OBJECT;
return desc->Parent;
}
CK_CLASSID CKGetCommonParent(CK_CLASSID cid1, CK_CLASSID cid2) {
@ -190,11 +207,28 @@ namespace LibCmo::CK2 {
#pragma region Initializations functions
CKERROR CKStartUp() {
// reserve class info array.
g_CKClassInfo.reserve(static_cast<size_t>(CK_CLASSID::CKCID_MAXCLASSID));
// todo: add class type registrations
CKClassRegister(CK_CLASSID::CKCID_OBJECT, CK_CLASSID::CKCID_OBJECT,
[](CKContext* ctx, CK_ID id, CKSTRING name) -> ObjImpls::CKObject* { return new ObjImpls::CKObject(ctx, id, name); },
[](CKContext* ctx, ObjImpls::CKObject* obj) -> void { delete obj; },
[]() -> CKSTRING { return "Basic Object"; });
#define EasyClassReg(clsname, cid, parentCid, strName) \
CKClassRegister(cid, parentCid, \
[](CKContext* ctx, CK_ID id, CKSTRING name) -> ObjImpls::CKObject* { return new clsname(ctx, id, name); }, \
[](CKContext* ctx, ObjImpls::CKObject* obj) -> void { delete obj; }, \
[]() -> CKSTRING { return strName; });
EasyClassReg(ObjImpls::CKObject, CK_CLASSID::CKCID_OBJECT, CK_CLASSID::CKCID_OBJECT, "Basic Object");
EasyClassReg(ObjImpls::CKSceneObject, CK_CLASSID::CKCID_SCENEOBJECT, CK_CLASSID::CKCID_OBJECT, "Scene Object");
EasyClassReg(ObjImpls::CKBeObject, CK_CLASSID::CKCID_BEOBJECT, CK_CLASSID::CKCID_SCENEOBJECT, "Behavioral Object");
EasyClassReg(ObjImpls::CKGroup, CK_CLASSID::CKCID_GROUP, CK_CLASSID::CKCID_BEOBJECT, "Group");
//CKClassRegister(CK_CLASSID::CKCID_OBJECT, CK_CLASSID::CKCID_OBJECT,
// [](CKContext* ctx, CK_ID id, CKSTRING name) -> ObjImpls::CKObject* { return new ObjImpls::CKObject(ctx, id, name); },
// [](CKContext* ctx, ObjImpls::CKObject* obj) -> void { delete obj; },
// []() -> CKSTRING { return "Basic Object"; });
#undef EasyClassReg
/*
// register CKObjects
@ -233,8 +267,6 @@ namespace LibCmo::CK2 {
CKERROR CKShutdown() {
// free class indo
g_CKClassInfo.clear();
g_CKClassInfoId2Idx.clear();
g_CKClassInfoMaxID = static_cast<CK_CLASSID>(0);
return CKERROR::CKERR_OK;
}