almost finish CKGroup
This commit is contained in:
parent
3755a2e148
commit
fd69914a25
|
@ -1,5 +1,6 @@
|
|||
#include "CKContext.hpp"
|
||||
#include "ObjImpls/CKObject.hpp"
|
||||
#include "../XContainer/XBitArray.hpp"
|
||||
#include <cstdarg>
|
||||
|
||||
namespace LibCmo::CK2 {
|
||||
|
@ -10,6 +11,29 @@ namespace LibCmo::CK2 {
|
|||
static char g_UniqueFolder[] = "LibCmo";
|
||||
#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
|
||||
|
||||
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() {
|
||||
// free all created objects
|
||||
for (auto& ptr : m_ObjectsList) {
|
||||
|
@ -89,6 +152,10 @@ namespace LibCmo::CK2 {
|
|||
m_ReturnedObjectIds.clear();
|
||||
// empty object list
|
||||
m_ObjectsList.clear();
|
||||
|
||||
// clear group and scene global index at the same time
|
||||
m_SceneGlobalIndex.clear();
|
||||
m_GroupGlobalIndex.clear();
|
||||
}
|
||||
|
||||
#pragma endregion
|
||||
|
@ -128,29 +195,6 @@ namespace LibCmo::CK2 {
|
|||
|
||||
#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
|
||||
|
||||
void CKContext::OutputToConsole(CKSTRING str) {
|
||||
|
|
|
@ -42,6 +42,12 @@ namespace LibCmo::CK2 {
|
|||
CK_CREATIONMODE* res = nullptr);
|
||||
ObjImpls::CKObject* GetCKObject(CK_ID id);
|
||||
void DestroyCKObject(CK_ID id);
|
||||
|
||||
CKDWORD AllocateGroupGlobalIndex();
|
||||
CKDWORD AllocateSceneGlobalIndex();
|
||||
void FreeGroupGlobalIndex(CKDWORD id);
|
||||
void FreeSceneGlobalIndex(CKDWORD id);
|
||||
|
||||
void DestroyAllCKObjects();
|
||||
|
||||
// ========== Object Access ==========
|
||||
|
@ -94,6 +100,9 @@ namespace LibCmo::CK2 {
|
|||
XContainer::XArray<ObjImpls::CKObject*> m_ObjectsList;
|
||||
std::deque<CK_ID> m_ReturnedObjectIds;
|
||||
|
||||
XContainer::XBitArray m_GroupGlobalIndex;
|
||||
XContainer::XBitArray m_SceneGlobalIndex;
|
||||
|
||||
// ========== File Save/Load Options ==========
|
||||
CKINT m_CompressionLevel;
|
||||
CK_FILE_WRITEMODE m_FileWriteMode;
|
||||
|
|
|
@ -34,6 +34,7 @@ namespace LibCmo::CK2 {
|
|||
//using CKClassDependenciesCountFct = std::function<CKINT(CKINT)>;
|
||||
|
||||
struct CKClassDesc {
|
||||
bool IsValid; /**< True if this CKClassDesc is a valid one. Because CK_CLASSID may not be consecutive. */
|
||||
bool Done;
|
||||
// Initialized upon class registration
|
||||
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)
|
||||
|
||||
CKClassDesc() :
|
||||
IsValid(false),
|
||||
Done(false),
|
||||
Self(CK_CLASSID::CKCID_OBJECT), Parent(CK_CLASSID::CKCID_OBJECT),
|
||||
CreationFct(nullptr), ReleaseFct(nullptr), NameFct(nullptr),
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -54,12 +54,13 @@ namespace LibCmo::CK2 {
|
|||
|
||||
// ========== CKClass Registration ==========
|
||||
|
||||
CK_CLASSID CKClassGetNewIdentifier();
|
||||
void CKClassRegister(CK_CLASSID cid, CK_CLASSID parentCid,
|
||||
CKClassCreationFct createFct, CKClassReleaseFct relFct, CKClassNameFct nameFct);
|
||||
|
||||
// ========== Class Hierarchy Management ==========
|
||||
|
||||
CKINT CKGetClassCount();
|
||||
CKDWORD CKGetClassCount();
|
||||
const CKClassDesc* CKGetClassDesc(CK_CLASSID cid);
|
||||
CKSTRING CKClassIDToString(CK_CLASSID cid);
|
||||
|
||||
|
|
|
@ -22,4 +22,9 @@ namespace LibCmo::CK2::ObjImpls {
|
|||
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;
|
||||
|
||||
bool IsInGroup(CKGroup* group);
|
||||
void CKGroup_SetGroups(CKDWORD pos, bool val);
|
||||
|
||||
protected:
|
||||
XContainer::XBitArray m_Groups;
|
||||
|
|
|
@ -1,27 +1,92 @@
|
|||
#include "CKSceneObject.hpp"
|
||||
#include "../CKStateChunk.hpp"
|
||||
#include "CKGroup.hpp"
|
||||
#include "../CKStateChunk.hpp"
|
||||
#include "../CKContext.hpp"
|
||||
#include <algorithm>
|
||||
|
||||
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) {
|
||||
return false;
|
||||
bool suc = CKBeObject::Save(chunk, file, flags);
|
||||
if (!suc) return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool CKGroup::Load(CKStateChunk* chunk, CKFileVisitor* file) {
|
||||
return false;
|
||||
bool suc = CKBeObject::Load(chunk, file);
|
||||
if (!suc) return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
CKDWORD CKGroup::GetGroupIndex() {
|
||||
return m_GroupIndex;
|
||||
}
|
||||
|
||||
CKObject* CKGroup::GetObject(CKDWORD pos) {
|
||||
return nullptr;
|
||||
CKERROR CKGroup::AddObject(CKBeObject* o) {
|
||||
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() {
|
||||
return CKDWORD();
|
||||
return static_cast<CKDWORD>(m_ObjectArray.size());
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -7,14 +7,8 @@ namespace LibCmo::CK2::ObjImpls {
|
|||
|
||||
class CKGroup : public CKBeObject {
|
||||
public:
|
||||
CKGroup(CKContext* ctx, CK_ID ckid, CKSTRING name) :
|
||||
CKBeObject(ctx, ckid, name),
|
||||
m_ObjectArray(),
|
||||
m_GroupIndex() // todo: allocate group id
|
||||
{}
|
||||
virtual ~CKGroup() {
|
||||
// todo: free allocated group id
|
||||
}
|
||||
CKGroup(CKContext* ctx, CK_ID ckid, CKSTRING name);
|
||||
virtual ~CKGroup();
|
||||
LIBCMO_DISABLE_COPY_MOVE(CKGroup);
|
||||
|
||||
virtual CK_CLASSID GetClassID(void) override {
|
||||
|
@ -29,20 +23,14 @@ namespace LibCmo::CK2::ObjImpls {
|
|||
|
||||
// ===== Insert =====
|
||||
CKERROR AddObject(CKBeObject *o);
|
||||
CKERROR AddObjectFront(CKBeObject *o);
|
||||
CKERROR InsertObjectAt(CKBeObject *o, CKDWORD pos);
|
||||
|
||||
// ===== Remove =====
|
||||
CKBeObject* RemoveObject(CKDWORD pos);
|
||||
void RemoveObject(CKBeObject *obj);
|
||||
void Clear();
|
||||
|
||||
// ===== Order =====
|
||||
void MoveObjectUp(CKBeObject *o);
|
||||
void MoveObjectDown(CKBeObject *o);
|
||||
|
||||
// ===== Access =====
|
||||
CKObject* GetObject(CKDWORD pos);
|
||||
CKBeObject* GetObject(CKDWORD pos);
|
||||
CKDWORD GetObjectCount();
|
||||
|
||||
protected:
|
||||
|
|
|
@ -189,6 +189,7 @@
|
|||
<ClCompile Include="CK2\CKStateChunk.cpp" />
|
||||
<ClCompile Include="VTUtils.cpp" />
|
||||
<ClCompile Include="VxMath\VxMemoryMappedFile.cpp" />
|
||||
<ClCompile Include="XContainer\XBitArray.cpp" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClInclude Include="CK2\CKDefines.hpp" />
|
||||
|
@ -209,6 +210,7 @@
|
|||
<ClInclude Include="VTUtils.hpp" />
|
||||
<ClInclude Include="VxMath\VxMemoryMappedFile.hpp" />
|
||||
<ClInclude Include="VxMath\VxTypes.hpp" />
|
||||
<ClInclude Include="XContainer\XBitArray.hpp" />
|
||||
<ClInclude Include="XContainer\XTypes.hpp" />
|
||||
</ItemGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
|
||||
|
|
|
@ -87,6 +87,9 @@
|
|||
<ClCompile Include="CK2\ObjImpls\CKGroup.cpp">
|
||||
<Filter>Sources\CK2\ObjImpls</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="XContainer\XBitArray.cpp">
|
||||
<Filter>Sources\XContainer</Filter>
|
||||
</ClCompile>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClInclude Include="VTUtils.hpp">
|
||||
|
@ -146,5 +149,8 @@
|
|||
<ClInclude Include="CK2\ObjImpls\CKGroup.hpp">
|
||||
<Filter>Headers\CK2\ObjImpls</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="XContainer\XBitArray.hpp">
|
||||
<Filter>Headers\XContainer</Filter>
|
||||
</ClInclude>
|
||||
</ItemGroup>
|
||||
</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) {
|
||||
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);
|
||||
}
|
||||
void PrintCKBaseManager(const LibCmo::CK2::MgrImpls::CKBaseManager* mgr) {
|
||||
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);
|
||||
}
|
||||
void PrintCKStateChunk(const LibCmo::CK2::CKStateChunk* chunk) {
|
||||
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
|
||||
LibCmo::CK2::CKStateChunk* operchunk = const_cast<LibCmo::CK2::CKStateChunk*>(chunk);
|
||||
|
|
|
@ -127,6 +127,7 @@ namespace Unvirt::Context {
|
|||
m_Help = root->RootHelp();
|
||||
|
||||
// create context
|
||||
LibCmo::CK2::CKStartUp();
|
||||
m_Ctx = new LibCmo::CK2::CKContext();
|
||||
m_Ctx->SetOutputCallback(std::bind(&UnvirtContext::PrintContextMsg, this, std::placeholders::_1));
|
||||
}
|
||||
|
@ -134,6 +135,11 @@ namespace Unvirt::Context {
|
|||
UnvirtContext::~UnvirtContext() {
|
||||
if (m_Help != nullptr)
|
||||
delete m_Help;
|
||||
|
||||
// free context
|
||||
ClearDocument();
|
||||
delete m_Ctx;
|
||||
LibCmo::CK2::CKShutdown();
|
||||
}
|
||||
|
||||
bool UnvirtContext::HasOpenedFile() {
|
||||
|
|
Loading…
Reference in New Issue
Block a user