Event Manager

이벤트매니져의 공개 함수는 다음과 같다.

struct EventHandler;
class MyPropertySystem;

using EntryName = std::string;  //to remove event
using EventId = std::string;
using EventFunc = std::function<bool(MyPropertySystem)>;
using EventList = std::list<EventHandler>;
using EventMap = std::unordered_map<EventId, EventList>;
using EnteryMap = std::unordered_map<EntryName, EventId>;

class EventManager
{
private:
    EventMap m_eventMap;
    EnteryMap m_entryMap;
public:
    EventManager();
    bool AddEvent(EventId eventId, EventFunc eventFunc);
    bool AddEvent(EventId eventId, EventFunc eventFunc, EntryName entryName);
    bool RemoveEvent(EntryName entryName);
    void Update(EventId eventId, const MyPropertySystem& param);

AddEvent

이벤트를 등록한다.
eventId 중복될수 있으며, entryName은 고유 키이다.
entryName이 생략 되면 eventId와 동일한 값이 저장된다. 이때, eventId는 중복 될수 없다.

RemoveEvent

entryName으로 이벤트를 제거한다.

Update

이벤트 리스트에 등록된 함수를 호출한다.

코드 설명

EventMap m_eventMap
EventId를 키로 EventList를 데이터로 저장한다.

EnteryMap m_entryMap
EntryName을 키로 EventId를 데이터로 저장한다.
m_entryMap은 RemoveEvent시 m_eventMap에서 제거하기 위해서 필요하다.

MyPropertySystem

속성 추가
    MyPropertySystem prop;
    prop.GetValue<int>("Damage") = 100;
    prop.GetValue<float>("hp") = 1000;
    prop.GetValue<std::string>("class") = "worrior";
    prop.GetValue<bool>("alive") = true;

사용 가능한 타입은 int, float, std::string, bool이다.

속성 사용
PropertyList list = prop.GetList();
for (auto p : list)
{
    std::cout << " : " <<  p->GetName() << " : " << p->GetTypeName() << " : " << ToString(p) << std::endl;
}
return 0;


EventManager와 MyPropertySystem을 같이 사용한 코드

struct Car
{
    std::string name;
    int ShowPrice(MyPropertySystem propertySystem)
    {
        PropertyList list = propertySystem.GetList();
        for (auto p : list)
        {
            std::cout << name << " : " <<  p->GetName() << " : " << p->GetTypeName() << " : " << ToString(p) << std::endl;
        }
        return 0;
    }

    int ShowLowPrice(MyPropertySystem propertySystem)
    {
        PropertyList list = propertySystem.GetList();
        for (auto p : list)
        {
            std::cout << name << " : "  << p->GetName() << " : " << p->GetTypeName() << " : " << ToString(p) << std::endl;
        }
        return 0;
    }
}

void DoTest()
{
    std::cout << "============ Test AddEvent: add NormalPrice, LowPrice ============" << std::endl;
    EventManager manager;
    Car car1;
    car1.name = "an electric car";
    Car car2;
    car2.name= "a gasoline car";

    manager.AddEvent("Update_Price", std::bind(&Car::ShowPrice, &car1, _1), "NormalPrice");
    manager.AddEvent("Update_Price", std::bind(&Car::ShowLowPrice, &car2, _1), "LowPrice");
    MyPropertySystem param;
    param.GetValue<int>("price") = 1000;
    param.GetValue<bool>("isAll") = true;
    manager.Update("Update_Price", param);

    std::cout << "============ Test RemoveEvent : remove NormalPrice ============" << std::endl;
    manager.RemoveEvent("NormalPrice");

    MyPropertySystem param1;
    param1.GetValue<int>("price") = 100;
    param1.GetValue<float>("percent") = 50.5f;

    manager.Update("Update_Price", param1);
}

결과)
============ Test AddEvent: add NormalPrice, LowPrice ============
an electric car : price : int : 1000
an electric car : isAll : bool : 1
a gasoline car : price : int : 1000
a gasoline car : isAll : bool : 1
============ Test RemoveEvent : remove NormalPrice ============
a gasoline car : price : int : 100
a gasoline car : percent : float : 50.500000

소스 파일 다운로드
EventManager.h
EventManager.cpp
EventTest.cpp

property/PropertyType.h
property/MyProperty.h
property/MyPropertySystem.h
property/MyPropertySystem.cpp

프로젝트 다운로
EventTest.zip




참고)
속성 코드 수정
http://dolphin.ivyro.net/file/cplusplus/entity01.html

특수화 템플릿 정적 멤버 초기화
https://stackoverflow.com/questions/42743048/c-template-the-static-member-in-a-global-object-is-not-initialized

template <class T>
class PropertyType
{
public :
    // Returns type ID associated with the templatized type.
    static  ePropertyType GetTypeID()
    {
        return ms_typeID;
    }
    static  const char* GetTypeName()
    {
         return ms_typeName;
    }

private:
    static  ePropertyType ms_typeID;
    static  const char* ms_typeName;
};

template<> ePropertyType PropertyType<bool>::ms_typeID = ept_bool;
빌드는 되지만 다음의 오류가 뜬다.

E1449    멤버 "PropertyType<T>::ms_typeID [대상 T=bool]"의 명시적 특수화는 처음 사용하기 전에 나타나야 합니다().

다음과 같이 정적 멤버 초기화 대신 정적멤버를 사용하는 함수를 초기화 해주면 된다.

template<> ePropertyType PropertyType<bool>::GetTypeID() { return ept_bool; }
template<> const char* PropertyType<bool>::GetTypeName() { return static_cast<const char*>("bool"); }