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

634 lines
17 KiB
C++

#include "stdafx.h"
#include "SGameQJTV.h"
#include <kfile/KFileManager.h>
#include "KRenderDeviceDX.h"
#include "KViewport.h"
#include <mmo/ArTime.h>
#include "KUITextureManager.h"
#include "GameDefine.h"
#include "KTGA_IO.h"
SGameQJTV::SGameQJTV( K3DRenderDeviceDX* pRenderDevice )
: m_pRenderDevice(pRenderDevice), m_CrrTime(0), m_StartTime(0), m_bPlay(false), m_bSuccessSetting(false)
, m_nState(QJTV::OFF), m_OldFrameRenderTime(0), m_nStartFrame(0), m_TextureOption(0), m_TextureWidth(0), m_TextureHeight(0)
, m_nCrrFrame(0), m_nCnt(0), m_fixFps(0), m_bRepeat(true), m_nFrameCnt(0), m_bSuccessCraeteTexture(false)
{
K3DMatrixIdentity( m_Matrix );
m_Matrix.SetPosVector( K3DVertex( 0, 0, 0.1f ) );
m_BackColor = KColor(0,0,0,0);
Init();
}
SGameQJTV::~SGameQJTV()
{
}
void SGameQJTV::Init()
{
KStream * pStream = KFileManager::Instance().CreateStreamFromResource( "QJTV.tml" );
m_Meta.importTML( *pStream );
KFileManager::Instance().DeleteStream( pStream );
m_pResSprite = new KResSprite;
}
void SGameQJTV::SetQJTV( const char* pFileName, DWORD TextureOption/*0*/, int nStart/*0*/, int nCnt/*0*/, float fixFps/*25*/, KColor BackColor/*KColor(0,0,0,0)*/ )
{
m_strFileName = pFileName;
m_TextureOption = TextureOption;
m_nStartFrame = nStart;
m_nCnt = nCnt;
m_fixFps = fixFps;
LoadQJTV(nStart, nCnt, BackColor);
}
//동영상의 시작할 첫번째 파일의 위치, 총 프레임 수, 각 프레임의 랜더링걸 시간
bool SGameQJTV::LoadQJTV( int nStart/*0*/, int nCnt/*0*/, KColor BackColor/*KColor(0,0,0,0)*/ )
{
//QJTVObj 안에서 KStream 삭제 된다
KStream* pStream = KFileManager::Instance().CreateStreamFromResource( m_strFileName.c_str() );
m_QJTV.Load( &m_Meta, pStream ); //파일로드
if( !CheckData(nStart, nCnt) ) //생성하고자 하는 옵션이 현재 로딩한 파일에 적합한지 검사
return false;
BYTE* pBits(NULL);
int nSrcWidth(0), nSrcHeight(0);
m_QJTV.GetFrame( m_nStartFrame, pBits, nSrcWidth, nSrcHeight ); //첫번째 프레임의 택스처 정보 얻기
if( !CreateTexture(BackColor, nSrcWidth, nSrcHeight) ) //첫번째 프레임에 맞게 택스처 생성
return false;
m_pResSprite->SetTransform(m_Matrix);
m_pSpritePrimitive.SetRes( m_pResSprite ); //프리미티브에 리소스 연결
m_pSpritePrimitive.SetVisibility( 1.0f );
m_pSpritePrimitive.SetMirror( false, true );
m_bSuccessSetting = true;
return true;
}
bool SGameQJTV::CheckData( int nStart/*0*/, int nCnt/*0*/ )
{
m_nFrameCnt = m_QJTV.GetFrameCount();
if( m_nFrameCnt == 0 ) return false;
if( m_nFrameCnt <= nStart ) return false;
if( m_nFrameCnt < nStart+nCnt ) return false;
return true;
}
bool SGameQJTV::CreateTexture(KColor BackColor, int& nSrcWidth, int& nSrcHeight )
{
int nExpX(0) ,nExpY(0);
if( m_TextureOption & QJTV::FULL ) //게임 해상도에 마춰서 택스처를 생성하겠다는 옵션
{
KSize ScreenSize = m_pRenderDevice->GetScreenSize();
// nExpX = ScreenSize.width; nExpY = ScreenSize.height;
nExpX = SIZE_1024; nExpY = SIZE_768;
}
if(nExpX==0 || nExpY==0) //아무런 옵션이 없던가 디폴트로 쎄팅 되있으니 택스처의 크기에 맞게 생성
K3DRenderDevice::GetSquareSize( nSrcWidth, nSrcHeight, nExpX, nExpY );
if( KUITextureManager::GetHWType() == KUITextureManager::HW_SUPPORT )
{
m_pTexture = m_pRenderDevice->CreateTexture( nExpX, nExpY, KUSAGE_DYNAMIC, K3DFMT_A8R8G8B8, D3DPOOL_DEFAULT );
}
else //Intel Chip 계열에서 지원 안 되는 넘들이 있음.
{
m_pTexture = m_pRenderDevice->CreateTexture( nExpX, nExpY, K3DFMT_A8R8G8B8, D3DPOOL_MANAGED );
}
if( m_pTexture == NULL ) return false;
else
{
BYTE* pTextureBuf(NULL); int nStride(0);
m_pTexture->LockRect( NULL, (void**)&pTextureBuf, nStride );
if( pTextureBuf == NULL )
{
m_pTexture = NULL;
assert( 0 && "QJTV Lock Failed <BackClear>!!!" );
return false;
}
m_BackColor = BackColor;
for( UINT i(0); i < (UINT)(nExpY*nExpX); i++ )
{
KColor* pColor = ( KColor* )pTextureBuf;
pColor[i] = BackColor;
}
m_pTexture->Unlock();
}
nSrcWidth = nExpX;
nSrcHeight = nExpY;
m_pResSprite->SetTexture(m_pTexture, NULL); //택스처 리소스스프라이트에 쎄팅
m_pSpritePrimitive.SetTargetSize( nSrcWidth, nSrcHeight );
return true;
}
bool SGameQJTV::RefreshSeenTexture()
{
if( !m_bSuccessSetting || m_pTexture == NULL ) return false;
int nTextureX(m_pTexture->GetWidth()), nTextureY(m_pTexture->GetHeight());
BYTE* pSrcBits(NULL);
int nSrcWidth(0), nSrcHeight(0);
m_QJTV.GetFrame( m_nCrrFrame, pSrcBits, nSrcWidth, nSrcHeight );
UINT StartX(0); UINT StartY(0);
if( m_TextureOption & QJTV::CENTER )
{
StartX = nTextureX/2-nSrcWidth/2;
StartY = nTextureY/2-nSrcHeight/2;
}
BYTE* pTextureBuf(NULL);
int nStride(0);
KRect rcRock(StartX, StartY, StartX+nSrcWidth, StartY+nSrcHeight);
m_pTexture->LockRect( &rcRock, (void**)&pTextureBuf, nStride );
if( pTextureBuf == NULL )
{
m_pTexture = NULL;
m_bSuccessCraeteTexture = false;
assert( 0 && "QJTV Lock Failed!!!" );
return false;
}
KColor* pColor(NULL);
for( UINT y(0); y < (UINT)nSrcHeight; y++ )
{
pColor = (KColor*)pTextureBuf;
for( UINT x(0); x < (UINT)nSrcWidth; ++x )
{
KColor col;
UINT Pos = (y*nSrcWidth +x)*4;
col.b = pSrcBits[Pos+0];
col.g = pSrcBits[Pos+1];
col.r = pSrcBits[Pos+2];
if( m_TextureOption & QJTV::ALPHA )
col.a = pSrcBits[Pos+3];
else col.a = 255; //택스처에 있는 알파값을 사용하지 않는 경우
pColor[x] = col;
}
pTextureBuf += nStride;
}
m_pTexture->Unlock();
m_bSuccessCraeteTexture = true;
return true;
}
bool SGameQJTV::SetScreenCenter()
{
if( m_pRenderDevice == NULL || m_pTexture == NULL ) return false;
KSize ScreenSize = m_pRenderDevice->GetScreenSize();
int nTextureX(m_pTexture->GetWidth()), nTextureY(m_pTexture->GetHeight());
int StartX = ScreenSize.width/2-nTextureX/2;
int StartY = ScreenSize.height/2-nTextureY/2;
m_Matrix.SetPosVector( K3DVertex( StartX, StartY, 0.1f ) );
m_pResSprite->SetTransform(m_Matrix);
return true;
}
void SGameQJTV::SetState( int nState )
{
m_nState = nState;
}
void SGameQJTV::StartPlay()
{
m_bPlay = true;
m_OldFrameRenderTime = m_StartTime = GetSafeTickCount();
m_nCrrFrame = m_nStartFrame;
RefreshSeenTexture();
m_nState = QJTV::PLAY;
}
void SGameQJTV::Play()
{
bool bOver( m_nCrrFrame+1 > (int)m_QJTV.GetFrameCount() );
if( !m_bRepeat && bOver )
{
m_nState = QJTV::END;
return;
}
float msFps = 1000.f / m_fixFps;
if ( m_CrrTime-m_OldFrameRenderTime > msFps )
{
++m_nCrrFrame;
m_OldFrameRenderTime = GetSafeTickCount();
if(bOver && m_bRepeat) m_nCrrFrame = m_nStartFrame;
if( m_bSuccessCraeteTexture && m_nFrameCnt <= 1 )
return;
RefreshSeenTexture();
}
}
void SGameQJTV::OFF()
{
m_bPlay = false;
m_nState = QJTV::OFF;
}
int SGameQJTV::Render( KViewportObject *viewport, bool bFront/*=true*/ )
{
//OFF이거나 STOP일때는 render안건다...
if( m_nState == QJTV::OFF ) return QJTV::OFF;
// if( m_nState == QJTV::STOP ) return QJTV::STOP;
viewport->Register( &m_pSpritePrimitive );
// viewport->Register( &m_pSpritePrimitive, bFront );
return m_nState;
}
int SGameQJTV::Proc( DWORD dwTime )
{
m_CrrTime = dwTime;
if( !m_bSuccessSetting || m_pTexture == NULL || m_nState == QJTV::OFF )
return SetOff();
switch(m_nState)
{
case QJTV::STARTPLAY: StartPlay(); break;
case QJTV::PLAY: Play(); break;
case QJTV::OFF: OFF(); break;
}
return m_nState;
}
int SGameQJTV::SetOff()
{
m_bPlay = false;
m_nState = QJTV::OFF;
return m_nState;
}
SGameMultiQJTV::SGameMultiQJTV( K3DRenderDeviceDX* pRenderDevice, int nWidth, int nHeight, KColor BackColor )
: m_pRenderDevice(pRenderDevice), m_nWidthSize(nWidth), m_nHeightSize(nHeight), m_pCrrQJTV(NULL)
{
K3DMatrixIdentity( m_Matrix );
m_Matrix.SetPosVector( K3DVertex( 0, 0, 0.1f ) );
m_BackColor = BackColor;
Init();
}
SGameMultiQJTV::~SGameMultiQJTV()
{
for( int i(0); i<(int)m_vecQJTV.size(); ++i )
{
SAFE_DELETE(m_vecQJTV[i]);
}
m_vecQJTV.clear();
m_vecQJTV_FileName.clear();
}
void SGameMultiQJTV::Init()
{
m_pResSprite = new KResSprite;
CreateTexture(m_BackColor, m_nWidthSize, m_nHeightSize);
m_pResSprite->SetTransform(m_Matrix);
m_pSpritePrimitive.SetRes( m_pResSprite ); //프리미티브에 리소스 연결
m_pSpritePrimitive.SetVisibility( 1.0f );
m_pSpritePrimitive.SetMirror( false, true );
}
bool SGameMultiQJTV::AddQJTV( const char* pFileName, DWORD TextureOption/*0*/, int nStart/*0*/, int nCnt/*0*/, float fixFps/*25*/ )
{
//이미 add한 파일인지 체크...
if( GetQJTVMovie(pFileName) ) return false;
sQJTV* pQJTV = new sQJTV;
if( pQJTV == NULL ) return false;
KStream * pStream = KFileManager::Instance().CreateStreamFromResource( "QJTV.tml" );
pQJTV->m_Meta.importTML( *pStream );
KFileManager::Instance().DeleteStream( pStream );
SetQJTV( pQJTV, pFileName, TextureOption, nStart, nCnt, fixFps );
m_vecQJTV.push_back( pQJTV );
m_vecQJTV_FileName.push_back( pFileName );
return true;
}
bool SGameMultiQJTV::SetCrrMovie( const char* lpFileName )
{
int nQJTVSize( m_vecQJTV.size() );
for( int i(0); i<(int)m_vecQJTV_FileName.size(); i++ )
{
if( m_vecQJTV_FileName[i] == lpFileName && i >= 0 && i < nQJTVSize )
{
m_pCrrQJTV = m_vecQJTV[i];
ClearTextureBuffer();
return true;
}
}
return false;
}
void SGameMultiQJTV::ClearTextureBuffer()
{
BYTE* pTextureBuf(NULL); int nStride(0);
m_pTexture->LockRect( NULL, (void**)&pTextureBuf, nStride );
if( pTextureBuf == NULL )
{
m_pTexture = NULL;
assert( 0 && "QJTV Lock Failed <BackClear>!!!" );
return;
}
for( UINT i(0); i < (UINT)(m_nWidthSize*m_nHeightSize); i++ )
{
KColor* pColor = ( KColor* )pTextureBuf;
pColor[i] = m_BackColor;
}
m_pTexture->Unlock();
}
sQJTV* SGameMultiQJTV::GetQJTVMovie( const char* lpFileName )
{
int nQJTVSize( m_vecQJTV.size() );
for( int i(0); i<(int)m_vecQJTV_FileName.size(); i++ )
{
if( m_vecQJTV_FileName[i] == lpFileName && i > 0 && i < nQJTVSize )
{
return m_vecQJTV[i];
}
}
return NULL;
}
void SGameMultiQJTV::SetQJTV( sQJTV* pQJTVSET, const char* pFileName, DWORD TextureOption/*0*/, int nStart/*0*/, int nCnt/*0*/, float fixFps/*25*/ )
{
if( pQJTVSET == NULL ) return;
pQJTVSET->m_strFileName = pFileName;
pQJTVSET->m_TextureOption = TextureOption;
pQJTVSET->m_nStartFrame = nStart;
pQJTVSET->m_nCnt = nCnt;
pQJTVSET->m_fixFps = fixFps;
LoadQJTV(pQJTVSET, nStart, nCnt );
}
//동영상의 시작할 첫번째 파일의 위치, 총 프레임 수, 각 프레임의 랜더링걸 시간
bool SGameMultiQJTV::LoadQJTV( sQJTV* pQJTVSET, int nStart/*0*/, int nCnt/*0*/ )
{
if( pQJTVSET == NULL ) return false;
//QJTVObj 안에서 KStream 삭제 된다
KStream* pStream = KFileManager::Instance().CreateStreamFromResource( pQJTVSET->m_strFileName.c_str() );
pQJTVSET->m_QJTV.Load( &pQJTVSET->m_Meta, pStream ); //파일로드
if( !CheckData(pQJTVSET, nStart, nCnt) ) //생성하고자 하는 옵션이 현재 로딩한 파일에 적합한지 검사
return false;
pQJTVSET->m_bSuccessSetting = true;
return true;
}
bool SGameMultiQJTV::CheckData( sQJTV* pQJTVSET, int nStart/*0*/, int nCnt/*0*/ )
{
if( pQJTVSET == NULL ) return false;
pQJTVSET->m_nFrameCnt = pQJTVSET->m_QJTV.GetFrameCount();
if( pQJTVSET->m_nFrameCnt == 0 ) return false;
if( pQJTVSET->m_nFrameCnt <= nStart ) return false;
if( pQJTVSET->m_nFrameCnt < nStart+nCnt ) return false;
return true;
}
bool SGameMultiQJTV::CreateTexture( KColor BackColor, int& nSrcWidth, int& nSrcHeight )
{
int nExpX(nSrcWidth) ,nExpY(nSrcHeight);
// K3DRenderDevice::GetSquareSize( nSrcWidth, nSrcHeight, nExpX, nExpY ); //택스처의 크기에 맞게 생성
if( KUITextureManager::GetHWType() == KUITextureManager::HW_SUPPORT )
{
m_pTexture = m_pRenderDevice->CreateTexture( nExpX, nExpY, KUSAGE_DYNAMIC, K3DFMT_A8R8G8B8, D3DPOOL_DEFAULT );
}
else //Intel Chip 계열에서 지원 안 되는 넘들이 있음.
{
m_pTexture = m_pRenderDevice->CreateTexture( nExpX, nExpY, K3DFMT_A8R8G8B8, D3DPOOL_MANAGED );
}
if( m_pTexture == NULL ) return false;
else
{
BYTE* pTextureBuf(NULL); int nStride(0);
m_pTexture->LockRect( NULL, (void**)&pTextureBuf, nStride );
if( pTextureBuf == NULL )
{
m_pTexture = NULL;
assert( 0 && "QJTV Lock Failed <BackClear>!!!" );
return false;
}
for( UINT i(0); i < (UINT)(nExpY*nExpX); i++ )
{
KColor* pColor = ( KColor* )pTextureBuf;
pColor[i] = m_BackColor;
}
m_pTexture->Unlock();
}
nSrcWidth = nExpX;
nSrcHeight = nExpY;
m_pResSprite->SetTexture(m_pTexture, NULL); //택스처 리소스스프라이트에 쎄팅
m_pSpritePrimitive.SetTargetSize( nSrcWidth, nSrcHeight );
return true;
}
bool SGameMultiQJTV::RefreshSeenTexture( sQJTV* pQJTVSET )
{
if( !pQJTVSET || !pQJTVSET->m_bSuccessSetting || m_pTexture == NULL ) return false;
int nTextureX(m_pTexture->GetWidth()), nTextureY(m_pTexture->GetHeight());
BYTE* pSrcBits(NULL);
int nSrcWidth(0), nSrcHeight(0);
pQJTVSET->m_QJTV.GetFrame( pQJTVSET->m_nCrrFrame, pSrcBits, nSrcWidth, nSrcHeight );
UINT StartX(0); UINT StartY(0);
if( pQJTVSET->m_TextureOption & QJTV::CENTER )
{
StartX = nTextureX/2-nSrcWidth/2;
StartY = nTextureY/2-nSrcHeight/2;
}
BYTE* pTextureBuf(NULL);
int nStride(0);
KRect rcRock(StartX, StartY, StartX+nSrcWidth, StartY+nSrcHeight);
m_pTexture->LockRect( &rcRock, (void**)&pTextureBuf, nStride );
if( pTextureBuf == NULL )
{
m_pTexture = NULL;
pQJTVSET->m_bSuccessCraeteTexture = false;
assert( 0 && "QJTV Lock Failed!!!" );
return false;
}
KColor* pColor(NULL);
for( UINT y(0); y < (UINT)nSrcHeight; y++ )
{
pColor = (KColor*)pTextureBuf;
for( UINT x(0); x < (UINT)nSrcWidth; ++x )
{
KColor col;
UINT Pos = (y*nSrcWidth +x)*4;
col.b = pSrcBits[Pos+0];
col.g = pSrcBits[Pos+1];
col.r = pSrcBits[Pos+2];
if( pQJTVSET->m_TextureOption & QJTV::ALPHA )
col.a = pSrcBits[Pos+3];
else col.a = 255; //택스처에 있는 알파값을 사용하지 않는 경우
pColor[x] = col;
}
pTextureBuf += nStride;
}
m_pTexture->Unlock();
pQJTVSET->m_bSuccessCraeteTexture = true;
return true;
}
bool SGameMultiQJTV::SetScreenCenter()
{
if( m_pRenderDevice == NULL || m_pTexture == NULL ) return false;
KSize ScreenSize = m_pRenderDevice->GetScreenSize();
int nTextureX(m_pTexture->GetWidth()), nTextureY(m_pTexture->GetHeight());
int StartX = ScreenSize.width/2-nTextureX/2;
int StartY = ScreenSize.height/2-nTextureY/2;
m_Matrix.SetPosVector( K3DVertex( StartX, StartY, 0.1f ) );
m_pResSprite->SetTransform(m_Matrix);
return true;
}
void SGameMultiQJTV::SetState( int nState )
{
if( m_pCrrQJTV )
m_pCrrQJTV->m_nState = nState;
}
void SGameMultiQJTV::StartPlay( sQJTV* pQJTVSET, bool bRefreshTexture )
{
if( pQJTVSET == NULL ) return;
pQJTVSET->m_bPlay = true;
pQJTVSET->m_OldFrameRenderTime = pQJTVSET->m_StartTime = GetSafeTickCount();
pQJTVSET->m_nCrrFrame = pQJTVSET->m_nStartFrame;
if( bRefreshTexture )
RefreshSeenTexture( pQJTVSET );
pQJTVSET->m_nState = QJTV::PLAY;
}
void SGameMultiQJTV::Play( sQJTV* pQJTVSET, bool bRefreshTexture )
{
if( pQJTVSET == NULL ) return;
bool bOver( pQJTVSET->m_nCrrFrame+1 > (int)pQJTVSET->m_QJTV.GetFrameCount() );
if( !pQJTVSET->m_bRepeat && bOver )
{
pQJTVSET->m_nState = QJTV::END;
return;
}
float msFps = 1000.f / pQJTVSET->m_fixFps;
if ( pQJTVSET->m_CrrTime - pQJTVSET->m_OldFrameRenderTime > msFps )
{
++pQJTVSET->m_nCrrFrame;
pQJTVSET->m_OldFrameRenderTime = GetSafeTickCount();
if(bOver && pQJTVSET->m_bRepeat) pQJTVSET->m_nCrrFrame = pQJTVSET->m_nStartFrame;
if( pQJTVSET->m_bSuccessCraeteTexture && pQJTVSET->m_nFrameCnt <= 1 )
return;
if( bRefreshTexture )
RefreshSeenTexture( pQJTVSET );
}
}
void SGameMultiQJTV::OFF( sQJTV* pQJTVSET )
{
if( pQJTVSET == NULL ) return;
pQJTVSET->m_bPlay = false;
pQJTVSET->m_nState = QJTV::OFF;
}
int SGameMultiQJTV::Render( KViewportObject *viewport, bool bFront/*=true*/ )
{
//OFF이거나 STOP일때는 render안건다...
if( !m_pCrrQJTV || m_pCrrQJTV->m_nState == QJTV::OFF ) return QJTV::OFF;
// if( m_nState == QJTV::STOP ) return QJTV::STOP;
viewport->Register( &m_pSpritePrimitive );
// viewport->Register( &m_pSpritePrimitive, bFront );
return m_pCrrQJTV->m_nState;
}
void SGameMultiQJTV::Proc( DWORD dwTime )
{
int nSize( m_vecQJTV.size() );
for( int i(0); i<nSize; ++i )
{
m_vecQJTV[i]->m_CrrTime = dwTime;
if( !m_vecQJTV[i]->m_bSuccessSetting || m_pTexture == NULL || m_vecQJTV[i]->m_nState == QJTV::OFF )
return;
bool bUpdateTexture( m_vecQJTV[i] == m_pCrrQJTV );
switch(m_vecQJTV[i]->m_nState)
{
case QJTV::STARTPLAY: StartPlay( m_vecQJTV[i], bUpdateTexture ); break;
case QJTV::PLAY: Play( m_vecQJTV[i], bUpdateTexture ); break;
case QJTV::OFF: OFF( m_vecQJTV[i] ); break;
}
}
}
int SGameMultiQJTV::SetOff()
{
if( !m_pCrrQJTV ) return QJTV::OFF;
m_pCrrQJTV->m_bPlay = false;
m_pCrrQJTV->m_nState = QJTV::OFF;
return m_pCrrQJTV->m_nState;
}