#include "StdAfx.h" #include "ResourceManager.h" #include "ModelFile.h" #include "ActorManager.h" bool IsMfFile(const NiFixedString& kName) { unsigned int uiLen = kName.GetLength(); const char* pcName = kName; if( uiLen >= 3 && pcName[uiLen - 3] == '.' && (pcName[uiLen - 2] == 'm' || pcName[uiLen - 2] == 'M') && (pcName[uiLen - 1] == 'f' || pcName[uiLen - 1] == 'F') ) return true; return false; } bool IsNifFile(const NiFixedString& kName) { unsigned int uiLen = kName.GetLength(); const char* pcName = kName; if( uiLen >= 4 && pcName[uiLen - 4] == '.' && (pcName[uiLen - 3] == 'n' || pcName[uiLen - 3] == 'N') && (pcName[uiLen - 2] == 'i' || pcName[uiLen - 2] == 'I') && (pcName[uiLen - 1] == 'f' || pcName[uiLen - 1] == 'F') ) return true; return false; } NiGlobalStringTable::GlobalStringHandle MakeStandardName(const char* src) { char dest[1024]; NIASSERT(strlen(src) < sizeof(dest) - 4); unsigned int i = 0; unsigned int j = 0; bool bSlash = false; //连续的斜杠只保留一个 for(; src[i] != '\0'; ++i) { if(src[i] == '\\' || src[i] == '/') { if(!bSlash) { dest[j++] = '\\'; bSlash = true; } continue; } bSlash = false; //转换成大写 if(src[i] >= 'a' && src[i] <= 'z') dest[j++] = src[i] + 'A' - 'a'; else dest[j++] = src[i]; } dest[j] = '\0'; return NiGlobalStringTable::AddString(dest); } void CoverMaterial(NiAVObject* pkObject) { if (NiIsKindOf(NiGeometry, pkObject)) { NiGeometry* pkGeom = (NiGeometry*)pkObject; NiMaterialProperty* pMat = (NiMaterialProperty*)pkGeom->GetProperty( NiProperty::MATERIAL ); if ( pMat ) { pMat->SetEmittance(NiColor(0.2f, 0.2f, 0.2f)); pMat->SetDiffuseColor(NiColor(1.4f, 1.4f, 1.4f)); pMat->SetAmbientColor(NiColor(0.8f, 0.8f, 0.8f)); } } if (NiIsKindOf(NiNode, pkObject)) { NiNode* pkNode = (NiNode*)pkObject; for (unsigned int i = 0; i < pkNode->GetArrayCount(); i++) { NiAVObject* pkChild = pkNode->GetAt(i); if (pkChild) CoverMaterial(pkChild); } } } CResMgr* CResMgr::ms_pkResMgr = NULL; CResMgr::CResMgr() :m_pkNullNif(NULL) ,m_pkNullKfm(NULL) ,m_pkNullTexture(NULL) ,m_kExtraDataName("ResExtraDataName") { NIASSERT(ms_pkResMgr == NULL); ms_pkResMgr = this; Initialize(); } CResMgr::~CResMgr() { Destroy(); ms_pkResMgr = NULL; } bool CResMgr::Initialize() { m_pkNullNif = LoadNifResNode(MakeStandardName("Data\\NullObjects\\NullNif.Nif")); m_pkNullKfm = LoadKfmResNode(MakeStandardName("Data\\NullObjects\\NullKfm.Kfm")); m_pkNullTexture = LoadTextureResNode(MakeStandardName("Data\\NullObjects\\NullTexture.dds")); DumpNif(); DumpMf(); DumpKfm(); DumpTexture(); return true; } void CResMgr::Destroy() { FreeNif((NiAVObject*)(m_pkNullNif->m_pkResource)); m_pkNullNif = NULL; FreeKfm((NiActorManager*)(m_pkNullKfm->m_pkResource)); m_pkNullKfm = NULL; FreeTexture((NiTexture*)(m_pkNullTexture->m_pkResource)); m_pkNullTexture = NULL; DumpNif(); DumpMf(); DumpKfm(); DumpTexture(); } void CResMgr::AddResData(NiAVObject* pkAVObject, const NiFixedString& kFilename) { NIASSERT(pkAVObject); NiStringExtraData* pkExtraData = (NiStringExtraData*)pkAVObject->GetExtraData(m_kExtraDataName); if(pkExtraData == NULL) { pkExtraData = NiNew NiStringExtraData(kFilename); pkExtraData->SetName(m_kExtraDataName); pkAVObject->AddExtraData(pkExtraData); } else { pkExtraData->SetValue(kFilename); } } const NiFixedString* CResMgr::GetResData(NiAVObject* pkAVObject) { NIASSERT(pkAVObject); NiStringExtraData* pkExtraData = (NiStringExtraData*)pkAVObject->GetExtraData(m_kExtraDataName); if(pkExtraData) return &pkExtraData->GetValue(); return NULL; } ResNode* CResMgr::LoadNifResNode(const CFixedString& kName) { int iName = (int)kName; ResNode* pkResNode; m_kNifLoader.m_kCS.Lock(); ResourceMap::iterator itr = m_kNifLoader.m_kResMap.find(iName); if(itr != m_kNifLoader.m_kResMap.end()) { pkResNode = itr->second; } else { if(m_kNifLoader.m_kStream.Load(kName) && m_kNifLoader.m_kStream.GetObjectCount()) { NiAVObject* pkAVObject = (NiAVObject*)m_kNifLoader.m_kStream.GetObjectAt(0); AddResData(pkAVObject, kName); pkResNode = NiNew ResNode(pkAVObject); m_kNifLoader.m_kResMap[iName] = pkResNode; } else { pkResNode = m_pkNullNif; char acMsg[1024]; NiSprintf(acMsg, sizeof(acMsg), "Nf not found %s\n", (const char*)kName); OutputDebugStringA(acMsg); } m_kNifLoader.m_kStream.RemoveAllObjects(); } NIASSERT(pkResNode); pkResNode->m_iRefCount++; m_kNifLoader.m_kCS.Unlock(); return pkResNode; } ResNode* CResMgr::LoadMfResNode(const CFixedString& kName) { int iName = (int)kName; ResNode* pkResNode; m_kMfLoader.m_kCS.Lock(); ResourceMap::iterator itr = m_kMfLoader.m_kResMap.find(iName); if(itr != m_kMfLoader.m_kResMap.end()) { pkResNode = itr->second; } else { { CModelFile kModelFile; pkResNode = kModelFile.Load(kName); } if(pkResNode) { NiAVObject* pkAVObject = (NiAVObject*)pkResNode->m_pkResource; AddResData(pkAVObject, kName); m_kMfLoader.m_kResMap[iName] = pkResNode; } else { pkResNode = m_pkNullNif; char acMsg[1024]; NiSprintf(acMsg, sizeof(acMsg), "Mf load error %s\n", (const char*)kName); OutputDebugStringA(acMsg); } } NIASSERT(pkResNode); pkResNode->m_iRefCount++; m_kMfLoader.m_kCS.Unlock(); return pkResNode; } NiAVObject* CResMgr::LoadNif(const NiFixedString& kFilename, bool bCopy) { CFixedString kName = MakeStandardName(kFilename); ResNode* pkResNode = NULL; if( IsMfFile(kName) ) { pkResNode = LoadMfResNode(kName); } else { pkResNode = LoadNifResNode(kName); } NIASSERT(pkResNode); NiAVObject* pkAVObject = (NiAVObject*)pkResNode->m_pkResource; if(bCopy) { NiCloningProcess kCloning; kCloning.m_eCopyType = NiObjectNET::COPY_EXACT; pkAVObject = (NiAVObject*)pkAVObject->Clone(kCloning); } return pkAVObject; } void CResMgr::FreeNif(NiAVObject* pkAVObject) { if(pkAVObject) { const NiFixedString* pkName = GetResData(pkAVObject); if(pkName == NULL) return; if(IsMfFile(*pkName)) FreeMf(*pkName); else if( IsNifFile(*pkName) ) FreeNif(*pkName); } } void CResMgr::FreeNif(const NiFixedString& kFilename) { int iName = (int)(const char*)kFilename; m_kNifLoader.m_kCS.Lock(); ResourceMap::iterator itr = m_kNifLoader.m_kResMap.find(iName); NIASSERT(itr != m_kNifLoader.m_kResMap.end()); if(itr == m_kNifLoader.m_kResMap.end()) { m_kNifLoader.m_kCS.Unlock(); return; } ResNode* pkResNode = itr->second; pkResNode->m_iRefCount--; NIASSERT(pkResNode->m_iRefCount >= 0); if(pkResNode->m_iRefCount == 0) { m_kNifLoader.m_kResMap.erase(itr); NiDelete pkResNode; } m_kNifLoader.m_kCS.Unlock(); } void CResMgr::FreeMf(const NiFixedString& kFilename) { int iName = (int)(const char*)kFilename; m_kMfLoader.m_kCS.Lock(); ResourceMap::iterator itr = m_kMfLoader.m_kResMap.find(iName); NIASSERT(itr != m_kMfLoader.m_kResMap.end()); if(itr == m_kMfLoader.m_kResMap.end()) { m_kMfLoader.m_kCS.Unlock(); return; } MfResNode* pkResNode = (MfResNode*)itr->second; pkResNode->m_iRefCount--; NIASSERT(pkResNode->m_iRefCount >= 0); if(pkResNode->m_iRefCount == 0) { if(pkResNode->m_aNifs[0]) { FreeNif(CFixedString((NiGlobalStringTable::GlobalStringHandle)pkResNode->m_aNifs[0])); } for(int i = 0; i < ARRAY_SIZE(pkResNode->m_aTextures); ++i) { if(pkResNode->m_aTextures[i]) { FreeTexture(CFixedString((NiGlobalStringTable::GlobalStringHandle)pkResNode->m_aTextures[i])); } } m_kMfLoader.m_kResMap.erase(itr); NiDelete pkResNode; } m_kMfLoader.m_kCS.Unlock(); } void CResMgr::DumpNif() { char acMsg[1024]; m_kNifLoader.m_kCS.Lock(); #ifdef _DEBUG const char* pcName; ResNode* pkResNode; ResourceMap::iterator itr; for(itr = m_kNifLoader.m_kResMap.begin(); itr != m_kNifLoader.m_kResMap.end(); itr++) { pcName = (const char*)itr->first; pkResNode = itr->second; NiSprintf(acMsg, sizeof(acMsg), "Nf %d %s\n", pkResNode->m_iRefCount, pcName); NiOutputDebugString(acMsg); } #endif //_DEBUG NiSprintf(acMsg, sizeof(acMsg), "Nf count %d\n", m_kNifLoader.m_kResMap.size()); OutputDebugStringA(acMsg); m_kNifLoader.m_kCS.Unlock(); } void CResMgr::DumpMf() { char acMsg[1024]; m_kMfLoader.m_kCS.Lock(); #ifdef _DEBUG const char* pcName; ResNode* pkResNode; ResourceMap::iterator itr; for(itr = m_kMfLoader.m_kResMap.begin(); itr != m_kMfLoader.m_kResMap.end(); itr++) { pcName = (const char*)itr->first; pkResNode = itr->second; NiSprintf(acMsg, sizeof(acMsg), "Mf %d %s\n", pkResNode->m_iRefCount, pcName); NiOutputDebugString(acMsg); } #endif //_DEBUG NiSprintf(acMsg, sizeof(acMsg), "Mf count %d\n", m_kMfLoader.m_kResMap.size()); OutputDebugStringA(acMsg); m_kMfLoader.m_kCS.Unlock(); } ResNode* CResMgr::LoadKfmResNode(const CFixedString& kName) { int iName = (int)kName; ResNode* pkResNode; m_kKfmLoader.m_kCS.Lock(); ResourceMap::iterator itr = m_kKfmLoader.m_kResMap.find(iName); if(itr != m_kKfmLoader.m_kResMap.end()) { pkResNode = itr->second; } else { NiActorManager* pkActorManager = NiActorManager::Create(kName, false, true, &m_kKfmLoader.m_kStream); if(pkActorManager) { AddResData(pkActorManager->GetNIFRoot(), kName); pkResNode = NiNew ResNode(pkActorManager); m_kKfmLoader.m_kResMap[iName] = pkResNode; } else { char acMsg[1024]; NiSprintf(acMsg, sizeof(acMsg), "Km not found %s\n", (const char*)kName); OutputDebugStringA(acMsg); pkResNode = m_pkNullKfm; } m_kKfmLoader.m_kStream.RemoveAllObjects(); } NIASSERT(pkResNode); pkResNode->m_iRefCount++; m_kKfmLoader.m_kCS.Unlock(); return pkResNode; } NiActorManager* CResMgr::LoadKfm(const NiFixedString& kFilename, bool bCopy) { CFixedString kName(MakeStandardName(kFilename)); ResNode* pkResNode = LoadKfmResNode(kName); NIASSERT(pkResNode); NiActorManager* pkActorManager = ((NiActorManager*)pkResNode->m_pkResource); if(bCopy) { NiCloningProcess kCloning; kCloning.m_eCopyType = NiObjectNET::COPY_EXACT; pkActorManager = pkActorManager->Clone(&kCloning); pkActorManager->SetTargetAnimation(NiActorManager::INVALID_SEQUENCE_ID); } return pkActorManager; } void CResMgr::FreeKfm(NiActorManager* pkActorManager) { if(pkActorManager) { const NiFixedString* pkName = GetResData(pkActorManager->GetNIFRoot()); if(pkName) FreeKfm(*pkName); } } void CResMgr::FreeKfm(const NiFixedString& kFilename) { int iName = (int)(const char*)kFilename; m_kKfmLoader.m_kCS.Lock(); ResourceMap::iterator itr = m_kKfmLoader.m_kResMap.find(iName); NIASSERT(itr != m_kKfmLoader.m_kResMap.end()); if(itr == m_kKfmLoader.m_kResMap.end()) { m_kKfmLoader.m_kCS.Unlock(); return; } ResNode* pkResNode = itr->second; pkResNode->m_iRefCount--; NIASSERT(pkResNode->m_iRefCount >= 0) if(pkResNode->m_iRefCount == 0) { m_kKfmLoader.m_kResMap.erase(itr); NiDelete pkResNode; } m_kKfmLoader.m_kCS.Unlock(); } void CResMgr::DumpKfm() { char acMsg[1024]; m_kKfmLoader.m_kCS.Lock(); #ifdef _DEBUG const char* pcName; ResNode* pkResNode; ResourceMap::iterator itr; for(itr = m_kKfmLoader.m_kResMap.begin(); itr != m_kKfmLoader.m_kResMap.end(); itr++) { pcName = (const char*)itr->first; pkResNode = itr->second; NiSprintf(acMsg, sizeof(acMsg), "Km %d %s\n", pkResNode->m_iRefCount, pcName); NiOutputDebugString(acMsg); } #endif //_DEBUG NiSprintf(acMsg, sizeof(acMsg), "Km count %d\n", m_kKfmLoader.m_kResMap.size()); OutputDebugStringA(acMsg); m_kKfmLoader.m_kCS.Unlock(); } ResNode* CResMgr::LoadTextureResNode(const CFixedString& kName) { NiTexture* pkTexture; ResNode* pkResNode; m_kTextureLoader.m_kCS.Lock(); ResourceMap::iterator itr = m_kTextureLoader.m_kResMap.find((int)kName); if(itr != m_kTextureLoader.m_kResMap.end()) { pkResNode = (ResNode*)itr->second; } else { pkTexture = NiSourceTexture::Create(kName); if(pkTexture) { pkTexture->SetName(kName); pkResNode = NiNew ResNode(pkTexture); m_kTextureLoader.m_kResMap[(int)kName] = pkResNode; } else { char acMsg[1024]; NiSprintf(acMsg, sizeof(acMsg), "Texture not found %s\n", (const char*)kName); OutputDebugStringA(acMsg); pkResNode = m_pkNullTexture; } } NIASSERT(pkResNode); pkResNode->m_iRefCount++;//外界的引用 m_kTextureLoader.m_kCS.Unlock(); return pkResNode; } NiTexture* CResMgr::LoadTexture(const NiFixedString& kFilename) { CFixedString kName(MakeStandardName(kFilename)); ResNode* pkResNode = LoadTextureResNode(MakeStandardName(kName)); NIASSERT(pkResNode); return (NiTexture*)pkResNode->m_pkResource; } void CResMgr::FreeTexture(NiTexture* pkTexture) { if(pkTexture) FreeTexture(pkTexture->GetName()); } void CResMgr::FreeTexture(const NiFixedString& kFilename) { int iName = (int)(const char*)kFilename; m_kTextureLoader.m_kCS.Lock(); ResourceMap::iterator itr = m_kTextureLoader.m_kResMap.find(iName); NIASSERT(itr != m_kTextureLoader.m_kResMap.end()); if(itr == m_kTextureLoader.m_kResMap.end()) { m_kTextureLoader.m_kCS.Unlock(); return; } ResNode* pkResNode = (ResNode*)itr->second; pkResNode->m_iRefCount--; NIASSERT(pkResNode->m_iRefCount >= 0); if(pkResNode->m_iRefCount == 0) { m_kTextureLoader.m_kResMap.erase(iName); NiDelete pkResNode; } m_kTextureLoader.m_kCS.Unlock(); } void CResMgr::DumpTexture() { char acMsg[1024]; m_kTextureLoader.m_kCS.Lock(); #ifdef _DEBUG const char* pcName; ResNode* pkResNode; NiTexture* pkTexture; ResourceMap::iterator itr; for(itr = m_kTextureLoader.m_kResMap.begin(); itr != m_kTextureLoader.m_kResMap.end(); itr++) { pcName = (const char*)itr->first; pkResNode = (ResNode*)itr->second; pkTexture = (NiTexture*)pkResNode->m_pkResource; NIASSERT(pkTexture->GetName().Equals(pcName)); NiSprintf(acMsg, sizeof(acMsg), "Texture %d %s\n", pkResNode->m_iRefCount, pcName); NiOutputDebugString(acMsg); } #endif //_DEBUG NiSprintf(acMsg, sizeof(acMsg), "Texture count %d\n", m_kTextureLoader.m_kResMap.size()); OutputDebugStringA(acMsg); m_kTextureLoader.m_kCS.Unlock(); } void CResMgr::ResetTexturePalette() { m_kNifLoader.m_kCS.Lock(); m_kNifLoader.m_kStream.SetTexturePalette(NiNew NiDefaultTexturePalette); m_kNifLoader.m_kCS.Unlock(); m_kKfmLoader.m_kCS.Lock(); m_kKfmLoader.m_kStream.SetTexturePalette(NiNew NiDefaultTexturePalette); m_kKfmLoader.m_kCS.Unlock(); }