#include "stdafx.h"
#include "SmallMiniMapWindow.h"
#include "UIImage.h"

#include "ResourceManager.h"
#include "GameResourceManager.h"
#include "WorldManager.h"
#include "ObjectManager.h"
#include "NaviMesh.h"
#include "Hero.h"
#include "Npc.h"
#include "FontAgent.h"
#include "GameUIManager.h"
#include "InputSystem.h"
#include "CameraManager.h"
#include "NpcScript.h"
#include "PartyManager.h"
#include "UITransformImage.h"
#include "Icon.h"
#include "Application.h"
#include "Label.h"

#include "StageScript.h"

cSmallMiniMapWindow::cSmallMiniMapWindow()
: mpMiniMapImage(0)
, mHeroData(0)
, mCameraData(0)
, mCoverData(0)
, mHoverData(0)
, mNeedUpdate( false )
, mNamePos( 0, 0 )
, mJobPos( 0, 0 )
, mpQuestNew(0)
, mpQuestPlay(0)
, mpQuestComplete(0)
, mUserSellData(0)
, mpMapName(0)
, mpChannelNum(0)
{
	mHeroX = 0;
	mHeroY = 0;

	mOldX = -1.f;
	mOldY = -1.f;

	mPercent = MAX_PERCENT;
	mOriginTexW = 512;
	mOriginTexH = 512;

	mHeroDir = -NiPoint3::UNIT_Y;
	mCameraDir = -NiPoint3::UNIT_Y;

	mPartyInSkinName = "SmallMiniMap_PartyIn";
	mPartyOutSkinName = "SmallMiniMap_PartyOut";
}

cSmallMiniMapWindow::~cSmallMiniMapWindow()
{
	/// 밑에 clear 함수도 같이 적용시키기
	/// 이미지 데이터 삭제
	cImageDataList::cIterator i = mImageDataList.Begin();
	cImageDataList::cIterator end = mImageDataList.End();
	for( ; i != end; ++i )
	{
		sBaseImageData* p = (sBaseImageData*)(*i);
		if( p && p->mpImage )
		{
			if( p->mType == eTYPE_NPC )
			{
				sNpcImageData* data = (sNpcImageData*)p;
				SAFE_DELETE( data->mAniParam );
				SAFE_DELETE( data->mpAniImage );
			}

			SAFE_DELETE( p->mpImage );
			SAFE_DELETE( p );
		}
	}
	mImageDataList.Clear();

	///
	if( mHeroData )
	{
		SAFE_DELETE( mHeroData->mpImage );
		SAFE_DELETE( mHeroData );
	}

	if( mCameraData )
	{
		SAFE_DELETE( mCameraData->mpImage );
		SAFE_DELETE( mCameraData );
	}

	if( mCoverData )
	{
		SAFE_DELETE( mCoverData->mpImage );
		SAFE_DELETE( mCoverData );
	}
	
	if( mpMiniMapImage )
		SAFE_DELETE( mpMiniMapImage );
}

/// 맵 바뀔때 삭제용 - 파티는 파티쪽에서 삭제하므로 제외
void cSmallMiniMapWindow::Clear()
{
	/// 이미지 데이터 삭제
	cImageDataList::cIterator i = mImageDataList.Begin();
	cImageDataList::cIterator end = mImageDataList.End();
	for( ; i != end; ++i )
	{
		sBaseImageData* p = (sBaseImageData*)(*i);
		if( p && p->mpImage )
		{
			if( p->mType == eTYPE_NPC )
			{
				sNpcImageData* data = (sNpcImageData*)p;
				SAFE_DELETE( data->mAniParam );
				SAFE_DELETE( data->mpAniImage );
			}

			SAFE_DELETE( p->mpImage );
			SAFE_DELETE( p );
		}
	}
	mImageDataList.Clear();

	/// 이미지 삭제
	if( mpMiniMapImage )
		SAFE_DELETE( mpMiniMapImage );

	///
	mName.Clear();
	mJobName.Clear();

	mNamePos.mX = 0;
	mNamePos.mY = 0;
	mJobPos.mX = 0;
	mJobPos.mY = 0;

	mPercent = MAX_PERCENT;
	mOldX = -1.f;
	mOldY = -1.f;
}

void cSmallMiniMapWindow::OnHide()
{
	cUIWindow::OnHide();

	mName.Clear();
	mJobName.Clear();
}

void cSmallMiniMapWindow::UIStageIn()
{
	/// 현재 hero의 맵 번호 알아오기
	unsigned long folderIdx = GAMERESOURCEMAN->GetMapFolderIdx( HERO->GetMapNum() );

	/// 미니맵 로딩
	cString pathName;
	pathName.Format( "./Map/Map%02d/MapImage_%02d.tga", folderIdx, folderIdx );
	if( LoadMiniMap( pathName ) == false )
	{
		assert(0);
		return;
	}

	/// 현재 윈도우에 적용된 텍스쳐 사이즈 구하기 ( 곱하기 100퍼센트 )
	mPerTexW = mOriginTexW * mPercent * 0.01;
	mPerTexH = mOriginTexH * mPercent * 0.01;
}

/// 맵이름, 포탈정보 세팅
void cSmallMiniMapWindow::SetMapData()
{
	/// 채널번호 입력
	if( mpChannelNum )
		mpChannelNum->SetValue( HERO->GetChannelNum() );

	/// 맵이름
	LPCTSTR mapname = GAMERESOURCEMAN->GetMapName( HERO->GetMapNum() );
	if( mpMapName )
		mpMapName->SetText( mapname );

	tPointerArray<void*>* pMapArray = STAGESCRIPT->GetMapChangeStarterArr( (unsigned short)HERO->GetMapNum() );

	/// 맵포탈 정보 세팅
	if( pMapArray->IsEmpty() == false )
	{
		for( unsigned int i = 0; i < pMapArray->GetSize(); ++i )
		{
			sStageChangePos* p = (sStageChangePos*)(*pMapArray)[i];
			AddPortal( p->mPosIdx );
		}
	}
}

/// 미니맵 이미지 로딩 
bool cSmallMiniMapWindow::LoadMiniMap( const cString& pathName )
{
	NiTexture* ptex = RESOURCEMAN->LoadTexture( pathName, false );
	if( ptex == 0 )
	{
		assert( 0 && "failed to load texture" );
		return false;
	}

	/// 텍스쳐 설정
	mpMiniMapImage = new cUITransformImage;
	mpMiniMapImage->SetTexture( ptex );

	unsigned short x = (unsigned short)GetAbsoluteRect().mLeft + MAP_X;
	unsigned short y = (unsigned short)GetAbsoluteRect().mTop + MAP_Y;

	mpMiniMapImage->SetTextureRect( 0, 0, mOriginTexW, mOriginTexH );
	mpMiniMapImage->SetScreenRect( cUIRect( x, y, x + MAP_W, y + MAP_H ) );
	return true;
}

///
bool cSmallMiniMapWindow::OnCreate( cUINodeProperty* pproperty )
{
	if( cUIWindow::OnCreate( pproperty ) == false )
		return false;

	mpMapName = (cLabel*)GetChild( eUIID_SMALL_MINIMAP_MAPNAME );
	mpChannelNum = (cLabel*)GetChild( eUIID_SMALL_MINIMAP_CHANNEL );

	cUISkin* pSkin = UIMAN->GetSkin();
	if( !pSkin )
		return false;

	/// CAMERA 이미지 로드
	cUINodeSkin* pCameraSkin = pSkin->GetNodeSkin( "SmallMiniMap_Camera" );
	if( pCameraSkin  )
	{
		mCameraData = new sBaseImageData;
		if( !mCameraData )
			return false;

		mCameraData->mpImage = new cUITransformImage;
		mCameraData->mpImage->SetTexture( pCameraSkin->mpTexture );
		mCameraData->mType = eTYPE_CAMERA;

		unsigned short tx = (unsigned short)pCameraSkin->mSkinInfo->mTexX;
		unsigned short ty = (unsigned short)pCameraSkin->mSkinInfo->mTexY;
		unsigned short w = (unsigned short)pCameraSkin->mSkinInfo->mTexWidth;
		unsigned short h = (unsigned short)pCameraSkin->mSkinInfo->mTexHeight;

		mCameraData->mSize.mWidth = w;
		mCameraData->mSize.mHeight = h;

		mCameraData->mpImage->SetTextureRect( tx, ty, tx + w, ty + h );
		mCameraData->mpImage->SetScreenRect( cUIRect( mCameraData->mPos.mX, mCameraData->mPos.mY, 
													  mCameraData->mPos.mX + w, mCameraData->mPos.mY + h ) );
	}

	///// HERO 이미지 로드
	cUINodeSkin* pHeroSkin = pSkin->GetNodeSkin( "SmallMiniMap_Hero" );
	if( pHeroSkin  )
	{
		mHeroData = new sBaseImageData;
		if( !mHeroData )
			return false;
		
		mHeroData->mpImage = new cUITransformImage;
		mHeroData->mpImage->SetTexture( pHeroSkin->mpTexture );
		mHeroData->mType = eTYPE_HERO;
				
		unsigned short tx = (unsigned short)pHeroSkin->mSkinInfo->mTexX;
		unsigned short ty = (unsigned short)pHeroSkin->mSkinInfo->mTexY;
		unsigned short w = (unsigned short)pHeroSkin->mSkinInfo->mTexWidth;
		unsigned short h = (unsigned short)pHeroSkin->mSkinInfo->mTexHeight;

		mHeroData->mSize.mWidth = w;
		mHeroData->mSize.mHeight = h;

		mHeroData->mpImage->SetTextureRect( tx, ty, tx + w, ty + h );
		mHeroData->mpImage->SetScreenRect( cUIRect( mHeroData->mPos.mX, mHeroData->mPos.mY, 
													mHeroData->mPos.mX + w, mHeroData->mPos.mY + h ) );
	}
	
	/// 좌표 이미지 로드
	cUINodeSkin* pCoverSkin = pSkin->GetNodeSkin( "SmallMiniMap_PosImage" );
	if( pCoverSkin  )
	{
		mCoverData = new sBaseImageData;
		if( !mCoverData )
			return false;

		mCoverData->mpImage = new cUITransformImage;
		mCoverData->mpImage->SetTexture( pHeroSkin->mpTexture );
		mCoverData->mType = eTYPE_NONE;

		unsigned short tx = (unsigned short)pCoverSkin->mSkinInfo->mTexX;
		unsigned short ty = (unsigned short)pCoverSkin->mSkinInfo->mTexY;
		unsigned short w = (unsigned short)pCoverSkin->mSkinInfo->mTexWidth;
		unsigned short h = (unsigned short)pCoverSkin->mSkinInfo->mTexHeight;
		mCoverData->mPos.mX = (unsigned short)pCoverSkin->mSkinInfo->mX;
		mCoverData->mPos.mY = (unsigned short)pCoverSkin->mSkinInfo->mY;

		mCoverData->mSize.mWidth = w;
		mCoverData->mSize.mHeight = h;

		mCoverData->mpImage->SetTextureRect( tx, ty, tx + w, ty + h );
		mCoverData->mpImage->SetScreenRect( cUIRect( mCoverData->mPos.mX, mCoverData->mPos.mY, 
											mCoverData->mPos.mX + w, mCoverData->mPos.mY + h ) );
	}

	/// 퀘스트 관련 이미지 
	{
		mpQuestNew = pSkin->GetNodeSkin( "SmallMiniMap_QuestNew" );
		if( mpQuestNew == 0 )
			return false;

		mpQuestPlay = pSkin->GetNodeSkin( "SmallMiniMap_QuestPlay" );
		if( mpQuestPlay == 0 )
			return false;

		mpQuestComplete = pSkin->GetNodeSkin( "SmallMiniMap_QuestComplete" );
		if( mpQuestComplete == 0 )
			return false;
	}

	if( mpMapName )
		mpMapName->SetTextColor( eCOLOR_WHITE );

	if( mpChannelNum )
		mpChannelNum->SetTextColor( eCOLOR_WHITE );
	return true;
}

///
void cSmallMiniMapWindow::UpdateRect()
{
	cUIWindow::UpdateRect();

	if( mpMiniMapImage )
	{
		short screenX = (short)GetAbsoluteRect().mLeft + MAP_X;
		short screenY = (short)GetAbsoluteRect().mTop + MAP_Y;
		mpMiniMapImage->SetPos( screenX, screenY );
	}

	if( mCoverData && mCoverData->mpImage )
	{
		short screenX = (unsigned short)mCoverData->mPos.mX + GetAbsoluteRect().mLeft;
		short screenY = (unsigned short)mCoverData->mPos.mY + GetAbsoluteRect().mTop;

		mCoverData->mpImage->SetPos( screenX, screenY );
	}

	mNeedUpdate = true;
}

/// 해상도 변경시 호출
void cSmallMiniMapWindow::UpdateSkin()
{
	cUIWindow::UpdateSkin();

	mNeedUpdate = true;
}

///
void cSmallMiniMapWindow::OnProcess( unsigned long deltaTime, unsigned long accumTime )
{
	if( mVisible == false )
		return;

	cUIWindow::OnProcess( deltaTime, accumTime );

	cHero* hero = OBJECTMANAGER->GetHero();
	cCamera* camera = CAMERAMAN->GetCurrent();
	cNaviMesh* navi = WORLDMAN->GetNaviMesh();

	if( !(hero && camera && navi) )
		return;

	float segLen = navi->GetSegmentLength();

	if( !(mHeroData && mHeroData->mpImage) )
		return;

	if( !(mCameraData && mCameraData->mpImage) )
		return;

	/// 이동
	float x = hero->GetXPos();
	float y = hero->GetYPos();

	if( x != mOldX || y != mOldY || mNeedUpdate )
	{
		mOldX = x;
		mOldY = y;

		/// 텍스쳐 상의 캐릭터 위치 GetSegmentLength : 맵의 변 길이 
		int heroX = (int)(x / segLen * mOriginTexW);
		int heroY = (int)(mOriginTexH - (y / segLen * mOriginTexH ));

		mHeroX = (int)(x * 0.01);
		mHeroY = (int)(y * 0.01);

		/// 윈도우에 적용할 텍스쳐 좌표 계산
		double texX = heroX - mPerTexW * 0.5f;
		double texY = heroY - mPerTexH * 0.5f;
		double texRight = heroX + mPerTexW * 0.5f;
		double texBottom = heroY + mPerTexH * 0.5f;

		/// 소수점 보정 
		short tl = (short)( texX + 0.5f );
		short tt = (short)( texY + 0.5f );
		unsigned short tr = (unsigned short)( texRight + 0.5f );
		unsigned short tb = (unsigned short)( texBottom + 0.5f );

		/// 미니맵의 스크롤 여부에 따른 보정값 계산 
		int fixX = 0;
		int fixY = 0;

		if( tl < 0 )
		{
			fixX = tl;
			tl = 0;
			tr = (short)mPerTexW;
		}
		else if( tr > mOriginTexW )
		{
			fixX = tr - mOriginTexW;
			tl = (short)(mOriginTexW - mPerTexW);
			tr = mOriginTexW;
		}

		if( tt < 0 )
		{
			fixY = tt;
			tt = 0;
			tb = (short)mPerTexH;
		}
		else if( tb > mOriginTexH )
		{
			fixY = tb - mOriginTexH;
			tt = (short)(mOriginTexH - mPerTexH);
			tb = mOriginTexH;
		}

		/// 보정값을 텍스쳐에 대한 비율로 변환
		fixX = (int)((float)fixX / mPerTexW * MAP_W);
		fixY = (int)((float)fixY / mPerTexH * MAP_H);

		//
		double xr = MAP_W * 0.5f + fixX + MAP_X;
		double yr = MAP_H * 0.5f + fixY + MAP_Y;

		/// 이미지 좌표 적용 
		mpMiniMapImage->SetTextureRect( tl, tt, tr, tb );

		mHeroData->mScreenPos.mX = (short)xr - (short)(mHeroData->mSize.mWidth * 0.5f );
		mHeroData->mScreenPos.mY = (short)yr - (short)(mHeroData->mSize.mHeight * 0.5f );
		mHeroData->mpImage->SetTranslate( (short)GetAbsoluteRect().mLeft + (short)mHeroData->mScreenPos.mX, 
										  (short)GetAbsoluteRect().mTop + (short)mHeroData->mScreenPos.mY );

		short camX = (short)xr - (short)(mCameraData->mSize.mWidth * 0.5f );
		short camY = (short)yr - (short)(mCameraData->mSize.mHeight * 0.5f );
		mCameraData->mpImage->SetTranslate( (short)GetAbsoluteRect().mLeft + (short)camX, 
											(short)GetAbsoluteRect().mTop + (short)camY );

		/// 이미지 갱신
		cImageDataList::cIterator i = mImageDataList.Begin();
		cImageDataList::cIterator end = mImageDataList.End();
		for( ; i != end; ++i )
		{
			sBaseImageData* p = (sBaseImageData*)(*i);
			if( p && p->mpImage )
			{
				int cx = (int)(p->mSize.mWidth * 0.5f);
				int cy = (int)(p->mSize.mHeight * 0.5f);

				if( !(p->mType == eTYPE_PARTY || p->mType == eTYPE_USERSELL) )
				{
					p->mShow = false;

					/// 출력 보정 ( 미니맵 범위안에 들어가야만 출력 )
					if( p->mPos.mX - cx >= tl && p->mPos.mX + cx <= tr && 
						p->mPos.mY - cy >= tt && p->mPos.mY + cy <= tb )
					{
						/// 윈도우사이즈에 맞게 변환 
						int x = (p->mPos.mX - tl) * MAP_W;
						int y = (p->mPos.mY - tt) * MAP_H;

						/// 텍스쳐상 의서의 위치 재계산
						p->mScreenPos.mX = (int)(( x / mPerTexW ) + MAP_X ) - cx + GetAbsoluteRect().mLeft; 
						p->mScreenPos.mY = (int)(( y / mPerTexH ) + MAP_Y ) - cy + GetAbsoluteRect().mTop;

						p->mpImage->SetPos( p->mScreenPos.mX, p->mScreenPos.mY );
						p->mShow = true;

						if( p->mType == eTYPE_NPC )
						{
							sNpcImageData* data =(sNpcImageData*)p;
							if( data->mpAniImage )
								data->mpAniImage->SetPos( p->mScreenPos.mX, p->mScreenPos.mY - 8 );
						}
					}
				}
				/// 파티원이나 개인상점등 유저관련 표시
				else
				{
					sUserImageData* data = (sUserImageData*)p;
					if( data->mMapNum != HERO->GetMapNum() )
						continue;
					
					int userX = data->mPos.mX;
					int userY = data->mPos.mY;

					/// 출력 보정 ( 미니맵 범위안에 들어가야만 출력 )
					if( data->mPos.mX - cx >= tl && data->mPos.mX + cx <= tr && 
						data->mPos.mY - cy >= tt && data->mPos.mY + cy <= tb )
					{
						data->mpImage->SetTexture( data->mpInSkin->mpTexture );
						unsigned int texX = data->mpInSkin->mSkinInfo->mTexX;
						unsigned int texY = data->mpInSkin->mSkinInfo->mTexY;
						unsigned int w = data->mpInSkin->mSkinInfo->mTexWidth;
						unsigned int h = data->mpInSkin->mSkinInfo->mTexHeight;
						data->mpImage->SetTextureRect( texX, texY, texX + w, texY + h );

						/// 윈도우사이즈에 맞게 변환 
						int x = (userX - tl) * MAP_W;
						int y = (userY - tt) * MAP_H;

						/// 텍스쳐상 의서의 위치 재계산
						data->mScreenPos.mX = (int)(( x / mPerTexW ) + MAP_X ) - cx + GetAbsoluteRect().mLeft; 
						data->mScreenPos.mY = (int)(( y / mPerTexH ) + MAP_Y ) - cy + GetAbsoluteRect().mTop;

						data->mpImage->SetPos( data->mScreenPos.mX, data->mScreenPos.mY );
					}
					else
					{
						/// 화살표 모양으로 변경하고, 더이상 밖으로 벗어나지 않게 한다.
						data->mpImage->SetTexture( data->mpOutSkin->mpTexture );
						unsigned int texX = data->mpOutSkin->mSkinInfo->mTexX;
						unsigned int texY = data->mpOutSkin->mSkinInfo->mTexY;
						unsigned int w = data->mpOutSkin->mSkinInfo->mTexWidth;
						unsigned int h = data->mpOutSkin->mSkinInfo->mTexHeight;
						data->mpImage->SetTextureRect( texX, texY, texX + w, texY + h );

						if( data->mPos.mX < tl )
							userX = tl;

						if( data->mPos.mX > tr )
							userX = tr;

						if( data->mPos.mY < tt )
							userY = tt;

						if( data->mPos.mY > tb )
							userY = tb;

						/// 윈도우사이즈에 맞게 변환 
						int x = (userX - tl) * MAP_W;
						int y = (userY - tt) * MAP_H;

						/// 텍스쳐상 의서의 위치 재계산
						double nxr = ( x / mPerTexW ) + MAP_X; 
						double nyr = ( y / mPerTexH ) + MAP_Y;

						cx = (int)( data->mpOutSkin->mSkinInfo->mWidth );
						cy = (int)( data->mpOutSkin->mSkinInfo->mHeight );

						// 유저 위치 얻어오기
						float hx = (float)(xr - (short)(mHeroData->mSize.mWidth * 0.5f ));
						float hy = (float)(yr - (short)(mHeroData->mSize.mHeight * 0.5f ));
						NiPoint3 hero( (float)hx, (float)hy, 0 );
						NiPoint3 user( (float)(nxr - cx), (float)(nyr - cy), 0 );

						/// 유저 방향 얻어내기
						NiPoint3 userDir = user - hero;
						userDir.Unitize(); 

						/// 방향에 따른 각도 구하기
						float dot = userDir.Dot( -NiPoint3::UNIT_Y ); 
						float ang = NiACos( dot ); 					  

						if( userDir.x > 0.f )
							ang = -ang;

						/// 회전
						data->mpImage->SetRotate( ang );

						/// 반지름 이동
						short r = (short)(GetAbsoluteRect().GetWidth() * 0.5f);
						int screenPosX = (short)mHeroData->mScreenPos.mX + (short)(userDir.x * r);
						int screenPosY = (short)mHeroData->mScreenPos.mY + (short)(userDir.y * r);
						
						/// 사각형에 붙여놓기
						if( screenPosX < MAP_X )
							screenPosX = MAP_X;

						if( screenPosX + cx > MAP_X + MAP_W )
							screenPosX = MAP_X + MAP_W - cx;

						if( screenPosY < MAP_Y )
							screenPosY = MAP_Y;

						if( screenPosY + cy > MAP_Y + MAP_H )
							screenPosY = MAP_Y + MAP_H - cy;
				
						data->mScreenPos.mX = screenPosX + GetAbsoluteRect().mLeft;
						data->mScreenPos.mY = screenPosY + GetAbsoluteRect().mTop;
						data->mpImage->SetTranslate( data->mScreenPos.mX, data->mScreenPos.mY );
					}

					data->mShow = true;
				}
			}
		}

		/// 갱신
		if( mHoverData )
			UpdateNamePos();

		/// 업데이트 완료 
		mNeedUpdate = false;
	}

	/// hero 회전
	NiPoint3 heroDir = hero->GetDirection();
	heroDir.z = 0.f;
	heroDir.Unitize();

	if( heroDir != mHeroDir )
	{
		mHeroDir = heroDir;

		float dot = heroDir.Dot( NiPoint3::UNIT_Y );
		float ang = NiACos( dot );

		if( heroDir.x > 0.f )
			ang = -ang;

		mHeroData->mpImage->SetRotate( ang );
	}	

	/// 카메라 회전
	NiPoint3  camDir = camera->GetWorldDirection();
	camDir.z = 0.f;
	camDir.Unitize();

	if( camDir != mCameraDir )
	{
		mCameraDir = camDir;

		float dot = camDir.Dot( NiPoint3::UNIT_Y );
		float ang = NiACos( dot );

		if( camDir.x > 0.f )
			ang = -ang;

		mCameraData->mpImage->SetRotate( ang );
	}

	/// 미니맵 노점상 표시 시간 체크
	if( mUserSellData && mUserSellData->mShow == true )
	{
		if( accumTime - mUserSellData->mStartTime > MAINTAIN_TIME )
		{
			RemoveUserSell( mUserSellData );
		}
	}

	/// 애니메이션 갱신
	cImageDataList::cIterator i = mImageDataList.Begin();
	cImageDataList::cIterator end = mImageDataList.End();
	for( ; i != end; ++i )
	{
		sBaseImageData* p = (sBaseImageData*)(*i);
		if( p && p->mType == eTYPE_NPC )
		{
			sNpcImageData* data = (sNpcImageData*)p;
			if( data->mQuestStatus != eNPCQUEST_NONE )
			{
				UpdateQuestAni( data, accumTime );
			}
		}
	}
}

///
void cSmallMiniMapWindow::OnRender( cUIFontItemKeeper* pKeeper )
{
	if( mpMiniMapImage )
		mpMiniMapImage->Draw();

	/// 이미지 렌더링
	if( mpImage )
		mpImage->Draw();

	/// 이미지 렌더링
	{
		cImageDataList::cIterator i = mImageDataList.Begin();
		cImageDataList::cIterator end = mImageDataList.End();
		for( ; i != end; ++i )
		{
			sBaseImageData* p = (sBaseImageData*)(*i);
			if( p && p->mpImage && p->mShow )
			{
				p->mpImage->Draw();

				/// 퀘스트 상태에 따라 애니메이션 출력 결정
				if( p->mType == eTYPE_NPC )
				{
					sNpcImageData* data = (sNpcImageData*)p;
					if( data->mpAniImage && data->mQuestStatus != eNPCQUEST_NONE )
						data->mpAniImage->Draw();
				}
			}
		}
	}

	if( mCameraData )
		mCameraData->mpImage->Draw();

	if( mHeroData )
		mHeroData->mpImage->Draw();

	/// 자식 렌더링
	{
		cChildList::cIterator i = mChildList.Begin();
		cChildList::cIterator end = mChildList.End();

		for( ; i != end; ++i )
		{
			if( ((cUINode*)(*i))->IsVisible() == true )
				((cUINode*)(*i))->OnRender(pKeeper);
		}
	}

	if( mCoverData && mCoverData->mpImage )
		mCoverData->mpImage->Draw();

	/// 문자열 출력 
	cStringT str;
	str.Format( _T("%d, %d"), mHeroX, mHeroY );
	pKeeper->AddFontItem( cFontAgent::eFont_System, (LPCTSTR)str.Cstr(), GetAbsoluteRect().mLeft + 12, GetAbsoluteRect().mTop + 169, eCOLOR_WHITE );

	/// 이름 라벨 출력 
	if( mJobName )
		pKeeper->AddFontItem( cFontAgent::eFont_System, const_cast<LPTSTR>(mJobName.Cstr()), mJobPos.mX, mJobPos.mY, eCOLOR_WHITE );
	
	if( mName )
		pKeeper->AddFontItem( cFontAgent::eFont_System, const_cast<LPTSTR>(mName.Cstr()), mNamePos.mX, mNamePos.mY, eCOLOR_WHITE );

	///
	pKeeper->DrawAll();
}

/// 이름 정보 위치 업데이트
void cSmallMiniMapWindow::UpdateNamePos()
{
	if( mName.IsEmpty() )
		return;

	if( !(mHoverData && mHoverData->mpImage && mHoverData->mShow) )
		return;

	cUIRect rc;
	rc.mLeft = mHoverData->mScreenPos.mX;
	rc.mTop = mHoverData->mScreenPos.mY;
	rc.mRight = rc.mLeft + mHoverData->mSize.mWidth;
	rc.mBottom = rc.mTop + mHoverData->mSize.mHeight;

	/// 맵 이미지 좌표 비교후 보정
	int mapLeft = GetAbsoluteRect().mLeft + MAP_X;
	int mapTop = GetAbsoluteRect().mTop + MAP_Y;

	int textHeight = FONTAGENT->GetTextHeight( cFontAgent::eFont_System );

	/// 직업이름이 있으면 좌표 세팅
	if( mJobName.IsEmpty() == false )
	{
		/// 직업좌표 세팅
		int textWidth = FONTAGENT->GetTextExtent( cFontAgent::eFont_System, mJobName.Cstr(), mJobName.GetLength() );
		
		mJobPos.mX = (int)(rc.mLeft + ( rc.GetWidth() - textWidth ) * 0.5);
		mJobPos.mY = rc.mTop - 10 - textHeight;

		/// 이름이 튀어나가지 않도록 보정
		if( mJobPos.mX <= mapLeft )
			mJobPos.mX = mapLeft;
		else if( mJobPos.mX + textWidth >= mapLeft + (int)MAP_W )
			mJobPos.mX = mapLeft + MAP_W - textWidth;

		/// 너무 위에 찍히는것을 방지
		if( mJobPos.mY <= mapTop )
			mJobPos.mY = rc.mBottom + 2;
	}

	/// 이름좌표 세팅
	int textWidth = FONTAGENT->GetTextExtent( cFontAgent::eFont_System, mName.Cstr(), mName.GetLength() );

	mNamePos.mX = (int)(rc.mLeft + ( rc.GetWidth() - textWidth ) * 0.5);
	mNamePos.mY = rc.mTop - 10;

	/// 이름이 튀어나가지 않도록 보정
	if( mNamePos.mX <= mapLeft )
		mNamePos.mX = mapLeft;
	else if( mNamePos.mX + textWidth >= mapLeft + (int)MAP_W )
		mNamePos.mX = mapLeft + MAP_W - textWidth;

	/// 너무 위에 찍히는 것을 방지
	if( mJobName.IsEmpty() == false )
		mNamePos.mY = mJobPos.mY + 2 + textHeight;
}

///
void cSmallMiniMapWindow::OnMouseMove( const cUIPos& pos )
{
	cUIWindow::OnMouseMove( pos );

	mName.Clear();
	mJobName.Clear();

	/// 화면 앞에서부터 검사
	cUIRect rect;
	cImageDataList::cIterator i = (--mImageDataList.End());
	cImageDataList::cIterator end = (--mImageDataList.Begin());
	for( ; i != end; --i )
	{
		sBaseImageData* p = (sBaseImageData*)(*i);
		if( p && p->mpImage && p->mShow )
		{
			/// 영역 체크
			rect.mLeft = p->mScreenPos.mX;
			rect.mTop = p->mScreenPos.mY;
			rect.mRight = rect.mLeft + p->mSize.mWidth;
			rect.mBottom = rect.mTop + p->mSize.mHeight;

			/// 
			if( rect.ContainPoint( pos ) == true )
			{
				mHoverData = p;
				
				switch( p->mType )
				{
				case eTYPE_NPC:
					{
						sNpcImageData* data = (sNpcImageData*)p;
						if( data )
						{
							mName = data->mName;

							TCHAR temp[128] = {0,};
							::_stprintf( temp, _T("<%s>"), (LPCTSTR)data->mJobName.Cstr() );
							mJobName = temp;
							UpdateNamePos();
						}
					}
					break;
				case eTYPE_PARTY:
				case eTYPE_DEATHMATCH:
				case eTYPE_USERSELL:
				case eTYPE_PORTAL:
					{
						sUserImageData* data = (sUserImageData*)p;
						if( data )
						{
							mName = data->mName;
							UpdateNamePos();
						}
					}
					break;
				}

				/// 중지
				break;
			}
		}
	}
}

///
void cSmallMiniMapWindow::OnMouseLeft( const cUIPos& )
{
	/// 출력용 이름 클리어
	if( mName.IsEmpty() == false )
	{
		mName.Clear();
		mJobName.Clear();
		mHoverData = 0;
	}
}

///
void cSmallMiniMapWindow::OnCommand( cUINode*, unsigned int id )
{
	switch( id )
	{
	case eUIID_SMALL_MINIMAP_CLOSE_BUTTON:
		{
			Hide();
		}
		break;
	case eUIID_SMALL_MINIMAP_LARGEOPEN:
		{
			/// 큰 미니맵 열기 버튼 
			GAMEUI->ToggleMiniMapWindow();
		}
		break;
	case eUIID_SMALL_MINIMAP_PLUS:
		{
			/// 미니맵 뷰 확대
			if( mPercent > MIN_PERCENT )
			{
				mPercent -= ADD_PERCENT;

				/// 현재 윈도우에 적용된 텍스쳐 사이즈 구하기 ( 곱하기 100퍼센트 )
				mPerTexW = mOriginTexW * mPercent * 0.01;
				mPerTexH = mOriginTexH * mPercent * 0.01;
				mNeedUpdate = true;
			}
		}
		break;
	case eUIID_SMALL_MINIMAP_MINUS:
		{
			/// 미니맵 뷰 축소 
			if( mPercent < MAX_PERCENT )
			{
				mPercent += ADD_PERCENT;

				/// 현재 윈도우에 적용된 텍스쳐 사이즈 구하기 ( 곱하기 100퍼센트 )
				mPerTexW= mOriginTexW * mPercent * 0.01;
				mPerTexH = mOriginTexH * mPercent * 0.01;
				mNeedUpdate = true;
			}			
		}
		break;
	}
}

/// 포탈 이미지 세팅
void cSmallMiniMapWindow::AddPortal( unsigned long index )
{
	sStageChangePos* p = STAGESCRIPT->GetPosScriptInfo( index );
	if( !p )
	{
		assert(0);
		return;
	}

	cUISkin* pSkin = UIMAN->GetSkin();
	if( !pSkin )
		return;

	cNaviMesh* navi = WORLDMAN->GetNaviMesh();
	if( !navi )
	{
		assert(0);
		return;
	}

	float segLen = navi->GetSegmentLength();

	cUINodeSkin* pPotalSkin = pSkin->GetNodeSkin( "SmallMiniMap_Portal" );
	if( pPotalSkin  )
	{
		sPortalImageData* potalData = new sPortalImageData;
		if( !potalData )
		{
			assert(0);
			return;
		}

		potalData->mpImage = new cUITransformImage;
		potalData->mpImage->SetTexture( pPotalSkin->mpTexture );
		potalData->mType = eTYPE_PORTAL;
		
		if( p->mTargetInfo )
			potalData->mTargetMapNum = p->mTargetInfo->mMapNumber;
		else
			potalData->mTargetMapNum = p->mMapNumber;

		potalData->mName = GAMERESOURCEMAN->GetMapName( potalData->mTargetMapNum );

		unsigned short tx = (unsigned short)pPotalSkin->mSkinInfo->mTexX;
		unsigned short ty = (unsigned short)pPotalSkin->mSkinInfo->mTexY;
		unsigned short w = (unsigned short)pPotalSkin->mSkinInfo->mTexWidth;
		unsigned short h = (unsigned short)pPotalSkin->mSkinInfo->mTexHeight;
		potalData->mPos.mX = (int)( p->mPosX / segLen * mOriginTexW );
		potalData->mPos.mY = (int)( mOriginTexH - ( p->mPosY / segLen * mOriginTexH ) );

		potalData->mSize.mWidth = w;
		potalData->mSize.mHeight = h;

		potalData->mpImage->SetTextureRect( tx, ty, tx + w, ty + h );
		potalData->mpImage->SetScreenRect( cUIRect( potalData->mPos.mX, potalData->mPos.mY, 
													potalData->mPos.mX + w, potalData->mPos.mY + h ) );

		/// 삽입
		mImageDataList.PushBack( potalData );
	}

	if( mNeedUpdate == false )
	{
		mOldX = 0;
		mOldY = 0;
		mNeedUpdate = true;
	}
}

/// npc 추가
void cSmallMiniMapWindow::AddNpc( sNpcData* data, bool IsSmall )
{
	if( data == 0 )
	{
		assert(0);
		return;
	}

	cUISkin* pSkin = UIMAN->GetSkin();
	if( !pSkin )
		return;

	cNaviMesh* navi = WORLDMAN->GetNaviMesh();
	if( !navi )
	{
		assert(0);
		return;
	}

	float segLen = navi->GetSegmentLength();

	sNPCList* pNpcList = NPCSCRIPT->GetNPCList( data->mNpcClassIdx );
	if( pNpcList )
	{
		sNpcImageData* npcData = new sNpcImageData;
		if( !npcData )
		{
			assert(0);
			return;
		}

		/// 정보세팅
		npcData->mType = eTYPE_NPC;
		npcData->mClassIndex = data->mNpcClassIdx;
		npcData->mNpcIndex = data->mNpcIdx;
		npcData->mQuestStatus = eNPCQUEST_NONE;
		npcData->mPos.mX = (int)( data->mPosX / segLen * mOriginTexW );
		npcData->mPos.mY = (int)( mOriginTexH - ( data->mPosY / segLen * mOriginTexH ) );
		npcData->mName = pNpcList->mName;
		npcData->mJobName = pNpcList->mJobName;

		unsigned long paramIdx = ( IsSmall == true ) ? pNpcList->mJobIconIndexSmall : pNpcList->mJobIconIndexLarge;

		cIconParam* param = UIMAN->GetIconParam( paramIdx );
		if( param )
		{
			/// 이미지세팅
			npcData->mpImage = new cUITransformImage;
			npcData->mpImage->SetTexture( param->mpTexture );
			unsigned short tx = (unsigned short)param->mTexPos.mX;
			unsigned short ty = (unsigned short)param->mTexPos.mY;
			npcData->mSize.mWidth = NPCICON_SIZE;
			npcData->mSize.mHeight = NPCICON_SIZE;

			npcData->mpImage->SetTextureRect( tx, ty, tx + NPCICON_SIZE, ty + NPCICON_SIZE );
			npcData->mpImage->SetScreenRect( cUIRect( npcData->mPos.mX, npcData->mPos.mY, 
													  npcData->mPos.mX + NPCICON_SIZE, npcData->mPos.mY + NPCICON_SIZE ) );
		}

		/// 애니메이션세팅
		npcData->mAniParam = new sAniParam;
		npcData->mAniParam->mTimeOut = 100;
		npcData->mAniParam->mLastAccumTime = 0;
		npcData->mAniParam->mFrame = 5;
		npcData->mAniParam->mTexX = 0;
		npcData->mAniParam->mTexY = 0;
		npcData->mAniParam->mAniOn = false;
		npcData->mAniParam->mCurFrame = 0;
		npcData->mAniParam->mReturn = false;

		/// 애니용 이미지 생성
		if( mpQuestNew )
		{
			npcData->mpAniImage = new cUITransformImage;
			npcData->mpAniImage->SetTexture( mpQuestNew->mpTexture );

			unsigned short tx = (unsigned short)mpQuestNew->mSkinInfo->mTexX;
			unsigned short ty = (unsigned short)mpQuestNew->mSkinInfo->mTexY;
			unsigned short tw = npcData->mAniParam->mWidth = mpQuestNew->mSkinInfo->mWidth;
			unsigned short th = npcData->mAniParam->mHeight = mpQuestNew->mSkinInfo->mHeight;
			npcData->mpAniImage->SetTextureRect( tx, ty, tx + tw, ty + th );
			npcData->mpAniImage->SetScreenRect( cUIRect( npcData->mPos.mX, npcData->mPos.mY, 
												npcData->mPos.mX + tw, npcData->mPos.mY + th ) );

			npcData->mAniParam->mWidth = tw;
			npcData->mAniParam->mHeight = th;
		}


		/*cIconParam* aniParam = UIMAN->GetIconParam( 11839 );
		if( aniParam )
		{
			npcData->mpAniImage = new cUITransformImage;
			npcData->mpAniImage->SetTexture( aniParam->mpTexture );

			unsigned short tx = (unsigned short)aniParam->mTexPos.mX;
			unsigned short ty = (unsigned short)aniParam->mTexPos.mY;
			npcData->mpAniImage->SetTextureRect( tx, ty, tx + ANIICON_SIZE, ty + ANIICON_SIZE );
			npcData->mpAniImage->SetScreenRect( cUIRect( npcData->mPos.mX, npcData->mPos.mY, 
														 npcData->mPos.mX + ANIICON_SIZE, npcData->mPos.mY + ANIICON_SIZE ) );
		}*/

		/// 삽입
		mImageDataList.PushBack( npcData );
	}

	if( mNeedUpdate == false )
	{
		mOldX = 0;
		mOldY = 0;
		mNeedUpdate = true;
	}
}

/// npc 삭제
void cSmallMiniMapWindow::RemoveNpc( unsigned long index )
{
	cImageDataList::cIterator i = mImageDataList.Begin();
	cImageDataList::cIterator end = mImageDataList.End();
	for( ; i != end; ++i )
	{
		sBaseImageData* p = (sBaseImageData*)(*i);
		if( p && p->mType == eTYPE_NPC )
		{
			sNpcImageData* data = (sNpcImageData*)p;
			if( data->mNpcIndex == index )
			{
				SAFE_DELETE( data->mAniParam );
				SAFE_DELETE( data->mpAniImage );
				SAFE_DELETE( data->mpImage );
				SAFE_DELETE( data );
				mImageDataList.Erase(i);
				break;
			}
		}
	}
}

/// npc 의 퀘스트 관련 상태 업데이트
void cSmallMiniMapWindow::SetNpcQuestStatus( unsigned long index, unsigned char status )
{
	/// 해당 npc 이미지 찾기
	cUINodeSkin* skin = 0;
	cImageDataList::cIterator i = mImageDataList.Begin();
	cImageDataList::cIterator end = mImageDataList.End();
	for( ; i != end; ++i )
	{
		sBaseImageData* p = (sBaseImageData*)(*i);
		if( !(p && p->mType == eTYPE_NPC) )
			continue;

		sNpcImageData* data = (sNpcImageData*)p;
		if( data->mNpcIndex == index )
		{
			data->mQuestStatus = status;

			switch( status )
			{
			case eNPCQUEST_NEW:			skin = mpQuestNew; break;
			case eNPCQUEST_PLAYING:		skin = mpQuestPlay; break;
			case eNPCQUEST_REWARD:		skin = mpQuestComplete; break;
			case eNPCQUEST_COMPLETE:	skin = mpQuestComplete; break;
			default: return;
			}

			if( skin && data->mpAniImage )
			{
				unsigned short tx = (unsigned short)skin->mSkinInfo->mTexX;
				unsigned short ty = (unsigned short)skin->mSkinInfo->mTexY;
				unsigned short tw = (unsigned short)skin->mSkinInfo->mTexWidth;
				unsigned short th = (unsigned short)skin->mSkinInfo->mTexHeight;

				data->mAniParam->mTexX = tx;
				data->mAniParam->mTexY = ty;
				data->mAniParam->mWidth = tw;
				data->mAniParam->mHeight = th;
				data->mpAniImage->SetTextureRect( tx, ty, tx + tw, ty + th );
			}
			break;
		}
	}
}

/// 파티원 추가
void cSmallMiniMapWindow::AddPartyUser( cPartyData* data )
{
	if( data == 0 )
	{
		assert(0);
		return;
	}

	cUISkin* pSkin = UIMAN->GetSkin();
	if( !pSkin )
		return;

	cNaviMesh* navi = WORLDMAN->GetNaviMesh();
	if( !navi )
	{
		assert(0);
		return;
	}

	float segLen = navi->GetSegmentLength();

	cUINodeSkin* pPartySkin = pSkin->GetNodeSkin( mPartyInSkinName );
	if( pPartySkin  )
	{
		sUserImageData* partyData = new sUserImageData;
		if( !partyData )
		{
			assert(0);
			return;
		}

		partyData->mpImage = new cUITransformImage;
		partyData->mpImage->SetTexture( pPartySkin->mpTexture );
		partyData->mType = eTYPE_PARTY;
		partyData->mMapNum = data->mMapNum;
		partyData->mUserIndex = data->mIndex;
		partyData->mName = data->mName;
		
		partyData->mpInSkin = pPartySkin;
		partyData->mpOutSkin = pSkin->GetNodeSkin( mPartyOutSkinName );
		if( !(partyData->mpInSkin && partyData->mpOutSkin) )
		{
			assert(0);
			return;
		}

		/// 같은맵에 없으면 안보이기
		if( partyData->mMapNum != HERO->GetMapNum() )
			partyData->mShow = false;

		unsigned short tx = (unsigned short)pPartySkin->mSkinInfo->mTexX;
		unsigned short ty = (unsigned short)pPartySkin->mSkinInfo->mTexY;
		unsigned short w = (unsigned short)pPartySkin->mSkinInfo->mTexWidth;
		unsigned short h = (unsigned short)pPartySkin->mSkinInfo->mTexHeight;
		partyData->mPos.mX = (int)( data->mInitX / segLen * mOriginTexW );
		partyData->mPos.mY = (int)( mOriginTexH - ( data->mInitY / segLen * mOriginTexH ) );

		partyData->mOldX = partyData->mPos.mX;
		partyData->mOldY = partyData->mPos.mY;
		partyData->mSize.mWidth = w;
		partyData->mSize.mHeight = h;

		partyData->mpImage->SetTextureRect( tx, ty, tx + w, ty + h );
		partyData->mpImage->SetScreenRect( cUIRect( partyData->mPos.mX, partyData->mPos.mY, 
													partyData->mPos.mX + w, partyData->mPos.mY + h ) );

		/// 삽입
		mImageDataList.PushBack( partyData );
	}

	if( mNeedUpdate == false )
	{
		mOldX = 0;
		mOldY = 0;
		mNeedUpdate = true;
	}
}

void cSmallMiniMapWindow::RemovePartyUser( unsigned long userIndex )
{
	cImageDataList::cIterator i = mImageDataList.Begin();
	cImageDataList::cIterator end = mImageDataList.End();
	for( ; i != end; ++i )
	{
		sBaseImageData* p = (sBaseImageData*)(*i);
		if( p && p->mType == eTYPE_PARTY )
		{
			sUserImageData* data = (sUserImageData*)p;
			if( data && data->mUserIndex == userIndex )
			{
				SAFE_DELETE( data->mpImage );
				SAFE_DELETE( data );
				mImageDataList.Erase(i);
				break;
			}
		}
	}
}

/// 전체 데이터 삭제
void cSmallMiniMapWindow::ClearParty()
{
	cImageDataList::cIterator i = mImageDataList.Begin();
	cImageDataList::cIterator end = mImageDataList.End();
	for( ; i != end; )
	{
		sBaseImageData* p = (sBaseImageData*)(*i);
		if( p && p->mType == eTYPE_PARTY )
		{
			sUserImageData* data = (sUserImageData*)p;
			if( data )
			{
				SAFE_DELETE( data->mpImage );
				SAFE_DELETE( data );
			}

			i = mImageDataList.Erase(i);
		}
		else
			++i;
	}
}

void cSmallMiniMapWindow::SetPosParty( unsigned long userIndex, float posX, float posY )
{
	cNaviMesh* navi = WORLDMAN->GetNaviMesh();
	if( !navi )
	{
		assert(0);
		return;
	}

	float segLen = navi->GetSegmentLength();

	cImageDataList::cIterator i = mImageDataList.Begin();
	cImageDataList::cIterator end = mImageDataList.End();
	for( ; i != end; ++i )
	{
		sBaseImageData* p = (sBaseImageData*)(*i);
		if( p && p->mType == eTYPE_PARTY )
		{
			sUserImageData* data = (sUserImageData*)p;
			if( data && data->mUserIndex == userIndex )
			{
				int newX = (int)( posX / segLen * mOriginTexW );
				int newY = (int)( mOriginTexH - ( posY / segLen * mOriginTexH ) );

				if( newX != data->mOldX ||
					newY != data->mOldY )
				{
					data->mPos.mX = newX;
					data->mPos.mY = newY;
					data->mOldX = newX;
					data->mOldY = newY;

					mNeedUpdate = true;
				}
				break;
			}
		}
	}
}


/// 미니맵 상에 파티원 show 여부 세팅
void cSmallMiniMapWindow::SetMapNumParty( int mapnum, unsigned long userIndex )
{	
	cImageDataList::cIterator i = mImageDataList.Begin();
	cImageDataList::cIterator end = mImageDataList.End();
	for( ; i != end; ++i )
	{
		sBaseImageData* p = (sBaseImageData*)(*i);
		if( p && p->mType == eTYPE_PARTY )
		{
			sUserImageData* data = (sUserImageData*)p;
			if( data && data->mUserIndex == userIndex )
			{
				data->mShow = ( mapnum == HERO->GetMapNum() ) ? true : false;
				data->mMapNum = mapnum;
				mNeedUpdate = true;
				break;
			}
		}
	}
}

/// 전장정보 세팅
void cSmallMiniMapWindow::AddDMUser( unsigned long userIndex, cStringT name, float posX, float posY )
{
	cUISkin* pSkin = UIMAN->GetSkin();
	if( !pSkin )
		return;

	cNaviMesh* navi = WORLDMAN->GetNaviMesh();
	if( !navi )
	{
		assert(0);
		return;
	}

	float segLen = navi->GetSegmentLength();

	cUINodeSkin* pDMUserSkin = pSkin->GetNodeSkin( "SmallMiniMap_PartyIn" );
	if( pDMUserSkin  )
	{
		sUserImageData* userData = new sUserImageData;
		if( !userData )
		{
			assert(0);
			return;
		}

		userData->mpImage = new cUITransformImage;
		userData->mpImage->SetTexture( pDMUserSkin->mpTexture );
		userData->mType = eTYPE_DEATHMATCH;
		userData->mMapNum = HERO->GetMapNum();
		userData->mUserIndex = userIndex;
		userData->mName = name;

		userData->mpInSkin = pDMUserSkin;
		userData->mpOutSkin = pSkin->GetNodeSkin( "SmallMiniMap_PartyOut" );
		if( !(userData->mpInSkin && userData->mpOutSkin) )
		{
			assert(0);
			return;
		}

		unsigned short tx = (unsigned short)pDMUserSkin->mSkinInfo->mTexX;
		unsigned short ty = (unsigned short)pDMUserSkin->mSkinInfo->mTexY;
		unsigned short w = (unsigned short)pDMUserSkin->mSkinInfo->mTexWidth;
		unsigned short h = (unsigned short)pDMUserSkin->mSkinInfo->mTexHeight;
		userData->mPos.mX = (int)( posX / segLen * mOriginTexW );
		userData->mPos.mY = (int)( mOriginTexH - ( posY / segLen * mOriginTexH ) );

		userData->mOldX = userData->mPos.mX;
		userData->mOldY = userData->mPos.mY;
		userData->mSize.mWidth = w;
		userData->mSize.mHeight = h;

		userData->mpImage->SetTextureRect( tx, ty, tx + w, ty + h );
		userData->mpImage->SetScreenRect( cUIRect( userData->mPos.mX, userData->mPos.mY, 
											userData->mPos.mX + w, userData->mPos.mY + h ) );

		/// 삽입
		mImageDataList.PushBack( userData );
	}

	if( mNeedUpdate == false )
	{
		mOldX = 0;
		mOldY = 0;
		mNeedUpdate = true;
	}
}

/// 전장정보 세팅
void cSmallMiniMapWindow::RemoveDMUser( unsigned long userIndex )
{
	cImageDataList::cIterator i = mImageDataList.Begin();
	cImageDataList::cIterator end = mImageDataList.End();
	for( ; i != end; ++i )
	{
		sBaseImageData* p = (sBaseImageData*)(*i);
		if( p && p->mType == eTYPE_DEATHMATCH )
		{
			sUserImageData* data = (sUserImageData*)p;
			if( data && data->mUserIndex == userIndex )
			{
				SAFE_DELETE( data->mpImage );
				SAFE_DELETE( data );
				mImageDataList.Erase(i);
				break;
			}
		}
	}
}

void cSmallMiniMapWindow::SetPosDMUser( unsigned long userIndex, float posX, float posY )
{
	cNaviMesh* navi = WORLDMAN->GetNaviMesh();
	if( !navi )
	{
		assert(0);
		return;
	}

	float segLen = navi->GetSegmentLength();

	cImageDataList::cIterator i = mImageDataList.Begin();
	cImageDataList::cIterator end = mImageDataList.End();
	for( ; i != end; ++i )
	{
		sBaseImageData* p = (sBaseImageData*)(*i);
		if( p && p->mType == eTYPE_DEATHMATCH )
		{
			sUserImageData* data = (sUserImageData*)p;
			if( data && data->mUserIndex == userIndex )
			{
				int newX = (int)( posX / segLen * mOriginTexW );
				int newY = (int)( mOriginTexH - ( posY / segLen * mOriginTexH ) );

				if( newX != data->mOldX ||
					newY != data->mOldY )
				{
					data->mPos.mX = newX;
					data->mPos.mY = newY;
					data->mOldX = newX;
					data->mOldY = newY;

					mNeedUpdate = true;
				}
				break;
			}
		}
	}
}

/// 노점상 정보 세팅
void cSmallMiniMapWindow::AddUserSell( cStringT name, int mapnum, float xpos, float ypos )
{
	/// 기존데이타 삭제
	if( mUserSellData )
		RemoveUserSell( mUserSellData );

	cUISkin* pSkin = UIMAN->GetSkin();
	if( !pSkin )
		return;

	cNaviMesh* navi = WORLDMAN->GetNaviMesh();
	if( !navi )
	{
		assert(0);
		return;
	}

	float segLen = navi->GetSegmentLength();

	/// 노점상 이미지 로드
	cUINodeSkin* pUserSellSkin = pSkin->GetNodeSkin( "SmallMiniMap_UsersellIn" );
	if( pUserSellSkin )
	{
		mUserSellData = new sUserSellImageData;
		if( !mUserSellData )
		{
			assert(0);
			return;
		}

		mUserSellData->mpImage = new cUITransformImage;
		mUserSellData->mpImage->SetTexture( pUserSellSkin->mpTexture );
		mUserSellData->mType = eTYPE_USERSELL;
		mUserSellData->mName = name;
		mUserSellData->mMapNum = mapnum;
		mUserSellData->mStartTime = THEAPP->GetWorldAccumTime();
		mUserSellData->mName = name;

		mUserSellData->mPos.mX = (int)( xpos / segLen * mOriginTexW );
		mUserSellData->mPos.mY = (int)( mOriginTexH - ( ypos / segLen * mOriginTexH ) );

		/// 맵번호가 다르면
		mUserSellData->mShow = ( mapnum == HERO->GetMapNum() ) ? true : false;

		mUserSellData->mpInSkin = pUserSellSkin;
		mUserSellData->mpOutSkin = pSkin->GetNodeSkin( "SmallMiniMap_UsersellOut" );
		if( !(mUserSellData->mpInSkin && mUserSellData->mpOutSkin) )
		{
			assert(0);
			return;
		}

		unsigned short tx = (unsigned short)pUserSellSkin->mSkinInfo->mTexX;
		unsigned short ty = (unsigned short)pUserSellSkin->mSkinInfo->mTexY;
		unsigned short w = (unsigned short)pUserSellSkin->mSkinInfo->mTexWidth;
		unsigned short h = (unsigned short)pUserSellSkin->mSkinInfo->mTexHeight;

		mUserSellData->mSize.mWidth = w;
		mUserSellData->mSize.mHeight = h;

		mUserSellData->mpImage->SetTextureRect( tx, ty, tx + w, ty + h );
		mUserSellData->mpImage->SetScreenRect( cUIRect( mUserSellData->mPos.mX, mUserSellData->mPos.mY, 
														mUserSellData->mPos.mX + w, mUserSellData->mPos.mY + h ) );

		/// 삽입
		mImageDataList.PushBack( mUserSellData );
	}

	if( mNeedUpdate == false )
	{
		mOldX = 0;
		mOldY = 0;
		mNeedUpdate = true;
	}
}

void cSmallMiniMapWindow::RemoveUserSell( sBaseImageData* data )
{
	cImageDataList::cIterator i = mImageDataList.Begin();
	cImageDataList::cIterator end = mImageDataList.End();
	for( ; i != end; ++i )
	{
		sBaseImageData* p = (sBaseImageData*)(*i);
		if( p && p == data && p->mType == eTYPE_USERSELL )
		{
			SAFE_DELETE( p->mpImage );
			SAFE_DELETE( p );
			mImageDataList.Erase(i);
			break;
		}
	}

	mUserSellData = 0;
}

/// 애니메이션 갱신
void cSmallMiniMapWindow::UpdateQuestAni( sNpcImageData* data, unsigned long accumTime )
{
	if( !data )
		return;

	sAniParam* aniParam = data->mAniParam;
	if( !aniParam )
		return;

	aniParam->mAccumTime = accumTime;
	unsigned long elasedTime = aniParam->mAccumTime - aniParam->mLastAccumTime;
	if( elasedTime > aniParam->mTimeOut )
	{
		// 텍스쳐 좌표 갱신
		aniParam->mCurFrame++;

		/// 프레임을 넘어가면 초기화
		if( aniParam->mCurFrame >= aniParam->mFrame )
			aniParam->mCurFrame = 0;

		/// 텍스쳐 좌표 세팅
		unsigned int tx = aniParam->mTexX + ( aniParam->mCurFrame * aniParam->mWidth );
		unsigned int ty = aniParam->mTexY;

		if( data->mpAniImage )
			data->mpAniImage->SetTextureRect( tx, ty, tx + aniParam->mWidth, ty + aniParam->mHeight );

		// 갱신 시간 저장
		aniParam->mLastAccumTime = aniParam->mAccumTime;
	}
}

void cSmallMiniMapWindow::SetImagePercent( float per )
{
	mPercent = per;

	if( mPercent > MAX_PERCENT )
		mPercent = MAX_PERCENT;
	if( mPercent < MIN_PERCENT )
		mPercent = MIN_PERCENT;
}

