From ddf596faece3266e948883d30ddaf3ec04fd3ec3 Mon Sep 17 00:00:00 2001 From: yyc12345 Date: Fri, 22 Sep 2023 14:48:45 +0800 Subject: [PATCH] create visitor for all existed CK class --- LibCmo/CK2/CKBitmapData.cpp | 47 +++++--- LibCmo/CK2/CKBitmapData.hpp | 144 ++++++++++++++++--------- LibCmo/CK2/CKStateChunk.hpp | 133 +++++++++++++---------- LibCmo/CK2/ObjImpls/CK3dEntity.cpp | 67 ++++++++++++ LibCmo/CK2/ObjImpls/CK3dEntity.hpp | 16 +++ LibCmo/CK2/ObjImpls/CKMaterial.cpp | 165 ++++++++++++++++++++++++++++- LibCmo/CK2/ObjImpls/CKMaterial.hpp | 62 ++++++++++- LibCmo/CK2/ObjImpls/CKMesh.cpp | 17 ++- LibCmo/CK2/ObjImpls/CKMesh.hpp | 14 +-- LibCmo/CK2/ObjImpls/CKTexture.cpp | 48 ++++++++- LibCmo/CK2/ObjImpls/CKTexture.hpp | 13 ++- LibCmo/XContainer/XTypes.cpp | 2 +- LibCmo/XContainer/XTypes.hpp | 2 +- 13 files changed, 582 insertions(+), 148 deletions(-) diff --git a/LibCmo/CK2/CKBitmapData.cpp b/LibCmo/CK2/CKBitmapData.cpp index 4ee8f21..c62a697 100644 --- a/LibCmo/CK2/CKBitmapData.cpp +++ b/LibCmo/CK2/CKBitmapData.cpp @@ -255,7 +255,7 @@ namespace LibCmo::CK2 { #pragma endregion -#pragma region Misc Functions +#pragma region Slot Functions void CKBitmapData::SetSlotCount(CKDWORD count) { m_Slots.resize(count); @@ -265,7 +265,7 @@ namespace LibCmo::CK2 { } } - CKDWORD CKBitmapData::GetSlotCount() { + CKDWORD CKBitmapData::GetSlotCount() const { return static_cast(m_Slots.size()); } @@ -280,16 +280,17 @@ namespace LibCmo::CK2 { } } - CKDWORD CKBitmapData::GetCurrentSlot() { + CKDWORD CKBitmapData::GetCurrentSlot() const { return m_CurrentSlot; } - void CKBitmapData::CreateImage(CKDWORD Width, CKDWORD Height, CKDWORD Slot) { - if (Slot >= m_Slots.size()) return; + bool CKBitmapData::CreateImage(CKDWORD Width, CKDWORD Height, CKDWORD Slot) { + if (Slot >= m_Slots.size()) return false; CKBitmapSlot& slotdata = m_Slots[Slot]; slotdata.m_ImageData.CreateImage(Width, Height); VxMath::VxDoAlphaBlit(&slotdata.m_ImageData, 0xFFu); + return true; } bool CKBitmapData::LoadImage(CKSTRING filename, CKDWORD slot) { @@ -351,18 +352,36 @@ namespace LibCmo::CK2 { m_Slots[slot].m_ImageData.FreeImage(); } - void CKBitmapData::SetSlotFileName(CKDWORD slot, CKSTRING filename) { - if (slot >= m_Slots.size()) return; - if (filename == nullptr) return; + bool CKBitmapData::SetSlotFileName(CKDWORD slot, CKSTRING filename) { + if (slot >= m_Slots.size()) return false; + if (filename == nullptr) return false; 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; 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; } @@ -370,7 +389,7 @@ namespace LibCmo::CK2 { m_SaveProperties = props; } - CK_TEXTURE_SAVEOPTIONS CKBitmapData::GetSaveOptions() { + CK_TEXTURE_SAVEOPTIONS CKBitmapData::GetSaveOptions() const { 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); } @@ -395,7 +414,7 @@ namespace LibCmo::CK2 { m_TransColor = col; } - CKDWORD CKBitmapData::GetTransparentColor() { + CKDWORD CKBitmapData::GetTransparentColor() const { return m_TransColor; } @@ -403,7 +422,7 @@ namespace LibCmo::CK2 { m_PickThreshold = threshold; } - CKDWORD CKBitmapData::GetPickThreshold() { + CKDWORD CKBitmapData::GetPickThreshold() const { return m_PickThreshold; } diff --git a/LibCmo/CK2/CKBitmapData.hpp b/LibCmo/CK2/CKBitmapData.hpp index 16a019e..9b131f5 100644 --- a/LibCmo/CK2/CKBitmapData.hpp +++ b/LibCmo/CK2/CKBitmapData.hpp @@ -38,6 +38,8 @@ namespace LibCmo::CK2 { ~CKBitmapData(); LIBCMO_DISABLE_COPY_MOVE(CKBitmapData); +#pragma region RW Funcs + static bool ReadSpecificFormatBitmap(CKStateChunk* chk, VxMath::VxImageDescEx* slot); static bool ReadRawBitmap(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 DumpToChunk(CKStateChunk* chunk, CKFileVisitor* file, const CKBitmapDataWriteIdentifiers& identifiers); +#pragma endregion + +#pragma region Slot funcs + void SetSlotCount(CKDWORD count); - CKDWORD GetSlotCount(); + CKDWORD GetSlotCount() const; void SetCurrentSlot(CKDWORD slot); - CKDWORD GetCurrentSlot(); - - 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); + CKDWORD GetCurrentSlot() const; /** - 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. - Remarks: + /** + * @brief Set associated file name for specified slot. + * @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. + Setting on the transparency and a transparent color automatically updates the alpha channel so that pixel with the transparent color have a 0 alpha value. - See also: IsTransparent,SetTranparentColor + @see IsTransparent, SetTranparentColor */ void SetTransparent(bool Transparency); /** - Summary: Returns whether color keyed transparency is enabled. - - Return Value: - TRUE if successful. - Arguments: - Transparency: TRUE activates transparency, FALSE disables it. - Return Value: - TRUE if color keying is enabled. - See also: IsTransparent + @brief Returns whether color keyed transparency is enabled. + @return TRUE if color keying is enabled. + @see SetTransparent */ - bool IsTransparent(); + bool IsTransparent() const; /** - Summary: Sets the transparent color. - Arguments: - Color: A 32 bit ARGB transparent color. - Remarks: + @brief Sets the transparent color. + @param Color[in] A 32 bit ARGB transparent color. + @remark + 0x00000000 (black) is the default transparent color. + Setting on the transparency and a transparent color automatically updates the alpha channel so that pixel with the transparent color have a 0 alpha value. - - See also: GetTranparentColor,SetTransparent + @see GetTranparentColor, SetTransparent */ void SetTransparentColor(CKDWORD col); /** - Summary: Returns the transparent color. - Return Value: - Color: A 32 bit ARGB transparent color. - Remarks: + @brief Returns the transparent color. + @return A 32 bit ARGB transparent color. + @remark + 0x00000000 (black) is the default transparent color. - - See also: SetTranparentColor,SetTransparent + @see SetTranparentColor, SetTransparent */ - CKDWORD GetTransparentColor(); + CKDWORD GetTransparentColor() const; /** - Summary: Sets pick threshold value. - Arguments: - pt: Pick threshold value to be set. - Remarks: + @brief Sets pick threshold value. + @param pt[in] Pick threshold value to be set. + @remark + The pick threshold is used when picking object with transparent textures. + 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. + 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. - - See Also: CKRenderContext::Pick + @see CKRenderContext::Pick */ 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: CKContext* m_Context; diff --git a/LibCmo/CK2/CKStateChunk.hpp b/LibCmo/CK2/CKStateChunk.hpp index f66fe15..6cb1064 100644 --- a/LibCmo/CK2/CKStateChunk.hpp +++ b/LibCmo/CK2/CKStateChunk.hpp @@ -8,7 +8,6 @@ namespace LibCmo::CK2 { class CKStateChunk { public: - //CKStateChunk(); CKStateChunk(CKFileVisitor* visitor, CKContext* ctx); CKStateChunk(const CKStateChunk&); CKStateChunk(CKStateChunk&&); @@ -183,9 +182,43 @@ namespace LibCmo::CK2 { bool Skip(CKDWORD DwordCount); 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); 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); + /** + * @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); #pragma endregion @@ -237,23 +270,21 @@ namespace LibCmo::CK2 { /** * @brief A RAII wrapper for LockReadBuffer and UnLockReadBuffer. * @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 - * + The return value is more like std::unique_ptr but it have more features. - * + If GeneralBuffer_t::GetPtr return nullptr, it mean 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. - * + You also can use GeneralBuffer_t::SetSize 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. - * + You can use GeneralBuffer_t::Reset to force free the return value. - * @example + * + The return value is just a std::unique_ptr but its deleter have more features. + * + If return value contained data is nullptr, it mean that this function is failed. + * + 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 LockedReadBuffer_t.get_deleter().SetConsumedSize() to set the final moving forward byte count before the return value free itself. + * + The value passed to LockedReadBuffer_t..get_deleter().SetConsumedSize() will finally be passed to UnLockReadBuffer. + * + You can use LockedReadBuffer_t.reset() to force free the return value. + * @remark Here is a example. * ``` - * LockedReadBuffer_t buf = ReadBufferLocker(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. + * auto buf = chunk->LockReadBufferWrapper(1919810); + * if (buf) { + * stuff(buf.get()); // do some operation... + * buf.get_deleter().SetConsumedSize(114514); // i only consume these bytes. + * buf.reset(); // immediately free it. * } * ``` * @see LockReadBuffer, UnLockReadBuffer, LockedReadBuffer_t @@ -348,14 +379,15 @@ namespace LibCmo::CK2 { /** * @brief Read buffer and copy it. + * * The copied buffer and the size of buffer will be returned to caller. * Caller should free the buffer by calling CKStateChunk::DeleteBuffer(void*). + * * @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. * @return True if success. - * @remark - * + Following original Virtools functions can use this function to implement: - * - ReadBuffer(void**) + * @remark Following original Virtools functions can use this function to implement: + * + ReadBuffer(void**) */ bool ReadBuffer(void** ppData, CKDWORD* size_in_byte); /** @@ -365,61 +397,52 @@ namespace LibCmo::CK2 { */ void DeleteBuffer(const void* buf); /** - * @brief A wrapper for ReadAndCopyBuffer(void**, CKDWORD*) - * @return + * @brief A RAII wrapper for ReadAndCopyBuffer(void**, CKDWORD*) + * @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(); /** * @brief Read buffer and fill user struct. + * * The size of buffer will be read from CKStateChunk internally and return to caller. + * * @param pData[out] The pointer holding the data. * @return True if success. - * @remark - * + Following original Virtools functions can use this function to implement: - * - ReadAndFillBuffer(void*) - * - ReadAndFillBuffer_LEndian(void*) - * - ReadAndFillBuffer_LEndian16(void*) + * @remark Following original Virtools functions can use this function to implement: + * + ReadAndFillBuffer(void*) + * + ReadAndFillBuffer_LEndian(void*) + * + ReadAndFillBuffer_LEndian16(void*) */ bool ReadAndFillBuffer(void* pData); /** * @brief Read buffer and fill user struct. + * * The size of buffer is provided by user. + * * @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 * @return True if success. - * @remark - * + Following original Virtools functions can use this function to implement: - * - ReadAndFillBuffer(int, void*) - * - ReadAndFillBuffer_LEndian(int, void*) - * - ReadAndFillBuffer_LEndian16(int, void*) + * @remark Following original Virtools functions can use this function to implement: + * + ReadAndFillBuffer(int, void*) + * + ReadAndFillBuffer_LEndian(int, void*) + * + ReadAndFillBuffer_LEndian16(int, void*) */ 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 ==========*/ /// diff --git a/LibCmo/CK2/ObjImpls/CK3dEntity.cpp b/LibCmo/CK2/ObjImpls/CK3dEntity.cpp index af20d09..ee471a8 100644 --- a/LibCmo/CK2/ObjImpls/CK3dEntity.cpp +++ b/LibCmo/CK2/ObjImpls/CK3dEntity.cpp @@ -195,4 +195,71 @@ namespace LibCmo::CK2::ObjImpls { 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(m_PotentialMeshes.size()); + } + + CKMesh* CK3dEntity::GetPotentialMesh(CKDWORD idx) const { + if (idx >= m_PotentialMeshes.size()) return nullptr; + return static_cast(m_PotentialMeshes[idx]); + } + + CKMesh* CK3dEntity::GetCurrentMesh() const { + return m_CurrentMesh; + } + + void CK3dEntity::SetCurrentMesh(CKMesh* mesh) { + m_CurrentMesh = mesh; + AddPotentialMesh(mesh); + } + +#pragma endregion + + } diff --git a/LibCmo/CK2/ObjImpls/CK3dEntity.hpp b/LibCmo/CK2/ObjImpls/CK3dEntity.hpp index 343fe33..4763823 100644 --- a/LibCmo/CK2/ObjImpls/CK3dEntity.hpp +++ b/LibCmo/CK2/ObjImpls/CK3dEntity.hpp @@ -25,6 +25,22 @@ namespace LibCmo::CK2::ObjImpls { virtual void Show(CK_OBJECT_SHOWOPTION show = CK_OBJECT_SHOWOPTION::CKSHOW) 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: XContainer::XObjectPointerArray m_PotentialMeshes; CKMesh* m_CurrentMesh; diff --git a/LibCmo/CK2/ObjImpls/CKMaterial.cpp b/LibCmo/CK2/ObjImpls/CKMaterial.cpp index cbc52ee..d222cb2 100644 --- a/LibCmo/CK2/ObjImpls/CKMaterial.cpp +++ b/LibCmo/CK2/ObjImpls/CKMaterial.cpp @@ -13,7 +13,7 @@ namespace LibCmo::CK2::ObjImpls { 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_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_SourceBlend(VxMath::VXBLEND_MODE::VXBLEND_ONE), m_DestBlend(VxMath::VXBLEND_MODE::VXBLEND_ZERO), m_EnableAlphaBlend(false), m_ShadeMode(VxMath::VXSHADE_MODE::VXSHADE_GOURAUD), @@ -161,7 +161,7 @@ namespace LibCmo::CK2::ObjImpls { // drop parameter id. CK_ID paramid; chunk->ReadObjectID(paramid); - + // read effect self CKDWORD data; chunk->ReadStruct(data); @@ -171,4 +171,165 @@ namespace LibCmo::CK2::ObjImpls { 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 + } \ No newline at end of file diff --git a/LibCmo/CK2/ObjImpls/CKMaterial.hpp b/LibCmo/CK2/ObjImpls/CKMaterial.hpp index bd8a8fd..2af60b8 100644 --- a/LibCmo/CK2/ObjImpls/CKMaterial.hpp +++ b/LibCmo/CK2/ObjImpls/CKMaterial.hpp @@ -11,17 +11,71 @@ namespace LibCmo::CK2::ObjImpls { CKMaterial(CKContext* ctx, CK_ID ckid, CKSTRING name); virtual ~CKMaterial(); LIBCMO_DISABLE_COPY_MOVE(CKMaterial); - - virtual CK_CLASSID GetClassID(void) override { - return CK_CLASSID::CKCID_MATERIAL; + + virtual CK_CLASSID GetClassID(void) override { + return CK_CLASSID::CKCID_MATERIAL; } virtual void CheckPreDeletion() override; - + // 2 RW functions virtual bool Save(CKStateChunk* chunk, CKFileVisitor* file, CKDWORD flags) 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: VxMath::VxColor m_Diffuse; VxMath::VxColor m_Ambient; diff --git a/LibCmo/CK2/ObjImpls/CKMesh.cpp b/LibCmo/CK2/ObjImpls/CKMesh.cpp index 0789b74..cb52eaa 100644 --- a/LibCmo/CK2/ObjImpls/CKMesh.cpp +++ b/LibCmo/CK2/ObjImpls/CKMesh.cpp @@ -424,7 +424,7 @@ namespace LibCmo::CK2::ObjImpls { #pragma region Vertex Section - CKDWORD CKMesh::GetVertexCount() { + CKDWORD CKMesh::GetVertexCount() const { return m_VertexCount; } @@ -469,7 +469,7 @@ namespace LibCmo::CK2::ObjImpls { #pragma region Material Slot Section - CKDWORD CKMesh::GetMaterialSlotCount() { + CKDWORD CKMesh::GetMaterialSlotCount() const { return m_MtlSlotCount; } @@ -478,16 +478,15 @@ namespace LibCmo::CK2::ObjImpls { m_MaterialSlot.resize(count, nullptr); } - void CKMesh::SetMaterialSlot(CKMaterial* mtl, CKDWORD idx) { - if (idx >= m_MtlSlotCount) return; - m_MaterialSlot[idx] = mtl; + CKMaterial** CKMesh::GetMaterialSlots() { + return m_MaterialSlot.data(); } #pragma endregion #pragma region Face Section - CKDWORD CKMesh::GetFaceCount() { + CKDWORD CKMesh::GetFaceCount() const { return m_FaceCount; } @@ -520,7 +519,7 @@ namespace LibCmo::CK2::ObjImpls { #pragma region Line Section - CKDWORD CKMesh::GetLineCount() { + CKDWORD CKMesh::GetLineCount() const { return m_LineCount; } @@ -537,7 +536,7 @@ namespace LibCmo::CK2::ObjImpls { #pragma region Mtl Channel Section - CKDWORD CKMesh::GetMtlChannelCount() { + CKDWORD CKMesh::GetMtlChannelCount() const { return m_MtlChannelCount; } @@ -574,7 +573,7 @@ namespace LibCmo::CK2::ObjImpls { 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(0); return m_MaterialChannels[idx].m_Flags; } diff --git a/LibCmo/CK2/ObjImpls/CKMesh.hpp b/LibCmo/CK2/ObjImpls/CKMesh.hpp index 6087108..eb2213c 100644 --- a/LibCmo/CK2/ObjImpls/CKMesh.hpp +++ b/LibCmo/CK2/ObjImpls/CKMesh.hpp @@ -33,7 +33,7 @@ namespace LibCmo::CK2::ObjImpls { // ===== Vertex Section ===== public: - CKDWORD GetVertexCount(); + CKDWORD GetVertexCount() const; void SetVertexCount(CKDWORD count); VxMath::VxVector3* GetVertexPositions(); VxMath::VxVector3* GetVertexNormals(); @@ -44,13 +44,13 @@ namespace LibCmo::CK2::ObjImpls { // ===== Material Slot Section ===== public: - CKDWORD GetMaterialSlotCount(); + CKDWORD GetMaterialSlotCount() const; void SetMaterialSlotCount(CKDWORD count); - void SetMaterialSlot(CKMaterial* mtl, CKDWORD idx); + CKMaterial** GetMaterialSlots(); // ===== Face Section ===== public: - CKDWORD GetFaceCount(); + CKDWORD GetFaceCount() const; void SetFaceCount(CKDWORD count); CKWORD* GetFaceIndices(); CKWORD* GetFaceMaterialSlotIndexs(); @@ -59,20 +59,20 @@ namespace LibCmo::CK2::ObjImpls { // ===== Line Section ===== public: - CKDWORD GetLineCount(); + CKDWORD GetLineCount() const; void SetLineCount(CKDWORD count); CKWORD* GetLineIndices(); // ===== Material Channel Section ===== public: - CKDWORD GetMtlChannelCount(); + CKDWORD GetMtlChannelCount() const; void SetMtlChannelCount(CKDWORD count); CKMaterial** GetMtlChannelMaterials(CKDWORD& stride); VxMath::VXBLEND_MODE* GetMtlChannelSourceBlends(CKDWORD& stride); VxMath::VXBLEND_MODE* GetMtlChannelDestBlends(CKDWORD& stride); 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); protected: // 2 sync functions served for material channels. diff --git a/LibCmo/CK2/ObjImpls/CKTexture.cpp b/LibCmo/CK2/ObjImpls/CKTexture.cpp index 7f786ee..2869f0e 100644 --- a/LibCmo/CK2/ObjImpls/CKTexture.cpp +++ b/LibCmo/CK2/ObjImpls/CKTexture.cpp @@ -94,7 +94,10 @@ namespace LibCmo::CK2::ObjImpls { } else { CKDWORD 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; chunk->ReadStruct(mixdata); m_UseMipMap = (mixdata & 0xFF); @@ -103,6 +106,7 @@ namespace LibCmo::CK2::ObjImpls { mixdata = mixdata & 0xFF00 >> 8; m_ImageHost.SetTransparent(mixdata & 0x1); bool hasVideoFmt = mixdata & 0x2; + m_ImageHost.SetCubeMap(mixdata & 0x4); // MARK: I ignore 0x4 in there because it involve video. // set current slot, transparent color, and video format. @@ -190,4 +194,46 @@ namespace LibCmo::CK2::ObjImpls { 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(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 + + } diff --git a/LibCmo/CK2/ObjImpls/CKTexture.hpp b/LibCmo/CK2/ObjImpls/CKTexture.hpp index 74d2e58..ed15f00 100644 --- a/LibCmo/CK2/ObjImpls/CKTexture.hpp +++ b/LibCmo/CK2/ObjImpls/CKTexture.hpp @@ -16,10 +16,19 @@ namespace LibCmo::CK2::ObjImpls { 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 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: CKBitmapData m_ImageHost; diff --git a/LibCmo/XContainer/XTypes.cpp b/LibCmo/XContainer/XTypes.cpp index ccd8fe1..37ba8aa 100644 --- a/LibCmo/XContainer/XTypes.cpp +++ b/LibCmo/XContainer/XTypes.cpp @@ -144,7 +144,7 @@ namespace LibCmo::XContainer { } 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); if (finder == objarray.end()) { objarray.emplace_back(obj); diff --git a/LibCmo/XContainer/XTypes.hpp b/LibCmo/XContainer/XTypes.hpp index 9b97e5c..df93e07 100644 --- a/LibCmo/XContainer/XTypes.hpp +++ b/LibCmo/XContainer/XTypes.hpp @@ -186,7 +186,7 @@ namespace LibCmo::XContainer { * @param obj * @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.