libcmo21/LibCmo/CK2/CKGlobals.cpp

279 lines
10 KiB
C++
Raw Normal View History

2023-08-23 16:04:58 +08:00
#include "../VTUtils.hpp"
2023-02-25 17:39:39 +08:00
#if defined(LIBCMO_OS_WIN32)
#define ZLIB_WINAPI
#endif
#include <zconf.h>
2023-08-23 16:04:58 +08:00
#include "../VTEncoding.hpp"
2023-02-25 17:39:39 +08:00
#include "CKGlobals.hpp"
2023-08-23 16:04:58 +08:00
#include <map>
#include <algorithm>
2023-02-25 17:39:39 +08:00
#include <zlib.h>
#include "ObjImpls/CKObject.hpp"
2023-09-01 12:19:06 +08:00
#include "ObjImpls/CKSceneObject.hpp"
#include "ObjImpls/CKBeObject.hpp"
#include "ObjImpls/CKGroup.hpp"
2023-09-01 14:55:31 +08:00
#include "ObjImpls/CKRenderObject.hpp"
#include "ObjImpls/CK3dEntity.hpp"
#include "ObjImpls/CK3dObject.hpp"
2023-08-25 21:57:22 +08:00
2023-02-26 21:48:03 +08:00
namespace LibCmo::CK2 {
2023-08-23 16:04:58 +08:00
#pragma region Compression utilities
2023-08-28 21:21:40 +08:00
void* CKPackData(const void* Data, CKDWORD size, CKDWORD& NewSize, CKINT compressionlevel) {
2023-08-22 15:30:26 +08:00
uLong boundary = compressBound(static_cast<uLong>(size));
char* DestBuffer = new char[boundary];
uLongf _destLen = static_cast<uLongf>(boundary);
if (compress2(
reinterpret_cast<Bytef*>(DestBuffer), &_destLen,
reinterpret_cast<const Bytef*>(Data), static_cast<uLong>(size),
static_cast<int>(compressionlevel)) != Z_OK) {
NewSize = 0;
delete[] DestBuffer;
return nullptr;
}
2023-08-28 21:21:40 +08:00
NewSize = static_cast<CKDWORD>(_destLen);
2023-08-22 15:30:26 +08:00
return DestBuffer;
}
2023-02-25 17:39:39 +08:00
2023-08-28 21:21:40 +08:00
void* CKUnPackData(CKDWORD DestSize, const void* SrcBuffer, CKDWORD SrcSize) {
2023-08-22 15:30:26 +08:00
char* DestBuffer = new char[DestSize];
2023-02-25 17:39:39 +08:00
uLongf cache = DestSize;
if (uncompress(
reinterpret_cast<Bytef*>(DestBuffer), &cache,
2023-08-28 21:21:40 +08:00
reinterpret_cast<const Bytef*>(SrcBuffer), static_cast<uLong>(SrcSize)) != Z_OK) {
2023-02-25 17:39:39 +08:00
delete[] DestBuffer;
return nullptr;
}
return DestBuffer;
}
CKDWORD CKComputeDataCRC(const void* data, CKDWORD size, CKDWORD PreviousCRC) {
2023-02-25 17:39:39 +08:00
return static_cast<CKDWORD>(adler32(
static_cast<uLong>(PreviousCRC),
reinterpret_cast<const Bytef*>(data),
static_cast<uInt>(size)
));
}
2023-08-23 16:04:58 +08:00
#pragma endregion
#pragma region CKClass Registration
static XContainer::XArray<CKClassDesc> g_CKClassInfo;
2023-09-01 12:19:06 +08:00
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);
}
}
2023-08-23 16:04:58 +08:00
static void ComputeParentsTable(CKClassDesc& desc) {
// if it has done, do not process it again.
if (desc.Done) return;
// find direct parent
2023-09-01 12:19:06 +08:00
CKClassDesc& parent = g_CKClassInfo[static_cast<size_t>(desc.Parent)];
if (!parent.IsValid) LIBPANIC("No such CK_CLASSID.");
2023-08-23 16:04:58 +08:00
// if it is not self inheritance, call recursively
if (desc.Self != desc.Parent) {
ComputeParentsTable(parent);
}
// copy parent's parents
desc.Parents = parent.Parents;
// and set self as its parent
2023-09-01 12:19:06 +08:00
desc.Parents[static_cast<size_t>(desc.Self)] = true;
2023-08-23 16:04:58 +08:00
// set derivation level
desc.DerivationLevel = parent.DerivationLevel + 1;
// set done
desc.Done = true;
2023-08-23 16:04:58 +08:00
}
static void CKBuildClassHierarchyTable() {
// set Done to false and resize all XBitArray
size_t classCount = g_CKClassInfo.size();
for (auto& item : g_CKClassInfo) {
2023-09-01 12:19:06 +08:00
if (!item.IsValid) continue;
item.Done = false;
2023-08-23 16:04:58 +08:00
item.Parents.resize(classCount, false);
item.Children.resize(classCount, false);
}
// compute parents
for (auto& item : g_CKClassInfo) {
2023-09-01 12:19:06 +08:00
if (!item.IsValid) continue;
2023-08-23 16:04:58 +08:00
ComputeParentsTable(item);
}
// compute children by parents table
// iterate CKClassDesc::Parents and register it self to gotten parents
for (auto& item : g_CKClassInfo) {
2023-09-01 12:19:06 +08:00
if (!item.IsValid) continue;
2023-08-23 16:04:58 +08:00
for (size_t idx = 0; idx < classCount; ++idx) {
2023-09-01 12:19:06 +08:00
if (!g_CKClassInfo[idx].IsValid) continue;
2023-08-23 16:04:58 +08:00
// if this idx is its parent,
// add self to parent.
if (item.Parents[idx]) {
2023-09-01 12:19:06 +08:00
g_CKClassInfo[idx].Children[static_cast<size_t>(item.Self)] = true;
2023-08-23 16:04:58 +08:00
}
}
}
}
void CKClassRegister(CK_CLASSID cid, CK_CLASSID parentCid,
CKClassCreationFct createFct, CKClassReleaseFct relFct, CKClassNameFct nameFct) {
2023-09-01 12:19:06 +08:00
// resize class desc array
size_t intcid = static_cast<size_t>(cid);
if (intcid >= g_CKClassInfo.size()) {
g_CKClassInfo.resize(intcid + 1);
}
// emplace desc
2023-08-23 16:04:58 +08:00
CKClassDesc desc;
2023-09-01 12:19:06 +08:00
desc.IsValid = true;
2023-08-23 16:04:58 +08:00
desc.Self = cid;
desc.Parent = parentCid;
desc.CreationFct = createFct;
desc.ReleaseFct = relFct;
desc.NameFct = nameFct;
2023-09-01 12:19:06 +08:00
g_CKClassInfo[intcid] = std::move(desc);
2023-08-23 16:04:58 +08:00
}
#pragma endregion
#pragma region Class Hierarchy Management
2023-09-01 12:19:06 +08:00
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());
2023-08-23 16:04:58 +08:00
}
const CKClassDesc* CKGetClassDesc(CK_CLASSID cid) {
2023-09-01 12:19:06 +08:00
size_t intcid;
if (!GetClassIdIndex(cid, intcid)) return nullptr;
return &g_CKClassInfo[intcid];
2023-08-23 16:04:58 +08:00
}
CKSTRING CKClassIDToString(CK_CLASSID cid) {
2023-09-01 12:19:06 +08:00
const CKClassDesc* desc = CKGetClassDesc(cid);
if (desc == nullptr) return "Undefined Type";
else return desc->NameFct();
2023-08-23 16:04:58 +08:00
}
bool CKIsChildClassOf(CK_CLASSID child, CK_CLASSID parent) {
2023-09-01 12:19:06 +08:00
size_t intchild, intparent;
if (!GetClassIdIndex(child, intchild) || !GetClassIdIndex(parent, intparent)) return false;
return g_CKClassInfo[intchild].Parents[intparent];
2023-08-23 16:04:58 +08:00
}
CK_CLASSID CKGetParentClassID(CK_CLASSID child) {
2023-09-01 12:19:06 +08:00
const CKClassDesc* desc = CKGetClassDesc(child);
if (desc == nullptr) return CK_CLASSID::CKCID_OBJECT;
return desc->Parent;
2023-08-23 16:04:58 +08:00
}
CK_CLASSID CKGetCommonParent(CK_CLASSID cid1, CK_CLASSID cid2) {
// I don't know algorithm, I just copy the decompiled code.
while (true) {
if (CKIsChildClassOf(cid1, cid2)) return cid2;
if (CKIsChildClassOf(cid2, cid1)) break;
cid2 = CKGetParentClassID(cid1);
cid1 = cid2;
}
return cid1;
}
#pragma endregion
#pragma region Initializations functions
CKERROR CKStartUp() {
2023-09-01 12:19:06 +08:00
// reserve class info array.
g_CKClassInfo.reserve(static_cast<size_t>(CK_CLASSID::CKCID_MAXCLASSID));
2023-08-23 16:04:58 +08:00
// todo: add class type registrations
2023-09-01 12:19:06 +08:00
#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");
2023-09-01 14:55:31 +08:00
EasyClassReg(ObjImpls::CKRenderObject, CK_CLASSID::CKCID_RENDEROBJECT, CK_CLASSID::CKCID_BEOBJECT, "Render Object");
EasyClassReg(ObjImpls::CK3dEntity, CK_CLASSID::CKCID_3DENTITY, CK_CLASSID::CKCID_RENDEROBJECT, "3D Entity");
EasyClassReg(ObjImpls::CK3dObject, CK_CLASSID::CKCID_3DOBJECT, CK_CLASSID::CKCID_3DENTITY, "3D Object");
2023-09-01 12:19:06 +08:00
#undef EasyClassReg
2023-08-23 16:04:58 +08:00
/*
// register CKObjects
m_ObjectsCreationMap{
{CK_CLASSID::CKCID_OBJECT, ([](CKContext* ctx, CK_ID id, CKSTRING name) ->CKObjectImplements::CKObject* { return new(std::nothrow) CKObjectImplements::CKObject(ctx, id, name); })},
{CK_CLASSID::CKCID_SCENEOBJECT, ([](CKContext* ctx, CK_ID id, CKSTRING name) ->CKObjectImplements::CKObject* { return new(std::nothrow) CKObjectImplements::CKSceneObject(ctx, id, name); })},
{CK_CLASSID::CKCID_BEOBJECT, ([](CKContext* ctx, CK_ID id, CKSTRING name) ->CKObjectImplements::CKObject* { return new(std::nothrow) CKObjectImplements::CKBeObject(ctx, id, name); })},
{CK_CLASSID::CKCID_GROUP, ([](CKContext* ctx, CK_ID id, CKSTRING name) ->CKObjectImplements::CKObject* { return new(std::nothrow) CKObjectImplements::CKGroup(ctx, id, name); })},
{CK_CLASSID::CKCID_MESH, ([](CKContext* ctx, CK_ID id, CKSTRING name) ->CKObjectImplements::CKObject* { return new(std::nothrow) CKObjectImplements::CKMesh(ctx, id, name); })},
{CK_CLASSID::CKCID_TEXTURE, ([](CKContext* ctx, CK_ID id, CKSTRING name) ->CKObjectImplements::CKObject* { return new(std::nothrow) CKObjectImplements::CKTexture(ctx, id, name); })},
{CK_CLASSID::CKCID_MATERIAL, ([](CKContext* ctx, CK_ID id, CKSTRING name) ->CKObjectImplements::CKObject* { return new(std::nothrow) CKObjectImplements::CKMaterial(ctx, id, name); })},
{CK_CLASSID::CKCID_RENDEROBJECT, ([](CKContext* ctx, CK_ID id, CKSTRING name) ->CKObjectImplements::CKObject* { return new(std::nothrow) CKObjectImplements::CKRenderObject(ctx, id, name); })},
{CK_CLASSID::CKCID_3DENTITY, ([](CKContext* ctx, CK_ID id, CKSTRING name) ->CKObjectImplements::CKObject* { return new(std::nothrow) CKObjectImplements::CK3dEntity(ctx, id, name); })},
{CK_CLASSID::CKCID_PARAMETERIN, ([](CKContext* ctx, CK_ID id, CKSTRING name) ->CKObjectImplements::CKObject* { return new(std::nothrow) CKObjectImplements::CKParameterIn(ctx, id, name); })},
{CK_CLASSID::CKCID_PARAMETER, ([](CKContext* ctx, CK_ID id, CKSTRING name) ->CKObjectImplements::CKObject* { return new(std::nothrow) CKObjectImplements::CKParameter(ctx, id, name); })},
{CK_CLASSID::CKCID_PARAMETEROUT, ([](CKContext* ctx, CK_ID id, CKSTRING name) ->CKObjectImplements::CKObject* { return new(std::nothrow) CKObjectImplements::CKParameterOut(ctx, id, name); })},
{CK_CLASSID::CKCID_PARAMETERLOCAL, ([](CKContext* ctx, CK_ID id, CKSTRING name) ->CKObjectImplements::CKObject* { return new(std::nothrow) CKObjectImplements::CKParameterLocal(ctx, id, name); })},
{CK_CLASSID::CKCID_PARAMETEROPERATION, ([](CKContext* ctx, CK_ID id, CKSTRING name) ->CKObjectImplements::CKObject* { return new(std::nothrow) CKObjectImplements::CKParameterOperation(ctx, id, name); })},
{CK_CLASSID::CKCID_BEHAVIORLINK, ([](CKContext* ctx, CK_ID id, CKSTRING name) ->CKObjectImplements::CKObject* { return new(std::nothrow) CKObjectImplements::CKBehaviorLink(ctx, id, name); })},
{CK_CLASSID::CKCID_BEHAVIORIO, ([](CKContext* ctx, CK_ID id, CKSTRING name) ->CKObjectImplements::CKObject* { return new(std::nothrow) CKObjectImplements::CKBehaviorLink(ctx, id, name); })},
{CK_CLASSID::CKCID_BEHAVIOR, ([](CKContext* ctx, CK_ID id, CKSTRING name) ->CKObjectImplements::CKObject* { return new(std::nothrow) CKObjectImplements::CKBehavior(ctx, id, name); })}
},
// register CKBaseManagers
m_ManagersCreationMap{
{ATTRIBUTE_MANAGER_GUID, ([](CKContext* ctx, CK_ID id) ->CKManagerImplements::CKBaseManager* { return new(std::nothrow) CKManagerImplements::CKAttributeManager(ctx, id); })},
}
*/
2023-08-25 21:57:22 +08:00
CKBuildClassHierarchyTable();
2023-08-23 16:04:58 +08:00
return CKERROR::CKERR_OK;
}
CKERROR CKShutdown() {
// free class indo
g_CKClassInfo.clear();
return CKERROR::CKERR_OK;
}
#pragma endregion
2023-02-25 17:39:39 +08:00
}