From 81872053f0c7906376a030620a62751fc7c9b85a Mon Sep 17 00:00:00 2001 From: yyc12345 Date: Wed, 20 Sep 2023 15:25:43 +0800 Subject: [PATCH] finish PreDelete and CheckPreDeletion. now there is no problem when deleting object --- CodeGen/EnumsMigration/src/VxEnums.txt | 10 +++++----- LibCmo/CK2/MgrImpls/CKObjectManager.cpp | 7 ++++++- LibCmo/CK2/ObjImpls/CK3dEntity.cpp | 12 ++++++++++++ LibCmo/CK2/ObjImpls/CK3dEntity.hpp | 6 ++++-- LibCmo/CK2/ObjImpls/CKBeObject.cpp | 10 +--------- LibCmo/CK2/ObjImpls/CKGroup.cpp | 18 ++++++++++++++++++ LibCmo/CK2/ObjImpls/CKGroup.hpp | 4 ++++ LibCmo/CK2/ObjImpls/CKMaterial.cpp | 11 +++++++++++ LibCmo/CK2/ObjImpls/CKMaterial.hpp | 5 +++-- LibCmo/CK2/ObjImpls/CKMesh.cpp | 18 ++++++++++++++++++ LibCmo/CK2/ObjImpls/CKMesh.hpp | 5 +++-- LibCmo/CK2/ObjImpls/CKObject.cpp | 5 +++++ LibCmo/CK2/ObjImpls/CKObject.hpp | 4 +++- LibCmo/VxMath/VxEnums.hpp | 10 +++++----- LibCmo/XContainer/XTypes.cpp | 2 +- Unvirt/UnvirtContext.cpp | 1 + 16 files changed, 100 insertions(+), 28 deletions(-) diff --git a/CodeGen/EnumsMigration/src/VxEnums.txt b/CodeGen/EnumsMigration/src/VxEnums.txt index 5c4a36b..f7ee614 100644 --- a/CodeGen/EnumsMigration/src/VxEnums.txt +++ b/CodeGen/EnumsMigration/src/VxEnums.txt @@ -211,11 +211,11 @@ typedef enum VXCMPFUNC Summary: Material special effects Remarks: -o Effects provide additionnal functionnalities to take advantage of graphic features such as bump mapping,cube maps etc... -o When an effect is enabled on a material (CKMaterial::SetEffect) it may override the default settings of mesh channels or material blend options -o New effects can be created by providing a callback function (see CKRenderManager::AddEffect) -o This enumeration provides the list of hardcoded existing effects. -o Most of this effect are heavily hardware and device (DX8,DX7,etc..) dependant ++ Effects provide additionnal functionnalities to take advantage of graphic features such as bump mapping,cube maps etc... ++ When an effect is enabled on a material (CKMaterial::SetEffect) it may override the default settings of mesh channels or material blend options ++ New effects can be created by providing a callback function (see CKRenderManager::AddEffect) ++ This enumeration provides the list of hardcoded existing effects. ++ Most of this effect are heavily hardware and device (DX8,DX7,etc..) dependant See also: CKMaterial::SetEffect,CKMaterial::GetEffect,CKRenderManager::AddEffect ******************************************************************/ typedef enum VX_EFFECT diff --git a/LibCmo/CK2/MgrImpls/CKObjectManager.cpp b/LibCmo/CK2/MgrImpls/CKObjectManager.cpp index e6a669d..23b34a5 100644 --- a/LibCmo/CK2/MgrImpls/CKObjectManager.cpp +++ b/LibCmo/CK2/MgrImpls/CKObjectManager.cpp @@ -97,7 +97,7 @@ namespace LibCmo::CK2::MgrImpls { // add into list validObjIds.emplace_back(ids[i]); } - + // then remove deleted object from m_ObjectListByClass // because we have set to be deleted flag. for (size_t i = 0; i < m_ObjectsListByClass.size(); ++i) { @@ -117,6 +117,11 @@ namespace LibCmo::CK2::MgrImpls { } } + // calling PreDelete function for deleted objects + for (const auto& objid : validObjIds) { + m_ObjectsList[Id2Offset(objid)]->PreDelete(); + } + // then free all valid object for (const auto& objid : validObjIds) { CKDWORD off = Id2Offset(objid); diff --git a/LibCmo/CK2/ObjImpls/CK3dEntity.cpp b/LibCmo/CK2/ObjImpls/CK3dEntity.cpp index 1feafd0..af20d09 100644 --- a/LibCmo/CK2/ObjImpls/CK3dEntity.cpp +++ b/LibCmo/CK2/ObjImpls/CK3dEntity.cpp @@ -19,6 +19,18 @@ namespace LibCmo::CK2::ObjImpls { CK3dEntity::~CK3dEntity() {} + void CK3dEntity::CheckPreDeletion() { + CKRenderObject::CheckPreDeletion(); + + // check active mesh + if (m_CurrentMesh->IsToBeDeleted()) { + m_CurrentMesh = nullptr; + } + + // check potential meshes + XContainer::NSXObjectPointerArray::PreDeletedCheck(m_PotentialMeshes, m_Context); + } + bool CK3dEntity::Save(CKStateChunk* chunk, CKFileVisitor* file, CKDWORD flags) { bool suc = CKRenderObject::Save(chunk, file, flags); if (!suc) return false; diff --git a/LibCmo/CK2/ObjImpls/CK3dEntity.hpp b/LibCmo/CK2/ObjImpls/CK3dEntity.hpp index 49d4a3f..343fe33 100644 --- a/LibCmo/CK2/ObjImpls/CK3dEntity.hpp +++ b/LibCmo/CK2/ObjImpls/CK3dEntity.hpp @@ -14,10 +14,12 @@ namespace LibCmo::CK2::ObjImpls { virtual CK_CLASSID GetClassID(void) override { return CK_CLASSID::CKCID_3DENTITY; } - //virtual void PreSave(CKFileVisitor* file, CKDWORD flags) override; + + 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; - //virtual void PostLoad() override; // it have special Show and IsVisible method virtual void Show(CK_OBJECT_SHOWOPTION show = CK_OBJECT_SHOWOPTION::CKSHOW) override; diff --git a/LibCmo/CK2/ObjImpls/CKBeObject.cpp b/LibCmo/CK2/ObjImpls/CKBeObject.cpp index b90e1ab..a4d1e35 100644 --- a/LibCmo/CK2/ObjImpls/CKBeObject.cpp +++ b/LibCmo/CK2/ObjImpls/CKBeObject.cpp @@ -10,15 +10,7 @@ namespace LibCmo::CK2::ObjImpls { CKBeObject::CKBeObject(CKContext* ctx, CK_ID ckid, CKSTRING name) : CKSceneObject(ctx, ckid, name), m_Groups() {} - CKBeObject::~CKBeObject() { - // remove self from all group - //for (size_t i = 0; i < m_Groups.size(); ++i) { - // if (m_Groups[i]) { - // CKGroup* group = static_cast(m_Context->GetObjectManager()->GetGroupByGlobalIndex(static_cast(i))); - // group->RemoveObject(this); - // } - //} - } + CKBeObject::~CKBeObject() {} bool CKBeObject::Save(CKStateChunk* chunk, CKFileVisitor* file, CKDWORD flags) { bool suc = CKSceneObject::Save(chunk, file, flags); diff --git a/LibCmo/CK2/ObjImpls/CKGroup.cpp b/LibCmo/CK2/ObjImpls/CKGroup.cpp index 31279c1..745921f 100644 --- a/LibCmo/CK2/ObjImpls/CKGroup.cpp +++ b/LibCmo/CK2/ObjImpls/CKGroup.cpp @@ -12,9 +12,27 @@ namespace LibCmo::CK2::ObjImpls { m_GroupIndex(m_Context->GetObjectManager()->AllocateGroupGlobalIndex()) {} CKGroup::~CKGroup() { + // free self allocated id m_Context->GetObjectManager()->FreeGroupGlobalIndex(m_GroupIndex); } + void CKGroup::PreDelete() { + CKBeObject::PreDelete(); + + // unlink all grouped object + for (auto& ptr : m_ObjectArray) { + static_cast(ptr)->ExplicitSetGroup(m_GroupIndex, false); + } + m_ObjectArray.clear(); + } + + void CKGroup::CheckPreDeletion() { + CKBeObject::CheckPreDeletion(); + + // remove self invalid object ptr + XContainer::NSXObjectPointerArray::PreDeletedCheck(m_ObjectArray, m_Context); + } + bool CKGroup::Save(CKStateChunk* chunk, CKFileVisitor* file, CKDWORD flags) { bool suc = CKBeObject::Save(chunk, file, flags); if (!suc) return false; diff --git a/LibCmo/CK2/ObjImpls/CKGroup.hpp b/LibCmo/CK2/ObjImpls/CKGroup.hpp index 6f526f7..f82e8ee 100644 --- a/LibCmo/CK2/ObjImpls/CKGroup.hpp +++ b/LibCmo/CK2/ObjImpls/CKGroup.hpp @@ -14,6 +14,10 @@ namespace LibCmo::CK2::ObjImpls { virtual CK_CLASSID GetClassID(void) override { return CK_CLASSID::CKCID_GROUP; } + + virtual void PreDelete() override; + virtual void CheckPreDeletion() override; + //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; diff --git a/LibCmo/CK2/ObjImpls/CKMaterial.cpp b/LibCmo/CK2/ObjImpls/CKMaterial.cpp index ba46dbf..cbc52ee 100644 --- a/LibCmo/CK2/ObjImpls/CKMaterial.cpp +++ b/LibCmo/CK2/ObjImpls/CKMaterial.cpp @@ -33,6 +33,17 @@ namespace LibCmo::CK2::ObjImpls { CKMaterial::~CKMaterial() {} + void CKMaterial::CheckPreDeletion() { + CKBeObject::CheckPreDeletion(); + + // check 4 textures + for (auto& tex : m_Textures) { + if (tex != nullptr && tex->IsToBeDeleted()) { + tex = nullptr; + } + } + } + bool CKMaterial::Save(CKStateChunk* chunk, CKFileVisitor* file, CKDWORD flags) { bool suc = CKBeObject::Save(chunk, file, flags); if (!suc) return false; diff --git a/LibCmo/CK2/ObjImpls/CKMaterial.hpp b/LibCmo/CK2/ObjImpls/CKMaterial.hpp index fbc1bfb..bd8a8fd 100644 --- a/LibCmo/CK2/ObjImpls/CKMaterial.hpp +++ b/LibCmo/CK2/ObjImpls/CKMaterial.hpp @@ -15,11 +15,12 @@ namespace LibCmo::CK2::ObjImpls { virtual CK_CLASSID GetClassID(void) override { return CK_CLASSID::CKCID_MATERIAL; } + + virtual void CheckPreDeletion() override; - //virtual void PreSave(CKFileVisitor* file, CKDWORD flags) override; + // 2 RW functions virtual bool Save(CKStateChunk* chunk, CKFileVisitor* file, CKDWORD flags) override; virtual bool Load(CKStateChunk* chunk, CKFileVisitor* file) override; - //virtual void PostLoad() override; protected: VxMath::VxColor m_Diffuse; diff --git a/LibCmo/CK2/ObjImpls/CKMesh.cpp b/LibCmo/CK2/ObjImpls/CKMesh.cpp index 298c3a6..0789b74 100644 --- a/LibCmo/CK2/ObjImpls/CKMesh.cpp +++ b/LibCmo/CK2/ObjImpls/CKMesh.cpp @@ -35,6 +35,24 @@ namespace LibCmo::CK2::ObjImpls { CKMesh::~CKMesh() {} + void CKMesh::CheckPreDeletion() { + CKBeObject::CheckPreDeletion(); + + // check material slots + for (auto& slot : m_MaterialSlot) { + if (slot != nullptr && slot->IsToBeDeleted()) { + slot = nullptr; + } + } + + // check mtl channels + for (auto& chl : m_MaterialChannels) { + if (chl.m_Material != nullptr && chl.m_Material->IsToBeDeleted()) { + chl.m_Material = nullptr; + } + } + } + bool CKMesh::Save(CKStateChunk* chunk, CKFileVisitor* file, CKDWORD flags) { bool suc = CKBeObject::Save(chunk, file, flags); if (!suc) return false; diff --git a/LibCmo/CK2/ObjImpls/CKMesh.hpp b/LibCmo/CK2/ObjImpls/CKMesh.hpp index fc1a7f9..6087108 100644 --- a/LibCmo/CK2/ObjImpls/CKMesh.hpp +++ b/LibCmo/CK2/ObjImpls/CKMesh.hpp @@ -15,10 +15,11 @@ namespace LibCmo::CK2::ObjImpls { return CK_CLASSID::CKCID_MESH; } - //virtual void PreSave(CKFileVisitor* file, CKDWORD flags) override; + 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; - //virtual void PostLoad() override; // it only have special Show method virtual void Show(CK_OBJECT_SHOWOPTION show = CK_OBJECT_SHOWOPTION::CKSHOW) override; diff --git a/LibCmo/CK2/ObjImpls/CKObject.cpp b/LibCmo/CK2/ObjImpls/CKObject.cpp index 7bf4d5a..04d0a7d 100644 --- a/LibCmo/CK2/ObjImpls/CKObject.cpp +++ b/LibCmo/CK2/ObjImpls/CKObject.cpp @@ -28,6 +28,9 @@ namespace LibCmo::CK2::ObjImpls { void CKObject::SetObjectFlags(CK_OBJECT_FLAGS flags) { m_ObjectFlags = flags; } + bool CKObject::IsToBeDeleted() const { + return EnumsHelper::Has(m_ObjectFlags, CK_OBJECT_FLAGS::CK_OBJECT_TOBEDELETED); + } CKContext* CKObject::GetCKContext() const { return m_Context; } @@ -35,6 +38,8 @@ namespace LibCmo::CK2::ObjImpls { #pragma endregion + void CKObject::PreDelete() {} + void CKObject::CheckPreDeletion() {} void CKObject::CheckPostDeletion() {} diff --git a/LibCmo/CK2/ObjImpls/CKObject.hpp b/LibCmo/CK2/ObjImpls/CKObject.hpp index 897bceb..44a23c2 100644 --- a/LibCmo/CK2/ObjImpls/CKObject.hpp +++ b/LibCmo/CK2/ObjImpls/CKObject.hpp @@ -16,6 +16,7 @@ Implement as original meaning: - Show() - IsVisible() +- PreDelete() - CheckPreDeletion() - CheckPostDeletion() @@ -30,7 +31,6 @@ No implement because don't care: Implement moved into other location: - Copy(): Use CKObject::CKObject(CK_ID newid, const CKObject* obj) ctor and CKClassDesc to implement. -- PreDelete(): Write in dtor. */ @@ -47,12 +47,14 @@ namespace LibCmo::CK2::ObjImpls { void SetName(CKSTRING u8_name); CK_OBJECT_FLAGS GetObjectFlags(void) const; void SetObjectFlags(CK_OBJECT_FLAGS flags); + bool IsToBeDeleted() const; CKContext* GetCKContext() const; virtual CK_CLASSID GetClassID(void) { return CK_CLASSID::CKCID_OBJECT; } + virtual void PreDelete(); virtual void CheckPreDeletion(); virtual void CheckPostDeletion(); diff --git a/LibCmo/VxMath/VxEnums.hpp b/LibCmo/VxMath/VxEnums.hpp index 7d254c1..7014856 100644 --- a/LibCmo/VxMath/VxEnums.hpp +++ b/LibCmo/VxMath/VxEnums.hpp @@ -183,11 +183,11 @@ namespace LibCmo::VxMath { /** Summary: Material special effects Remarks: - o Effects provide additionnal functionnalities to take advantage of graphic features such as bump mapping,cube maps etc... - o When an effect is enabled on a material (CKMaterial::SetEffect) it may override the default settings of mesh channels or material blend options - o New effects can be created by providing a callback function (see CKRenderManager::AddEffect) - o This enumeration provides the list of hardcoded existing effects. - o Most of this effect are heavily hardware and device (DX8,DX7,etc..) dependant + + Effects provide additionnal functionnalities to take advantage of graphic features such as bump mapping,cube maps etc... + + When an effect is enabled on a material (CKMaterial::SetEffect) it may override the default settings of mesh channels or material blend options + + New effects can be created by providing a callback function (see CKRenderManager::AddEffect) + + This enumeration provides the list of hardcoded existing effects. + + Most of this effect are heavily hardware and device (DX8,DX7,etc..) dependant See also: CKMaterial::SetEffect,CKMaterial::GetEffect,CKRenderManager::AddEffect */ enum class VX_EFFECT : CKDWORD { diff --git a/LibCmo/XContainer/XTypes.cpp b/LibCmo/XContainer/XTypes.cpp index 39bb8d1..ccd8fe1 100644 --- a/LibCmo/XContainer/XTypes.cpp +++ b/LibCmo/XContainer/XTypes.cpp @@ -98,7 +98,7 @@ namespace LibCmo::XContainer { } else { obj = item; } - if (EnumsHelper::Has(obj->GetObjectFlags(), CK2::CK_OBJECT_FLAGS::CK_OBJECT_TOBEDELETED)) return false; + if (obj->IsToBeDeleted()) return false; } else { CK2::MgrImpls::CKObjectManager* objmgr = ctx->GetObjectManager(); if constexpr (std::is_same_v<_Ty, CK2::CK_ID>) { diff --git a/Unvirt/UnvirtContext.cpp b/Unvirt/UnvirtContext.cpp index 00e18e1..1527759 100644 --- a/Unvirt/UnvirtContext.cpp +++ b/Unvirt/UnvirtContext.cpp @@ -204,6 +204,7 @@ namespace Unvirt::Context { // split cmd and parse it auto cmds = m_Splitter.Convert(u8cmd); + if (cmds.empty()) continue; // get sub command if (!m_Root.RootConsume(cmds)) {