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

2049 lines
56 KiB
C++

#include "stdafx.h"
#ifndef _COUNTRY_ME_
#include "KViewport.h"
#include "../KTextPhrase.h"
#include "KPrimitiveSprite.h"
//#include "KUIControl.h"
#include "KUITipControl.h"
#include "KUIWndManager.h"
#include "KUIDragAndDrop.h"
#include "KResourceManager.h"
#include <toolkit/XStringUtil.h>
//#include "Util.h"
#include <toolkit/nsluni.h>
#include "KTextPhrase.h"
#include <toolkit/SafeTickCount.h>
using namespace KUI_MESSAGE;
using namespace rp;
namespace
{
const char* c_szDefaultTooltipAniName = "static_fulldown_outframe";
struct StringOmitter
{
struct Element {
Element( bool isTag, const std::string& token ) : mIsTag( isTag ), mToken( token ) { }
bool mIsTag;
std::string mToken;
};
bool operator( )( std::string& out, const char* target, DWORD limitByte, const char* omissionMark )
{
if( target == 0 )
return false;
out.assign( target );
std::vector< Element > List;
size_t curBegin = 0;
DWORD byteCount = 0;
while( true )
{
size_t tag_begin = out.find( '<', curBegin );
if( tag_begin == out.npos )
{
if( out.begin() + curBegin != out.end() )
{
List.push_back( Element( false, std::string( out.begin() + curBegin, out.begin() + out.size() ) ) );
byteCount += out.size() - curBegin;
}
break;
}
size_t tag_end = out.find( '>', curBegin );
if( tag_end == out.npos )
{
if( out.begin() + curBegin != out.end() )
{
List.push_back( Element( false, std::string( out.begin() + curBegin, out.begin() + out.size() ) ) );
byteCount += out.size() - curBegin;
}
break;
}
if( tag_end > tag_begin )
{
if( tag_begin > curBegin )
{
List.push_back( Element( false, std::string( out.begin() + curBegin, out.begin() + tag_begin ) ) );
byteCount += tag_begin - curBegin;
}
List.push_back( Element( true, std::string( out.begin() + tag_begin, out.begin() + tag_end + 1 ) ) );
curBegin = tag_end + 1;
}
else
break;
}
if( byteCount <= limitByte )
return false;
out.clear();
bool found = false, needOmission = false;
byteCount = 0;
if( limitByte >= ::strlen( omissionMark ) )
{
limitByte -= ::strlen( omissionMark );
needOmission = true;
}
std::vector< Element >::iterator begin = List.begin(), end = List.end();
for( ; begin != end; ++begin )
{
Element& elem = *begin;
if( !elem.mIsTag )
{
if( !found )
{
byteCount += elem.mToken.size();
if( byteCount >= limitByte )
{
found = true;
DWORD overByte = byteCount - limitByte;
if( overByte > 0 )
{
LPCSTR lpszEnd = elem.mToken.c_str() + elem.mToken.size();
LPCSTR lpszNew = lpszEnd;
while( (lpszEnd - lpszNew) < overByte )
{
lpszNew = CharPrev( elem.mToken.c_str(), lpszNew );
}
elem.mToken.assign( elem.mToken.c_str(), lpszNew );
if( needOmission )
elem.mToken.append( omissionMark );
}
}
out.append( elem.mToken );
}
}
else
{
out.append( elem.mToken );
}
}
return true;
}
std::vector< Element > result;
};
};
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// KUIControl Implement
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
bool KUIControl::s_bIsDrawRectGrid = false;
short KUIControl::s_nBlankWidth = 0;
KUIControl* KUIControl::s_pToolTipOnControl = NULL;
void KUIControl::OnToolTipOnControl( KUIControl* pControl )
{
OffToolTipOnControl( pControl );
s_pToolTipOnControl = pControl;
}
void KUIControl::OffToolTipOnControl( KUIControl* pNewControl )
{
if( s_pToolTipOnControl && s_pToolTipOnControl != pNewControl )
{
s_pToolTipOnControl->SetTooltipOff();
s_pToolTipOnControl = NULL;
}
}
void KUIControl::SetNULLToolTipOnControl()
{
s_pToolTipOnControl = NULL;
}
KUIControl::KUIControl(void)
{
m_bIsDisable = false;
m_bUsePos = false;
m_bUsePosEnable = true;
m_bUseCustomSize = false; // #2.1.2.11.1
m_bUseHorizonPiece = true;
m_bUseEmoticonFilter = true;
m_bCaptionRandomColor = false;
m_bToolTipLeftRender = false;
m_nPieceCount = 0;
m_pSpriteList = NULL;
m_pTipControl = NULL;
m_pDragObject = NULL;
m_dwToolTipStartTime = 0;
m_dwToolTipPreStartTime = 0;
m_strEnableColor = "<#242424>";
m_strDisableColor = "<#505050>";
m_pRectGrid = new KWireUtilPrimitive;
m_bCutCaption = false; // 제목의 잘림처리 여부.
}
KUIControl::~KUIControl(void)
{
// 2010.05.06 - prodongi
clearEmoticonSizeList();
SAFE_DELETE( m_pRectGrid );
_destroyControl();
}
void KUIControl::Create(KUIWND_CREATE_ARG& CREATE_ARG)
{
KUIWnd::Create(CREATE_ARG);
_initControl();
SAFE_DELETE(m_pDragObject );
m_strTooltipSprName = CREATE_ARG.lpszSprName;
m_strTooltipAniName = c_szDefaultTooltipAniName;
if( m_dwFlag & KFLAG_CAN_DRAG)
{
if (m_pDragObject == NULL)
m_pDragObject = new KUIDragAndDropObject;
}
// 2010.07.05. bintitle. FontSize 얻기.
m_FontSize = 0;
std::string::size_type nPos = m_sCaption.find( "<size:" );
if( nPos != std::string::npos )
{
nPos += strlen( "<size:" );
std::string strTemp( m_sCaption.begin() + nPos, m_sCaption.begin() + m_sCaption.size() );
std::string::size_type nPos_End = strTemp.find_first_of( ">" );
strTemp = strTemp.substr( 0, nPos_End );
m_FontSize = ::atoi( m_sCaption.substr( nPos, strTemp.size() ).c_str() );
}
}
void KUIControl::Render( KViewportObject *pViewport, bool isFront )
{
if ( m_bShowFlag )
{
_renderBack(pViewport, isFront);
_renderChild(pViewport, isFront);
_renderCaption(pViewport, isFront);
#ifdef _KUI_INVALIDATION
// _renderToolTip(pViewport, isFront);
#else
_renderToolTip(pViewport, isFront);
#endif
if( s_bIsDrawRectGrid )
{
m_pRectGrid->Clear();
KRect rc = GetRect();
K3DVector pos[4];
K3DVector opos[4];
for( int i(0); 4>i; i++ )
{
pos[0] = K3DVector(0,0,0);
opos[0] = K3DVector(0,0,0);
}
pos[0] = K3DVector( rc.left , rc.top , 0 );
pos[1] = K3DVector( rc.right, rc.top , 0 );
pos[2] = K3DVector( rc.left , rc.bottom, 0 );
pos[3] = K3DVector( rc.right, rc.bottom, 0 );
pViewport->Get2DVto3DV( pos[0], opos[0] );
pViewport->Get2DVto3DV( pos[1], opos[1] );
pViewport->Get2DVto3DV( pos[2], opos[2] );
pViewport->Get2DVto3DV( pos[3], opos[3] );
m_pRectGrid->AddLine( opos[0], opos[1], KColor(255,0,0,255) );
m_pRectGrid->AddLine( opos[1], opos[3], KColor(255,0,0,255) );
m_pRectGrid->AddLine( opos[2], opos[3], KColor(255,0,0,255) );
m_pRectGrid->AddLine( opos[2], opos[0], KColor(255,0,0,255) );
pViewport->RegisterWire( m_pRectGrid );
}
}
}
void KUIControl::Process(DWORD dwTime)
{
KUIWnd::Process(dwTime);
_processAlphaShow(dwTime);
_processToolTip();
}
void KUIControl::_processAlphaShow( DWORD dwTime )
{
if( m_bShowAlpha && m_dwStyle & KSTYLE_ALPHA_SHOW )
{
DWORD dwTimeDiff = dwTime - m_dwAlphaTime;
float fAlphaValue = (float)dwTimeDiff / (float)500.f;
ChangeAlpha( fAlphaValue);
if(dwTimeDiff >= 500.f )
m_bShowAlpha = false;
}
}
void KUIControl::SetTooltip( LPCSTR lpszTip /*= NULL*/ )
{
//툴팁
if( lpszTip == NULL )
{
m_sTip.clear();
m_LazyTip = NULL;
SAFE_DELETE(m_pTipControl);
}
else
{
std::string sTip = lpszTip;
if( m_sTip != sTip )
{
/// 2010.11.03 툴팁 배경이 검은 색이기 때문에 툴팁이 검정색일 경우에는 흰색으로 바꿔준다 - prodongi
XStringUtil::Replace(sTip, "<#000000>", "<#ffffff>");
m_sTip = sTip;
m_LazyTip = NULL;
SAFE_DELETE(m_pTipControl);
}
}
// 메인 툴팁이 호출되면 서브는 초기화 한다.
ClearSubTooptip();
}
// sonador 1.2.5 Lazy Tooltip 구현
void KUIControl::SetLazyTooltip( KLazyTip* lazyTip ) // sonador #2.1.2.4.3 팻 조작 UI 연동
{
if( lazyTip == NULL )
{
m_sTip.clear();
m_LazyTip = NULL;
SAFE_DELETE(m_pTipControl);
}
else
{
if( m_LazyTip != lazyTip )
{
m_LazyTip = lazyTip;
m_sTip.clear();
SAFE_DELETE( m_pTipControl );
}
}
// 메인 툴팁이 호출되면 서브는 초기화 한다.
ClearSubTooptip();
}
void KUIControl::AddSubTooltip( LPCSTR lpszText )
{
if( lpszText == NULL )
{
SAFE_DELETE(m_pTipControl);
ClearSubTooptip();
}
else
{
std::string sSubTip = (NULL != lpszText) ? lpszText : "";
auto pos = std::find( m_SubTip.begin(), m_SubTip.end(), sSubTip );
if( pos == m_SubTip.end() )
{
SAFE_DELETE(m_pTipControl);
/// 2010.11.03 툴팁 배경이 검은 색이기 때문에 툴팁이 검정색일 경우에는 흰색으로 바꿔준다 - prodongi
XStringUtil::Replace(sSubTip, "<#000000>", "<#ffffff>");
m_SubTip.push_back( sSubTip );
SAFE_DELETE_VECTOR( m_SubTipContorl );
}
}
}
void KUIControl::AddLazySubTooltip( KLazyTip* pLazyTip )
{
if( pLazyTip == NULL )
{
SAFE_DELETE(m_pTipControl);
ClearSubTooptip();
}
else
{
auto pos = std::find( m_SubLazyTip.begin(), m_SubLazyTip.end(), pLazyTip );
if( pos == m_SubLazyTip.end() )
{
SAFE_DELETE(m_pTipControl);
m_SubLazyTip.push_back( pLazyTip );
SAFE_DELETE_VECTOR( m_SubTipContorl );
}
}
}
void KUIControl::ClearSubTooptip()
{
m_SubTip.clear();
m_SubLazyTip.clear();
SAFE_DELETE_VECTOR( m_SubTipContorl );
}
DWORD KUIControl::OnMouseMessage(DWORD dwMessage, int x, int y)
{
DWORD dwRet = KUIWnd::OnMouseMessage(dwMessage,x,y);
// sonador 1.2.5 Lazy Tooltip 구현
if(false == IsInRect(x, y )|| ( m_sTip.empty() && !m_LazyTip ) || dwMessage != KMOUSE_MOVE)
{
// Tooltip Cancel
if( m_dwToolTipStartTime != 0 )
_setToolTipOff();
return dwRet;
}
// Clip 안에 들어오지 않는다면 아예 받지를 말자.
if( false == m_rcClipArea.IsInRect( x, y ))
return dwRet;
// 예전과 다른 위치 (Tooltip Set)
if(x != m_nOldPosX || y != m_nOldPosY )
{
//_oprint( "# 툴팁 갱신 : %s\n", m_sID.c_str() );
DWORD dwTime = GetSafeTickCount();
m_dwToolTipPreStartTime = dwTime;
m_nOldPosX = x;
m_nOldPosY = y;
// 만약 Tool Tip을 찍는 도중이라면 time을 update
if(m_dwToolTipStartTime != 0)
{
// if( 0 == dwTime ) DebugBreak();
m_dwToolTipStartTime = dwTime;
}
else
{
// Position Offset
int TIP_OFFSET_X = 10;
int TIP_OFFSET_Y = 20;
// ToolTip 이 찍힐 자리 보정 (스크린을 넘어서면 이동)
m_nToolTipPosX = x;
m_nToolTipPosY = y;
if( !m_bToolTipLeftRender )
{
m_nToolTipPosX += TIP_OFFSET_X;
m_nToolTipPosY += TIP_OFFSET_Y;
}
if( NULL == m_pTipControl)
UpdateTip();
/// 2010.11.01 화면 경계 체크를 함수로 뺌 - prodongi
/*
if( m_pTipControl )
{
if( m_bToolTipLeftRender )
{
m_nToolTipPosX -= m_pTipControl->GetRect().GetWidth();
if( m_nToolTipPosX<0 ) m_nToolTipPosX=0;
}
int xDiff = KUIWndManager::GetResolution().width - (m_nToolTipPosX +
m_pTipControl->GetRect().GetWidth() );
int yDiff = KUIWndManager::GetResolution().height - (m_nToolTipPosY +
m_pTipControl->GetRect().GetHeight() );
if(xDiff < 0)
m_nToolTipPosX += xDiff;
if(yDiff < 0)
m_nToolTipPosY += yDiff;
}
*/
checkToolTipScreenBound();
}
}
return dwRet;
}
void* KUIControl::Perform( KID id, KArg& msg )
{
return NULL;
}
// Parent로 Message 를 Pumping 해준다.
void KUIControl::PumpUpMessage(LPCSTR lpszControlID, DWORD dwMessage, DWORD dwLParam, DWORD dwWParam)
{
if ( GetParent() )
GetParent()->PumpUpMessage( lpszControlID, dwMessage, dwLParam, dwWParam );
}
void KUIControl::OnChangeCaptionNotify()
{
// disable 이면 텍스트 회색으로..
if( IsDisable() )
{
size_t cpos = 0;
while( ( cpos = m_sCaption.find( "<#" ) ) != m_sCaption.npos )
{
m_sCaption.erase( cpos, 9 );
}
std::string strNewCaption = m_strDisableColor.c_str();
strNewCaption += m_sCaption;
m_sCaption = strNewCaption;
m_sOrgCaption = m_sCaption; /// 2011.02.16 m_sOrgCaption에 저장하지 않으면 Disable했다가 SetCaption했을 때, Caption이 적용되지 않는다 - prodongi
}
UpdateCaption();
KUIWnd::OnChangeCaptionNotify();
}
void KUIControl::OnChangeAniNameNotify()
{
UpdateAniName();
KUIWnd::OnChangeAniNameNotify();
}
void KUIControl::OnChagneBackNotify()
{
UpdateBack();
KUIWnd::OnChagneBackNotify();
}
void KUIControl::OnSizeChangeNofity(const KRect& rcNewRect)
{
KUIWnd::OnSizeChangeNofity( rcNewRect);
_initControl();
}
void KUIControl::OnParentSizeChangeNotify(const KRect& rcNewRect, int nXMove, int nYMove, int nResizeStyle)
{
std::list< KUIWnd* >::iterator it = m_listChild.begin();
for ( ; it != m_listChild.end() ; ++it )
{
KUIWnd * wnd = *it;
(*it)->OnParentSizeChangeNotify(rcNewRect, nXMove ,nYMove, nResizeStyle);
}
int nXMoveOffset = 0; int nYMoveOffset = 0;
if( nResizeStyle & KSTYLE_RESIZE_LEFT) // 왼쪽으로 이동
nXMoveOffset = (m_dwAnchor & KANCHOR_LEFT ) ? nXMove : 0;
else
nXMoveOffset = (m_dwAnchor & KANCHOR_RIGHT ) ? nXMove : 0;
if( nResizeStyle & KSTYLE_RESIZE_TOP)
nYMoveOffset = (m_dwAnchor & KANCHOR_TOP ) ? nYMove : 0;
else
nYMoveOffset = (m_dwAnchor & KANCHOR_BOTTOM ) ? nYMove : 0;
MovePosOffset( nXMoveOffset, nYMoveOffset);
}
void KUIControl::OnParentPosChangeNotify(int x, int y)
{
MovePos(m_rcRegion.left + x, m_rcRegion.top + y);
}
void KUIControl::OnPosChangeNofity(int x, int y)
{
KUIWnd::OnPosChangeNofity(x,y);
//if( ::_stricmp( GetID(), "worldmap_small" ) == 0 )
// int a = 0;
int i;
for(i = 0; i < m_nPieceCount; ++i)
m_pSpriteList[i].SetAddPosition(x,y);
if(m_pCaptionPhrase)
m_pCaptionPhrase->SetAddPosition(x,y);
for( i = 0; i < m_vtSprite.size(); ++i)
m_vtSprite.at(i)->SetAddPosition(x,y);
for( i = 0; i < m_vtTextPhrase.size(); ++i)
m_vtTextPhrase.at(i)->SetAddPosition(x,y);
}
void KUIControl::OnClipChangeNotify(const KRect& rcClipRect)
{
KUIWnd::OnClipChangeNotify( rcClipRect );
int i;
for(i = 0; i < m_nPieceCount; ++i)
m_pSpriteList[i].SetClipRect( &m_rcClipArea ) ;
if(m_pCaptionPhrase)
m_pCaptionPhrase->SetClipRect( m_rcClipArea );
for( i = 0; i < m_vtSprite.size(); ++i)
m_vtSprite.at(i)->SetClipRect( &m_rcClipArea);
for( i = 0; i < m_vtTextPhrase.size(); ++i)
m_vtTextPhrase.at(i)->SetClipRect( m_rcClipArea );
}
void KUIControl::OnParentClipChangeNotify(const KRect& rcClipRect)
{
OnClipChangeNotify( rcClipRect );
}
void KUIControl::OnAlphaChangeNotify(float fAlpha)
{
KUIWnd::OnAlphaChangeNotify( fAlpha);
int i;
for(i = 0; i < m_nPieceCount; ++i)
m_pSpriteList[i].SetVisibility( m_fAlpha);
if(m_pCaptionPhrase)
m_pCaptionPhrase->SetVisibility( m_fAlpha);
for( i = 0; i < m_vtSprite.size(); ++i)
m_vtSprite.at(i)->SetVisibility( m_fAlpha);
for( i = 0; i < m_vtTextPhrase.size(); ++i)
m_vtTextPhrase.at(i)->SetVisibility(m_fAlpha);
}
void KUIControl::OnParentAlphaChangeNotify(float fAlphaDiff)
{
ChangeAlpha( m_fAlpha + fAlphaDiff);
}
void KUIControl::OnAlphaChangeNotNotify(float alpha)
{
int i;
for(i = 0; i < m_nPieceCount; ++i)
m_pSpriteList[i].SetVisibility( alpha);
if(m_pCaptionPhrase)
m_pCaptionPhrase->SetVisibility( alpha);
for( i = 0; i < m_vtSprite.size(); ++i)
m_vtSprite.at(i)->SetVisibility( alpha);
for( i = 0; i < m_vtTextPhrase.size(); ++i)
m_vtTextPhrase.at(i)->SetVisibility(alpha);
}
KUIDragAndDropObject* KUIControl::GetDragObject()
{
if( NULL != m_pDragObject)
m_pDragObject->Set( m_pParent, this);
return m_pDragObject;
}
void KUIControl::UpdateBack()
{
if( m_bUsePos && m_bUsePosEnable && !m_bUseCustomSize) // #2.1.2.11.1
m_rcRegion.right = -1;
_reArrangeRect( m_bUseHorizonPiece );
m_rcCaptionArea = m_rcRegion;
}
void KUIControl::UpdateAniName()
{
// { 임시로 이렇게 구현 by Testors
UpdateBack();
// }
}
// 2010.09.03 - prodongi // SINGLE_LINE 처리 수정:2010.09.27 - bintitle.
void KUIControl::UpdateCaption(DWORD maxWidth)
{
// Caption 설정
if((!m_sCaption.empty() || GetClassName() == "edit") && m_rcCaptionArea.GetWidth() > 1 && m_rcCaptionArea.GetHeight() > 1)
{
/// 2011.02.23 m_pCaptionPhrase에서 스프라이트 스크롤 정보를 갖고와서 저장해 놓는다, 캡션이 바껴도 이 설정은 유지 되야 되기 때문에 - prodongi
KTextPhrase::sSpriteScrollInfo spriteScrollInfo;
if (m_pCaptionPhrase)
m_pCaptionPhrase->getSpriteScrollInfo(spriteScrollInfo);
SAFE_DELETE(m_pCaptionPhrase);
m_pCaptionPhrase = new KTextPhrase(m_rcCaptionArea.right - m_rcCaptionArea.left, m_rcCaptionArea.bottom - m_rcCaptionArea.top);
m_pCaptionPhrase->SetAlign( m_dwCaptionAlign );
m_pCaptionPhrase->SetPosition(m_rcCaptionArea.left, m_rcCaptionArea.top, m_fZPos);
m_pCaptionPhrase->SetVisibility( m_fAlpha );
/// 2011.02.23 복구 - prodongi
m_pCaptionPhrase->setSpriteScrollInfo(spriteScrollInfo);
m_pCaptionPhrase->SetCaptionRandomColor( m_bCaptionRandomColor );
if( m_dwFlag & KFLAG_SINGLE_LINE)
{
/// 2010.11.04 - prodongi
DWORD realCaptionWidth = KTextPhrase::GetOneLineStringSize(m_sCaption.c_str(), NULL, NULL);
if (realCaptionWidth > m_rcCaptionArea.GetWidth())
{
DWORD dwWidht = 0;
std::string sFontName;
std::string strSingleLine; // <br>태그가 존재할 경우 첫<br> 태그 이전( 첫번째줄 ) 텍스트.
std::string strPureCaption; // <> 태그를 제거한 순수한 텍스트.
// <br> 태그가 존재하면 2줄 이상인 것이다. 첫번째 <br>이전의 텍스트에 대한 SINGLE_LINE 처리를 한다.
bool bBr = true;
std::string::size_type nfos = m_sCaption.find( "<br>" );
if( nfos == std::string::npos )
{
nfos = m_sCaption.find( "<BR>" );
if( nfos == std::string::npos )
bBr = false;
}
bool bFontBold;
CStringUtil::GetTextFontName(m_sCaption, sFontName);
CStringUtil::GetTextFontBold(m_sCaption, bFontBold);
std::wstring wStrPure;
if( bBr )
{
strSingleLine = m_sCaption.substr( 0, nfos );
wStrPure = nsl::uni::conv( strSingleLine.c_str() );
}
else
{
strSingleLine = m_sCaption;
wStrPure = nsl::uni::conv( m_sCaption.c_str() );
}
// 태그를 제거할때 <$> 태그를 보존하기 위함.
std::wstring wTemp( wStrPure );
std::wstring wTagKey( L"***!!!@_%_&_#_^_@" );
std::wstring wTagString;
std::wstring::size_type sTagStart = wStrPure.find( L"<$" );
if( sTagStart != std::wstring::npos )
{
wTemp = wStrPure.substr( sTagStart, wStrPure.size() );
std::wstring::size_type sTagEnd = wTemp.find_first_of( L">" );
if( sTagEnd != std::wstring::npos )
{
wTagString = wStrPure.substr( sTagStart, sTagEnd + 1 );
wStrPure.replace( sTagStart, sTagEnd + 1, wTagKey );
}
}
// 텍스트 꾸미기태그분리( 텍스트 내부의 태그는 제외 ).
std::string strDeco( "" );
std::wstring::size_type sEnd( 0 );
// ★ 태그를 제외한 텍스트만을 걸러낸다.
if( !wStrPure.empty() )
{
while( 1 )
{
std::wstring::size_type sStart = wStrPure.find_first_of( L"<" );
if( sStart != std::wstring::npos )
{
// "<" 는 존재하는데 ">" 는 없다는 것도 태그가 없는 것.
sEnd = wStrPure.find_first_of( L">" );
if( sEnd == std::wstring::npos || sStart > sEnd )
break;
else
{
strDeco += nsl::uni::conv( wStrPure.substr( sStart, sEnd - sStart + 1 ) );
wStrPure = wStrPure.replace( sStart, sEnd - sStart + 1, L"" );
}
}
// 텍스트에 "<" 이 문자가 없다는 것은 태그가 없다는 것. 모두 걸러내었다! 종료.
else
break;
}
}
// 태그를 걸러낸 텍스트에 보존해논 <$> 적용.
if( !wTagString.empty() )
{
sTagStart = wStrPure.find( wTagKey );
if( sTagStart != std::wstring::npos )
{
wStrPure.replace( sTagStart, wTagKey.size(), wTagString );
}
}
strPureCaption = nsl::uni::conv( wStrPure.c_str() ); // 태그를 모두 걸러낸 텍스트.
DWORD dwHeight = 0;
KTextRender::GetStringSize(sFontName.c_str(), this->GetFontSize(), bFontBold, strPureCaption.c_str(), strPureCaption.size(), &dwWidht, &dwHeight);
if( bBr || dwWidht > m_rcCaptionArea.GetWidth() )
{
//this->SetTooltip( m_sCaption.c_str() );
DWORD dwByte = GetOneLineStringByte( strSingleLine.c_str(), m_rcCaptionArea.GetWidth()-4 );
/// 2010.10.27 GetOneLineStringByte 할 때 넓이를 -4 했기 때문에 여기서는 안해도 됩니다. - prodongi
//if( dwByte > 8 )
// dwByte -= 8;
std::string newCaption;
static StringOmitter omitter;
/*if( omitter( newCaption, strPureCaption.c_str(), dwByte, "..." ) == false && bBr )
{
newCaption += "...";
this->SetTooltip( m_sCaption.c_str() );
}*/
if( omitter( newCaption, strPureCaption.c_str(), dwByte, "..." ) )
this->SetTooltip( m_sCaption.c_str() );
else if( bBr )
{
this->SetTooltip( m_sCaption.c_str() );
newCaption += "...";
}
m_pCaptionPhrase->AddString( ( strDeco + newCaption ).c_str(), m_fZPos, true, false, m_bUseEmoticonFilter );
}
else
{
this->SetTooltip( NULL );
m_pCaptionPhrase->AddString(m_sCaption.c_str(), m_fZPos, true, false, m_bUseEmoticonFilter);
}
//UpdateTip();
}
else
{
m_pCaptionPhrase->AddString(m_sCaption.c_str(), m_fZPos, true, false, m_bUseEmoticonFilter, false, maxWidth);
SetTooltip(NULL);
}
}
else
{
// 2010.09.03 - prodongi
m_pCaptionPhrase->AddString(m_sCaption.c_str(), m_fZPos, true, false, m_bUseEmoticonFilter, false, maxWidth);
}
/// 2011.02.23 - prodongi
m_pCaptionPhrase->updateSpriteScrollInfo();
m_pCaptionPhrase->SetClipRect(m_rcClipArea);
// MIMI 2005/08/17 이모티콘이 추가된 텍스트는 텍스쳐 크기가 틀려지므로 ?팁에 적용하기 위해 기억한다.
if( GetClassName() == "tooltip" )
{
m_nToolTipTextWidth = m_pCaptionPhrase->GetTextureSize().cx;
m_nToolTipTextWidth += s_nBlankWidth;
m_nToolTipTextHeight = m_pCaptionPhrase->GetTextureSize().cy;
}
}
else
{
//_oprint( "DELETE CAPTION PHARSE : %s(%s)\n", m_sID.c_str(), m_sCaption.c_str() );
SAFE_DELETE(m_pCaptionPhrase);
}
}
void KUIControl::UpdateTip()
{
if( false == m_sTip.empty() )
{
SAFE_DELETE(m_pTipControl);
KUIWND_CREATE_ARG arg;
arg.lpszClassName = "tooltip";
arg.lpszID = "tool_tip";
arg.lpszCaption = m_sTip.c_str();
arg.lpszAniName = m_strTooltipAniName;
arg.lpszSprName = "ui_frame.spr";
arg.rcRect = KRect( 0, 0, KUITipControl::m_dwTipWindowWidth, KUITipControl::m_dwTipWindowHeight );
arg.pParent = NULL;
m_pTipControl = reinterpret_cast<KUITipControl*>( m_pManager->CreateControl( arg) );
if( m_pTipControl )
m_pTipControl->UpdateTooltipRegion( m_pTipControl->m_nToolTipTextWidth, m_pTipControl->m_nToolTipTextHeight );
}
// sonador 1.2.5 Lazy Tooltip 구현
else if( m_LazyTip )
{
SAFE_DELETE(m_pTipControl);
KUIWND_CREATE_ARG arg;
arg.lpszClassName = "tooltip";
arg.lpszID = "tool_tip";
arg.lpszCaption = m_LazyTip->getTip();
arg.lpszAniName = m_strTooltipAniName;
arg.lpszSprName = "ui_frame.spr";
arg.rcRect = KRect( 0, 0, KUITipControl::m_dwTipWindowWidth, KUITipControl::m_dwTipWindowHeight );
arg.pParent = NULL;
m_pTipControl = reinterpret_cast<KUITipControl*>( m_pManager->CreateControl( arg) );
if( m_pTipControl )
m_pTipControl->UpdateTooltipRegion( m_pTipControl->m_nToolTipTextWidth, m_pTipControl->m_nToolTipTextHeight );
}
else
{
SAFE_DELETE(m_pTipControl);
SAFE_DELETE_VECTOR( m_SubTipContorl );
}
// 메인 툴팁이 있다면 서브 튤팁도 만든다.
if( m_pTipControl != NULL )
{
SAFE_DELETE_VECTOR( m_SubTipContorl );
if( m_SubTip.empty() == false )
{
auto pos = m_SubTip.begin();
auto end = m_SubTip.end();
for( ; pos != end; ++pos )
{
KUIWND_CREATE_ARG arg;
arg.lpszClassName = "tooltip";
arg.lpszID = "tool_tip";
arg.lpszCaption = (*pos).c_str();
arg.lpszAniName = m_strTooltipAniName;
arg.lpszSprName = "ui_frame.spr";
arg.rcRect = KRect( 0, 0, KUITipControl::m_dwTipWindowWidth, KUITipControl::m_dwTipWindowHeight );
arg.pParent = NULL;
KUITipControl* pSubTipContorl = reinterpret_cast<KUITipControl*>( m_pManager->CreateControl( arg) );
if( pSubTipContorl )
{
pSubTipContorl->UpdateTooltipRegion( pSubTipContorl->m_nToolTipTextWidth, pSubTipContorl->m_nToolTipTextHeight );
m_SubTipContorl.push_back( pSubTipContorl );
}
}
}
if( m_SubLazyTip.empty() == false )
{
auto pos = m_SubLazyTip.begin();
auto end = m_SubLazyTip.end();
for( ; pos != end; ++pos )
{
KUIWND_CREATE_ARG arg;
arg.lpszClassName = "tooltip";
arg.lpszID = "tool_tip";
arg.lpszCaption = (*pos)->getTip();
arg.lpszAniName = m_strTooltipAniName;
arg.lpszSprName = "ui_frame.spr";
arg.rcRect = KRect( 0, 0, KUITipControl::m_dwTipWindowWidth, KUITipControl::m_dwTipWindowHeight );
arg.pParent = NULL;
KUITipControl* pSubTipContorl = reinterpret_cast<KUITipControl*>( m_pManager->CreateControl( arg) );
if( pSubTipContorl )
{
pSubTipContorl->UpdateTooltipRegion( pSubTipContorl->m_nToolTipTextWidth, pSubTipContorl->m_nToolTipTextHeight );
m_SubTipContorl.push_back( pSubTipContorl );
}
}
}
}
// 2010.05.06 - prodongi
updateToolTipEmoticonSize();
}
void KUIControl::SetRotate(float fRadian)
{
K3DMatrix matRot;
K3DMatrixRotationZ( matRot, fRadian);
for(int i = 0; i <m_nPieceCount; ++i)
{
matRot.SetPosVector( m_pSpriteList[i].GetPosition());
m_pSpriteList[i].SetTransform(matRot );
}
for(int i = 0; i < m_vtSprite.size(); ++i)
{
matRot.SetPosVector( m_vtSprite.at(i)->GetPosition());
m_vtSprite.at(i)->SetTransform(matRot);
}
}
int KUIControl::GetOneLineStringByte(LPCSTR lpszText,DWORD dwWidth)
{
return KTextPhrase::GetOneLineStringByte( lpszText, dwWidth );
}
void KUIControl::_destroyControl()
{
if( s_pToolTipOnControl == this ) SetNULLToolTipOnControl(); // [sonador] fix acess violation
SAFE_DELETE( m_pCaptionPhrase );
SAFE_DELETE_ARRAY( m_pSpriteList );
SAFE_DELETE(m_pTipControl);
SAFE_DELETE_VECTOR( m_SubTipContorl );
SAFE_DELETE(m_pDragObject );
}
void KUIControl::_initControl()
{
// Back Ground Set
UpdateBack();
// Caption Set
UpdateCaption();
}
void KUIControl::RenderToolTip(KViewportObject * pViewport, bool isFront)
{
_renderToolTip( pViewport, isFront );
}
void KUIControl::_renderChild(KViewportObject* pViewport, bool isFront)
{
std::list< KUIWnd* >::iterator it = m_listChild.begin();
for ( ; it != m_listChild.end() ; ++it )
{
(*it)->Render(pViewport, isFront);
}
}
void KUIControl::_renderBack(KViewportObject * pViewport, bool isFront)
{
for(int i = 0; i < m_nPieceCount; ++i)
{
pViewport->Register(&m_pSpriteList[i], isFront);
}
std::vector<KSpritePrimitive*>::iterator it = m_vtSprite.begin();
std::vector<KSpritePrimitive*>::iterator end = m_vtSprite.end();
for(; it != end; ++it)
{
pViewport->Register( *it , isFront);
}
}
void KUIControl::_renderCaption(KViewportObject * pViewport, bool isFront)
{
if(m_pCaptionPhrase)
{
m_pCaptionPhrase->Render(pViewport,isFront );
}
std::vector<KTextPhrase*>::iterator it = m_vtTextPhrase.begin();
std::vector<KTextPhrase*>::iterator end = m_vtTextPhrase.end();
for(; it != end; ++it)
{
(*it)->Render(pViewport,isFront );
}
}
void KUIControl::_renderToolTip(KViewportObject * pViewport, bool isFront)
{
// sonador 1.2.5 Lazy Tooltip 구현
if( m_sTip.empty() && !m_LazyTip )
return;
if(m_dwToolTipStartTime != 0)
{
// Tip Control을 Render
if(NULL == m_pTipControl)
{
// sonador 1.2.5 Lazy Tooltip 구현
if( m_sTip.empty() == false || m_LazyTip )
{
UpdateTip();
checkToolTipScreenBound(); /// 2010.11.01 기존에는 마우스를 움직여야만 체크가 되어 있어서, 체크가 안되는 경우가 발생 했음- prodongi
}
else
return;
}
m_pTipControl->MovePos(m_nToolTipPosX,m_nToolTipPosY);
m_pTipControl->Render(pViewport, isFront);
if( m_SubTipContorl.empty() == false )
{
int nSubToolTipPosX = m_nToolTipPosX;
const int nLeftSpace = 34; // 왼쪽을 출력할때 마우스 커서로 인해 34 아이콘 하나 크기만큼 간격을 띄운다.
int nRightWidth = KUIWndManager::GetResolution().width - nSubToolTipPosX - m_pTipControl->GetRect().GetWidth();
// 기본 툴팁 좌표가 화면의 오른쪽에 있다면 왼쪽에 표시한다.
if( (nSubToolTipPosX - nLeftSpace) > nRightWidth )
{
int nSubToolTipWidth = nLeftSpace;
auto pos = m_SubTipContorl.begin();
auto end = m_SubTipContorl.end();
for( ; pos != end; ++pos )
{
KUITipControl* pSubTip = (*pos);
nSubToolTipWidth += pSubTip->GetRect().GetWidth();
}
nSubToolTipPosX = m_nToolTipPosX - nSubToolTipWidth;
}
else
{
nSubToolTipPosX += m_pTipControl->GetRect().GetWidth();
}
auto pos = m_SubTipContorl.begin();
auto end = m_SubTipContorl.end();
for( ; pos != end; ++pos )
{
KUITipControl* pSubTip = (*pos);
int nSubToolTipPosY = m_nToolTipPosY;
int yDiff = KUIWndManager::GetResolution().height - (nSubToolTipPosY + pSubTip->GetRect().GetHeight() );
if(yDiff < 0)
nSubToolTipPosY += yDiff;
// Tip Control을 Render
pSubTip->MovePos(nSubToolTipPosX, nSubToolTipPosY);
pSubTip->Render(pViewport, isFront);
nSubToolTipPosX += pSubTip->GetRect().GetWidth();
}
}
}
}
void KUIControl::_processToolTip()
{
// { [sonador] performance tunning
if( m_dwToolTipPreStartTime == 0 && m_dwToolTipStartTime == 0 ) return;
// }
DWORD dwTime = GetSafeTickCount();
if(m_dwToolTipPreStartTime != 0 )
{
// Tool Tip이 찍히는 도중이 아니면
if(m_dwToolTipStartTime == 0)
{
if( KUITipControl::GetToolTipOnOff() == false)
{
// if( 0 == dwTime ) DebugBreak();
m_dwToolTipStartTime = dwTime;
KUITipControl::SetToolTipOnOff( true );
OnToolTipOnControl( this );
//부모에게 툴팁 설정 됨을 알림.
if( m_pParent )
m_pParent->OnToolTipWnd( this );
}
}
}
if(m_dwToolTipStartTime != 0)
{
// Drag 하는 경우에는 Tooltip 취소
if(dwTime - m_dwToolTipStartTime >= KUITipControl::GetContinueTime() || m_pManager->GetDragObject() != NULL )
_setToolTipOff();
// 2010.07.16 메세지박스가 출력되고 있을때 툴팁이 안나오도록 한다- prodongi
else if (m_pManager->IsOpenModalWnd())
_setToolTipOff();
}
}
void KUIControl::_reArrangeRect(bool bHorizonPiece)
{
// AniName 이 없으면 만든 Sprite 삭제
if(m_sAniName.empty() )
{
SAFE_DELETE_ARRAY(m_pSpriteList);
m_nPieceCount = 0;
return;
}
// Pos로 되어 있어서 Sprite로부터 Rect Size를 얻어오는 경우
if(m_bUsePosEnable && ( m_rcRegion.right == -1 || m_bUseCustomSize ) ) // #2.1.2.11.1
{
KResSprite * pFrame = NULL;
if( _getSpriteSet() )
pFrame = _getSpriteSet()->GetSpriteRes(m_sAniName.c_str(), m_nFrameIndex);
if(pFrame)
{
m_nPieceCount = 1;
if( !m_bUseCustomSize )
{
m_rcRegion.right = int(m_rcRegion.left + pFrame->GetSizeX());
m_rcRegion.bottom = int(m_rcRegion.top + pFrame->GetSizeY());
}
}
m_rcPieceArea[0] = m_rcRegion;
_makeSpriteForArrangedRect();
return;
}
if( _getSpriteSet() )
{
m_nPieceCount = _getSpriteSet()->GetSpriteResAniCount( m_sAniName.c_str() );
if(m_nPieceCount < 1)
return;
int nLeft = m_rcRegion.left;
int nTop = m_rcRegion.top;
switch(m_nPieceCount)
{
case 1:
{
m_rcPieceArea[0] = m_rcRegion;
}
break;
case 3:
{
// 가로로 세조각
KResSprite* pSpriteFrame_0( _getSpriteSet()->GetSpriteRes( m_sAniName.c_str(), 0 ) );
KResSprite* pSpriteFrame_2( _getSpriteSet()->GetSpriteRes( m_sAniName.c_str(), 2 ) );
if(bHorizonPiece)
{
int nCalcMidSizeX = m_rcRegion.GetWidth() - pSpriteFrame_0->GetSizeX() - pSpriteFrame_2->GetSizeX();
int nCalcMidSizeY = pSpriteFrame_0->GetSizeY();
for(int i(0); i < 3; ++i)
{
int nFrameSizeX( _getSpriteSet()->GetSpriteRes( m_sAniName.c_str(), i )->GetSizeX() );
int nFrameSizeY( _getSpriteSet()->GetSpriteRes( m_sAniName.c_str(), i )->GetSizeY() );
m_rcPieceArea[i].left = nLeft;
m_rcPieceArea[i].top = nTop;
m_rcPieceArea[i].right = nLeft + nFrameSizeX;
m_rcPieceArea[i].bottom = nTop + nFrameSizeY;
if(i == 1)
{
m_rcPieceArea[i].right = nLeft + nCalcMidSizeX;
nLeft += nCalcMidSizeX;
}
else
nLeft += nFrameSizeX;
}
}
// 세로로 세조각
else
{
int nCalcMidSizeX = pSpriteFrame_0->GetSizeX();
int nCalcMidSizeY = m_rcRegion.GetWidth() - pSpriteFrame_0->GetSizeY() - pSpriteFrame_2->GetSizeY();
for(int i(0); i < 3; ++i)
{
int nFrameSizeX( _getSpriteSet()->GetSpriteRes( m_sAniName.c_str(), i )->GetSizeX() );
int nFrameSizeY( _getSpriteSet()->GetSpriteRes( m_sAniName.c_str(), i )->GetSizeY() );
m_rcPieceArea[i].left = nLeft;
m_rcPieceArea[i].top = nTop;
m_rcPieceArea[i].right = nLeft + nFrameSizeX;
m_rcPieceArea[i].bottom = nTop + nFrameSizeY;
if(i == 1)
{
m_rcPieceArea[i].bottom = nTop + nCalcMidSizeY;
nTop += nCalcMidSizeY;
}
else
nTop += nFrameSizeY;
}
}
}
break;
case 9: // 9조각으로 찢어질 경우
{
KResSprite* pSpriteFrame_0( _getSpriteSet()->GetSpriteRes( m_sAniName.c_str(), 0 ) );
KResSprite* pSpriteFrame_2( _getSpriteSet()->GetSpriteRes( m_sAniName.c_str(), 2 ) );
KResSprite* pSpriteFrame_6( _getSpriteSet()->GetSpriteRes( m_sAniName.c_str(), 6 ) );
int nCount = 0;
int nCalcMidSizeX = m_rcRegion.GetWidth() - pSpriteFrame_0->GetSizeX() - pSpriteFrame_2->GetSizeX();
int nCalcMidSizeY = m_rcRegion.GetHeight() - pSpriteFrame_0->GetSizeY() - pSpriteFrame_6->GetSizeY();
// 찍는 부분 설정
for(int i = 0; i < 3; ++ i)
{
nLeft = m_rcRegion.left;
for(int j = 0; j < 3; ++j)
{
int nFrameSizeX( _getSpriteSet()->GetSpriteRes( m_sAniName.c_str(), nCount )->GetSizeX() );
int nFrameSizeY( _getSpriteSet()->GetSpriteRes( m_sAniName.c_str(), nCount )->GetSizeY() );
m_rcPieceArea[nCount].left = nLeft;
m_rcPieceArea[nCount].top = nTop;
m_rcPieceArea[nCount].right = m_rcPieceArea[nCount].left + nFrameSizeX;
m_rcPieceArea[nCount].bottom = m_rcPieceArea[nCount].top + nFrameSizeY;
// 중간 열
if( j == 1 )
{
m_rcPieceArea[nCount].right = nLeft + nCalcMidSizeX;
nLeft += nCalcMidSizeX;
}
else
{
nLeft += nFrameSizeX;
}
// 중간 행
if(i == 1)
{
m_rcPieceArea[nCount].bottom = nTop + nCalcMidSizeY ;
}
nCount++;
}
// Mid
if( i == 0 )
nTop += pSpriteFrame_0->GetSizeY();
if( i == 1 )
nTop += nCalcMidSizeY;
if( i == 2 )
nTop += pSpriteFrame_6->GetSizeY();
}
}
break;
case 10:
break;
default:
{
_oprint( "Error!!! : Frame의 조각이 맞지 않습니다 - %s : %d\n", m_sAniName.c_str(), m_nPieceCount );
break;
}
}
}
_makeSpriteForArrangedRect();
}
void KUIControl::_makeSpriteForArrangedRect()
{
SAFE_DELETE_ARRAY(m_pSpriteList);
if(0 == m_nPieceCount)
return;
m_pSpriteList = new KSpritePrimitive[m_nPieceCount];
// Position을 사용할 경우 FrameIndex 에 지정된 Frame을 가져와서 만든다.
if(true == m_bUsePos)
{
KResSprite * pFrame = NULL;
if(_getSpriteSet())
pFrame = _getSpriteSet()->GetSpriteRes( m_sAniName.c_str(), m_nFrameIndex );
if(NULL == pFrame)
return;
m_pSpriteList[0].SetRes(pFrame);
m_pSpriteList[0].SetTargetSize( (float)m_rcPieceArea[0].GetWidth(),
(float)m_rcPieceArea[0].GetHeight() );
m_pSpriteList[0].SetPosition( K3DVector((K3DVALUE)m_rcPieceArea[0].left ,
(K3DVALUE)m_rcPieceArea[0].top, m_fZPos ) );
return;
}
// 그게 아닐경우 조합
for(int i = 0; i <m_nPieceCount; ++i)
{
KResSprite * pFrame = NULL;
if(_getSpriteSet())
pFrame = _getSpriteSet()->GetSpriteRes( m_sAniName.c_str(), i );
if(NULL == pFrame)
continue;
m_pSpriteList[i].SetRes(pFrame);
m_pSpriteList[i].SetTargetSize( (float)m_rcPieceArea[i].GetWidth(), (float)m_rcPieceArea[i].GetHeight() );
m_pSpriteList[i].SetPosition( K3DVector((K3DVALUE)m_rcPieceArea[i].left ,(K3DVALUE)m_rcPieceArea[i].top, m_fZPos ) );
}
}
void KUIControl::_setToolTipOff()
{
KUITipControl::SetToolTipOnOff( false );
m_dwToolTipStartTime = 0;
m_dwToolTipPreStartTime = 0;
#ifdef _KUI_INVALIDATION
m_pParent->OnToolTipWnd( NULL );
#endif
}
void KUIControl::UpdateUV( KRect rt )
{
SAFE_DELETE_ARRAY(m_pSpriteList);
if( m_nPieceCount == 0 ) return;
m_pSpriteList = new KSpritePrimitive[m_nPieceCount];
for( int i = 0; i < m_nPieceCount; i++ )
{
KResSprite* pFrame = NULL;
if( _getSpriteSet() ) pFrame = _getSpriteSet()->GetSpriteRes( m_sAniName.c_str(), i );
if( pFrame == NULL ) continue;
if( pFrame->GetTexture() == NULL ) continue;
m_pSpriteList[i].SetRes( pFrame );
// uv 좌표 구한다
float fX = static_cast<float>(rt.left+pFrame->GetRectSrc().left) / static_cast<float>(pFrame->GetTexture()->GetSize().width);
float fY = static_cast<float>(rt.top+pFrame->GetRectSrc().top) / static_cast<float>(pFrame->GetTexture()->GetSize().height);
float fR = static_cast<float>(rt.right+pFrame->GetRectSrc().left) / static_cast<float>(pFrame->GetTexture()->GetSize().width);
float fB = static_cast<float>(rt.bottom+pFrame->GetRectSrc().top) / static_cast<float>(pFrame->GetTexture()->GetSize().height);
m_pSpriteList[i].SetSourceUVRect( fX, fY, fR, fB );
m_pSpriteList[i].SetTargetSize( static_cast<float>(m_rcPieceArea[i].GetWidth()), static_cast<float>(m_rcPieceArea[i].GetHeight()) );
m_pSpriteList[i].SetPosition( K3DVector( (K3DVALUE)GetRect().left ,(K3DVALUE)GetRect().top, m_fZPos ) );
m_pSpriteList[i].SetVisibility( m_fAlpha );
}
}
//void KUIControl::UpdateUV( KRect rt, int nTextureCount, int nMapPosX, int nMapPosY )
//{
// SAFE_DELETE_ARRAY(m_pSpriteList);
// if( m_nPieceCount == 0 ) return;
//
// int nPieceCount = nTextureCount; nPieceCount++;
//
// if( nPieceCount%2 != 0 ) nPieceCount = 1;
//
// m_nPieceCount = nPieceCount;
//
// m_pSpriteList = new KSpritePrimitive[nPieceCount];
// KResSprite* pFrame = NULL;
// switch(nPieceCount)
// {
// case 1:
// {
// if( _getSpriteSet() ) pFrame = _getSpriteSet()->GetSpriteRes( m_sAniName.c_str(), 0 );
// if( pFrame == NULL ) return;
//
// m_pSpriteList[0].SetRes( pFrame );
//
// // uv 좌표 구한다
// float fX = static_cast<float>(rt.left+pFrame->GetRectSrc().left) / static_cast<float>(pFrame->GetTexture()->GetSize().width);
// float fY = static_cast<float>(rt.top+pFrame->GetRectSrc().top) / static_cast<float>(pFrame->GetTexture()->GetSize().height);
// float fR = static_cast<float>(rt.right+pFrame->GetRectSrc().left) / static_cast<float>(pFrame->GetTexture()->GetSize().width);
// float fB = static_cast<float>(rt.bottom+pFrame->GetRectSrc().top) / static_cast<float>(pFrame->GetTexture()->GetSize().height);
//
// m_pSpriteList[0].SetSourceUVRect( fX, fY, fR, fB );
// m_pSpriteList[0].SetTargetSize( static_cast<float>(m_rcPieceArea[0].GetWidth()), static_cast<float>(m_rcPieceArea[0].GetHeight()) );
// m_pSpriteList[0].SetPosition( K3DVector( (K3DVALUE)GetRect().left ,(K3DVALUE)GetRect().top, m_fZPos ) );
// }
// break;
// case 2:
// {
// std::string strAniName[2];
// strAniName[0] = m_sAniName;
// KRect rtTexture[2]; rtTexture[0] = rt; rtTexture[1] = rt;
// int nOffsetX[2], nOffsetY[2];
// for( int i = 0; i < nPieceCount; i++ )
// {
// nOffsetX[i] = GetRect().left;
// nOffsetY[i] = GetRect().top;
// }
//
// int nMapIndex = 0;
// if( ::_stricmp( GetID(), "worldmap_small" ) == 0 ) nMapIndex = WORLDMAP_INDEX;
// else nMapIndex = MINIMAP_INDEX;
//
// // ↑ or ↓
// if( rt.top < 0 || rt.bottom > GetTextureSizeY() )
// {
// if( rt.top < 0 )
// {
// rtTexture[0].top = 0;
//
// rtTexture[1].top = GetTextureSizeY() + rt.top;
// rtTexture[1].bottom = GetTextureSizeY();
//
// strAniName[1] = c_szMapAniName[c_nMapIndex[nMapPosY+1][nMapPosX]][nMapIndex];
// nOffsetY[0] = GetRect().top + rtTexture[1].GetHeight();
// }
// else if( rt.bottom > GetTextureSizeY() )
// {
// rtTexture[0].bottom = GetTextureSizeY();
//
// rtTexture[1].top = 0;
// rtTexture[1].bottom = rt.bottom - GetTextureSizeY();
//
// strAniName[1] = c_szMapAniName[c_nMapIndex[nMapPosY-1][nMapPosX]][nMapIndex];
// nOffsetY[1] = GetRect().top + rtTexture[0].GetHeight();
// }
// }
// // ← or →
// else if( rt.left < 0 || rt.right > GetTextureSizeX() )
// {
// if( rt.left < 0 )
// {
// rtTexture[0].left = 0;
//
// rtTexture[1].left = GetTextureSizeX() + rt.left;
// rtTexture[1].right = GetTextureSizeX();
//
// strAniName[1] = c_szMapAniName[c_nMapIndex[nMapPosY][nMapPosX-1]][nMapIndex];
// nOffsetX[0] = GetRect().left + rtTexture[1].GetWidth();
// }
// else if( rt.right > GetTextureSizeX() )
// {
// rtTexture[0].right = GetTextureSizeX();
//
// rtTexture[1].left = 0;
// rtTexture[1].right = rt.right - GetTextureSizeX();
//
// strAniName[1] = c_szMapAniName[c_nMapIndex[nMapPosY][nMapPosX+1]][nMapIndex];
// nOffsetX[1] = GetRect().left + rtTexture[0].GetWidth();
// }
// }
//
// for( int i = 0; i < nPieceCount; i++ )
// {
// if( _getSpriteSet() ) pFrame = _getSpriteSet()->GetSpriteRes( strAniName[i].c_str(), 0 );
// if( pFrame == NULL ) continue;
//
// m_pSpriteList[i].SetRes( pFrame );
//
// // uv 좌표 구한다
// float fX = static_cast<float>(rtTexture[i].left+pFrame->GetRectSrc().left) / static_cast<float>(pFrame->GetTexture()->GetSize().width);
// float fY = static_cast<float>(rtTexture[i].top+pFrame->GetRectSrc().top) / static_cast<float>(pFrame->GetTexture()->GetSize().height);
// float fR = static_cast<float>(rtTexture[i].right+pFrame->GetRectSrc().left) / static_cast<float>(pFrame->GetTexture()->GetSize().width);
// float fB = static_cast<float>(rtTexture[i].bottom+pFrame->GetRectSrc().top) / static_cast<float>(pFrame->GetTexture()->GetSize().height);
//
// m_pSpriteList[i].SetSourceUVRect( fX, fY, fR, fB );
// m_pSpriteList[i].SetTargetSize( static_cast<float>(rtTexture[i].GetWidth()), static_cast<float>(rtTexture[i].GetHeight()) );
// m_pSpriteList[i].SetPosition( K3DVector( (K3DVALUE)nOffsetX[i] ,(K3DVALUE)nOffsetY[i], m_fZPos ) );
// }
// }
// break;
// case 4:
// {
// if( _getSpriteSet() ) pFrame = _getSpriteSet()->GetSpriteRes( m_sAniName.c_str(), 0 );
// if( pFrame == NULL ) return;
//
// m_pSpriteList[0].SetRes( pFrame );
//
// // uv 좌표 구한다
// float fX = static_cast<float>(rt.left+pFrame->GetRectSrc().left) / static_cast<float>(pFrame->GetTexture()->GetSize().width);
// float fY = static_cast<float>(rt.top+pFrame->GetRectSrc().top) / static_cast<float>(pFrame->GetTexture()->GetSize().height);
// float fR = static_cast<float>(rt.right+pFrame->GetRectSrc().left) / static_cast<float>(pFrame->GetTexture()->GetSize().width);
// float fB = static_cast<float>(rt.bottom+pFrame->GetRectSrc().top) / static_cast<float>(pFrame->GetTexture()->GetSize().height);
//
// m_pSpriteList[0].SetSourceUVRect( fX, fY, fR, fB );
// m_pSpriteList[0].SetTargetSize( static_cast<float>(m_rcPieceArea[0].GetWidth()), static_cast<float>(m_rcPieceArea[0].GetHeight()) );
// m_pSpriteList[0].SetPosition( K3DVector( (K3DVALUE)GetRect().left ,(K3DVALUE)GetRect().top, m_fZPos ) );
// }
// break;
// }
//}
int KUIControl::GetTextureSizeX()
{
if( m_nPieceCount == 0 ) return -1;
KResSprite* pFrame = NULL;
if( _getSpriteSet() ) pFrame = _getSpriteSet()->GetSpriteRes( m_sAniName.c_str(), 0 );
if( pFrame == NULL ) return -1;
return pFrame->GetSizeX();
}
int KUIControl::GetTextureSizeY()
{
if( m_nPieceCount == 0) return -1;
KResSprite* pFrame = NULL;
if( _getSpriteSet() ) pFrame = _getSpriteSet()->GetSpriteRes( m_sAniName.c_str(), 0 );
if( pFrame == NULL ) return -1;
return pFrame->GetSizeY();
}
void KUIControl::SetTooltipOff()
{
_setToolTipOff();
}
static void GetTextWidth( SIZE& size, const char* szText, int nLen, const char* szFontName, int nFontSize, bool bBold )
{
//GetTextExtentPoint32( KTextRender::GetStaticDC(), szText, nLen, &size );
DWORD nW, nH;
KTextRender::GetStringSize( szFontName, nFontSize, bBold, szText, nLen, &nW, &nH );
size.cx = nW;
size.cy = nH;
}
void KUIControl::SplitLine( std::vector< std::string > & vecLineList, const std::string& strOriginal, const char* szFontName, int nFontSize, bool bBold, bool bUseFontSize /*= false*/ )
{
#ifdef _DEBUG
int nDWidth = GetRect().GetWidth();
int nDHeight = GetRect().GetHeight();
#endif
std::vector< std::string > vTextList;
{
std::string strTmp = strOriginal;
size_t pos, pos0, pos1;
while( true )
{
pos0 = strTmp.find( "<BR>" );
pos1 = strTmp.find( "<br>" );
if( pos0 != strTmp.npos && pos1 != strTmp.npos )
pos = std::min( pos0, pos1 );
else if( pos0 != strTmp.npos )
pos = pos0;
else if( pos1 != strTmp.npos )
pos = pos1;
else
{
if( !strTmp.empty() ) vTextList.push_back( strTmp );
break;
}
std::string strLine( strTmp.begin(), strTmp.begin() + pos );
vTextList.push_back( strLine );
strTmp = strTmp.substr( pos + 4, strTmp.size() );
}
}
while( !vTextList.empty() )
{
std::string strTmp = vTextList.front();
if( strTmp.size() == 0 )
{
vecLineList.push_back( strTmp );
vTextList.erase( vTextList.begin() );
continue;
}
{
std::vector< std::string > vTempList;
//KTextPhrase::GetSplitString( CStringUtil::StringFormat( "<font:%s><size:%d>%s", szFontName, nFontSize, strTmp.c_str() ).c_str(), GetRect().GetWidth(), vTempList, bUseFontSize );
// 텍스트 분할을 하기위해 <font> 와 <size> 태그 가 필요하다. bintite. 2010.09.29.
std::string::size_type fpos = strTmp.find( "<font" );
std::string::size_type spos = strTmp.find( "<size" );
if( fpos == std::string::npos || spos == std::string::npos )
KTextPhrase::GetSplitString( CStringUtil::StringFormat( "<font:%s><size:%d>%s", szFontName, nFontSize, strTmp.c_str() ).c_str(), GetRect().GetWidth(), vTempList, bUseFontSize );
else
KTextPhrase::GetSplitString( strTmp.c_str(), GetRect().GetWidth(), vTempList, bUseFontSize );
for( unsigned int i(0); vTempList.size()>i; i++ )
vecLineList.push_back( vTempList[i].c_str() );
}
vTextList.erase( vTextList.begin() );
}
// { 처음 공백은 무시해 달라는 구랴...
for( std::vector< std::string >::iterator it = vecLineList.begin(); it != vecLineList.end(); ++it )
{
while( !(*it).empty() )
{
if( (*it)[0] != ' ' ) break;
(*it) = (*it).substr( 1, (*it).size()-1 );
}
}
}
#include "KUITextureManager.h"
// 2010.03.15 - bintitle
// 자신과 동일한 control을 생성하여 반환.
KUIControl * KUIControl::Clone()
{
KUIControl * pControl = static_cast< KUIControl * >( m_pManager->CreateControl( KUIWND_CREATE_ARG( m_sClassName.c_str(),
this->GetID(),//GetClassNameA().c_str(),
GetCaption(),
GetRect(),
GetStyle(),
GetFlag(),
GetParent(),
GetAniName(),
GetSprName(),
m_pManager,
GetFrameIndex(),
"",
GetAnchor() ) )
);
pControl->SetEnableColor( m_strEnableColor.c_str() );
pControl->SetDisableColor( m_strDisableColor.c_str() );
return pControl;
}
// 2010.03.15 - bintitle
// 자신과 동일한 control을 생성하여 반환.
KUIControl * KUIControl::Clone( const char * newName )
{
return static_cast< KUIControl * >( m_pManager->CreateControl( KUIWND_CREATE_ARG( m_sClassName.c_str(),
newName,
GetCaption(),
GetRect(),
GetStyle(),
GetFlag(),
GetParent(),
GetAniName(),
GetSprName(),
m_pManager,
GetFrameIndex(),
"",
GetAnchor() ) )
);
}
// bintitle.
void KUIControl::SetColor( KColor & color ){
if( m_pSpriteList )
m_pSpriteList->SetColor( color );
}
// Modified. bintitle. 2010.09.29
// Trim the caption to fit the window size (add "..." at the end),
// and show the original caption as a tooltip.
void KUIControl::CutCaptionNTooltip()
{
// 추가. bintitle. 2010.10.01.
if( m_sCaption.empty() )
return;
// <br> 태그가 속한 텍스트는 무시.
std::string::size_type nPos = m_sCaption.find( "<br>" );
if( nPos != -1 )
return;
// Font명 얻기.
std::string fontName = "Default";
nPos = m_sCaption.find( "<font:" );
if( nPos != std::string::npos )
{
nPos += strlen( "<font:" );
std::string strTemp( m_sCaption.begin() + nPos, m_sCaption.begin() + m_sCaption.size() );
std::string::size_type nPos_End = strTemp.find_first_of( ">" );
fontName = strTemp.substr( 0, nPos_End );
}
// FontSize.
int nFontSize = this->GetFontSize();
m_sOrgCaption = m_sCaption; // 원본 복사.
// 잘림처리( .. )
std::vector< std::string > arrString;
// 텍스트 분할.
this->SplitLine( arrString, m_sCaption, fontName.c_str(), nFontSize, fontName == "font_02" ? true : false, true );
if( arrString.size() > 1 )
{
m_bCutCaption = true; // 제목의 잘림처리 여부.
// Tooltip.
this->SetTooltip( m_sOrgCaption.c_str() );
UpdateTip();
// 분할한 텍스트의 첫행.
std::wstring wstr( nsl::uni::conv(arrString[0]) );
// 2010.10.01. bintitle.
// 2010.10.01 맨 뒤에 짜투리 스트링이 있을 경우- prodongi
std::wstring extraStr;
std::wstring::size_type extraPos = wstr.rfind(L">");
if (extraPos != (wstr.size()-1))
{
extraStr = wstr.substr(extraPos+1, wstr.size()-1);
}
if (extraStr.empty())
{
cutCaptionNToolTipWithTag(wstr, 3);
}
else
{
if (3 <= extraStr.size())
{
wstr.erase(wstr.end()-1);
wstr.erase(wstr.end()-1);
wstr.erase(wstr.end()-1);
wstr += L"..."; /// 2010.10.25 ".."-> "..." - prodongi
}
else
{
wstr = wstr.substr(0, extraPos+1);
cutCaptionNToolTipWithTag(wstr, 3 - extraStr.size());
}
}
std::string textDecorate( m_sOrgCaption );
// 앞부분 꾸미기태그 얻기 : 번역 전 텍스트( 스트링 ID ) 인 경우.
std::string::size_type nPos = textDecorate.find( "<$" );
if( nPos != std::string::npos )
{
textDecorate = textDecorate.substr( 0, nPos );
nPos = textDecorate.rfind( ">" ) + 1;
textDecorate = textDecorate.substr( 0, nPos ) ;
}
// 앞부분 꾸미기태그 얻기 : 번역 후 텍스트( 스트링 ID가 실제 텍스트로 변환 ) 인 경우.
else
{
nPos = textDecorate.rfind( ">" ) + 1;
textDecorate = textDecorate.substr( 0, nPos ) ;
//textDecorate.erase();
//// 텍스트 꾸미기태그분리( 텍스트 내부의 태그는 제외 ).
////std::wstring wStrPure( wstr );
//std::wstring wStrPure( nsl::uni::conv(m_sCaption.c_str()));
//std::wstring::size_type sEnd;
//std::wstring::size_type oldEnd = 0;
//// ★ 태그를 제외한 텍스트만을 걸러낸다.
//if( !wStrPure.empty() )
//{
// while( 1 )
// {
// std::wstring::size_type sStart = wStrPure.find_first_of( L"<" );
// if( sStart != std::wstring::npos )
// {
// // 텍스트 꾸미기태그분리( 텍스트 내부의 태그는 제외 ).
// if( textDecorate.empty() && sStart > 0 )
// textDecorate = m_sCaption.substr( 0, oldEnd ).c_str();
// // "<" 는 존재하는데 ">" 는 없다는 것도 태그가 없는 것.
// sEnd = wStrPure.find_first_of( L">" );
//
// if( sEnd == std::wstring::npos || sStart > sEnd )
// break;
// else
// oldEnd += sEnd + 1;
// wStrPure = wStrPure.replace( sStart, sEnd - sStart + 1, L"" );
// }
// // 텍스트에 "<" 이 문자가 없다는 것은 태그가 없다는 것. 모두 걸러내었다! 종료.
// else
// {
// // 텍스트 꾸미기태그분리( 텍스트에 태그가 없는 경우 ).
// if( textDecorate.empty() && oldEnd > 0 )
// textDecorate = m_sCaption.substr( 0, oldEnd ).c_str();
// break;
// }
// }
//}
}
// Caption 설정.
textDecorate += nsl::uni::conv(wstr.c_str());
this->SetCaption( textDecorate.c_str() );
}
else
{
m_bCutCaption = false; // 제목의 잘림처리 여부.
// Tooltip.
this->SetTooltip();
}
}
// 2010.05.06 - prodongi
void KUIControl::addEmoticonSize(std::string const& aniName, int width, int height)
{
m_emoticonSizeList.push_back(sEmoticonSize(aniName, width, height));
}
// 2010.05.06 - prodongi
void KUIControl::updateToolTipEmoticonSize()
{
if (!m_pTipControl)
return ;
if (m_emoticonSizeList.empty())
return ;
std::vector<sEmoticonSize>::iterator it = m_emoticonSizeList.begin();
for (; it != m_emoticonSizeList.end(); ++it)
{
m_pTipControl->applyEmoticonSize(it->m_aniName, it->m_width, it->m_height);
}
m_emoticonSizeList.clear();
}
// 2010.10.01 - prodongi
void KUIControl::cutCaptionNToolTipWithTag(std::wstring& wstr, size_t strEraseCount)
{
// 2010.10.01. bintitle.
// 분할한 텍스트에서 순수한텍스트 의 뒤에 <태그> 가 있는 경우에 제거한다.
// ex >> "<font:font_01><#b35134>ABC<B><#ffffff><OFFSET:10>" 이런 텍스트의 경우 "<font:font_01><#b35134>ABC" 와 "<B><#ffffff><OFFSET:10>" 를 분리 하는 것이다.
std::vector< std::wstring > arrStrEndTag;
while( 1 )
{
std::wstring::size_type eTagpos = wstr.rfind( L">" );
if( eTagpos != std::wstring::npos && eTagpos == ( wstr.size()-1 ) )
{
std::wstring::size_type sTagpos = wstr.rfind( L"<" );
if( sTagpos != std::wstring::npos )
{
arrStrEndTag.push_back( wstr.substr( sTagpos, eTagpos ) );
wstr = wstr.substr( 0, sTagpos );
}
else
break;
}
else
break;
}
// 2010.06.08 조건 추가 - prodongi
for (size_t i = 0; i < strEraseCount; ++i)
{
if (wstr.size() > 0) wstr.erase(wstr.end()-1);
}
wstr += L"..."; /// 2010.10.25 ".."-> "..." - prodongi
// 2010.10.01. bintitle.
// 뒷부분의 태그를 제거한 경우 ".." 처리 후 추가한다. 제거시에 거꾸로 추가되었기때문에 뒤에서부터 추가.
if( !arrStrEndTag.empty() )
{
int size = arrStrEndTag.size();
for( int i=size-1; i>=0; --i )
wstr += arrStrEndTag[ i ];
// 2010.10.01 - prodongi
arrStrEndTag.clear();
}
}
/// 2010.11.01 - prodongi
void KUIControl::checkToolTipScreenBound()
{
if (!m_pTipControl)
return ;
if( m_bToolTipLeftRender )
{
m_nToolTipPosX -= m_pTipControl->GetRect().GetWidth();
if( m_nToolTipPosX<0 ) m_nToolTipPosX=0;
}
int xDiff = KUIWndManager::GetResolution().width - (m_nToolTipPosX +
m_pTipControl->GetRect().GetWidth() );
int yDiff = KUIWndManager::GetResolution().height - (m_nToolTipPosY +
m_pTipControl->GetRect().GetHeight() );
if(xDiff < 0)
m_nToolTipPosX += xDiff;
if(yDiff < 0)
m_nToolTipPosY += yDiff;
}
// 2011.03.23 - servantes
bool KUIControl::GetUVScrollEndFlag()
{
KTextPhrase* pPhrase = GetCaptionPhrase();
if(NULL == pPhrase)
return false;
std::vector<KTextPhrase::KTEXT_LINE_OBJECT *>* pList = pPhrase->GetLineList();
if(NULL == pList)
return false;
KTextPhrase::KTEXT_LINE_OBJECT* pLineObj = pList->at(0);
if(NULL == pLineObj)
return false;
KTextPhrase::KTEXT_OBJECT Obj = pLineObj->vtLineObject.at(0);
KSpritePrimitive* pSP = Obj.pRender->GetSpritePrimitive();
if(NULL == pSP)
return false;
sSpritePrimitiveScrollType* pScrollType = pSP->GetScroll();
if(NULL == pScrollType)
return false;
return pScrollType->m_bEnd;
}
// 2011.03.23 - servantes
void KUIControl::ResetUVScrollEndFlag()
{
KTextPhrase* pPhrase = GetCaptionPhrase();
if(NULL == pPhrase)
return ;
std::vector<KTextPhrase::KTEXT_LINE_OBJECT *>* pList = pPhrase->GetLineList();
if(NULL == pList)
return ;
KTextPhrase::KTEXT_LINE_OBJECT* pLineObj = pList->at(0);
if(NULL == pLineObj)
return ;
KTextPhrase::KTEXT_OBJECT Obj = pLineObj->vtLineObject.at(0);
KSpritePrimitive* pSP = Obj.pRender->GetSpritePrimitive();
if(NULL == pSP)
return ;
sSpritePrimitiveScrollType* pScrollType = pSP->GetScroll();
if(NULL == pScrollType)
return ;
pScrollType->m_bEnd = false;
}
#endif