[DirectX] Res 매니저와 스마트 포인터


Res(리소스) 매니저 클래스 구현하기


// 헤더파일

#pragma once
#include "CSingleton.h"

#include "ptr.h"
#include "CRes.h"

class CMesh;

class CResMgr :
    public CSingleton<CResMgr>
{
private:
    map<wstring, Ptr<CRes>> m_arrRes[(UINT)RES_TYPE::END];

public:
    void init();

private:
    void CreateDefaultMesh();
    void CreateDefaultGraphicsShader();

public:
    template<typename T>
    Ptr<T> FindRes(const wstring& _strKey);


public:
    CResMgr();
    ~CResMgr();
};

// T가 무엇인지 알아내는 함수(전역함수)
RES_TYPE GetResType()
{
    const type_info& mesh = typeid(CMesh);
    const type_info& meshdata = typeid(CMeshData);
    const type_info& material = typeid(CMaterial);
    const type_info& texture = typeid(CTexture);
    const type_info& sound = typeid(CSound);
    const type_info& prefab = typeid(CPrefab);
    const type_info& gs = typeid(CGraphicsShader);
    const type_info& cs = typeid(CComputeShader);

    if (typeid(T).hash_code == mesh.hash_code())
        return RES_TYPE::MESH;

    if (typeid(T).hash_code == gs.hash_code())
        return RES_TYPE::GRAPHICS_SHADER;

    return RES_TYPE::END;
}

template<typename T>
inline Ptr<T> CResMgr::FindRes(const wstring& _strKey)
{   
    if (typeid(T).hash_code() == typeid(CMesh).hash_code())
    {
        map<wstring, Ptr<CRes>>::iterator iter = m_arrRes[(UINT)RES_TYPE::MESH].find(_strKey);
        if (iter == m_arrRes[(UINT)RES_TYPE::MESH].end())
            return nullptr;

        return (T*)iter->second.Get();
    }

    return nullptr;
}


// cpp 파일

#include "pch.h"
#include "CResMgr.h"

#include "CMesh.h"
#include "CGraphicsShader.h"

CResMgr::CResMgr()
{
}

CResMgr::~CResMgr()
{
}

void CResMgr::init()
{
	CreateDefaultMesh(); // 메쉬 생성
    CreateDefaultGraphicsShader(); // 쉐이더 생성
}

void CResMgr::CreateDefaultMesh()
{	
	vector<Vtx> vecVtx;
	vector<UINT> vecIdx;
	Vtx v;


	Ptr<CMesh> pMesh = nullptr;
	// =============
	// RectMesh 생성
	// =============	
	// 0 --- 1 
	// |  \  |
	// 3 --- 2
	v.vPos = Vec3(-0.5f, 0.5f, 0.5f);
	v.vColor = Vec4(1.f, 0.f, 0.f, 1.f);
	vecVtx.push_back(v);

	v.vPos = Vec3(0.5f, 0.5f, 0.5f);
	v.vColor = Vec4(0.f, 1.f, 0.f, 1.f);
	vecVtx.push_back(v);

	v.vPos = Vec3(0.5f, -0.5f, 0.5f);
	v.vColor = Vec4(0.f, 0.f, 1.f, 1.f);
	vecVtx.push_back(v);

	v.vPos = Vec3(-0.5f, -0.5f, 0.5f);
	v.vColor = Vec4(0.f, 0.f, 0.f, 1.f);
	vecVtx.push_back(v);

	vecIdx.push_back(0);
	vecIdx.push_back(2);
	vecIdx.push_back(3);

	vecIdx.push_back(0);
	vecIdx.push_back(1);
	vecIdx.push_back(2);

	pMesh = new CMesh;
	pMesh->SetKey(L"RectMesh");

	pMesh->Create(vecVtx.data(), (UINT)vecVtx.size(), vecIdx.data(), (UINT)vecIdx.size());
	m_arrRes[(UINT)RES_TYPE::MESH].insert(make_pair(pMesh->GetKey(), pMesh.Get()));
}

void CResMgr::CreateDefaultGraphicsShader()
{
	// Shader 생성
    Ptr<CGraphicsShader> pShader = nullptr;

    // Test Shader
	pShader = new CGraphicsShader;
    pShader->SetKey(L"TestShader");
	pShader->CreateVertexShader(L"shader\\test.fx", "VS_Test");
	pShader->CreatePixelShader(L"shader\\test.fx", "PS_Test");
    m_arrRes[(UINT)RES_TYPE::GRAPHICS_SHADER].insert(make_pair(pShader->GetKey(), pShader.Get()));

}



Res 매니저에서 사용하기 위한 스마트 포인터 구현


스마트 포인터는 클래스가 아닌 헤더파일로 구현한다.

#pragma once

template<typename T>
class Ptr
{
private:
    T*  m_Res;

public:
    T*  Get() const { return m_Res; }

    T*  operator -> ()
    {
        return m_Res;
    }

    void operator = (T* _Res)
    {
        if (m_Res != nullptr)
            m_Res->Release();
        
        m_Res = _Res;

        if (m_Res != nullptr)
            m_Res->AddRef();
    }

    void operator = (const Ptr<T>& _Res)
    {
        if (m_Res != nullptr)
            m_Res->Release();
        
        m_Res = _Res;

        if (m_Res != nullptr)
            m_Res->AddRef();
    }


    // 스마트 포인터는 사실 객체이므로 nullptr과 비교하기 위해서
    // 직접 구현을 해놓는다.

    bool operator == (T* _Other)
    {
        return m_Res == _Other;
    }

    bool operator != (T* _Other)
    {
        return m_Res != _Other;
    }

    bool operator == (const Ptr<T>& _Other)
    {
        return m_Res == _Other.m_Res;
    }

    bool operator != (const Ptr<T>& _Other)
    {
        return m_Res != _Other.m_Res;
    }

public:
    Ptr()
        : m_Res(nullptr)
    {

    }

    Ptr(T* _Res)
        : m_Res(_Res)
    {
        if (m_Res != nullptr)
            m_Res->AddRef();
    }

    Ptr(const Ptr<T>& _Res)
        : m_Res(_Res.m_Res)
    {
        if (m_Res != nullptr)
            m_Res->AddRef();
    }


    ~Ptr()
    {
        if (m_Res != nullptr)
        {
            m_Res->Release();
        }
    }
}


그리고 global.h에

#include <typeinfo>

를 추가한다.

CMeshRender에서의 코드 수정


메쉬와 쉐이더가 스마트 포인터를 사용하게 만들기 위해서 다음과 같이 코드를 작성한다.

// 헤더파일

#pragma once
#include "CComponent.h"


#include "CMesh.h"
#include "CGraphicsShader.h"
#include "ptr.h"




class CMeshRender :
    public CComponent
{
private:
    Ptr<CMesh>              m_pMesh;
    Ptr<CGraphicsShader>    m_pShader;

public:
    void SetMesh(Ptr<CMesh> _Mesh) { m_pMesh = _Mesh; }
    void SetShader(Ptr<CGraphicsShader> _Shader) { m_pShader = _Shader; }

    Ptr<CMesh> GetMesh() { return m_pMesh; }
    Ptr<CGraphicsShader>  GetShader() { return m_pShader; }


public:
    virtual void finaltick() override;
    void render();

    CLONE(CMeshRender);
public:
    CMeshRender();
    ~CMeshRender();
};



// cpp 파일

#include "pch.h"
#include "CMeshRender.h"

#include "CTransform.h"

CMeshRender::CMeshRender()
	: CComponent(COMPONENT_TYPE::MESHRENDER)	
	, m_pMesh(nullptr)
	, m_pShader(nullptr)
{
}

CMeshRender::~CMeshRender()
{
}

void CMeshRender::finaltick()
{
}

void CMeshRender::render()
{	
	if (nullptr == m_pMesh || nullptr == m_pShader)
		return;

	// Transform 에 UpdateData 요청
	Transform()->UpdateData();

	m_pShader->UpdateData();
	m_pMesh->render();
}


Test.cpp에서의 동작 코드 작성


이제 동작 코드는 다음과 같이 작성된다.

CGameObject* g_Obj = nullptr;


void Init()
{
	
}

void Tick()
{
	g_Obj->tick();
	g_Obj->finaltick();
}

void Render()
{
	g_Obj->render();
}

void Release()
{
	delete g_Obj;
}


왼쪽에서 비교를 하게 만들고 싶을 때


nullptr == class 형태로 왼쪽에서 비교할 수 있도록 만들고 싶을 때.

// Ptr 헤더에서 전역 operator로 다음과 같이 작성한다.

template<typename T>
bool operator == (void* _Res, const Ptr<T>& _Ptr)
{  
    return _Res == _Ptr.Get();
}

template<typename T>
bool operator != (void* _Res, const Ptr<T>& _Ptr)
{  
    return _Res != _Ptr.Get();
}

© 2022.07. by Wookey_Kim

Powered by Hydejack v7.5.2