diff --git a/LibCmo/CK2/CKBitmapData.cpp b/LibCmo/CK2/CKBitmapData.cpp index cfdc777..bef65f9 100644 --- a/LibCmo/CK2/CKBitmapData.cpp +++ b/LibCmo/CK2/CKBitmapData.cpp @@ -1,6 +1,7 @@ #include "CKBitmapData.hpp" #include "CKContext.hpp" #include "CKStateChunk.hpp" +#include "CKFile.hpp" #include "DataHandlers/CKBitmapHandler.hpp" #include "MgrImpls/CKPathManager.hpp" #include @@ -123,7 +124,7 @@ namespace LibCmo::CK2 { return false; } - void CKBitmapData::WriteSpecificFormatBitmap(CKStateChunk* chk, const VxMath::VxImageDescEx* slot) { + void CKBitmapData::WriteSpecificFormatBitmap(CKStateChunk* chk, const VxMath::VxImageDescEx* slot, const CKBitmapProperties* savefmt) { } @@ -250,7 +251,98 @@ namespace LibCmo::CK2 { } bool CKBitmapData::DumpToChunk(CKStateChunk* chunk, CKFileVisitor* file, const CKBitmapDataWriteIdentifiers& identifiers) { - return false; + // resolve save fmt and save opt + CK_TEXTURE_SAVEOPTIONS saveopt = GetSaveOptions(); + if (saveopt == CK_TEXTURE_SAVEOPTIONS::CKTEXTURE_USEGLOBAL) { + saveopt = m_Context->GetGlobalImagesSaveOptions(); + } + CKBitmapProperties savefmt(GetSaveFormat()); + if (GetSaveOptions() == CK_TEXTURE_SAVEOPTIONS::CKTEXTURE_USEGLOBAL) { + savefmt = m_Context->GetGlobalImagesSaveFormat(); + } + + // filter external / original files + // the slot can not fulfill extrnal saving requirement will be written in raw data + CKDWORD slotcount = GetSlotCount(); + XContainer::XBitArray validExternalSavingSlot; + if (saveopt == CK_TEXTURE_SAVEOPTIONS::CKTEXTURE_EXTERNAL) { + for (CKDWORD i = 0; i < slotcount; ++i) { + if (GetSlotFileName(i) == nullptr) { + saveopt = CK_TEXTURE_SAVEOPTIONS::CKTEXTURE_RAWDATA; + } else { + XContainer::NSXBitArray::Set(validExternalSavingSlot, i); + } + } + } + if (saveopt == CK_TEXTURE_SAVEOPTIONS::CKTEXTURE_INCLUDEORIGINALFILE) { + for (CKDWORD i = 0; i < slotcount; ++i) { + if (file->AddSavedFile(GetSlotFileName(i))) { + XContainer::NSXBitArray::Set(validExternalSavingSlot, i); + } else { + saveopt = CK_TEXTURE_SAVEOPTIONS::CKTEXTURE_RAWDATA; + } + } + } + + // save data + if (saveopt == CK_TEXTURE_SAVEOPTIONS::CKTEXTURE_RAWDATA) { + // save as raw data + chunk->WriteIdentifier(identifiers.m_RawData); + chunk->WriteStruct(slotcount); + + VxMath::VxImageDescEx invalidDesc; + for (CKDWORD i = 0; i < slotcount; ++i) { + if (XContainer::NSXBitArray::IsSet(validExternalSavingSlot, i)) { + // if this slot can save as external, pass a invalid desc to writer + WriteRawBitmap(chunk, &invalidDesc); + } else { + // otherwise, pass the real slot data + WriteRawBitmap(chunk, GetImageDesc(i)); + } + } + + } + if (saveopt == CK_TEXTURE_SAVEOPTIONS::CKTEXTURE_IMAGEFORMAT) { + // save as special format + chunk->WriteIdentifier(identifiers.m_SpecificFormat); + chunk->WriteStruct(slotcount); + + // prepare height, width, bpp data + CKDWORD height = 0, width = 0, bpp = 32; + for (CKDWORD i = 0; i < slotcount; ++i) { + VxMath::VxImageDescEx* desc = GetImageDesc(i); + if (desc->IsValid()) { + height = desc->GetHeight(); + width = desc->GetWidth(); + break; + } + } + // write it + chunk->WriteStruct(width); + chunk->WriteStruct(height); + chunk->WriteStruct(bpp); + + // write slot one by one + for (CKDWORD i = 0; i < slotcount; ++i) { + WriteSpecificFormatBitmap(chunk, GetImageDesc(i), &savefmt); + } + + } + + // write filename + { + chunk->WriteIdentifier(identifiers.m_FileNames); + chunk->WriteStruct(slotcount); + + XContainer::XString filename; + for (CKDWORD i = 0; i < slotcount; ++i) { + XContainer::NSXString::FromCKSTRING(filename, GetSlotFileName(i)); + m_Context->GetPathManager()->GetFileName(filename); + chunk->WriteString(filename); + } + } + + return true; } #pragma endregion @@ -361,7 +453,9 @@ namespace LibCmo::CK2 { CKSTRING CKBitmapData::GetSlotFileName(CKDWORD slot) const { if (slot >= m_Slots.size()) return nullptr; - return m_Slots[slot].m_FileName.c_str(); + // return nullptr if no corresponding filename + if (m_Slots[slot].m_FileName.empty()) return nullptr; + else return m_Slots[slot].m_FileName.c_str(); } #pragma endregion diff --git a/LibCmo/CK2/CKBitmapData.hpp b/LibCmo/CK2/CKBitmapData.hpp index 938bdc2..830f5e6 100644 --- a/LibCmo/CK2/CKBitmapData.hpp +++ b/LibCmo/CK2/CKBitmapData.hpp @@ -43,7 +43,7 @@ namespace LibCmo::CK2 { static bool ReadSpecificFormatBitmap(CKStateChunk* chk, VxMath::VxImageDescEx* slot); static bool ReadRawBitmap(CKStateChunk* chk, VxMath::VxImageDescEx* slot); static bool ReadOldRawBitmap(CKStateChunk* chk, VxMath::VxImageDescEx* slot); - static void WriteSpecificFormatBitmap(CKStateChunk* chk, const VxMath::VxImageDescEx* slot); + static void WriteSpecificFormatBitmap(CKStateChunk* chk, const VxMath::VxImageDescEx* slot, const CKBitmapProperties* savefmt); static void WriteRawBitmap(CKStateChunk* chk, const VxMath::VxImageDescEx* slot); bool ReadFromChunk(CKStateChunk* chunk, CKFileVisitor* file, const CKBitmapDataReadIdentifiers& identifiers); diff --git a/LibCmo/CK2/CKDefines.hpp b/LibCmo/CK2/CKDefines.hpp index 5892e45..84eb589 100644 --- a/LibCmo/CK2/CKDefines.hpp +++ b/LibCmo/CK2/CKDefines.hpp @@ -110,6 +110,10 @@ namespace LibCmo::CK2 { return m_Data; } + CKDWORD GetSize() const { + return c_DataLen; + } + bool operator==(const CKFileExtension& rhs) const { return CKStrEqualI(m_Data, rhs.m_Data); } diff --git a/LibCmo/CK2/CKFile.hpp b/LibCmo/CK2/CKFile.hpp index ddf10a2..29a2a90 100644 --- a/LibCmo/CK2/CKFile.hpp +++ b/LibCmo/CK2/CKFile.hpp @@ -174,6 +174,8 @@ namespace LibCmo::CK2 { const CKFileObject* GetFileObjectByIndex(CKDWORD index); CKDWORD GetIndexByObjectID(CK_ID objid); + bool AddSavedFile(CKSTRING u8FileName); + protected: bool m_IsReader; CKFileReader* m_Reader; diff --git a/LibCmo/CK2/CKFileOthers.cpp b/LibCmo/CK2/CKFileOthers.cpp index 18a03cc..e1e9b6f 100644 --- a/LibCmo/CK2/CKFileOthers.cpp +++ b/LibCmo/CK2/CKFileOthers.cpp @@ -334,6 +334,14 @@ namespace LibCmo::CK2 { return finder->second; } + bool CKFileVisitor::AddSavedFile(CKSTRING u8FileName) { + if (m_IsReader) { + return false; + } else { + return m_Writer->AddSavedFile(u8FileName); + } + } + #pragma endregion } diff --git a/LibCmo/CK2/DataHandlers/CKBitmapHandler.cpp b/LibCmo/CK2/DataHandlers/CKBitmapHandler.cpp index ca8f222..1ae8be0 100644 --- a/LibCmo/CK2/DataHandlers/CKBitmapHandler.cpp +++ b/LibCmo/CK2/DataHandlers/CKBitmapHandler.cpp @@ -323,8 +323,8 @@ namespace LibCmo::CK2::DataHandlers { return nullptr; } - std::unique_ptr CKBitmapHandler::GetBitmapHandlerWrapper(const CKFileExtension& ext, const CKGUID& guid) { - return std::unique_ptr(GetBitmapHandler(ext, guid)); + CKBitmapHandlerWrapper_t CKBitmapHandler::GetBitmapHandlerWrapper(const CKFileExtension& ext, const CKGUID& guid) { + return CKBitmapHandlerWrapper_t(GetBitmapHandler(ext, guid)); } void CKBitmapHandlerDeleter::operator()(CKBitmapHandler* handler) { diff --git a/LibCmo/CK2/DataHandlers/CKBitmapHandler.hpp b/LibCmo/CK2/DataHandlers/CKBitmapHandler.hpp index bdeed1f..38f5dbd 100644 --- a/LibCmo/CK2/DataHandlers/CKBitmapHandler.hpp +++ b/LibCmo/CK2/DataHandlers/CKBitmapHandler.hpp @@ -16,6 +16,10 @@ namespace LibCmo::CK2::DataHandlers { CKBitmapHandlerDeleter(const CKBitmapHandlerDeleter&) noexcept {} void operator()(CKBitmapHandler* handler); }; + /** + * @brief The type of Auto-free wrapper of CKBitmapHandler. + */ + using CKBitmapHandlerWrapper_t = std::unique_ptr; /** * The interface about processing bitmap data between raw data and specific data. @@ -41,7 +45,7 @@ namespace LibCmo::CK2::DataHandlers { /** * @brief A auto free wrapper for GetBitmapHandler */ - static std::unique_ptr GetBitmapHandlerWrapper(const CKFileExtension& ext, const CKGUID& guid); + static CKBitmapHandlerWrapper_t GetBitmapHandlerWrapper(const CKFileExtension& ext, const CKGUID& guid); /** * @brief General CKBitmapHandler disposer * @param handler[in] The handler need to be free.