feat(事件系统): 实现完整的事件处理框架
添加事件系统核心组件,包括事件基类、各种输入事件类型和事件分发机制。主要功能: - 新增基础事件类及键盘、鼠标、触摸、手柄等输入事件 - 在Actor类中实现事件监听和分发功能 - 在Scene类中添加事件处理逻辑 - 在Application类中集成SDL事件转换和分发 - 添加测试用例验证手柄事件处理 事件系统支持冒泡和优先级排序,为游戏交互提供基础支持
This commit is contained in:
@@ -4,8 +4,16 @@
|
||||
#include <frostbite2D/types/type_alias.h>
|
||||
#include <frostbite2D/types/type_math.h>
|
||||
#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 <vector>
|
||||
#include <functional>
|
||||
#include <unordered_map>
|
||||
|
||||
namespace frostbite2D {
|
||||
|
||||
@@ -70,7 +78,43 @@ public:
|
||||
ActorList& GetChildren() { 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 SetScene(Scene* scene) { scene_ = scene; }
|
||||
|
||||
@@ -99,6 +143,18 @@ private:
|
||||
mutable Transform2D worldTransform_;
|
||||
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 updateLocalTransform() const;
|
||||
void updateWorldTransform() const;
|
||||
|
||||
@@ -3,7 +3,9 @@
|
||||
#include <frostbite2D/core/window.h>
|
||||
#include <frostbite2D/graphics/camera.h>
|
||||
#include <frostbite2D/types/type_alias.h>
|
||||
#include <frostbite2D/event/event.h>
|
||||
#include <string>
|
||||
#include <memory>
|
||||
|
||||
namespace frostbite2D {
|
||||
|
||||
@@ -175,6 +177,9 @@ private:
|
||||
*/
|
||||
void render();
|
||||
|
||||
std::unique_ptr<Event> convertSDLEvent(const SDL_Event& sdlEvent);
|
||||
void dispatchEvent(const Event& event);
|
||||
|
||||
Window* window_ = nullptr;
|
||||
class Renderer* renderer_ = 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
|
||||
|
||||
#include <frostbite2D/2d/actor.h>
|
||||
#include <frostbite2D/event/event.h>
|
||||
#include <vector>
|
||||
|
||||
namespace frostbite2D {
|
||||
|
||||
@@ -15,7 +17,15 @@ public:
|
||||
void Update(float deltaTime) override;
|
||||
void Render() override;
|
||||
|
||||
bool OnEvent(const Event& event) override;
|
||||
|
||||
static Scene* GetCurrent();
|
||||
|
||||
private:
|
||||
bool dispatchToChildren(const Event& event);
|
||||
|
||||
static Scene* current_;
|
||||
|
||||
friend class SceneManager;
|
||||
};
|
||||
|
||||
|
||||
@@ -1,4 +1,9 @@
|
||||
#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>
|
||||
|
||||
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_events.h>
|
||||
#include <algorithm>
|
||||
#include <cstdio>
|
||||
#include <memory>
|
||||
#include <frostbite2D/audio/audio_system.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/renderer.h>
|
||||
#include <frostbite2D/platform/switch.h>
|
||||
@@ -10,6 +18,7 @@
|
||||
#include <frostbite2D/resource/npk_archive.h>
|
||||
#include <frostbite2D/resource/pvf_archive.h>
|
||||
#include <frostbite2D/resource/sound_pack_archive.h>
|
||||
#include <frostbite2D/scene/scene.h>
|
||||
#include <frostbite2D/scene/scene_manager.h>
|
||||
#include <frostbite2D/types/type_math.h>
|
||||
|
||||
@@ -116,11 +125,18 @@ bool Application::initCoreModules() {
|
||||
asset.setWorkingDirectory("/switch/Frostbite2D/" + config_.appName);
|
||||
SDL_Log("Asset working directory: %s", asset.getWorkingDirectory().c_str());
|
||||
#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());
|
||||
return false;
|
||||
}
|
||||
|
||||
// 打开第一个手柄(如果存在)
|
||||
if (SDL_GameController *controller = SDL_GameControllerOpen(0)) {
|
||||
SDL_Log("GameController opened: %s", SDL_GameControllerName(controller));
|
||||
} else {
|
||||
SDL_Log("No GameController found");
|
||||
}
|
||||
|
||||
// 使用SDL2创建窗口
|
||||
this->window_ = new Window();
|
||||
|
||||
@@ -201,29 +217,19 @@ void Application::resume() {
|
||||
}
|
||||
|
||||
void Application::mainLoop() {
|
||||
// 记录程序启动时的初始时间(毫秒)
|
||||
Uint32 start_time = SDL_GetTicks();
|
||||
// 定时退出时间:1秒 = 1000毫秒
|
||||
const Uint32 EXIT_DELAY = 1000;
|
||||
|
||||
while (!shouldQuit_) {
|
||||
SDL_Event event;
|
||||
while (SDL_PollEvent(&event)) {
|
||||
if (event.type == SDL_QUIT) {
|
||||
SDL_Event sdlEvent;
|
||||
while (SDL_PollEvent(&sdlEvent)) {
|
||||
if (sdlEvent.type == SDL_QUIT) {
|
||||
shouldQuit_ = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// ===================== 新增:1秒定时退出 =====================
|
||||
Uint32 current_time = SDL_GetTicks();
|
||||
// 判断是否达到1秒
|
||||
if (current_time - start_time >= EXIT_DELAY) {
|
||||
shouldQuit_ = true;
|
||||
// 跳出事件循环
|
||||
break;
|
||||
auto event = convertSDLEvent(sdlEvent);
|
||||
if (event) {
|
||||
dispatchEvent(*event);
|
||||
}
|
||||
}
|
||||
// ============================================================
|
||||
|
||||
if (!paused_) {
|
||||
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() {
|
||||
double currentTime = SDL_GetPerformanceCounter() / static_cast<double>(SDL_GetPerformanceFrequency());
|
||||
deltaTime_ = static_cast<float>(currentTime - lastFrameTime_);
|
||||
|
||||
@@ -1,9 +1,13 @@
|
||||
#include <frostbite2D/scene/scene.h>
|
||||
#include <algorithm>
|
||||
#include <SDL2/SDL.h>
|
||||
|
||||
namespace frostbite2D {
|
||||
|
||||
Scene* Scene::current_ = nullptr;
|
||||
|
||||
Scene::Scene() {
|
||||
current_ = this;
|
||||
}
|
||||
|
||||
Scene::~Scene() {
|
||||
@@ -25,5 +29,54 @@ void Scene::Render() {
|
||||
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 <frostbite2D/core/application.h>
|
||||
#include <frostbite2D/core/window.h>
|
||||
#include <frostbite2D/event/event.h>
|
||||
#include <frostbite2D/graphics/renderer.h>
|
||||
#include <frostbite2D/graphics/texture.h>
|
||||
#include <glad/glad.h>
|
||||
|
||||
|
||||
#include <frostbite2D/2d/sprite.h>
|
||||
#include <frostbite2D/scene/scene.h>
|
||||
#include <frostbite2D/scene/scene_manager.h>
|
||||
@@ -41,8 +43,47 @@ int main(int argc, char **argv) {
|
||||
|
||||
// SDL_Log("Starting main loop...");
|
||||
|
||||
// auto menuScene = MakePtr<Scene>();
|
||||
// SceneManager::get().PushScene(menuScene);
|
||||
auto menuScene = MakePtr<Scene>();
|
||||
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");
|
||||
|
||||
Reference in New Issue
Block a user