#include "stdafx.h" #include "KResourceManager.h" #include "KUITextureManager.h" #include "KViewport.h" #include "KUIParser.h" #include "KUIGenWnd.h" #include "KUIDefine.h" #include "KUIWndManager.h" #include "KUIDragAndDrop.h" #include "Controls/KUIControl.h" #include "Controls/KUIControlEdit.h" #include "Controls/KUIControlStatic.h" #include "Controls/KUIControlButton.h" #include "Controls/KUIControlGauge.h" #include "Controls/KUIControlStatusBar.h" #include "Controls/KUIControlTitleBar.h" #include "Controls/KUITipControl.h" // { [sonador] #ifdef _KUI_INVALIDATION #include "KResource.h" #include #endif // } #include "SGameOption.h" bool KUIGenWnd::m_bWinMove; using namespace KUI_MESSAGE; namespace { const int FRAME_GAP = 2; //AniName 임. spr에 존재 해야함. const char * DEFAULT_GENWND_ANINAME[TOTAL_GENWND_ANINAME] = { "window_titlebar01", //타이틀 바 "window_off", //닫기? "window_reduction", //MINIMIZE "button_common_down", //리사이즈 임시 버튼? windows_button01_right "window_statusbar", //상태 바 "outframe", //테두리 "window_topframe", //상단 "window_tile", //타이틀 "window_button01", //버튼? }; } namespace { KUIWnd* GenWndCreator() { return new KUIGenWnd; } bool bRegister = KUIFactory::GetInstance()->RegisterCreator( GenWndCreator, "genwnd"); } //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // KUIGenWnd Implement //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// KUIGenWnd::KUIGenWnd() // { [sonador] #ifdef _KUI_INVALIDATION : m_spImageCache ( 0 ) , m_pImageCachePrimitive ( 0 ) , m_bNeedToCheckCached ( true ) , m_bActivateImageCache ( true ) #endif // } { m_pMinimize = NULL; m_pClose = NULL; m_pTitleBar = NULL; m_pTopFrame = NULL; m_pStatusBar = NULL; m_pResize = NULL; m_nPieceCount = 0; m_pSpriteList = NULL; m_pBackgroundArea = NULL; m_nBackgroundCount = 0; m_pBackgroundList = NULL; m_bResizing = false; m_bMoving = false; m_pDragAndDropIcon = new KUIDragAndDropNormalIconRenderer; m_pDragAndDropIcon->SetMaxState( TOTAL_STATE ); m_nResizeXUnit = 1; m_nResizeYUnit = 1; #ifdef _RAC SetShow( false ); #else SetShow( true ); #endif for(int i = 0; i < TOTAL_GENWND_ANINAME; ++i) m_sTotalAniName[i] = DEFAULT_GENWND_ANINAME[i]; m_bRightDown = false; //gmpbigsun( 20130104, #23793 ) : 잠금기능 설정하더라도 초기화코드때문에 풀림현상 수정 // m_bWinMove = true; //old const _OPT_DATA& opt_data = GetGameOption().GetOptData(); KUIGenWnd::AbleMoveWin( !opt_data.nWinLock ); } KUIGenWnd::~KUIGenWnd() { SAFE_DELETE_ARRAY( m_pBackgroundList ); SAFE_DELETE_ARRAY( m_pBackgroundArea ); SAFE_DELETE_ARRAY( m_pSpriteList ); SAFE_DELETE( m_pTopFrame ); SAFE_DELETE( m_pDragAndDropIcon ); // { [sonador] #ifdef _KUI_INVALIDATION SAFE_DELETE( m_pImageCachePrimitive ); RemoveAllPopupControl(); #endif // } } // MJ 2004/09/15 void KUIGenWnd::Create(KStream& stream, KUIWndManager* pManager) { KUIParser parser; if( false == parser.DoParsing( stream) ) return; if( parser.GetParseObjCount() < 1) return; // For now, the initial Parser Object is set to a single GenWNd KUIWndParseObject* pParseObj = parser.GetParseObject( 0); KUIWND_CREATE_ARG genArg = pParseObj->GetCreateArg(); m_pManager = pManager; genArg.pWndManager = pManager; Create( genArg ); for(DWORD i = 0; i < pParseObj->GetChildCount(); ++i) { KUIWndParseObject* pChildParseObj = pParseObj->GetChildParseObj( i ); KUIWND_CREATE_ARG childArg = pChildParseObj->GetCreateArg(); if(childArg.lpszSprName.empty()) childArg.lpszSprName = this->m_sSprName; childArg.pParent = this; childArg.pWndManager = m_pManager; // It goes up into actual memory KUITextureManager::GetManager()->GetSprAni( childArg.lpszSprName.c_str(), childArg.lpszAniName.c_str() ); m_pManager->CreateControl( childArg ); } // pManager->AddWnd( this ); } void KUIGenWnd::Create(KUIWND_CREATE_ARG& CREATE_ARG) { KUIWnd::Create( CREATE_ARG); m_rcClipArea = m_rcRegion; if( NULL == _getSpriteSet() ) { OutputDebugString( "Sprite not found" ); return; } m_maxSize = KUIWndManager::GetResolution(); m_minSize = KSize(100,100); KUIWND_CREATE_ARG CHILD_ARG; CHILD_ARG.pParent = this; CHILD_ARG.pWndManager = m_pManager; CHILD_ARG.lpszSprName = m_sSprName.c_str(); if ( m_dwStyle & KSTYLE_NORESIZE ) { m_pResize = NULL; } else { std::string sAniName; KResSprite* pFrame = _getSpriteSet()->GetSpriteRes( m_sTotalAniName[GENWND_RESIZE].c_str(), 0 ); if( pFrame ) { if( m_dwStyle & KSTYLE_RESIZE_LEFT) { CHILD_ARG.dwAnchor = KANCHOR_LEFT; m_rcResize.left = m_rcRegion.left + FRAME_GAP; } else { CHILD_ARG.dwAnchor = KANCHOR_RIGHT; m_rcResize.left = m_rcRegion.right - pFrame->GetSizeX() - FRAME_GAP; } if( m_dwStyle & KSTYLE_RESIZE_TOP) { CHILD_ARG.dwAnchor |= KANCHOR_TOP; m_rcResize.top = m_rcRegion.top + FRAME_GAP; } else { CHILD_ARG.dwAnchor |= KANCHOR_BOTTOM; m_rcResize.top = m_rcRegion.bottom - pFrame->GetSizeY() - FRAME_GAP; } } } if(! (m_dwStyle & KSTYLE_NOFRAME) ) { _reArrangeFrame(); _makeSpriteFrame(); } if( !(m_dwStyle & KSTYLE_NOTOPFRAME) ) _makeTopFrame(); if( !(m_dwStyle & KSTYLE_NOBACKGROUND) ) { _reArrangeBackground(); _makeBackgroundFrame(); } } void KUIGenWnd::Render( KViewportObject *pViewport, bool isFront ) { if( m_bShowFlag ) { #ifdef _KUI_INVALIDATION if( _initImageCache() ) { _prepareImageCache( isFront ); pViewport->Register( m_pImageCachePrimitive, isFront ); } else { _render( pViewport, isFront ); } _renderPopupControl( pViewport, isFront ); _renderToolTip( pViewport, true ); #else // Background을 먼저 깔고 for(int i = 0; i < m_nBackgroundCount; ++i) pViewport->Register( &m_pBackgroundList[i] ); // 나머지 콘트롤들을 렌더 KUIWnd::Render( pViewport, isFront ); if(NULL != m_pTopFrame) pViewport->Register(m_pTopFrame); for(int i = 0; i < m_vtGenWndControls.size(); ++i) m_vtGenWndControls.at(i)->Render( pViewport, isFront ); // 한 후에 다시 Frame Render for(int i = 0; i < m_nPieceCount; ++i) pViewport->Register(&m_pSpriteList[i]); #endif } } DWORD KUIGenWnd::OnMouseMessage(DWORD dwMessage, int x, int y) { /// 2011.10.18 test - prodongi if (stricmp(GetID(), "window_raid_siege_status") == 0) { int a = 0; } DWORD dwRet = KUIWnd::OnMouseMessage( dwMessage, x, y ); if( ::_stricmp( GetID(), "chat" ) == 0 && (dwMessage == KWHEEL_UP || dwMessage == KWHEEL_DOWN) ) dwRet = KMR_NORMAL | dwRet; if(KMR_NO_GET & dwRet) return dwRet; switch(dwMessage) { case KMOUSE_MOVE: if(m_bResizing) { // KResSprite* pFrame = _getSpriteSet()->GetSpriteRes( m_sTotalAniName[GENWND_RESIZE].c_str(), 0 ); if( !pFrame ) return dwRet; KRect newrect = m_rcRegion; if( m_dwStyle & KSTYLE_RESIZE_LEFT) newrect.left = x + pFrame->GetSizeX()/3; else newrect.right = x + pFrame->GetSizeX()/3; if( m_dwStyle & KSTYLE_RESIZE_TOP) newrect.top = y + pFrame->GetSizeY()/3; else newrect.bottom = y + pFrame->GetSizeY()/3; KRect oldRect = m_rcRegion; Resize( newrect ); if( oldRect != m_rcRegion) { PumpUpMessage( GetID(), KUI_MESSAGE::KGENWND_RESIZE, oldRect.GetWidth(), oldRect.GetHeight() ); } } else if(m_bMoving) { if( IsAbleMoveWin() ) { int XOffset = x - m_ptMovingOffset.x; int YOffset = y - m_ptMovingOffset.y; if(XOffset != 0 || YOffset != 0) { KPoint ptOld( m_rcRegion.left, m_rcRegion.top); MovePos( XOffset, YOffset); PumpUpMessage( GetID(), KUI_MESSAGE::KGENWND_MOVE, ptOld.x, ptOld.y); } } } break; case KLBUTTON_UP: if(m_bResizing) { m_bResizing = false; m_pManager->ReleaseCapture(this); } else if(m_bMoving) { m_bMoving = false; m_pManager->ReleaseCapture(this); } break; case KLBUTTON_DBLCLK: { PumpUpMessage(GetID(), KICON_DBLCLK, x, y ); } break; case KLBUTTON_DOWN: { // MJ 2004/10/21 // 별개의 윈도우끼리 포커스 처리 같이 해줄때, skill 창 focus 되면 sysmenu 도 함께 focus 되어야 한다..등.. // 메인 프레임 아무곳이나 선택해도 컨트롤과 상관없이 메시지 처리해야 할때 PumpUpMessage(GetID(), KFOCUS_ACTIVATED, x, y ); if(true == m_bResizing || true == m_bMoving) break; // Child가 메시지를 받지 않거나, NO_GET인 경우 if( (m_dwStyle & KSTYLE_MOVE_BY_ALL) && m_rcRegion.IsInRect( x, y) && ( !(dwRet & KMR_CHILD_GET_MSG) ) ) m_bMoving = true; if( (m_dwStyle & KSTYLE_MOVE_BY_TITLEBAR) && NULL != m_pTitleBar && m_pTitleBar->IsInRect( x, y) ) m_bMoving = true; if( (m_dwStyle & KSTYLE_MOVE_BY_TOPFRAME) && m_rcTopFrame.IsInRect( x , y ) ) m_bMoving = true; if (!(dwRet & KMR_CHILD_GET_MSG) ) { if( (m_dwStyle & KSTYLE_MOVE_BY_ALL) && m_rcRegion.IsInRect( x, y) ) m_bMoving = true; if( (m_dwStyle & KSTYLE_MOVE_BY_CUSTOM) ) { for(int i = 0; i < m_vtCustomRect.size(); ++i) { if( m_vtCustomRect.at( i ).IsInRect( x, y ) ) { m_bMoving = true; break; } } } } if( true == m_bMoving ) { m_ptMovingOffset = KPoint( x - m_rcRegion.left, y - m_rcRegion.top); m_pManager->SetCapture( this); } } break; case KRBUTTON_UP: { if( IsInRect( x, y ) && m_bRightDown ) { m_bRightDown = false; //Right Click 발생 PumpUpMessage(GetID(), KGENWND_RIGHT_CLICK, x, y ); // _oprint( "KGENWND_RIGHT_CLICK 발생\n" ); } } break; case KRBUTTON_DOWN: { if( IsInRect( x, y ) ) m_bRightDown = true; else m_bRightDown = false; } break; default: break; } return dwRet; } DWORD KUIGenWnd::OnKeyMessage(DWORD dwMessage, DWORD dwKeyCode) { DWORD dwRet = KUIWnd::OnKeyMessage( dwMessage, dwKeyCode); if(KMR_NO_GET & dwRet) return dwRet; if ( dwMessage == KKEY_DOWN && dwKeyCode == VK_RETURN ) PumpUpMessage( "IDOK", KBUTTON_CLICK, 0, 0 ); if ( dwMessage == KKEY_DOWN && dwKeyCode == VK_ESCAPE ) PumpUpMessage( "IDCANCEL", KBUTTON_CLICK, 0, 0 ); return dwRet; } void* KUIGenWnd::Perform( KID id, KArg& msg ) { _CID( UI_BEGIN_DRAG ); _CID( UI_RECV_DROP ); _CID( UI_SEND_DROP ); _CID( UI_CANDROP ); _CID( UI_ON_CHECK_DROP ); // 요건 상속받은 놈들에서 처리하자. if ( id == id_UI_BEGIN_DRAG ) { KUIBeginDragMessage* pBeginMsg = static_cast( &msg ); // Drag Object의 Icon의 Renderer 설정. // ( 상속받은 놈에서 이걸 맘대로 고쳐줄수 있음) KUIWnd* pWnd = GetChild( pBeginMsg->sDragControlID.c_str() ); if( NULL != pWnd) { m_pDragAndDropIcon->SetStateIcon( pWnd->GetSprName(), pWnd->GetAniName(), pWnd->GetFrameIndex(), STATE_NORMAL); // Drag And Drop을 하지 못할때의 Icon 설정 // m_pDragAndDropIcon->SetStateIcon( m_sSprName.c_str(), "", 0, STATE_CANNOT_DROP); // 가능 할때 Icon 설정 // m_pDragAndDropIcon->SetStateIcon( m_sSprName.c_str(), "", 0, STATE_CAN_DROP); } pBeginMsg->pDragAndDropRenderer = m_pDragAndDropIcon; } else if ( id == id_UI_RECV_DROP ) { KUISendRecvDropMessage* pRecvMsg = static_cast( &msg ); } else if ( id == id_UI_SEND_DROP ) { KUISendRecvDropMessage* pSendMsg = static_cast( &msg ); } else if ( id == id_UI_CANDROP ) { KUIDragAndDropMessage* pDropMsg = static_cast( &msg ); pDropMsg->sRecvDropParentID = GetID(); static KUIOnCheckDropMessage checkMsg; checkMsg.sSendDropControlID = pDropMsg->pObject->GetControlID(); checkMsg.sRecvDropParentID = GetID(); checkMsg.ptDropPos = pDropMsg->ptDropPos; bool bFind = false; KUIWnd* pParent = pDropMsg->pObject->GetParent(); // List를 돌면서 check (뒤에서부터 이므로 주의) for(std::list::reverse_iterator it = m_listChild.rbegin(); it != m_listChild.rend(); ++it) { KUIWnd *pWnd = (*it); // 맨처음으로 Rect에 걸린 녀석만 체크해 준다. if( pWnd->IsInRect( pDropMsg->ptDropPos.x, pDropMsg->ptDropPos.y) && !(pWnd->GetFlag() & KFLAG_NO_GET_MESSAGE ) ) { // Control에 대해서 체크 pDropMsg->sRecvDropControlID = pWnd->GetID(); checkMsg.sRecvDropControlID = pWnd->GetID(); if( NULL != pParent) pParent->Perform( id_UI_ON_CHECK_DROP, checkMsg); pWnd->Perform(id_UI_CANDROP, *pDropMsg); bFind = true; break; } } // GenWnd 대해서 체크 if( false == bFind) { // 받은놈이 없지? checkMsg.sRecvDropControlID = ""; if( NULL != pParent) pParent->Perform( id_UI_ON_CHECK_DROP, checkMsg); } } else if ( id == id_UI_ON_CHECK_DROP ) { // Drag를 쏜 Parent GenWnd 로 이 메세지가 날라온다. // ( 현재 Icon의 위치와 연관되는 Receiver Control, Parent GenWnd ID, ptPos를 담고 있다.) KUIOnCheckDropMessage* pCheckMsg = static_cast ( &msg ); for( DWORD i = 0; i < 3; ++i) m_pDragAndDropIcon->EnableState( i , false); m_pDragAndDropIcon->EnableState( STATE_NORMAL, true); if(pCheckMsg->sRecvDropControlID.empty() == false && pCheckMsg->sSendDropControlID != pCheckMsg->sRecvDropControlID) { m_pDragAndDropIcon->EnableState( STATE_CAN_DROP, true); } } return NULL; } void KUIGenWnd::PumpUpMessage( LPCSTR lpszControlID, DWORD nMessage, DWORD lparam, DWORD wparam ) { switch ( nMessage ) { case KEDIT_SYSKEY: if ( lparam == VK_RETURN ) PumpUpMessage( "IDOK", KBUTTON_CLICK, 0, 0 ); if ( lparam == VK_ESCAPE ) PumpUpMessage( "IDCANCEL", KBUTTON_CLICK, 0, 0 ); if ( lparam == VK_TAB ) { if ( m_listChild.size() > 1 ) { for( std::list::iterator it = m_listChild.begin(); it != m_listChild.end(); it++ ) { // 포커스를 가진 차일드가 있는 경우 if( (*it)->HasFocus() ) { std::list::iterator itNext = it; // 나머지 차일드 중 포커스를 받을 수 있는 것을 찾아서 포커스를 준다. for( size_t n( 0 ); n < (m_listChild.size() - 1); ++n ) { itNext++; if( itNext == m_listChild.end() ) itNext = m_listChild.begin(); // tab stop플래그가 없으므로 edit컨트롤에만 포커스를 주도록 한다. if( (*itNext)->GetClassName() == "edit" ) { (*it)->SetFocus( false ); (*itNext)->SetFocus( true ); break; } } break; } } } } break; case KBUTTON_PRESSING: //TODO : 하드코딩 if ( _stricmp( "_Resize", lpszControlID ) == 0 ) { m_bResizing = true; m_pManager->SetCapture( this ); } break; case KBUTTON_CLICK: if ( _stricmp( "_Resize", lpszControlID ) == 0 ) { m_bResizing = false; m_pManager->ReleaseCapture( this ); } // 이건 있으면 문제의 소지가 있음 .. "_Close" 자체로 해결 가능. //else if(_stricmp( "_Close", lpszControlID) == 0) //{ // PumpUpMessage("ID_CLOSE", KBUTTON_CLICK, 0,0); //} break; } } void KUIGenWnd::OnSizeChangeNofity(const KRect& rcRect) { // Unit 만큼 보정한 값을 가져온다. KRect rcNewResize = _calculateCorrectionRect(rcRect); // 같으면 안되네. if(rcNewResize == m_rcRegion) return; int nXMove = 0; int nYMove = 0; if( m_dwStyle & KSTYLE_RESIZE_LEFT) nXMove = rcNewResize.left - m_rcRegion.left; else nXMove = rcNewResize.right - m_rcRegion.right; if( m_dwStyle & KSTYLE_RESIZE_TOP) nYMove = rcNewResize.top - m_rcRegion.top; else nYMove = rcNewResize.bottom - m_rcRegion.bottom; // 보정값 만큼 설정 m_rcRegion = rcNewResize; m_rcClipArea = rcNewResize; m_rcCaptionArea = rcNewResize; const KRect & rcChildRect = _calculateChildRect( rcNewResize ); // Child Control들은 Child Control Area로 setting for ( std::list< KUIWnd* >::iterator it = m_listChild.begin();it != m_listChild.end() ; ++it ) { (*it)->OnParentSizeChangeNotify(rcChildRect , nXMove, nYMove, m_dwStyle); (*it)->OnParentClipChangeNotify(rcChildRect); } // GenWnd에 등록된 Control의 Clip Area는 다시 셋팅 for ( std::vector::iterator it = m_vtGenWndControls.begin(); it != m_vtGenWndControls.end(); ++it ) (*it)->OnParentClipChangeNotify(m_rcRegion); // frame size setting if( NULL != m_pTopFrame) { BuildPrimitive( m_pTopFrame, m_sTotalAniName[GENWND_TOPFRAME].c_str(), 1, K3DVertex(m_rcRegion.left, m_rcRegion.top, m_fZPos), 1.0f, KSize(m_rcRegion.GetWidth(), -1), false ); } if( !(m_dwStyle & KSTYLE_NOBACKGROUND) ) { _reArrangeBackground(); _makeBackgroundFrame(); _reArrangeFrame(); for(int i = 0; i SetAddPosition(x,y); _updateTopFrameRect(); m_rcClipArea.left += x; m_rcClipArea.top += y; m_rcClipArea.right += x; m_rcClipArea.bottom += y; const KRect & rcChildRect = _calculateChildRect( m_rcClipArea ); // Child Control들은 Child Control Area로 setting for ( std::list< KUIWnd* >::iterator it = m_listChild.begin();it != m_listChild.end() ; ++it ) (*it)->OnParentClipChangeNotify(rcChildRect); // GenWND에 등록된 Control의 Clip Area는 다시 셋팅 for ( std::vector::iterator it = m_vtGenWndControls.begin(); it != m_vtGenWndControls.end() ;++it ) (*it)->OnParentClipChangeNotify(m_rcClipArea); // Custom Moving Rect 이동 for(int i = 0; i < m_vtCustomRect.size(); ++i) { KRect& rcCustom = m_vtCustomRect.at( i ); rcCustom.left += x; rcCustom.top += y; rcCustom.right += x;rcCustom.bottom += y; } } void KUIGenWnd::OnParentPosChangeNotify(int XOffset, int YOffset) { MovePos( m_rcRegion.left + XOffset, m_rcRegion.top + YOffset ); } void KUIGenWnd::OnClipChangeNotify( const KRect& rcClipRect) { KUIWnd::OnClipChangeNotify( rcClipRect ); for(int i = 0; i < m_nPieceCount; ++i) m_pSpriteList[i].SetClipRect( &m_rcClipArea ); for(int i = 0; i < m_nBackgroundCount; ++i) m_pBackgroundList[i].SetClipRect( &m_rcClipArea ); if( m_pTopFrame ) m_pTopFrame->SetClipRect( &m_rcClipArea); } void KUIGenWnd::OnParentClipChangeNotify(const KRect& rcClipRect) { if( !(m_dwStyle & KSTYLE_NO_CLIPPING) ) ClipRect( rcClipRect ); } void KUIGenWnd::OnAlphaChangeNotify(float fAlpha) { KUIWnd::OnAlphaChangeNotify( fAlpha ); for(int i = 0; i < m_nPieceCount; ++i) m_pSpriteList[i].SetVisibility( fAlpha ); for(int i = 0; i < m_nBackgroundCount; ++i) m_pBackgroundList[i].SetVisibility( fAlpha ); if(m_pTopFrame) m_pTopFrame->SetVisibility( fAlpha ); } void KUIGenWnd::OnChangeCaptionNotify() { if( NULL != m_pTitleBar ) m_pTitleBar->SetCaption( m_sCaption.c_str() ); KUIWnd::OnChangeCaptionNotify(); } #ifdef _KUI_INVALIDATION void KUIGenWnd::OnShowNotify( bool bShowFlag ) { if( GetParent() == 0 ) { if( bShowFlag == false ) { _releaseImageCache(); m_bNeedToCheckCached = true; } } } void KUIGenWnd::ActivateImageCache( bool bActive ) { m_bActivateImageCache = bActive; if( !m_bActivateImageCache ) { _releaseImageCache(); } } void KUIGenWnd::OnDeviceLost() { _releaseImageCache(); InvalidateWnd(); } #endif void KUIGenWnd::AddButton( const char *_id, const char *_caption, const char* _toolTip ) { if ( m_pStatusBar ) { DWORD capwidth = m_rcRegion.GetWidth(); capwidth = KTextPhrase::GetStringSize( _caption, capwidth).width; KResSprite* pFrame = _getSpriteSet()->GetSpriteRes( m_sTotalAniName[GENWND_STATUSBAR_BTN].c_str(), 0 ); KRect rc; int style = 0; if ( m_VtButtons.size() == 0 ) { rc.left = m_rcRegion.left; rc.top = m_rcRegion.bottom - pFrame->GetSizeY(); style = KSTYLE_BUTTON_LEFTSIDE; rc.right = rc.left + pFrame->GetSizeX() * 3 + capwidth; rc.bottom = m_rcRegion.bottom; } else { KRect lastrc = m_VtButtons[m_VtButtons.size()-1]->GetRect(); rc.left = lastrc.right - pFrame->GetSizeX(); rc.top = m_rcRegion.bottom - pFrame->GetSizeY(); rc.right = rc.left + pFrame->GetSizeX() * 3 + capwidth; rc.bottom = m_rcRegion.bottom; } rc.top -= FRAME_GAP; rc.bottom -=FRAME_GAP; KUIWND_CREATE_ARG arg; arg.lpszClassName = "button"; arg.lpszID = _id; arg.lpszCaption = _caption; arg.lpszToolTip = _toolTip; arg.lpszAniName = m_sTotalAniName[GENWND_STATUSBAR_BTN].c_str(); arg.lpszSprName = m_sSprName.c_str(); arg.rcRect = rc; arg.pParent = this; arg.dwStyle = style; arg.dwAnchor = KANCHOR_BOTTOM | KANCHOR_LEFT; KUIControlButton *button = reinterpret_cast(m_pManager->CreateControl(arg)); m_VtButtons.push_back( button ); _refreshStatusBar(); m_vtGenWndControls.push_back( button); } } void KUIGenWnd::SetStatusText( const char *text ) { m_sStatusBarCaption = text; m_pStatusBar->SetCaption( m_sStatusBarCaption.c_str()); } void KUIGenWnd::SetResizeUnit(int nXUnit, int nYUnit, KSize minSize, KSize maxSize) { m_nResizeXUnit = nXUnit; m_nResizeYUnit = nYUnit; m_minSize = minSize; m_maxSize = maxSize; } void KUIGenWnd::SetGenWndAniName(LPCSTR lpszAniName, int nType) { if( nType < 0 || nType >= TOTAL_GENWND_ANINAME) return; if( lpszAniName == NULL) m_sTotalAniName[nType] = ""; else m_sTotalAniName[nType] = lpszAniName; } void KUIGenWnd::SetCustomMovingRect(const KRect& rcMovingRect) { if(m_vtCustomRect.empty() ) { AddCustomRect( rcMovingRect ); } else { ChangeCustomRect(rcMovingRect, 0); } } void KUIGenWnd::AddCustomRect(const KRect& rcCustom) { m_vtCustomRect.push_back( rcCustom ); } void KUIGenWnd::ChangeCustomRect(const KRect& rcMovingRect, int nIndex) { if( nIndex < 0 || nIndex >= m_vtCustomRect.size() ) { assert(false && "Invalid Index"); return; } m_vtCustomRect.at( nIndex ) = rcMovingRect; } KRect& KUIGenWnd::GetCustomRect(int nIndex) { return m_vtCustomRect.at( nIndex ); } int KUIGenWnd::GetCustomRectSize()const { return int( m_vtCustomRect.size() ); } void KUIGenWnd::RemoveCustomRectAll() { m_vtCustomRect.clear(); } bool KUIGenWnd::RemoveCustomRect(DWORD dwIndex) { if( dwIndex >= m_vtCustomRect.size() ) return false; m_vtCustomRect.erase( m_vtCustomRect.begin() + dwIndex ); return true; } KRect KUIGenWnd::_calculateCorrectionRect(const KRect& rcRect) { KRect rcNewResize = rcRect; // Min, Max Check if(m_dwStyle & KSTYLE_RESIZE_LEFT) { rcNewResize.left = min( m_rcRegion.right - m_minSize.cx, rcNewResize.left ); rcNewResize.left = max( m_rcRegion.right - m_maxSize.cx, rcNewResize.left ); } else { rcNewResize.right = max( rcNewResize.right, m_rcRegion.left + m_minSize.cx); rcNewResize.right = min( rcNewResize.right, m_rcRegion.left + m_maxSize.cx); } if( m_dwStyle & KSTYLE_RESIZE_TOP) { rcNewResize.top = min( m_rcRegion.bottom - m_minSize.cy, rcNewResize.top ); rcNewResize.top = max( m_rcRegion.bottom - m_maxSize.cy, rcNewResize.top ); } else { rcNewResize.bottom = max( rcNewResize.bottom, m_rcRegion.top + m_minSize.cy); rcNewResize.bottom = min( rcNewResize.bottom, m_rcRegion.top + m_maxSize.cy); } // 바뀐값 (offset) int nXMove = 0; int nYMove = 0; if(m_dwStyle & KSTYLE_RESIZE_LEFT) nXMove = rcNewResize.left - m_rcRegion.left; else nXMove = rcNewResize.right - m_rcRegion.right; if(m_dwStyle & KSTYLE_RESIZE_TOP) nYMove = rcNewResize.top - m_rcRegion.top; else nYMove = rcNewResize.bottom - m_rcRegion.bottom; // Unit로 나눈 나머지 int nXMoveMod = m_nResizeXUnit ? nXMove % m_nResizeXUnit : nXMove; int nYMoveMod = m_nResizeYUnit ? nYMove % m_nResizeYUnit : nYMove; // Unit 만큼 Resize값 보정 if (m_nResizeXUnit < (int)abs( nXMoveMod ) * 2) { int nXCorrection = nXMoveMod > 0 ? m_nResizeXUnit : -m_nResizeXUnit; if(m_dwStyle & KSTYLE_RESIZE_LEFT) rcNewResize.left = rcNewResize.left - nXMoveMod + nXCorrection; else rcNewResize.right = rcNewResize.right - nXMoveMod + nXCorrection; } else { if(m_dwStyle & KSTYLE_RESIZE_LEFT) rcNewResize.left = rcNewResize.left - nXMoveMod; else rcNewResize.right = rcNewResize.right - nXMoveMod; } if (m_nResizeYUnit < (int)abs( nYMoveMod ) * 2) { int nYCorrection = nYMoveMod > 0 ? m_nResizeYUnit : -m_nResizeYUnit; if(m_dwStyle & KSTYLE_RESIZE_TOP) rcNewResize.top = rcNewResize.top - nYMoveMod + nYCorrection; else rcNewResize.bottom = rcNewResize.bottom - nYMoveMod + nYCorrection; } else { if(m_dwStyle & KSTYLE_RESIZE_TOP) rcNewResize.top = rcNewResize.top - nYMoveMod; else rcNewResize.bottom = rcNewResize.bottom - nYMoveMod; } return rcNewResize; } const KRect& KUIGenWnd::_calculateChildRect(const KRect& rcWindowRect) { m_rcChildRect = rcWindowRect; // Frame ( -1씩 빼줌) if( !(KSTYLE_NOFRAME & m_dwStyle) ) { m_rcChildRect.left += 1; m_rcChildRect.top += 1; m_rcChildRect.right -= 1; m_rcChildRect.bottom -= 1; } // Status Bar or Button if( !(KSTYLE_NOSTATUSBAR & m_dwStyle) || m_VtButtons.size() > 0 ) { int nStatusBarHeight = m_pStatusBar ? m_pStatusBar->GetRect().GetHeight() : 0; m_rcChildRect.bottom -= nStatusBarHeight + FRAME_GAP; } return m_rcChildRect; } void KUIGenWnd::_refreshStatusBar() { if ( m_pStatusBar ) { KResSprite* pFrame = _getSpriteSet()->GetSpriteRes( m_sTotalAniName[GENWND_STATUSBAR_BTN].c_str(), 0 ); int style = 0; if ( m_VtButtons.size() > 0 ) { KRect lastrc = m_VtButtons[m_VtButtons.size() - 1]->GetRect(); m_rcStatusBar.left = lastrc.right - pFrame->GetSizeX(); m_rcStatusBar.top = m_rcRegion.bottom - pFrame->GetSizeY(); m_rcStatusBar.bottom = m_rcRegion.bottom; m_rcStatusBar.right = m_rcRegion.right; } else { style = KSTYLE_SB_NOLEFTSIDE; m_rcStatusBar.left = m_rcRegion.left; m_rcStatusBar.top = m_rcRegion.bottom - pFrame->GetSizeY(); m_rcStatusBar.bottom = m_rcRegion.bottom; m_rcStatusBar.right = m_rcRegion.right; } m_rcStatusBar.top -= FRAME_GAP; m_rcStatusBar.bottom -= FRAME_GAP; m_rcStatusBar.right -= FRAME_GAP; if ( m_dwStyle & KSTYLE_NORESIZE || m_dwStyle & KSTYLE_RESIZE_LEFT || m_dwStyle & KSTYLE_RESIZE_TOP ) style |= KSTYLE_SB_NORIGHTSIDE; m_pStatusBar->SetStyle( style ); m_pStatusBar->Resize( m_rcStatusBar ); } } void KUIGenWnd::_reArrangeFrame() { if( _getSpriteSet() ) { m_nPieceCount = _getSpriteSet()->GetSpriteResAniCount( m_sTotalAniName[GENWND_FRAME].c_str() ); if(m_nPieceCount < 1) return; int nLeft = m_rcRegion.left; int nTop = m_rcRegion.top; KResSprite * pFrame = _getSpriteSet()->GetSpriteRes( m_sTotalAniName[GENWND_FRAME].c_str(), 0 ); int nSizeX = (int)pFrame->GetSizeX(); int nSizeY = (int)pFrame->GetSizeY(); int nMidSizeX = m_rcRegion.right - m_rcRegion.left - nSizeX * 2; int nMidSizeY = m_rcRegion.bottom - m_rcRegion.top - nSizeY * 2; switch(m_nPieceCount) { case 9: // 9조각으로 찢어질 경우 { int nCount = 0; // 찍는 부분 설정 for(int i = 0; i < 3; ++ i) { nLeft = m_rcRegion.left; for(int j = 0; j < 3; ++j) { m_rcPieceArea[nCount].left = nLeft; m_rcPieceArea[nCount].top = nTop; m_rcPieceArea[nCount].right = m_rcPieceArea[nCount].left + nSizeX; m_rcPieceArea[nCount].bottom = m_rcPieceArea[nCount].top + nSizeY; // 중간 열 if( j == 1) { nLeft += nMidSizeX; m_rcPieceArea[nCount].right = m_rcPieceArea[nCount].left + nMidSizeX; } else nLeft += nSizeX; // 중간 행 if(i == 1) m_rcPieceArea[nCount].bottom = m_rcPieceArea[nCount].top + nMidSizeY ; nCount++; } // Mid if( i == 1) nTop += nMidSizeY; else nTop += nSizeY; } } break; default: { assert(false && "Piece Number is Invalid"); } } } } void KUIGenWnd::_reArrangeBackground() { SAFE_DELETE_ARRAY( m_pBackgroundArea ); KResSprite * pFrame = NULL; if(_getSpriteSet()) pFrame = _getSpriteSet()->GetSpriteRes( m_sTotalAniName[GENWND_BACKGROUND].c_str(), 0 ); if( NULL == pFrame) return; int nSizeX = pFrame->GetSizeX(); int nSizeY = pFrame->GetSizeY(); int nVerticalCount = 1; int nHorizontalCount = 1; // 우선은 기본적으로 Genwnd 크기 int nBackWidth = m_rcRegion.GetWidth(); int nBackHeight = m_rcRegion.GetHeight(); // 세로 반복 if( KSTYLE_VERTICAL_REPEAT & m_dwStyle) { nBackHeight = nSizeY; // 모자라면 + 1 해줌 nVerticalCount = ( m_rcRegion.GetHeight() - 1 ) / nSizeY + 1; } // 가로 반복 if( KSTYLE_HORIZONTAL_REPEAT & m_dwStyle) { nBackWidth = nSizeX; // 모자라면 + 1 해줌 nHorizontalCount = ( m_rcRegion.GetWidth() - 1 ) / nSizeX + 1; } m_nBackgroundCount = nVerticalCount * nHorizontalCount; m_pBackgroundArea = new KRect[m_nBackgroundCount]; // 우선 세로 먼저 int nPosX = m_rcRegion.left; int nPosY = m_rcRegion.top; for(int i = 0; i < nVerticalCount; ++i) { nPosX = m_rcRegion.left; for(int k = 0; k < nHorizontalCount; ++k) { m_pBackgroundArea[i * nHorizontalCount + k] = KRect( nPosX, nPosY, nPosX + nBackWidth, nPosY + nBackHeight); nPosX += nSizeX; } nPosY += nSizeY; } } void KUIGenWnd::_makeSpriteFrame() { SAFE_DELETE_ARRAY( m_pSpriteList ); m_pSpriteList = new KSpritePrimitive[m_nPieceCount]; for(int i = 0; i GetSpriteRes( m_sTotalAniName[GENWND_FRAME].c_str(), i ); if(!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 KUIGenWnd::_makeBackgroundFrame() { SAFE_DELETE_ARRAY( m_pBackgroundList ); m_pBackgroundList = new KSpritePrimitive[m_nBackgroundCount]; KResSprite * pFrame = NULL; if(_getSpriteSet()) pFrame = _getSpriteSet()->GetSpriteRes( m_sTotalAniName[GENWND_BACKGROUND].c_str(), 0 ); if(!pFrame) return; for(int i = 0; i GetRes() != NULL ) m_rcTopFrame.bottom = m_rcTopFrame.top + m_pTopFrame->GetRes()->GetSizeY(); else m_rcTopFrame.bottom = m_rcTopFrame.top; } // { [sonador] #ifdef _KUI_INVALIDATION bool KUIGenWnd::_initImageCache() { if( !m_bActivateImageCache || !_isTopWindow() ) return false; if( m_bNeedToCheckCached ) { if( m_spImageCache == 0 ) m_spImageCache = _getRenderTarget(); if( m_spImageCache ) { if( m_pImageCachePrimitive == 0 ) { m_pImageCachePrimitive = new KSpritePrimitive(); m_pImageCachePrimitive->SetRes( new KResSprite() ); } m_pImageCachePrimitive->GetRes()->SetTexture( m_spImageCache, 0 ); } else { SAFE_DELETE( m_pImageCachePrimitive ); } m_bNeedToCheckCached = false; } return m_spImageCache; } void KUIGenWnd::_releaseImageCache() { m_bNeedToCheckCached = true; // [sonador] =_=;;; 어쩔수 없나... if( m_spImageCache ) m_spImageCache = 0; if( m_pImageCachePrimitive && m_pImageCachePrimitive->GetRes() && m_pImageCachePrimitive->GetRes()->GetTexture() ) m_pImageCachePrimitive->GetRes()->SetTexture( 0, 0 ); } bool KUIGenWnd::_prepareImageCache( bool isFront ) { if( !m_pManager || !m_pManager->GetViewportObject() ) return false; if( !IsValidWnd() ) { KViewportObject* pGuiViewport = m_pManager->GetViewportObject(); _render( pGuiViewport, isFront ); K3DVector vRegion( m_rcRegion.left, m_rcRegion.top, 0.0f ); pGuiViewport->RearrangeSpriteOffset( vRegion ); pGuiViewport->Render( m_spImageCache ); m_pImageCachePrimitive->SetRes( m_pImageCachePrimitive->GetRes() ); ValidateWnd(); } // KUIGenWnd의 위치에 맞게 렌더타겟용 sprite primitive를 움직이자. K3DMatrix mSprite; K3DMatrixIdentity( mSprite ); K3DVector vRegion( m_rcRegion.left, m_rcRegion.top, m_fZPos ); mSprite.SetPosVector( vRegion ); m_pImageCachePrimitive->SetTransform( mSprite ); return true; } #endif // } void KUIGenWnd::SwapControl( const char* szID, const char* szSwapID ) { if( m_listChild.size() == 0 ) return; std::list BackList; KUIWnd* pOriginalWnd; KUIWnd* pNewWnd; bool bNewUpdate = false, bOriginalUpdate = false; std::list::iterator it = m_listChild.begin(); while( it != m_listChild.end() ) { KUIWnd* pWnd = (*it); if( ::_stricmp(pWnd->GetID(), szID) == 0 && !bOriginalUpdate ) { pOriginalWnd = KUIFactory::GetInstance()->CreateObject( pWnd->GetClassName().c_str() ); *pOriginalWnd = *pWnd; bOriginalUpdate = true; } else if( ::_stricmp(pWnd->GetID(), szSwapID) == 0 && !bNewUpdate ) { pNewWnd = KUIFactory::GetInstance()->CreateObject( pWnd->GetClassName().c_str() ); *pNewWnd = *pWnd; bNewUpdate = true; } BackList.push_back(pWnd); it++; } bNewUpdate = false, bOriginalUpdate = false; it = BackList.begin(); while( it != BackList.end() ) { KUIWnd* pWnd =(*it); if( ::_stricmp(pWnd->GetID(), szID) == 0 && !bNewUpdate ) { *(*it) = *pNewWnd; bNewUpdate = true; } else if( ::_stricmp(pWnd->GetID(), szSwapID) == 0 && !bOriginalUpdate ) { *(*it) = *pOriginalWnd; bOriginalUpdate = true; } it++; } m_listChild.swap( BackList ); } #ifdef _KUI_INVALIDATION void KUIGenWnd::AddPopupControl( KUIControl* pControl ) { if( pControl == NULL ) return; for( int i(0); iSetPopupWnd(true); } void KUIGenWnd::RemovePopupControl( KUIControl* pControl ) { if( pControl == NULL ) return; std::vector::iterator it = m_vtPopupControl.begin(); KUIControl* pCmpControl(NULL); while( it != m_vtPopupControl.end() ) { pCmpControl = *it; if( pCmpControl == pControl ) { if( pCmpControl ) pCmpControl->SetPopupWnd(false); m_vtPopupControl.erase( it ); return; } it++; } } void KUIGenWnd::RemoveAllPopupControl() { for( int i(0); iSetPopupWnd(false); } m_vtPopupControl.clear(); } void KUIGenWnd::_render( KViewportObject* pViewport, bool isFront ) { // Background을 먼저 깔고 for(int i = 0; i < m_nBackgroundCount; ++i) pViewport->Register( &m_pBackgroundList[i] ); // 나머지 콘트롤들을 렌더 KUIWnd::Render( pViewport, isFront ); if(NULL != m_pTopFrame) pViewport->Register(m_pTopFrame); for(int i = 0; i < m_vtGenWndControls.size(); ++i) m_vtGenWndControls.at(i)->Render( pViewport, isFront ); // 한 후에 다시 Frame Render for(int i = 0; i < m_nPieceCount; ++i) pViewport->Register(&m_pSpriteList[i]); } void KUIGenWnd::_renderPopupControl( KViewportObject *pViewport, bool isFront ) { for( int i(0); iIsShow() ) m_vtPopupControl[i]->Render( pViewport, isFront ); } } void KUIGenWnd::_renderToolTip( KViewportObject *pViewport, bool isFront ) { if( m_pOnToolTipWnd ) ((KUIControl*)m_pOnToolTipWnd)->RenderToolTip( pViewport, isFront ); } #endif