almost finish CKGroup
This commit is contained in:
parent
3755a2e148
commit
fd69914a25
|
@ -1,5 +1,6 @@
|
||||||
#include "CKContext.hpp"
|
#include "CKContext.hpp"
|
||||||
#include "ObjImpls/CKObject.hpp"
|
#include "ObjImpls/CKObject.hpp"
|
||||||
|
#include "../XContainer/XBitArray.hpp"
|
||||||
#include <cstdarg>
|
#include <cstdarg>
|
||||||
|
|
||||||
namespace LibCmo::CK2 {
|
namespace LibCmo::CK2 {
|
||||||
|
@ -10,6 +11,29 @@ namespace LibCmo::CK2 {
|
||||||
static char g_UniqueFolder[] = "LibCmo";
|
static char g_UniqueFolder[] = "LibCmo";
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#pragma region Ctor Dtor
|
||||||
|
|
||||||
|
CKContext::CKContext() :
|
||||||
|
m_ObjectsList(), m_ReturnedObjectIds(),
|
||||||
|
m_GroupGlobalIndex(), m_SceneGlobalIndex(),
|
||||||
|
m_CompressionLevel(5), m_FileWriteMode(CK_FILE_WRITEMODE::CKFILE_UNCOMPRESSED),
|
||||||
|
m_NameEncoding(), m_TempFolder(),
|
||||||
|
m_OutputCallback(nullptr)
|
||||||
|
{
|
||||||
|
// preset for temp folder
|
||||||
|
// todo: add current CKContext pointer as the part of temp path.
|
||||||
|
// thus multiple CKContext can work.
|
||||||
|
m_TempFolder = std::filesystem::temp_directory_path();
|
||||||
|
m_TempFolder /= g_UniqueFolder;
|
||||||
|
std::filesystem::create_directory(m_TempFolder);
|
||||||
|
}
|
||||||
|
|
||||||
|
CKContext::~CKContext() {
|
||||||
|
DestroyAllCKObjects();
|
||||||
|
}
|
||||||
|
|
||||||
|
#pragma endregion
|
||||||
|
|
||||||
#pragma region Objects Management
|
#pragma region Objects Management
|
||||||
|
|
||||||
ObjImpls::CKObject* CKContext::CreateCKObject(CK_CLASSID cls, CKSTRING name,
|
ObjImpls::CKObject* CKContext::CreateCKObject(CK_CLASSID cls, CKSTRING name,
|
||||||
|
@ -78,6 +102,45 @@ namespace LibCmo::CK2 {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
CKDWORD CKContext::AllocateGroupGlobalIndex() {
|
||||||
|
// try find first non-true position
|
||||||
|
CKDWORD index;
|
||||||
|
if (!XContainer::XBitArrayPatch::GetSetBitPosition(m_GroupGlobalIndex, 0, index)) {
|
||||||
|
// failed. distribute new one
|
||||||
|
index = static_cast<CKDWORD>(m_GroupGlobalIndex.size());
|
||||||
|
m_GroupGlobalIndex.resize(m_GroupGlobalIndex.size() + 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
// set to occupy
|
||||||
|
m_GroupGlobalIndex[index] = true;
|
||||||
|
return index;
|
||||||
|
}
|
||||||
|
|
||||||
|
CKDWORD CKContext::AllocateSceneGlobalIndex() {
|
||||||
|
// same as group
|
||||||
|
CKDWORD index;
|
||||||
|
if (!XContainer::XBitArrayPatch::GetSetBitPosition(m_SceneGlobalIndex, 0, index)) {
|
||||||
|
index = static_cast<CKDWORD>(m_SceneGlobalIndex.size());
|
||||||
|
m_SceneGlobalIndex.resize(m_SceneGlobalIndex.size() + 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
m_SceneGlobalIndex[index] = true;
|
||||||
|
return index;
|
||||||
|
}
|
||||||
|
|
||||||
|
void CKContext::FreeGroupGlobalIndex(CKDWORD id) {
|
||||||
|
// check position
|
||||||
|
if (id >= m_GroupGlobalIndex.size()) return;
|
||||||
|
// set value
|
||||||
|
m_GroupGlobalIndex[id] = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
void CKContext::FreeSceneGlobalIndex(CKDWORD id) {
|
||||||
|
// same as group
|
||||||
|
if (id >= m_SceneGlobalIndex.size()) return;
|
||||||
|
m_SceneGlobalIndex[id] = false;
|
||||||
|
}
|
||||||
|
|
||||||
void CKContext::DestroyAllCKObjects() {
|
void CKContext::DestroyAllCKObjects() {
|
||||||
// free all created objects
|
// free all created objects
|
||||||
for (auto& ptr : m_ObjectsList) {
|
for (auto& ptr : m_ObjectsList) {
|
||||||
|
@ -89,6 +152,10 @@ namespace LibCmo::CK2 {
|
||||||
m_ReturnedObjectIds.clear();
|
m_ReturnedObjectIds.clear();
|
||||||
// empty object list
|
// empty object list
|
||||||
m_ObjectsList.clear();
|
m_ObjectsList.clear();
|
||||||
|
|
||||||
|
// clear group and scene global index at the same time
|
||||||
|
m_SceneGlobalIndex.clear();
|
||||||
|
m_GroupGlobalIndex.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
#pragma endregion
|
#pragma endregion
|
||||||
|
@ -128,29 +195,6 @@ namespace LibCmo::CK2 {
|
||||||
|
|
||||||
#pragma endregion
|
#pragma endregion
|
||||||
|
|
||||||
|
|
||||||
#pragma region Ctor Dtor
|
|
||||||
|
|
||||||
CKContext::CKContext() :
|
|
||||||
m_ObjectsList(), m_ReturnedObjectIds(),
|
|
||||||
m_CompressionLevel(5), m_FileWriteMode(CK_FILE_WRITEMODE::CKFILE_UNCOMPRESSED),
|
|
||||||
m_NameEncoding(), m_TempFolder(),
|
|
||||||
m_OutputCallback(nullptr)
|
|
||||||
{
|
|
||||||
// preset for temp folder
|
|
||||||
// todo: add current CKContext pointer as the part of temp path.
|
|
||||||
// thus multiple CKContext can work.
|
|
||||||
m_TempFolder = std::filesystem::temp_directory_path();
|
|
||||||
m_TempFolder /= g_UniqueFolder;
|
|
||||||
std::filesystem::create_directory(m_TempFolder);
|
|
||||||
}
|
|
||||||
|
|
||||||
CKContext::~CKContext() {
|
|
||||||
DestroyAllCKObjects();
|
|
||||||
}
|
|
||||||
|
|
||||||
#pragma endregion
|
|
||||||
|
|
||||||
#pragma region Output utilities
|
#pragma region Output utilities
|
||||||
|
|
||||||
void CKContext::OutputToConsole(CKSTRING str) {
|
void CKContext::OutputToConsole(CKSTRING str) {
|
||||||
|
|
|
@ -42,6 +42,12 @@ namespace LibCmo::CK2 {
|
||||||
CK_CREATIONMODE* res = nullptr);
|
CK_CREATIONMODE* res = nullptr);
|
||||||
ObjImpls::CKObject* GetCKObject(CK_ID id);
|
ObjImpls::CKObject* GetCKObject(CK_ID id);
|
||||||
void DestroyCKObject(CK_ID id);
|
void DestroyCKObject(CK_ID id);
|
||||||
|
|
||||||
|
CKDWORD AllocateGroupGlobalIndex();
|
||||||
|
CKDWORD AllocateSceneGlobalIndex();
|
||||||
|
void FreeGroupGlobalIndex(CKDWORD id);
|
||||||
|
void FreeSceneGlobalIndex(CKDWORD id);
|
||||||
|
|
||||||
void DestroyAllCKObjects();
|
void DestroyAllCKObjects();
|
||||||
|
|
||||||
// ========== Object Access ==========
|
// ========== Object Access ==========
|
||||||
|
@ -94,6 +100,9 @@ namespace LibCmo::CK2 {
|
||||||
XContainer::XArray<ObjImpls::CKObject*> m_ObjectsList;
|
XContainer::XArray<ObjImpls::CKObject*> m_ObjectsList;
|
||||||
std::deque<CK_ID> m_ReturnedObjectIds;
|
std::deque<CK_ID> m_ReturnedObjectIds;
|
||||||
|
|
||||||
|
XContainer::XBitArray m_GroupGlobalIndex;
|
||||||
|
XContainer::XBitArray m_SceneGlobalIndex;
|
||||||
|
|
||||||
// ========== File Save/Load Options ==========
|
// ========== File Save/Load Options ==========
|
||||||
CKINT m_CompressionLevel;
|
CKINT m_CompressionLevel;
|
||||||
CK_FILE_WRITEMODE m_FileWriteMode;
|
CK_FILE_WRITEMODE m_FileWriteMode;
|
||||||
|
|
|
@ -34,6 +34,7 @@ namespace LibCmo::CK2 {
|
||||||
//using CKClassDependenciesCountFct = std::function<CKINT(CKINT)>;
|
//using CKClassDependenciesCountFct = std::function<CKINT(CKINT)>;
|
||||||
|
|
||||||
struct CKClassDesc {
|
struct CKClassDesc {
|
||||||
|
bool IsValid; /**< True if this CKClassDesc is a valid one. Because CK_CLASSID may not be consecutive. */
|
||||||
bool Done;
|
bool Done;
|
||||||
// Initialized upon class registration
|
// Initialized upon class registration
|
||||||
CK_CLASSID Self;
|
CK_CLASSID Self;
|
||||||
|
@ -62,6 +63,7 @@ namespace LibCmo::CK2 {
|
||||||
//XContainer::XSArray<CK_CLASSID> ToNotify; // List of ClassID to notify when an object of this class is deleted (inverse of ToBeNotify)
|
//XContainer::XSArray<CK_CLASSID> ToNotify; // List of ClassID to notify when an object of this class is deleted (inverse of ToBeNotify)
|
||||||
|
|
||||||
CKClassDesc() :
|
CKClassDesc() :
|
||||||
|
IsValid(false),
|
||||||
Done(false),
|
Done(false),
|
||||||
Self(CK_CLASSID::CKCID_OBJECT), Parent(CK_CLASSID::CKCID_OBJECT),
|
Self(CK_CLASSID::CKCID_OBJECT), Parent(CK_CLASSID::CKCID_OBJECT),
|
||||||
CreationFct(nullptr), ReleaseFct(nullptr), NameFct(nullptr),
|
CreationFct(nullptr), ReleaseFct(nullptr), NameFct(nullptr),
|
||||||
|
|
|
@ -11,6 +11,9 @@
|
||||||
#include <zlib.h>
|
#include <zlib.h>
|
||||||
|
|
||||||
#include "ObjImpls/CKObject.hpp"
|
#include "ObjImpls/CKObject.hpp"
|
||||||
|
#include "ObjImpls/CKSceneObject.hpp"
|
||||||
|
#include "ObjImpls/CKBeObject.hpp"
|
||||||
|
#include "ObjImpls/CKGroup.hpp"
|
||||||
|
|
||||||
namespace LibCmo::CK2 {
|
namespace LibCmo::CK2 {
|
||||||
|
|
||||||
|
@ -61,17 +64,23 @@ namespace LibCmo::CK2 {
|
||||||
#pragma region CKClass Registration
|
#pragma region CKClass Registration
|
||||||
|
|
||||||
static XContainer::XArray<CKClassDesc> g_CKClassInfo;
|
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) {
|
static void ComputeParentsTable(CKClassDesc& desc) {
|
||||||
// if it has done, do not process it again.
|
// if it has done, do not process it again.
|
||||||
if (desc.Done) return;
|
if (desc.Done) return;
|
||||||
|
|
||||||
// find direct parent
|
// find direct parent
|
||||||
auto finder = g_CKClassInfoId2Idx.find(desc.Parent);
|
CKClassDesc& parent = g_CKClassInfo[static_cast<size_t>(desc.Parent)];
|
||||||
if (finder == g_CKClassInfoId2Idx.end()) LIBPANIC("No such CK_CLASSID.");
|
if (!parent.IsValid) LIBPANIC("No such CK_CLASSID.");
|
||||||
CKClassDesc& parent = g_CKClassInfo[finder->second];
|
|
||||||
|
|
||||||
// if it is not self inheritance, call recursively
|
// if it is not self inheritance, call recursively
|
||||||
if (desc.Self != desc.Parent) {
|
if (desc.Self != desc.Parent) {
|
||||||
|
@ -81,9 +90,7 @@ namespace LibCmo::CK2 {
|
||||||
// copy parent's parents
|
// copy parent's parents
|
||||||
desc.Parents = parent.Parents;
|
desc.Parents = parent.Parents;
|
||||||
// and set self as its parent
|
// and set self as its parent
|
||||||
finder = g_CKClassInfoId2Idx.find(desc.Self);
|
desc.Parents[static_cast<size_t>(desc.Self)] = true;
|
||||||
if (finder == g_CKClassInfoId2Idx.end()) LIBPANIC("No such CK_CLASSID.");
|
|
||||||
desc.Parents[finder->second] = true;
|
|
||||||
|
|
||||||
// set derivation level
|
// set derivation level
|
||||||
desc.DerivationLevel = parent.DerivationLevel + 1;
|
desc.DerivationLevel = parent.DerivationLevel + 1;
|
||||||
|
@ -95,26 +102,30 @@ namespace LibCmo::CK2 {
|
||||||
// set Done to false and resize all XBitArray
|
// set Done to false and resize all XBitArray
|
||||||
size_t classCount = g_CKClassInfo.size();
|
size_t classCount = g_CKClassInfo.size();
|
||||||
for (auto& item : g_CKClassInfo) {
|
for (auto& item : g_CKClassInfo) {
|
||||||
|
if (!item.IsValid) continue;
|
||||||
|
|
||||||
item.Done = false;
|
item.Done = false;
|
||||||
item.Parents.resize(classCount, false);
|
item.Parents.resize(classCount, false);
|
||||||
item.Children.resize(classCount, false);
|
item.Children.resize(classCount, false);
|
||||||
}
|
}
|
||||||
// compute parents
|
// compute parents
|
||||||
for (auto& item : g_CKClassInfo) {
|
for (auto& item : g_CKClassInfo) {
|
||||||
|
if (!item.IsValid) continue;
|
||||||
|
|
||||||
ComputeParentsTable(item);
|
ComputeParentsTable(item);
|
||||||
}
|
}
|
||||||
// compute children by parents table
|
// compute children by parents table
|
||||||
// iterate CKClassDesc::Parents and register it self to gotten parents
|
// iterate CKClassDesc::Parents and register it self to gotten parents
|
||||||
for (auto& item : g_CKClassInfo) {
|
for (auto& item : g_CKClassInfo) {
|
||||||
auto finder = g_CKClassInfoId2Idx.find(item.Self);
|
if (!item.IsValid) continue;
|
||||||
if (finder == g_CKClassInfoId2Idx.end()) LIBPANIC("No such CK_CLASSID.");
|
|
||||||
size_t selfidx = finder->second;
|
|
||||||
|
|
||||||
for (size_t idx = 0; idx < classCount; ++idx) {
|
for (size_t idx = 0; idx < classCount; ++idx) {
|
||||||
|
if (!g_CKClassInfo[idx].IsValid) continue;
|
||||||
|
|
||||||
// if this idx is its parent,
|
// if this idx is its parent,
|
||||||
// add self to parent.
|
// add self to parent.
|
||||||
if (item.Parents[idx]) {
|
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,
|
void CKClassRegister(CK_CLASSID cid, CK_CLASSID parentCid,
|
||||||
CKClassCreationFct createFct, CKClassReleaseFct relFct, CKClassNameFct nameFct) {
|
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;
|
CKClassDesc desc;
|
||||||
|
desc.IsValid = true;
|
||||||
desc.Self = cid;
|
desc.Self = cid;
|
||||||
desc.Parent = parentCid;
|
desc.Parent = parentCid;
|
||||||
desc.CreationFct = createFct;
|
desc.CreationFct = createFct;
|
||||||
desc.ReleaseFct = relFct;
|
desc.ReleaseFct = relFct;
|
||||||
desc.NameFct = nameFct;
|
desc.NameFct = nameFct;
|
||||||
g_CKClassInfoId2Idx.emplace(cid, g_CKClassInfo.size());
|
g_CKClassInfo[intcid] = std::move(desc);
|
||||||
g_CKClassInfo.emplace_back(std::move(desc));
|
|
||||||
g_CKClassInfoMaxID = std::max(g_CKClassInfoMaxID, cid);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#pragma endregion
|
#pragma endregion
|
||||||
|
|
||||||
#pragma region Class Hierarchy Management
|
#pragma region Class Hierarchy Management
|
||||||
|
|
||||||
CKINT CKGetClassCount() {
|
static bool GetClassIdIndex(CK_CLASSID cid, size_t& intcid) {
|
||||||
return static_cast<CKINT>(g_CKClassInfo.size());
|
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) {
|
const CKClassDesc* CKGetClassDesc(CK_CLASSID cid) {
|
||||||
auto finder = g_CKClassInfoId2Idx.find(cid);
|
size_t intcid;
|
||||||
if (finder == g_CKClassInfoId2Idx.end()) return nullptr;
|
if (!GetClassIdIndex(cid, intcid)) return nullptr;
|
||||||
return g_CKClassInfo.data() + finder->second;
|
return &g_CKClassInfo[intcid];
|
||||||
}
|
}
|
||||||
|
|
||||||
CKSTRING CKClassIDToString(CK_CLASSID cid) {
|
CKSTRING CKClassIDToString(CK_CLASSID cid) {
|
||||||
auto finder = g_CKClassInfoId2Idx.find(cid);
|
const CKClassDesc* desc = CKGetClassDesc(cid);
|
||||||
if (finder == g_CKClassInfoId2Idx.end() || g_CKClassInfo[finder->second].NameFct == nullptr) return "Invalid Class Identifier";
|
if (desc == nullptr) return "Undefined Type";
|
||||||
return g_CKClassInfo[finder->second].NameFct();
|
else return desc->NameFct();
|
||||||
}
|
}
|
||||||
|
|
||||||
bool CKIsChildClassOf(CK_CLASSID child, CK_CLASSID parent) {
|
bool CKIsChildClassOf(CK_CLASSID child, CK_CLASSID parent) {
|
||||||
// get corresponding index first
|
size_t intchild, intparent;
|
||||||
// if we can't find it, return false anyway.
|
if (!GetClassIdIndex(child, intchild) || !GetClassIdIndex(parent, intparent)) return false;
|
||||||
auto finder = g_CKClassInfoId2Idx.find(child);
|
return g_CKClassInfo[intchild].Parents[intparent];
|
||||||
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];
|
|
||||||
}
|
}
|
||||||
|
|
||||||
CK_CLASSID CKGetParentClassID(CK_CLASSID child) {
|
CK_CLASSID CKGetParentClassID(CK_CLASSID child) {
|
||||||
auto finder = g_CKClassInfoId2Idx.find(child);
|
const CKClassDesc* desc = CKGetClassDesc(child);
|
||||||
if (finder == g_CKClassInfoId2Idx.end()) LIBPANIC("No such CK_CLASSID.");
|
if (desc == nullptr) return CK_CLASSID::CKCID_OBJECT;
|
||||||
return g_CKClassInfo[finder->second].Parent;
|
return desc->Parent;
|
||||||
}
|
}
|
||||||
|
|
||||||
CK_CLASSID CKGetCommonParent(CK_CLASSID cid1, CK_CLASSID cid2) {
|
CK_CLASSID CKGetCommonParent(CK_CLASSID cid1, CK_CLASSID cid2) {
|
||||||
|
@ -190,11 +207,28 @@ namespace LibCmo::CK2 {
|
||||||
#pragma region Initializations functions
|
#pragma region Initializations functions
|
||||||
|
|
||||||
CKERROR CKStartUp() {
|
CKERROR CKStartUp() {
|
||||||
|
|
||||||
|
// reserve class info array.
|
||||||
|
g_CKClassInfo.reserve(static_cast<size_t>(CK_CLASSID::CKCID_MAXCLASSID));
|
||||||
|
|
||||||
// todo: add class type registrations
|
// todo: add class type registrations
|
||||||
CKClassRegister(CK_CLASSID::CKCID_OBJECT, CK_CLASSID::CKCID_OBJECT,
|
#define EasyClassReg(clsname, cid, parentCid, strName) \
|
||||||
[](CKContext* ctx, CK_ID id, CKSTRING name) -> ObjImpls::CKObject* { return new ObjImpls::CKObject(ctx, id, name); },
|
CKClassRegister(cid, parentCid, \
|
||||||
[](CKContext* ctx, ObjImpls::CKObject* obj) -> void { delete obj; },
|
[](CKContext* ctx, CK_ID id, CKSTRING name) -> ObjImpls::CKObject* { return new clsname(ctx, id, name); }, \
|
||||||
[]() -> CKSTRING { return "Basic Object"; });
|
[](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
|
// register CKObjects
|
||||||
|
@ -233,8 +267,6 @@ namespace LibCmo::CK2 {
|
||||||
CKERROR CKShutdown() {
|
CKERROR CKShutdown() {
|
||||||
// free class indo
|
// free class indo
|
||||||
g_CKClassInfo.clear();
|
g_CKClassInfo.clear();
|
||||||
g_CKClassInfoId2Idx.clear();
|
|
||||||
g_CKClassInfoMaxID = static_cast<CK_CLASSID>(0);
|
|
||||||
|
|
||||||
return CKERROR::CKERR_OK;
|
return CKERROR::CKERR_OK;
|
||||||
}
|
}
|
||||||
|
|
|
@ -54,12 +54,13 @@ namespace LibCmo::CK2 {
|
||||||
|
|
||||||
// ========== CKClass Registration ==========
|
// ========== CKClass Registration ==========
|
||||||
|
|
||||||
|
CK_CLASSID CKClassGetNewIdentifier();
|
||||||
void CKClassRegister(CK_CLASSID cid, CK_CLASSID parentCid,
|
void CKClassRegister(CK_CLASSID cid, CK_CLASSID parentCid,
|
||||||
CKClassCreationFct createFct, CKClassReleaseFct relFct, CKClassNameFct nameFct);
|
CKClassCreationFct createFct, CKClassReleaseFct relFct, CKClassNameFct nameFct);
|
||||||
|
|
||||||
// ========== Class Hierarchy Management ==========
|
// ========== Class Hierarchy Management ==========
|
||||||
|
|
||||||
CKINT CKGetClassCount();
|
CKDWORD CKGetClassCount();
|
||||||
const CKClassDesc* CKGetClassDesc(CK_CLASSID cid);
|
const CKClassDesc* CKGetClassDesc(CK_CLASSID cid);
|
||||||
CKSTRING CKClassIDToString(CK_CLASSID cid);
|
CKSTRING CKClassIDToString(CK_CLASSID cid);
|
||||||
|
|
||||||
|
|
|
@ -22,4 +22,9 @@ namespace LibCmo::CK2::ObjImpls {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void CKBeObject::CKGroup_SetGroups(CKDWORD pos, bool val) {
|
||||||
|
if (pos >= m_Groups.size()) m_Groups.resize(pos + 1);
|
||||||
|
m_Groups[pos] = val;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
|
@ -22,6 +22,7 @@ namespace LibCmo::CK2::ObjImpls {
|
||||||
//virtual void PostLoad() override;
|
//virtual void PostLoad() override;
|
||||||
|
|
||||||
bool IsInGroup(CKGroup* group);
|
bool IsInGroup(CKGroup* group);
|
||||||
|
void CKGroup_SetGroups(CKDWORD pos, bool val);
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
XContainer::XBitArray m_Groups;
|
XContainer::XBitArray m_Groups;
|
||||||
|
|
|
@ -1,27 +1,92 @@
|
||||||
#include "CKSceneObject.hpp"
|
|
||||||
#include "../CKStateChunk.hpp"
|
|
||||||
#include "CKGroup.hpp"
|
#include "CKGroup.hpp"
|
||||||
|
#include "../CKStateChunk.hpp"
|
||||||
|
#include "../CKContext.hpp"
|
||||||
|
#include <algorithm>
|
||||||
|
|
||||||
namespace LibCmo::CK2::ObjImpls {
|
namespace LibCmo::CK2::ObjImpls {
|
||||||
|
|
||||||
|
CKGroup::CKGroup(CKContext* ctx, CK_ID ckid, CKSTRING name) :
|
||||||
|
CKBeObject(ctx, ckid, name),
|
||||||
|
m_ObjectArray(),
|
||||||
|
m_GroupIndex(m_Context->AllocateGroupGlobalIndex()) {}
|
||||||
|
|
||||||
|
CKGroup::~CKGroup() {
|
||||||
|
m_Context->FreeGroupGlobalIndex(m_GroupIndex);
|
||||||
|
}
|
||||||
|
|
||||||
bool CKGroup::Save(CKStateChunk* chunk, CKFileVisitor* file, CKDWORD flags) {
|
bool CKGroup::Save(CKStateChunk* chunk, CKFileVisitor* file, CKDWORD flags) {
|
||||||
return false;
|
bool suc = CKBeObject::Save(chunk, file, flags);
|
||||||
|
if (!suc) return false;
|
||||||
|
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool CKGroup::Load(CKStateChunk* chunk, CKFileVisitor* file) {
|
bool CKGroup::Load(CKStateChunk* chunk, CKFileVisitor* file) {
|
||||||
return false;
|
bool suc = CKBeObject::Load(chunk, file);
|
||||||
|
if (!suc) return false;
|
||||||
|
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
CKDWORD CKGroup::GetGroupIndex() {
|
CKDWORD CKGroup::GetGroupIndex() {
|
||||||
return m_GroupIndex;
|
return m_GroupIndex;
|
||||||
}
|
}
|
||||||
|
|
||||||
CKObject* CKGroup::GetObject(CKDWORD pos) {
|
CKERROR CKGroup::AddObject(CKBeObject* o) {
|
||||||
return nullptr;
|
if (o == nullptr || o == this || !CKIsChildClassOf(o->GetClassID(), CK_CLASSID::CKCID_BEOBJECT)) {
|
||||||
|
return CKERROR::CKERR_INVALIDPARAMETER;
|
||||||
|
}
|
||||||
|
if (o->IsInGroup(this)) {
|
||||||
|
return CKERROR::CKERR_ALREADYPRESENT;
|
||||||
|
}
|
||||||
|
|
||||||
|
// set object
|
||||||
|
o->CKGroup_SetGroups(m_GroupIndex, true);
|
||||||
|
// set self
|
||||||
|
m_ObjectArray.emplace_back(o);
|
||||||
|
return CKERROR::CKERR_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
CKBeObject* CKGroup::RemoveObject(CKDWORD pos) {
|
||||||
|
// check pos
|
||||||
|
if (pos >= m_ObjectArray.size()) return nullptr;
|
||||||
|
|
||||||
|
auto it = m_ObjectArray.begin() + pos;
|
||||||
|
CKBeObject* obj = static_cast<CKBeObject*>(*it);
|
||||||
|
// set object
|
||||||
|
obj->CKGroup_SetGroups(m_GroupIndex, false);
|
||||||
|
// remove self
|
||||||
|
m_ObjectArray.erase(it);
|
||||||
|
return obj;
|
||||||
|
}
|
||||||
|
|
||||||
|
void CKGroup::RemoveObject(CKBeObject* obj) {
|
||||||
|
// find first
|
||||||
|
auto finder = std::find(m_ObjectArray.begin(), m_ObjectArray.end(), static_cast<CKObject*>(obj));
|
||||||
|
if (finder != m_ObjectArray.end()) {
|
||||||
|
// set object
|
||||||
|
static_cast<CKBeObject*>(*finder)->CKGroup_SetGroups(m_GroupIndex, false);
|
||||||
|
// remove self
|
||||||
|
m_ObjectArray.erase(finder);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void CKGroup::Clear() {
|
||||||
|
for (auto& beobj : m_ObjectArray) {
|
||||||
|
// set object
|
||||||
|
static_cast<CKBeObject*>(beobj)->CKGroup_SetGroups(m_GroupIndex, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
m_ObjectArray.clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
CKBeObject* CKGroup::GetObject(CKDWORD pos) {
|
||||||
|
if (pos >= m_ObjectArray.size()) return nullptr;
|
||||||
|
else return static_cast<CKBeObject*>(m_ObjectArray[pos]);
|
||||||
}
|
}
|
||||||
|
|
||||||
CKDWORD CKGroup::GetObjectCount() {
|
CKDWORD CKGroup::GetObjectCount() {
|
||||||
return CKDWORD();
|
return static_cast<CKDWORD>(m_ObjectArray.size());
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -7,14 +7,8 @@ namespace LibCmo::CK2::ObjImpls {
|
||||||
|
|
||||||
class CKGroup : public CKBeObject {
|
class CKGroup : public CKBeObject {
|
||||||
public:
|
public:
|
||||||
CKGroup(CKContext* ctx, CK_ID ckid, CKSTRING name) :
|
CKGroup(CKContext* ctx, CK_ID ckid, CKSTRING name);
|
||||||
CKBeObject(ctx, ckid, name),
|
virtual ~CKGroup();
|
||||||
m_ObjectArray(),
|
|
||||||
m_GroupIndex() // todo: allocate group id
|
|
||||||
{}
|
|
||||||
virtual ~CKGroup() {
|
|
||||||
// todo: free allocated group id
|
|
||||||
}
|
|
||||||
LIBCMO_DISABLE_COPY_MOVE(CKGroup);
|
LIBCMO_DISABLE_COPY_MOVE(CKGroup);
|
||||||
|
|
||||||
virtual CK_CLASSID GetClassID(void) override {
|
virtual CK_CLASSID GetClassID(void) override {
|
||||||
|
@ -29,20 +23,14 @@ namespace LibCmo::CK2::ObjImpls {
|
||||||
|
|
||||||
// ===== Insert =====
|
// ===== Insert =====
|
||||||
CKERROR AddObject(CKBeObject *o);
|
CKERROR AddObject(CKBeObject *o);
|
||||||
CKERROR AddObjectFront(CKBeObject *o);
|
|
||||||
CKERROR InsertObjectAt(CKBeObject *o, CKDWORD pos);
|
|
||||||
|
|
||||||
// ===== Remove =====
|
// ===== Remove =====
|
||||||
CKBeObject* RemoveObject(CKDWORD pos);
|
CKBeObject* RemoveObject(CKDWORD pos);
|
||||||
void RemoveObject(CKBeObject *obj);
|
void RemoveObject(CKBeObject *obj);
|
||||||
void Clear();
|
void Clear();
|
||||||
|
|
||||||
// ===== Order =====
|
|
||||||
void MoveObjectUp(CKBeObject *o);
|
|
||||||
void MoveObjectDown(CKBeObject *o);
|
|
||||||
|
|
||||||
// ===== Access =====
|
// ===== Access =====
|
||||||
CKObject* GetObject(CKDWORD pos);
|
CKBeObject* GetObject(CKDWORD pos);
|
||||||
CKDWORD GetObjectCount();
|
CKDWORD GetObjectCount();
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
|
|
@ -189,6 +189,7 @@
|
||||||
<ClCompile Include="CK2\CKStateChunk.cpp" />
|
<ClCompile Include="CK2\CKStateChunk.cpp" />
|
||||||
<ClCompile Include="VTUtils.cpp" />
|
<ClCompile Include="VTUtils.cpp" />
|
||||||
<ClCompile Include="VxMath\VxMemoryMappedFile.cpp" />
|
<ClCompile Include="VxMath\VxMemoryMappedFile.cpp" />
|
||||||
|
<ClCompile Include="XContainer\XBitArray.cpp" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<ClInclude Include="CK2\CKDefines.hpp" />
|
<ClInclude Include="CK2\CKDefines.hpp" />
|
||||||
|
@ -209,6 +210,7 @@
|
||||||
<ClInclude Include="VTUtils.hpp" />
|
<ClInclude Include="VTUtils.hpp" />
|
||||||
<ClInclude Include="VxMath\VxMemoryMappedFile.hpp" />
|
<ClInclude Include="VxMath\VxMemoryMappedFile.hpp" />
|
||||||
<ClInclude Include="VxMath\VxTypes.hpp" />
|
<ClInclude Include="VxMath\VxTypes.hpp" />
|
||||||
|
<ClInclude Include="XContainer\XBitArray.hpp" />
|
||||||
<ClInclude Include="XContainer\XTypes.hpp" />
|
<ClInclude Include="XContainer\XTypes.hpp" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
|
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
|
||||||
|
|
|
@ -87,6 +87,9 @@
|
||||||
<ClCompile Include="CK2\ObjImpls\CKGroup.cpp">
|
<ClCompile Include="CK2\ObjImpls\CKGroup.cpp">
|
||||||
<Filter>Sources\CK2\ObjImpls</Filter>
|
<Filter>Sources\CK2\ObjImpls</Filter>
|
||||||
</ClCompile>
|
</ClCompile>
|
||||||
|
<ClCompile Include="XContainer\XBitArray.cpp">
|
||||||
|
<Filter>Sources\XContainer</Filter>
|
||||||
|
</ClCompile>
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<ClInclude Include="VTUtils.hpp">
|
<ClInclude Include="VTUtils.hpp">
|
||||||
|
@ -146,5 +149,8 @@
|
||||||
<ClInclude Include="CK2\ObjImpls\CKGroup.hpp">
|
<ClInclude Include="CK2\ObjImpls\CKGroup.hpp">
|
||||||
<Filter>Headers\CK2\ObjImpls</Filter>
|
<Filter>Headers\CK2\ObjImpls</Filter>
|
||||||
</ClInclude>
|
</ClInclude>
|
||||||
|
<ClInclude Include="XContainer\XBitArray.hpp">
|
||||||
|
<Filter>Headers\XContainer</Filter>
|
||||||
|
</ClInclude>
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
</Project>
|
</Project>
|
30
LibCmo/XContainer/XBitArray.cpp
Normal file
30
LibCmo/XContainer/XBitArray.cpp
Normal file
|
@ -0,0 +1,30 @@
|
||||||
|
#include "XBitArray.hpp"
|
||||||
|
|
||||||
|
namespace LibCmo::XContainer::XBitArrayPatch {
|
||||||
|
|
||||||
|
template<bool _Cond>
|
||||||
|
bool GeneralGetBitPosition(XBitArray& ba, CK2::CKDWORD n, CK2::CKDWORD& got) {
|
||||||
|
CK2::CKDWORD counter = 0;
|
||||||
|
for (size_t i = 0; i < ba.size(); ++i) {
|
||||||
|
if (ba[i] == _Cond) {
|
||||||
|
if (counter == n) {
|
||||||
|
got = static_cast<CK2::CKDWORD>(i);
|
||||||
|
return true;
|
||||||
|
} else {
|
||||||
|
++counter;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool GetSetBitPosition(XBitArray& ba, CK2::CKDWORD n, CK2::CKDWORD& got) {
|
||||||
|
return GeneralGetBitPosition<true>(ba, n, got);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool GetUnsetBitPosition(XBitArray& ba, CK2::CKDWORD n, CK2::CKDWORD& got) {
|
||||||
|
return GeneralGetBitPosition<false>(ba, n, got);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
17
LibCmo/XContainer/XBitArray.hpp
Normal file
17
LibCmo/XContainer/XBitArray.hpp
Normal file
|
@ -0,0 +1,17 @@
|
||||||
|
#pragma once
|
||||||
|
#include "XTypes.hpp"
|
||||||
|
|
||||||
|
namespace LibCmo::XContainer::XBitArrayPatch {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Returns the position of the n-th set(1) bit
|
||||||
|
* @return false if not found.
|
||||||
|
*/
|
||||||
|
bool GetSetBitPosition(XBitArray& ba, CK2::CKDWORD n, CK2::CKDWORD& got);
|
||||||
|
/**
|
||||||
|
* @brief Returns the position of the n-th unset(0) bit
|
||||||
|
* @return false if not found.
|
||||||
|
*/
|
||||||
|
bool GetUnsetBitPosition(XBitArray& ba, CK2::CKDWORD n, CK2::CKDWORD& got);
|
||||||
|
|
||||||
|
}
|
|
@ -167,14 +167,28 @@ namespace Unvirt::StructFormatter {
|
||||||
|
|
||||||
void PrintCKObject(const LibCmo::CK2::ObjImpls::CKObject* obj) {
|
void PrintCKObject(const LibCmo::CK2::ObjImpls::CKObject* obj) {
|
||||||
fputs(UNVIRT_TERMCOL_LIGHT_YELLOW(("CKObject\n")), stdout);
|
fputs(UNVIRT_TERMCOL_LIGHT_YELLOW(("CKObject\n")), stdout);
|
||||||
|
if (obj == nullptr) {
|
||||||
|
fputs(UNVIRT_TERMCOL_LIGHT_RED(("No Data\n")), stdout);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
fputs(UNVIRT_TERMCOL_LIGHT_RED(("Not Implemented.\n")), stdout);
|
fputs(UNVIRT_TERMCOL_LIGHT_RED(("Not Implemented.\n")), stdout);
|
||||||
}
|
}
|
||||||
void PrintCKBaseManager(const LibCmo::CK2::MgrImpls::CKBaseManager* mgr) {
|
void PrintCKBaseManager(const LibCmo::CK2::MgrImpls::CKBaseManager* mgr) {
|
||||||
fputs(UNVIRT_TERMCOL_LIGHT_YELLOW(("CKBaseManager\n")), stdout);
|
fputs(UNVIRT_TERMCOL_LIGHT_YELLOW(("CKBaseManager\n")), stdout);
|
||||||
|
if (mgr == nullptr) {
|
||||||
|
fputs(UNVIRT_TERMCOL_LIGHT_RED(("No Data\n")), stdout);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
fputs(UNVIRT_TERMCOL_LIGHT_RED(("Not Implemented.\n")), stdout);
|
fputs(UNVIRT_TERMCOL_LIGHT_RED(("Not Implemented.\n")), stdout);
|
||||||
}
|
}
|
||||||
void PrintCKStateChunk(const LibCmo::CK2::CKStateChunk* chunk) {
|
void PrintCKStateChunk(const LibCmo::CK2::CKStateChunk* chunk) {
|
||||||
fputs(UNVIRT_TERMCOL_LIGHT_YELLOW(("CKStateChunk\n")), stdout);
|
fputs(UNVIRT_TERMCOL_LIGHT_YELLOW(("CKStateChunk\n")), stdout);
|
||||||
|
if (chunk == nullptr) {
|
||||||
|
fputs(UNVIRT_TERMCOL_LIGHT_RED(("No Data\n")), stdout);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
// hack const state chunk
|
// hack const state chunk
|
||||||
LibCmo::CK2::CKStateChunk* operchunk = const_cast<LibCmo::CK2::CKStateChunk*>(chunk);
|
LibCmo::CK2::CKStateChunk* operchunk = const_cast<LibCmo::CK2::CKStateChunk*>(chunk);
|
||||||
|
|
|
@ -127,6 +127,7 @@ namespace Unvirt::Context {
|
||||||
m_Help = root->RootHelp();
|
m_Help = root->RootHelp();
|
||||||
|
|
||||||
// create context
|
// create context
|
||||||
|
LibCmo::CK2::CKStartUp();
|
||||||
m_Ctx = new LibCmo::CK2::CKContext();
|
m_Ctx = new LibCmo::CK2::CKContext();
|
||||||
m_Ctx->SetOutputCallback(std::bind(&UnvirtContext::PrintContextMsg, this, std::placeholders::_1));
|
m_Ctx->SetOutputCallback(std::bind(&UnvirtContext::PrintContextMsg, this, std::placeholders::_1));
|
||||||
}
|
}
|
||||||
|
@ -134,6 +135,11 @@ namespace Unvirt::Context {
|
||||||
UnvirtContext::~UnvirtContext() {
|
UnvirtContext::~UnvirtContext() {
|
||||||
if (m_Help != nullptr)
|
if (m_Help != nullptr)
|
||||||
delete m_Help;
|
delete m_Help;
|
||||||
|
|
||||||
|
// free context
|
||||||
|
ClearDocument();
|
||||||
|
delete m_Ctx;
|
||||||
|
LibCmo::CK2::CKShutdown();
|
||||||
}
|
}
|
||||||
|
|
||||||
bool UnvirtContext::HasOpenedFile() {
|
bool UnvirtContext::HasOpenedFile() {
|
||||||
|
|
Loading…
Reference in New Issue
Block a user