2023-09-21 13:47:30 +08:00
|
|
|
#include "BMap.hpp"
|
|
|
|
|
|
|
|
namespace BMap {
|
|
|
|
|
|
|
|
#pragma region BMMeshTransition
|
|
|
|
|
|
|
|
BMMeshTransition::TransitionVertex::TransitionVertex(
|
|
|
|
const LibCmo::VxMath::VxVector3& vec,
|
|
|
|
const LibCmo::VxMath::VxVector3& norm,
|
|
|
|
const LibCmo::VxMath::VxVector2& uv) :
|
|
|
|
m_Vertex(vec), m_Norm(norm), m_UV(uv) {}
|
|
|
|
|
2023-09-23 15:55:57 +08:00
|
|
|
BMMeshTransition::TransitionFace::TransitionFace(LibCmo::CKDWORD _i1, LibCmo::CKDWORD _i2, LibCmo::CKDWORD _i3, LibCmo::CKDWORD mtl_id) :
|
2023-09-21 13:47:30 +08:00
|
|
|
m_Idx1(_i1), m_Idx2(_i2), m_Idx3(_i3), m_MtlSlotIdx(mtl_id) {}
|
|
|
|
|
|
|
|
bool BMMeshTransition::TransitionVertexCompare::operator()(const TransitionVertex& lhs, const TransitionVertex& rhs) const {
|
|
|
|
if (auto cmp = std::memcmp(&lhs.m_Vertex, &rhs.m_Vertex, sizeof(LibCmo::VxMath::VxVector3)); cmp != 0) return cmp < 0;
|
|
|
|
if (auto cmp = std::memcmp(&lhs.m_Norm, &rhs.m_Norm, sizeof(LibCmo::VxMath::VxVector3)); cmp != 0) return cmp < 0;
|
|
|
|
return std::memcmp(&lhs.m_UV, &rhs.m_UV, sizeof(LibCmo::VxMath::VxVector2)) < 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
BMMeshTransition::BMMeshTransition() :
|
|
|
|
m_IsVertexOK(false), m_IsNormalOK(false), m_IsUVOK(false), m_IsFaceOK(false), m_IsMtlSlotOK(false),
|
|
|
|
m_IsParsed(false),
|
|
|
|
m_Vertexs(), m_Normals(), m_UVs(),
|
|
|
|
m_MtlSlots(),
|
|
|
|
m_FaceVertexs(), m_FaceNormals(), m_FaceUVs(), m_FaceMtlSlotIdxs(),
|
|
|
|
m_ProcVertexs(), m_ProcFaces(), m_ProcDupRemover() {}
|
|
|
|
|
|
|
|
BMMeshTransition::~BMMeshTransition() {}
|
2023-10-03 21:33:00 +08:00
|
|
|
|
|
|
|
bool BMMeshTransition::PrepareVertexCount(LibCmo::CKDWORD count) {
|
|
|
|
if (m_IsParsed) return false;
|
2023-09-21 13:47:30 +08:00
|
|
|
m_Vertexs.resize(count);
|
|
|
|
m_IsVertexOK = true;
|
2023-10-03 21:33:00 +08:00
|
|
|
return true;
|
2023-09-21 13:47:30 +08:00
|
|
|
}
|
|
|
|
|
2023-09-23 15:55:57 +08:00
|
|
|
LibCmo::VxMath::VxVector3* BMMeshTransition::PrepareVertex() {
|
|
|
|
if (m_IsParsed || !m_IsVertexOK) return nullptr;
|
|
|
|
return m_Vertexs.data();
|
2023-09-21 13:47:30 +08:00
|
|
|
}
|
|
|
|
|
2023-10-03 21:33:00 +08:00
|
|
|
bool BMMeshTransition::PrepareNormalCount(LibCmo::CKDWORD count) {
|
|
|
|
if (m_IsParsed) return false;
|
2023-09-21 13:47:30 +08:00
|
|
|
m_Normals.resize(count);
|
|
|
|
m_IsNormalOK = true;
|
2023-10-03 21:33:00 +08:00
|
|
|
return true;
|
2023-09-21 13:47:30 +08:00
|
|
|
}
|
|
|
|
|
2023-09-23 15:55:57 +08:00
|
|
|
LibCmo::VxMath::VxVector3* BMMeshTransition::PrepareNormal() {
|
|
|
|
if (m_IsParsed || !m_IsNormalOK) return nullptr;
|
|
|
|
return m_Normals.data();
|
2023-09-21 13:47:30 +08:00
|
|
|
}
|
|
|
|
|
2023-10-03 21:33:00 +08:00
|
|
|
bool BMMeshTransition::PrepareUVCount(LibCmo::CKDWORD count) {
|
|
|
|
if (m_IsParsed) return false;
|
2023-09-21 13:47:30 +08:00
|
|
|
m_UVs.resize(count);
|
|
|
|
m_IsUVOK = true;
|
2023-10-03 21:33:00 +08:00
|
|
|
return true;
|
2023-09-21 13:47:30 +08:00
|
|
|
}
|
|
|
|
|
2023-09-23 15:55:57 +08:00
|
|
|
LibCmo::VxMath::VxVector2* BMMeshTransition::PrepareUV() {
|
|
|
|
if (m_IsParsed || !m_IsUVOK) return nullptr;
|
|
|
|
return m_UVs.data();
|
2023-09-21 13:47:30 +08:00
|
|
|
}
|
|
|
|
|
2023-10-03 21:33:00 +08:00
|
|
|
bool BMMeshTransition::PrepareMtlSlotCount(LibCmo::CKDWORD count) {
|
|
|
|
if (m_IsParsed) return false;
|
2023-10-05 21:08:58 +08:00
|
|
|
m_MtlSlots.resize(count, 0);
|
2023-09-21 13:47:30 +08:00
|
|
|
m_IsMtlSlotOK = true;
|
2023-10-03 21:33:00 +08:00
|
|
|
return true;
|
2023-09-21 13:47:30 +08:00
|
|
|
}
|
|
|
|
|
2023-10-05 21:08:58 +08:00
|
|
|
LibCmo::CK2::CK_ID* BMMeshTransition::PrepareMtlSlot() {
|
2023-09-23 15:55:57 +08:00
|
|
|
if (m_IsParsed || !m_IsMtlSlotOK) return nullptr;
|
|
|
|
return m_MtlSlots.data();
|
2023-09-21 13:47:30 +08:00
|
|
|
}
|
|
|
|
|
2023-10-03 21:33:00 +08:00
|
|
|
bool BMMeshTransition::PrepareFaceCount(LibCmo::CKDWORD count) {
|
|
|
|
if (m_IsParsed) return false;
|
2023-09-21 13:47:30 +08:00
|
|
|
m_FaceVertexs.resize(count * 3);
|
|
|
|
m_FaceNormals.resize(count * 3);
|
|
|
|
m_FaceUVs.resize(count * 3);
|
|
|
|
m_FaceMtlSlotIdxs.resize(count);
|
|
|
|
m_IsFaceOK = true;
|
2023-10-03 21:33:00 +08:00
|
|
|
return true;
|
2023-09-21 13:47:30 +08:00
|
|
|
}
|
|
|
|
|
2023-09-23 15:55:57 +08:00
|
|
|
LibCmo::CKDWORD* BMMeshTransition::PrepareFaceVertexIndices() {
|
|
|
|
if (m_IsParsed || !m_IsFaceOK) return nullptr;
|
|
|
|
return m_FaceVertexs.data();
|
2023-09-21 13:47:30 +08:00
|
|
|
}
|
|
|
|
|
2023-09-23 15:55:57 +08:00
|
|
|
LibCmo::CKDWORD* BMMeshTransition::PrepareFaceNormalIndices() {
|
|
|
|
if (m_IsParsed || !m_IsFaceOK) return nullptr;
|
2023-12-01 23:31:09 +08:00
|
|
|
return m_FaceNormals.data();
|
2023-09-21 13:47:30 +08:00
|
|
|
}
|
|
|
|
|
2023-09-23 15:55:57 +08:00
|
|
|
LibCmo::CKDWORD* BMMeshTransition::PrepareFaceUVIndices() {
|
|
|
|
if (m_IsParsed || !m_IsFaceOK) return nullptr;
|
2023-12-01 23:31:09 +08:00
|
|
|
return m_FaceUVs.data();
|
2023-09-21 13:47:30 +08:00
|
|
|
}
|
|
|
|
|
2023-09-23 15:55:57 +08:00
|
|
|
LibCmo::CKDWORD* BMMeshTransition::PrepareFaceMtlSlot() {
|
|
|
|
if (m_IsParsed || !m_IsFaceOK) return nullptr;
|
2023-12-01 23:31:09 +08:00
|
|
|
return m_FaceMtlSlotIdxs.data();
|
2023-09-21 13:47:30 +08:00
|
|
|
}
|
|
|
|
|
2023-10-30 10:25:31 +08:00
|
|
|
bool BMMeshTransition::Parse(BMFile* bmfile, LibCmo::CK2::CK_ID mesh_id) {
|
|
|
|
// check basic status
|
|
|
|
if (m_IsParsed || bmfile == nullptr) return false;
|
2023-09-21 13:47:30 +08:00
|
|
|
if (!m_IsVertexOK || !m_IsNormalOK || !m_IsUVOK || !m_IsFaceOK || !m_IsMtlSlotOK) return false;
|
2023-10-30 10:25:31 +08:00
|
|
|
// check pointer assign
|
|
|
|
LibCmo::CK2::ObjImpls::CKObject* writing_mesh = bmfile->GetObjectPtr(mesh_id);
|
|
|
|
if (writing_mesh == nullptr || writing_mesh->GetClassID() != LibCmo::CK2::CK_CLASSID::CKCID_MESH) return false;
|
2023-09-21 13:47:30 +08:00
|
|
|
|
2023-09-23 15:55:57 +08:00
|
|
|
// do parse
|
2023-10-30 10:25:31 +08:00
|
|
|
m_IsParsed = true;
|
2023-09-21 13:47:30 +08:00
|
|
|
DoRealParse();
|
2023-09-23 16:25:26 +08:00
|
|
|
|
2023-09-23 15:55:57 +08:00
|
|
|
// check vertex overflow
|
|
|
|
if (m_ProcVertexs.size() > std::numeric_limits<LibCmo::CKWORD>::max()) {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
// check mtl slot overflow
|
|
|
|
if (m_MtlSlots.size() > std::numeric_limits<LibCmo::CKWORD>::max()) {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
// apply to mesh
|
2023-10-30 10:25:31 +08:00
|
|
|
ApplyToMesh(bmfile, static_cast<LibCmo::CK2::ObjImpls::CKMesh*>(writing_mesh));
|
2023-09-21 13:47:30 +08:00
|
|
|
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
void BMMeshTransition::DoRealParse() {
|
|
|
|
// reserve vector to prevent extra mem alloc
|
|
|
|
// use the most bad situation to reserve
|
|
|
|
size_t face_size = m_FaceMtlSlotIdxs.size();
|
|
|
|
m_ProcVertexs.reserve(face_size * 3);
|
|
|
|
m_ProcFaces.reserve(face_size);
|
|
|
|
|
|
|
|
// iterate face
|
|
|
|
for (size_t faceid = 0; faceid < face_size; ++faceid) {
|
2023-10-30 10:25:31 +08:00
|
|
|
LibCmo::CKDWORD idx[3] { 0, 0, 0 };
|
2023-09-21 13:47:30 +08:00
|
|
|
for (int j = 0; j < 3; ++j) {
|
|
|
|
// create one first
|
|
|
|
TransitionVertex tvec(
|
|
|
|
m_Vertexs[m_FaceVertexs[faceid * 3 + j]],
|
2023-12-01 23:31:09 +08:00
|
|
|
m_Normals[m_FaceNormals[faceid * 3 + j]],
|
|
|
|
m_UVs[m_FaceUVs[faceid * 3 + j]]
|
2023-09-21 13:47:30 +08:00
|
|
|
);
|
|
|
|
|
|
|
|
// try insert it
|
2023-09-23 15:55:57 +08:00
|
|
|
auto insert_result = m_ProcDupRemover.try_emplace(tvec, static_cast<LibCmo::CKDWORD>(m_ProcVertexs.size()));
|
2023-09-21 13:47:30 +08:00
|
|
|
// get the new inserted index or existed index.
|
|
|
|
idx[j] = insert_result.first->second;
|
|
|
|
// if insert successfully, append to proc vertexs
|
|
|
|
if (insert_result.second) {
|
|
|
|
m_ProcVertexs.emplace_back(tvec);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// create face
|
|
|
|
m_ProcFaces.emplace_back(idx[0], idx[1], idx[2], m_FaceMtlSlotIdxs[faceid]);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2023-10-30 10:25:31 +08:00
|
|
|
void BMMeshTransition::ApplyToMesh(BMFile* bmfile, LibCmo::CK2::ObjImpls::CKMesh* write_into_mesh) {
|
2023-09-23 15:55:57 +08:00
|
|
|
LibCmo::CKDWORD vec_count = static_cast<LibCmo::CKDWORD>(m_ProcVertexs.size()),
|
|
|
|
face_count = static_cast<LibCmo::CKDWORD>(m_ProcFaces.size()),
|
|
|
|
mtl_count = static_cast<LibCmo::CKDWORD>(m_MtlSlots.size());
|
|
|
|
write_into_mesh->CleanMesh();
|
|
|
|
|
|
|
|
// write vertex
|
|
|
|
write_into_mesh->SetVertexCount(vec_count);
|
|
|
|
LibCmo::VxMath::VxCopyStructure(
|
|
|
|
vec_count,
|
|
|
|
write_into_mesh->GetVertexPositions(),
|
|
|
|
CKSizeof(LibCmo::VxMath::VxVector3),
|
|
|
|
CKSizeof(LibCmo::VxMath::VxVector3),
|
|
|
|
&m_ProcVertexs.data()->m_Vertex,
|
|
|
|
CKSizeof(TransitionVertex)
|
|
|
|
);
|
|
|
|
LibCmo::VxMath::VxCopyStructure(
|
|
|
|
vec_count,
|
|
|
|
write_into_mesh->GetVertexNormals(),
|
|
|
|
CKSizeof(LibCmo::VxMath::VxVector3),
|
|
|
|
CKSizeof(LibCmo::VxMath::VxVector3),
|
|
|
|
&m_ProcVertexs.data()->m_Norm,
|
|
|
|
CKSizeof(TransitionVertex)
|
|
|
|
);
|
|
|
|
LibCmo::VxMath::VxCopyStructure(
|
|
|
|
vec_count,
|
|
|
|
write_into_mesh->GetVertexUVs(),
|
|
|
|
CKSizeof(LibCmo::VxMath::VxVector2),
|
|
|
|
CKSizeof(LibCmo::VxMath::VxVector2),
|
|
|
|
&m_ProcVertexs.data()->m_UV,
|
|
|
|
CKSizeof(TransitionVertex)
|
|
|
|
);
|
|
|
|
|
|
|
|
// write face
|
|
|
|
write_into_mesh->SetFaceCount(face_count);
|
|
|
|
auto pIndices = write_into_mesh->GetFaceIndices();
|
|
|
|
auto pMtlIdx = write_into_mesh->GetFaceMaterialSlotIndexs();
|
|
|
|
for (LibCmo::CKDWORD i = 0; i < face_count; ++i) {
|
|
|
|
*(pIndices++) = static_cast<LibCmo::CKWORD>(m_ProcFaces[i].m_Idx1);
|
|
|
|
*(pIndices++) = static_cast<LibCmo::CKWORD>(m_ProcFaces[i].m_Idx2);
|
|
|
|
*(pIndices++) = static_cast<LibCmo::CKWORD>(m_ProcFaces[i].m_Idx3);
|
|
|
|
|
|
|
|
*(pMtlIdx++) = static_cast<LibCmo::CKWORD>(m_ProcFaces[i].m_MtlSlotIdx);
|
|
|
|
}
|
|
|
|
|
|
|
|
// set mtl slot
|
|
|
|
write_into_mesh->SetMaterialSlotCount(mtl_count);
|
2023-10-05 21:08:58 +08:00
|
|
|
LibCmo::CK2::ObjImpls::CKMaterial** pMtlSlot = write_into_mesh->GetMaterialSlots();
|
2023-09-23 15:55:57 +08:00
|
|
|
for (LibCmo::CKDWORD i = 0; i < mtl_count; ++i) {
|
2023-10-05 21:08:58 +08:00
|
|
|
// convert id to CKMaterial* and check its type
|
2023-10-30 10:25:31 +08:00
|
|
|
LibCmo::CK2::ObjImpls::CKObject* mtlptr = bmfile->GetObjectPtr(m_MtlSlots[i]);
|
|
|
|
if (mtlptr != nullptr && mtlptr->GetClassID() == LibCmo::CK2::CK_CLASSID::CKCID_MATERIAL) {
|
2023-10-05 21:08:58 +08:00
|
|
|
*(pMtlSlot++) = static_cast<LibCmo::CK2::ObjImpls::CKMaterial*>(mtlptr);
|
|
|
|
} else {
|
|
|
|
*(pMtlSlot++) = nullptr;
|
|
|
|
}
|
2023-09-23 15:55:57 +08:00
|
|
|
}
|
2023-09-21 13:47:30 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
#pragma endregion
|
|
|
|
|
2023-09-23 15:55:57 +08:00
|
|
|
#pragma region BMfile
|
|
|
|
|
2023-11-15 21:47:58 +08:00
|
|
|
BMFile::BMFile(LibCmo::CKSTRING temp_folder, LibCmo::CKSTRING texture_folder, NakedOutputCallback raw_callback, LibCmo::CKDWORD encoding_count, LibCmo::CKSTRING* encodings, bool is_loader) :
|
2023-10-30 10:25:31 +08:00
|
|
|
m_IsInitError(false), m_IsLoader(is_loader), m_HasLoaded(false), m_HasSaved(false), m_Context(nullptr) {
|
2023-09-23 16:25:26 +08:00
|
|
|
m_Context = new LibCmo::CK2::CKContext();
|
2023-11-15 21:47:58 +08:00
|
|
|
// binding callback with lambda wrapper.
|
|
|
|
// check whether callback is nullptr.
|
|
|
|
m_IsInitError = m_IsInitError || (raw_callback == nullptr);
|
|
|
|
if (raw_callback != nullptr) {
|
|
|
|
m_Context->SetOutputCallback([raw_callback](LibCmo::CKSTRING strl) -> void {
|
|
|
|
raw_callback(strl);
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
2023-09-23 16:25:26 +08:00
|
|
|
// set temp folder and texture folder
|
|
|
|
auto pm = m_Context->GetPathManager();
|
2023-10-30 10:25:31 +08:00
|
|
|
m_IsInitError = m_IsInitError || !pm->AddPath(texture_folder);
|
|
|
|
m_IsInitError = m_IsInitError || !pm->SetTempFolder(temp_folder);
|
2023-11-15 21:47:58 +08:00
|
|
|
|
2023-09-23 16:25:26 +08:00
|
|
|
// set encoding
|
|
|
|
LibCmo::XContainer::XArray<LibCmo::XContainer::XString> cache;
|
|
|
|
for (LibCmo::CKDWORD i = 0; i < encoding_count; ++i) {
|
|
|
|
if (encodings[i] != nullptr)
|
|
|
|
cache.emplace_back(encodings[i]);
|
|
|
|
}
|
|
|
|
m_Context->SetEncoding(cache);
|
2023-10-29 10:27:35 +08:00
|
|
|
|
2023-10-02 20:54:31 +08:00
|
|
|
// set default texture save mode is external
|
|
|
|
m_Context->SetGlobalImagesSaveOptions(LibCmo::CK2::CK_TEXTURE_SAVEOPTIONS::CKTEXTURE_EXTERNAL);
|
2023-10-29 10:27:35 +08:00
|
|
|
// set default file write mode is whole compressed
|
|
|
|
m_Context->SetFileWriteMode(LibCmo::CK2::CK_FILE_WRITEMODE::CKFILE_WHOLECOMPRESSED);
|
2023-09-23 16:25:26 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
BMFile::~BMFile() {
|
|
|
|
delete m_Context;
|
2023-09-23 15:55:57 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
bool BMFile::Load(LibCmo::CKSTRING filename) {
|
2023-10-30 10:25:31 +08:00
|
|
|
if (!CanExecLoad()) return false;
|
2023-10-03 21:33:00 +08:00
|
|
|
|
2023-10-29 10:27:35 +08:00
|
|
|
// create temp ckfile and load
|
|
|
|
LibCmo::CK2::CKFileReader reader(m_Context);
|
|
|
|
LibCmo::CK2::CKERROR err = reader.DeepLoad(filename);
|
|
|
|
|
|
|
|
// detect error
|
|
|
|
if (err != LibCmo::CK2::CKERROR::CKERR_OK) {
|
|
|
|
// failed. clear document and return false
|
|
|
|
m_Context->ClearAll();
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
// sync data list to our list
|
|
|
|
m_ObjGroups.clear();
|
|
|
|
m_Obj3dObjects.clear();
|
|
|
|
m_ObjMeshs.clear();
|
|
|
|
m_ObjMaterials.clear();
|
|
|
|
m_ObjTextures.clear();
|
|
|
|
for (const auto& fileobj : reader.GetFileObjects()) {
|
|
|
|
if (fileobj.ObjPtr == nullptr) continue;
|
|
|
|
|
|
|
|
switch (fileobj.ObjectCid) {
|
|
|
|
case LibCmo::CK2::CK_CLASSID::CKCID_GROUP:
|
|
|
|
m_ObjGroups.emplace_back(fileobj.CreatedObjectId);
|
|
|
|
break;
|
|
|
|
case LibCmo::CK2::CK_CLASSID::CKCID_3DOBJECT:
|
|
|
|
m_Obj3dObjects.emplace_back(fileobj.CreatedObjectId);
|
|
|
|
break;
|
|
|
|
case LibCmo::CK2::CK_CLASSID::CKCID_MESH:
|
|
|
|
m_ObjMeshs.emplace_back(fileobj.CreatedObjectId);
|
|
|
|
break;
|
|
|
|
case LibCmo::CK2::CK_CLASSID::CKCID_MATERIAL:
|
|
|
|
m_ObjMaterials.emplace_back(fileobj.CreatedObjectId);
|
|
|
|
break;
|
|
|
|
case LibCmo::CK2::CK_CLASSID::CKCID_TEXTURE:
|
|
|
|
m_ObjTextures.emplace_back(fileobj.CreatedObjectId);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2023-10-30 10:25:31 +08:00
|
|
|
m_HasLoaded = true;
|
2023-10-03 21:33:00 +08:00
|
|
|
return true;
|
2023-09-23 15:55:57 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
bool BMFile::Save(LibCmo::CKSTRING filename, LibCmo::CKINT compress_level) {
|
2023-10-30 10:25:31 +08:00
|
|
|
if (!CanExecSave()) return false;
|
2023-09-23 15:55:57 +08:00
|
|
|
|
2023-10-29 10:27:35 +08:00
|
|
|
// create temp writer
|
|
|
|
LibCmo::CK2::CKFileWriter writer(m_Context);
|
|
|
|
|
|
|
|
// fill object data
|
|
|
|
for (const auto& id : m_ObjGroups) {
|
|
|
|
writer.AddSavedObject(m_Context->GetObject(id));
|
|
|
|
}
|
|
|
|
for (const auto& id : m_Obj3dObjects) {
|
|
|
|
writer.AddSavedObject(m_Context->GetObject(id));
|
|
|
|
}
|
|
|
|
for (const auto& id : m_ObjMeshs) {
|
|
|
|
writer.AddSavedObject(m_Context->GetObject(id));
|
|
|
|
}
|
|
|
|
for (const auto& id : m_ObjMaterials) {
|
|
|
|
writer.AddSavedObject(m_Context->GetObject(id));
|
|
|
|
}
|
|
|
|
for (const auto& id : m_ObjTextures) {
|
|
|
|
writer.AddSavedObject(m_Context->GetObject(id));
|
|
|
|
}
|
|
|
|
|
|
|
|
// set compress level
|
|
|
|
m_Context->SetCompressionLevel(compress_level);
|
|
|
|
|
|
|
|
// save to file and detect error
|
|
|
|
LibCmo::CK2::CKERROR err = writer.Save(filename);
|
|
|
|
|
|
|
|
// return with error detect.
|
2023-10-30 10:25:31 +08:00
|
|
|
m_HasSaved = true;
|
2023-10-29 10:27:35 +08:00
|
|
|
return err == LibCmo::CK2::CKERROR::CKERR_OK;
|
2023-10-03 21:33:00 +08:00
|
|
|
}
|
2023-09-23 16:25:26 +08:00
|
|
|
|
2023-10-03 21:33:00 +08:00
|
|
|
LibCmo::CKDWORD BMFile::GetGroupCount() { return CommonGetObjectCount(m_ObjGroups); }
|
|
|
|
LibCmo::CK2::CK_ID BMFile::GetGroup(LibCmo::CKDWORD idx) { return CommonGetObject(m_ObjGroups, idx); }
|
2023-10-05 21:08:58 +08:00
|
|
|
LibCmo::CK2::CK_ID BMFile::CreateGroup() { return CommonCreateObject(m_ObjGroups, LibCmo::CK2::CK_CLASSID::CKCID_GROUP); }
|
2023-10-03 21:33:00 +08:00
|
|
|
LibCmo::CKDWORD BMFile::Get3dObjectCount() { return CommonGetObjectCount(m_Obj3dObjects); }
|
|
|
|
LibCmo::CK2::CK_ID BMFile::Get3dObject(LibCmo::CKDWORD idx) { return CommonGetObject(m_Obj3dObjects, idx); }
|
2023-10-05 21:08:58 +08:00
|
|
|
LibCmo::CK2::CK_ID BMFile::Create3dObject() { return CommonCreateObject(m_Obj3dObjects, LibCmo::CK2::CK_CLASSID::CKCID_3DOBJECT); }
|
2023-10-03 21:33:00 +08:00
|
|
|
LibCmo::CKDWORD BMFile::GetMeshCount() { return CommonGetObjectCount(m_ObjMeshs); }
|
|
|
|
LibCmo::CK2::CK_ID BMFile::GetMesh(LibCmo::CKDWORD idx) { return CommonGetObject(m_ObjMeshs, idx); }
|
2023-10-05 21:08:58 +08:00
|
|
|
LibCmo::CK2::CK_ID BMFile::CreateMesh() { return CommonCreateObject(m_ObjMeshs, LibCmo::CK2::CK_CLASSID::CKCID_MESH); }
|
2023-10-03 21:33:00 +08:00
|
|
|
LibCmo::CKDWORD BMFile::GetMaterialCount() { return CommonGetObjectCount(m_ObjMaterials); }
|
|
|
|
LibCmo::CK2::CK_ID BMFile::GetMaterial(LibCmo::CKDWORD idx) { return CommonGetObject(m_ObjMaterials, idx); }
|
2023-10-05 21:08:58 +08:00
|
|
|
LibCmo::CK2::CK_ID BMFile::CreateMaterial() { return CommonCreateObject(m_ObjMaterials, LibCmo::CK2::CK_CLASSID::CKCID_MATERIAL); }
|
2023-10-03 21:33:00 +08:00
|
|
|
LibCmo::CKDWORD BMFile::GetTextureCount() { return CommonGetObjectCount(m_ObjTextures); }
|
|
|
|
LibCmo::CK2::CK_ID BMFile::GetTexture(LibCmo::CKDWORD idx) { return CommonGetObject(m_ObjTextures, idx); }
|
2023-10-05 21:08:58 +08:00
|
|
|
LibCmo::CK2::CK_ID BMFile::CreateTexture() { return CommonCreateObject(m_ObjTextures, LibCmo::CK2::CK_CLASSID::CKCID_TEXTURE); }
|
2023-09-23 15:55:57 +08:00
|
|
|
|
|
|
|
#pragma endregion
|
2023-09-21 13:47:30 +08:00
|
|
|
|
|
|
|
}
|