完整代码:https://github.com/DXT00/Hazel_study/tree/master/Event%20System
创建Event文件夹,包含4个.h文件
Event.h
#pragma once
#include "Hazel/Core.h"
#include<string>
#include<functional>
namespace Hazel {
//Events in Hazel is blocking,when an event happen
//,the whole APP stop and process that event.
enum class EventType {
None = 0,
WindowClose, WindowResize, WindowFocus, WindowsLostFocus, WindowMoved,
AppTick, AppUpdate, AppRender,
KeyPressed, KeyReleased,
MouseButtonPressed,MouseButtonRelease,MouseMoved,MouseScrolled
};
enum EventCategory {
None = 0,
EventCategoryApplication = BIT(0),
EventCategoryInput = BIT(1),
EventCategoryKeyBoard = BIT(2),
EventCategoryMouse = BIT(3),
EventCategoryMouseButton = BIT(4)
};
class HAZEL_API Event {
friend class EventDispatcher;
public:
virtual EventType GetEventype() const = 0;
virtual const char* GetName() const = 0;
virtual int GetCategoryFlags() const = 0;
virtual std::string ToString()const { return GetName(); }
inline bool IsInCategory(EventCategory category) {
return GetCategoryFlags() & category;
}
protected:
bool m_Handled = false; //Event是否被处理了
};
}
Core.h
#define BIT(x) (1<<x)
包含EventType 和 EventCategory
注意EventCategory使用bit field
enum EventCategory {
None = 0,
EventCategoryApplication = BIT(0), //0000 0000
EventCategoryInput = BIT(1), //0000 0001
EventCategoryKeyBoard = BIT(2), //0000 0010
EventCategoryMouse = BIT(3), //0000 0100
EventCategoryMouseButton = BIT(4) //0000 1000};
也即是:
EventCategoryMouseButton,EventCategoryMouse, EventCategoryKeyBoard,EventCategoryInput 属于 EventCategoryApplication
EventCategoryMouseButton,EventCategoryMouse, EventCategoryKeyBoard 属于 EventCategoryInput
EventCategoryMouseButton 属于 EventCategoryMouse
比如 flags = 0000 0111时 ,
flags&EventCategoryMouse>0
flags&EventCategoryKeyBoard>0
flags&EventCategoryInput>0
所以flags属于EventCategoryMouse,EventCategoryKeyBoard,EventCategoryInput 3种Events
KeyEvent.h
class HAZEL_API KeyPressedEvent : public KeyEvent {
public:
KeyPressedEvent(int keycode,int repeatCount): //keep track the amount of time that the key has repeated
KeyEvent(keycode), m_RepeatCount(repeatCount){}
inline int GetRepeatCount() const { return m_RepeatCount; }
std::string ToString()const override{
std::stringstream ss;
ss << "KeyPressedEvent: " << m_KeyCode << " (" << m_RepeatCount << "repeats)";
return ss.str();
}
static EventType GetStaticType() { return EventType::MouseScrolled; }
virtual EventType GetEventype()const override { return GetStaticType(); }
virtual const char* GetName() const override { return "MouseScrolled"; }
virtual int GetCategoryFlags() const override { return EventCategoryInput| EventCategoryMouse; }
private:
int m_RepeatCount;
};
这4行可以用宏来代替:
static EventType GetStaticType() { return EventType::MouseScrolled; }
virtual EventType GetEventype()const override { return GetStaticType(); }
virtual const char* GetName() const override { return "MouseScrolled"; }
virtual int GetCategoryFlags() const override { return EventCategoryInput| EventCategoryMouse; }
#define EVENT_CLASS_TYPE(type) static EventType GetStaticType() { return EventType::##type; }\
virtual EventType GetEventype()const override { return GetStaticType(); }\
virtual const char* GetName() const override { return #type; }#define EVENT_CLASS_CATEGORY(category) virtual int GetCategoryFlags() const override{ return category;}
四个event文件完整代码:
Event.h
#pragma once
#include "Hazel/Core.h"
#include<string>
#include<functional>
namespace Hazel {
//Events in Hazel is blocking,when an event happen
//,the whole APP stop and process that event.
enum class EventType {
None = 0,
WindowClose, WindowResize, WindowFocus, WindowsLostFocus, WindowMoved,
AppTick, AppUpdate, AppRender,
KeyPressed, KeyReleased,
MouseButtonPressed,MouseButtonReleased,MouseMoved,MouseScrolled
};
enum EventCategory {
None = 0,
EventCategoryApplication = BIT(0),
EventCategoryInput = BIT(1),
EventCategoryKeyBoard = BIT(2),
EventCategoryMouse = BIT(3),
EventCategoryMouseButton = BIT(4)
};
#define EVENT_CLASS_TYPE(type) static EventType GetStaticType() { return EventType::##type; }\
virtual EventType GetEventype()const override { return GetStaticType(); }\
virtual const char* GetName() const override { return #type; }
#define EVENT_CLASS_CATEGORY(category) virtual int GetCategoryFlags() const override{ return category;}
/*-----------------------------------------------------------------------*/
class HAZEL_API Event {
friend class EventDispatcher;
public:
virtual EventType GetEventype() const = 0;
virtual const char * GetName() const = 0;
virtual int GetCategoryFlags() const = 0;
virtual std::string ToString()const { return GetName(); }
inline bool IsInCategory(EventCategory category) {
return GetCategoryFlags() & category;
}
protected:
bool m_Handled = false; //Event是否被处理了
};
/*-----------------------------------------------------------------------*/
class EventDispatcher
{
template<typename T>
using EventFn = std::function<bool(T&)>; //输入参数类型 (T&),返回参数类型 bool
public:
EventDispatcher(Event& event)
:m_Event(event){}
template<typename T>
bool Dispatch(EventFn<T> func) {
if (m_Event.GetEventype() == T::GetStaticType()) {
m_Event.m_Handled = func(*(T*)&m_Event);
return true;
}
return false;
}
private:
Event &m_Event;
};
inline std::ostream& operator<<(std::ostream& os, const Event&e) {
return os << e.ToString();
}
}
event调度类:
class EventDispatcher
{
template<typename T>
using EventFn = std::function<bool(T&)>; //输入参数类型 (T&),返回参数类型 bool
public:
EventDispatcher(Event& event)
:m_Event(event){}
template<typename T>
bool Dispatch(EventFn<T> func) {
if (m_Event.GetEventype() == T::GetStaticType()) {
m_Event.m_Handled = func(*(T*)&m_Event);
return true;
}
return false;
}
private:
Event &m_Event;
};
Application.h
#pragma once
#include"Event.h"
#include <sstream>
namespace Hazel {
class HAZEL_API WindowResizeEvent :public Event
{
public:
WindowResizeEvent(unsigned int width, unsigned int height)
:m_Width(width), m_Height(height){}
inline unsigned int GetWidth() const{ return m_Width; }
inline unsigned int GetHeight() const { return m_Height; }
std::string ToString() const override {
std::stringstream ss;
ss << "WindowResizeEvent: " << GetWidth() << ", " << GetHeight();
return ss.str();
}
EVENT_CLASS_TYPE(WindowResize)
EVENT_CLASS_CATEGORY(EventCategoryApplication)
private:
unsigned int m_Width, m_Height;
};
class HAZEL_API WindowCloseEvent :public Event
{
public:
WindowCloseEvent() {}
EVENT_CLASS_TYPE(WindowClose)
EVENT_CLASS_CATEGORY(EventCategoryApplication)
};
class HAZEL_API AppTickEvent :public Event
{
public:
AppTickEvent() {}
EVENT_CLASS_TYPE(AppTick)
EVENT_CLASS_CATEGORY(EventCategoryApplication)
};
class HAZEL_API AppUpdateEvent :public Event
{
public:
AppUpdateEvent() {}
EVENT_CLASS_TYPE(AppUpdate)
EVENT_CLASS_CATEGORY(EventCategoryApplication)
};
class HAZEL_API AppRenderEvent :public Event
{
public:
AppRenderEvent() {}
EVENT_CLASS_TYPE(AppRender)
EVENT_CLASS_CATEGORY(EventCategoryApplication)
};
}
KeyEvent.h
#pragma once
#include "Event.h"
#include <sstream>
namespace Hazel {
class HAZEL_API KeyEvent:public Event //abstact
{
public:
inline int GetKeyCode()const { return m_KeyCode; }
EVENT_CLASS_CATEGORY(EventCategoryInput | EventCategoryKeyBoard)
protected:
KeyEvent(int keycode):m_KeyCode(keycode){} //you won't be able to make a KeyEvent
int m_KeyCode;
};
/*-----------------------------------------------------------------------*/
class HAZEL_API KeyPressedEvent : public KeyEvent {
public:
KeyPressedEvent(int keycode,int repeatCount): //keep track the amount of time that the key has repeated
KeyEvent(keycode), m_RepeatCount(repeatCount){}
inline int GetRepeatCount() const { return m_RepeatCount; }
std::string ToString()const override{
std::stringstream ss;
ss << "KeyPressedEvent: " << m_KeyCode << " (" << m_RepeatCount << "repeats)";
return ss.str();
}
EVENT_CLASS_TYPE(KeyPressed)
EVENT_CLASS_CATEGORY( EventCategoryInput | EventCategoryKeyBoard)
private:
int m_RepeatCount;
};
/*-----------------------------------------------------------------------*/
class HAZEL_API KeyReleasedEvent : public KeyEvent {
public:
KeyReleasedEvent(int keycode) : //keep track the amount of time that the key has repeated
KeyEvent(keycode) {}
std::string ToString()const override {
std::stringstream ss;
ss << "KeyReleasedEvent: " << m_KeyCode ;
return ss.str();
}
EVENT_CLASS_TYPE(KeyReleased)
EVENT_CLASS_CATEGORY(EventCategoryInput | EventCategoryKeyBoard)
};
}
MouseEvent.h
#pragma once
#include "Event.h"
#include <sstream>
namespace Hazel {
class HAZEL_API MouseMovedEvent : public Event
{
public:
MouseMovedEvent(float x,float y) : //keep track the amount of time that the key has repeated
m_MouseX(x), m_MouseY(y) {}
inline float GetX() const { return m_MouseX; }
inline float GetY() const { return m_MouseY; }
std::string ToString()const override {
std::stringstream ss;
ss << "MouseMovedEvent: " << GetX() << " , " << GetY();
return ss.str();
}
EVENT_CLASS_TYPE(MouseMoved);
EVENT_CLASS_CATEGORY(EventCategoryInput | EventCategoryMouse);
private:
int m_MouseX,m_MouseY;
};
class HAZEL_API MouseScrolledEvent : public Event
{
public:
MouseScrolledEvent(float xOffset, float yOffset) : //keep track the amount of time that the key has repeated
m_XOffset(xOffset), m_YOffset(yOffset) {}
inline float GetXOffset() const { return m_XOffset; }
inline float GetYOffset() const { return m_YOffset; }
std::string ToString()const override {
std::stringstream ss;
ss << "MouseScrolledEvent: " << GetXOffset() << " , " << GetYOffset();
return ss.str();
}
EVENT_CLASS_TYPE(MouseScrolled);
EVENT_CLASS_CATEGORY(EventCategoryInput | EventCategoryMouse);
/* static EventType GetStaticType() { return EventType::MouseScrolled; }
virtual EventType GetEventype()const override { return GetStaticType(); }
virtual const char* GetName() const override { return "MouseScrolled"; }
virtual int GetCategoryFlags() const override { return EventCategoryInput| EventCategoryMouse; }*/
private:
int m_XOffset, m_YOffset;
};
class HAZEL_API MouseButtonEvent : public Event
{
public:
inline int GetMouseButton() const { return m_Button; }
EVENT_CLASS_CATEGORY(EventCategoryInput | EventCategoryMouse);
protected:
MouseButtonEvent(int button)
:m_Button(button) {};
int m_Button;
};
class HAZEL_API MouseButtonPressedEvent : public MouseButtonEvent
{
public:
MouseButtonPressedEvent(int button)
:MouseButtonEvent(button) {};
std::string ToString()const override {
std::stringstream ss;
ss << "MouseButtonPressedEvent: " << m_Button;
return ss.str();
}
EVENT_CLASS_TYPE(MouseButtonPressed);
};
class HAZEL_API MouseButtonReleaseEvent : public MouseButtonEvent
{
public:
MouseButtonReleaseEvent(int button)
:MouseButtonEvent(button) {};
std::string ToString()const override {
std::stringstream ss;
ss << "MouseButtonReleaseEvent: " << m_Button;
return ss.str();
}
EVENT_CLASS_TYPE(MouseButtonReleased);
};
}
Appication.cpp里添加一个event:
#include "Application.h"
#include "Hazel/Event/ApplicationEvent.h"
#include "Hazel/Log.h"
namespace Hazel {
Application::Application()
{
}
Application::~Application()
{
}
void Application:: Run() {
WindowResizeEvent e(1280, 720);
HZ_TRACE(e);
while (true);
}
}
F5 run: