#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(""); 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(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 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; }