UI

김태훈·2024년 1월 11일
0

Win32API

목록 보기
20/24
post-custom-banner

UI

카메라의 영향을 받아야 하는 것도 있고
받지 않아야 하는 것도 있다

계층 구조를 가진다
부모ul,자식ul
그 자식이 자식 ul를 가질수 있다

scene한테는 최상위 부모ul만 넣어준다

부모와 자식을 둘다 알수 있게 쌍방향 연결한다

update,render

본인 업데이트를 하고 자식을 업데이트 시켜준다
rendering 또한 마찬가지이다
void CUI::update_child()
{
for (size_t i = 0; i < m_vecChildUI.size(); ++i)
m_vecChildUI[i]->update();

}
void CUI::update()
{
update_child();

}

final update

자식이 setpos 할때는 부모로 부터 offset할지 set하는 것이다

CObject::finalupdate();

m_vFinalPos = GetPos();
	
if (GetParent()) 
{
	Vec2 vParentPos = GetParent()->GetFinalPos();
	m_vFinalPos += vParentPoss; //자신이 자식이라면 부모 위치를 더한다
}

소멸자

본인이 지워질때 자기의 자식 UI를 지워준다

Mouse On

마우스가 자기 자신 위에 올라왔는지 확인한다(카메라의 영향에 따라 다름)
final update때 마다 확인

void CUI::IsMouseOnCheck()
{
	Vec2 MousePos = MOUSE_POS;
	if (m_bAffectedCam)
		MousePos = CCamera::GetInst()->GetRealPos(MousePos);
	
	if (MousePos.x >= m_vFinalPos.x && MousePos.x <= m_vFinalPos.x + GetScale().x
		&& MousePos.y >= m_vFinalPos.y && MousePos.y <= m_vFinalPos.y + GetScale().y)
	{
		m_bMouseOn = true; 
	}

	else 
	{
		m_bMouseOn = false;
	}

}

PanelUI

UI의 자식 UI

생성자

UI에서 기본 생성자를 없애고
카메라 영향을 매개변수로 하는 생성자를 만들었다

부모의 기본 생성자가 없기 때문에
PanelUI는 부모UI의 생성자를 지정해줘야 한다
CPanelUI::CPanelUI()
:CUI(false),m_bMouseOnDown(false)
{

}

UI이벤트

1.마우스가 내 UI에 올라왓을때

  1. 해당 UI를 눌렀을때

  2. 해당 UI위에서 떼졌을때

  3. 클릭 된 경우
    범위 안에서 다운과 업이 발생했을때를 뜻한다

이 4개의 이벤트들을 virtual함수로 하여 자식UI들이 활용 할수 있도록 함

카메라 영향을 받는지 안받는지를 스스로 알아야 한다

UI Mgr

UI이벤트들을 체크 해준다
상황 체크 후 이벤트 호출

if (TargetUI != nullptr) 
{
	if (bLbtnTap)
		{		
				TargetUI->MouseLbtnDown(); 
		}

	else if (TargetUI->IsMouseOn() && TargetUI->m_bLbtnDown && bLbtnAway) 
				{ 
					TargetUI->MouseLbtnClicked(); 
					TargetUI->m_bLbtnDown = false; 
				}

	else if (bLbtnAway) { TargetUI->MouseLbtnUp(); }
		
}

Target UI 찾기

자식 UI의 이벤트가 호출되면
부모 UI의 이벤트는 호출되지 않는다

  1. 부모 포함 모든 자식 UI들을 검사한다
  2. 타겟 UI들 중 계층이 더 낮은 UI일수록 타겟 UI의 우선순위이다

레벨순회를 진행해야할 필요가 있다 ,모든 자식을 순회해야 한다

이러한 레벨순회에서는 que자류구조를 사용한다

부모가 먼저 들어간후 꺼낸뒤 자기 자식을 넣은 다음
들어간 자식 중 첫번째가 나올때 똑같이 자기 자식을 넣는 방식이라면 모든 자식들을 넣을수 있다

리스트를 활용하여 큐처럼 제한하여 만든다

큐안에 아무것도 없을때 순회가 끝난다

CUI* CUIMgr::GetTargetUI(CUI* _pparentUI)
{
	list<CUI*>quee;
	vecNoneTarget.clear();
	quee.clear();

	quee.push_back(_pparentUI);
	CUI* pTargetUI=nullptr;

	while (!quee.empty()) //타겟인지 체크하기
	{
		//데이터 하나 꺼내기
		CUI*pUI= quee.front();
		quee.pop_front();

		if (pUI->IsMouseOn())
		{
			pTargetUI = pUI;
			for (size_t i = 0; i < pUI->m_vecChildUI.size(); ++i)
				quee.push_back(pUI->m_vecChildUI[i]);

		}

		else { vecNoneTarget.push_back(pUI);}
	}
	//타겟이 아닌 애들은 false로 만들기
	for (size_t i = 0; i < vecNoneTarget.size(); ++i)
	{
		vecNoneTarget[i]->m_bMouseOn = false;
		
	}
	return pTargetUI;
}
CUI* TargetUI = GetTargetUI(m_pForcusedUI);
		//각 Lbtn 상황에 맞는 함수 실행
	if (TargetUI != nullptr) 
	{
		if (bLbtnTap) 
		{ TargetUI->m_bLbtnDown = true; TargetUI->MouseLbtnDown(); }
			
		 else if (TargetUI->IsMouseOn() && TargetUI->m_bLbtnDown && bLbtnAway)
			 { 
				TargetUI->MouseLbtnClicked(); 
				TargetUI->m_bLbtnDown = false;
			 }

		else if (bLbtnAway) { TargetUI->MouseLbtnUp(); }
		
	}

Forcused UI

부모UI 중 forcused UI를 찾기

벡터에 쌓인대로 렌더링,
가장 마지막이 가장 바깥쪽에 렌더링

포커싱 받은 얘가 맨 뒤로 가면 된다!

검사 순서와 렌더링 순서는 반대

나중에 눌린얘가 포커스 되는게 맞으므로 검사 순서를 그래도 하는것이 맞다

CUI* CUIMgr::GetForcusedUI()
{

CScene* pCurScene = CSceneMgr::GetInst()->Get_pCurScene();
vector<CObject*>&vecUI = pCurScene->Get_vecUI();//현재 씬의 UI그룹벡터 가져오기

vector<CObject*>::iterator Targetiter=vecUI.end();
vector<CObject*>::iterator iter=vecUI.begin();
bool bMousedown = KeySta_Check(KEY::LBTN, KEY_STATE::TAP);
CUI* pUI=nullptr;

if (!bMousedown && m_pForcusedUI)
	return m_pForcusedUI;
//Tap이 발생 했다는 전제
for (; iter != vecUI.end(); ++iter)//On된 것들 중의 가장 나중의 UI를 찾기
{
	if (((CUI*)(*iter))->IsMouseOn())
	{
		if (((CUI*)(*iter))->m_bLbtnTap)
		{
			pUI =(CUI*)(*iter);
			Targetiter = iter;
		}


	}
}	
if (Targetiter == vecUI.end())//찾아도 없으면
	return nullptr;

((CUI*)(*Targetiter))->m_bLbtnDown = true;

vecUI.erase(Targetiter);//그룹벡터에서 해당 iter erase
vecUI.push_back((CObject*)pUI); //맨 뒤에 넣기


return pUI;

}

forcused UI를 바꾸기

void CUIMgr::SetFcousedUI(CUI*_pUI)
{
if (m_pForcusedUI == _pUI|| _pUI == nullptr)
return;

CScene* pCurScene = CSceneMgr::GetInst()->Get_pCurScene();
vector<CObject*>& vecUI = pCurScene->Get_vecUI();
vector<CObject*>::iterator iter = vecUI.begin();
m_pForcusedUI = _pUI;
for (; iter != vecUI.end(); ++iter)
{
	if (m_pForcusedUI == *iter)
	{
		break;
	}
}

vecUI.erase(iter);
vecUI.push_back(m_pForcusedUI);

}

함수 포인터 사용

수 많은 이벤트들의 해당하는 함수를 따로 구현한다면
클래스마다 오버라이딩을 해줘야 해서 비효율적
함수 포인터로 함수를 받아서 실행 하자
btnUI에서 정의한것

typedef void (*BTN_FUNC)(DWORD_PTR, DWORD_PTR);

   void SetClickedCallBack(BTN_FUNC _pFunc, DWORD_PTR _param1, DWORD_PTR _param2) 
    {
         m_pFunc=_pFunc;
         m_param1 = _param1;
         m_param2 = _param2;
    }
//전역함수
void ScenChange(DWORD_PTR, DWORD_PTR) {
	ChangeScene(SCENE_TYPE::START);
}

btnStartUI->SetClickedCallBack(&ScenChange, 0, 0);
								
profile
복습을 위한 핵심 내용 및 모작
post-custom-banner

0개의 댓글