create visitor for all existed CK class

This commit is contained in:
yyc12345 2023-09-22 14:48:45 +08:00
parent 08722adeb2
commit ddf596faec
13 changed files with 582 additions and 148 deletions

View File

@ -255,7 +255,7 @@ namespace LibCmo::CK2 {
#pragma endregion #pragma endregion
#pragma region Misc Functions #pragma region Slot Functions
void CKBitmapData::SetSlotCount(CKDWORD count) { void CKBitmapData::SetSlotCount(CKDWORD count) {
m_Slots.resize(count); m_Slots.resize(count);
@ -265,7 +265,7 @@ namespace LibCmo::CK2 {
} }
} }
CKDWORD CKBitmapData::GetSlotCount() { CKDWORD CKBitmapData::GetSlotCount() const {
return static_cast<CKDWORD>(m_Slots.size()); return static_cast<CKDWORD>(m_Slots.size());
} }
@ -280,16 +280,17 @@ namespace LibCmo::CK2 {
} }
} }
CKDWORD CKBitmapData::GetCurrentSlot() { CKDWORD CKBitmapData::GetCurrentSlot() const {
return m_CurrentSlot; return m_CurrentSlot;
} }
void CKBitmapData::CreateImage(CKDWORD Width, CKDWORD Height, CKDWORD Slot) { bool CKBitmapData::CreateImage(CKDWORD Width, CKDWORD Height, CKDWORD Slot) {
if (Slot >= m_Slots.size()) return; if (Slot >= m_Slots.size()) return false;
CKBitmapSlot& slotdata = m_Slots[Slot]; CKBitmapSlot& slotdata = m_Slots[Slot];
slotdata.m_ImageData.CreateImage(Width, Height); slotdata.m_ImageData.CreateImage(Width, Height);
VxMath::VxDoAlphaBlit(&slotdata.m_ImageData, 0xFFu); VxMath::VxDoAlphaBlit(&slotdata.m_ImageData, 0xFFu);
return true;
} }
bool CKBitmapData::LoadImage(CKSTRING filename, CKDWORD slot) { bool CKBitmapData::LoadImage(CKSTRING filename, CKDWORD slot) {
@ -351,18 +352,36 @@ namespace LibCmo::CK2 {
m_Slots[slot].m_ImageData.FreeImage(); m_Slots[slot].m_ImageData.FreeImage();
} }
void CKBitmapData::SetSlotFileName(CKDWORD slot, CKSTRING filename) { bool CKBitmapData::SetSlotFileName(CKDWORD slot, CKSTRING filename) {
if (slot >= m_Slots.size()) return; if (slot >= m_Slots.size()) return false;
if (filename == nullptr) return; if (filename == nullptr) return false;
m_Slots[slot].m_FileName = filename; m_Slots[slot].m_FileName = filename;
return true;
} }
CKSTRING CKBitmapData::GetSlotFileName(CKDWORD slot) { CKSTRING CKBitmapData::GetSlotFileName(CKDWORD slot) const {
if (slot >= m_Slots.size()) return nullptr; if (slot >= m_Slots.size()) return nullptr;
return m_Slots[slot].m_FileName.c_str(); return m_Slots[slot].m_FileName.c_str();
} }
const CKBitmapProperties& CKBitmapData::GetSaveFormat() { #pragma endregion
#pragma region Not important variable visitor
void CKBitmapData::SetCubeMap(bool is_cube) {
if (is_cube) {
SetSlotCount(6);
EnumsHelper::Add(m_BitmapFlags, CK_BITMAPDATA_FLAGS::CKBITMAPDATA_CUBEMAP);
} else {
EnumsHelper::Rm(m_BitmapFlags, CK_BITMAPDATA_FLAGS::CKBITMAPDATA_CUBEMAP);
}
}
bool CKBitmapData::IsCubeMap() const {
return EnumsHelper::Has(m_BitmapFlags, CK_BITMAPDATA_FLAGS::CKBITMAPDATA_CUBEMAP);
}
const CKBitmapProperties& CKBitmapData::GetSaveFormat() const {
return m_SaveProperties; return m_SaveProperties;
} }
@ -370,7 +389,7 @@ namespace LibCmo::CK2 {
m_SaveProperties = props; m_SaveProperties = props;
} }
CK_TEXTURE_SAVEOPTIONS CKBitmapData::GetSaveOptions() { CK_TEXTURE_SAVEOPTIONS CKBitmapData::GetSaveOptions() const {
return m_SaveOptions; return m_SaveOptions;
} }
@ -386,7 +405,7 @@ namespace LibCmo::CK2 {
} }
} }
bool CKBitmapData::IsTransparent() { bool CKBitmapData::IsTransparent() const {
return EnumsHelper::Has(m_BitmapFlags, CK_BITMAPDATA_FLAGS::CKBITMAPDATA_TRANSPARENT); return EnumsHelper::Has(m_BitmapFlags, CK_BITMAPDATA_FLAGS::CKBITMAPDATA_TRANSPARENT);
} }
@ -395,7 +414,7 @@ namespace LibCmo::CK2 {
m_TransColor = col; m_TransColor = col;
} }
CKDWORD CKBitmapData::GetTransparentColor() { CKDWORD CKBitmapData::GetTransparentColor() const {
return m_TransColor; return m_TransColor;
} }
@ -403,7 +422,7 @@ namespace LibCmo::CK2 {
m_PickThreshold = threshold; m_PickThreshold = threshold;
} }
CKDWORD CKBitmapData::GetPickThreshold() { CKDWORD CKBitmapData::GetPickThreshold() const {
return m_PickThreshold; return m_PickThreshold;
} }

View File

@ -38,6 +38,8 @@ namespace LibCmo::CK2 {
~CKBitmapData(); ~CKBitmapData();
LIBCMO_DISABLE_COPY_MOVE(CKBitmapData); LIBCMO_DISABLE_COPY_MOVE(CKBitmapData);
#pragma region RW Funcs
static bool ReadSpecificFormatBitmap(CKStateChunk* chk, VxMath::VxImageDescEx* slot); static bool ReadSpecificFormatBitmap(CKStateChunk* chk, VxMath::VxImageDescEx* slot);
static bool ReadRawBitmap(CKStateChunk* chk, VxMath::VxImageDescEx* slot); static bool ReadRawBitmap(CKStateChunk* chk, VxMath::VxImageDescEx* slot);
static bool ReadOldRawBitmap(CKStateChunk* chk, VxMath::VxImageDescEx* slot); static bool ReadOldRawBitmap(CKStateChunk* chk, VxMath::VxImageDescEx* slot);
@ -47,78 +49,114 @@ namespace LibCmo::CK2 {
bool ReadFromChunk(CKStateChunk* chunk, CKFileVisitor* file, const CKBitmapDataReadIdentifiers& identifiers); bool ReadFromChunk(CKStateChunk* chunk, CKFileVisitor* file, const CKBitmapDataReadIdentifiers& identifiers);
bool DumpToChunk(CKStateChunk* chunk, CKFileVisitor* file, const CKBitmapDataWriteIdentifiers& identifiers); bool DumpToChunk(CKStateChunk* chunk, CKFileVisitor* file, const CKBitmapDataWriteIdentifiers& identifiers);
#pragma endregion
#pragma region Slot funcs
void SetSlotCount(CKDWORD count); void SetSlotCount(CKDWORD count);
CKDWORD GetSlotCount(); CKDWORD GetSlotCount() const;
void SetCurrentSlot(CKDWORD slot); void SetCurrentSlot(CKDWORD slot);
CKDWORD GetCurrentSlot(); CKDWORD GetCurrentSlot() const;
void CreateImage(CKDWORD Width, CKDWORD Height, CKDWORD Slot);
bool LoadImage(CKSTRING filename, CKDWORD slot);
bool SaveImage(CKSTRING filename, CKDWORD slot, bool isForceThisFmt = false);
VxMath::VxImageDescEx* GetImageDesc(CKDWORD slot);
void ReleaseImage(CKDWORD slot);
void SetSlotFileName(CKDWORD slot, CKSTRING filename);
CKSTRING GetSlotFileName(CKDWORD slot);
const CKBitmapProperties& GetSaveFormat();
void SetSaveFormat(const CKBitmapProperties& props);
CK_TEXTURE_SAVEOPTIONS GetSaveOptions();
void SetSaveOptions(CK_TEXTURE_SAVEOPTIONS opts);
/** /**
Summary: Enables or disables the color key transparency. * @brief Create a black image with full alpha in specified slot.
* @param Width[in] Image width
* @param Height[in] Image height
* @param Slot[in] The slot placing image.
* @return True if creating success.
*/
bool CreateImage(CKDWORD Width, CKDWORD Height, CKDWORD Slot);
/**
* @brief Load image into specified slot.
* @param filename[in] The file name of loading image.
* @param slot[in] The slot placing loaded image.
* @return True if load successfully.
*/
bool LoadImage(CKSTRING filename, CKDWORD slot);
/**
* @brief Save image for specified slot.
* @param filename[in] The file name of saving image.
* @param slot[in] The slot will be saved.
* @param isForceThisFmt[in] True to use this class specified format to save image. Otherwise use the format evaluated by the image file name.
* @return True if success.
*/
bool SaveImage(CKSTRING filename, CKDWORD slot, bool isForceThisFmt = false);
/**
* @brief Get specified slot image descriptor.
* @param slot[in] The slot to get.
* @return The descriptor. nullptr if failed.
*/
VxMath::VxImageDescEx* GetImageDesc(CKDWORD slot);
/**
* @brief Release specified slot image.
* @param slot[in] The slot to free.
*/
void ReleaseImage(CKDWORD slot);
Arguments: /**
Transparency: TRUE activates transparency, FALSE disables it. * @brief Set associated file name for specified slot.
Remarks: * @param slot[in] The slot to set.
* @param filename[in] The associated file name.
*/
bool SetSlotFileName(CKDWORD slot, CKSTRING filename);
/**
* @brief Get associated file name for specified slot.
* @param slot[in] The slot to get.
* @return The file name. nullptr if failed.
*/
CKSTRING GetSlotFileName(CKDWORD slot) const;
#pragma endregion
#pragma region Not important funcs
void SetCubeMap(bool is_cube);
bool IsCubeMap() const;
const CKBitmapProperties& GetSaveFormat() const;
void SetSaveFormat(const CKBitmapProperties& props);
CK_TEXTURE_SAVEOPTIONS GetSaveOptions() const;
void SetSaveOptions(CK_TEXTURE_SAVEOPTIONS opts);
/**
@brief Enables or disables the color key transparency.
@param Transparency[in] TRUE activates transparency, FALSE disables it.
@remark
+ 0x00000000 (black) is the default transparent color. + 0x00000000 (black) is the default transparent color.
+ Setting on the transparency and a transparent color automatically + Setting on the transparency and a transparent color automatically
updates the alpha channel so that pixel with the transparent color have updates the alpha channel so that pixel with the transparent color have
a 0 alpha value. a 0 alpha value.
See also: IsTransparent,SetTranparentColor @see IsTransparent, SetTranparentColor
*/ */
void SetTransparent(bool Transparency); void SetTransparent(bool Transparency);
/** /**
Summary: Returns whether color keyed transparency is enabled. @brief Returns whether color keyed transparency is enabled.
@return TRUE if color keying is enabled.
Return Value: @see SetTransparent
TRUE if successful.
Arguments:
Transparency: TRUE activates transparency, FALSE disables it.
Return Value:
TRUE if color keying is enabled.
See also: IsTransparent
*/ */
bool IsTransparent(); bool IsTransparent() const;
/** /**
Summary: Sets the transparent color. @brief Sets the transparent color.
Arguments: @param Color[in] A 32 bit ARGB transparent color.
Color: A 32 bit ARGB transparent color. @remark
Remarks:
+ 0x00000000 (black) is the default transparent color. + 0x00000000 (black) is the default transparent color.
+ Setting on the transparency and a transparent color automatically + Setting on the transparency and a transparent color automatically
updates the alpha channel so that pixel with the transparent color have updates the alpha channel so that pixel with the transparent color have
a 0 alpha value. a 0 alpha value.
@see GetTranparentColor, SetTransparent
See also: GetTranparentColor,SetTransparent
*/ */
void SetTransparentColor(CKDWORD col); void SetTransparentColor(CKDWORD col);
/** /**
Summary: Returns the transparent color. @brief Returns the transparent color.
Return Value: @return A 32 bit ARGB transparent color.
Color: A 32 bit ARGB transparent color. @remark
Remarks:
+ 0x00000000 (black) is the default transparent color. + 0x00000000 (black) is the default transparent color.
@see SetTranparentColor, SetTransparent
See also: SetTranparentColor,SetTransparent
*/ */
CKDWORD GetTransparentColor(); CKDWORD GetTransparentColor() const;
/** /**
Summary: Sets pick threshold value. @brief Sets pick threshold value.
Arguments: @param pt[in] Pick threshold value to be set.
pt: Pick threshold value to be set. @remark
Remarks:
+ The pick threshold is used when picking object with + The pick threshold is used when picking object with
transparent textures. transparent textures.
+ It is the minimum value for alpha component + It is the minimum value for alpha component
@ -126,14 +164,16 @@ namespace LibCmo::CK2 {
and the default value 0 means the picking is always valid. and the default value 0 means the picking is always valid.
+ But if a value >0 is used and the texture use transparency (some pixels of the bitmap will have + But if a value >0 is used and the texture use transparency (some pixels of the bitmap will have
alpha component of 0) an object will not be picked on its transparent part. alpha component of 0) an object will not be picked on its transparent part.
@see CKRenderContext::Pick
See Also: CKRenderContext::Pick
*/ */
void SetPickThreshold(CKDWORD threshold); void SetPickThreshold(CKDWORD threshold);
/** /**
Summary: Gets pick threshold value. @brief Gets pick threshold value.
@return Pick threshold value
*/ */
CKDWORD GetPickThreshold(); CKDWORD GetPickThreshold() const;
#pragma endregion
protected: protected:
CKContext* m_Context; CKContext* m_Context;

View File

@ -8,7 +8,6 @@ namespace LibCmo::CK2 {
class CKStateChunk { class CKStateChunk {
public: public:
//CKStateChunk();
CKStateChunk(CKFileVisitor* visitor, CKContext* ctx); CKStateChunk(CKFileVisitor* visitor, CKContext* ctx);
CKStateChunk(const CKStateChunk&); CKStateChunk(const CKStateChunk&);
CKStateChunk(CKStateChunk&&); CKStateChunk(CKStateChunk&&);
@ -183,9 +182,43 @@ namespace LibCmo::CK2 {
bool Skip(CKDWORD DwordCount); bool Skip(CKDWORD DwordCount);
private: private:
/**
* @brief Convert byte based size to DWORD based size.
*
* Becase CKStateChunk use DWORD based buffer, so all data should be aligned to DWORD boundary.
* This function can convert byte based size to DWORD based size while keeping its size aligned with DWORD boundary.
* For example, caller want to allocate 3 bytes for data storing, this function will first align it to DWORD boundary, 4 bytes.
* Then convert it in DWORD size, 1 DWORD.
*
* @param char_size[in] The size in byte unit.
* @return The size in DWORD unit.
*/
CKDWORD GetCeilDwordSize(size_t char_size); CKDWORD GetCeilDwordSize(size_t char_size);
bool ResizeBuffer(CKDWORD new_dwsize); bool ResizeBuffer(CKDWORD new_dwsize);
/**
* @brief Check whether there are enough buffer to read.
*
* This function will check whether current CKStateChunk is in read mode and
* whether data area is enough to write.
* However, it is different with EnsureReadSpace. If no space to write, this function will
* try calling ResizeBuffer to get a enough buffer. Only when resize failed,
* this function will return false.
*
* @param dwsize[in] Required buffer size in DWORD unit.
* @return True if have enough space to write.
* @see EnsureReadSpace
*/
bool EnsureWriteSpace(CKDWORD dwsize); bool EnsureWriteSpace(CKDWORD dwsize);
/**
* @brief Check whether there are enough buffer to read.
*
* This function will check whether current CKStateChunk is in read mode and
* whether data area is enough to read.
*
* @param dword_required[in] Required buffer size in DWORD unit.
* @return True if have enough space to read.
* @see EnsureWriteSpace
*/
bool EnsureReadSpace(CKDWORD dword_required); bool EnsureReadSpace(CKDWORD dword_required);
#pragma endregion #pragma endregion
@ -237,23 +270,21 @@ namespace LibCmo::CK2 {
/** /**
* @brief A RAII wrapper for LockReadBuffer and UnLockReadBuffer. * @brief A RAII wrapper for LockReadBuffer and UnLockReadBuffer.
* @param size_in_byte[in] The value passed to LockReadBuffer. * @param size_in_byte[in] The value passed to LockReadBuffer.
* @return A read-only buffer with RAII feature (more like std::unique_ptr). * @return LockedReadBuffer_t (actually is a std::unique_ptr with custom deleter)
* @remark * @remark
* + The return value is more like std::unique_ptr but it have more features. * + The return value is just a std::unique_ptr but its deleter have more features.
* + If GeneralBuffer_t::GetPtr return nullptr, it mean this function is failed. * + If return value contained data is nullptr, it mean that this function is failed.
* + If you only use the pointer-getter provided by the return value, the final moving forward byte count is the value passed in this function. * + If you only use the pointer provided by the return value, the final moving forward byte count is the value passed in this function.
* + You also can use GeneralBuffer_t::SetSize to set the final moving forward byte count before the return value free itself. * + You also can use LockedReadBuffer_t.get_deleter().SetConsumedSize() to set the final moving forward byte count before the return value free itself.
* + The value passed to GeneralBuffer_t::SetSize will finally be passed to UnLockReadBuffer. * + The value passed to LockedReadBuffer_t..get_deleter().SetConsumedSize() will finally be passed to UnLockReadBuffer.
* + You can use GeneralBuffer_t::Reset to force free the return value. * + You can use LockedReadBuffer_t.reset() to force free the return value.
* @example * @remark Here is a example.
* ``` * ```
* LockedReadBuffer_t buf = ReadBufferLocker(1919810); * auto buf = chunk->LockReadBufferWrapper(1919810);
* if (buf.GetPtr() == nullptr) { * if (buf) {
* // failed * stuff(buf.get()); // do some operation...
* } else { * buf.get_deleter().SetConsumedSize(114514); // i only consume these bytes.
* stuff(buf); // do some operation... * buf.reset(); // immediately free it.
* buf.SetSize(114514); // i only consume these bytes.
* buf.Reset(); // immediately free it.
* } * }
* ``` * ```
* @see LockReadBuffer, UnLockReadBuffer, LockedReadBuffer_t * @see LockReadBuffer, UnLockReadBuffer, LockedReadBuffer_t
@ -348,14 +379,15 @@ namespace LibCmo::CK2 {
/** /**
* @brief Read buffer and copy it. * @brief Read buffer and copy it.
*
* The copied buffer and the size of buffer will be returned to caller. * The copied buffer and the size of buffer will be returned to caller.
* Caller should free the buffer by calling CKStateChunk::DeleteBuffer(void*). * Caller should free the buffer by calling CKStateChunk::DeleteBuffer(void*).
*
* @param ppData[out] The pointer to pointer holding the new copied data. * @param ppData[out] The pointer to pointer holding the new copied data.
* @param size_in_byte[out] Set to the size of buffer when success. * @param size_in_byte[out] Set to the size of buffer when success.
* @return True if success. * @return True if success.
* @remark * @remark Following original Virtools functions can use this function to implement:
* + Following original Virtools functions can use this function to implement: * + ReadBuffer(void**)
* - ReadBuffer(void**)
*/ */
bool ReadBuffer(void** ppData, CKDWORD* size_in_byte); bool ReadBuffer(void** ppData, CKDWORD* size_in_byte);
/** /**
@ -365,61 +397,52 @@ namespace LibCmo::CK2 {
*/ */
void DeleteBuffer(const void* buf); void DeleteBuffer(const void* buf);
/** /**
* @brief A wrapper for ReadAndCopyBuffer(void**, CKDWORD*) * @brief A RAII wrapper for ReadAndCopyBuffer(void**, CKDWORD*)
* @return * @return Buffer_t (actually is a std::unique_ptr with custom deleter)
* @remark
* + The return value is std::unique_ptr but its deleter have more features.
* + If return value containing value is nullptr, it mean this function is failed.
* + Use Buffer_t.get_deleter().GetBufferSize() to get the size of buffer.
* + You can use Buffer_t.reset() to force free the return value.
* @remark Here is a exmaple about how to use this function
* ```
* Buffer_t buf = chunk->ReadBufferWrapper(114);
* if (buf) {
* stuff(buf.get(), buf.get_deleter().GetBufferSize()); // do some operation...
* buf.reset(); // immediately free it.
* }
* ```
*/ */
Buffer_t ReadBufferWrapper(); Buffer_t ReadBufferWrapper();
/** /**
* @brief Read buffer and fill user struct. * @brief Read buffer and fill user struct.
*
* The size of buffer will be read from CKStateChunk internally and return to caller. * The size of buffer will be read from CKStateChunk internally and return to caller.
*
* @param pData[out] The pointer holding the data. * @param pData[out] The pointer holding the data.
* @return True if success. * @return True if success.
* @remark * @remark Following original Virtools functions can use this function to implement:
* + Following original Virtools functions can use this function to implement: * + ReadAndFillBuffer(void*)
* - ReadAndFillBuffer(void*) * + ReadAndFillBuffer_LEndian(void*)
* - ReadAndFillBuffer_LEndian(void*) * + ReadAndFillBuffer_LEndian16(void*)
* - ReadAndFillBuffer_LEndian16(void*)
*/ */
bool ReadAndFillBuffer(void* pData); bool ReadAndFillBuffer(void* pData);
/** /**
* @brief Read buffer and fill user struct. * @brief Read buffer and fill user struct.
*
* The size of buffer is provided by user. * The size of buffer is provided by user.
*
* @param pData[out] The pointer holding the data. * @param pData[out] The pointer holding the data.
* @param size_in_byte[in] The size of data which you want to read in byte unit * @param size_in_byte[in] The size of data which you want to read in byte unit
* @return True if success. * @return True if success.
* @remark * @remark Following original Virtools functions can use this function to implement:
* + Following original Virtools functions can use this function to implement: * + ReadAndFillBuffer(int, void*)
* - ReadAndFillBuffer(int, void*) * + ReadAndFillBuffer_LEndian(int, void*)
* - ReadAndFillBuffer_LEndian(int, void*) * + ReadAndFillBuffer_LEndian16(int, void*)
* - ReadAndFillBuffer_LEndian16(int, void*)
*/ */
bool ReadAndFillBuffer(void* pData, CKDWORD size_in_byte); bool ReadAndFillBuffer(void* pData, CKDWORD size_in_byte);
///**
// * @brief A RAII wrapper for ReadBuffer and DeleteBuffer
// * @param uptr The pointer to unique_ptr receiving data.
// * @param len_in_byte The size of gotten buffer.
// * @return A buffer with RAII feature (more like std::unique_ptr).
// * @remark
// * + The return value is more like std::unique_ptr but it have more features.
// * + If Buffer_t::GetPtr return nullptr, it mean this function is failed.
// * + Use Buffer_t::GetSize to get the size of buffer.
// * + You can use Buffer_t::Reset to force free the return value.
// * @example
// * ```
// * Buffer_t buf = ReadBufferWrapper(1919810);
// * if (buf.GetPtr() == nullptr) {
// * // failed
// * } else {
// * stuff(buf); // do some operation...
// * buf.SetSize(114514); // i only consume these bytes.
// * buf.Reset(); // immediately free it.
// * }
// * ```
//*/
//Buffer_t ReadBufferWrapper();
/* ========== Sequence Functions ==========*/ /* ========== Sequence Functions ==========*/
/// <summary> /// <summary>

View File

@ -195,4 +195,71 @@ namespace LibCmo::CK2::ObjImpls {
return CKObject::IsVisible(); return CKObject::IsVisible();
} }
#pragma region Misc Oper
const VxMath::VxMatrix& CK3dEntity::GetWorldMatrix() const {
return m_WorldMatrix;
}
void CK3dEntity::SetWorldMatrix(const VxMath::VxMatrix& mat) {
m_WorldMatrix = mat;
}
CK_3DENTITY_FLAGS CK3dEntity::GetEntityFlags() const {
return m_3dEntityFlags;
}
void CK3dEntity::SetEntityFlags(CK_3DENTITY_FLAGS flags) {
m_3dEntityFlags = flags;
}
VxMath::VX_MOVEABLE_FLAGS CK3dEntity::GetMoveableFlags() const {
return m_MoveableFlags;
}
void CK3dEntity::SetMoveableFlags(VxMath::VX_MOVEABLE_FLAGS flags) {
m_MoveableFlags = flags;
}
CKDWORD CK3dEntity::GetZOrder() const {
return m_ZOrder;
}
void CK3dEntity::SetZOrder(CKDWORD ord) {
m_ZOrder = ord;
}
#pragma endregion
#pragma region Mesh Oper
void CK3dEntity::AddPotentialMesh(CKMesh* mesh) {
XContainer::NSXObjectPointerArray::AddIfNotHere(m_PotentialMeshes, mesh);
}
void CK3dEntity::RemovePotentialMesh(CKMesh* mesh) {
std::erase(m_PotentialMeshes, mesh);
}
CKDWORD CK3dEntity::GetPotentialMeshCount() const {
return static_cast<CKDWORD>(m_PotentialMeshes.size());
}
CKMesh* CK3dEntity::GetPotentialMesh(CKDWORD idx) const {
if (idx >= m_PotentialMeshes.size()) return nullptr;
return static_cast<CKMesh*>(m_PotentialMeshes[idx]);
}
CKMesh* CK3dEntity::GetCurrentMesh() const {
return m_CurrentMesh;
}
void CK3dEntity::SetCurrentMesh(CKMesh* mesh) {
m_CurrentMesh = mesh;
AddPotentialMesh(mesh);
}
#pragma endregion
} }

View File

@ -25,6 +25,22 @@ namespace LibCmo::CK2::ObjImpls {
virtual void Show(CK_OBJECT_SHOWOPTION show = CK_OBJECT_SHOWOPTION::CKSHOW) override; virtual void Show(CK_OBJECT_SHOWOPTION show = CK_OBJECT_SHOWOPTION::CKSHOW) override;
virtual bool IsVisible() const override; virtual bool IsVisible() const override;
const VxMath::VxMatrix& GetWorldMatrix() const;
void SetWorldMatrix(const VxMath::VxMatrix& mat);
CK_3DENTITY_FLAGS GetEntityFlags() const;
void SetEntityFlags(CK_3DENTITY_FLAGS flags);
VxMath::VX_MOVEABLE_FLAGS GetMoveableFlags() const;
void SetMoveableFlags(VxMath::VX_MOVEABLE_FLAGS flags);
CKDWORD GetZOrder() const;
void SetZOrder(CKDWORD ord);
void AddPotentialMesh(CKMesh* mesh);
void RemovePotentialMesh(CKMesh* mesh);
CKDWORD GetPotentialMeshCount() const;
CKMesh* GetPotentialMesh(CKDWORD idx) const;
CKMesh* GetCurrentMesh() const;
void SetCurrentMesh(CKMesh* mesh);
protected: protected:
XContainer::XObjectPointerArray m_PotentialMeshes; XContainer::XObjectPointerArray m_PotentialMeshes;
CKMesh* m_CurrentMesh; CKMesh* m_CurrentMesh;

View File

@ -13,7 +13,7 @@ namespace LibCmo::CK2::ObjImpls {
m_Specular(0.5f, 0.5f, 0.5f, 1.0f), m_SpecularPower(0.0f), m_Specular(0.5f, 0.5f, 0.5f, 1.0f), m_SpecularPower(0.0f),
m_Emissive(0.0f, 0.0f, 0.0f, 1.0f), m_Emissive(0.0f, 0.0f, 0.0f, 1.0f),
m_EnableTwoSided(false), m_EnableTwoSided(false),
m_Textures{nullptr, nullptr, nullptr, nullptr}, m_Textures { nullptr, nullptr, nullptr, nullptr },
m_TextureMinMode(VxMath::VXTEXTURE_FILTERMODE::VXTEXTUREFILTER_LINEAR), m_TextureMagMode(VxMath::VXTEXTURE_FILTERMODE::VXTEXTUREFILTER_LINEAR), m_TextureMinMode(VxMath::VXTEXTURE_FILTERMODE::VXTEXTUREFILTER_LINEAR), m_TextureMagMode(VxMath::VXTEXTURE_FILTERMODE::VXTEXTUREFILTER_LINEAR),
m_SourceBlend(VxMath::VXBLEND_MODE::VXBLEND_ONE), m_DestBlend(VxMath::VXBLEND_MODE::VXBLEND_ZERO), m_EnableAlphaBlend(false), m_SourceBlend(VxMath::VXBLEND_MODE::VXBLEND_ONE), m_DestBlend(VxMath::VXBLEND_MODE::VXBLEND_ZERO), m_EnableAlphaBlend(false),
m_ShadeMode(VxMath::VXSHADE_MODE::VXSHADE_GOURAUD), m_ShadeMode(VxMath::VXSHADE_MODE::VXSHADE_GOURAUD),
@ -171,4 +171,165 @@ namespace LibCmo::CK2::ObjImpls {
return true; return true;
} }
#pragma region Data Visitor
const VxMath::VxColor& CKMaterial::GetDiffuse() const {
return m_Diffuse;
}
void CKMaterial::SetDiffuse(const VxMath::VxColor& col) {
m_Diffuse = col;
}
const VxMath::VxColor& CKMaterial::GetAmbient() const {
return m_Ambient;
}
void CKMaterial::SetAmbient(const VxMath::VxColor& col) {
m_Ambient = col;
}
const VxMath::VxColor& CKMaterial::GetSpecular() const {
return m_Specular;
}
void CKMaterial::SetSpecular(const VxMath::VxColor& col) {
m_Specular = col;
}
const VxMath::VxColor& CKMaterial::GetEmissive() const {
return m_Emissive;
}
void CKMaterial::SetEmissive(const VxMath::VxColor& col) {
m_Emissive = col;
}
CKFLOAT CKMaterial::GetSpecularPower() const {
return m_SpecularPower;
}
void CKMaterial::SetSpecularPower(CKFLOAT val) {
m_SpecularPower = val;
}
CKTexture* CKMaterial::GetTexture(CKDWORD idx) const {
if (idx >= m_Textures.size()) return nullptr;
return m_Textures[idx];
}
void CKMaterial::SetTexture(CKTexture* tex, CKDWORD idx) {
if (idx >= m_Textures.size()) return;
m_Textures[idx] = tex;
}
CKDWORD CKMaterial::GetTextureBorderColor() const {
return m_TextureBorderColor;
}
void CKMaterial::SetTextureBorderColor(CKDWORD val) {
m_TextureBorderColor = val;
}
VxMath::VXTEXTURE_BLENDMODE CKMaterial::GetTextureBlendMode() const {
return m_TextureBlendMode;
}
void CKMaterial::SetTextureBlendMode(VxMath::VXTEXTURE_BLENDMODE val) {
m_TextureBlendMode = val;
}
VxMath::VXTEXTURE_FILTERMODE CKMaterial::GetTextureMinMode() const {
return m_TextureMinMode;
}
void CKMaterial::SetTextureMinMode(VxMath::VXTEXTURE_FILTERMODE val) {
m_TextureMinMode = val;
}
VxMath::VXTEXTURE_FILTERMODE CKMaterial::GetTextureMagMode() const {
return m_TextureMagMode;
}
void CKMaterial::SetTextureMagMode(VxMath::VXTEXTURE_FILTERMODE val) {
m_TextureMagMode = val;
}
VxMath::VXTEXTURE_ADDRESSMODE CKMaterial::GetTextureAddressMode() const {
return m_TextureAddressMode;
}
void CKMaterial::SetTextureAddressMode(VxMath::VXTEXTURE_ADDRESSMODE val) {
m_TextureAddressMode = val;
}
VxMath::VXBLEND_MODE CKMaterial::GetSourceBlend() const {
return m_SourceBlend;
}
void CKMaterial::SetSourceBlend(VxMath::VXBLEND_MODE val) {
m_SourceBlend = val;
}
VxMath::VXBLEND_MODE CKMaterial::GetDestBlend() const {
return m_DestBlend;
}
void CKMaterial::SetDestBlend(VxMath::VXBLEND_MODE val) {
m_DestBlend = val;
}
VxMath::VXFILL_MODE CKMaterial::GetFillMode() const {
return m_FillMode;
}
void CKMaterial::SetFillMode(VxMath::VXFILL_MODE val) {
m_FillMode = val;
}
VxMath::VXSHADE_MODE CKMaterial::GetShadeMode() const {
return m_ShadeMode;
}
void CKMaterial::SetShadeMode(VxMath::VXSHADE_MODE val) {
m_ShadeMode = val;
}
bool CKMaterial::GetAlphaTestEnabled() const {
return m_EnableAlphaTest;
}
void CKMaterial::SetAlphaTestEnabled(bool enabled) {
m_EnableAlphaTest = enabled;
}
bool CKMaterial::GetAlphaBlendEnabled() const {
return m_EnableAlphaBlend;
}
void CKMaterial::SetAlphaBlendEnabled(bool enabled) {
m_EnableAlphaBlend = enabled;
}
bool CKMaterial::GetPerspectiveCorrectionEnabled() const {
return m_EnablePerspectiveCorrection;
}
void CKMaterial::SetPerspectiveCorrectionEnabled(bool enabled) {
m_EnablePerspectiveCorrection = enabled;
}
bool CKMaterial::GetZWriteEnabled() const {
return m_EnableZWrite;
}
void CKMaterial::SetZWriteEnabled(bool enabled) {
m_EnableZWrite = enabled;
}
bool CKMaterial::GetTwoSidedEnabled() const {
return m_EnableTwoSided;
}
void CKMaterial::SetTwoSidedEnabled(bool enabled) {
m_EnableTwoSided = enabled;
}
CKBYTE CKMaterial::GetAlphaRef() const {
return m_AlphaRef;
}
void CKMaterial::SetAlphaRef(CKBYTE val) {
m_AlphaRef = val;
}
VxMath::VXCMPFUNC CKMaterial::GetAlphaFunc() const {
return m_AlphaFunc;
}
void CKMaterial::SetAlphaFunc(VxMath::VXCMPFUNC val) {
m_AlphaFunc = val;
}
VxMath::VXCMPFUNC CKMaterial::GetZFunc() const {
return m_ZFunc;
}
void CKMaterial::SetZFunc(VxMath::VXCMPFUNC val) {
m_ZFunc = val;
}
VxMath::VX_EFFECT CKMaterial::GetEffect() const {
return m_Effect;
}
void CKMaterial::SetEffect(VxMath::VX_EFFECT val) {
m_Effect = val;
}
#pragma endregion
} }

View File

@ -22,6 +22,60 @@ namespace LibCmo::CK2::ObjImpls {
virtual bool Save(CKStateChunk* chunk, CKFileVisitor* file, CKDWORD flags) override; virtual bool Save(CKStateChunk* chunk, CKFileVisitor* file, CKDWORD flags) override;
virtual bool Load(CKStateChunk* chunk, CKFileVisitor* file) override; virtual bool Load(CKStateChunk* chunk, CKFileVisitor* file) override;
const VxMath::VxColor& GetDiffuse() const;
void SetDiffuse(const VxMath::VxColor& col);
const VxMath::VxColor& GetAmbient() const;
void SetAmbient(const VxMath::VxColor& col);
const VxMath::VxColor& GetSpecular() const;
void SetSpecular(const VxMath::VxColor& col);
const VxMath::VxColor& GetEmissive() const;
void SetEmissive(const VxMath::VxColor& col);
CKFLOAT GetSpecularPower() const;
void SetSpecularPower(CKFLOAT val);
CKTexture* GetTexture(CKDWORD idx = 0) const;
void SetTexture(CKTexture* tex, CKDWORD idx = 0);
CKDWORD GetTextureBorderColor() const;
void SetTextureBorderColor(CKDWORD val);
VxMath::VXTEXTURE_BLENDMODE GetTextureBlendMode() const;
void SetTextureBlendMode(VxMath::VXTEXTURE_BLENDMODE val);
VxMath::VXTEXTURE_FILTERMODE GetTextureMinMode() const;
void SetTextureMinMode(VxMath::VXTEXTURE_FILTERMODE val);
VxMath::VXTEXTURE_FILTERMODE GetTextureMagMode() const;
void SetTextureMagMode(VxMath::VXTEXTURE_FILTERMODE val);
VxMath::VXTEXTURE_ADDRESSMODE GetTextureAddressMode() const;
void SetTextureAddressMode(VxMath::VXTEXTURE_ADDRESSMODE val);
VxMath::VXBLEND_MODE GetSourceBlend() const;
void SetSourceBlend(VxMath::VXBLEND_MODE val);
VxMath::VXBLEND_MODE GetDestBlend() const;
void SetDestBlend(VxMath::VXBLEND_MODE val);
VxMath::VXFILL_MODE GetFillMode() const;
void SetFillMode(VxMath::VXFILL_MODE val);
VxMath::VXSHADE_MODE GetShadeMode() const;
void SetShadeMode(VxMath::VXSHADE_MODE val);
bool GetAlphaTestEnabled() const;
void SetAlphaTestEnabled(bool enabled);
bool GetAlphaBlendEnabled() const;
void SetAlphaBlendEnabled(bool enabled);
bool GetPerspectiveCorrectionEnabled() const;
void SetPerspectiveCorrectionEnabled(bool enabled);
bool GetZWriteEnabled() const;
void SetZWriteEnabled(bool enabled);
bool GetTwoSidedEnabled() const;
void SetTwoSidedEnabled(bool enabled);
CKBYTE GetAlphaRef() const;
void SetAlphaRef(CKBYTE val);
VxMath::VXCMPFUNC GetAlphaFunc() const;
void SetAlphaFunc(VxMath::VXCMPFUNC val);
VxMath::VXCMPFUNC GetZFunc() const;
void SetZFunc(VxMath::VXCMPFUNC val);
VxMath::VX_EFFECT GetEffect() const;
void SetEffect(VxMath::VX_EFFECT val);
protected: protected:
VxMath::VxColor m_Diffuse; VxMath::VxColor m_Diffuse;
VxMath::VxColor m_Ambient; VxMath::VxColor m_Ambient;

View File

@ -424,7 +424,7 @@ namespace LibCmo::CK2::ObjImpls {
#pragma region Vertex Section #pragma region Vertex Section
CKDWORD CKMesh::GetVertexCount() { CKDWORD CKMesh::GetVertexCount() const {
return m_VertexCount; return m_VertexCount;
} }
@ -469,7 +469,7 @@ namespace LibCmo::CK2::ObjImpls {
#pragma region Material Slot Section #pragma region Material Slot Section
CKDWORD CKMesh::GetMaterialSlotCount() { CKDWORD CKMesh::GetMaterialSlotCount() const {
return m_MtlSlotCount; return m_MtlSlotCount;
} }
@ -478,16 +478,15 @@ namespace LibCmo::CK2::ObjImpls {
m_MaterialSlot.resize(count, nullptr); m_MaterialSlot.resize(count, nullptr);
} }
void CKMesh::SetMaterialSlot(CKMaterial* mtl, CKDWORD idx) { CKMaterial** CKMesh::GetMaterialSlots() {
if (idx >= m_MtlSlotCount) return; return m_MaterialSlot.data();
m_MaterialSlot[idx] = mtl;
} }
#pragma endregion #pragma endregion
#pragma region Face Section #pragma region Face Section
CKDWORD CKMesh::GetFaceCount() { CKDWORD CKMesh::GetFaceCount() const {
return m_FaceCount; return m_FaceCount;
} }
@ -520,7 +519,7 @@ namespace LibCmo::CK2::ObjImpls {
#pragma region Line Section #pragma region Line Section
CKDWORD CKMesh::GetLineCount() { CKDWORD CKMesh::GetLineCount() const {
return m_LineCount; return m_LineCount;
} }
@ -537,7 +536,7 @@ namespace LibCmo::CK2::ObjImpls {
#pragma region Mtl Channel Section #pragma region Mtl Channel Section
CKDWORD CKMesh::GetMtlChannelCount() { CKDWORD CKMesh::GetMtlChannelCount() const {
return m_MtlChannelCount; return m_MtlChannelCount;
} }
@ -574,7 +573,7 @@ namespace LibCmo::CK2::ObjImpls {
return m_MaterialChannels[idx].m_CustomUV.data(); return m_MaterialChannels[idx].m_CustomUV.data();
} }
VxMath::VXCHANNEL_FLAGS CKMesh::GetMtlChannelFlags(CKDWORD idx) { VxMath::VXCHANNEL_FLAGS CKMesh::GetMtlChannelFlags(CKDWORD idx) const {
if (idx >= m_MtlChannelCount) return static_cast<VxMath::VXCHANNEL_FLAGS>(0); if (idx >= m_MtlChannelCount) return static_cast<VxMath::VXCHANNEL_FLAGS>(0);
return m_MaterialChannels[idx].m_Flags; return m_MaterialChannels[idx].m_Flags;
} }

View File

@ -33,7 +33,7 @@ namespace LibCmo::CK2::ObjImpls {
// ===== Vertex Section ===== // ===== Vertex Section =====
public: public:
CKDWORD GetVertexCount(); CKDWORD GetVertexCount() const;
void SetVertexCount(CKDWORD count); void SetVertexCount(CKDWORD count);
VxMath::VxVector3* GetVertexPositions(); VxMath::VxVector3* GetVertexPositions();
VxMath::VxVector3* GetVertexNormals(); VxMath::VxVector3* GetVertexNormals();
@ -44,13 +44,13 @@ namespace LibCmo::CK2::ObjImpls {
// ===== Material Slot Section ===== // ===== Material Slot Section =====
public: public:
CKDWORD GetMaterialSlotCount(); CKDWORD GetMaterialSlotCount() const;
void SetMaterialSlotCount(CKDWORD count); void SetMaterialSlotCount(CKDWORD count);
void SetMaterialSlot(CKMaterial* mtl, CKDWORD idx); CKMaterial** GetMaterialSlots();
// ===== Face Section ===== // ===== Face Section =====
public: public:
CKDWORD GetFaceCount(); CKDWORD GetFaceCount() const;
void SetFaceCount(CKDWORD count); void SetFaceCount(CKDWORD count);
CKWORD* GetFaceIndices(); CKWORD* GetFaceIndices();
CKWORD* GetFaceMaterialSlotIndexs(); CKWORD* GetFaceMaterialSlotIndexs();
@ -59,20 +59,20 @@ namespace LibCmo::CK2::ObjImpls {
// ===== Line Section ===== // ===== Line Section =====
public: public:
CKDWORD GetLineCount(); CKDWORD GetLineCount() const;
void SetLineCount(CKDWORD count); void SetLineCount(CKDWORD count);
CKWORD* GetLineIndices(); CKWORD* GetLineIndices();
// ===== Material Channel Section ===== // ===== Material Channel Section =====
public: public:
CKDWORD GetMtlChannelCount(); CKDWORD GetMtlChannelCount() const;
void SetMtlChannelCount(CKDWORD count); void SetMtlChannelCount(CKDWORD count);
CKMaterial** GetMtlChannelMaterials(CKDWORD& stride); CKMaterial** GetMtlChannelMaterials(CKDWORD& stride);
VxMath::VXBLEND_MODE* GetMtlChannelSourceBlends(CKDWORD& stride); VxMath::VXBLEND_MODE* GetMtlChannelSourceBlends(CKDWORD& stride);
VxMath::VXBLEND_MODE* GetMtlChannelDestBlends(CKDWORD& stride); VxMath::VXBLEND_MODE* GetMtlChannelDestBlends(CKDWORD& stride);
VxMath::VxVector2* GetMtlChannelCustomUVs(CKDWORD idx); VxMath::VxVector2* GetMtlChannelCustomUVs(CKDWORD idx);
VxMath::VXCHANNEL_FLAGS GetMtlChannelFlags(CKDWORD idx); VxMath::VXCHANNEL_FLAGS GetMtlChannelFlags(CKDWORD idx) const;
void SetMtlChannelFlags(CKDWORD idx, VxMath::VXCHANNEL_FLAGS flags); void SetMtlChannelFlags(CKDWORD idx, VxMath::VXCHANNEL_FLAGS flags);
protected: protected:
// 2 sync functions served for material channels. // 2 sync functions served for material channels.

View File

@ -94,7 +94,10 @@ namespace LibCmo::CK2::ObjImpls {
} else { } else {
CKDWORD fmtbytesize; CKDWORD fmtbytesize;
if (chunk->SeekIdentifierAndReturnSize(CK_STATESAVEFLAGS_TEXTURE::CK_STATESAVE_OLDTEXONLY, &fmtbytesize)) { if (chunk->SeekIdentifierAndReturnSize(CK_STATESAVEFLAGS_TEXTURE::CK_STATESAVE_OLDTEXONLY, &fmtbytesize)) {
// 0xFF (blank) 0xFF (save options) 0xFF (transparent + movie info + video fmt) 0xFF (mip map) // for mid data:
// HIGH >>> 0xFF (blank) 0xFF (save options) 0xFF (transparent + movie info + video fmt) 0xFF (mip map) <<< LOW
// for mixed flags:
// HIGH >>> 1(blank) 1(cubemap) 1(has video fmt) 1(is transparent)
CKDWORD mixdata; CKDWORD mixdata;
chunk->ReadStruct(mixdata); chunk->ReadStruct(mixdata);
m_UseMipMap = (mixdata & 0xFF); m_UseMipMap = (mixdata & 0xFF);
@ -103,6 +106,7 @@ namespace LibCmo::CK2::ObjImpls {
mixdata = mixdata & 0xFF00 >> 8; mixdata = mixdata & 0xFF00 >> 8;
m_ImageHost.SetTransparent(mixdata & 0x1); m_ImageHost.SetTransparent(mixdata & 0x1);
bool hasVideoFmt = mixdata & 0x2; bool hasVideoFmt = mixdata & 0x2;
m_ImageHost.SetCubeMap(mixdata & 0x4);
// MARK: I ignore 0x4 in there because it involve video. // MARK: I ignore 0x4 in there because it involve video.
// set current slot, transparent color, and video format. // set current slot, transparent color, and video format.
@ -190,4 +194,46 @@ namespace LibCmo::CK2::ObjImpls {
return true; return true;
} }
#pragma region Visitor
CKBitmapData& CKTexture::GetUnderlyingData() {
return m_ImageHost;
}
bool CKTexture::IsUseMipmap() const {
return m_UseMipMap;
}
void CKTexture::UseMipmap(bool isUse) {
m_UseMipMap = isUse;
if (!m_UseMipMap) {
m_MipmapImages.clear();
}
}
CKDWORD CKTexture::GetMipmapLevel() const {
return static_cast<CKDWORD>(m_MipmapImages.size());
}
void CKTexture::SetMipmapLevel(CKDWORD level) {
m_MipmapImages.resize(level);
}
VxMath::VxImageDescEx* CKTexture::GetMipmapLevelData(CKDWORD level) {
if (!m_UseMipMap || level >= m_MipmapImages.size()) return nullptr;
return &m_MipmapImages[level];
}
VxMath::VX_PIXELFORMAT CKTexture::GetVideoFormat() const {
return m_VideoFormat;
}
void CKTexture::SetVideoFormat(VxMath::VX_PIXELFORMAT fmt) {
m_VideoFormat = fmt;
}
#pragma endregion
} }

View File

@ -16,10 +16,19 @@ namespace LibCmo::CK2::ObjImpls {
return CK_CLASSID::CKCID_TEXTURE; return CK_CLASSID::CKCID_TEXTURE;
} }
//virtual void PreSave(CKFileVisitor* file, CKDWORD flags) override;
virtual bool Save(CKStateChunk* chunk, CKFileVisitor* file, CKDWORD flags) override; virtual bool Save(CKStateChunk* chunk, CKFileVisitor* file, CKDWORD flags) override;
virtual bool Load(CKStateChunk* chunk, CKFileVisitor* file) override; virtual bool Load(CKStateChunk* chunk, CKFileVisitor* file) override;
//virtual void PostLoad() override;
CKBitmapData& GetUnderlyingData();
bool IsUseMipmap() const;
void UseMipmap(bool isUse);
CKDWORD GetMipmapLevel() const;
void SetMipmapLevel(CKDWORD level);
VxMath::VxImageDescEx* GetMipmapLevelData(CKDWORD level);
VxMath::VX_PIXELFORMAT GetVideoFormat() const;
void SetVideoFormat(VxMath::VX_PIXELFORMAT fmt);
protected: protected:
CKBitmapData m_ImageHost; CKBitmapData m_ImageHost;

View File

@ -144,7 +144,7 @@ namespace LibCmo::XContainer {
} }
namespace NSXObjectPointerArray { namespace NSXObjectPointerArray {
bool AddIfNotHere(XObjectPointerArray& objarray, CK2::ObjImpls::CKObject* const obj) { bool AddIfNotHere(XObjectPointerArray& objarray, CK2::ObjImpls::CKObject* obj) {
auto finder = std::find(objarray.begin(), objarray.end(), obj); auto finder = std::find(objarray.begin(), objarray.end(), obj);
if (finder == objarray.end()) { if (finder == objarray.end()) {
objarray.emplace_back(obj); objarray.emplace_back(obj);

View File

@ -186,7 +186,7 @@ namespace LibCmo::XContainer {
* @param obj * @param obj
* @return True if the object was already present, false otherwise * @return True if the object was already present, false otherwise
*/ */
bool AddIfNotHere(XObjectPointerArray& objarray, CK2::ObjImpls::CKObject* const obj); bool AddIfNotHere(XObjectPointerArray& objarray, CK2::ObjImpls::CKObject* obj);
/** /**
* @brief Check Object pointer validation and remove invalid pointers before deletion. * @brief Check Object pointer validation and remove invalid pointers before deletion.