finish ckgroup again

This commit is contained in:
yyc12345 2023-09-01 13:27:46 +08:00
parent fd69914a25
commit eea15c2028
8 changed files with 117 additions and 63 deletions

View File

@ -36,7 +36,7 @@ namespace LibCmo::CK2 {
#pragma region Objects Management #pragma region Objects Management
ObjImpls::CKObject* CKContext::CreateCKObject(CK_CLASSID cls, CKSTRING name, ObjImpls::CKObject* CKContext::CreateObject(CK_CLASSID cls, CKSTRING name,
CK_OBJECTCREATION_OPTIONS options, CK_CREATIONMODE* res) { CK_OBJECTCREATION_OPTIONS options, CK_CREATIONMODE* res) {
// todo: Process paramter options and res // todo: Process paramter options and res
@ -66,13 +66,13 @@ namespace LibCmo::CK2 {
return obj; return obj;
} }
ObjImpls::CKObject* CKContext::GetCKObject(CK_ID id) { ObjImpls::CKObject* CKContext::GetObject(CK_ID id) {
if (id >= m_ObjectsList.size()) return nullptr; if (id >= m_ObjectsList.size()) return nullptr;
return m_ObjectsList[id]; return m_ObjectsList[id];
} }
/** /**
* @brief The real CKObject destroy worker shared by CKContext::DestroyCKObject and CKContext::~CKContext * @brief The real CKObject destroy worker shared by CKContext::DestroyObject and CKContext::~CKContext
* @param[in] ctx The CKContext * @param[in] ctx The CKContext
* @param[in] obj The CKObject need to be free. * @param[in] obj The CKObject need to be free.
*/ */
@ -88,7 +88,7 @@ namespace LibCmo::CK2 {
// free it and return its value // free it and return its value
desc->ReleaseFct(ctx, obj); desc->ReleaseFct(ctx, obj);
} }
void CKContext::DestroyCKObject(CK_ID id) { void CKContext::DestroyObject(CK_ID id) {
if (id >= m_ObjectsList.size()) return; if (id >= m_ObjectsList.size()) return;
// get object and free it // get object and free it

View File

@ -37,11 +37,11 @@ namespace LibCmo::CK2 {
* @remark CKObjects must be destroy with the DestroyObject method. * @remark CKObjects must be destroy with the DestroyObject method.
* @see CKObject, DestroyObject * @see CKObject, DestroyObject
*/ */
ObjImpls::CKObject* CreateCKObject(CK_CLASSID cls, CKSTRING name, ObjImpls::CKObject* CreateObject(CK_CLASSID cls, CKSTRING name,
CK_OBJECTCREATION_OPTIONS options = CK_OBJECTCREATION_OPTIONS::CK_OBJECTCREATION_NONAMECHECK, CK_OBJECTCREATION_OPTIONS options = CK_OBJECTCREATION_OPTIONS::CK_OBJECTCREATION_NONAMECHECK,
CK_CREATIONMODE* res = nullptr); CK_CREATIONMODE* res = nullptr);
ObjImpls::CKObject* GetCKObject(CK_ID id); ObjImpls::CKObject* GetObject(CK_ID id);
void DestroyCKObject(CK_ID id); void DestroyObject(CK_ID id);
CKDWORD AllocateGroupGlobalIndex(); CKDWORD AllocateGroupGlobalIndex();
CKDWORD AllocateSceneGlobalIndex(); CKDWORD AllocateSceneGlobalIndex();

View File

@ -348,7 +348,7 @@ namespace LibCmo::CK2 {
if (obj.Data == nullptr) continue; if (obj.Data == nullptr) continue;
// create object and assign created obj ckid // create object and assign created obj ckid
obj.ObjPtr = m_Ctx->CreateCKObject(obj.ObjectCid, obj.Name.c_str()); obj.ObjPtr = m_Ctx->CreateObject(obj.ObjectCid, obj.Name.c_str());
if (obj.ObjPtr == nullptr) { if (obj.ObjPtr == nullptr) {
obj.CreatedObjectId = 0u; obj.CreatedObjectId = 0u;
} else { } else {
@ -378,7 +378,7 @@ namespace LibCmo::CK2 {
obj.Data = nullptr; obj.Data = nullptr;
} else { } else {
// if failed, delete it // if failed, delete it
m_Ctx->DestroyCKObject(obj.ObjectId); m_Ctx->DestroyObject(obj.ObjectId);
obj.ObjPtr = nullptr; obj.ObjPtr = nullptr;
obj.CreatedObjectId = 0u; obj.CreatedObjectId = 0u;
} }

View File

@ -111,23 +111,21 @@ namespace LibCmo::CK2 {
#pragma region Misc Funcs #pragma region Misc Funcs
const ChunkProfile CKStateChunk::GetStateChunkProfile() { const ChunkProfile CKStateChunk::GetStateChunkProfile() {
ChunkProfile profile; return ChunkProfile {
.m_ClassId = this->m_ClassId,
.m_DataDwSize = this->m_DataDwSize,
.m_pData = this->m_pData,
profile.m_ClassId = this->m_ClassId; .m_DataVersion = this->m_DataVersion,
profile.m_DataDwSize = this->m_DataDwSize; .m_ChunkVersion = this->m_ChunkVersion,
profile.m_pData = this->m_pData;
profile.m_DataVersion = this->m_DataVersion; .m_ObjectListSize = this->m_ObjectList.size(),
profile.m_ChunkVersion = this->m_ChunkVersion; .m_ChunkListSize = this->m_ChunkList.size(),
.m_ManagerListSize = this->m_ManagerList.size(),
profile.m_ObjectListSize = this->m_ObjectList.size(); .m_BindFile = this->m_BindFile,
profile.m_ChunkListSize = this->m_ChunkList.size(); .m_BindContext = this->m_BindContext,
profile.m_ManagerListSize = this->m_ManagerList.size(); };
profile.m_BindFile = this->m_BindFile;
profile.m_BindContext = this->m_BindContext;
return profile;
} }
void CKStateChunk::Clear(void) { void CKStateChunk::Clear(void) {
@ -773,7 +771,7 @@ namespace LibCmo::CK2 {
/* ========== Sequence Functions ==========*/ /* ========== Sequence Functions ==========*/
bool CKStateChunk::ReadObjectIDSequence(std::vector<CK_ID>* ls) { bool CKStateChunk::ReadObjectIDSequence(XContainer::XArray<CK_ID>* ls) {
if (ls == nullptr) return false; if (ls == nullptr) return false;
ls->clear(); ls->clear();
@ -793,7 +791,7 @@ namespace LibCmo::CK2 {
return true; return true;
} }
bool CKStateChunk::ReadManagerIntSequence(CKGUID* guid, std::vector<CKINT>* ls) { bool CKStateChunk::ReadManagerIntSequence(CKGUID* guid, XContainer::XArray<CKINT>* ls) {
if (guid == nullptr || ls == nullptr) return false; if (guid == nullptr || ls == nullptr) return false;
// read count // read count
@ -815,7 +813,7 @@ namespace LibCmo::CK2 {
return true; return true;
} }
bool CKStateChunk::ReadSubChunkSequence(std::vector<CKStateChunk*>* ls) { bool CKStateChunk::ReadSubChunkSequence(XContainer::XArray<CKStateChunk*>* ls) {
if (ls == nullptr) return false; if (ls == nullptr) return false;
// clear first // clear first
@ -848,17 +846,18 @@ namespace LibCmo::CK2 {
return true; return true;
} }
bool CKStateChunk::ReadObjectArray(std::vector<CK_ID>* ls) { bool CKStateChunk::ReadXObjectArray(XContainer::XObjectArray* ls) {
if (ls == nullptr) return false; if (ls == nullptr) return false;
ls->clear(); ls->clear();
// read count // read count
CKDWORD count; CKDWORD count;
if (!this->ReadStruct(count)) return false; if (!this->ReadStruct(count)) return false;
if (!count) return true; // 0 size array if (count == 0) return true; // 0 size array
// old file size correction // old file size correction
if (this->m_ChunkVersion < CK_STATECHUNK_CHUNKVERSION::CHUNK_VERSION1) { bool old_file = this->m_ChunkVersion < CK_STATECHUNK_CHUNKVERSION::CHUNK_VERSION1;
if (old_file) {
// skip 4. but I don't know why!!! // skip 4. but I don't know why!!!
this->Skip(4); this->Skip(4);
if (!this->ReadStruct(count)) return false; if (!this->ReadStruct(count)) return false;
@ -874,21 +873,36 @@ namespace LibCmo::CK2 {
return false; return false;
} }
// remap id // in old file or no bind file, the read data directly is CK_ID.
if (this->m_BindFile != nullptr) { // in new file or has bind file, the read data is the index in FileObjects
if (cache < 0) { if (old_file || this->m_BindFile == nullptr) {
id = 0u;
} else {
id = this->m_BindFile->GetFileObjectByIndex(cache)->CreatedObjectId;
}
} else {
id = static_cast<CK_ID>(cache); id = static_cast<CK_ID>(cache);
} else {
if (cache < 0) id = 0;
else id = this->m_BindFile->GetFileObjectByIndex(cache)->CreatedObjectId;
} }
} }
return true; return true;
} }
bool CKStateChunk::ReadXObjectPointerArray(XContainer::XObjectPointerArray* ls) {
if (ls == nullptr) return false;
// very very similar to ReadXObjectArray
// we execute it first.
XContainer::XObjectArray idarr;
if (!ReadXObjectArray(idarr)) return false;
// then convert it to pointer list
ls->resize(idarr.size());
for (size_t i = 0; i < idarr.size(); ++i) {
(*ls)[i] = m_BindContext->GetObject(idarr[i]);
}
return true;
}
#pragma endregion #pragma endregion

View File

@ -119,14 +119,14 @@ namespace LibCmo::CK2 {
/* ========== Basic Data Read Functions ==========*/ /* ========== Basic Data Read Functions ==========*/
private: private:
/// <summary> /**
/// The base read function for all data. * @brief The base read function for all data.
/// <para>This function will check all read requirements.</para> * This function will check all read requirements.
/// <para>If you have use this function or functions calling this function. You do not need check any reading requirements anymore</para> * If you have use this function or functions calling this function. You do not need check any reading requirements anymore.
/// </summary> * @param data_ptr[out] the pointer to data. must be allocated first.
/// <param name="data_ptr">the pointer to data. must be allocated first.</param> * @param size_in_byte[in] the size of data in byte.
/// <param name="size_in_byte">the size of data in byte.</param> * @return True if success.
/// <returns></returns> */
bool ReadByteData(void* data_ptr, CKDWORD size_in_byte); bool ReadByteData(void* data_ptr, CKDWORD size_in_byte);
public: public:
/// <summary> /// <summary>
@ -228,8 +228,8 @@ namespace LibCmo::CK2 {
/// </summary> /// </summary>
/// <param name="ls"></param> /// <param name="ls"></param>
/// <returns></returns> /// <returns></returns>
bool ReadObjectIDSequence(std::vector<CK_ID>* ls); bool ReadObjectIDSequence(XContainer::XArray<CK_ID>* ls);
inline bool ReadObjectIDSequence(std::vector<CK_ID>& ls) { inline bool ReadObjectIDSequence(XContainer::XArray<CK_ID>& ls) {
return ReadObjectIDSequence(&ls); return ReadObjectIDSequence(&ls);
} }
@ -240,8 +240,8 @@ namespace LibCmo::CK2 {
/// <param name="guid"></param> /// <param name="guid"></param>
/// <param name="ls"></param> /// <param name="ls"></param>
/// <returns></returns> /// <returns></returns>
bool ReadManagerIntSequence(CKGUID* guid, std::vector<CKINT>* ls); bool ReadManagerIntSequence(CKGUID* guid, XContainer::XArray<CKINT>* ls);
inline bool ReadManagerIntSequence(CKGUID& guid, std::vector<CKINT>& ls) { inline bool ReadManagerIntSequence(CKGUID& guid, XContainer::XArray<CKINT>& ls) {
return ReadManagerIntSequence(&guid, &ls); return ReadManagerIntSequence(&guid, &ls);
} }
@ -252,20 +252,31 @@ namespace LibCmo::CK2 {
/// </summary> /// </summary>
/// <param name="ls"></param> /// <param name="ls"></param>
/// <returns></returns> /// <returns></returns>
bool ReadSubChunkSequence(std::vector<CKStateChunk*>* ls); bool ReadSubChunkSequence(XContainer::XArray<CKStateChunk*>* ls);
inline bool ReadSubChunkSequence(std::vector<CKStateChunk*>& ls) { inline bool ReadSubChunkSequence(XContainer::XArray<CKStateChunk*>& ls) {
return ReadSubChunkSequence(&ls); return ReadSubChunkSequence(&ls);
} }
/// <summary> /**
/// Read Object Array (actually still is CK_ID) * @brief Read Object Array (actually still is CK_ID)
/// <para>ReadXObjectArray() and ReadObjectArray() redirect to this.</para> * @remark ReadObjectArray() and XObjectArray::Load redirect to this.
/// </summary> * @param ls The list
/// <param name="ls"></param> * @return True if success.
/// <returns></returns> */
bool ReadObjectArray(std::vector<CK_ID>* ls); bool ReadXObjectArray(XContainer::XObjectArray* ls);
inline bool ReadObjectArray(std::vector<CK_ID>& ls) { inline bool ReadXObjectArray(XContainer::XObjectArray& ls) {
return ReadObjectArray(&ls); return ReadXObjectArray(&ls);
}
/**
* @brief Read Object Array (actually is CKObject*)
* @remark ReadXObjectArray() and XObjectPointerArray::Load redirect to this.
* @param ls The list
* @return True if success
*/
bool ReadXObjectPointerArray(XContainer::XObjectPointerArray* ls);
inline bool ReadXObjectPointerArray(XContainer::XObjectPointerArray& ls) {
return ReadXObjectPointerArray(&ls);
} }
//int ReadInt(); //int ReadInt();

View File

@ -1,6 +1,7 @@
#include "CKSceneObject.hpp" #include "CKSceneObject.hpp"
#include "../CKStateChunk.hpp" #include "../CKStateChunk.hpp"
#include "CKBeObject.hpp" #include "CKBeObject.hpp"
#include "CKGroup.hpp"
namespace LibCmo::CK2::ObjImpls { namespace LibCmo::CK2::ObjImpls {
@ -19,7 +20,10 @@ namespace LibCmo::CK2::ObjImpls {
} }
bool CKBeObject::IsInGroup(CKGroup* group) { bool CKBeObject::IsInGroup(CKGroup* group) {
return false; if (group == nullptr) return false;
CKDWORD idx = group->CKBeObject_GetGroupIndex();
if (idx >= m_Groups.size()) return false;
return m_Groups[idx];
} }
void CKBeObject::CKGroup_SetGroups(CKDWORD pos, bool val) { void CKBeObject::CKGroup_SetGroups(CKDWORD pos, bool val) {

View File

@ -25,10 +25,35 @@ namespace LibCmo::CK2::ObjImpls {
bool suc = CKBeObject::Load(chunk, file); bool suc = CKBeObject::Load(chunk, file);
if (!suc) return false; if (!suc) return false;
// cleat self
this->Clear();
// get grouped objects
if (chunk->SeekIdentifier(CK_STATESAVEFLAGS_GROUP::CK_STATESAVE_GROUPALL)) {
XContainer::XObjectPointerArray ptrs;
chunk->ReadXObjectPointerArray(ptrs);
// filter pointer and check them type
for (auto& ptr : ptrs) {
// skip bad one
if (ptr == nullptr || ptr == this
|| !CKIsChildClassOf(ptr->GetClassID(), CK_CLASSID::CKCID_BEOBJECT)) {
continue;
}
CKBeObject* beobj = static_cast<CKBeObject*>(ptr);
if (beobj->IsInGroup(this)) continue;
// add good one
beobj->CKGroup_SetGroups(m_GroupIndex, true);
m_ObjectArray.emplace_back(beobj);
}
}
return true; return true;
} }
CKDWORD CKGroup::GetGroupIndex() { CKDWORD CKGroup::CKBeObject_GetGroupIndex() {
return m_GroupIndex; return m_GroupIndex;
} }

View File

@ -19,7 +19,7 @@ namespace LibCmo::CK2::ObjImpls {
virtual bool Load(CKStateChunk* chunk, CKFileVisitor* file) override; virtual bool Load(CKStateChunk* chunk, CKFileVisitor* file) override;
//virtual void PostLoad() override; //virtual void PostLoad() override;
CKDWORD GetGroupIndex(); CKDWORD CKBeObject_GetGroupIndex();
// ===== Insert ===== // ===== Insert =====
CKERROR AddObject(CKBeObject *o); CKERROR AddObject(CKBeObject *o);