Files
2026-06-01 12:46:52 +02:00

277 lines
6.6 KiB
C++

#include "stdafx.h"
//#include "Util.h"
#include "KRenderDevice.h"
#include "KResource.h"
#include "TerrainTextureInfo.h"
#include "KResourceManager.h"
#include <kfile/KFileManager.h>
#include <mmo/ArTime.h>
#ifdef _MEMORY_LEAK_FIX_
const DWORD TEXTURE_HOLD_TIME = 0;
#else
const DWORD TEXTURE_HOLD_TIME = 300000;
#endif
CTerrainTextureInfo::CTerrainTextureInfo()
: m_pDevice( NULL )
{
m_dwLastTextureRemoveTime = GetSafeTickCount();
}
CTerrainTextureInfo::~CTerrainTextureInfo()
{
Release();
}
bool CTerrainTextureInfo::Initialize( const char* szTextureInfoFileName, K3DRenderDevice* pDevice )
{
THREAD_SYNCRONIZE( m_lckTexture );
Release();
m_pDevice = pDevice;
// dummy texture 생성
if( !InitializeDummyTexture() )
return false;
// 파일로부터 text들을 읽어낸다.
STRING_VECTOR TextLines;
{
KStream* pStream = KFileManager::Instance().CreateStreamFromResource( szTextureInfoFileName, false );
if( NULL == pStream )
return false;
int nTextLength = int( pStream->GetLength() );
char* pEntireText = new char[ nTextLength + 1 ];
pStream->Read( pEntireText, sizeof(char) * nTextLength );
pEntireText[ nTextLength ] = '\0';
delete pStream;
CStringUtil::GetTextLinesFromString( pEntireText, TextLines );
delete [] pEntireText;
}
const char* c_szCategory = "CATEGORY=";
const char* c_szDetail = "DETAIL=";
const char* c_szTexture = "TEXTURE=";
int nCurrentCategory = 0;
float fCurrentDetailRatio = 1.f;
DWORD stime = GetSafeTickCount();
for( size_t n = 0; n < TextLines.size(); ++n )
{
std::string strLine = TextLines[n];
if( ';' == strLine[0] )
continue;
std::string strContent;
// category
if( CStringUtil::GetContentString( strLine, c_szCategory, strContent ) )
{
if( strContent.size() > 0 )
{
nCurrentCategory = (-1);
for( size_t nCategory = 0; nCategory < m_CategoryNames.size(); ++nCategory )
{
if( m_CategoryNames[nCategory] == strContent )
{
// 이미 존재하는 category명인 경우 그대로 사용
nCurrentCategory = static_cast<int>(nCategory);
break;
}
}
// 새로운 category명을 추가
if( (-1) == nCurrentCategory )
{
m_CategoryNames.push_back( strContent );
nCurrentCategory = static_cast<int>( m_CategoryNames.size() - 1 );
}
}
}
// detail
else if( CStringUtil::GetContentString( strLine, c_szDetail, strContent ) )
{
fCurrentDetailRatio = (float)(::atof( strContent.c_str() ));
if( 0.f == fCurrentDetailRatio )
fCurrentDetailRatio = 1.f;
}
// texture
else if( CStringUtil::GetContentString( strLine, c_szTexture, strContent ) )
{
// ',' 문자를 찾는다.
int nCommaPos = static_cast<int>( strContent.find( ',' ) );
if( nCommaPos != std::string::npos )
{
// ',' 앞의 텍스쳐 번호
std::string strTexNum;
strTexNum.assign( strContent, 0, nCommaPos );
// ',' 뒤의 텍스쳐 파일명
std::string strTexFileName;
strTexFileName.assign( strContent, nCommaPos + 1, strContent.size() - (nCommaPos + 1) );
if( strTexNum.size() > 0 && strTexFileName.size() > 0 )
{
WORD wTexNum = static_cast<WORD>( ::atoi( strTexNum.c_str() ) );
K3DTexture* pTexture = NULL;
#ifndef _RAC
NX3LoadPack loadpack;
loadpack.Init();
pTexture = KTextureManager::GetManager()->RefreshTexture( strTexFileName.c_str(), &loadpack );
#endif
TEXINFO_STRUCT ts;
ts.bIsLoadFailed = false;
ts.nCategory = nCurrentCategory;
ts.fDetailRatio = fCurrentDetailRatio;
ts.spTexture = pTexture;
ts.strName = strTexFileName;
m_mapTexInfo[ wTexNum ] = ts;
}
}
}
}
//_oprint( "TerrainTextureInfo Loading Time : %d\n", GetSafeTickCount()-stime );
// category가 한번도 안 나온 경우
if( m_CategoryNames.size() == 0 )
m_CategoryNames.push_back( "?" );
return true;
}
void CTerrainTextureInfo::Release()
{
THREAD_SYNCRONIZE( m_lckTexture );
ReleaseDummyTexture();
m_mapTexInfo.clear();
m_CategoryNames.clear();
}
bool CTerrainTextureInfo::InitializeDummyTexture()
{
ReleaseDummyTexture();
const int c_nDummyLength = 16;
m_spDummyTexture = m_pDevice->CreateTexture( c_nDummyLength, c_nDummyLength, K3DFMT_A1R5G5B5 );
if( m_spDummyTexture == NULL ) return false;
WORD* pBuf;
int nPitch;
m_spDummyTexture->LockRect( NULL, (void**)&pBuf, nPitch );
if( pBuf == NULL ) return false;
nPitch /= sizeof(WORD);
for( int nY = 0; nY < c_nDummyLength; nY++ )
for( int nX = 0; nX < c_nDummyLength; nX++ )
pBuf[ (nY * nPitch) + nX ] = ( nX == nY || (c_nDummyLength - nX) == (nY + 1) ) ? 0xFC00 : 0xFFFF;
m_spDummyTexture->Unlock();
return true;
}
void CTerrainTextureInfo::ReleaseDummyTexture()
{
}
void CTerrainTextureInfo::RemoveUnnecessaryTexture()
{
if( m_dwLastTextureRemoveTime + TEXTURE_HOLD_TIME > GetSafeTickCount() ) return;
THREAD_SYNCRONIZE( m_lckTexture );
DWORD dwCurrentTime = GetSafeTickCount();
for( std::map< WORD, TEXINFO_STRUCT >::iterator it = m_mapTexInfo.begin(); it != m_mapTexInfo.end(); ++it )
{
if( !(*it).second.spTexture || (*it).second.bIsLoadFailed )
continue;
if( (*it).second.spTexture->GetRefCount() > 1 )
continue;
if( (*it).second.dwLastAccessTime + TEXTURE_HOLD_TIME > dwCurrentTime )
continue;
(*it).second.spTexture = NULL;
}
m_dwLastTextureRemoveTime = GetSafeTickCount();
}
K3DTexture* CTerrainTextureInfo::GetNotFoundTexture()
{
NX3LoadPack loadpack;
loadpack.Init();
return KTextureManager::GetManager()->RefreshTexture( "NotFound.dds", &loadpack );
}
K3DTexture* CTerrainTextureInfo::GetTexture( WORD wTextureNum )
{
std::map< WORD, TEXINFO_STRUCT >::iterator it;
{
THREAD_SYNCRONIZE( m_lckTexture );
it = m_mapTexInfo.find( wTextureNum );
if( it == m_mapTexInfo.end() )
return NULL;
(*it).second.dwLastAccessTime = GetSafeTickCount();
}
// 로딩 실패했던 텍스쳐라면 KIN
if( (*it).second.bIsLoadFailed )
return NULL;
if( (*it).second.spTexture == NULL)
{
// TODO: In the process of adding resource option loading
NX3LoadPack loadpack;
loadpack.Init();
// Loading
(*it).second.spTexture = KTextureManager::GetManager()->RefreshTexture( (*it).second.strName.c_str(), &loadpack );
if((*it).second.spTexture == NULL)
{
std::string str = (*it).second.strName;
str += "\nNon-existent texture";
#ifndef _RAC
AfxMessageBox( str.c_str(), MB_OK | MB_ICONERROR );
#endif
return NULL;
}
if( (*it).second.spTexture != NULL)
{
//_oprint( "TERRAIN TEXTURE LOADING : %s (%d) (thread:%d)\n", (*it).second.strName.c_str(), wTextureNum, GetCurrentThreadId() );
}
else
{
(*it).second.bIsLoadFailed = true;
}
}
return (*it).second.spTexture;
}