finish CKtexture writer
- finish CKTexture writer - add std::enable_if for CKStateChunk::ReadIdent&WriteIdent to limit it in enum type. - fix error function calling in CKBitmapData writer. - let CKTexture reader mor formal for mipmap. - fix CKStateChunk ReadBuffer redirect guideline. - add a stupid height and width getter for CKBitmapData to serve CKTexture using.
This commit is contained in:
parent
3195a9682f
commit
eedd9bdb55
|
@ -458,40 +458,35 @@ namespace LibCmo::CK2 {
|
|||
// save data
|
||||
if (saveopt == CK_TEXTURE_SAVEOPTIONS::CKTEXTURE_RAWDATA) {
|
||||
// save as raw data
|
||||
chunk->WriteIdentifier(identifiers.m_RawData);
|
||||
chunk->WriteIdentifierDword(identifiers.m_RawData);
|
||||
chunk->WriteStruct(slotcount);
|
||||
|
||||
VxMath::VxImageDescEx invalidDesc;
|
||||
for (CKDWORD i = 0; i < slotcount; ++i) {
|
||||
if (XContainer::NSXBitArray::IsSet(validExternalSavingSlot, i)) {
|
||||
VxMath::VxImageDescEx* thisimg = GetImageDesc(i);
|
||||
if (XContainer::NSXBitArray::IsSet(validExternalSavingSlot, i) || !thisimg->IsValid()) {
|
||||
// if this slot can save as external, pass a invalid desc to writer
|
||||
// or image is invalid, simply write it as invalid one.
|
||||
WriteRawBitmap(chunk, &invalidDesc);
|
||||
} else {
|
||||
// otherwise, pass the real slot data
|
||||
WriteRawBitmap(chunk, GetImageDesc(i));
|
||||
// do upside down first as reader done
|
||||
VxMath::VxImageDescEx upsidedown(thisimg->GetWidth(), thisimg->GetHeight());
|
||||
VxMath::VxDoBlitUpsideDown(thisimg, &upsidedown);
|
||||
WriteRawBitmap(chunk, &upsidedown);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
if (saveopt == CK_TEXTURE_SAVEOPTIONS::CKTEXTURE_IMAGEFORMAT) {
|
||||
// save as special format
|
||||
chunk->WriteIdentifier(identifiers.m_SpecificFormat);
|
||||
chunk->WriteIdentifierDword(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 width, height and bpp
|
||||
chunk->WriteStruct(GetWidth());
|
||||
chunk->WriteStruct(GetHeight());
|
||||
chunk->WriteStruct(32);
|
||||
|
||||
// write slot one by one
|
||||
for (CKDWORD i = 0; i < slotcount; ++i) {
|
||||
|
@ -502,7 +497,7 @@ namespace LibCmo::CK2 {
|
|||
|
||||
// write filename
|
||||
{
|
||||
chunk->WriteIdentifier(identifiers.m_FileNames);
|
||||
chunk->WriteIdentifierDword(identifiers.m_FileNames);
|
||||
chunk->WriteStruct(slotcount);
|
||||
|
||||
XContainer::XString filename;
|
||||
|
@ -629,6 +624,24 @@ namespace LibCmo::CK2 {
|
|||
else return m_Slots[slot].m_FileName.c_str();
|
||||
}
|
||||
|
||||
CKDWORD CKBitmapData::GetWidth() const {
|
||||
for (auto& slot : m_Slots) {
|
||||
if (slot.m_ImageData.IsValid()) {
|
||||
return slot.m_ImageData.GetWidth();
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
CKDWORD CKBitmapData::GetHeight() const {
|
||||
for (auto& slot : m_Slots) {
|
||||
if (slot.m_ImageData.IsValid()) {
|
||||
return slot.m_ImageData.GetHeight();
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
#pragma endregion
|
||||
|
||||
#pragma region Not important variable visitor
|
||||
|
|
|
@ -106,6 +106,17 @@ namespace LibCmo::CK2 {
|
|||
*/
|
||||
CKSTRING GetSlotFileName(CKDWORD slot) const;
|
||||
|
||||
/**
|
||||
* @brief Get first valid image's width.
|
||||
* @return 0 if no valid image.
|
||||
*/
|
||||
CKDWORD GetWidth() const;
|
||||
/**
|
||||
* @brief Get first valid image's height.
|
||||
* @return 0 if no valid image
|
||||
*/
|
||||
CKDWORD GetHeight() const;
|
||||
|
||||
#pragma endregion
|
||||
|
||||
#pragma region Not important funcs
|
||||
|
|
|
@ -3,6 +3,7 @@
|
|||
#include "../VTAll.hpp"
|
||||
#include <memory>
|
||||
#include <functional>
|
||||
#include <type_traits>
|
||||
|
||||
namespace LibCmo::CK2 {
|
||||
|
||||
|
@ -268,11 +269,11 @@ namespace LibCmo::CK2 {
|
|||
public:
|
||||
bool SeekIdentifierDword(CKDWORD identifier);
|
||||
bool SeekIdentifierDwordAndReturnSize(CKDWORD identifier, CKDWORD* out_size);
|
||||
template<typename TEnum>
|
||||
template<typename TEnum, std::enable_if_t<std::is_enum_v<TEnum>, int> = 0>
|
||||
inline bool SeekIdentifier(TEnum enum_v) {
|
||||
return SeekIdentifierDword(static_cast<CKDWORD>(enum_v));
|
||||
}
|
||||
template<typename TEnum>
|
||||
template<typename TEnum, std::enable_if_t<std::is_enum_v<TEnum>, int> = 0>
|
||||
inline bool SeekIdentifierAndReturnSize(TEnum enum_v, CKDWORD* out_size) {
|
||||
return SeekIdentifierDwordAndReturnSize(static_cast<CKDWORD>(enum_v), out_size);
|
||||
}
|
||||
|
@ -403,18 +404,21 @@ namespace LibCmo::CK2 {
|
|||
/*
|
||||
Buffer related function implements:
|
||||
|
||||
ReadBuffer(void**) Read Byte based size. -> ReadAndCopyBuffer(void**, CKDWORD*)
|
||||
ReadAndFillBuffer(int, void*) User give Byte based size. -> ReadBuffer(const void**, CKDWORD)
|
||||
ReadAndFillBuffer(void*) Read Byte based size. -> ReadBuffer(const void**, CKDWORD*)
|
||||
ReadAndFillBuffer_LEndian(int, void*) User give Byte based size. -> ReadBuffer(const void**, CKDWORD)
|
||||
ReadAndFillBuffer_LEndian(void*) Read Byte based size. -> ReadBuffer(const void**, CKDWORD*)
|
||||
ReadAndFillBuffer_LEndian16(int, void*) User give Byte based size. -> ReadBuffer(const void**, CKDWORD)
|
||||
ReadAndFillBuffer_LEndian16(void*) Read Byte based size. -> ReadBuffer(const void**, CKDWORD*)
|
||||
ReadBuffer(void**) Read Byte based size. -> ReadBuffer(void**, CKDWORD*)
|
||||
ReadAndFillBuffer(int, void*) User give Byte based size. -> ReadAndFillBuffer(const void*, CKDWORD)
|
||||
ReadAndFillBuffer(void*) Read Byte based size. -> ReadAndFillBuffer(const void*)
|
||||
ReadAndFillBuffer_LEndian(int, void*) User give Byte based size. -> ReadAndFillBuffer(const void*, CKDWORD)
|
||||
ReadAndFillBuffer_LEndian(void*) Read Byte based size. -> ReadAndFillBuffer(const void*)
|
||||
ReadAndFillBuffer_LEndian16(int, void*) User give Byte based size. -> ReadAndFillBuffer(const void*, CKDWORD)
|
||||
ReadAndFillBuffer_LEndian16(void*) Read Byte based size. -> ReadAndFillBuffer(const void*)
|
||||
*/
|
||||
|
||||
/**
|
||||
* @brief Read buffer and copy it.
|
||||
*
|
||||
* The size of buffer will be read from CKStateChunk internally.
|
||||
* It mean the read buffer must be written by WriteBuffer().
|
||||
*
|
||||
* The copied buffer and the size of buffer will be returned to caller.
|
||||
* Caller should free the buffer by calling CKStateChunk::DeleteBuffer(void*).
|
||||
*
|
||||
|
@ -454,6 +458,7 @@ namespace LibCmo::CK2 {
|
|||
* @brief Read buffer and fill user struct.
|
||||
*
|
||||
* The size of buffer will be read from CKStateChunk internally and return to caller.
|
||||
* It mean the read buffer must be written by WriteBuffer().
|
||||
*
|
||||
* @param pData[out] The pointer holding the data.
|
||||
* @return True if success.
|
||||
|
@ -467,6 +472,7 @@ namespace LibCmo::CK2 {
|
|||
* @brief Read buffer and fill user struct.
|
||||
*
|
||||
* The size of buffer is provided by user.
|
||||
* It mean the read buffer must be written by WriteBufferNoSize().
|
||||
*
|
||||
* @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
|
||||
|
@ -553,7 +559,7 @@ namespace LibCmo::CK2 {
|
|||
|
||||
public:
|
||||
bool WriteIdentifierDword(CKDWORD identifier);
|
||||
template<typename TEnum>
|
||||
template<typename TEnum, std::enable_if_t<std::is_enum_v<TEnum>, int> = 0>
|
||||
inline bool WriteIdentifier(TEnum enum_v) {
|
||||
return WriteIdentifierDword(static_cast<CKDWORD>(enum_v));
|
||||
}
|
||||
|
|
|
@ -22,6 +22,11 @@ namespace LibCmo::CK2 {
|
|||
|
||||
// force chunk version
|
||||
this->m_ChunkVersion = CK_STATECHUNK_CHUNKVERSION::CHUNK_VERSION4;
|
||||
// set data version
|
||||
// MARK: in virtools impl, this statement is written in CKObject::Save
|
||||
// and data version is delivered by merging CKStateChunk.
|
||||
// but we do not use that saving strategy, so we init data version in here.
|
||||
this->m_DataVersion = CK_STATECHUNK_DATAVERSION::CHUNK_DEV_2_1;
|
||||
|
||||
// switch status
|
||||
this->m_Parser.m_Status = CKStateChunkStatus::WRITE;
|
||||
|
|
|
@ -70,6 +70,129 @@ namespace LibCmo::CK2::ObjImpls {
|
|||
bool suc = CKBeObject::Save(chunk, file, flags);
|
||||
if (!suc) return false;
|
||||
|
||||
// save base image
|
||||
suc = m_ImageHost.DumpToChunk(chunk, file, CKBitmapDataWriteIdentifiers {
|
||||
.m_SpecificFormat = static_cast<CKDWORD>(CK_STATESAVEFLAGS_TEXTURE::CK_STATESAVE_TEXREADER),
|
||||
.m_RawData = static_cast<CKDWORD>(CK_STATESAVEFLAGS_TEXTURE::CK_STATESAVE_TEXCOMPRESSED),
|
||||
.m_FileNames = static_cast<CKDWORD>(CK_STATESAVEFLAGS_TEXTURE::CK_STATESAVE_TEXFILENAMES),
|
||||
.m_MovieFileName = static_cast<CKDWORD>(CK_STATESAVEFLAGS_TEXTURE::CK_STATESAVE_TEXAVIFILENAME)
|
||||
});
|
||||
if (!suc) return false;
|
||||
|
||||
// write main properties
|
||||
{
|
||||
// write ident
|
||||
chunk->WriteIdentifier(CK_STATESAVEFLAGS_TEXTURE::CK_STATESAVE_OLDTEXONLY);
|
||||
|
||||
// prepare mix data. see Read for more info about the struct of this mix data
|
||||
CKDWORD mixdata = 0;
|
||||
// save options
|
||||
mixdata &= static_cast<CKDWORD>(m_ImageHost.GetSaveOptions()) & 0xFF;
|
||||
mixdata <<= 8;
|
||||
// mix flags
|
||||
CKDWORD mixflags = 0;
|
||||
if (m_ImageHost.IsTransparent()) {
|
||||
mixflags &= 0x1;
|
||||
}
|
||||
if (m_VideoFormat != VxMath::VX_PIXELFORMAT::UNKNOWN_PF) {
|
||||
mixflags &= 0x2;
|
||||
}
|
||||
if (m_ImageHost.IsCubeMap()) {
|
||||
mixflags &= 0x4;
|
||||
}
|
||||
mixdata &= mixflags & 0xFF;
|
||||
mixdata <<= 8;
|
||||
// mipmap
|
||||
mixdata &= (IsUseMipmap() ? 0xFF : 0);
|
||||
|
||||
// write mix data
|
||||
chunk->WriteStruct(mixdata);
|
||||
|
||||
// transparent color
|
||||
chunk->WriteStruct(m_ImageHost.GetTransparentColor());
|
||||
// current slot
|
||||
if (m_ImageHost.GetSlotCount() > 1) {
|
||||
chunk->WriteStruct(m_ImageHost.GetCurrentSlot());
|
||||
}
|
||||
// video fmt
|
||||
if (m_VideoFormat != VxMath::VX_PIXELFORMAT::UNKNOWN_PF) {
|
||||
chunk->WriteStruct(m_VideoFormat);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// mipmap
|
||||
if (GetMipmapLevel() != 0) {
|
||||
chunk->WriteIdentifier(CK_STATESAVEFLAGS_TEXTURE::CK_STATESAVE_USERMIPMAP);
|
||||
|
||||
// write mipmap level
|
||||
chunk->WriteStruct(GetMipmapLevel());
|
||||
|
||||
// write data
|
||||
for (auto& level : m_MipmapImages) {
|
||||
if (level.IsValid()) {
|
||||
// do upside down and write
|
||||
VxMath::VxImageDescEx upsidedown(level.GetWidth(), level.GetHeight());
|
||||
VxMath::VxDoBlitUpsideDown(&level, &upsidedown);
|
||||
CKBitmapData::WriteRawBitmap(chunk, &upsidedown);
|
||||
} else {
|
||||
// write it directly
|
||||
CKBitmapData::WriteRawBitmap(chunk, &level);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// pick threshold
|
||||
if (m_ImageHost.GetPickThreshold() != 0) {
|
||||
chunk->WriteIdentifier(CK_STATESAVEFLAGS_TEXTURE::CK_STATESAVE_PICKTHRESHOLD);
|
||||
chunk->WriteStruct(m_ImageHost.GetPickThreshold());
|
||||
}
|
||||
|
||||
// bitmap properties
|
||||
{
|
||||
chunk->WriteIdentifier(CK_STATESAVEFLAGS_TEXTURE::CK_STATESAVE_TEXSAVEFORMAT);
|
||||
|
||||
// prepare a fake one
|
||||
FakeBitmapProperties props;
|
||||
const CKBitmapProperties& realprops = m_ImageHost.GetSaveFormat();
|
||||
|
||||
// setup fake self
|
||||
props.m_Size = CKSizeof(props);
|
||||
props.m_Data = 6172;
|
||||
|
||||
// setup fake VxImageDescEx
|
||||
props.m_Format.Size = CKSizeof(props.m_Format);
|
||||
props.m_Format.Flags = static_cast<CKDWORD>(VxMath::VX_PIXELFORMAT::_32_ARGB8888);
|
||||
props.m_Format.Width = m_ImageHost.GetWidth();
|
||||
props.m_Format.Height = m_ImageHost.GetHeight();
|
||||
props.m_Format.BytesPerLine = VxMath::VxImageDescEx::PixelSize * props.m_Format.Height * props.m_Format.Width;
|
||||
props.m_Format.BitsPerPixel = 32;
|
||||
|
||||
props.m_Format.RedMask = 0x00FF0000;
|
||||
props.m_Format.GreenMask = 0x0000FF00;
|
||||
props.m_Format.BlueMask = 0x000000FF;
|
||||
props.m_Format.AlphaMask = 0xFF000000;
|
||||
|
||||
props.m_Format.BytesPerColorEntry = 0;
|
||||
props.m_Format.ColorMapEntries = 0;
|
||||
|
||||
props.m_Format.ColorMap = 0;
|
||||
props.m_Format.Image = 0;
|
||||
|
||||
// setup ext and guid
|
||||
props.m_ReaderGuid.d1 = realprops.m_ReaderGuid.d1;
|
||||
props.m_ReaderGuid.d2 = realprops.m_ReaderGuid.d2;
|
||||
std::memcpy(
|
||||
props.m_Ext.m_Data,
|
||||
realprops.m_Ext.GetExt(),
|
||||
std::min(CKSizeof(props.m_Ext.m_Data), realprops.m_Ext.GetSize())
|
||||
);
|
||||
|
||||
// write fake one
|
||||
chunk->WriteBuffer(&props, CKSizeof(props));
|
||||
}
|
||||
|
||||
chunk->SetClassId(CK_CLASSID::CKCID_TEXTURE);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -104,7 +227,7 @@ namespace LibCmo::CK2::ObjImpls {
|
|||
CKDWORD mixdata;
|
||||
chunk->ReadStruct(mixdata);
|
||||
// set mipmap
|
||||
m_UseMipMap = (mixdata & 0xFF);
|
||||
UseMipmap(mixdata & 0xFF);
|
||||
mixdata >>= 8;
|
||||
// mix flags
|
||||
CKDWORD mixflags = mixdata & 0xFF;
|
||||
|
@ -159,7 +282,7 @@ namespace LibCmo::CK2::ObjImpls {
|
|||
if (chunk->SeekIdentifier(CK_STATESAVEFLAGS_TEXTURE::CK_STATESAVE_USERMIPMAP)) {
|
||||
CKDWORD mipmapCount;
|
||||
chunk->ReadStruct(mipmapCount);
|
||||
m_MipmapImages.resize(mipmapCount);
|
||||
SetMipmapLevel(mipmapCount);
|
||||
|
||||
for (CKDWORD i = 0; i < mipmapCount; ++i) {
|
||||
VxMath::VxImageDescEx cache;
|
||||
|
|
|
@ -1,69 +0,0 @@
|
|||
# Visual Studio 生成了具有 C++ 设置的 .editorconfig 文件。
|
||||
root = true
|
||||
|
||||
[*.{c++,cc,cpp,cppm,cxx,h,h++,hh,hpp,hxx,inl,ipp,ixx,tlh,tli}]
|
||||
|
||||
# Visual C++ 代码样式设置
|
||||
|
||||
cpp_generate_documentation_comments = doxygen_slash_star
|
||||
|
||||
# Visual C++ 格式设置
|
||||
|
||||
cpp_indent_braces = false
|
||||
cpp_indent_multi_line_relative_to = statement_begin
|
||||
cpp_indent_within_parentheses = indent
|
||||
cpp_indent_preserve_within_parentheses = true
|
||||
cpp_indent_case_contents = true
|
||||
cpp_indent_case_labels = true
|
||||
cpp_indent_case_contents_when_block = false
|
||||
cpp_indent_lambda_braces_when_parameter = true
|
||||
cpp_indent_goto_labels = one_left
|
||||
cpp_indent_preprocessor = leftmost_column
|
||||
cpp_indent_access_specifiers = false
|
||||
cpp_indent_namespace_contents = true
|
||||
cpp_indent_preserve_comments = false
|
||||
cpp_new_line_before_open_brace_namespace = same_line
|
||||
cpp_new_line_before_open_brace_type = same_line
|
||||
cpp_new_line_before_open_brace_function = same_line
|
||||
cpp_new_line_before_open_brace_block = same_line
|
||||
cpp_new_line_before_open_brace_lambda = same_line
|
||||
cpp_new_line_scope_braces_on_separate_lines = true
|
||||
cpp_new_line_close_brace_same_line_empty_type = true
|
||||
cpp_new_line_close_brace_same_line_empty_function = true
|
||||
cpp_new_line_before_catch = false
|
||||
cpp_new_line_before_else = false
|
||||
cpp_new_line_before_while_in_do_while = false
|
||||
cpp_space_before_function_open_parenthesis = remove
|
||||
cpp_space_within_parameter_list_parentheses = false
|
||||
cpp_space_between_empty_parameter_list_parentheses = false
|
||||
cpp_space_after_keywords_in_control_flow_statements = true
|
||||
cpp_space_within_control_flow_statement_parentheses = false
|
||||
cpp_space_before_lambda_open_parenthesis = false
|
||||
cpp_space_within_cast_parentheses = false
|
||||
cpp_space_after_cast_close_parenthesis = false
|
||||
cpp_space_within_expression_parentheses = false
|
||||
cpp_space_before_block_open_brace = true
|
||||
cpp_space_between_empty_braces = false
|
||||
cpp_space_before_initializer_list_open_brace = true
|
||||
cpp_space_within_initializer_list_braces = true
|
||||
cpp_space_preserve_in_initializer_list = true
|
||||
cpp_space_before_open_square_bracket = false
|
||||
cpp_space_within_square_brackets = false
|
||||
cpp_space_before_empty_square_brackets = false
|
||||
cpp_space_between_empty_square_brackets = false
|
||||
cpp_space_group_square_brackets = true
|
||||
cpp_space_within_lambda_brackets = false
|
||||
cpp_space_between_empty_lambda_brackets = false
|
||||
cpp_space_before_comma = false
|
||||
cpp_space_after_comma = true
|
||||
cpp_space_remove_around_member_operators = true
|
||||
cpp_space_before_inheritance_colon = true
|
||||
cpp_space_before_constructor_colon = true
|
||||
cpp_space_remove_before_semicolon = true
|
||||
cpp_space_after_semicolon = true
|
||||
cpp_space_remove_around_unary_operator = true
|
||||
cpp_space_around_binary_operator = insert
|
||||
cpp_space_around_assignment_operator = insert
|
||||
cpp_space_pointer_reference_alignment = left
|
||||
cpp_space_around_ternary_operator = insert
|
||||
cpp_wrap_preserve_blocks = one_liners
|
Loading…
Reference in New Issue
Block a user