feat(事件系统): 实现完整的事件处理框架
添加事件系统核心组件,包括事件基类、各种输入事件类型和事件分发机制。主要功能: - 新增基础事件类及键盘、鼠标、触摸、手柄等输入事件 - 在Actor类中实现事件监听和分发功能 - 在Scene类中添加事件处理逻辑 - 在Application类中集成SDL事件转换和分发 - 添加测试用例验证手柄事件处理 事件系统支持冒泡和优先级排序,为游戏交互提供基础支持
This commit is contained in:
@@ -4,8 +4,16 @@
|
|||||||
#include <frostbite2D/types/type_alias.h>
|
#include <frostbite2D/types/type_alias.h>
|
||||||
#include <frostbite2D/types/type_math.h>
|
#include <frostbite2D/types/type_math.h>
|
||||||
#include <frostbite2D/utils/intrusive_list.hpp>
|
#include <frostbite2D/utils/intrusive_list.hpp>
|
||||||
|
#include <frostbite2D/event/event.h>
|
||||||
|
#include <frostbite2D/event/key_event.h>
|
||||||
|
#include <frostbite2D/event/mouse_event.h>
|
||||||
|
#include <frostbite2D/event/touch_event.h>
|
||||||
|
#include <frostbite2D/event/joystick_event.h>
|
||||||
|
#include <frostbite2D/event/window_event.h>
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
#include <functional>
|
||||||
|
#include <unordered_map>
|
||||||
|
|
||||||
namespace frostbite2D {
|
namespace frostbite2D {
|
||||||
|
|
||||||
@@ -70,7 +78,43 @@ public:
|
|||||||
ActorList& GetChildren() { return children_; }
|
ActorList& GetChildren() { return children_; }
|
||||||
const ActorList& GetChildren() const { return children_; }
|
const ActorList& GetChildren() const { return children_; }
|
||||||
|
|
||||||
protected:
|
bool IsEventReceiveEnabled() const { return eventReceiveEnabled_; }
|
||||||
|
void EnableEventReceive() { eventReceiveEnabled_ = true; }
|
||||||
|
void DisableEventReceive() { eventReceiveEnabled_ = false; }
|
||||||
|
|
||||||
|
int32 GetEventPriority() const { return eventPriority_; }
|
||||||
|
void SetEventPriority(int32 priority) { eventPriority_ = priority; }
|
||||||
|
|
||||||
|
bool IsEventInterceptEnabled() const { return eventInterceptEnabled_; }
|
||||||
|
void EnableEventIntercept() { eventInterceptEnabled_ = true; }
|
||||||
|
void DisableEventIntercept() { eventInterceptEnabled_ = false; }
|
||||||
|
|
||||||
|
using EventCallback = std::function<bool(const Event&)>;
|
||||||
|
|
||||||
|
uint32 AddEventListener(EventType type, EventCallback callback);
|
||||||
|
bool RemoveEventListener(uint32 listenerId);
|
||||||
|
void ClearEventListeners();
|
||||||
|
|
||||||
|
virtual bool OnEvent(const Event& event);
|
||||||
|
|
||||||
|
virtual bool OnKeyDown(const KeyEvent& event);
|
||||||
|
virtual bool OnKeyUp(const KeyEvent& event);
|
||||||
|
virtual bool OnMouseDown(const MouseEvent& event);
|
||||||
|
virtual bool OnMouseUp(const MouseEvent& event);
|
||||||
|
virtual bool OnMouseMove(const MouseEvent& event);
|
||||||
|
virtual bool OnMouseWheel(const MouseEvent& event);
|
||||||
|
virtual bool OnTouchDown(const TouchEvent& event);
|
||||||
|
virtual bool OnTouchUp(const TouchEvent& event);
|
||||||
|
virtual bool OnTouchMove(const TouchEvent& event);
|
||||||
|
virtual bool OnJoystickAxis(const JoystickEvent& event);
|
||||||
|
virtual bool OnJoystickButtonDown(const JoystickEvent& event);
|
||||||
|
virtual bool OnJoystickButtonUp(const JoystickEvent& event);
|
||||||
|
virtual bool OnWindowResize(const WindowEvent& event);
|
||||||
|
|
||||||
|
bool DispatchEvent(const Event& event);
|
||||||
|
bool BubbleEvent(const Event& event);
|
||||||
|
|
||||||
|
protected:
|
||||||
void SetParent(Actor* parent) { parent_ = parent; }
|
void SetParent(Actor* parent) { parent_ = parent; }
|
||||||
void SetScene(Scene* scene) { scene_ = scene; }
|
void SetScene(Scene* scene) { scene_ = scene; }
|
||||||
|
|
||||||
@@ -99,6 +143,18 @@ private:
|
|||||||
mutable Transform2D worldTransform_;
|
mutable Transform2D worldTransform_;
|
||||||
mutable bool transformDirty_ = true;
|
mutable bool transformDirty_ = true;
|
||||||
|
|
||||||
|
bool eventReceiveEnabled_ = false;
|
||||||
|
int32 eventPriority_ = 0;
|
||||||
|
bool eventInterceptEnabled_ = false;
|
||||||
|
|
||||||
|
struct EventListener {
|
||||||
|
uint32 id;
|
||||||
|
EventType type;
|
||||||
|
EventCallback callback;
|
||||||
|
};
|
||||||
|
std::vector<EventListener> eventListeners_;
|
||||||
|
uint32 nextListenerId_ = 1;
|
||||||
|
|
||||||
void markTransformDirty();
|
void markTransformDirty();
|
||||||
void updateLocalTransform() const;
|
void updateLocalTransform() const;
|
||||||
void updateWorldTransform() const;
|
void updateWorldTransform() const;
|
||||||
|
|||||||
@@ -3,7 +3,9 @@
|
|||||||
#include <frostbite2D/core/window.h>
|
#include <frostbite2D/core/window.h>
|
||||||
#include <frostbite2D/graphics/camera.h>
|
#include <frostbite2D/graphics/camera.h>
|
||||||
#include <frostbite2D/types/type_alias.h>
|
#include <frostbite2D/types/type_alias.h>
|
||||||
|
#include <frostbite2D/event/event.h>
|
||||||
#include <string>
|
#include <string>
|
||||||
|
#include <memory>
|
||||||
|
|
||||||
namespace frostbite2D {
|
namespace frostbite2D {
|
||||||
|
|
||||||
@@ -175,6 +177,9 @@ private:
|
|||||||
*/
|
*/
|
||||||
void render();
|
void render();
|
||||||
|
|
||||||
|
std::unique_ptr<Event> convertSDLEvent(const SDL_Event& sdlEvent);
|
||||||
|
void dispatchEvent(const Event& event);
|
||||||
|
|
||||||
Window* window_ = nullptr;
|
Window* window_ = nullptr;
|
||||||
class Renderer* renderer_ = nullptr;
|
class Renderer* renderer_ = nullptr;
|
||||||
Camera* camera_ = nullptr;
|
Camera* camera_ = nullptr;
|
||||||
|
|||||||
63
Frostbite2D/include/frostbite2D/event/event.h
Normal file
63
Frostbite2D/include/frostbite2D/event/event.h
Normal file
@@ -0,0 +1,63 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <frostbite2D/types/type_alias.h>
|
||||||
|
|
||||||
|
namespace frostbite2D {
|
||||||
|
|
||||||
|
class Actor;
|
||||||
|
|
||||||
|
enum class EventType : int32 {
|
||||||
|
None = 0,
|
||||||
|
WindowClose,
|
||||||
|
WindowResize,
|
||||||
|
WindowFocus,
|
||||||
|
WindowMinimize,
|
||||||
|
WindowMaximize,
|
||||||
|
WindowRestore,
|
||||||
|
KeyDown,
|
||||||
|
KeyUp,
|
||||||
|
KeyText,
|
||||||
|
MouseMove,
|
||||||
|
MouseButtonDown,
|
||||||
|
MouseButtonUp,
|
||||||
|
MouseWheel,
|
||||||
|
TouchDown,
|
||||||
|
TouchUp,
|
||||||
|
TouchMove,
|
||||||
|
JoystickAxis,
|
||||||
|
JoystickBall,
|
||||||
|
JoystickHat,
|
||||||
|
JoystickButtonDown,
|
||||||
|
JoystickButtonUp,
|
||||||
|
Custom
|
||||||
|
};
|
||||||
|
|
||||||
|
class Event {
|
||||||
|
public:
|
||||||
|
virtual ~Event() = default;
|
||||||
|
|
||||||
|
virtual EventType getType() const = 0;
|
||||||
|
|
||||||
|
bool isHandled() const { return handled_; }
|
||||||
|
void setHandled(bool handled) { handled_ = handled; }
|
||||||
|
|
||||||
|
bool isPropagationStopped() const { return propagationStopped_; }
|
||||||
|
void stopPropagation() { propagationStopped_ = true; }
|
||||||
|
|
||||||
|
Actor* getSource() const { return source_; }
|
||||||
|
void setSource(Actor* actor) { source_ = actor; }
|
||||||
|
|
||||||
|
uint32 getTimestamp() const { return timestamp_; }
|
||||||
|
|
||||||
|
protected:
|
||||||
|
Event() = default;
|
||||||
|
Event(uint32 timestamp)
|
||||||
|
: timestamp_(timestamp) {}
|
||||||
|
|
||||||
|
bool handled_ = false;
|
||||||
|
bool propagationStopped_ = false;
|
||||||
|
Actor* source_ = nullptr;
|
||||||
|
uint32 timestamp_ = 0;
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
||||||
112
Frostbite2D/include/frostbite2D/event/joystick_event.h
Normal file
112
Frostbite2D/include/frostbite2D/event/joystick_event.h
Normal file
@@ -0,0 +1,112 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <frostbite2D/event/event.h>
|
||||||
|
#include <SDL2/SDL_joystick.h>
|
||||||
|
|
||||||
|
namespace frostbite2D {
|
||||||
|
|
||||||
|
class JoystickEvent : public Event {
|
||||||
|
public:
|
||||||
|
JoystickEvent(EventType type, uint32 timestamp, int32 deviceId)
|
||||||
|
: Event(timestamp)
|
||||||
|
, type_(type)
|
||||||
|
, deviceId_(deviceId) {}
|
||||||
|
|
||||||
|
EventType getType() const override {
|
||||||
|
return type_;
|
||||||
|
}
|
||||||
|
|
||||||
|
int32 getDeviceId() const { return deviceId_; }
|
||||||
|
|
||||||
|
protected:
|
||||||
|
EventType type_;
|
||||||
|
int32 deviceId_;
|
||||||
|
};
|
||||||
|
|
||||||
|
class JoystickAxisEvent : public JoystickEvent {
|
||||||
|
public:
|
||||||
|
JoystickAxisEvent(uint32 timestamp, int32 deviceId, uint8 axis, int16 value)
|
||||||
|
: JoystickEvent(EventType::JoystickAxis, timestamp, deviceId)
|
||||||
|
, axis_(axis)
|
||||||
|
, value_(value) {}
|
||||||
|
|
||||||
|
uint8 getAxis() const { return axis_; }
|
||||||
|
int16 getValue() const { return value_; }
|
||||||
|
|
||||||
|
float getNormalizedValue() const {
|
||||||
|
return static_cast<float>(value_) / 32767.0f;
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
uint8 axis_;
|
||||||
|
int16 value_;
|
||||||
|
};
|
||||||
|
|
||||||
|
class JoystickBallEvent : public JoystickEvent {
|
||||||
|
public:
|
||||||
|
JoystickBallEvent(uint32 timestamp, int32 deviceId, uint8 ball, int16 dx, int16 dy)
|
||||||
|
: JoystickEvent(EventType::JoystickBall, timestamp, deviceId)
|
||||||
|
, ball_(ball)
|
||||||
|
, dx_(dx)
|
||||||
|
, dy_(dy) {}
|
||||||
|
|
||||||
|
uint8 getBall() const { return ball_; }
|
||||||
|
int16 getDX() const { return dx_; }
|
||||||
|
int16 getDY() const { return dy_; }
|
||||||
|
|
||||||
|
private:
|
||||||
|
uint8 ball_;
|
||||||
|
int16 dx_;
|
||||||
|
int16 dy_;
|
||||||
|
};
|
||||||
|
|
||||||
|
class JoystickHatEvent : public JoystickEvent {
|
||||||
|
public:
|
||||||
|
JoystickHatEvent(uint32 timestamp, int32 deviceId, uint8 hat, uint8 value)
|
||||||
|
: JoystickEvent(EventType::JoystickHat, timestamp, deviceId)
|
||||||
|
, hat_(hat)
|
||||||
|
, value_(value) {}
|
||||||
|
|
||||||
|
uint8 getHat() const { return hat_; }
|
||||||
|
uint8 getValue() const { return value_; }
|
||||||
|
|
||||||
|
bool isCentered() const { return value_ == SDL_HAT_CENTERED; }
|
||||||
|
bool isUp() const { return (value_ & SDL_HAT_UP) != 0; }
|
||||||
|
bool isRight() const { return (value_ & SDL_HAT_RIGHT) != 0; }
|
||||||
|
bool isDown() const { return (value_ & SDL_HAT_DOWN) != 0; }
|
||||||
|
bool isLeft() const { return (value_ & SDL_HAT_LEFT) != 0; }
|
||||||
|
|
||||||
|
private:
|
||||||
|
uint8 hat_;
|
||||||
|
uint8 value_;
|
||||||
|
};
|
||||||
|
|
||||||
|
class JoystickButtonEvent : public JoystickEvent {
|
||||||
|
public:
|
||||||
|
JoystickButtonEvent(EventType type, uint32 timestamp, int32 deviceId, uint8 button)
|
||||||
|
: JoystickEvent(type, timestamp, deviceId)
|
||||||
|
, button_(button) {}
|
||||||
|
|
||||||
|
EventType getType() const override {
|
||||||
|
return type_;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint8 getButton() const { return button_; }
|
||||||
|
|
||||||
|
private:
|
||||||
|
uint8 button_;
|
||||||
|
};
|
||||||
|
|
||||||
|
class JoystickButtonDownEvent : public JoystickButtonEvent {
|
||||||
|
public:
|
||||||
|
JoystickButtonDownEvent(uint32 timestamp, int32 deviceId, uint8 button)
|
||||||
|
: JoystickButtonEvent(EventType::JoystickButtonDown, timestamp, deviceId, button) {}
|
||||||
|
};
|
||||||
|
|
||||||
|
class JoystickButtonUpEvent : public JoystickButtonEvent {
|
||||||
|
public:
|
||||||
|
JoystickButtonUpEvent(uint32 timestamp, int32 deviceId, uint8 button)
|
||||||
|
: JoystickButtonEvent(EventType::JoystickButtonUp, timestamp, deviceId, button) {}
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
||||||
208
Frostbite2D/include/frostbite2D/event/key_event.h
Normal file
208
Frostbite2D/include/frostbite2D/event/key_event.h
Normal file
@@ -0,0 +1,208 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <frostbite2D/event/event.h>
|
||||||
|
#include <SDL2/SDL_keyboard.h>
|
||||||
|
#include <string>
|
||||||
|
|
||||||
|
namespace frostbite2D {
|
||||||
|
|
||||||
|
enum class KeyCode {
|
||||||
|
Unknown = SDLK_UNKNOWN,
|
||||||
|
Return = SDLK_RETURN,
|
||||||
|
Escape = SDLK_ESCAPE,
|
||||||
|
Backspace = SDLK_BACKSPACE,
|
||||||
|
Tab = SDLK_TAB,
|
||||||
|
Space = SDLK_SPACE,
|
||||||
|
Exclaim = SDLK_EXCLAIM,
|
||||||
|
Quotedbl = SDLK_QUOTEDBL,
|
||||||
|
Hash = SDLK_HASH,
|
||||||
|
Percent = SDLK_PERCENT,
|
||||||
|
Dollar = SDLK_DOLLAR,
|
||||||
|
Ampersand = SDLK_AMPERSAND,
|
||||||
|
Quote = SDLK_QUOTE,
|
||||||
|
LeftParen = SDLK_LEFTPAREN,
|
||||||
|
RightParen = SDLK_RIGHTPAREN,
|
||||||
|
Asterisk = SDLK_ASTERISK,
|
||||||
|
Plus = SDLK_PLUS,
|
||||||
|
Comma = SDLK_COMMA,
|
||||||
|
Minus = SDLK_MINUS,
|
||||||
|
Period = SDLK_PERIOD,
|
||||||
|
Slash = SDLK_SLASH,
|
||||||
|
Num0 = SDLK_0,
|
||||||
|
Num1 = SDLK_1,
|
||||||
|
Num2 = SDLK_2,
|
||||||
|
Num3 = SDLK_3,
|
||||||
|
Num4 = SDLK_4,
|
||||||
|
Num5 = SDLK_5,
|
||||||
|
Num6 = SDLK_6,
|
||||||
|
Num7 = SDLK_7,
|
||||||
|
Num8 = SDLK_8,
|
||||||
|
Num9 = SDLK_9,
|
||||||
|
Colon = SDLK_COLON,
|
||||||
|
Semicolon = SDLK_SEMICOLON,
|
||||||
|
Less = SDLK_LESS,
|
||||||
|
Equals = SDLK_EQUALS,
|
||||||
|
Greater = SDLK_GREATER,
|
||||||
|
Question = SDLK_QUESTION,
|
||||||
|
At = SDLK_AT,
|
||||||
|
LeftBracket = SDLK_LEFTBRACKET,
|
||||||
|
Backslash = SDLK_BACKSLASH,
|
||||||
|
RightBracket = SDLK_RIGHTBRACKET,
|
||||||
|
Caret = SDLK_CARET,
|
||||||
|
Underscore = SDLK_UNDERSCORE,
|
||||||
|
Backquote = SDLK_BACKQUOTE,
|
||||||
|
a = SDLK_a,
|
||||||
|
b = SDLK_b,
|
||||||
|
c = SDLK_c,
|
||||||
|
d = SDLK_d,
|
||||||
|
e = SDLK_e,
|
||||||
|
f = SDLK_f,
|
||||||
|
g = SDLK_g,
|
||||||
|
h = SDLK_h,
|
||||||
|
i = SDLK_i,
|
||||||
|
j = SDLK_j,
|
||||||
|
k = SDLK_k,
|
||||||
|
l = SDLK_l,
|
||||||
|
m = SDLK_m,
|
||||||
|
n = SDLK_n,
|
||||||
|
o = SDLK_o,
|
||||||
|
p = SDLK_p,
|
||||||
|
q = SDLK_q,
|
||||||
|
r = SDLK_r,
|
||||||
|
s = SDLK_s,
|
||||||
|
t = SDLK_t,
|
||||||
|
u = SDLK_u,
|
||||||
|
v = SDLK_v,
|
||||||
|
w = SDLK_w,
|
||||||
|
x = SDLK_x,
|
||||||
|
y = SDLK_y,
|
||||||
|
z = SDLK_z,
|
||||||
|
CapsLock = SDLK_CAPSLOCK,
|
||||||
|
F1 = SDLK_F1,
|
||||||
|
F2 = SDLK_F2,
|
||||||
|
F3 = SDLK_F3,
|
||||||
|
F4 = SDLK_F4,
|
||||||
|
F5 = SDLK_F5,
|
||||||
|
F6 = SDLK_F6,
|
||||||
|
F7 = SDLK_F7,
|
||||||
|
F8 = SDLK_F8,
|
||||||
|
F9 = SDLK_F9,
|
||||||
|
F10 = SDLK_F10,
|
||||||
|
F11 = SDLK_F11,
|
||||||
|
F12 = SDLK_F12,
|
||||||
|
PrintScreen = SDLK_PRINTSCREEN,
|
||||||
|
ScrollLock = SDLK_SCROLLLOCK,
|
||||||
|
Pause = SDLK_PAUSE,
|
||||||
|
Insert = SDLK_INSERT,
|
||||||
|
Home = SDLK_HOME,
|
||||||
|
PageUp = SDLK_PAGEUP,
|
||||||
|
Delete = SDLK_DELETE,
|
||||||
|
End = SDLK_END,
|
||||||
|
PageDown = SDLK_PAGEDOWN,
|
||||||
|
Right = SDLK_RIGHT,
|
||||||
|
Left = SDLK_LEFT,
|
||||||
|
Down = SDLK_DOWN,
|
||||||
|
Up = SDLK_UP,
|
||||||
|
Numpad0 = SDLK_KP_0,
|
||||||
|
Numpad1 = SDLK_KP_1,
|
||||||
|
Numpad2 = SDLK_KP_2,
|
||||||
|
Numpad3 = SDLK_KP_3,
|
||||||
|
Numpad4 = SDLK_KP_4,
|
||||||
|
Numpad5 = SDLK_KP_5,
|
||||||
|
Numpad6 = SDLK_KP_6,
|
||||||
|
Numpad7 = SDLK_KP_7,
|
||||||
|
Numpad8 = SDLK_KP_8,
|
||||||
|
Numpad9 = SDLK_KP_9,
|
||||||
|
NumpadDecimal = SDLK_KP_DECIMAL,
|
||||||
|
NumpadDivide = SDLK_KP_DIVIDE,
|
||||||
|
NumpadMultiply = SDLK_KP_MULTIPLY,
|
||||||
|
NumpadMinus = SDLK_KP_MINUS,
|
||||||
|
NumpadPlus = SDLK_KP_PLUS,
|
||||||
|
NumpadEnter = SDLK_KP_ENTER,
|
||||||
|
NumpadEquals = SDLK_KP_EQUALS,
|
||||||
|
LShift = SDLK_LSHIFT,
|
||||||
|
RShift = SDLK_RSHIFT,
|
||||||
|
LCtrl = SDLK_LCTRL,
|
||||||
|
RCtrl = SDLK_RCTRL,
|
||||||
|
LAlt = SDLK_LALT,
|
||||||
|
RAlt = SDLK_RALT,
|
||||||
|
LGui = SDLK_LGUI,
|
||||||
|
RGui = SDLK_RGUI
|
||||||
|
};
|
||||||
|
|
||||||
|
enum class KeyMod {
|
||||||
|
None = KMOD_NONE,
|
||||||
|
LShift = KMOD_LSHIFT,
|
||||||
|
RShift = KMOD_RSHIFT,
|
||||||
|
Shift = KMOD_SHIFT,
|
||||||
|
LCtrl = KMOD_LCTRL,
|
||||||
|
RCtrl = KMOD_RCTRL,
|
||||||
|
Ctrl = KMOD_CTRL,
|
||||||
|
LAlt = KMOD_LALT,
|
||||||
|
RAlt = KMOD_RALT,
|
||||||
|
Alt = KMOD_ALT,
|
||||||
|
LGui = KMOD_LGUI,
|
||||||
|
RGui = KMOD_RGUI,
|
||||||
|
Gui = KMOD_GUI,
|
||||||
|
Num = KMOD_NUM,
|
||||||
|
Caps = KMOD_CAPS
|
||||||
|
};
|
||||||
|
|
||||||
|
class KeyEvent : public Event {
|
||||||
|
public:
|
||||||
|
KeyEvent(uint32 timestamp, KeyCode keyCode, KeyMod modifiers, bool repeat)
|
||||||
|
: Event(timestamp)
|
||||||
|
, keyCode_(keyCode)
|
||||||
|
, modifiers_(modifiers)
|
||||||
|
, repeat_(repeat) {}
|
||||||
|
|
||||||
|
EventType getType() const override {
|
||||||
|
return EventType::KeyDown;
|
||||||
|
}
|
||||||
|
|
||||||
|
KeyCode getKeyCode() const { return keyCode_; }
|
||||||
|
KeyMod getModifiers() const { return modifiers_; }
|
||||||
|
bool isRepeat() const { return repeat_; }
|
||||||
|
|
||||||
|
private:
|
||||||
|
KeyCode keyCode_;
|
||||||
|
KeyMod modifiers_;
|
||||||
|
bool repeat_;
|
||||||
|
};
|
||||||
|
|
||||||
|
class KeyUpEvent : public Event {
|
||||||
|
public:
|
||||||
|
KeyUpEvent(uint32 timestamp, KeyCode keyCode, KeyMod modifiers)
|
||||||
|
: Event(timestamp)
|
||||||
|
, keyCode_(keyCode)
|
||||||
|
, modifiers_(modifiers) {}
|
||||||
|
|
||||||
|
EventType getType() const override {
|
||||||
|
return EventType::KeyUp;
|
||||||
|
}
|
||||||
|
|
||||||
|
KeyCode getKeyCode() const { return keyCode_; }
|
||||||
|
KeyMod getModifiers() const { return modifiers_; }
|
||||||
|
|
||||||
|
private:
|
||||||
|
KeyCode keyCode_;
|
||||||
|
KeyMod modifiers_;
|
||||||
|
};
|
||||||
|
|
||||||
|
class KeyTextEvent : public Event {
|
||||||
|
public:
|
||||||
|
KeyTextEvent(uint32 timestamp, const std::string& text)
|
||||||
|
: Event(timestamp)
|
||||||
|
, text_(text) {}
|
||||||
|
|
||||||
|
EventType getType() const override {
|
||||||
|
return EventType::KeyText;
|
||||||
|
}
|
||||||
|
|
||||||
|
const std::string& getText() const { return text_; }
|
||||||
|
|
||||||
|
private:
|
||||||
|
std::string text_;
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
||||||
108
Frostbite2D/include/frostbite2D/event/mouse_event.h
Normal file
108
Frostbite2D/include/frostbite2D/event/mouse_event.h
Normal file
@@ -0,0 +1,108 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <frostbite2D/event/event.h>
|
||||||
|
#include <frostbite2D/types/type_math.h>
|
||||||
|
#include <SDL2/SDL_mouse.h>
|
||||||
|
|
||||||
|
namespace frostbite2D {
|
||||||
|
|
||||||
|
enum class MouseButton {
|
||||||
|
Left = SDL_BUTTON_LEFT,
|
||||||
|
Right = SDL_BUTTON_RIGHT,
|
||||||
|
Middle = SDL_BUTTON_MIDDLE,
|
||||||
|
X1 = SDL_BUTTON_X1,
|
||||||
|
X2 = SDL_BUTTON_X2
|
||||||
|
};
|
||||||
|
|
||||||
|
class MouseEvent : public Event {
|
||||||
|
public:
|
||||||
|
MouseEvent(EventType type, uint32 timestamp, const Vec2& position)
|
||||||
|
: Event(timestamp)
|
||||||
|
, type_(type)
|
||||||
|
, position_(position) {}
|
||||||
|
|
||||||
|
virtual ~MouseEvent() = default;
|
||||||
|
|
||||||
|
EventType getType() const override { return type_; }
|
||||||
|
const Vec2& getPosition() const { return position_; }
|
||||||
|
int32 getX() const { return static_cast<int32>(position_.x); }
|
||||||
|
int32 getY() const { return static_cast<int32>(position_.y); }
|
||||||
|
|
||||||
|
protected:
|
||||||
|
EventType type_;
|
||||||
|
Vec2 position_;
|
||||||
|
};
|
||||||
|
|
||||||
|
class MouseMoveEvent : public Event {
|
||||||
|
public:
|
||||||
|
MouseMoveEvent(uint32 timestamp, const Vec2& position, const Vec2& relative)
|
||||||
|
: Event(timestamp)
|
||||||
|
, position_(position)
|
||||||
|
, relative_(relative) {}
|
||||||
|
|
||||||
|
EventType getType() const override {
|
||||||
|
return EventType::MouseMove;
|
||||||
|
}
|
||||||
|
|
||||||
|
const Vec2& getPosition() const { return position_; }
|
||||||
|
const Vec2& getRelative() const { return relative_; }
|
||||||
|
|
||||||
|
int32 getX() const { return static_cast<int32>(position_.x); }
|
||||||
|
int32 getY() const { return static_cast<int32>(position_.y); }
|
||||||
|
|
||||||
|
private:
|
||||||
|
Vec2 position_;
|
||||||
|
Vec2 relative_;
|
||||||
|
};
|
||||||
|
|
||||||
|
class MouseButtonEvent : public Event {
|
||||||
|
public:
|
||||||
|
MouseButtonEvent(uint32 timestamp, MouseButton button, const Vec2& position, bool down)
|
||||||
|
: Event(timestamp)
|
||||||
|
, button_(button)
|
||||||
|
, position_(position)
|
||||||
|
, down_(down) {}
|
||||||
|
|
||||||
|
EventType getType() const override {
|
||||||
|
return down_ ? EventType::MouseButtonDown : EventType::MouseButtonUp;
|
||||||
|
}
|
||||||
|
|
||||||
|
MouseButton getButton() const { return button_; }
|
||||||
|
const Vec2& getPosition() const { return position_; }
|
||||||
|
bool isDown() const { return down_; }
|
||||||
|
|
||||||
|
int32 getX() const { return static_cast<int32>(position_.x); }
|
||||||
|
int32 getY() const { return static_cast<int32>(position_.y); }
|
||||||
|
|
||||||
|
private:
|
||||||
|
MouseButton button_;
|
||||||
|
Vec2 position_;
|
||||||
|
bool down_;
|
||||||
|
};
|
||||||
|
|
||||||
|
class MouseWheelEvent : public Event {
|
||||||
|
public:
|
||||||
|
MouseWheelEvent(uint32 timestamp, const Vec2& position, const Vec2& direction, bool flipped)
|
||||||
|
: Event(timestamp)
|
||||||
|
, position_(position)
|
||||||
|
, direction_(direction)
|
||||||
|
, flipped_(flipped) {}
|
||||||
|
|
||||||
|
EventType getType() const override {
|
||||||
|
return EventType::MouseWheel;
|
||||||
|
}
|
||||||
|
|
||||||
|
const Vec2& getPosition() const { return position_; }
|
||||||
|
const Vec2& getDirection() const { return direction_; }
|
||||||
|
bool isFlipped() const { return flipped_; }
|
||||||
|
|
||||||
|
int32 getX() const { return static_cast<int32>(direction_.x); }
|
||||||
|
int32 getY() const { return static_cast<int32>(direction_.y); }
|
||||||
|
|
||||||
|
private:
|
||||||
|
Vec2 position_;
|
||||||
|
Vec2 direction_;
|
||||||
|
bool flipped_;
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
||||||
64
Frostbite2D/include/frostbite2D/event/touch_event.h
Normal file
64
Frostbite2D/include/frostbite2D/event/touch_event.h
Normal file
@@ -0,0 +1,64 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <frostbite2D/event/event.h>
|
||||||
|
#include <frostbite2D/types/type_math.h>
|
||||||
|
#include <SDL2/SDL_touch.h>
|
||||||
|
|
||||||
|
namespace frostbite2D {
|
||||||
|
|
||||||
|
class TouchEvent : public Event {
|
||||||
|
public:
|
||||||
|
TouchEvent(EventType type, uint32 timestamp, int64 touchId, int64 fingerId,
|
||||||
|
const Vec2& position, const Vec2& delta, float pressure)
|
||||||
|
: Event(timestamp)
|
||||||
|
, type_(type)
|
||||||
|
, touchId_(touchId)
|
||||||
|
, fingerId_(fingerId)
|
||||||
|
, position_(position)
|
||||||
|
, delta_(delta)
|
||||||
|
, pressure_(pressure) {}
|
||||||
|
|
||||||
|
EventType getType() const override {
|
||||||
|
return type_;
|
||||||
|
}
|
||||||
|
|
||||||
|
int64 getTouchId() const { return touchId_; }
|
||||||
|
int64 getFingerId() const { return fingerId_; }
|
||||||
|
const Vec2& getPosition() const { return position_; }
|
||||||
|
const Vec2& getDelta() const { return delta_; }
|
||||||
|
float getPressure() const { return pressure_; }
|
||||||
|
|
||||||
|
private:
|
||||||
|
EventType type_;
|
||||||
|
int64 touchId_;
|
||||||
|
int64 fingerId_;
|
||||||
|
Vec2 position_;
|
||||||
|
Vec2 delta_;
|
||||||
|
float pressure_;
|
||||||
|
};
|
||||||
|
|
||||||
|
class TouchDownEvent : public TouchEvent {
|
||||||
|
public:
|
||||||
|
TouchDownEvent(uint32 timestamp, int64 touchId, int64 fingerId,
|
||||||
|
const Vec2& position, float pressure)
|
||||||
|
: TouchEvent(EventType::TouchDown, timestamp, touchId, fingerId,
|
||||||
|
position, Vec2(0, 0), pressure) {}
|
||||||
|
};
|
||||||
|
|
||||||
|
class TouchUpEvent : public TouchEvent {
|
||||||
|
public:
|
||||||
|
TouchUpEvent(uint32 timestamp, int64 touchId, int64 fingerId,
|
||||||
|
const Vec2& position, float pressure)
|
||||||
|
: TouchEvent(EventType::TouchUp, timestamp, touchId, fingerId,
|
||||||
|
position, Vec2(0, 0), pressure) {}
|
||||||
|
};
|
||||||
|
|
||||||
|
class TouchMoveEvent : public TouchEvent {
|
||||||
|
public:
|
||||||
|
TouchMoveEvent(uint32 timestamp, int64 touchId, int64 fingerId,
|
||||||
|
const Vec2& position, const Vec2& delta, float pressure)
|
||||||
|
: TouchEvent(EventType::TouchMove, timestamp, touchId, fingerId,
|
||||||
|
position, delta, pressure) {}
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
||||||
77
Frostbite2D/include/frostbite2D/event/window_event.h
Normal file
77
Frostbite2D/include/frostbite2D/event/window_event.h
Normal file
@@ -0,0 +1,77 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <frostbite2D/event/event.h>
|
||||||
|
#include <SDL2/SDL_events.h>
|
||||||
|
|
||||||
|
namespace frostbite2D {
|
||||||
|
|
||||||
|
class WindowEvent : public Event {
|
||||||
|
public:
|
||||||
|
WindowEvent(EventType type, uint32 timestamp, int32 windowId)
|
||||||
|
: Event(timestamp)
|
||||||
|
, type_(type)
|
||||||
|
, windowId_(windowId) {}
|
||||||
|
|
||||||
|
EventType getType() const override {
|
||||||
|
return type_;
|
||||||
|
}
|
||||||
|
|
||||||
|
int32 getWindowId() const { return windowId_; }
|
||||||
|
|
||||||
|
protected:
|
||||||
|
EventType type_;
|
||||||
|
int32 windowId_;
|
||||||
|
};
|
||||||
|
|
||||||
|
class WindowCloseEvent : public WindowEvent {
|
||||||
|
public:
|
||||||
|
WindowCloseEvent(uint32 timestamp, int32 windowId)
|
||||||
|
: WindowEvent(EventType::WindowClose, timestamp, windowId) {}
|
||||||
|
};
|
||||||
|
|
||||||
|
class WindowResizeEvent : public WindowEvent {
|
||||||
|
public:
|
||||||
|
WindowResizeEvent(uint32 timestamp, int32 windowId, int32 width, int32 height)
|
||||||
|
: WindowEvent(EventType::WindowResize, timestamp, windowId)
|
||||||
|
, width_(width)
|
||||||
|
, height_(height) {}
|
||||||
|
|
||||||
|
int32 getWidth() const { return width_; }
|
||||||
|
int32 getHeight() const { return height_; }
|
||||||
|
|
||||||
|
private:
|
||||||
|
int32 width_;
|
||||||
|
int32 height_;
|
||||||
|
};
|
||||||
|
|
||||||
|
class WindowFocusEvent : public WindowEvent {
|
||||||
|
public:
|
||||||
|
WindowFocusEvent(uint32 timestamp, int32 windowId, bool focused)
|
||||||
|
: WindowEvent(EventType::WindowFocus, timestamp, windowId)
|
||||||
|
, focused_(focused) {}
|
||||||
|
|
||||||
|
bool isFocused() const { return focused_; }
|
||||||
|
|
||||||
|
private:
|
||||||
|
bool focused_;
|
||||||
|
};
|
||||||
|
|
||||||
|
class WindowMinimizeEvent : public WindowEvent {
|
||||||
|
public:
|
||||||
|
WindowMinimizeEvent(uint32 timestamp, int32 windowId)
|
||||||
|
: WindowEvent(EventType::WindowMinimize, timestamp, windowId) {}
|
||||||
|
};
|
||||||
|
|
||||||
|
class WindowMaximizeEvent : public WindowEvent {
|
||||||
|
public:
|
||||||
|
WindowMaximizeEvent(uint32 timestamp, int32 windowId)
|
||||||
|
: WindowEvent(EventType::WindowMaximize, timestamp, windowId) {}
|
||||||
|
};
|
||||||
|
|
||||||
|
class WindowRestoreEvent : public WindowEvent {
|
||||||
|
public:
|
||||||
|
WindowRestoreEvent(uint32 timestamp, int32 windowId)
|
||||||
|
: WindowEvent(EventType::WindowRestore, timestamp, windowId) {}
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
||||||
@@ -1,6 +1,8 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <frostbite2D/2d/actor.h>
|
#include <frostbite2D/2d/actor.h>
|
||||||
|
#include <frostbite2D/event/event.h>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
namespace frostbite2D {
|
namespace frostbite2D {
|
||||||
|
|
||||||
@@ -15,7 +17,15 @@ public:
|
|||||||
void Update(float deltaTime) override;
|
void Update(float deltaTime) override;
|
||||||
void Render() override;
|
void Render() override;
|
||||||
|
|
||||||
|
bool OnEvent(const Event& event) override;
|
||||||
|
|
||||||
|
static Scene* GetCurrent();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
bool dispatchToChildren(const Event& event);
|
||||||
|
|
||||||
|
static Scene* current_;
|
||||||
|
|
||||||
friend class SceneManager;
|
friend class SceneManager;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -1,4 +1,9 @@
|
|||||||
#include <frostbite2D/2d/actor.h>
|
#include <frostbite2D/2d/actor.h>
|
||||||
|
#include <frostbite2D/event/key_event.h>
|
||||||
|
#include <frostbite2D/event/mouse_event.h>
|
||||||
|
#include <frostbite2D/event/touch_event.h>
|
||||||
|
#include <frostbite2D/event/joystick_event.h>
|
||||||
|
#include <frostbite2D/event/window_event.h>
|
||||||
#include <SDL2/SDL.h>
|
#include <SDL2/SDL.h>
|
||||||
|
|
||||||
namespace frostbite2D {
|
namespace frostbite2D {
|
||||||
@@ -210,5 +215,170 @@ void Actor::RenderChildren() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
uint32 Actor::AddEventListener(EventType type, EventCallback callback) {
|
||||||
|
EventListener listener;
|
||||||
|
listener.id = nextListenerId_++;
|
||||||
|
listener.type = type;
|
||||||
|
listener.callback = std::move(callback);
|
||||||
|
eventListeners_.push_back(listener);
|
||||||
|
return listener.id;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Actor::RemoveEventListener(uint32 listenerId) {
|
||||||
|
for (auto it = eventListeners_.begin(); it != eventListeners_.end(); ++it) {
|
||||||
|
if (it->id == listenerId) {
|
||||||
|
eventListeners_.erase(it);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Actor::ClearEventListeners() {
|
||||||
|
eventListeners_.clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Actor::OnEvent(const Event& event) {
|
||||||
|
if (!eventReceiveEnabled_) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (const auto& listener : eventListeners_) {
|
||||||
|
if (listener.type == event.getType()) {
|
||||||
|
if (listener.callback(event)) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
switch (event.getType()) {
|
||||||
|
case EventType::KeyDown:
|
||||||
|
return OnKeyDown(static_cast<const KeyEvent&>(event));
|
||||||
|
case EventType::KeyUp:
|
||||||
|
return OnKeyUp(static_cast<const KeyEvent&>(event));
|
||||||
|
case EventType::MouseButtonDown:
|
||||||
|
return OnMouseDown(static_cast<const MouseEvent&>(event));
|
||||||
|
case EventType::MouseButtonUp:
|
||||||
|
return OnMouseUp(static_cast<const MouseEvent&>(event));
|
||||||
|
case EventType::MouseMove:
|
||||||
|
return OnMouseMove(static_cast<const MouseEvent&>(event));
|
||||||
|
case EventType::MouseWheel:
|
||||||
|
return OnMouseWheel(static_cast<const MouseEvent&>(event));
|
||||||
|
case EventType::TouchDown:
|
||||||
|
return OnTouchDown(static_cast<const TouchEvent&>(event));
|
||||||
|
case EventType::TouchUp:
|
||||||
|
return OnTouchUp(static_cast<const TouchEvent&>(event));
|
||||||
|
case EventType::TouchMove:
|
||||||
|
return OnTouchMove(static_cast<const TouchEvent&>(event));
|
||||||
|
case EventType::JoystickAxis:
|
||||||
|
return OnJoystickAxis(static_cast<const JoystickEvent&>(event));
|
||||||
|
case EventType::JoystickButtonDown:
|
||||||
|
return OnJoystickButtonDown(static_cast<const JoystickEvent&>(event));
|
||||||
|
case EventType::JoystickButtonUp:
|
||||||
|
return OnJoystickButtonUp(static_cast<const JoystickEvent&>(event));
|
||||||
|
case EventType::WindowResize:
|
||||||
|
return OnWindowResize(static_cast<const WindowEvent&>(event));
|
||||||
|
default:
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Actor::OnKeyDown(const KeyEvent& event) {
|
||||||
|
(void)event;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Actor::OnKeyUp(const KeyEvent& event) {
|
||||||
|
(void)event;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Actor::OnMouseDown(const MouseEvent& event) {
|
||||||
|
(void)event;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Actor::OnMouseUp(const MouseEvent& event) {
|
||||||
|
(void)event;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Actor::OnMouseMove(const MouseEvent& event) {
|
||||||
|
(void)event;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Actor::OnMouseWheel(const MouseEvent& event) {
|
||||||
|
(void)event;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Actor::OnTouchDown(const TouchEvent& event) {
|
||||||
|
(void)event;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Actor::OnTouchUp(const TouchEvent& event) {
|
||||||
|
(void)event;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Actor::OnTouchMove(const TouchEvent& event) {
|
||||||
|
(void)event;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Actor::OnJoystickAxis(const JoystickEvent& event) {
|
||||||
|
(void)event;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Actor::OnJoystickButtonDown(const JoystickEvent& event) {
|
||||||
|
(void)event;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Actor::OnJoystickButtonUp(const JoystickEvent& event) {
|
||||||
|
(void)event;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Actor::OnWindowResize(const WindowEvent& event) {
|
||||||
|
(void)event;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Actor::DispatchEvent(const Event& event) {
|
||||||
|
if (event.isPropagationStopped()) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (OnEvent(event)) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (auto it = children_.begin(); it != children_.end(); ++it) {
|
||||||
|
if (*it) {
|
||||||
|
if ((*it)->DispatchEvent(event)) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Actor::BubbleEvent(const Event& event) {
|
||||||
|
if (!parent_) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (parent_->OnEvent(event)) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return parent_->BubbleEvent(event);
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,8 +1,16 @@
|
|||||||
#include <SDL2/SDL.h>
|
#include <SDL2/SDL.h>
|
||||||
|
#include <SDL2/SDL_events.h>
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
#include <cstdio>
|
#include <cstdio>
|
||||||
|
#include <memory>
|
||||||
#include <frostbite2D/audio/audio_system.h>
|
#include <frostbite2D/audio/audio_system.h>
|
||||||
#include <frostbite2D/core/application.h>
|
#include <frostbite2D/core/application.h>
|
||||||
|
#include <frostbite2D/event/event.h>
|
||||||
|
#include <frostbite2D/event/key_event.h>
|
||||||
|
#include <frostbite2D/event/mouse_event.h>
|
||||||
|
#include <frostbite2D/event/touch_event.h>
|
||||||
|
#include <frostbite2D/event/joystick_event.h>
|
||||||
|
#include <frostbite2D/event/window_event.h>
|
||||||
#include <frostbite2D/graphics/camera.h>
|
#include <frostbite2D/graphics/camera.h>
|
||||||
#include <frostbite2D/graphics/renderer.h>
|
#include <frostbite2D/graphics/renderer.h>
|
||||||
#include <frostbite2D/platform/switch.h>
|
#include <frostbite2D/platform/switch.h>
|
||||||
@@ -10,6 +18,7 @@
|
|||||||
#include <frostbite2D/resource/npk_archive.h>
|
#include <frostbite2D/resource/npk_archive.h>
|
||||||
#include <frostbite2D/resource/pvf_archive.h>
|
#include <frostbite2D/resource/pvf_archive.h>
|
||||||
#include <frostbite2D/resource/sound_pack_archive.h>
|
#include <frostbite2D/resource/sound_pack_archive.h>
|
||||||
|
#include <frostbite2D/scene/scene.h>
|
||||||
#include <frostbite2D/scene/scene_manager.h>
|
#include <frostbite2D/scene/scene_manager.h>
|
||||||
#include <frostbite2D/types/type_math.h>
|
#include <frostbite2D/types/type_math.h>
|
||||||
|
|
||||||
@@ -116,11 +125,18 @@ bool Application::initCoreModules() {
|
|||||||
asset.setWorkingDirectory("/switch/Frostbite2D/" + config_.appName);
|
asset.setWorkingDirectory("/switch/Frostbite2D/" + config_.appName);
|
||||||
SDL_Log("Asset working directory: %s", asset.getWorkingDirectory().c_str());
|
SDL_Log("Asset working directory: %s", asset.getWorkingDirectory().c_str());
|
||||||
#endif
|
#endif
|
||||||
if (SDL_Init(SDL_INIT_VIDEO | SDL_INIT_EVENTS) != 0) {
|
if (SDL_Init(SDL_INIT_VIDEO | SDL_INIT_EVENTS | SDL_INIT_GAMECONTROLLER) != 0) {
|
||||||
SDL_Log("Failed to initialize SDL: %s", SDL_GetError());
|
SDL_Log("Failed to initialize SDL: %s", SDL_GetError());
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 打开第一个手柄(如果存在)
|
||||||
|
if (SDL_GameController *controller = SDL_GameControllerOpen(0)) {
|
||||||
|
SDL_Log("GameController opened: %s", SDL_GameControllerName(controller));
|
||||||
|
} else {
|
||||||
|
SDL_Log("No GameController found");
|
||||||
|
}
|
||||||
|
|
||||||
// 使用SDL2创建窗口
|
// 使用SDL2创建窗口
|
||||||
this->window_ = new Window();
|
this->window_ = new Window();
|
||||||
|
|
||||||
@@ -201,29 +217,19 @@ void Application::resume() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void Application::mainLoop() {
|
void Application::mainLoop() {
|
||||||
// 记录程序启动时的初始时间(毫秒)
|
|
||||||
Uint32 start_time = SDL_GetTicks();
|
|
||||||
// 定时退出时间:1秒 = 1000毫秒
|
|
||||||
const Uint32 EXIT_DELAY = 1000;
|
|
||||||
|
|
||||||
while (!shouldQuit_) {
|
while (!shouldQuit_) {
|
||||||
SDL_Event event;
|
SDL_Event sdlEvent;
|
||||||
while (SDL_PollEvent(&event)) {
|
while (SDL_PollEvent(&sdlEvent)) {
|
||||||
if (event.type == SDL_QUIT) {
|
if (sdlEvent.type == SDL_QUIT) {
|
||||||
shouldQuit_ = true;
|
shouldQuit_ = true;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
// ===================== 新增:1秒定时退出 =====================
|
auto event = convertSDLEvent(sdlEvent);
|
||||||
Uint32 current_time = SDL_GetTicks();
|
if (event) {
|
||||||
// 判断是否达到1秒
|
dispatchEvent(*event);
|
||||||
if (current_time - start_time >= EXIT_DELAY) {
|
}
|
||||||
shouldQuit_ = true;
|
|
||||||
// 跳出事件循环
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
// ============================================================
|
|
||||||
|
|
||||||
if (!paused_) {
|
if (!paused_) {
|
||||||
update();
|
update();
|
||||||
@@ -233,6 +239,129 @@ void Application::mainLoop() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
std::unique_ptr<Event> Application::convertSDLEvent(const SDL_Event& sdlEvent) {
|
||||||
|
switch (sdlEvent.type) {
|
||||||
|
case SDL_WINDOWEVENT: {
|
||||||
|
switch (sdlEvent.window.event) {
|
||||||
|
case SDL_WINDOWEVENT_CLOSE:
|
||||||
|
return std::make_unique<WindowCloseEvent>(sdlEvent.window.timestamp, sdlEvent.window.windowID);
|
||||||
|
case SDL_WINDOWEVENT_RESIZED:
|
||||||
|
case SDL_WINDOWEVENT_SIZE_CHANGED:
|
||||||
|
return std::make_unique<WindowResizeEvent>(sdlEvent.window.timestamp, sdlEvent.window.windowID,
|
||||||
|
sdlEvent.window.data1, sdlEvent.window.data2);
|
||||||
|
case SDL_WINDOWEVENT_FOCUS_GAINED:
|
||||||
|
case SDL_WINDOWEVENT_FOCUS_LOST:
|
||||||
|
return std::make_unique<WindowFocusEvent>(sdlEvent.window.timestamp, sdlEvent.window.windowID,
|
||||||
|
sdlEvent.window.event == SDL_WINDOWEVENT_FOCUS_GAINED);
|
||||||
|
case SDL_WINDOWEVENT_MINIMIZED:
|
||||||
|
return std::make_unique<WindowMinimizeEvent>(sdlEvent.window.timestamp, sdlEvent.window.windowID);
|
||||||
|
case SDL_WINDOWEVENT_MAXIMIZED:
|
||||||
|
return std::make_unique<WindowMaximizeEvent>(sdlEvent.window.timestamp, sdlEvent.window.windowID);
|
||||||
|
case SDL_WINDOWEVENT_RESTORED:
|
||||||
|
return std::make_unique<WindowRestoreEvent>(sdlEvent.window.timestamp, sdlEvent.window.windowID);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
case SDL_KEYDOWN: {
|
||||||
|
return std::make_unique<KeyEvent>(sdlEvent.key.timestamp,
|
||||||
|
static_cast<KeyCode>(sdlEvent.key.keysym.sym),
|
||||||
|
static_cast<KeyMod>(sdlEvent.key.keysym.mod),
|
||||||
|
sdlEvent.key.repeat != 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
case SDL_KEYUP: {
|
||||||
|
return std::make_unique<KeyUpEvent>(sdlEvent.key.timestamp,
|
||||||
|
static_cast<KeyCode>(sdlEvent.key.keysym.sym),
|
||||||
|
static_cast<KeyMod>(sdlEvent.key.keysym.mod));
|
||||||
|
}
|
||||||
|
|
||||||
|
case SDL_TEXTINPUT: {
|
||||||
|
return std::make_unique<KeyTextEvent>(sdlEvent.text.timestamp, sdlEvent.text.text);
|
||||||
|
}
|
||||||
|
|
||||||
|
case SDL_MOUSEMOTION: {
|
||||||
|
return std::make_unique<MouseMoveEvent>(sdlEvent.motion.timestamp,
|
||||||
|
Vec2(static_cast<float>(sdlEvent.motion.x), static_cast<float>(sdlEvent.motion.y)),
|
||||||
|
Vec2(static_cast<float>(sdlEvent.motion.xrel), static_cast<float>(sdlEvent.motion.yrel)));
|
||||||
|
}
|
||||||
|
|
||||||
|
case SDL_MOUSEBUTTONDOWN: {
|
||||||
|
return std::make_unique<MouseButtonEvent>(sdlEvent.button.timestamp,
|
||||||
|
static_cast<MouseButton>(sdlEvent.button.button),
|
||||||
|
Vec2(static_cast<float>(sdlEvent.button.x), static_cast<float>(sdlEvent.button.y)),
|
||||||
|
true);
|
||||||
|
}
|
||||||
|
|
||||||
|
case SDL_MOUSEBUTTONUP: {
|
||||||
|
return std::make_unique<MouseButtonEvent>(sdlEvent.button.timestamp,
|
||||||
|
static_cast<MouseButton>(sdlEvent.button.button),
|
||||||
|
Vec2(static_cast<float>(sdlEvent.button.x), static_cast<float>(sdlEvent.button.y)),
|
||||||
|
false);
|
||||||
|
}
|
||||||
|
|
||||||
|
case SDL_MOUSEWHEEL: {
|
||||||
|
return std::make_unique<MouseWheelEvent>(sdlEvent.wheel.timestamp,
|
||||||
|
Vec2(static_cast<float>(sdlEvent.wheel.mouseX), static_cast<float>(sdlEvent.wheel.mouseY)),
|
||||||
|
Vec2(static_cast<float>(sdlEvent.wheel.x), static_cast<float>(sdlEvent.wheel.y)),
|
||||||
|
sdlEvent.wheel.direction == SDL_MOUSEWHEEL_FLIPPED);
|
||||||
|
}
|
||||||
|
|
||||||
|
case SDL_FINGERDOWN: {
|
||||||
|
return std::make_unique<TouchDownEvent>(sdlEvent.tfinger.timestamp,
|
||||||
|
sdlEvent.tfinger.touchId,
|
||||||
|
sdlEvent.tfinger.fingerId,
|
||||||
|
Vec2(static_cast<float>(sdlEvent.tfinger.x), static_cast<float>(sdlEvent.tfinger.y)),
|
||||||
|
sdlEvent.tfinger.pressure);
|
||||||
|
}
|
||||||
|
|
||||||
|
case SDL_FINGERUP: {
|
||||||
|
return std::make_unique<TouchUpEvent>(sdlEvent.tfinger.timestamp,
|
||||||
|
sdlEvent.tfinger.touchId,
|
||||||
|
sdlEvent.tfinger.fingerId,
|
||||||
|
Vec2(static_cast<float>(sdlEvent.tfinger.x), static_cast<float>(sdlEvent.tfinger.y)),
|
||||||
|
sdlEvent.tfinger.pressure);
|
||||||
|
}
|
||||||
|
|
||||||
|
case SDL_FINGERMOTION: {
|
||||||
|
return std::make_unique<TouchMoveEvent>(sdlEvent.tfinger.timestamp,
|
||||||
|
sdlEvent.tfinger.touchId,
|
||||||
|
sdlEvent.tfinger.fingerId,
|
||||||
|
Vec2(static_cast<float>(sdlEvent.tfinger.x), static_cast<float>(sdlEvent.tfinger.y)),
|
||||||
|
Vec2(static_cast<float>(sdlEvent.tfinger.dx), static_cast<float>(sdlEvent.tfinger.dy)),
|
||||||
|
sdlEvent.tfinger.pressure);
|
||||||
|
}
|
||||||
|
|
||||||
|
case SDL_CONTROLLERBUTTONDOWN: {
|
||||||
|
return std::make_unique<JoystickButtonDownEvent>(sdlEvent.cbutton.timestamp,
|
||||||
|
sdlEvent.cbutton.which,
|
||||||
|
sdlEvent.cbutton.button);
|
||||||
|
}
|
||||||
|
|
||||||
|
case SDL_CONTROLLERBUTTONUP: {
|
||||||
|
return std::make_unique<JoystickButtonUpEvent>(sdlEvent.cbutton.timestamp,
|
||||||
|
sdlEvent.cbutton.which,
|
||||||
|
sdlEvent.cbutton.button);
|
||||||
|
}
|
||||||
|
|
||||||
|
case SDL_CONTROLLERAXISMOTION: {
|
||||||
|
return std::make_unique<JoystickAxisEvent>(sdlEvent.caxis.timestamp,
|
||||||
|
sdlEvent.caxis.which,
|
||||||
|
sdlEvent.caxis.axis,
|
||||||
|
sdlEvent.caxis.value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Application::dispatchEvent(const Event& event) {
|
||||||
|
Scene* currentScene = SceneManager::get().GetCurrentScene();
|
||||||
|
if (currentScene) {
|
||||||
|
currentScene->OnEvent(event);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void Application::update() {
|
void Application::update() {
|
||||||
double currentTime = SDL_GetPerformanceCounter() / static_cast<double>(SDL_GetPerformanceFrequency());
|
double currentTime = SDL_GetPerformanceCounter() / static_cast<double>(SDL_GetPerformanceFrequency());
|
||||||
deltaTime_ = static_cast<float>(currentTime - lastFrameTime_);
|
deltaTime_ = static_cast<float>(currentTime - lastFrameTime_);
|
||||||
|
|||||||
@@ -1,9 +1,13 @@
|
|||||||
#include <frostbite2D/scene/scene.h>
|
#include <frostbite2D/scene/scene.h>
|
||||||
|
#include <algorithm>
|
||||||
#include <SDL2/SDL.h>
|
#include <SDL2/SDL.h>
|
||||||
|
|
||||||
namespace frostbite2D {
|
namespace frostbite2D {
|
||||||
|
|
||||||
|
Scene* Scene::current_ = nullptr;
|
||||||
|
|
||||||
Scene::Scene() {
|
Scene::Scene() {
|
||||||
|
current_ = this;
|
||||||
}
|
}
|
||||||
|
|
||||||
Scene::~Scene() {
|
Scene::~Scene() {
|
||||||
@@ -25,5 +29,54 @@ void Scene::Render() {
|
|||||||
RenderChildren();
|
RenderChildren();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Scene* Scene::GetCurrent() {
|
||||||
|
return current_;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Scene::OnEvent(const Event& event) {
|
||||||
|
if (Actor::OnEvent(event)) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (dispatchToChildren(event)) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Scene::dispatchToChildren(const Event& event) {
|
||||||
|
if (event.isPropagationStopped()) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::vector<Actor*> sortedChildren;
|
||||||
|
for (auto it = children_.begin(); it != children_.end(); ++it) {
|
||||||
|
Actor* child = it->Get();
|
||||||
|
if (child && child->IsEventReceiveEnabled()) {
|
||||||
|
sortedChildren.push_back(child);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
std::sort(sortedChildren.begin(), sortedChildren.end(),
|
||||||
|
[](Actor* a, Actor* b) {
|
||||||
|
return a->GetEventPriority() < b->GetEventPriority();
|
||||||
|
});
|
||||||
|
|
||||||
|
for (Actor* child : sortedChildren) {
|
||||||
|
if (child->IsEventInterceptEnabled()) {
|
||||||
|
if (child->OnEvent(event)) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (child->DispatchEvent(event)) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -3,10 +3,12 @@
|
|||||||
#include <SDL2/SDL.h>
|
#include <SDL2/SDL.h>
|
||||||
#include <frostbite2D/core/application.h>
|
#include <frostbite2D/core/application.h>
|
||||||
#include <frostbite2D/core/window.h>
|
#include <frostbite2D/core/window.h>
|
||||||
|
#include <frostbite2D/event/event.h>
|
||||||
#include <frostbite2D/graphics/renderer.h>
|
#include <frostbite2D/graphics/renderer.h>
|
||||||
#include <frostbite2D/graphics/texture.h>
|
#include <frostbite2D/graphics/texture.h>
|
||||||
#include <glad/glad.h>
|
#include <glad/glad.h>
|
||||||
|
|
||||||
|
|
||||||
#include <frostbite2D/2d/sprite.h>
|
#include <frostbite2D/2d/sprite.h>
|
||||||
#include <frostbite2D/scene/scene.h>
|
#include <frostbite2D/scene/scene.h>
|
||||||
#include <frostbite2D/scene/scene_manager.h>
|
#include <frostbite2D/scene/scene_manager.h>
|
||||||
@@ -41,8 +43,47 @@ int main(int argc, char **argv) {
|
|||||||
|
|
||||||
// SDL_Log("Starting main loop...");
|
// SDL_Log("Starting main loop...");
|
||||||
|
|
||||||
// auto menuScene = MakePtr<Scene>();
|
auto menuScene = MakePtr<Scene>();
|
||||||
// SceneManager::get().PushScene(menuScene);
|
SceneManager::get().PushScene(menuScene);
|
||||||
|
|
||||||
|
auto TestActor = MakePtr<Actor>();
|
||||||
|
|
||||||
|
menuScene->AddChild(TestActor);
|
||||||
|
|
||||||
|
TestActor->EnableEventReceive();
|
||||||
|
|
||||||
|
// 监听手柄按键按下
|
||||||
|
TestActor->AddEventListener(
|
||||||
|
EventType::JoystickButtonDown, [](const Event &event) {
|
||||||
|
const auto &ke = static_cast<const JoystickButtonEvent &>(event);
|
||||||
|
SDL_Log("Joystick Button Down: device=%d, button=%d", ke.getDeviceId(),
|
||||||
|
ke.getButton());
|
||||||
|
|
||||||
|
if(ke.getButton() == 6) {
|
||||||
|
Application::get().quit();
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
});
|
||||||
|
|
||||||
|
// 监听手柄按键抬起
|
||||||
|
TestActor->AddEventListener(
|
||||||
|
EventType::JoystickButtonUp, [](const Event &event) {
|
||||||
|
const auto &ke = static_cast<const JoystickButtonEvent &>(event);
|
||||||
|
SDL_Log("Joystick Button Up: device=%d, button=%d", ke.getDeviceId(),
|
||||||
|
ke.getButton());
|
||||||
|
|
||||||
|
return true;
|
||||||
|
});
|
||||||
|
|
||||||
|
// 监听手柄轴
|
||||||
|
TestActor->AddEventListener(EventType::JoystickAxis, [](const Event &event) {
|
||||||
|
const auto &ae = static_cast<const JoystickAxisEvent &>(event);
|
||||||
|
if (std::abs(ae.getNormalizedValue()) > 0.1f) {
|
||||||
|
SDL_Log("Joystick Axis: device=%d, axis=%d, value=%.2f", ae.getDeviceId(),
|
||||||
|
ae.getAxis(), ae.getNormalizedValue());
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
});
|
||||||
|
|
||||||
// // 尝试加载精灵
|
// // 尝试加载精灵
|
||||||
// auto sprite = Sprite::createFromFile("assets/player.png");
|
// auto sprite = Sprite::createFromFile("assets/player.png");
|
||||||
|
|||||||
Reference in New Issue
Block a user