#include "StdAfx.h" #include "CallbackStreamPak.h" #include "ResourceManager.h" NiCriticalSection cCallbackStreamPACK::mQueueCriticalSection; cCallbackStreamPACK::cCallbackStreamPACK() { // Å×½ºÆ®¸¦ ÅëÇØ¼­ Å©±â¸¦ Á¶ÀýÇÑ´Ù. mpFileQueue = NiNew NiTPrimitiveQueue(100); } cCallbackStreamPACK::~cCallbackStreamPACK() { ClearQueue(); SAFE_NIDELETE( mpFileQueue ); } void cCallbackStreamPACK::AddLoadFile( const char* fileName ) { if( ::strlen( fileName ) == 0 ) { return; } /// Å¥¸¦ ä¿î´Ù. mQueueCriticalSection.Lock(); { char* name = new char[260]; NiStrcpy( name, 260, fileName ); mpFileQueue->Add( name ); } mQueueCriticalSection.Unlock(); } void cCallbackStreamPACK::ClearQueue() { mQueueCriticalSection.Lock(); { char* name = mpFileQueue->Remove(); while( name ) { delete[]name; name = mpFileQueue->Remove(); } } mQueueCriticalSection.Unlock(); } void cCallbackStreamPACK::BackgroundLoadBeginEx() { mQueueCriticalSection.Lock(); { /// ¸¸¾à ¿ÜºÎ¿¡¼­ Á÷Á¢ Á¢±ÙÇϵµ·Ï ¼öÁ¤ÇÑ´Ù¸é, ¾Æ·¡ ÁÖ¼® ÇØÁ¦ÇϽÿÀ.. // if( m_eBackgroundLoadStatus != IDLE ) return; if( mpFileQueue->IsEmpty() ) { mQueueCriticalSection.Unlock(); return; } /// Set m_uiLoad to UINT_MAX so we can determine in BackgroundLoadPoll /// whether the background thread has run far enough to set the variables /// we use to compute progress. m_uiLoad = UINT_MAX; /// °ÔÀӺ긮¿À ³»ºÎ ó¸®ÀÌ´Ù. if( m_pkBGLoadProc == NULL ) m_pkBGLoadProc = NiNew cBackgroundLoadProcedureEx( this ); /// StreamPackÇѰ³¿¡ ..·Îµù ¾²·¹µå´Â ÇѰ³¸¸À¸·Î ÇÑ´Ù.. assert( m_pkThread == NULL ); if( m_pkThread ) { mQueueCriticalSection.Unlock(); return; } /// ·Îµù ¾²·¹µå »ý¼º.. m_pkThread = NiThread::Create( m_pkBGLoadProc ); assert(m_pkThread); if( !m_pkThread ) { mQueueCriticalSection.Unlock(); return; } /// ¾²·¹µå ¿É¼Ç ¼ÂÆÃ m_pkThread->SetPriority(NiThread::BELOW_NORMAL); m_pkThread->Resume(); m_eBackgroundLoadStatus = LOADING; } mQueueCriticalSection.Unlock(); } /// ÁÖÀÇ!! À̺κÐÀº ¸ÞÀΰú´Â ´Ù¸¥ ¾²·¹µåÀ̹ǷΠÄÚµù¿¡ ¸Å¿ì ÁÖÀÇ void cCallbackStreamPACK::BackgroundLoadEx() { bool isEmpty = false; char* fileName = NULL; NiNode* n = NULL; while( !isEmpty ) { /// Å¥¸¦ Çϳª ºñ¿î´Ù. mQueueCriticalSection.Lock(); { fileName = mpFileQueue->Remove(); if( mpFileQueue->IsEmpty() ) { isEmpty = true; } } mQueueCriticalSection.Unlock(); if( !fileName || strlen(fileName) < 5) { /// ·ÎµùÇÏ·Á´Â ÆÄÀϸíÀÌ NULLÀÎ °æ¿ì¸é.. continue; } if( RESOURCEMAN->GetObjectByName(fileName) ) { /// ÀÌ¹Ì ·ÎµùµÇ¾î ÀÖ´Ù¸é.. continue; } #ifdef _PAK_LOAD #else //if( NiStream::Load( cResourceManager::ConvertMediaFilename(fileName) ) ) if( NiStream::Load( fileName ) ) { n = NiDynamicCast( NiNode, NiStream::GetObjectAt(0) ); if( n ) { /// TODO : Çʼö ¼öÁ¤ ¿ä¼Ò!! RESOURCEMAN->AddObject( n, fileName, false ); } else { assert(0); } BackgroundLoadOnExit(); } #endif /// ÀâÇôÀÖ´Â ¸Þ¸ð¸® ºñ¿î´Ù. SAFE_DELETE_ARRAY( fileName ); } m_kSemaphore.Signal(); } void cCallbackStreamPACK::BackgroundLoadOnExit() { /// ÀоîµéÀÎ µ¥ÀÌÅÍ¿¡ ´ëÇÑ ¸ÞÀξ²·¹µå 󸮸¦ À§ÇØ /// ¸ÞÀξ²·¹µå¿¡ CPU¸¦ ÇÒ´çÇÑ´Ù. NiSleep( 1 ); } unsigned int cCallbackStreamPACK::cBackgroundLoadProcedureEx::ThreadProcedure( void* /*pArg*/ ) { ( (cCallbackStreamPACK*)m_pkStream )->BackgroundLoadEx(); return 0; } /// ÁÖÀÇ!! À̺κÐÀº Main Thread»ó¿¡¼­ÀÇ Ã³¸®ºÎ /// Àý´ë ·Îµù¾²·¹µåÀÇ Ã³¸®ºÎ°¡ ¾Æ´Ï´Ù. void cCallbackStreamPACK::Process() { if( m_eBackgroundLoadStatus == IDLE ) { /// ·Îµù ¾²·¹µå°¡ È޽ĻóÅÂ¸é ´ÙÀ½ µ¥ÀÌÅÍ¿¡ /// ´ëÇØ üũÇÑ´Ù. BackgroundLoadBeginEx(); } else { /// ·Îµù ÁøÇàÇüÀ̸é /// ·Îµù ¾²·¹µå¿¡ CPUÇÒ´ç.. Sleep( 1 ); /// »óŰª °»½Å LoadState loadState; BackgroundLoadPoll(&loadState); } }