카메라의 영향을 받아야 하는 것도 있고
받지 않아야 하는 것도 있다
계층 구조를 가진다
부모ul,자식ul
그 자식이 자식 ul를 가질수 있다
scene한테는 최상위 부모ul만 넣어준다
부모와 자식을 둘다 알수 있게 쌍방향 연결한다
본인 업데이트를 하고 자식을 업데이트 시켜준다
rendering 또한 마찬가지이다
void CUI::update_child()
{
for (size_t i = 0; i < m_vecChildUI.size(); ++i)
m_vecChildUI[i]->update();
}
void CUI::update()
{
update_child();
}
자식이 setpos 할때는 부모로 부터 offset할지 set하는 것이다
CObject::finalupdate();
m_vFinalPos = GetPos();
if (GetParent())
{
Vec2 vParentPos = GetParent()->GetFinalPos();
m_vFinalPos += vParentPoss; //자신이 자식이라면 부모 위치를 더한다
}
본인이 지워질때 자기의 자식 UI를 지워준다
마우스가 자기 자신 위에 올라왔는지 확인한다(카메라의 영향에 따라 다름)
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;
}
}
UI의 자식 UI
UI에서 기본 생성자를 없애고
카메라 영향을 매개변수로 하는 생성자를 만들었다
부모의 기본 생성자가 없기 때문에
PanelUI는 부모UI의 생성자를 지정해줘야 한다
CPanelUI::CPanelUI()
:CUI(false),m_bMouseOnDown(false)
{
}
1.마우스가 내 UI에 올라왓을때
해당 UI를 눌렀을때
해당 UI위에서 떼졌을때
클릭 된 경우
범위 안에서 다운과 업이 발생했을때를 뜻한다
이 4개의 이벤트들을 virtual함수로 하여 자식UI들이 활용 할수 있도록 함
카메라 영향을 받는지 안받는지를 스스로 알아야 한다
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(); }
}
자식 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(); }
}
부모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;
}
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);