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

584 lines
14 KiB
C++

#include "stdafx.h"
#include "SGameCutScene.h"
#include "SGameSceneManager.h"
#include "SGameMilesSoundMgr.h"
#include "KResourceManager.h"
#include "KViewport.h"
#include "TinyXML.h"
#include <mmo/ArTime.h>
#include <kfile/KFileManager.h>
#include "SStringDB.h"
using namespace rp;
SGameCutScene::Image::Image( SGameSceneManager& sceneMgr, const char* szName, const char* szFileName )
: Primitive( szName )
{
NX3LoadPack loadpack;
loadpack.Init();
mTexture = sceneMgr.textureMgr().GetTexture( szFileName, &loadpack, true, 0 );
assert( mTexture && "image scene's texture was not loaded!!" );
if( mTexture == 0 )
return;
K3DMatrix worldMatrix;
K3DMatrixIdentity( worldMatrix );
worldMatrix.SetPosVector( K3DVector( 0, 0, 0 ) );
mSprite = new KResSprite();
mSprite->SetTexture( mTexture, NULL );
mSprite->SetTransform( worldMatrix );
mPrimitive.SetRes( mSprite );
}
SGameCutScene::Image::~Image()
{
mPrimitive.SetRes( 0 );
}
SGameCutScene::Text::Text( const char* szName, const char* szText, int nWidth, int nHeight )
: Primitive( szName ), mText( szText ), m_pText( NULL )
{
//_ASSERTE( _CrtCheckMemory( ) );
SDEBUGLOG("SGameCutScene::Text::Text - begin");
SDEBUGLOG("SGameCutScene::Text::Text %s, %s, %d, %d",szName,szText,nWidth,nHeight);
#ifdef _COUNTRY_ME_
m_pText = new KTextLayout2( nWidth, nHeight );
#else
m_pText = new KTextPhrase( nWidth, nHeight );
#endif
SDEBUGLOG("SGameCutScene::Text::Text - KTextPhrase()");
//_ASSERTE( _CrtCheckMemory( ) );
m_pText->AddString( szText );
SDEBUGLOG("SGameCutScene::Text::Text - end");
}
SGameCutScene::Text::Text( const char* szName, const int nTextID, int nWidth, int nHeight )
: Primitive( szName ), m_pText( NULL )
{
mText = GetStringDB().GetString( nTextID );
#ifdef _COUNTRY_ME_
m_pText = new KTextLayout2( nWidth, nHeight );
#else
m_pText = new KTextPhrase( nWidth, nHeight );
#endif
m_pText->AddString( mText.c_str() );
}
SGameCutScene::Text::~Text()
{
SAFE_DELETE( m_pText );
}
void SGameCutScene::Image::SetPosition( int nX, int nY )
{
mPrimitive.SetPosition( nX, nY, 0 );
}
void SGameCutScene::Image::SetVisibility( float fVis )
{
mPrimitive.SetVisibility( fVis );
}
void SGameCutScene::Image::SetScale( float fW, float fH )
{
mPrimitive.SetTargetSize( fW * mSprite->GetSizeX(), fH * mSprite->GetSizeY() );
}
void SGameCutScene::Image::SetSize( float fW, float fH )
{
mPrimitive.SetTargetSize( fW, fH );
}
void SGameCutScene::Image::Render( KViewportObject* viewport )
{
viewport->Register( &mPrimitive );
}
void SGameCutScene::Text::SetPosition( int nX, int nY )
{
m_pText->SetPosition( nX, nY, 0 );
}
void SGameCutScene::Text::SetVisibility( float fVis )
{
m_pText->SetVisibility( fVis );
}
void SGameCutScene::Text::SetScale( float fW, float fH )
{
}
void SGameCutScene::Text::SetSize( float fW, float fH )
{
}
void SGameCutScene::Text::Render( KViewportObject* viewport )
{
m_pText->Render( viewport, true );
}
SGameCutScene::animation::animation( const char* szName )
: mObjName( szName )
{}
SGameCutScene::animation::~animation()
{
for ( ilistAttr itor = mAttrs.begin(); itor != mAttrs.end(); ++itor )
delete *itor;
mAttrs.clear();
}
void SGameCutScene::attr_pos::Apply( DWORD dwTime, SGameCutScene::attr_snapshot& attr )
{
if ( IsInTime( dwTime ) )
{
if ( dwEndTime == 0xFFFFFFFF )
{
attr.nX = nSX;
attr.nY = nSY;
}
else
{
float fD1 = ( dwEndTime - dwTime );
float fD2 = ( dwTime - dwStartTime );
attr.nX = ( nSX * fD1 + nEX * fD2 ) / (dwEndTime - dwStartTime);
attr.nY = ( nSY * fD1 + nEY * fD2 ) / (dwEndTime - dwStartTime);
}
}
}
void SGameCutScene::attr_scale::Apply( DWORD dwTime, SGameCutScene::attr_snapshot& attr )
{
if ( IsInTime( dwTime ) )
{
if ( dwEndTime == 0xFFFFFFFF )
{
attr.fW = fSW;
attr.fH = fSH;
}
else
{
float fD1 = ( dwEndTime - dwTime );
float fD2 = ( dwTime - dwStartTime );
attr.fW = ( fSW * fD1 + fEW * fD2 ) / (dwEndTime - dwStartTime);
attr.fH = ( fSH * fD1 + fEH * fD2 ) / (dwEndTime - dwStartTime);
}
}
}
void SGameCutScene::attr_vis::Apply( DWORD dwTime, SGameCutScene::attr_snapshot& attr )
{
if ( IsInTime( dwTime ) )
{
if ( dwEndTime == 0xFFFFFFFF )
{
attr.fV = fSVis;
}
else
{
float fD1 = ( dwEndTime - dwTime );
float fD2 = ( dwTime - dwStartTime );
attr.fV = ( fSVis * fD1 + fEVis * fD2 ) / (dwEndTime - dwStartTime);
}
}
}
SGameCutScene::attr_snapshot SGameCutScene::animation::GetAttrAt( DWORD dwTime )
{
attr_snapshot attr;
for ( ilistAttr itor = mAttrs.begin(); itor != mAttrs.end(); ++itor )
(*itor)->Apply( dwTime, attr );
return attr;
}
bool SGameCutScene::animation::IsVisibleAt( DWORD dwTime )
{
for ( ilistAttr itor = mAttrs.begin(); itor != mAttrs.end(); ++itor )
{
if ( (*itor)->IsInTime( dwTime ) )
return true;
}
return false;
}
bool SGameCutScene::animation::IsEnd( DWORD dwTime )
{
DWORD dwMaxEndTime = 0;
for ( ilistAttr itor = mAttrs.begin(); itor != mAttrs.end(); ++itor )
{
if ( (*itor)->dwEndTime != 0xFFFFFFFF )
dwMaxEndTime = std::max( (*itor)->dwEndTime, dwMaxEndTime );
}
return dwTime >= dwMaxEndTime;
}
SGameCutScene::SGameCutScene(
SGameSceneManager& sceneMgr
, SGameScene* parent
, const char* sceneName
, const char* sceneFile
, const K3DVector& position
, const K3DVector2& size )
: SGameScene( sceneMgr, parent, sceneName )
, mSceneFile( sceneFile )
, mStartTime( 0 )
, mLastTime( 0 )
, mPosition( position )
, mSize( size )
{
}
SGameCutScene::~SGameCutScene()
{
onLeave();
}
void SGameCutScene::onEnter()
{
// pack파일에서 .xml 파일을 추출한다.
//_ASSERTE( _CrtCheckMemory( ) );
std::string strFile = KFileManager::Instance().CreateTemporaryFileFromResourceWithLocale( mSceneFile.c_str() );
//_ASSERTE( _CrtCheckMemory( ) );
TiXmlDocument doc( strFile.c_str() );
bool bSuc = doc.LoadFile();
//_ASSERTE( _CrtCheckMemory( ) );
// 추출한 pack파일을 삭제한다.
KFileManager::Instance().DeleteTemporaryFile( mSceneFile.c_str() );
//_ASSERTE( _CrtCheckMemory( ) );
if ( bSuc )
{
TiXmlElement* pBGM = doc.FirstChildElement( "bgm" );
if ( pBGM )
m_strBGMFileName = pBGM->Attribute( "filename" );
//_ASSERTE( _CrtCheckMemory( ) );
TiXmlNode* pObjRoot = doc.FirstChild( "objects" );
//_ASSERTE( _CrtCheckMemory( ) );
if ( pObjRoot )
{
TiXmlElement* pObj = pObjRoot->FirstChildElement();
while ( pObj)
{
//_ASSERTE( _CrtCheckMemory( ) );
if ( strcmp( pObj->Value(), "image" ) == 0 )
{
SDEBUGLOG("%s ",pObj->Value() );
Image* pImage = new Image( getSceneManager(), pObj->Attribute( "name" ), pObj->Attribute( "file" ) );
// 2010.06.03 - prodongi
if (!pImage->mSprite)
continue;
// CutScene 내부 좌표계는 0,0 ~ 1024,768 을 기준임으로 실제 화면 사이즈에 맞게 조절 해 준다. 2006.06.04 sfreer
int nWidth = pImage->mSprite->GetSizeX();
int nHeight = pImage->mSprite->GetSizeY();
if(mSize.x > 0)
nWidth = nWidth * mSize.x / 1024;
if(mSize.y > 0)
nHeight = nHeight * mSize.y / 768;
pImage->SetSize(nWidth, nHeight);
mPrimitives.insert( mapPrimitive::value_type( pObj->Attribute( "name" ), pImage ) );
mImagelist.push_back( pImage );
}
else if ( strcmp( pObj->Value(), "string" ) == 0 )
{
int nWidth, nHeight;
pObj->Attribute( "width", &nWidth );
pObj->Attribute( "height", &nHeight );
SDEBUGLOG("%s %d %d",pObj->Value(),nWidth, nHeight);
// CutScene 내부 좌표계는 0,0 ~ 1024,768 을 기준임으로 실제 화면 사이즈에 맞게 조절 해 준다. 2006.06.04 sfreer
if(mSize.x > 0)
nWidth = nWidth * mSize.x / 1024;
if(mSize.y > 0)
nHeight = nHeight * mSize.y / 768;
//_ASSERTE( _CrtCheckMemory( ) );
Text* pText = new Text( pObj->Attribute( "name" ), pObj->Attribute( "text" ), nWidth, nHeight ); //[MEMORY_LEAK] 2012. 3. 5 - marine 맵 clear 시 메모리 해제 되고 있음.
auto ret = mPrimitives.insert( mapPrimitive::value_type( pObj->Attribute( "name" ), pText ) );
if( ret.second == false )
{
delete pText;
}
}
else if ( strcmp( pObj->Value(), "stringid" ) == 0 )
{
int nWidth, nHeight;
int nTextID;
pObj->Attribute( "width", &nWidth );
pObj->Attribute( "height", &nHeight );
pObj->Attribute( "textid", &nTextID );
SDEBUGLOG("%s %d %d %d",pObj->Value(),nWidth, nHeight, nTextID);
// CutScene 내부 좌표계는 0,0 ~ 1024,768 을 기준임으로 실제 화면 사이즈에 맞게 조절 해 준다. 2006.06.04 sfreer
if(mSize.x > 0)
nWidth = nWidth * mSize.x / 1024;
if(mSize.y > 0)
nHeight = nHeight * mSize.y / 768;
//_ASSERTE( _CrtCheckMemory( ) );
Text* pText = new Text( pObj->Attribute( "name" ), nTextID, nWidth, nHeight );
auto ret = mPrimitives.insert( mapPrimitive::value_type( pObj->Attribute( "name" ), pText ) );
if( ret.second == false )
{
delete pText;
}
}
pObj = pObj->NextSiblingElement();
}
}
//_ASSERTE( _CrtCheckMemory( ) );
TiXmlElement* pAniRoot = doc.FirstChildElement( "animation" );
while ( pAniRoot )
{
animation* pAnimation = new animation( pAniRoot->Attribute( "object" ) );
TiXmlElement* pAttr = pAniRoot->FirstChildElement();
while ( pAttr )
{
DWORD dwStartTime, dwEndTime;
pAttr->Attribute( "stime", (int *)&dwStartTime );
if ( pAttr->Attribute( "etime", (int *)&dwEndTime ) == NULL )
dwEndTime = 0xFFFFFFFF;
if ( strcmp( pAttr->Value(), "position" ) == 0 )
{
int nSX, nSY, nEX, nEY;
pAttr->Attribute( "sx", &nSX );
pAttr->Attribute( "sy", &nSY );
pAttr->Attribute( "ex", &nEX );
pAttr->Attribute( "ey", &nEY );
// CutScene 내부 좌표계는 0,0 ~ 1024,768 을 기준임으로 실제 화면 사이즈에 맞게 조절 해 준다. 2006.06.04 sfreer
if(mSize.x > 0)
{
nSX = (nSX * mSize.x / 1024);// + mPosition.x;
nEX = (nEX * mSize.x / 1024);// + mPosition.x;
}
if(mSize.y > 0)
{
nSY = (nSY * mSize.y / 768);// + mPosition.y;
nEY = (nEY * mSize.y / 768);// + mPosition.y;
}
nSX = nSX + mPosition.x;
nEX = nEX + mPosition.x;
nSY = nSY + mPosition.y;
nEY = nEY + mPosition.y;
attr_pos* pPos = new attr_pos( dwStartTime, nSX, nSY, dwEndTime, nEX, nEY );
pAnimation->mAttrs.push_back( pPos );
}
else if ( strcmp( pAttr->Value(), "scale" ) == 0 )
{
double dSW, dSH, dEW, dEH;
pAttr->Attribute( "sw", &dSW );
pAttr->Attribute( "sh", &dSH );
pAttr->Attribute( "ew", &dEW );
pAttr->Attribute( "eh", &dEH );
attr_scale* pScale = new attr_scale( dwStartTime, dSW, dSH, dwEndTime, dEW, dEH );
pAnimation->mAttrs.push_back( pScale );
}
else if ( strcmp( pAttr->Value(), "visibility" ) == 0 )
{
double dSV, dEV;
pAttr->Attribute( "sv", &dSV );
pAttr->Attribute( "ev", &dEV );
attr_vis* pVis = new attr_vis( dwStartTime, dSV, dwEndTime, dEV );
pAnimation->mAttrs.push_back( pVis );
}
pAttr = pAttr->NextSiblingElement();
}
mAnimations.push_back( pAnimation );
pAniRoot = pAniRoot->NextSiblingElement( "animation" );
}
}
else
{
std::string errmsg = "xml scene's was not loaded - ";
errmsg += mSceneFile;
MessageBox(NULL, errmsg.c_str(),"error", MB_OK);
}
//_ASSERTE( _CrtCheckMemory( ) );
}
void SGameCutScene::onLeave()
{
//mImagelist.push_back( pImage );
for ( imapPrimitive itor = mPrimitives.begin(); itor != mPrimitives.end(); ++itor )
{
bool enabledel = true;
for( std::list<Image *>::iterator itt = mImagelist.begin() ; itt != mImagelist.end(); ++itt)
{
if( (*itt) == itor->second )
{
enabledel = false;
break;
}
}
if(enabledel)
delete itor->second;
}
mPrimitives.clear();
for( std::list<Image *>::iterator itt = mImagelist.begin() ; itt != mImagelist.end(); ++itt)
delete (*itt);
mImagelist.clear();
for ( ilistAnimation itor = mAnimations.begin(); itor != mAnimations.end(); ++itor )
delete *itor;
mAnimations.clear();
}
void SGameCutScene::onActivate()
{
// mStartTime = mLastTime = mSceneMgr.timer().getTime();
mStartTime = GetSafeTickCount();
mLastTime = 0;
_oprint( "\n\n\nFrame Start Time = %d\n\n\n\n", mStartTime );
//mSceneMgr.milesSoundMgr().StopBgm();
mSceneMgr.milesSoundMgr().StopMusic();
//mSceneMgr.milesSoundMgr().ForcePlayMusic( m_strBGMFileName.c_str() );
mSceneMgr.milesSoundMgr().SwapPlayBGM( m_strBGMFileName.c_str(), 100, 1000, 1000, false );
}
void SGameCutScene::onDeactivate()
{
SGameScene::onDeactivate();
}
void SGameCutScene::onTick()
{
SGameScene::onTick();
//_oprint( "LastTime = %d ", mLastTime );
if(mLastTime == 0)
mLastTime = GetSafeTickCount();//mSceneMgr.timer().getTime();
DWORD ScreeningTimeDiff = /*mSceneMgr.timer().getTime()*/GetSafeTickCount() - mLastTime;
//_oprint( "Frame Diff Time = %d ", ScreeningTimeDiff );
bool bAllEnd = true;
DWORD dwFrame = (mLastTime - mStartTime) * 30 / 1000;
animation* pAni;
for ( ilistAnimation itor = mAnimations.begin(); itor != mAnimations.end(); ++itor )
{
pAni = *itor;
if ( !pAni->IsEnd( dwFrame ) )
bAllEnd = false;
if ( pAni->IsVisibleAt( dwFrame ) )
{
imapPrimitive itObj;
itObj = mPrimitives.find( pAni->mObjName );
if ( itObj != mPrimitives.end() )
{
Primitive* pPrim = itObj->second;
attr_snapshot attr = pAni->GetAttrAt( dwFrame );
/*
pPrim->SetPosition( attr.nX, attr.nY);
pPrim->SetVisibility( attr.fV );
*/
//_oprint( "Frame : %d, Vis = %x, nX = %d, nY = %d \n", dwFrame, attr.fV );
}
}
}
if (bAllEnd )
activate( false );
mLastTime += ScreeningTimeDiff;
}
void SGameCutScene::onRender( KViewportObject* viewport )
{
if(mLastTime == 0)
return;
animation* pAni;
DWORD dwFrame = (mLastTime - mStartTime) * 30 / 1000;
for ( ilistAnimation itor = mAnimations.begin(); itor != mAnimations.end(); ++itor )
{
pAni = *itor;
if ( pAni->IsVisibleAt( dwFrame ) )
{
imapPrimitive itObj;
itObj = mPrimitives.find( pAni->mObjName );
if ( itObj != mPrimitives.end() )
{
Primitive* pPrim = itObj->second;
//좌표값, 투명도 갱신이 제대로 이루어져있지 않아 onTick 에서 여기로 임시로 옮겨옴. 2009.07.10 sfreer
attr_snapshot attr = pAni->GetAttrAt( dwFrame );
pPrim->SetPosition( attr.nX, attr.nY);
pPrim->SetVisibility( attr.fV );
pPrim->Render( viewport );
}
}
}
}