Files
Leviathan/Client/Game/engine/Ui/Controls/KUIControlSkillCastGauge.cpp
2026-06-01 12:46:52 +02:00

618 lines
13 KiB
C++

#include "stdafx.h"
#include "KViewport.h"
#include "KPrimitiveSprite.h"
#include "KUIControlSkillCastGauge.h"
#include "KResourceManager.h"
#include "KUIDefine.h"
#include "KUIWndManager.h"
using namespace KUI_MESSAGE;
namespace
{
KUIWnd* Creator()
{
return new KUIControlSkillCastGauge;
}
bool bRegister = KUIFactory::GetInstance()->RegisterCreator( Creator, "skill_cast_gauge");
enum CONTROL_STATE
{
CS_NONE = 0,
CS_CAST,
CS_CAST_LAST,
CS_CLOSE,
};
const int TEXT_Y_OFFSET = 2;
const int TEXT_Y_SIZE = 16;
const int CAST_LAST_TIME = 200;
const int CLOSE_TIME = 800;
}
KUIControlSkillCastGauge::KUIControlSkillCastGauge()
{
m_CurState = CONTROL_STATE::CS_NONE;
m_StartTime = 0;
m_CastTime = 0;
_registerPhrase(&m_SkillNamePhrase);
}
KUIControlSkillCastGauge::~KUIControlSkillCastGauge()
{
}
void KUIControlSkillCastGauge::Cast(LPCSTR skillName, DWORD castTime)
{
ChangeAlpha(1.f);
m_StartTime = m_CurTime;
m_CastTime = castTime;
m_CurState = CONTROL_STATE::CS_CAST;
std::string tagedSkillName("<HCENTER>");
tagedSkillName.append(skillName);
m_SkillNamePhrase.Clear();
m_SkillNamePhrase.AddString(tagedSkillName.c_str() );
m_rcGaugeClipArea = m_rcRegion;
InvalidateWnd();
}
void KUIControlSkillCastGauge::DelayCast( DWORD castTime )
{
if( m_CastTime != castTime )
{
m_CastTime = castTime;
InvalidateWnd();
}
}
void KUIControlSkillCastGauge::Cancel()
{
_SetNextState(CONTROL_STATE::CS_CLOSE,CLOSE_TIME);
m_CurState = CONTROL_STATE::CS_CLOSE;
InvalidateWnd();
}
DWORD KUIControlSkillCastGauge::GetRemainTime()
{
if(m_StartTime > m_CurTime)
return 0;
DWORD passTime = m_CurTime - m_StartTime;
if( passTime > m_CastTime)
return 0;
return m_CastTime - passTime;
}
void KUIControlSkillCastGauge::Process( DWORD dwTime )
{
m_CurTime = dwTime;
float fPercent = _GetPercent();
switch( m_CurState)
{
case CONTROL_STATE::CS_NONE:
break;
case CONTROL_STATE::CS_CAST:
m_rcGaugeClipArea.right = m_rcGaugeClipArea.left + m_rcRegion.GetWidth() * fPercent;
if( m_pSpriteList )
m_pSpriteList[0].SetClipRect(&m_rcGaugeClipArea);
else
assert( false && "KUIControlSkillCastGauge::Process m_pSpriteList == NULL" );
if(fPercent == 1.f)
_SetNextState(CS_CAST_LAST,CAST_LAST_TIME);
#ifdef _KUI_INVALIDATION
// { [sonador]
InvalidateWnd();
// }
#endif
break;
case CONTROL_STATE::CS_CAST_LAST:
if(fPercent == 1.f)
_SetNextState(CS_CLOSE, CLOSE_TIME);
break;
case CONTROL_STATE::CS_CLOSE:
ChangeAlpha(1.f - fPercent);
if(fPercent == 1.f)
_SetNextState(CONTROL_STATE::CS_NONE,0);
break;
default:
assert(false && "Invalid State");
}
}
void KUIControlSkillCastGauge::Render(KViewportObject * pViewport, bool isFront)
{
if(false == m_bShowFlag || CONTROL_STATE::CS_NONE == m_CurState)
return;
_renderBack(pViewport,isFront);
m_SkillNamePhrase.Render(pViewport, isFront);
}
void KUIControlSkillCastGauge::OnPosChangeNofity(int XOffset, int YOffset)
{
KUIControl::OnPosChangeNofity(XOffset,YOffset);
m_rcGaugeClipArea.left += XOffset;
m_rcGaugeClipArea.right+= XOffset;
m_rcGaugeClipArea.top += YOffset;
m_rcGaugeClipArea.bottom += YOffset;
}
void KUIControlSkillCastGauge::OnClipChangeNotify(const KRect& rcClipRect)
{
KUIControl::OnClipChangeNotify(rcClipRect);
if(m_nPieceCount == 0)
return;
if( m_pSpriteList )
m_pSpriteList[0].SetClipRect(&m_rcGaugeClipArea);
else
assert( false && "KUIControlSkillCastGauge::OnClipChangeNotify m_pSpriteList == NULL" );
}
void KUIControlSkillCastGauge::_initControl()
{
UpdateBack();
if(m_nPieceCount == 0)
return;
m_rcGaugeClipArea = m_rcRegion;
if( m_pSpriteList )
m_pSpriteList[0].SetClipRect(&m_rcGaugeClipArea);
else
assert( false && "KUIControlSkillCastGauge::_initControl() m_pSpriteList == NULL" );
m_SkillNamePhrase.Initialize(m_rcRegion.GetWidth(), TEXT_Y_SIZE);
m_SkillNamePhrase.SetPosition(m_rcRegion.left, m_rcRegion.bottom + TEXT_Y_OFFSET,m_fZPos);
}
void KUIControlSkillCastGauge::_SetNextState(DWORD nextState, DWORD castTime)
{
m_CurState = nextState;
m_StartTime = m_CurTime;
m_CastTime = castTime;
InvalidateWnd();
}
float KUIControlSkillCastGauge::_GetPercent()
{
if(m_CastTime == 0)
return 1.f;
return std::min(1.f, static_cast<float>(m_CastTime - GetRemainTime() ) / m_CastTime );
}
//////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////
namespace
{
KUIWnd* EffectGaugeCreator()
{
return new KUIControlEffectGauge;
}
bool bEffectGaugeRegister = KUIFactory::GetInstance()->RegisterCreator( EffectGaugeCreator, "effect_gauge");
enum
{
STEP_NONE,
STEP_INIT,
STEP_ING,
STEP_END,
};
const int ALPHA_TIME = 500;
}
class KSimpleSpriteAnimator
{
public:
enum ANI_TYPE
{
NORMAL = 1 << 0,
LAST_PAGE = 1 << 1,
REVERSE = 1 << 2,
REPEAT = 1 << 3,
PING_PONG = 1 << 4,
};
public:
KSimpleSpriteAnimator()
{
m_isPlay = false;
m_startTime = 0;
m_aniType = NORMAL;
m_curTime = 0;
m_frameTime = 0;
}
~KSimpleSpriteAnimator()
{
for(size_t i = 0 ; i < m_vtSpriteFrame.size(); ++i)
delete m_vtSpriteFrame[i];
m_vtSpriteFrame.clear();
}
void AddRes(KResSprite* pRes)
{
KSpritePrimitive *pSpr = new KSpritePrimitive;
pSpr->SetRes(pRes);
//Additive
pSpr->SetAdditiveRenderMode( true );
m_vtSpriteFrame.push_back(pSpr);
}
void StartAnimation(DWORD curTime, int aniType, DWORD frameTime)
{
m_isPlay = true;
m_startTime = curTime;
m_aniType = aniType;
m_frameTime = frameTime;
}
void StopAnimation()
{
m_isPlay = false;
}
bool IsPlay()
{
return m_isPlay;
}
KSpritePrimitive* Process(DWORD time)
{
m_curTime = time;
if(m_isPlay == false)
return NULL;
DWORD timeDiff = m_curTime - m_startTime;
if(m_frameTime == 0)
assert(false);
const size_t totalFrame = m_vtSpriteFrame.size();
if(totalFrame == 0)
assert(false );
DWORD frameIdx = timeDiff / m_frameTime;
if( frameIdx >= totalFrame)
{
if(m_aniType & PING_PONG)
{
// PING
if( (frameIdx / totalFrame) % 2 == 0)
{
frameIdx %= totalFrame;
}
else
{
frameIdx %= totalFrame;
frameIdx = totalFrame - 1 - frameIdx;
}
}
else if(m_aniType & REPEAT)
{
frameIdx %= totalFrame;
}
else if(m_aniType & LAST_PAGE)
{
frameIdx = totalFrame - 1;
}
else
{
m_isPlay = false;
frameIdx = 0;
return NULL;
}
}
if(m_aniType & REVERSE)
{
frameIdx = totalFrame - 1 - frameIdx;
}
return m_vtSpriteFrame.at(frameIdx);
}
void SetPosition(int x, int y, int z)
{
for(size_t i = 0 ; i < m_vtSpriteFrame.size(); ++i)
m_vtSpriteFrame.at(i)->SetPosition(x,y,z);
}
void SetAddPosition(int x, int y)
{
for(size_t i = 0 ; i < m_vtSpriteFrame.size(); ++i)
m_vtSpriteFrame.at(i)->SetAddPosition(x,y,0);
}
void SetVisibility(float fVisi)
{
for(size_t i = 0 ; i < m_vtSpriteFrame.size(); ++i)
m_vtSpriteFrame.at(i)->SetVisibility(fVisi);
}
void SetAniTargetSize( float width, float height )
{
for(size_t i = 0 ; i < m_vtSpriteFrame.size(); ++i)
m_vtSpriteFrame.at(i)->SetTargetSize( width, height );
}
private:
bool m_isPlay;
int m_aniType;
DWORD m_startTime;
DWORD m_curTime;
DWORD m_frameTime;
std::vector<KSpritePrimitive*> m_vtSpriteFrame;
};
KUIControlEffectGauge::KUIControlEffectGauge()
{
_SetNextState( STEP_NONE, 0 );
m_StartTime = 0;
m_CastTime = 0;
}
KUIControlEffectGauge::~KUIControlEffectGauge()
{
SAFE_DELETE_VECTOR(m_vtFrameAnimator);
}
void KUIControlEffectGauge::SetWorkingTime( int m_CastTime )
{
ChangeAlpha(1.f);
_SetNextState( STEP_INIT, m_CastTime );
InvalidateWnd();
}
void KUIControlEffectGauge::_SetNextState(short nextState, DWORD castTime)
{
m_nCurStep = nextState;
m_StartTime = m_CurTime;
m_CastTime = castTime;
InvalidateWnd();
}
void KUIControlEffectGauge::Process( DWORD dwTime )
{
m_CurTime = dwTime;
switch( m_nCurStep )
{
case STEP_NONE :
{
}
break;
case STEP_INIT :
{
m_StartTime = m_CurTime;
_SetNextState( STEP_ING, m_CastTime );
for(int i = 0 ; i < 1; ++i)
{
KSimpleSpriteAnimator* pAnimator = m_vtFrameAnimator.at(i);
pAnimator->StartAnimation( m_CurTime, KSimpleSpriteAnimator::REPEAT, 100 );
pAnimator->SetPosition( m_rcRegion.left, m_rcRegion.top, m_fZPos );
}
}
break;
case STEP_ING :
{
if( (m_CurTime - m_StartTime) >= m_CastTime )
{
_SetNextState( STEP_END, ALPHA_TIME );
m_rcGaugeClipArea.left = m_rcRegion.right;
}
else
{
float fValue = (float)(m_CurTime - m_StartTime)/m_CastTime;
m_rcGaugeClipArea.left = m_rcRegion.left + (m_rcRegion.GetWidth()-64)*fValue;
}
m_GaugeSprite[KEFFECTGAUGE_GRAY].SetClipRect(&m_rcGaugeClipArea);
for(int i = 0 ; i < 1; ++i)
{
KSimpleSpriteAnimator* pAnimator = m_vtFrameAnimator.at(i);
pAnimator->SetPosition( m_rcGaugeClipArea.left, m_rcGaugeClipArea.top, m_fZPos );
}
}
break;
case STEP_END :
{
_SetNextState(STEP_NONE,0);
}
break;
}
}
void KUIControlEffectGauge::Render(KViewportObject * pViewport, bool isFront /*= false*/ )
{
if( false == m_bShowFlag /*|| STEP_NONE == m_nCurStep*/ )
return;
for( int i = 0; i < KEFFECTGAUGE_MAX; ++i )
{
pViewport->Register(&m_GaugeSprite[i], isFront );
}
if( STEP_ING != m_nCurStep ) return;
for(size_t i = 0 ; i < m_vtFrameAnimator.size(); ++i)
{
KSpritePrimitive* pPrimitive = m_vtFrameAnimator.at(i)->Process(m_CurTime);
if(pPrimitive)
{
pViewport->Register(pPrimitive);
}
}
}
void KUIControlEffectGauge::OnPosChangeNofity(int XOffset, int YOffset)
{
KUIControl::OnPosChangeNofity(XOffset,YOffset);
m_rcGaugeClipArea.left += XOffset;
m_rcGaugeClipArea.right += XOffset;
m_rcGaugeClipArea.top += YOffset;
m_rcGaugeClipArea.bottom += YOffset;
}
void KUIControlEffectGauge::OnClipChangeNotify(const KRect& rcClipRect)
{
KUIControl::OnClipChangeNotify(rcClipRect);
if(m_nPieceCount == 0)
return;
m_GaugeSprite[KEFFECTGAUGE_GRAY].SetClipRect(&m_rcGaugeClipArea);
}
void KUIControlEffectGauge::updateSprite()
{
KResSprite* pFrame = _getSpriteSet()->GetSpriteRes(m_sAniName.c_str(),0);
if( !pFrame )
{
assert( false && "Cannot find Sprite Res Frame" );
return;
}
m_rcRegion.right = m_rcRegion.left + pFrame->GetSizeX();
m_rcRegion.bottom = m_rcRegion.top + pFrame->GetSizeY();
m_rcGaugeClipArea = m_rcRegion;
char buff[_MAX_PATH];
for( int i = 0; i < KEFFECTGAUGE_MAX; ++i )
{
_snprintf_s(buff, _MAX_PATH, _MAX_PATH-1, (i) < 1 ? "" : "_00" );
std::string aniName = m_sAniName;
aniName += buff;
KResSprite* pFrame = _getSpriteSet()->GetSpriteRes( aniName.c_str(), 0 );
if(!pFrame)
{
continue;
}
m_GaugeSprite[i].SetRes( pFrame );
m_GaugeSprite[i].SetPosition( m_rcRegion.left , m_rcRegion.top , m_fZPos );
if( i == KEFFECTGAUGE_GRAY )
m_GaugeSprite[i].SetClipRect(&m_rcGaugeClipArea);
}
//처음에 다 로드를 하자?
for(int i = 0 ; i < 1; ++i)
{
KSimpleSpriteAnimator* pAnimator = m_vtFrameAnimator.at(i);
char buff[_MAX_PATH];
for(int k = 0; k < 8; ++k)
{
_snprintf_s(buff, _MAX_PATH, _MAX_PATH-1, (k+1) >= 10 ? "%d" : "0%d", k+1);
std::string aniName = "effect_";
aniName += buff;
KResSprite* pRes = _getSpriteSet()->GetSpriteRes(aniName.c_str(), 0);
pAnimator->AddRes(pRes);
}
pAnimator->SetPosition(m_rcRegion.left, m_rcRegion.top, m_fZPos);
}
}
void KUIControlEffectGauge::_initControl()
{
if( m_sAniName.empty() )
return;
m_vtFrameAnimator.push_back(new KSimpleSpriteAnimator);
updateSprite();
}
void KUIControlEffectGauge::UpdateBack()
{
if( m_sAniName.empty() )
return;
updateSprite();
InvalidateWnd();
}
DWORD KUIControlEffectGauge::OnMouseMessage(DWORD dwMessage, int x, int y)
{
DWORD dwRet = KUIControl::OnMouseMessage(dwMessage,x,y);
if(KMR_NO_GET & dwRet)
return dwRet;
if( IsDisable() ) return dwRet;
if(IsInRect(x,y) )
{
switch(dwMessage)
{
case KMOUSE_MOVE:
break;
case KLBUTTON_DOWN:
PumpUpMessage(GetID(), KEFFECTGAUGE_PRESSING, 0,0);
m_dwButtonState = KEFFECTGAUGE_DOWN;
break;
case KLBUTTON_UP:
if(m_dwButtonState == KEFFECTGAUGE_DOWN )
PumpUpMessage(GetID(), KEFFECTGAUGE_CLICK, 0,0);
m_dwButtonState = KEFFECTGAUGE_ACTIVATE;
break;
case KLBUTTON_DBLCLK:
PumpUpMessage(GetID(), KEFFECTGAUGE_KICON_DBLCLK, 0,0);
m_dwButtonState = KEFFECTGAUGE_ACTIVATE;
break;
default:
break;
}
}
else
{
if ( dwMessage == KLBUTTON_UP )
{
m_pManager->ReleaseCapture( this );
}
// 마우스 범위를 벗어나면 Normal로 돌린다.
if(m_dwButtonState == KEFFECTGAUGE_ACTIVATE || m_dwButtonState == KEFFECTGAUGE_DOWN)
m_dwButtonState = KEFFECTGAUGE_NORMAL;
}
return dwRet;
}