#include "stdafx.h" #include //#include "KRenderObject.h" #include "KRenderDefine.h" #include "KRenderObjectEtc.h" #include "KRenderObjectBone.h" #include "KRenderObjectMesh.h" #include "KResourceManager.h" #include "KUITextureManager.h" #include "KResource.h" #include "KNX3Loader.h" #include #include "KSpriteLoader.h" #include "KDeviceManager.h" #include "KThreadLoader.h" #include #include #include #include #include #include #include "KResourceManagerUtil.h" #include "XLRUCacheContainer.h" #include #include //#include "KGameResourceManager.h" #include //#include "KGameFileSystem.h" //#include //#include //#include //#include "SDebug_Util.h" const int RELEASE_TIME = 300000; //5분 //XCriticalSection g_hashCS; XCriticalSection g_SpriteAniCS; //#ifdef _RAC extern HWND g_hWnd; //#endif XFileBasedFS g_PackedFile; //#define DEF_FILESYSTEM #ifdef DEF_FILESYSTEM KWin32FS g_FileSystem; #endif const char * pResLevel[] = { "_AA.", //상, 사용 하지 않음 "_CC.", //하, }; int NX3LoadPack::nLoad_Level = 0; bool NX3LoadPack::SetTextureLevel( int nLevel ) { if( nLoad_Level == nLevel ) return false; else { nLoad_Level = nLevel; return true; } }; /////////////////////////////////////////////////////////////////////////////////////////////////////////////////// //KTextureManager Implement /////////////////////////////////////////////////////////////////////////////////////////////////////////////////// XCriticalSection g_texture_CS; struct PR_DATA { const char * pStr; int nRef; }; struct PrintCompareFN { bool operator() ( const PR_DATA& pr1, const PR_DATA& pr2 ) const { return strlen(pr1.pStr) > strlen(pr2.pStr); } }; KTextureManager * KSingletoneResourceManager::s_pStaticManager = new KTextureManager; KTextureManager::KTextureManager() { m_nTextureQualityLevel = 0; //최고 퀄리티 m_policy = ORG_THEN_DDS; // 일단 주어진 파일명으로 찾고, 실패하면 확장자를 dds 로 바꿔 다시 검색 } KTextureManager::~KTextureManager() { DiscardAll(); } void KTextureManager::init(void) { ////////////////////// #ifdef _DEV _TextureModeReload(); _TextureModeBuild(); #endif NX3LoadPack loadpack; loadpack.Init(); _spSpecular[0]= GetTexture( "spec_01.dds",&loadpack,TRUE,0); _spSpecular[1]= GetTexture( "spec_02.dds",&loadpack,TRUE,0); _spSpecular[2]= GetTexture( "spec_03.dds",&loadpack,TRUE,0); _spSpecular[3]= GetTexture( "spec_04.dds",&loadpack,TRUE,0); _spSpecular[4]= GetTexture( "spec_30.dds",&loadpack,TRUE,0); _spSpecular[5]= GetTexture( "spec_40.dds",&loadpack,TRUE,0); _spSpecular[6]= GetTexture( "spec_50.dds",&loadpack,TRUE,0); //_spSpecular = (void*) m_spSpecular; } void KTextureManager::makeHashString( char *buf, const char *filename, DWORD c1, DWORD c2, DWORD c3, DWORD c4 ) { // Fraun textures loading change //sprintf(buf, "%s@%08x", filename, c1);// , c2, c3, c4 ); sprintf( buf, "%s@%08x%08x%08x%08x", filename, c1, c2, c3, c4 ); } void KTextureManager::makeFileName( char *buf, const char *hashname ) { int len = static_cast(strlen( hashname )); strncpy( buf, hashname, len-33 ); buf[len-33] = '\0'; } void KTextureManager::makeColor( const char *hashname, DWORD& c1, DWORD& c2, DWORD& c3, DWORD& c4 ) { char szBuf[33] = { 0, }; int len = static_cast(strlen( hashname )); strncpy( szBuf, &hashname[len-32], 32 ); std::string strColor; strColor = szBuf; char *HEX_P; c1 = strtoul( strColor.substr( 0, 8 ).c_str(), &HEX_P, 16); c2 = strtoul( strColor.substr( 8, 8 ).c_str(), &HEX_P, 16); c3 = strtoul( strColor.substr( 16, 8 ).c_str(), &HEX_P, 16); c4 = strtoul( strColor.substr( 24, 8 ).c_str(), &HEX_P, 16); } void KTextureManager::PrintList( const char * pOutFileName ) { K3DTexture *tex; bool res; THREAD_SYNCRONIZE( g_texture_CS ); res = m_texByName.get_first_value( tex ); std::vector< PR_DATA > strFileList; if( res ) { while ( res ) { if ( tex != NULL ) { PR_DATA pr; pr.nRef = tex->GetRefCount(); pr.pStr = tex->GetName(); strFileList.push_back( pr ); } res = m_texByName.get_next_value( tex ); } } if( !strFileList.empty() ) { std::vector< PR_DATA >::iterator it; std::sort( strFileList.begin(), strFileList.end(), PrintCompareFN() ); KFileStream * pFileStream = new KFileStream( pOutFileName, KFileStream::wronly ); pFileStream->Seek( 0, KFileStream::seekSet ); std::string strline = "\r\n"; std::string strName; std::string strRef; for( it = strFileList.begin(); it != strFileList.end(); ++it ) { strName = (*it).pStr; std::string::size_type pos = strName.rfind('@'); if( pos != std::string::npos ) { pFileStream->Write( (*it).pStr, pos ); XStringUtil::Format( strRef, " - Ref Count : %d ", (*it).nRef ); pFileStream->Write( strRef.c_str(), strRef.length() ); pFileStream->Write( strline.c_str(), strline.length() ); } } XStringUtil::Format( strline, "\r\nTotal Texture Cnt : %d\r\n", strFileList.size() ); pFileStream->Write( strline.c_str(), strline.length() ); delete pFileStream; } } void KTextureManager::EventTime( DWORD dwTime ) { } bool KTextureManager::IsExistTexture( const char *texname, const NX3LoadPack * pLoadPack ) { char tempname[_MAX_PATH]; tempname[_MAX_PATH-1] = '\0'; std::vector< std::string > vList; XStringUtil::Split( texname, vList, "\\", false ); if( KFileManager::Instance().IsValidResource( vList.back().c_str() ) ) return true; strcpy( tempname, vList.back().c_str() ); if( KNX3Manager::GetManager()->GetSystemRequirements() == KNX3Manager::MINIMUM_SYSTEM || KNX3Manager::GetManager()->GetSystemRequirements() == KNX3Manager::MINIMUM_SYSTEM_BY_USER_SELECT ) { changeExtFromFileName( tempname, pLoadPack ? 1 : 0, "dds" ); } else { changeExtFromFileName( tempname, pLoadPack ? pLoadPack->nLoad_Level : 0, "dds" ); } //_CC 또는 원본 //dds 혹은 원본 파일을 쓸 수 있음으로 둘다 체크하는 것 으로 수정함 2009.04.14 sfreer if( KFileManager::Instance().IsValidResource( tempname ) || KFileManager::Instance().IsValidResource( vList.back().c_str() ) ) return true; strcpy( tempname, vList.back().c_str() ); changeExtFromFileName( tempname, 0, "dds" ); return KFileManager::Instance().IsValidResource( tempname ); } //#define _TEX_TEST K3DTexture* KTextureManager::GetTexture( const char *texname, const NX3LoadPack * pLoadPack, bool bRegMissingRes, int nTextureQuality ) { K3DTexture *restex = NULL; char hashname[_MAX_PATH]; #ifdef _TEX_TEST makeHashString( hashname, getFileNameFromPath( "4By4Tex.dds" ), 0, 0, 0, 0 ); #else makeHashString( hashname, getFileNameFromPath( texname ), 0, 0, 0, 0 ); #endif { THREAD_SYNCRONIZE( g_texture_CS ); if ( m_texByName.lookup(hashname, restex ) == true ) return restex; } #ifdef _TEX_TEST restex = loadTexture( "4By4Tex.dds", pLoadPack, bRegMissingRes, nTextureQuality ); #else restex = loadTexture( texname, pLoadPack, bRegMissingRes, nTextureQuality ); #endif { THREAD_SYNCRONIZE( g_texture_CS ); if(restex) { restex->SetLoadedTime( GetSafeTickCount() ); restex->SetName( hashname ); // for later use // _oprint( "m_texByName.add 01: %d %s\n", restex->GetID(), hashname ); restex->SetManagedByTexManager(); m_texByName.add( hashname, restex ); // doesn't null-check for performance } return restex; } } K3DTexture* KTextureManager::GetTexture( const char *texname, const NX3LoadPack * pLoadPack, DWORD c1, DWORD c2, DWORD c3, DWORD c4, int nTextureQuality, short nMode/* = 0*/ ) { K3DTexture *restex = NULL; char hashname[_MAX_PATH]; #ifdef _TEX_TEST makeHashString( hashname, getFileNameFromPath( "4By4Tex.dds" ), c1, c2, c3, c4 ); #else makeHashString( hashname, getFileNameFromPath( texname ), c1, c2, c3, c4 ); #endif { THREAD_SYNCRONIZE( g_texture_CS ); if ( m_texByName.lookup( hashname, restex ) == true) return restex; } if ( c1 == 0 && c2 == 0 && c3 == 0 && c4 == 0 ) { #ifdef _TEX_TEST restex = loadTexture( "4By4Tex.dds", pLoadPack, true, nTextureQuality ); #else restex = loadTexture( texname, pLoadPack, true, nTextureQuality ); #endif } else { #ifdef _TEX_TEST restex = loadColorizedTexture( "4By4Tex.dds", pLoadPack, c1, c2, c3, c4, nTextureQuality, nMode ); #else restex = loadColorizedTexture( texname, pLoadPack, c1, c2, c3, c4, nTextureQuality, nMode ); #endif } { THREAD_SYNCRONIZE( g_texture_CS ); if(restex) { restex->SetLoadedTime( GetSafeTickCount() ); restex->SetName( hashname); // _oprint( "m_texByName.add 02: %d %s\n", restex->GetID(), hashname ); restex->SetManagedByTexManager(); m_texByName.add( hashname, restex ); // doesn't null-check for performance } } return restex; } K3DTexture* KTextureManager::GetTexture( K3DTexture *tex, const NX3LoadPack * pLoadPack, DWORD c1, DWORD c2, DWORD c3, DWORD c4, int nTextureQuality, short nMode/* = 0*/ ) { if ( tex == NULL ) return NULL; char filename[_MAX_PATH]; makeFileName( filename, tex->GetName() ); return GetTexture( filename, pLoadPack, c1, c2, c3, c4, nTextureQuality, nMode ); } K3DTexture* KTextureManager::RefreshTexture( const char *texname, const NX3LoadPack * pLoadPack, DWORD c1, DWORD c2 /* = 0 */, DWORD c3 /* = 0 */, DWORD c4 /* = 0 */ ) { K3DTexture *restex = NULL; char hashname[_MAX_PATH]; makeHashString( hashname, getFileNameFromPath( texname ), c1, c2, c3, c4 ); THREAD_SYNCRONIZE( g_texture_CS ); if ( m_texByName.lookup( hashname, restex ) == true ) { if ( restex == NULL ) { // _oprint( "m_texByName.erase 02 : %d %s\n", restex->GetID(), hashname ); m_texByName.erase( hashname ); return GetTexture( texname, pLoadPack, c1, c2, c3, c4 ); } char tempname[_MAX_PATH]; tempname[_MAX_PATH-1] = '\0'; strcpy( tempname, texname ); KStream *stream = NULL; if ( m_policy & ORG_ONLY && !checkExtFromFileName(texname,"DDS") ) { stream = KFileManager::Instance().CreateStreamFromResource( texname ); } if ( (!stream && (m_policy & DDS_ONLY)) || checkExtFromFileName(texname,"DDS") ) { if( KNX3Manager::GetManager()->GetSystemRequirements() == KNX3Manager::MINIMUM_SYSTEM || KNX3Manager::GetManager()->GetSystemRequirements() == KNX3Manager::MINIMUM_SYSTEM_BY_USER_SELECT ) { changeExtFromFileName( tempname, pLoadPack ? 1 : 0, "DDS" ); } else { changeExtFromFileName( tempname, pLoadPack ? pLoadPack->nLoad_Level : 0, "DDS" ); } stream = KFileManager::Instance().CreateStreamFromResource( tempname ); } if ( stream ) { restex->Refresh( *stream, GetMipMapBiasLevel() ); KFileManager::Instance().DeleteStream( stream ); return restex; } //m_policy 설정에 따라 dds가 아닌 원본 파일이 우선 load 될 수 있다. /* KStream *stream = KFileManager::Instance().CreateStreamFromResource( tempname ); if ( stream ) { restex->Refresh( *stream, GetMipMapBiasLevel() ); KFileManager::Instance().DeleteStream( stream ); return restex; } else { stream = KFileManager::Instance().CreateStreamFromResource( texname ); if ( stream ) { restex->Refresh( *stream, GetMipMapBiasLevel() ); KFileManager::Instance().DeleteStream( stream ); return restex; } }*/ } return GetTexture(texname, pLoadPack, c1, c2, c3, c4, GetMipMapBiasLevel() ); } K3DTexture* KTextureManager::GetTexture(KStream& stream,const char *texname, const NX3LoadPack * pLoadPack, int nTextureQuality ) { K3DTexture *restex = NULL; char hashname[_MAX_PATH]; makeHashString( hashname, getFileNameFromPath( texname ), 0, 0, 0, 0 ); { THREAD_SYNCRONIZE( g_texture_CS ); if ( m_texByName.lookup( hashname, restex ) == true ) return restex; } restex = loadTexture( stream, pLoadPack, nTextureQuality ); { THREAD_SYNCRONIZE( g_texture_CS ); if(restex) { restex->SetLoadedTime( GetSafeTickCount() ); restex->SetName( hashname ); // for later use // _oprint( "m_texByName.add 03: %d %s\n", restex->GetID(), hashname ); restex->SetManagedByTexManager(); m_texByName.add( hashname, restex ); // doesn't null-check for performance } return restex; } } static const char *getTextureFormatInfo( int nFormat ) { struct TextureFormatInfo { int nFormat; char* pszName; }; static TextureFormatInfo s_TextureFormatInfo[] = { {K3DFMT_UNKNOWN, "K3DFMT_UNKNOWN"}, {K3DFMT_R8G8B8, "K3DFMT_R8G8B8"}, {K3DFMT_A8R8G8B8, "K3DFMT_A8R8G8B8"}, {K3DFMT_X8R8G8B8, "K3DFMT_X8R8G8B8"}, {K3DFMT_R5G6B5, "K3DFMT_R5G6B5"}, {K3DFMT_X1R5G5B5, "K3DFMT_X1R5G5B5"}, {K3DFMT_A1R5G5B5, "K3DFMT_A1R5G5B5"}, {K3DFMT_A4R4G4B4, "K3DFMT_A4R4G4B4"}, {K3DFMT_R3G3B2, "K3DFMT_R3G3B2"}, {K3DFMT_A8, "K3DFMT_A8"}, {K3DFMT_A8R3G3B2, "K3DFMT_A8R3G3B2"}, {K3DFMT_X4R4G4B4, "K3DFMT_X4R4G4B4"}, {K3DFMT_A2B10G10R10, "K3DFMT_A2B10G10R10"}, {K3DFMT_G16R16, "K3DFMT_G16R16"}, {K3DFMT_A8P8, "K3DFMT_A8P8"}, {K3DFMT_P8, "K3DFMT_P8"}, {K3DFMT_L8, "K3DFMT_L8"}, {K3DFMT_A8L8, "K3DFMT_A8L8"}, {K3DFMT_A4L4, "K3DFMT_A4L4"}, {K3DFMT_V8U8, "K3DFMT_V8U8"}, {K3DFMT_L6V5U5, "K3DFMT_L6V5U5"}, {K3DFMT_X8L8V8U8, "K3DFMT_X8L8V8U8"}, {K3DFMT_Q8W8V8U8, "K3DFMT_Q8W8V8U8"}, {K3DFMT_V16U16, "K3DFMT_V16U16"}, {K3DFMT_W11V11U10, "K3DFMT_W11V11U10"}, {K3DFMT_A2W10V10U10, "K3DFMT_A2W10V10U10"}, {K3DFMT_UYVY, "K3DFMT_UYVY"}, {K3DFMT_YUY2, "K3DFMT_YUY2"}, {K3DFMT_DXT1, "K3DFMT_DXT1"}, {K3DFMT_DXT2, "K3DFMT_DXT2"}, {K3DFMT_DXT3, "K3DFMT_DXT3"}, {K3DFMT_DXT4, "K3DFMT_DXT4"}, {K3DFMT_DXT5, "K3DFMT_DXT5"}, {K3DFMT_D16_LOCKABLE, "K3DFMT_D16_LOCKABLE"}, {K3DFMT_D32, "K3DFMT_D32"}, {K3DFMT_D15S1, "K3DFMT_D15S1"}, {K3DFMT_D24S8, "K3DFMT_D24S8"}, {K3DFMT_D16, "K3DFMT_D16"}, {K3DFMT_D24X8, "K3DFMT_D24X8"}, {K3DFMT_D24X4S4, "K3DFMT_D24X4S4"}, {K3DFMT_VERTEXDATA, "K3DFMT_VERTEXDATA"}, {K3DFMT_INDEX16, "K3DFMT_INDEX16"}, {K3DFMT_INDEX32, "K3DFMT_INDEX32"}, {K3DFMT_R32F, "K3DFMT_R32F"}, {K3DFMT_FORCE_DWORD, "K3DFMT_FORCE_DWORD"}, { 0, NULL }, }; TextureFormatInfo *p = &s_TextureFormatInfo[0]; while( p->pszName ) { if( p->nFormat == nFormat ) return p->pszName; p++; } return "UNKNOWN"; } K3DTexture* KTextureManager::loadTexture( const char *texname, const NX3LoadPack * pLoadPack, bool bRegMissingRes, int nTextureQuality ) { DWORD dwStartTime = GetSafeTickCount(); // _oprint( "loadTexture %s\n", texname ); K3DTexture* restex = NULL; KStream* stream = NULL; char tempname[_MAX_PATH]; std::vector< std::string > vList; if ( m_policy & ORG_ONLY && !checkExtFromFileName(texname,"DDS") ) { vList.clear(); tempname[_MAX_PATH-1] = '\0'; strcpy( tempname, texname ); //if ( m_policy == DDS_ONLY ) // changeExtFromFileName( tempname, pLoadPack ? pLoadPack->nLoad_Level : 0, "DDS" ); XStringUtil::Split( tempname, vList, "\\", false ); assert( vList.size() ); //if (vList.empty()) //{ // // Fraun texture change // return nullptr; //} stream = KFileManager::Instance().CreateStreamFromResource( vList.back().c_str() ); } if ( (!stream && (m_policy & DDS_ONLY)) || checkExtFromFileName(texname,"DDS") ) { vList.clear(); tempname[_MAX_PATH-1] = '\0'; strcpy( tempname, texname ); if( KNX3Manager::GetManager()->GetSystemRequirements() == KNX3Manager::MINIMUM_SYSTEM || KNX3Manager::GetManager()->GetSystemRequirements() == KNX3Manager::MINIMUM_SYSTEM_BY_USER_SELECT ) { changeExtFromFileName( tempname, pLoadPack ? 1 : 0, "DDS" ); } else { changeExtFromFileName( tempname, pLoadPack ? pLoadPack->nLoad_Level : 0, "DDS" ); } XStringUtil::Split( tempname, vList, "\\", false ); stream = KFileManager::Instance().CreateStreamFromResource( vList.back().c_str() ); if ( !stream ) { vList.clear(); tempname[_MAX_PATH-1] = '\0'; strcpy( tempname, texname ); changeExtFromFileName( tempname, 0, "DDS" ); XStringUtil::Split( tempname, vList, "\\", false ); stream = KFileManager::Instance().CreateStreamFromResource( vList.back().c_str() ); } } int nSize = 0; if ( stream ) { nSize = stream->GetLength(); restex = loadTexture( *stream, pLoadPack, nTextureQuality ); KFileManager::Instance().DeleteStream( stream ); _oprint( "\n"); } else { /// 2012.04.05 다른 내용 디버깅에 방해가 되서 주석 처리함 - prodongi //_oprint( "loadTexture Not Found %s\n", tempname ); } // 여기의 assert() 와 경고박스를 절.대.로. 없애지 말것!!! // 해결 방법은 assert() 를 지우는것이 아니라 없는 리소스를 읽는 일이 없도록 만드는 것임. #ifndef NDEBUG if( !restex ) { // char buf[1024]; std::string buf; XStringUtil::Format( buf, "Attempted to read a non-existent texture: %s\n", texname ); if( ENV().IsExist( "no_err_box" ) == false ) { //::MessageBox( ::g_hWnd, buf.c_str() , "RESOURCE ERROR", MB_OK | MB_ICONEXCLAMATION ); } } #endif DWORD dwLoadTime = GetSafeTickCount() - dwStartTime; int nTextureFormat = 0; if( restex ) { nTextureFormat = restex->GetFormat(); restex->GetTextureMode((char*)texname); } // If the texture loading time takes more than 20ms, the format is not DXT-compressed, or it's larger than 256KB, a loading log will be recorded if( restex && ( dwLoadTime >= 30 || ( nTextureFormat != K3DFMT_DXT1 && nTextureFormat != K3DFMT_DXT2 && nTextureFormat != K3DFMT_DXT3 && nTextureFormat != K3DFMT_DXT4 && nTextureFormat != K3DFMT_DXT5 ) || nSize > 256*1024 ) ) { _oprint( "TEXLOG : %s (%dms) (%dKB) (%dx%d) (%s) (Mips:%d) (%d:%d) ThreadId:%d", tempname, dwLoadTime, nSize/1024, restex->GetWidth(), restex->GetHeight(), getTextureFormatInfo( nTextureFormat ), restex->GetMipsLevels(), pLoadPack == 0 ? 1 : 0, pLoadPack ? pLoadPack->nLoad_Level : 0, GetCurrentThreadId() ); } return restex; } K3DTexture* KTextureManager::loadTexture( KStream& stream, const NX3LoadPack * pLoadPack, int nTextureQuality ) { K3DTexture *restex = NULL; if (stream.IsValid() ) { restex = KDeviceManager::GetDeviceManager()->GetRenderDevice()->CreateTexture( stream, nTextureQuality ); return restex; } return NULL; } K3DTexture* KTextureManager::loadColorizedTexture( const char *texname, const NX3LoadPack * pLoadPack, DWORD c1, DWORD c2, DWORD c3, DWORD c4, int nTextureQuality, short nMode ) { K3DTexture *restex = GetTexture( texname, pLoadPack, true, nTextureQuality ); if(restex) { int height = restex->GetHeight(); int width = restex->GetWidth(); K3DTexture *newtex = KDeviceManager::GetDeviceManager()->GetRenderDevice()->CreateTexture( width, height, K3DFMT_A8R8G8B8, D3DPOOL_MANAGED, restex->GetMipsLevels() ); if( newtex ) { newtex->SetColorizedMode( nMode ); //기존 텍스쳐 밉맵 포함 복사, 포맷에 상관 없이 가능 if( restex->LoadSurfaceFromSurface( newtex, c1, c2, c3, c4, nMode ) != S_OK ) return NULL; newtex->GetTextureMode((char*)texname); return newtex; } } return NULL; } K3DTexture* KTextureManager::GetTextureOriginal( const char *texname, const NX3LoadPack * pLoadPack, bool bRegMissingRes/* = true*/ ) { // 없는 텍스쳐라우.. if( !texname || *texname == '0' ) return NULL; K3DTexture* pTex = GetTexture( texname, pLoadPack, bRegMissingRes, 10000 ); if ( pTex ) pTex->Flags() |= TEXFLAG_ORIGINAL; return pTex; } void KTextureManager::RemoveTexture( K3DTexture *tex ) { THREAD_SYNCRONIZE( g_texture_CS ); if ( tex != NULL ) { if( strlen(tex->GetName()) > 0 && tex->GetManagedByTexManager() ) { // _oprint( "m_texByName.erase 01 : %d %s\n", tex->GetID(), tex->GetName() ); m_texByName.erase( tex->GetName() ); } } } int KTextureManager::GetMipMapBiasLevel() { return m_nTextureQualityLevel; } void KTextureManager::SetMipMapBiasLevel( int nLevel ) { if( m_nTextureQualityLevel != nLevel ) { m_nTextureQualityLevel = nLevel; _oprint( "Adjust texture quality (nLevel: %d)\n", m_nTextureQualityLevel ); //KDeviceManager::GetDeviceManager()->GetRenderDevice()->SetMipBias((float) nLevel * 0.5f); } } void KTextureManager::ReloadRes( bool bRepair, unsigned char withMask, unsigned char withoutMask ) { bool res; char buf[_MAX_PATH]; KHash::node *_node = NULL; THREAD_SYNCRONIZE( g_texture_CS ); res = m_texByName.get_first_node( _node ); int nTexQuality = GetMipMapBiasLevel(); //TODO : 리소스 옵션 로딩 추가 작업 중. NX3LoadPack loadpack; loadpack.Init(); DWORD c1, c2, c3, c4; for (; res; res = m_texByName.get_next_node( _node ) ) { if ( _node->value != NULL ) { unsigned char flags = _node->value->GetFlags(); if ( withMask != 0 && (flags & withMask) != withMask ) continue; if ( withoutMask != 0 && (flags & withoutMask) != 0 ) continue; makeFileName( buf, _node->key.m_pStr ); makeColor( _node->key.m_pStr, c1, c2, c3, c4 ); // 리전이나 셀렉트관련 텍스쳐는 텍스쳐설정과 상관없이 최상옵션으로 적용된다. if ( !strcmp ( buf, "rcfx_skillregion_on.dds" ) || !strcmp ( buf, "rcfx_select_on01.dds" ) || !strcmp ( buf, "rcfx_select_on02.dds" ) ) continue; // m_policy옵션에 따라 원래 확장자를 dds확장자보다 우선순위를 높인다. KStream *stream = NULL; if ( m_policy & ORG_ONLY && !checkExtFromFileName(buf,"DDS") ) { stream = KFileManager::Instance().CreateStreamFromResource( buf ); } if ( (!stream && (m_policy & DDS_ONLY)) || checkExtFromFileName(buf,"DDS") ) { if( KNX3Manager::GetManager()->GetSystemRequirements() == KNX3Manager::MINIMUM_SYSTEM || KNX3Manager::GetManager()->GetSystemRequirements() == KNX3Manager::MINIMUM_SYSTEM_BY_USER_SELECT ) { changeExtFromFileName( buf, 1, "DDS" ); } else { changeExtFromFileName( buf, loadpack.GetTextureLevel(), "DDS" ); } stream = KFileManager::Instance().CreateStreamFromResource( buf ); } /* if( KNX3Manager::GetManager()->GetSystemRequirements() == KNX3Manager::MINIMUM_SYSTEM || KNX3Manager::GetManager()->GetSystemRequirements() == KNX3Manager::MINIMUM_SYSTEM_BY_USER_SELECT ) { changeExtFromFileName( buf, 1, "DDS" ); } else { changeExtFromFileName( buf, loadpack.GetTextureLevel(), "DDS" ); }*/ bool bFind = flags & TEXFLAG_ORIGINAL; if( c1 != 0 || c2 != 0 || c3 != 0 || c4 != 0 ) { //칼라 라이즈 된 텍스쳐 //_LEAK_SUN if( stream ) KFileManager::Instance().DeleteStream( stream ); } else { //KStream *stream = KFileManager::Instance().CreateStreamFromResource( buf ); if ( stream ) { //복구가 아니라면, bFind는 다시 Load 할 필요가 없다. if( bRepair ) //복구는 다 Load _node->value->Refresh( *stream, bFind ? 0 : GetMipMapBiasLevel() ); else { //복구가 아니다. 텍스쳐 퀄리티가 0인 것은 다시 로드 하지 않는다. if( !bFind ) _node->value->Refresh( *stream, GetMipMapBiasLevel() ); } KFileManager::Instance().DeleteStream( stream ); } } } else { //여기는 애초에 리소스를 찾지 못 했을 경우에 들어 온다. makeFileName( buf, _node->key.m_pStr ); //Load 가 처음 부터 안되었으므로 모두 다시 Load 시도 한다. _node->value = loadTexture( buf, &loadpack, true, GetMipMapBiasLevel() ); } } } void KTextureManager::DiscardAll() { K3DTexture *tex; bool res; THREAD_SYNCRONIZE( g_texture_CS ); res = m_texByName.get_first_value( tex ); while ( res ) { if ( tex != NULL ) { tex->Discard(); } res = m_texByName.get_next_value( tex ); } m_texByName.clear(); } /////////////////////////////////////////////////////////////////////////////////////////////////////////////////// //KSoundManager Implement /////////////////////////////////////////////////////////////////////////////////////////////////////////////////// //KSoundManager *KSingletoneResourceManager::s_pStaticManager = new KSoundManager; //KSoundManager::KSoundManager() //{ //} //KSoundManager::~KSoundManager() //{ // DiscardAll(); //} // //KSoundData* KSoundManager::GetSound(const char * soundName) //{ // KSoundData * pSound = NULL; // // char lower_name[MAX_PATH]; // strcpy( lower_name, soundName ); // strlwr( lower_name ); // // if ( m_soundByName.lookup( lower_name, pSound ) == true ) // return pSound; // // THREAD_SYNCRONIZE( &KResourceManager::GetLockInstance() ); // // pSound = _LoadSound(lower_name); // if(pSound) // { // m_soundByName.add(lower_name,pSound); // } // // // // return pSound; // //} //void KSoundManager::ReloadRes() //{ // bool res; // KHash::node *_node = NULL; // // THREAD_SYNCRONIZE( &KResourceManager::GetLockInstance() ); // // res = m_soundByName.get_first_node( _node ); // while ( res ) // { // if ( _node->value != NULL ) // { // _node->value->Reload(KDeviceManager::GetDeviceManager()->GetSoundDevice() ); // } // else // { // _node->value = _LoadSound(_node->key.m_pStr); // } // res = m_soundByName.get_next_node( _node ); // } //} // //void KSoundManager::DiscardAll() //{ // KSoundData *pSound; // bool res; // // THREAD_SYNCRONIZE( &KResourceManager::GetLockInstance() ); // // res = m_soundByName.get_first_value( pSound ); // while ( res ) // { // if ( pSound != NULL ) // delete pSound; // // res = m_soundByName.get_next_value( pSound); // } // m_soundByName.clear(); // // //} // // //KSoundData* KSoundManager::_LoadSound( const char *soundName) //{ // KSoundData *resSound = new KSoundData; // // std::string validName = KResourceManager::GetValidFileName(soundName); // // if ( validName.size() > 0) // { // if( resSound->LoadWAV(validName.c_str(), KDeviceManager::GetDeviceManager()->GetSoundDevice()) ) // { // resSound->SetName( soundName ); // for later use // return resSound; // } // else // { // SAFE_DELETE(resSound); // } // } // // return NULL; //} XCriticalSection g_nx3_CS; /////////////////////////////////////////////////////////////////////////////////////////////////////////////////// //KNX3Manager Implement /////////////////////////////////////////////////////////////////////////////////////////////////////////////////// bool loadNX3( const char * szName, const NX3LoadPack * plodpack, KStream &stream, NX3SET *nx3set ); void loadMesh( std::vector &vecMeshSeq, std::vector &vecFXSeq, std::vector &vecEvSeq, KNX3Mesh *mesh, std::vector &tmList ); KFXSeq *loadFXBillboard( KNX3Mesh *mesh, KNX3FX *fx ); KFXSeq *loadFXParticle( KNX3Mesh *mesh, KNX3FX *fx, DWORD dwParticleType); KFXSeq *loadFXAfterImage( KNX3Mesh *mesh, KNX3FX *fx); struct NX3SET { NX3SET() { // nRefCount = 0; // _oprint( "NX3 CREATE : (0x%08X)\n", this ); } ~NX3SET(); // int nRefCount; std::string strName; std::string strProperty; std::vector< KSeqObject* > vpMeshSeq; std::vector< KSeqObject* > vpFXSeq; std::vector< KSeqObject* > vpLightSeq; std::vector< KSeqObject* > vpCamSeq; std::vector< KSeqObject* > vpEventSeq; std::vector< KSeqObject* > vpBoneSeq; std::vector< KSeqObject* > vpPfxSeq; }; struct NX3Data { #ifdef NDEBUG NX3Data() : m_LRUList( 10, true ) #else NX3Data() : m_LRUList( 10, true ) #endif { } bool AddToLoadingList( const char *szResourceName ) { THREAD_SYNCRONIZE( &m_lock ); if( IsLoading( szResourceName ) ) return false; m_vLoadingList.push_back( szResourceName ); return true; } bool RemoveFromLoadingList( const char *szResourceName ) { THREAD_SYNCRONIZE( &m_lock ); if( !IsLoading( szResourceName ) ) return false; for( std::vector< std::string >::iterator it = m_vLoadingList.begin(); it != m_vLoadingList.end(); ++it ) { if( _stricmp( (*it).c_str(), szResourceName ) ) continue; m_vLoadingList.erase( it ); return true; } return false; } bool IsLoading( const char *szResourceName ) { THREAD_SYNCRONIZE( &m_lock ); for( std::vector< std::string >::iterator it = m_vLoadingList.begin(); it != m_vLoadingList.end(); ++it ) { if( _stricmp( (*it).c_str(), szResourceName ) ) continue; return true; } return false; } size_t GetLoadingCount() { THREAD_SYNCRONIZE( &m_lock ); return m_vLoadingList.size(); } XCriticalSection m_lock; std::vector< std::string > m_vLoadingList; XLRUCacheContainer< std::string, hashPr_string_nocase, NX3SET* > m_LRUList; }; KNX3Manager *KSingletoneResourceManager::s_pStaticManager = new KNX3Manager; KNX3Manager::SYSTEM_REQUIREMENTS KNX3Manager::s_nSysRequirements = KNX3Manager::MIXED_SYSTEM; KNX3Manager::KNX3Manager() // 5분동안 사용 안되면 사라짐 { m_pNX3Data = new NX3Data; } KNX3Manager::~KNX3Manager() { DiscardAll(); delete m_pNX3Data; } void KNX3Manager::ReloadRes( bool bRepair ) { } void KNX3Manager::ExceptListPrint() { THREAD_SYNCRONIZE( &g_nx3_CS ); std::vector< std::string > vExceptList; m_pNX3Data->m_LRUList.EnumExceptList( vExceptList ); if( !vExceptList.empty() ) { std::vector< std::string >::iterator it; std::sort( vExceptList.begin(), vExceptList.end() ); KFileStream * pFileStream = new KFileStream( "ExceptList.txt", KFileStream::wronly ); pFileStream->Seek( 0, KFileStream::seekSet ); std::string strline = "\r\n"; std::string strRef; for( it = vExceptList.begin(); it != vExceptList.end(); ++it ) { pFileStream->Write( (*it).c_str(), (*it).length() ); pFileStream->Write( strline.c_str(), strline.length() ); } XStringUtil::Format( strline, "\r\nTotal ExceptList Cnt : %d\r\n", vExceptList.size() ); pFileStream->Write( strline.c_str(), strline.length() ); delete pFileStream; } } void KNX3Manager::AddToExceptList( const char * pName ) { THREAD_SYNCRONIZE( &g_nx3_CS ); if( !m_pNX3Data->m_LRUList.IsInExceptList( pName ) ) m_pNX3Data->m_LRUList.AddToExceptList( pName ); } void KNX3Manager::RemoveFromExceptList( const char * pName ) { THREAD_SYNCRONIZE( &g_nx3_CS ); m_pNX3Data->m_LRUList.RemoveFromExceptList( pName ); } bool KNX3Manager::IsInExceptList( const char * pName ) { THREAD_SYNCRONIZE( &g_nx3_CS ); return m_pNX3Data->m_LRUList.IsInExceptList( pName ); } void KNX3Manager::ClearExceptList() { THREAD_SYNCRONIZE( &g_nx3_CS ); m_pNX3Data->m_LRUList.ClearExceptList(); } void KNX3Manager::ClearUnreferencedResource() { // assert( _CrtCheckMemory() && "Memory Error!!!" ); THREAD_SYNCRONIZE( &g_nx3_CS ); m_pNX3Data->m_LRUList.ClearUnreferencedResource(); // assert( _CrtCheckMemory() && "Memory Error!!!" ); } void KNX3Manager::DiscardAll() { THREAD_SYNCRONIZE( &g_nx3_CS ); m_pNX3Data->m_LRUList.Clear(); } NX3SET::~NX3SET() { THREAD_SYNCRONIZE( &g_nx3_CS ); if ( !vpMeshSeq.empty() ) { for ( size_t i=0 ; i::iterator it; std::vector< NX3SET* > vNX3List; m_pNX3Data->m_LRUList.Enum( vNX3List ); // m_pNX3Data->m_LRUList.PrintList(); std::vector< PR_DATA > strFileList; if( !vNX3List.empty() ) { for( it = vNX3List.begin(); it != vNX3List.end(); ++it ) { NX3SET* pSet = (*it); PR_DATA pr; pr.pStr = pSet->strName.c_str(); pr.nRef = 0; strFileList.push_back( pr ); } } if( !strFileList.empty() ) { std::vector< PR_DATA >::iterator it; std::sort( strFileList.begin(), strFileList.end(), PrintCompareFN() ); KFileStream * pFileStream = new KFileStream( pOutFileName, KFileStream::wronly ); pFileStream->Seek( 0, KFileStream::seekSet ); std::string strline = "\r\n"; std::string strRef; for( it = strFileList.begin(); it != strFileList.end(); ++it ) { pFileStream->Write( (*it).pStr, strlen((*it).pStr) ); XStringUtil::Format( strRef, " - Ref Count : %d ", (*it).nRef ); pFileStream->Write( strRef.c_str(), strRef.length() ); pFileStream->Write( strline.c_str(), strline.length() ); } XStringUtil::Format( strline, "\r\nTotal NX3 Cnt : %d\r\n", strFileList.size() ); pFileStream->Write( strline.c_str(), strline.length() ); delete pFileStream; } ExceptListPrint(); } void KNX3Manager::EventTime( DWORD dwTime ) { THREAD_SYNCRONIZE( &g_nx3_CS ); #ifdef _MEMORY_LEAK_FIX_ static DWORD LRU_CHECK_INTERVAL = 0; #else const DWORD LRU_CHECK_INTERVAL = 20000; #endif static DWORD m_PrevTime = dwTime; if( m_PrevTime + LRU_CHECK_INTERVAL < dwTime ) { m_pNX3Data->m_LRUList.Process(); m_PrevTime = dwTime; } } void KNX3Manager::addSeqObjectToSeq( KSequencer* & seq, std::vector< KSeqObject* > & vObj ) { if( vObj.empty() ) return; if ( seq == NULL ) seq = new KSequencer(true); for ( size_t i=0 ; iAddSeqObject( vObj[i]->Clone() ); } } struct NX3ThreadLoader : XBossWorker::XWorker { NX3ThreadLoader( const char *szName, NX3Data *pData, const NX3LoadPack * plodpack ) : m_strName( szName ), m_pNX3Data( pData ), m_loadpack(*plodpack) {} virtual bool onProcess( int nThreadNum ) { DWORD dwTime = GetSafeTickCount(); KStream *stream = KFileManager::Instance().CreateStreamFromResource( m_strName.c_str() ); if ( stream == NULL ) return false; size_t nSize = stream->GetLength(); NX3SET *nx3set = NULL; nx3set = new NX3SET; if ( !loadNX3( m_strName.c_str(), &m_loadpack, *stream, nx3set ) ) { { THREAD_SYNCRONIZE( &g_nx3_CS ); m_pNX3Data->RemoveFromLoadingList( m_strName.c_str() ); assert( 0 ); } KFileManager::Instance().DeleteStream( stream ); delete nx3set; return false; } KFileManager::Instance().DeleteStream( stream ); { THREAD_SYNCRONIZE( &g_nx3_CS ); nx3set->strName = m_strName.c_str(); m_pNX3Data->m_LRUList.Add( m_strName.c_str(), nx3set, true ); } DWORD dwLoadTime = GetSafeTickCount() - dwTime; if( dwLoadTime > 50 ) { _oprint( "NX3] END THREAD LOADING : %s (%dms) (%dKB) : %d\n", m_strName.c_str(), dwLoadTime, nSize/1024, GetCurrentThreadId() ); } return true; } virtual void onEnd( bool bIsCancel ) { m_pNX3Data->RemoveFromLoadingList( m_strName.c_str() ); delete this; } NX3LoadPack m_loadpack; NX3Data* m_pNX3Data; std::string m_strName; }; //#define _NOT_THREAD_LOAD_ void KNX3Manager::RequestThreadLoading( const char *resname, const NX3LoadPack * plodpack ) { { THREAD_SYNCRONIZE( &g_nx3_CS ); if( m_pNX3Data->m_LRUList.IsExist( resname ) || m_pNX3Data->IsLoading( resname ) ) return; m_pNX3Data->AddToLoadingList( resname ); // _oprint( "RequestThreadLoading : %s\n", resname ); } #ifdef _NOT_THREAD_LOAD_ NX3ThreadLoader load( resname, this->m_pNX3Data, plodpack ); load.onProcess(0); #else KThreadResource::PendWorkToThreadPool( new NX3ThreadLoader( resname, this->m_pNX3Data, plodpack ) ); #endif } size_t KNX3Manager::GetThreadLoadingCount() const { { THREAD_SYNCRONIZE( &g_nx3_CS ); return m_pNX3Data->GetLoadingCount(); } } KSequencer *KNX3Manager::CreateSequencer( const char *resname, const NX3LoadPack * plodpack, int reqtype ) { // assert( _CrtCheckMemory() && "Memory Error!!!" ); bool bCheckValidRes = true; const char* pResultName = resname; if( s_nSysRequirements == MINIMUM_SYSTEM || s_nSysRequirements == MINIMUM_SYSTEM_BY_USER_SELECT ) { char resorucename[_MAX_PATH]; strcpy( resorucename, resname ); if( resname != NULL ) { char szExtName[10]; const char* pExtName = getExtFromFileName( resname ); if( pExtName ) { strcpy( szExtName, pExtName ); changeExtFromFileName( resorucename, 1, szExtName ); if( KFileManager::Instance().IsValidResource( resorucename ) ) { pResultName = resorucename; bCheckValidRes = false; } } } } if( bCheckValidRes ) { if( !KFileManager::Instance().IsValidResource( pResultName ) ) return NULL; } NX3SET *nx3set = NULL; bool bRtn = false; { THREAD_SYNCRONIZE( &g_nx3_CS ); bRtn = m_pNX3Data->m_LRUList.Get( pResultName, &nx3set ); } // 이미 nx3set 이 캐쉬에 있는 경우 if( bRtn ) { // assert( nx3set->nRefCount >= 0 && "당담자 호출!!!"); return getSequencerFromNX3Set( nx3set, reqtype ); } // { 없다면 NX3를 로딩해서 시퀀서를 만든다 return createSequencer( pResultName, plodpack, reqtype ); // } } KSequencer* KNX3Manager::createSequencer( const char *resname, const NX3LoadPack * plodpack, int reqtype ) { // assert( _CrtCheckMemory() && "Memory Error!!!" ); NX3SET *nx3set = NULL; bool bRtn = false; nx3set = new NX3SET; bool bIsLoading = false; { THREAD_SYNCRONIZE( &g_nx3_CS ); if( m_pNX3Data->m_LRUList.Get( resname, &nx3set ) ) { //assert( nx3set->nRefCount >= 0 && "당담자 호출!!!"); // _oprint( "NX3] Error Find! 01\n" ); return getSequencerFromNX3Set( nx3set, reqtype ); } // 이미 다른 쓰레드에서 로딩 중인지 검사 bIsLoading = m_pNX3Data->IsLoading( resname ); if( !bIsLoading ) m_pNX3Data->AddToLoadingList( resname ); } // 이미 다른 쓰레드에서 로딩 중이라면 로딩이 끝나는것을 기다려서 활용한다. if( bIsLoading ) { delete nx3set; nx3set = NULL; DWORD dwTime = GetSafeTickCount(); _oprint( "NX3] WAITING LOADING : %s\n", resname ); while( true ) { NX3SET *nx3set_cached = NULL; { THREAD_SYNCRONIZE( &g_nx3_CS ); m_pNX3Data->m_LRUList.Get( resname, &nx3set_cached ); } if( nx3set_cached ) { _oprint( "NX3] WAIT COMPLETE : %s (%dms)\n", resname, GetSafeTickCount() - dwTime ); // assert( nx3set_cached->nRefCount >= 0 && "당담자 호출!!!"); return getSequencerFromNX3Set( nx3set_cached, reqtype ); } Sleep( 20 ); } } KStream *stream = KFileManager::Instance().CreateStreamFromResource( resname ); if ( stream == NULL ) { // 여기의 assert() 와 경고박스를 절.대.로. 없애지 말것!!! // 해결 방법은 assert() 를 지우는것이 아니라 없는 리소스를 읽는 일이 없도록 만드는 것임. #ifndef NDEBUG // char buf[1024]; std::string buf; XStringUtil::Format( buf, "Tried to read a non-existent resource: %s\n", resname ); if( ENV().IsExist( "no_err_box" ) == false ) { //::MessageBox( ::g_hWnd, buf.c_str(), "RESOURCE ERROR", MB_OK | MB_ICONEXCLAMATION ); } #endif THREAD_SYNCRONIZE( &g_nx3_CS ); m_pNX3Data->RemoveFromLoadingList( resname ); return NULL; } if ( !loadNX3( resname, plodpack, *stream, nx3set ) ) { { THREAD_SYNCRONIZE( &g_nx3_CS ); m_pNX3Data->RemoveFromLoadingList( resname ); } KFileManager::Instance().DeleteStream( stream ); delete nx3set; return NULL; } KFileManager::Instance().DeleteStream( stream ); { THREAD_SYNCRONIZE( &g_nx3_CS ); nx3set->strName = resname; m_pNX3Data->RemoveFromLoadingList( resname ); m_pNX3Data->m_LRUList.Add( resname, nx3set ); } // assert( _CrtCheckMemory() && "Memory Error!!!" ); // NX3Set 으로부터 Sequencer 를 만들어 리턴 // _oprint( "NX3] Error Find! 02\n" ); return getSequencerFromNX3Set( nx3set, reqtype ); } KSequencer* KNX3Manager::getSequencerFromNX3Set( NX3SET *nx3set, int reqtype ) { // assert( _CrtCheckMemory() && "Memory Error!!!" ); KSequencer *seq = NULL; if ( nx3set == NULL ) return NULL; seq = NULL; if ( reqtype & SEQTYPE_CAMERA ) addSeqObjectToSeq( seq, nx3set->vpCamSeq ); if ( reqtype & SEQTYPE_LIGHT ) addSeqObjectToSeq( seq, nx3set->vpLightSeq ); if ( reqtype & SEQTYPE_BONE ) addSeqObjectToSeq( seq, nx3set->vpBoneSeq ); if ( reqtype & SEQTYPE_MESH ) { addSeqObjectToSeq( seq, nx3set->vpMeshSeq ); addSeqObjectToSeq( seq, nx3set->vpEventSeq ); } if ( reqtype & SEQTYPE_FX ) addSeqObjectToSeq( seq, nx3set->vpFXSeq ); if ( reqtype & SEQTYPE_PFX ) addSeqObjectToSeq( seq, nx3set->vpPfxSeq ); if ( seq ) { THREAD_SYNCRONIZE( &g_nx3_CS ); seq->SetName( nx3set->strName.c_str() ); seq->LoadProp( nx3set->strProperty.c_str() ); //m_pNX3Data->m_LRUList.AddRef( nx3set->strName ); //nx3set->nRefCount++; } // assert( _CrtCheckMemory() && "Memory Error!!!" ); return seq; } void KNX3Manager::ReleaseRes( const char *resname ) { THREAD_SYNCRONIZE( &g_nx3_CS ); //예외 리스트에 있으면 Skip if( m_pNX3Data->m_LRUList.IsInExceptList( resname ) ) return; if ( m_pNX3Data->m_LRUList.IsExist( resname ) == true ) { m_pNX3Data->m_LRUList.ReleaseRef( resname ); } } template< typename T > static inline T _min( const T& a, const T& b ) { return a < b ? a : b; } template< typename T > static inline T _max( const T& a, const T& b ) { return a > b ? a : b; } KFXSeq *loadFXBillboard( KNX3Mesh *mesh, KNX3FX *fx ) { if ( fx->GetFXElementSize() == 0 ) return NULL; KNX3FXElement *fxele = fx->GetFxElementByIndeX(0); if ( mesh->GetMeshElements().size() == 0 ) return NULL; KNX3MeshElement *meshele = mesh->GetMeshElements()[0]; if ( meshele->GetFrameCount() == 0 ) return NULL; KNX3MeshFrame *meshfr = meshele->GetFrame(0); K3DVertexBuffer *vb = meshfr->GetVertexBuffer();//Vertex Buffer Add 일어남 int stride = vb->GetVertexStride(); int count = vb->GetVertexCount(); if ( count < 4 ) return NULL; KFXBillboardSeq *seq = new KFXBillboardSeq; KResFXBillboard *res = new KResFXBillboard; res->SetRes( mesh->GetMatrixAniRes(), mesh->GetVisibilityRes() ); K3DVector ua = fxele->GetVectorValue( "uvani", K3DVector( 0.f, 0.f, 0.f ) ); res->SetUVAnimation( ua.x > .0f, static_cast(ua.y), static_cast< int >( ua.z ) ); res->SetAlignedCameraMode( fxele->GetNumValue( "align", 0 ) != 0 ); res->SetAdditiveRenderMode( fxele->GetNumValue( "rendertype", 0 ) != 0 ); int base, vari; base = 0; vari = 0; fxele->GetVariNumValue( "loop", &base, &vari ); res->SetLoopMode( base != 0 ); res->SetRange( fxele->GetFrameTime(), vari * 160 ); res->SetScale( fxele->Get2DVectorValue( "scale", K3DVector( 1.f, 1.f, 1.f ) ) ); res->SetFixedAxis( fxele->GetNumValue( "fixedaxis", -1 ) ); res->SetRotateSpeed( fxele->GetFloatValue( "rotatespeed", 0.0f ) ); K3DVector cube_min(100.f,100.f,100.f), cube_max(-100.f,-100.f,-100.f); char *vtxtempbuf = NULL; K3DVertex vtx[4]; vb->Lock( (void**)&vtxtempbuf, count ); if( vtxtempbuf ) { for ( int i=0 ; i<4 ; ++i ) { vtx[i] = *((K3DVertex*)vtxtempbuf); vtxtempbuf += stride; // make axis aligned cube cube_min.x = _min(cube_min.x , vtx[i].x); cube_min.y = _min(cube_min.y , vtx[i].y); cube_min.z = _min(cube_min.z , vtx[i].z); cube_max.x = _max(cube_max.x , vtx[i].x); cube_max.y = _max(cube_max.y , vtx[i].y); cube_max.z = _max(cube_max.z , vtx[i].z); } } vb->Unlock(); // vb->Release(); res->SetVertices( vtx ); res->SetTexture( meshele->GetTexture() ); seq->SetRes( res ); seq->SetCube( cube_min.x, cube_max.x, cube_min.y, cube_max.y, cube_min.z, cube_max.z ); return seq; } KFXSeq *loadFXParticle( KNX3Mesh *mesh, KNX3FX *fx, DWORD dwType) { if ( fx->GetFXElementSize() == 0 ) return NULL; KNX3FXElement *fxele = fx->GetFxElementByIndeX(0); if ( mesh->GetMeshElements().size() == 0 ) return NULL; KNX3MeshElement *meshele = mesh->GetMeshElements()[0]; if ( meshele->GetFrameCount() == 0 ) return NULL; KNX3MeshFrame *meshfr = meshele->GetFrame(0); K3DVertexBuffer *vb = meshfr->GetVertexBuffer();//Vertex Buffer Add 일어남 int stride = vb->GetVertexStride(); int count = vb->GetVertexCount(); if ( count < 4 ) { return NULL; } KFXParticleSeq *seq = new KFXParticleSeq(dwType); KResFXParticle *res = new KResFXParticle; res->SetRes( mesh->GetMatrixAniRes(), mesh->GetVisibilityRes() ); res->SetCreateTime( fxele->GetNumValue( "createtime", 100 ) ); res->SetBeginSpeed( fxele->GetVectorValue( "beginspeed", K3DVector( 1.f, 1.f, 1.f ) ) ); res->SetVelocity( fxele->GetVectorValue( "velocity", K3DVector( 1.f, 1.f, 1.f ) ) ); res->SetSpreadAngle( fxele->GetFloatValue( "angle", 0 ) ); int base, vari; base = 1000; vari = 0; fxele->GetVariNumValue( "lifetime", &base, &vari ); res->SetLifeTime( base, vari ); base = 0; vari = 0; fxele->GetVariNumValue( "loop", &base, &vari ); res->SetLoopMode( base != 0 ); res->SetRange( fxele->GetFrameTime(), vari * 160 ); res->SetScale( fxele->Get2DVectorValue( "scale", K3DVector( 1.f, 1.f, 1.f ) ) ); res->SetAdditiveRenderMode( fxele->GetNumValue( "rendertype", 0 ) != 0 ); K3DVector ua = fxele->GetVectorValue( "uvani", K3DVector( 0.f, 0.f, 0.f ) ); res->SetUVAnimation( ua.x > .0f, static_cast(ua.y), static_cast< int >( ua.z ) ); res->SetGravityAccel( fxele->GetFloatValue( "gravityaccel", 9.8f) ); res->SetGravity( fxele->GetVectorValue( "gravityvector", K3DVector( 0.f, 0.f, -1.f)) ); int attachparent = fxele->GetNumValue( "attachparent", 0 ); res->SetAttachParent( ( attachparent == 1 ) ); char *vtxtempbuf = NULL; K3DVertex vtx[4]; vb->Lock( (void**)&vtxtempbuf, count ); if( vtxtempbuf ) { for ( int i=0 ; i<4 ; ++i ) { vtx[i] = *((K3DVertex*)vtxtempbuf); vtxtempbuf += stride; } } vb->Unlock(); // vb->Release(); res->SetVertices( vtx ); res->CalcNormal( vtx ); res->SetTexture( meshele->GetTexture() ); seq->SetRes( res ); return seq; } KFXSeq *loadFXAfterImage( KNX3Mesh *mesh, KNX3FX *fx ) { if ( fx->GetFXElementSize() == 0 ) return NULL; KNX3FXElement *fxele = fx->GetFxElementByIndeX(0); if ( mesh->GetMeshElements().size() == 0 ) return NULL; KNX3MeshElement *meshele = mesh->GetMeshElements()[0]; if ( meshele->GetFrameCount() == 0 ) return NULL; KNX3MeshFrame *meshfr = meshele->GetFrame(0); K3DVertexBuffer *vb = meshfr->GetVertexBuffer(); //Vertex Buffer Add 일어남 int stride = vb->GetVertexStride(); int count = vb->GetVertexCount(); if ( count < 4 ) return NULL; KFXAfterImageSeq *seq = new KFXAfterImageSeq; KResFXAfterImage *res = new KResFXAfterImage; res->SetRes( mesh->GetMatrixAniRes(), mesh->GetVisibilityRes() ); int nFrameNumber = max( fxele->GetNumValue( "FrameNumber", 3 ), 1 ); int nFrameTime = max( fxele->GetNumValue( "FrameTime", 160 ), 1 ); res->SetFrameNumber( nFrameNumber ); res->SetFrameTime( nFrameTime ); res->SetBlendMode( meshele->GetBlendMode() ); char *vtxtempbuf = NULL; K3DVertex vtx[4]; vb->Lock( (void**)&vtxtempbuf, count ); if( vtxtempbuf ) { for ( int i=0 ; i<4 ; ++i ) { vtx[i] = *((K3DVertex*)vtxtempbuf); vtxtempbuf += stride; } } vb->Unlock(); // vb->Release(); res->SetVertices( vtx ); res->SetTexture( meshele->GetTexture() ); seq->SetRes( res ); return seq; } void loadMesh( std::vector &vecMeshSeq, std::vector &vecFXSeq, std::vector &vecEvSeq, KNX3Mesh *mesh, std::vector &tmList ) { std::vector &meshele = mesh->GetMeshElements(); if ( mesh->IsEventBox() ) { K3DResEventBox *pRes = new K3DResEventBox; pRes->SetName( mesh->GetMeshName() ); pRes->SetRes( mesh->GetMeshElements()[0]->GetEventCube(), mesh->GetMatrixAniRes() ); KEventBoxSeq *pSeq = new KEventBoxSeq; pSeq->SetRes( pRes ); vecEvSeq.push_back( pSeq ); return; } if ( mesh->IsEventPoint() ) { K3DResEventPoint *pResPoint = new K3DResEventPoint; pResPoint->SetName( mesh->GetMeshName() ); pResPoint->SetRes( mesh->GetMatrixAniRes() ); KEventPointSeq *pSeq = new KEventPointSeq; pSeq->SetRes( pResPoint ); vecEvSeq.push_back( pSeq ); return; } K3DMeshResource *pMeshRes = new K3DMeshResource; K3DResVertexAnimation **ppVbAni = new K3DResVertexAnimation*[meshele.size()]; K3DWeight ** ppWeight = new K3DWeight*[meshele.size()]; K3DMatrix * pNodeTM = new K3DMatrix[meshele.size()]; if( tmList.size() >0 ) { K3DMeshTM * pMeshTM = new K3DMeshTM[tmList.size()]; for( unsigned int i(0); tmList.size()>i; i++ ) { memset( &pMeshTM[i], 0, sizeof(pMeshTM[i]) ); memcpy( pMeshTM[i].szName, tmList[i]->szName, sizeof(pMeshTM[i].szName) ); memcpy( pMeshTM[i].fTM , tmList[i]->baseTM, sizeof(pMeshTM[i].fTM) ); pMeshTM[i].mTM = K3DMatrix(tmList[i]->baseTM); } pMeshRes->SetMeshTM( pMeshTM, static_cast(tmList.size()) ); delete [] pMeshTM; } if ( meshele.size() > 0 ) { K3DMatrix iden; K3DMatrixIdentity(iden); K3DBoundRotCube cube, t_cube; for(unsigned int it = 0; it < meshele.size(); ++it ) { t_cube = meshele[it]->GetEventCube(); t_cube.SetTransform(iden); cube.AddCube(t_cube); } pMeshRes->SetBound( cube, meshele[0]->GetBoundSphere() ); } pMeshRes->SetName( mesh->GetMeshName() ); const char * pName = mesh->GetMeshName(); for ( unsigned int n=0 ; nSetIndexBuffer( meshele[n]->GetIndexBuffer() ); ppVbAni[n]->SetIndexArray ( meshele[n]->GetIndexArray() ); ppVbAni[n]->SetPrimitivesInfo(meshele[n]->GetPrimitiveCount(), meshele[n]->GetSimultaneousFrameCount()); ppWeight[n] = NULL; KNX3MeshElement *mele = meshele[n]; ppVbAni[n]->SetKeyCount( mele->GetFrameCount() ); for ( int j=0 ; jGetFrameCount() ; ++j ) { KNX3MeshFrame *frame = mele->GetFrame(j); K3DResVertexAnimation::Key key; key.m_spVB = frame->GetVertexBuffer(); key.m_spVB_array = frame->GetVertexArray(); //충돌, 높낮이 용 key.time = frame->GetFrameTime(); ppVbAni[n]->SetKey( j, &key ); //Vertex Buffer Add 일어남 memcpy( &pNodeTM[n], frame->GetNodeTM(), sizeof(pNodeTM[n]) ); //Weight 덩어리가 프레임안에 덩어리루 있다. //Weight 값도 추가. if( j == 0 ) //처음 프레임에서만, 빼낸다. { nWeightCount = frame->GetBoneSize(); //가중치 블럭의 수 if( nWeightCount > 0 ) { if( tmList.size() <= 0 ) { _oprint( "Data Error: Bone weights exist, but the Mesh has no TM. Export failed. Mesh Name %s\n", pName ); } ppWeight[n] = new K3DWeight[nWeightCount]; std::vector< KNX3WeightElement * > WeightList = frame->GetWeightList(); for( size_t a(0); WeightList.size()>a; a++ ) { K3DWeight * pTmp = &(ppWeight[n][a]); pTmp->m_nTotal = nWeightCount; //Face Animation이 된다면, 수정해야 한다. //사용하는 본의 실제 인덱스... nUseBoneIndexCount = frame->GetUseBoneIndexCount(); if( nUseBoneIndexCount > 0 ) { pTmp->m_nUseBoneCount = nUseBoneIndexCount; pTmp->m_pUseBoneList = new int[nUseBoneIndexCount]; memcpy( pTmp->m_pUseBoneList, frame->GetUseBoneList(), sizeof(int)*nUseBoneIndexCount ); } KNX3WeightElement * pWE = WeightList[a]; //File 에서 Load 된것 #ifdef _DEBUG K3DWeight * pW = new K3DWeight; //Resource pW->m_nWeight = pWE->GetWeightSize(); strcpy( pTmp->m_szBoneName, pWE->GetBoneName() ); if( pW->m_nWeight>0 ) { pTmp->m_nWeight= pW->m_nWeight; float* pVertex = pWE->GetVertexIndex(); float* pWeight = pWE->GetVertexWeight(); pW->m_pVertexIndex = new float[pW->m_nWeight]; pW->m_pVertexWeight = new float[pW->m_nWeight]; // pW->m_pOffsetVector = new K3DVector[pW->m_nWeight]; pTmp->m_pVertexIndex = new float[pW->m_nWeight]; pTmp->m_pVertexWeight = new float[pW->m_nWeight]; for( int n(0); pW->m_nWeight>n; n++ ) { pW->m_pVertexIndex[n] = pVertex[n]; pW->m_pVertexWeight[n] = pWeight[n]; pTmp->m_pVertexIndex[n] = pVertex[n]; pTmp->m_pVertexWeight[n] = pWeight[n]; } // memcpy( pW->m_pVertexIndex , pWE->GetVertexIndex() , sizeof(float)*pW->m_nWeight ); // memcpy( pW->m_pVertexWeight, pWE->GetVertexWeight(), sizeof(float)*pW->m_nWeight ); //// memcpy( pW->m_pOffsetVector, pWE->GetOffSetVector(), sizeof(K3DVector)*pW->m_nWeight ); // memcpy( pTmp->m_pVertexIndex , pWE->GetVertexIndex() , sizeof(float)*pW->m_nWeight ); // memcpy( pTmp->m_pVertexWeight, pWE->GetVertexWeight(), sizeof(float)*pW->m_nWeight ); //// memcpy( pTmp->m_pOffsetVector, pWE->GetOffSetVector(), sizeof(K3DVector)*pW->m_nWeight ); } delete pW; #else if( pWE->GetWeightSize()>0 ) { pTmp->m_nWeight = pWE->GetWeightSize(); strcpy( pTmp->m_szBoneName, pWE->GetBoneName() ); pTmp->m_pVertexIndex = new float[pWE->GetWeightSize()]; pTmp->m_pVertexWeight = new float[pWE->GetWeightSize()]; // pTmp->m_pOffsetVector = new K3DVector[pWE->GetWeightSize()]; //Face Animation이 된다면, 수정해야 한다. nUseBoneIndexCount = frame->GetUseBoneIndexCount(); if( nUseBoneIndexCount > 0 ) { SAFE_DELETE_ARRAY(pTmp->m_pUseBoneList); pTmp->m_nUseBoneCount = nUseBoneIndexCount; pTmp->m_pUseBoneList = new int[nUseBoneIndexCount]; memcpy( pTmp->m_pUseBoneList, frame->GetUseBoneList(), sizeof(int)*nUseBoneIndexCount ); } memcpy( pTmp->m_pVertexIndex , pWE->GetVertexIndex() , sizeof(float)*pWE->GetWeightSize() ); memcpy( pTmp->m_pVertexWeight, pWE->GetVertexWeight(), sizeof(float)*pWE->GetWeightSize() ); // memcpy( pTmp->m_pOffsetVector, pWE->GetOffSetVector(), sizeof(K3DVector)*pWE->GetWeightSize() ); } #endif } } } } ppVbAni[n]->SetBlendMode( mele->GetBlendMode() ); ppVbAni[n]->SetMaterial( mele->GetMaterial() ); TEXPACK texpack; texpack.spTexture = mele->GetTexture(); texpack.spTexture_Bump = mele->GetBumpTexture(); texpack.spTexture_Illumin = mele->GetIlluminTexture(); texpack.spTexture_Specular = mele->GetSpecularTexture(); #ifdef _SPECULAR_EDITING_ texpack.spTexture_SpecularColor = mele->GetSpecularColorTexture(); #else texpack.spTexture_SpecularColor = mele->GetSpecularColorTexture(); #endif ppVbAni[n]->SetTexturePack( &texpack ); ppVbAni[n]->SetLightMapIndex( mele->GetLightMapIndex() ); // ppVbAni[n]->SetTexture( mele->GetTexture(), mele->GetSpecularTexture(), mele->GetSpecularColorTexture(), mele->GetIlluminTexture() ); } pMeshRes->SetWeightResource( ppWeight, static_cast(meshele.size()) ); pMeshRes->SetVBResource( ppVbAni, static_cast(meshele.size()) ); pMeshRes->SetNodeTM( pNodeTM, static_cast(meshele.size()) ); delete[] ppVbAni; delete[] ppWeight; //Weight 임시 담아 놓은곳. delete[] pNodeTM; if ( mesh->IsFX() ) { KNX3FX *fx = mesh->GetFXVector()[0]; const char *value = fx->GetFxElementByIndeX( 0 )->GetValue( "NXFX" ); if ( _stricmp( value, "particle" ) == 0 ) { KFXSeq *seq = loadFXParticle( mesh, fx, KFXParticleSeq::KPARTICLE_DEFAULT); if ( seq ) vecFXSeq.push_back( seq ); } else if ( _stricmp( value, "billboard" ) == 0 ) { KFXSeq *seq = loadFXBillboard( mesh, fx ); if ( seq ) vecFXSeq.push_back( seq ); } else if ( _stricmp( value, "gravity_particle" ) == 0 ) { KFXSeq *seq = loadFXParticle( mesh, fx ,KFXParticleSeq::KPARTICLE_GRAVITY); if ( seq ) vecFXSeq.push_back( seq ); } else if ( _stricmp( value, "reverse_particle" ) == 0 ) { KFXSeq *seq = loadFXParticle( mesh, fx, KFXParticleSeq::KPARTICLE_REVERSE ); if ( seq ) vecFXSeq.push_back( seq ); } else if ( _stricmp( value, "after_image" ) == 0 ) { KFXSeq *seq = loadFXAfterImage( mesh, fx ); if ( seq ) vecFXSeq.push_back( seq ); } pMeshRes->Discard(); } else { KMeshSeqObject *meshSeq = new KMeshSeqObject; meshSeq->SetMeshRes( pMeshRes ); meshSeq->SetMatrixRes( mesh->GetMatrixAniRes() ); meshSeq->SetVisibilityRes( mesh->GetVisibilityRes() ); meshSeq->SetUVAniRes( mesh->GetUVAniRes() ); vecMeshSeq.push_back( meshSeq ); std::vector childmeshes = mesh->GetChild(); for ( unsigned int i=0 ; iGetMetaData(), ptr.ptr, stream.GetLength() ); if ( !nxloader.LoadTRF( plodpack, KDeviceManager::GetDeviceManager()->GetRenderDevice(), mapper.root(), szName ) ) return false; } catch ( trf::Exception& /* e */) { #ifdef _DEBUG assert( 0 && "화일 Load Fail. 담당자에게 알려!!!" ); #endif return false; } } else { KBinaryFiler filer; if ( !filer.Load( stream ) ) { #ifdef _DEBUG assert( 0 && "화일 Load Fail. 담당자에게 알려!!!" ); #endif return false; } if ( !nxloader.Load( plodpack, KDeviceManager::GetDeviceManager()->GetRenderDevice(), &filer, szName ) ) return false; } nx3set->strProperty = nxloader.GetPropertyString(); KNX3MeshChannel *meshch = nxloader.GetMeshChannel(); if ( meshch ) { std::vector vecMeshSeq; std::vector vecFXSeq; std::vector vecEvSeq; std::vector &meshlist = meshch->GetMeshList(); for ( size_t i=0 ; ivpMeshSeq, nx3set->vpFXSeq, nx3set->vpEventSeq, meshlist[i], meshch->GetMeshTMList() ); } } KNX3CameraChannel *camch = nxloader.GetCameraChannel(); if ( camch ) { K3DResCamera *camres = camch->GetCameraRes(); KCameraSeq *camseq = new KCameraSeq; camseq->SetRes( camres ); nx3set->vpCamSeq.push_back( camseq ); } // Light KNX3LightChannel *litch = nxloader.GetLightChannel(); if ( litch ) { for ( int n=0 ; nGetLightCount(); ++n ) { KLightSeq* p = new KLightSeq; p->SetRes( litch->GetLight(n)->GetLightRes() ); nx3set->vpLightSeq.push_back( p ); } } //Bone 작업 중.. KNX3BoneChannel * bonech = nxloader.GetBoneChannel(); if( bonech ) { //이런식으로 되야 된다. K3DBoneResource *boneres = bonech->GetBoneRes(); KBoneSeqObject *boneseq = new KBoneSeqObject; boneseq->SetRes( boneres ); nx3set->vpBoneSeq.push_back( boneseq ); } #ifdef _KPATH_EFFECT // PathEffect KNX3PfxChannel* pfxch = nxloader.GetPfxChannel(); if(pfxch) { KResPathEffectChain* pfxres = pfxch->GetRes(); KSeqPathEffectChain* pfxseq = new KSeqPathEffectChain; pfxseq->SetRes(pfxres); nx3set->vpPfxSeq.push_back(pfxseq); } #endif DWORD dwLoadTime = GetSafeTickCount() - unStartTime; if( dwLoadTime > 60 ) { _oprint( "NX3 Load : %s (%dms) (%dKB) ThreadId:%d\n", szName, dwLoadTime, stream.GetLength()/1024, GetCurrentThreadId() ); } return true; } /////////////////////////////////////////////////////////////////////////////////////////////////////////////////// //KSpriteManager::SPRITE_SET Implement /////////////////////////////////////////////////////////////////////////////////////////////////////////////////// SPRITE_SET::SPRITE_SET() { } SPRITE_SET::~SPRITE_SET() { m_resByAniName.clear(); m_vtResSpriteAni.clear(); } int SPRITE_SET::GetResCount() { return static_cast(m_vtResSpriteAni.size()); } int SPRITE_SET::GetSpriteResAniCount( LPCSTR lpszAniName ) { KResSpriteAnimation *resani = GetSpriteResAni( lpszAniName ); if ( resani ) return resani->GetKeyCount(); return 0; } void SPRITE_SET::EraseSpriteResAni( LPCSTR lpszAniName ) { std::vector::iterator it = m_vtResSpriteAni.begin(); while( it != m_vtResSpriteAni.end() ) { if( ::_stricmp( lpszAniName, (*it)->GetName() ) == 0 ) { m_vtResSpriteAni.erase( it ); m_resByAniName.erase( lpszAniName ); break; } ++it; } } KResSpriteAnimation* SPRITE_SET::GetSpriteResAni( int nIndex) { return m_vtResSpriteAni.at(nIndex); } KResSpriteAnimation* SPRITE_SET::GetSpriteResAni( LPCSTR lpszAniName) { KResSpriteAnimation* pAni = NULL; m_resByAniName.lookup(lpszAniName, pAni); return pAni; } KResSprite* SPRITE_SET::GetSpriteRes(LPCSTR lpszAniName, int nIndex) { KResSpriteAnimation * pAni; if( m_resByAniName.lookup(lpszAniName, pAni ) ) { if( pAni && !pAni->IsLoaded() ) { KUITextureManager::GetManager()->GetSprAni( m_strResName.c_str(), lpszAniName ); } return (pAni) ? pAni->GetSpriteByFrame(nIndex) : NULL; } return NULL; } void SPRITE_SET::AddResSpriteAni(KResSpriteAnimation * pRes) { if( GetSpriteResAni( pRes->GetName() ) ) { ModifyResSpriteAni( pRes ); return; } THREAD_SYNCRONIZE( g_SpriteAniCS ); m_vtResSpriteAni.push_back(KResSpriteAnimationSPtr( pRes ) ); m_resByAniName.add(pRes->GetName(), pRes); } void SPRITE_SET::ModifyResSpriteAni( KResSpriteAnimation* pRes ) { std::vector::iterator it = m_vtResSpriteAni.begin(); while( it != m_vtResSpriteAni.end() ) { if( ::_stricmp( pRes->GetName(), (*it)->GetName() ) == 0 ) { (*it)->SetKeyCount( pRes->GetKeyCount() ); for( int i = 0; i < pRes->GetKeyCount(); i++ ) { KResSpriteAnimation::Key key = pRes->GetKey(i); (*it)->SetKey(i, &key ); } return; } it++; } } /////////////////////////////////////////////////////////////////////////////////////////////////////////////////// //KSpriteManager Implement /////////////////////////////////////////////////////////////////////////////////////////////////////////////////// KSpriteManager *KSingletoneResourceManager::s_pStaticManager = new KSpriteManager; KSpriteManager::KSpriteManager() { // - prodongi #ifdef SPR_LIST_EXTRACTOR m_sprListExtractor.initialize(); #endif } KSpriteManager::~KSpriteManager() { DiscardAll(); // - prodongi #ifdef SPR_LIST_EXTRACTOR m_sprListExtractor.closeFile(); #endif } #define MAX_SPR_LIST (6) static char * sprArrays[MAX_SPR_LIST] = { "01_equip.spr", "02_item.spr", "03_skill.spr", "04_event.spr", "05_ui.spr", "06_live.spr" }; bool KSpriteManager::LoadSpriteSet( const char *resname ) { SPRITE_SET *pSet = new SPRITE_SET; if (!pSet) return false; for (int i=0; i j - prodongi //for ( int i=0 ; iAddResSpriteAni(pRes); // - prodongi #ifdef SPR_LIST_EXTRACTOR m_sprListExtractor.extract(pRes, sprArrays[i]); #endif } } else { SAFE_DELETE(pSet); return false; } KFileManager::Instance().DeleteStream(stream); stream = NULL; } } pSet->m_strResName = resname; m_setByName.add(resname, pSet); return true; } SPRITE_SET* KSpriteManager::GetSpriteSet( const char *resname ) { SPRITE_SET *pSet = NULL; if( m_setByName.lookup( resname, pSet ) == false ) { KStream *stream = KFileManager::Instance().CreateStreamFromResource( resname ); if ( stream ) { THREAD_SYNCRONIZE( g_SpriteAniCS ); OutputDebugString( "Loading Sprite - " ); OutputDebugString( resname ); OutputDebugString( "\r\n" ); pSet = new SPRITE_SET; if ( _LoadSpriteSet( *stream, pSet ) ) { _AddSpriteSet( resname, pSet ); } else { SAFE_DELETE(pSet); } KFileManager::Instance().DeleteStream( stream ); stream = NULL; } } return pSet; } SPRITE_SET *KSpriteManager::GetSpriteSet( KStream &Stream, const char *resname ) { SPRITE_SET *pSet = NULL; if( m_setByName.lookup( resname, pSet ) == false ) { THREAD_SYNCRONIZE( g_SpriteAniCS ); pSet = new SPRITE_SET; if ( _LoadSpriteSet( Stream, pSet ) ) { _AddSpriteSet( resname, pSet ); } else { SAFE_DELETE(pSet); } } return pSet; } bool GetIconAniName( const char * pFileName, std::string & strOutAniName ) { std::string strAniName = pFileName; std::string::size_type pos = strAniName.rfind( '.' ); if( pos != std::string::npos ) { strAniName.erase( pos, strAniName.length()-pos ); //확장자 제거 pos = std::string::npos; pos = strAniName.rfind( '\\' ); if( pos != std::string::npos ) { strAniName.erase( 0, pos+1 ); //폴더 제거 } else { assert(0); return false; } } else { assert(0); return false; } strOutAniName = strAniName; return true; } void KSpriteManager::AddIconSprite( const char *resname, const char *file_name, bool bEncrypt, bool bUseColorKey, KColor color, bool bLoad ) { SPRITE_SET *pSet = NULL; if( m_setByName.lookup( resname, pSet ) == false ) { THREAD_SYNCRONIZE( g_SpriteAniCS ); pSet = new SPRITE_SET; _AddSpriteSet( resname, pSet); //스프라이트 셋트 등록 _AddSpriteAnimation( file_name, pSet, bEncrypt, bUseColorKey, color ); //개별 리소스 등록 } if( pSet ) { std::string strAniName; if( !GetIconAniName( file_name, strAniName ) ) return; //기존에 있는 것은 if( !pSet->GetSpriteResAni( strAniName.c_str() ) ) { //_AddSpriteAnimation( file_name, pSet, bEncrypt, bUseColorKey, color ); //개별 리소스 등록 _AddSpriteAnimation( file_name, pSet, bEncrypt, bUseColorKey, color, bLoad ); // 수정. bintitle. } //if( bLoad ) //{ // //기존에 있는 것은 // if( pSet->GetSpriteResAni( strAniName.c_str() ) ) // { // pSet->EraseSpriteResAni( strAniName.c_str() ); // 기존 스프라이트 제거. // // _AddSpriteAnimation( file_name, pSet, bEncrypt, bUseColorKey, color, bLoad ); // 수정. bintitle. // } //} //else //{ // //기존에 있는 것은 // if( !pSet->GetSpriteResAni( strAniName.c_str() ) ) // { // //_AddSpriteAnimation( file_name, pSet, bEncrypt, bUseColorKey, color ); //개별 리소스 등록 // _AddSpriteAnimation( file_name, pSet, bEncrypt, bUseColorKey, color, bLoad ); // 수정. bintitle. // } //} } } void KSpriteManager::_AddSpriteAnimation( const char *file_name, SPRITE_SET *pSet, bool bEncrypt, bool bUseColorKey, KColor color, bool bLoad ) { KSpriteLoader sprloader; //sprloader.Load_Icon( file_name ); if( bLoad ) sprloader.Load_IconEx( file_name ); else sprloader.Load_Icon( file_name ); int count = sprloader.GetResCount(); for ( int i=0 ; iSetEncrypt( bEncrypt ); pRes->SetUseColorKey( bUseColorKey ); pRes->SetColorKey( color ); pSet->AddResSpriteAni(pRes); } } KResSpriteAnimation* KSpriteManager::GetResSpriteAni(LPCSTR lpszSprName, LPCSTR lpszAniName) { SPRITE_SET *pSet = GetSpriteSet(lpszSprName); if(pSet) { return pSet->GetSpriteResAni(lpszAniName); } return NULL; } int KSpriteManager::GetAnimationFrameCount(LPCSTR lpszSprName, LPCSTR lpszAniName) { KResSpriteAnimation * pRes = GetResSpriteAni(lpszSprName,lpszAniName); if(pRes) return pRes->GetKeyCount(); return 0; } KResSprite* KSpriteManager::GetResSprite(LPCSTR lpszSprName, LPCSTR lpszAniName,int nIndex) { SPRITE_SET *pSet = GetSpriteSet(lpszSprName); if(pSet) { KResSpriteAnimation * pRes = pSet->GetSpriteResAni( lpszAniName ); if( pRes && !pRes->IsLoaded() ) { KUITextureManager::GetManager()->GetSprAni( lpszSprName, lpszAniName ); } return pSet->GetSpriteRes(lpszAniName,nIndex); } return NULL; } // Set 자체를 Reference 하는 객체는 없으므로 이렇게 써도 무방할 듯 하다. void KSpriteManager::ReleaseSpriteSet(LPCSTR lpszSprName) { THREAD_SYNCRONIZE( g_SpriteAniCS ); SPRITE_SET *pSet; if ( m_setByName.lookup( lpszSprName, pSet ) == true ) { m_setByName.erase( lpszSprName ); SAFE_DELETE(pSet); } } void KSpriteManager::PrintList( const char * pOutFileName ) { } void KSpriteManager::ReloadRes( bool bRepair ) { } void KSpriteManager::DiscardAll() { SPRITE_SET *pSet; bool bRet; THREAD_SYNCRONIZE( g_SpriteAniCS ); bRet = m_setByName.get_first_value( pSet ); while ( bRet ) { SAFE_DELETE(pSet); bRet = m_setByName.get_next_value( pSet ); } m_setByName.clear(); } bool KSpriteManager::_LoadSpriteSet( KStream &stream, SPRITE_SET *pSet) { KSpriteLoader sprloader; if ( sprloader.Load( stream ) ) { int count = sprloader.GetResCount(); for ( int i=0 ; iAddResSpriteAni(pRes); } return true; } return false; } bool KSpriteManager::_AddSpriteSet( const char *name, SPRITE_SET *pSet) { THREAD_SYNCRONIZE( g_SpriteAniCS ); pSet->m_strResName = name; m_setByName.add( name, pSet ); return true; } // - prodongi #ifdef SPR_LIST_EXTRACTOR void sSprListExtractor::initialize() { assert(!m_file); m_file = fopen ("spr.ini", "w"); if (!m_file) { assert(0 && "failed create spr.ini file"); return ; } assert(!m_dupliFile); m_dupliFile = fopen ("spr_dupli.ini", "w"); if (!m_dupliFile) { assert(0 && "failed create spr_dupli.ini file"); return ; } } void sSprListExtractor::extract(KResSpriteAnimation *res, char const* sprName) { std::map::iterator it_m; std::vector::const_iterator it = res->GetFrame().begin(); for (; it != res->GetFrame().end(); ++it) { it_m = m_list.find(it->c_str()); if (it_m == m_list.end()) { fwrite(it->c_str(), it->length(), 1, m_file); fwrite("\n", strlen("\n"), 1, m_file); m_list.insert(std::make_pair(*it, sprName)); } else { sprintf(m_temp, "%s\t, cur:%s, ori:%s", it->c_str(), sprName, it_m->second.c_str()); fwrite(m_temp, strlen(m_temp), 1, m_dupliFile); fwrite("\n", strlen("\n"), 1, m_dupliFile); } } } void sSprListExtractor::closeFile() { if (m_file) fclose(m_file); if (m_dupliFile) fclose(m_dupliFile); } #endif