WIN32 UI

Date:     Updated:

카테고리:

태그:

19일 차

- Default
    - Client.h
    - framework.h
    - Resouce.h
    - targetver.h
- Engine
    1. Header
        1. define.h
        **2. struct.h**
        3. func.h
        4. func.cpp
        5. global.h
    2. Core
        1. CCore.cpp
 ****       2. CCore.h
    3. Manager
        1. KeyMgr
            1. CkeyMgr.cpp
            2. CkeyMgr.h
        2. TimeMgr
            1. CTimeMgr.cpp
            2. CTimeMgr.h
        3. SceneMgr
            1. CSceneMgr.cpp
            2. CSceneMgr.h
    		4. PathMgr
						1. CPathMgr.cpp
						2. CPathMgr.h
				5. ResMgr
						1. CResMgr.cpp
						2. CResMgr.h
	****			6. CollisionMgr
						1. CCollisionMgr.cpp
						2. CCollisionMgr.h
				7. EventMgr
						1. CEventMgr.cpp
****						2. CEventMgr.h
				**8. Camera
						1. CCamera.cpp**
						2. CCamera.h
				**9. CUIMgr.
						1. CUIMgr.cpp
						2. CUIMgr.h**
    4. Object
		    1. Monser
			    1. CMonster.cpp
			    2. CMonster.h
			  2. Missle
				  1. Missile.cpp
				  2. Missile.h
****				3. Player
					1. CPlayer.cpp
					2. Cplayer.h
				4. Tile
					1. CTile.cpp
					2. CTile.h
				**5. UI
					1. BtnUI
						1. CBtnUI.cpp
						2. CBtnUI.h
					2. PanelUI
						1. CPanelUI.cpp
						2. CPanelUI.h
					1. CUI.cpp
					2. CUI.h
        1. CObject.cpp
        2. CObject.h**
    5. Scene
        1. Scene_Start
            1. CScene_Start.cpp
            2. CScene_Start.h
        **2. Scene_Tool
		        1. CScene_Tool.cpp
		        2. CScene_Tool.h**
        **3. CScene.cpp
        4. CScene.h**
    6. Resource
		    1. Sound
		    2. Texture
			    1. CTexture.cpp
				  2. CTexture.h
		    3. CRes.cpp
		    4. CRes.h
		7. Component
				1. Collider
					1. CCollider.cpp
					2. CCollider.h
				2. Animator
					1. Animation
						1. CAnimation.cpp
						2. CAnimation.h
					1. CAnimator.cpp
					2. CAnimation.h
		8. Module
				1. SelectGDI.cpp
				2. SelectGDI.h
- 리소스 파일
- main.cpp
- pch.h.
  • 오늘은 UI에 대한 것을 했다. UI 1 ~ 7강까지 한 번에 다룬다.
  1. struct.h
	bool IsZero() {
		if (x == 0.f && y == 0.f) return true;
		else return false;
	}
  • IsZero함수 추가.
  • 카메라에서 에러가 뜨는 게 있어서…(카메라가 처음 초기화 될 때, 거리차이가 0이라서.)
  1. CCamera.cpp
void CCamera::CalDiff()
{
	//이전 LookAt과 현재 Look의 차이값을 보정해서 현재의 LookAt을 구한다.
	//방향 벡터.

	m_fAccTime += fDT;
	if (m_fAccTime >= m_fTime) {
		m_vCurLookAt = m_vLookAt;
	}
	else {
		Vec2 vLookDir = m_vLookAt - m_prevLookAt;

		if (!vLookDir.IsZero()) {
			m_vCurLookAt = m_prevLookAt + vLookDir.Normalize() * m_fSpeed * fDT;
		}
	}

	Vec2 vResolution = CCore::GetInstance()->GetResolution();
	Vec2 vCenter = vResolution / 2;

	//
	m_vDiff = m_vCurLookAt - vCenter;
	m_prevLookAt = m_vCurLookAt;
}
  1. CUI.h
#pragma once
#include "CObject.h"

//UI는 계층화 되어 있음 부모 UI, 자식 UI
//씬에는 그 계층화된 부모 UI만 넣어줌. 그러면 실제로는 연계된 UI가 들어감. 

class CUI :
    public CObject
{

private:
    vector<CUI*>        m_vecChildUI;
    CUI*                m_pParentUI;
    Vec2                m_vFinalPos;

    bool                m_bCamAffected;     //UI가 카메라의 영향을 받는 유무. 
    bool                m_bMouseOn;         //UI위에 마우스가 있는지.
    bool                m_bLbtnDown;        //UI에 왼쪽 버튼이 눌린 적이 있는지. 
public:

    Vec2 GetFinalPos() { return m_vFinalPos; }
    CUI* GetParent() { return m_pParentUI; }
    bool IsMouseOn() { return m_bMouseOn; }
    bool IsLbtnDown() { return m_bLbtnDown; }

    void AddChild(CUI* _pUI) 
    { 
        m_vecChildUI.push_back(_pUI);
        _pUI->m_pParentUI = this;
    }
    const vector<CUI*>& GetChildsUI() { return m_vecChildUI; }
public:
    virtual void update();
    virtual void finalupdate();
    virtual void render(HDC _dc);

private:
    void update_child();
    void finalupdate_child();
    void render_child(HDC _dc);

    void MouseOnCheck();

public:
    virtual void MouseOn();             //마우스가 UI위에 올라와 있을 때. 
    
    virtual void MouseLbtnDown();       //눌렸을 때.
    virtual void MouseLbtnUp();         //떼졌을 때.
    virtual void MouseLbtnClicked();    //클릭. 

    virtual CUI* Clone() = 0;

public:
    CUI(bool _bcamAff);
    CUI(const CUI& _origin);
    virtual ~CUI();

    friend class CUIMgr;
};

  • 계층 구조는 부모 UI에서 자식을 관리하는 형태이며, 버튼 클릭을 위한 변수, OFFSET을 통한 실제 위치, 카메라에 영향을 받는지(체력바랑 화면에 전역적인(메이플 인벤토리창…) 생각하면 될 거 같다
  1. CUI.cpp
#include "pch.h"
#include "CUI.h"

#include "CCamera.h"
#include "CkeyMgr.h"

#include "SelectGDI.h"

CUI::CUI(bool _bCamAff)
	: m_pParentUI(nullptr)
	, m_bCamAffected(_bCamAff)
	, m_bMouseOn(false)
{
}

CUI::CUI(const CUI& _origin)
	: CObject(_origin)
	, m_pParentUI(nullptr)
	, m_bCamAffected(_origin.m_bCamAffected)
	, m_bMouseOn(false)
	, m_bLbtnDown(false)
{
	//여기서 복사 생성자를 만들었어도, 부모에선 기본생성자로 들어가기 때문에.
	//따라서 복사 생성자를 명시적으로 넣어줘야만 함. 
	for (auto& child : _origin.m_vecChildUI) {
		AddChild(child->Clone());
	}
}

CUI::~CUI()
{
	Safe_Delete_Vec(m_vecChildUI);
}

void CUI::update()
{
	//child ui update
	update_child();
}

void CUI::finalupdate()
{
	CObject::finalupdate();
	m_vFinalPos = GetPos();
	//UI의 최종 좌표를 구한다.
	if (GetParent()) {
		Vec2 vParentPos = GetParent()->GetFinalPos();
		m_vFinalPos += vParentPos;
	}

	//UI 마우스 체크
	MouseOnCheck();

	finalupdate_child();
}

void CUI::render(HDC _dc)
{
	Vec2 vPos = GetFinalPos();
	Vec2 vScale = GetScale();

	if (m_bCamAffected) {
		vPos = CCamera::GetInstance()->GetRenderPos(vPos);
	}
	if (m_bLbtnDown) {
		SelectGDI select(_dc, PEN_TYPE::GREEN);
		Rectangle(_dc, (int)(vPos.x), (int)(vPos.y),
			(int)(vPos.x + vScale.x),
			(int)(vPos.y + vScale.y));
	}
	else {
		Rectangle(_dc, (int)(vPos.x), (int)(vPos.y),
			(int)(vPos.x + vScale.x),
			(int)(vPos.y + vScale.y));
	}
	//child ui render
	render_child(_dc);
}

void CUI::update_child()
{
	for (auto& child : m_vecChildUI) {
		child->update();
	}
}

void CUI::finalupdate_child()
{
	for (auto& child : m_vecChildUI) {
		child->finalupdate();
	}
}

void CUI::render_child(HDC _dc)
{
	for (auto& child : m_vecChildUI) {
		child->render(_dc);
	}
}

void CUI::MouseOn()
{
}

void CUI::MouseLbtnDown()
{
}

void CUI::MouseLbtnUp()
{
}

void CUI::MouseLbtnClicked()
{
}

void CUI::MouseOnCheck()
{
	Vec2 vMousePos = MOUSE_POS;
	Vec2 vScale = GetScale();

	if (m_bCamAffected) {
		vMousePos = CCamera::GetInstance()->GetRealPos(vMousePos);
	}
	

	if (m_vFinalPos.x <= vMousePos.x && vMousePos.x <=m_vFinalPos.x + vScale.x
		&& m_vFinalPos.y <= vMousePos.y && vMousePos.y <= m_vFinalPos.y + vScale.y) 
	{
		m_bMouseOn = true;
	}
	else {
		m_bMouseOn = false;
	}
}

//누르는 순간 그 UI로 렌더링 포커싱이 바뀌어야 함. -> 캔버스 UI들의 렌더링 순서를 해야만 함. 
  • update나 렌더러를 보면 부모에서 업데이트, 렌더링을 하고 자식에서 하는 형태가 된다.
  • 좌표는 부모 좌표에 자신의 오프셋을 추가로 계산해주는 식이다.
  1. CObject.cpp
void CObject::finalupdate()
{
	if (m_pCollider) m_pCollider->finalupdate();
	if (m_pAnimator) m_pAnimator->finalupdate();
}
  • finalupdate에 애니메이트 업데이트를 넣어주었다.
  1. CAnimator.cpp
void CAnimator::update()
{

}

void CAnimator::finalupdate()
{
	if (nullptr != m_pCurAnim) {
		m_pCurAnim->update();

		if (m_bRepeat && m_pCurAnim->IsFinish()) {
			m_pCurAnim->SetFrame(0);
		}
	}
}
  • update에 있던 것을 finalupdate에 옮겼다.
  1. CPanelUI.h
#pragma once
#include "CUI.h"
class CPanelUI :
    public CUI
{

private:
    Vec2        m_vDragStart;

public:

    virtual void update();
    virtual void MouseOn();
    virtual void MouseLbtnDown();
    virtual void MouseLbtnUp();

    CLONE(CPanelUI)

public:
    CPanelUI();
    ~CPanelUI();
};

  • m_vDragStart는 UIPanel의 이동(마우스로 드래그)을 위한 변수이다.
  1. CPanelUI.cpp
#include "pch.h"
#include "CPanelUI.h"
#include "CkeyMgr.h"

CPanelUI::CPanelUI()
	: CUI(false)
{

}

CPanelUI::~CPanelUI() {

}

void CPanelUI::update()
{
}

void CPanelUI::MouseOn()
{
	if (IsLbtnDown()) {
		Vec2 vDiff = MOUSE_POS - m_vDragStart;

		Vec2 vCurPos = GetPos();
		vCurPos += vDiff;
		SetPos(vCurPos);

		m_vDragStart = MOUSE_POS;
	}
}

void CPanelUI::MouseLbtnDown()
{
	//패널 UI는 드래그해서 이동 가능하게 해야함. 
	//누른 순간에 기억을 해서 그걸 좌표를 기억하고, 움직인 좌표를 계산하여 똑같은 거리만큼 이동시키면 되는 것. 
	m_vDragStart = MOUSE_POS;
}

void CPanelUI::MouseLbtnUp()
{
}
  • MouseOn일때, 그리고 버튼이 클릭되고 있을 때 이동시켜준다.
  1. CBtnUI.h
#pragma once
#include "CUI.h"

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

class CBtnUI :
    public CUI
{

private:
    //함수 포인터를 불러와서 버튼이 눌렸을 때 그걸 씀.
    BTN_FUNC    m_pFunc;
    DWORD_PTR   m_param1;
    DWORD_PTR   m_param2;

public:
    virtual void MouseOn();
    virtual void MouseLbtnDown();
    virtual void MouseLbtnUp();
    virtual void MouseLbtnClicked();

    void SetClickedCallBack(BTN_FUNC _pFunc, DWORD_PTR _param1, DWORD_PTR _param2) {
        m_pFunc = _pFunc;
        m_param1 = _param1;
        m_param2 = _param2;
    }

    CLONE(CBtnUI)

public:
    CBtnUI();
    ~CBtnUI();
};

  • 버튼마다 고유한 기능은 함수 포인터로 처리한다
  1. CBtnUI.cpp
#include "pch.h"
#include "CBtnUI.h"

CBtnUI::CBtnUI()
	: CUI(false)
{
}

CBtnUI::~CBtnUI()
{
}

void CBtnUI::MouseOn()
{
}

void CBtnUI::MouseLbtnDown()
{
}

void CBtnUI::MouseLbtnUp()
{
}

//버튼마다 해야 할 일이 전부 다 다르지 않나?
//어떤 버튼은 저장, 로드, 레벨업등등... 다 다름. 
void CBtnUI::MouseLbtnClicked()
{
	if (nullptr != m_pFunc) {
		m_pFunc(m_param1, m_param2);
	}
}

  1. CScene.h
#pragma once

#include "global.h"
//전방선언하는 이유는 컴파일 속도에 영향을 주지 않기 위해. 
class CObject;

class CScene
{

private:
	vector<CObject*> m_arrObj[(UINT)GROUP_TYPE::END];		//벡터 안에 모든 오브젝트 집어 넣겠다. 이런 특성(요소)를 가진만큼 나눠주기.
	//달리말하면 그룹 갯수만큼 나눠주기.

	wstring			m_strName; //Scene 이름

	UINT			m_iTileX;		//타일 가로 개수
	UINT			m_iTileY;		//타일 세로 개수. 

public:
	void SetName(const wstring& _strName) { m_strName = _strName; }
	const wstring& GetName() { return m_strName; }

	UINT GetTileX() { return m_iTileX; }
	UINT GetTileY() { return m_iTileY; }

	virtual void update();
	virtual void finalupdate();
	virtual void render(HDC _dc);
	
	virtual void Enter() = 0;		//해당 Scene에 진입 시 호출.
	virtual void Exit() = 0;		//해당 Scene에 탈출 시 호출.

public:
	//클래스는 헤더에 구현하면 인라인 처리가 됨. 
	//따라서 함수 호출 비용이 사라짐. 
	void AddObject(CObject* _pObj, GROUP_TYPE _eType)
	{
		m_arrObj[(UINT)_eType].push_back(_pObj);
	}

	const vector<CObject*>& GetGroupObject(GROUP_TYPE _eType) 
	{
		return m_arrObj[(UINT)_eType];
	}

	vector<CObject*>& GetUIGroup() { return m_arrObj[(UINT)GROUP_TYPE::UI]; }

	void DeleteGroup(GROUP_TYPE _eGroup);
	void DeleteAll();
	void CreateTile(UINT _IXCount, UINT _IYCount);

public:
	CScene();

	//소멸자의 가상함수 해줘야함. 씬 매니저가 모든 Scene을 부모 포인터로 관리함.
	// CSceneMgr에서 씬을 소멸시킬때, 소멸자는 부모인 CScene만 호출됨.  
	virtual ~CScene();
};

  • UI GROUP만 반환해주는(CONST아님) Get추가 되었다.
  1. CScene_Tool.cpp
#include "pch.h"
#include "CScene_Tool.h"
#include "CkeyMgr.h"
#include "CSceneMgr.h"
#include "CTile.h"
#include "CCore.h"
#include "CResMgr.h"

#include "resource.h"
#include "CSceneMgr.h"
#include "CUI.h"
#include "CPanelUI.h"
#include "CBtnUI.h"
#include "CUIMgr.h"

void ChangeScene(DWORD_PTR, DWORD_PTR);

CScene_Tool::CScene_Tool()
{

}

CScene_Tool::~CScene_Tool()
{

}

void CScene_Tool::Enter()
{
	CreateTile(5, 5);
	Vec2 vResolution = CCore::GetInstance()->GetResolution();

	//UI가 무언가 역할을 수행하려면 클릭할 수 있어야만 함. 
	//전반적인 UI의 이벤트 설계를 해준다면 <- 특정 상황때 호출하는 함수가 명확

	CUI* pPanelUI = new CPanelUI;
	pPanelUI->SetName(L"ParentUI");
	pPanelUI->SetScale(Vec2(500.f, 300.f));
	pPanelUI->SetPos(Vec2(vResolution.x - pPanelUI->GetScale().x, 0.f));

	CBtnUI* pBtnUI = new CBtnUI;
	pBtnUI->SetName(L"ChildUI");
	pBtnUI->SetScale(Vec2(100.f, 40.f));
	pBtnUI->SetPos(Vec2(0.f, 0.f));
	//pBtnUI->SetClickedCallBack(ChangeScene, 0, 0);
	
	pPanelUI->AddChild(pBtnUI);

	AddObject(pPanelUI, GROUP_TYPE::UI);

	CUI* pClonePanel = pPanelUI->Clone();
	pClonePanel->SetPos(pClonePanel->GetPos() + Vec2(-500.f, 0.f));

	//이렇게 해주면 기능이야 같겠지만, 다른 포인터.
	((CBtnUI*)pClonePanel->GetChildsUI()[0])->SetClickedCallBack(ChangeScene, 0, 0);
	AddObject(pClonePanel, GROUP_TYPE::UI);

	m_pUI = pClonePanel;
	//Camera Look 지점.
	CCamera::GetInstance()->SetLookAt(vResolution / 2.f);
}

//씬 안에 존재하는 모든 것은 오브젝트. 
//1. 무언가를 입력 받을 수 있는 오브젝트를 만들면 되는 거 아닐까.
//값을 세팅하거나, 그런 게 있는데 윈도우에서 어느정도 기능을 제공하는 것이 있음. 
void CScene_Tool::Exit()
{
	//이전 씬에서 포커싱되었던 것을 UIMgr이 기억하고 있는데...
	//그래서 씬 바꿀때는 그런 거 다 해제 해야함. 
	DeleteAll();
}

void CScene_Tool::update()
{
	//부모쪽 기능 호출. 
	CScene::update();

	SetTileIdx();
	if (KEY_TAP(KEY::LSHIFT)) {
		CUIMgr::GetInstance()->SetFocusedUI(m_pUI);
	}
}

void CScene_Tool::SetTileIdx()
{
	if (KEY_TAP(KEY::LBTN)) {
		Vec2 vMousePos = MOUSE_POS;

		vMousePos = CCamera::GetInstance()->GetRealPos(vMousePos);

		int iTileX = GetTileX();
		int iTileY = GetTileY();

		int iCol = (int)vMousePos.x / TILE_SIZE;
		int iRow = (int)vMousePos.y / TILE_SIZE;

		if (vMousePos.x < 0.f || iTileX <= iCol
			|| vMousePos.y < 0.f || iTileY <= iRow) return;

		UINT iIdx = iRow * iTileX + iCol;

		const vector<CObject*>& vecTile = GetGroupObject(GROUP_TYPE::TILE);

		((CTile*)vecTile[iIdx])->AddImgIdx();
	}
}

void ChangeScene(DWORD_PTR, DWORD_PTR) {
	ChangeScene(SCENE_TYPE::START);
}

//=============================
// Tile Count Window Proc
//=============================

// 정보 대화 상자의 메시지 처리기입니다.

//__stdcall은 함수 호출 규약. 
INT_PTR __stdcall TileCountProc(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam)
{
	UNREFERENCED_PARAMETER(lParam);
	switch (message)
	{
	case WM_INITDIALOG:
		return (INT_PTR)TRUE;

	case WM_COMMAND:
		if (LOWORD(wParam) == IDOK)// ok나 X창 누르면
		{
			UINT iXCount = GetDlgItemInt(hDlg, IDC_EDIT1, nullptr, false);
			UINT iYCount = GetDlgItemInt(hDlg, IDC_EDIT2, nullptr, false);

			CScene* pCurScene = CSceneMgr::GetInstance()->GetCurScene();

			//이게 성공하면 정상적으로 캐스팅이 완료 
			CScene_Tool* pToolScene = dynamic_cast<CScene_Tool*>(pCurScene);
			assert(pToolScene);

			pToolScene->DeleteGroup(GROUP_TYPE::TILE);
			pToolScene->CreateTile(iXCount, iYCount);

			EndDialog(hDlg, LOWORD(wParam));    //Dialog 끝내기. 
			return (INT_PTR)TRUE;
		}
		else if (LOWORD(wParam) == IDCANCEL) {
			EndDialog(hDlg, LOWORD(wParam));    
			return (INT_PTR)TRUE;
		}
		break;
	}
	return (INT_PTR)FALSE;
}

  • 주요 변경점이라고 할 건 없지만, 중점은 UI를 생성하는 부분이다. UI의 계층 구조, 함수 포인터를 통한 기능 넣기 등등.
  1. CUIMgr.h
#pragma once

class CUI;
class CUIMgr
{
	SINGLE(CUIMgr)

private:
	CUI*		m_pFocusedUI;

public:
	void update();

	//해당 ui는 활성화 되면서 자신을 보라고 쏴줌. 
	void SetFocusedUI(CUI* _pUI);

private:
	CUI* GetFocusedUI();						//현재 포커싱 된 ui
	CUI* GetTargetedUI(CUI* _pParentUI);		//부모 UI내에서 실제로 타겟팅 된 ui를 찾아서 반환한다. 

};

  • 지금 누른(포커싱된) UI가 뭔지에 따라 렌더링과 입력(마우스)에 대한 구분이 다 달라진다.
  1. CUIMgr.cpp
#include "pch.h"
#include "CUIMgr.h"

#include "CSceneMgr.h"
#include "CScene.h"
#include "CUI.h"

#include "CkeyMgr.h"

CUIMgr::CUIMgr() 
	: m_pFocusedUI(nullptr)
{

}

CUIMgr::~CUIMgr() {

}

void CUIMgr::update()
{
	bool bLbtnTap = KEY_TAP(KEY::LBTN);
	bool bLbtnAway = KEY_AWAY(KEY::LBTN);
	// 1. FocusedUI 확인
	m_pFocusedUI = GetFocusedUI();

	if (!m_pFocusedUI) return;

	// 2. FocusedUI 내에서 부모 UI 포함, 자식 UI들 중 실제 타겟팅 된 UI를 가져온다. 
	CUI* pTargetUI = GetTargetedUI(m_pFocusedUI);

	if (nullptr != pTargetUI) {
		pTargetUI->MouseOn();

		if (bLbtnTap) {//눌리기까지 함. 
			pTargetUI->MouseLbtnDown();
			pTargetUI->m_bLbtnDown = true;
		}
		else if (bLbtnAway)
		{
			//이번에 안 눌렀는데, 해당 위에 있다.
			pTargetUI->MouseLbtnUp();
			if (pTargetUI->m_bLbtnDown) {
				pTargetUI->MouseLbtnClicked();
			}
			//왼쪽 버튼 떼면 눌렸던 체크를 다시 해제한다. 
			pTargetUI->m_bLbtnDown = false;
		}
	}	
}

//특정 키 눌렸을 때 어떤 UI를 보여줘야 한다. 
void CUIMgr::SetFocusedUI(CUI* _pUI)
{
	//이미 포커스 된 거나, nullptr값이 들어올 경우에. 
	if (m_pFocusedUI == _pUI || nullptr == _pUI) {
		m_pFocusedUI = _pUI;
		return;
	}

	m_pFocusedUI = _pUI;

	CScene* pCurScene = CSceneMgr::GetInstance()->GetCurScene();
	vector<CObject*>& vecUI = pCurScene->GetUIGroup();

	vector<CObject*>::iterator CUIIter = vecUI.begin();
	//왼쪽 버튼 TAP이 발생했다는 전제가 있는 UI들. 
	for (; CUIIter != vecUI.end(); CUIIter++) {
		if (m_pFocusedUI == *CUIIter) {
			break;
		}
	}

	vecUI.erase(CUIIter);
	vecUI.push_back(m_pFocusedUI);
}

CUI* CUIMgr::GetFocusedUI()
{
	CScene* pCurScene = CSceneMgr::GetInstance()->GetCurScene();
	vector<CObject*>& vecUI = pCurScene->GetUIGroup();

	bool bLbtnTap = KEY_TAP(KEY::LBTN);

	//기존 포커싱 UI를 받아두고 변경되었는지 확인한다. 
	CUI* pFocusedUI = m_pFocusedUI;

	//왼쪽 클릭이 없다면, Focus가 전환될 이유도 없기에 그냥 리턴. 
	if (!bLbtnTap) return pFocusedUI;

	vector<CObject*>::iterator targetIter = vecUI.end();
	vector<CObject*>::iterator CUIIter = vecUI.begin();
	//왼쪽 버튼 TAP이 발생했다는 전제가 있는 UI들. 
	for (; CUIIter != vecUI.end(); CUIIter++) {
		if (((CUI*)*CUIIter)->IsMouseOn()) {
			targetIter = CUIIter;
		}
	}

	//마우스가 눌리긴 했는데 허공을 눌렀을 경우, 받아갈 놈이 없음.
	if (vecUI.end() == targetIter) {
		return nullptr;
	}

	pFocusedUI = (CUI*)*targetIter;
	//계속 위에서 교체되다가 보면, 최종적인 Focus를 가져가는 UI가 된다. 
	//그리고 벡터 내부에서 순서를 바꿔줘야함. 

	vecUI.erase(targetIter);
	vecUI.push_back(pFocusedUI);

	return pFocusedUI;
}

CUI* CUIMgr::GetTargetedUI(CUI* _pParentUI)
{
	//1. 부모 UI포함, 모든 자식 UI를 검사. 그 안에서 가장 우선순위 높은 건 가장 아래 자식.(자식 아래까지 내려가야함)

	//2. 여러 UI가 타겟중일때, 우선 순위가 제일 높은 건 아래 자식. 
	//3. UI가 겹쳐있다면? <- UI 배치부터가 잘못되었다. 

	//이런 트리 구조 순회는 Level 순회라고 한다. -> 재귀함수 방식으로 하면 부모 -> 자식 -> 더 자식 순서대로. 
	//우리가 원하는 것은 더 깊게가 아닌, 같은 계층의 UI는 같이 검사. 
	//따라서 Queue를 활용한다. 
	//0(부모)에서 1,2(자식)넣고, 1에서 3,4,5.. 넣고.. 이러면 된다. 
	bool bLbtnAway = KEY_AWAY(KEY::LBTN);

	CUI* pTargetUI = nullptr;

	//계속 함수 올 때마다 할당하는 건 낭비.
	static list<CUI*> levelQueue;
	static vector<CUI*> vecNoneTarget;

	//그냥 비워준다.
	levelQueue.clear();
	vecNoneTarget.clear();

	levelQueue.push_back(_pParentUI);

	while (!levelQueue.empty()) {
		CUI* pUI = levelQueue.front();

		levelQueue.pop_front();

		// 큐에서 꺼내온 UI가 TargetUI인지 확인.
		if (pUI->IsMouseOn()) {
			if (nullptr != pTargetUI) {
				vecNoneTarget.push_back(pTargetUI);
			}

			pTargetUI = pUI;
		}
		else {
			vecNoneTarget.push_back(pUI);
		}

		const vector<CUI*>& vecChild = pUI->GetChildsUI();
		for (auto& child : vecChild) {
			levelQueue.push_back(child);
		}
	}
	if (bLbtnAway) {
		for (auto& noneChild : vecNoneTarget) {
			noneChild->m_bLbtnDown = false;
		}
	}

	return pTargetUI;
}

  • 주석에 전부 적어놓았다. 주요 기능은 한 UI를 눌렸을 때 포커싱(렌더링 우선순위, 선택 우선순위)과 한 UI계층 안에서 가장 아래 계층을 최우선순위로 두는 방식이다.
  1. CEventMgr.cpp
	case EVENT_TYPE::SCENE_CHANGE:
	{
		// lParam : Next Scene Type
		// wParam : NULL
		CSceneMgr::GetInstance()->ChangeScene((SCENE_TYPE)_eve.lParam);

		//이전 Scene에 대한 UI를 가리키고 있었기에 그거 해제. 
		CUIMgr::GetInstance()->SetFocusedUI(nullptr);
	}

  • SCENE변경이 일어날 때, 그것에 대한 FocusUI를 초기화 해줘야 한다.

WINAPI 카테고리 내 다른 글 보러가기

댓글 남기기