aboutsummaryrefslogtreecommitdiff
path: root/mwe/events/src
diff options
context:
space:
mode:
Diffstat (limited to 'mwe/events/src')
-rw-r--r--mwe/events/src/event.cpp71
-rw-r--r--mwe/events/src/eventHandler.cpp2
-rw-r--r--mwe/events/src/eventManager.cpp115
-rw-r--r--mwe/events/src/iKeyListener.cpp17
-rw-r--r--mwe/events/src/iMouseListener.cpp23
-rw-r--r--mwe/events/src/inputSystem.cpp91
-rw-r--r--mwe/events/src/keyCodes.cpp139
-rw-r--r--mwe/events/src/keyListenerTest.cpp13
-rw-r--r--mwe/events/src/loopManager.cpp99
-rw-r--r--mwe/events/src/main.cpp86
-rw-r--r--mwe/events/src/mouseListenerTest.cpp25
-rw-r--r--mwe/events/src/timer.cpp52
-rw-r--r--mwe/events/src/uiObject.cpp31
-rw-r--r--mwe/events/src/uiRenderer.cpp104
-rw-r--r--mwe/events/src/window.cpp45
15 files changed, 913 insertions, 0 deletions
diff --git a/mwe/events/src/event.cpp b/mwe/events/src/event.cpp
new file mode 100644
index 0000000..0040c73
--- /dev/null
+++ b/mwe/events/src/event.cpp
@@ -0,0 +1,71 @@
+#include "event.h"
+#include "keyCodes.h"
+// Event class methods
+Event::Event(std::string eventType) { eventData["eventType"] = eventType; }
+
+void Event::addArgument(const std::string & key,
+ const std::variant<int, std::string, float> & value) {
+ eventData[key] = value;
+}
+
+std::variant<int, std::string, float> Event::getArgument(const std::string & key) const {
+ return eventData.at(key);
+}
+
+std::string Event::getType() const { return std::get<std::string>(eventData.at("eventType")); }
+std::string Event::toString() const { return std::to_string(getEventType()); }
+bool Event::getHandled() const { return isHandled; }
+
+void Event::markHandled() { isHandled = true; }
+
+// KeyPressedEvent class methods
+KeyPressedEvent::KeyPressedEvent(int keycode)
+ : Event("KeyPressedEvent"),
+ key(keycode),
+ repeatCount(0) {}
+
+Keycode KeyPressedEvent::getKeyCode() const { return key; }
+
+int KeyPressedEvent::getRepeatCount() const { return repeatCount; }
+
+// KeyReleasedEvent class methods
+KeyReleasedEvent::KeyReleasedEvent(int keycode) : Event("KeyReleasedEvent"), key(keycode) {}
+
+Keycode KeyReleasedEvent::getKeyCode() const { return key; }
+
+// MousePressedEvent class methods
+MousePressedEvent::MousePressedEvent(int mouseX, int mouseY)
+ : Event("MousePressedEvent"),
+ mouseX(mouseX),
+ mouseY(mouseY) {}
+
+std::pair<int, int> MousePressedEvent::getMousePosition() const { return {mouseX, mouseY}; }
+
+//Collision event
+CollisionEvent::CollisionEvent(Collision collision)
+ : collisionData(collision),
+ Event("CollisionEvent") {}
+
+Collision CollisionEvent::getCollisionData() const { return this->collisionData; }
+
+TextSubmitEvent::TextSubmitEvent(std::string text) : text(text), Event("TextSubmitEvent") {}
+
+std::string TextSubmitEvent::getText() const { return this->text; }
+
+MouseReleasedEvent::MouseReleasedEvent(int x, int y, MouseButton button)
+ : mouseX(x),
+ mouseY(y),
+ button(button),
+ Event("MouseReleased") {}
+std::pair<int, int> MouseReleasedEvent::getMousePosition() const { return {mouseX, mouseY}; }
+MouseClickEvent::MouseClickEvent(int x, int y, MouseButton button)
+ : mouseX(x),
+ mouseY(y),
+ button(button),
+ Event("MouseClickEvent") {}
+MouseMovedEvent::MouseMovedEvent(int x, int y)
+ : mouseX(x),
+ mouseY(y),
+ Event("MouseMovedEvent") {}
+std::pair<int, int> MouseClickEvent::getMousePosition() const { return {mouseX, mouseY}; }
+std::pair<int, int> MouseMovedEvent::getMousePosition() const { return {mouseX, mouseY}; }
diff --git a/mwe/events/src/eventHandler.cpp b/mwe/events/src/eventHandler.cpp
new file mode 100644
index 0000000..7fb8d70
--- /dev/null
+++ b/mwe/events/src/eventHandler.cpp
@@ -0,0 +1,2 @@
+#include "eventHandler.h"
+void IEventHandlerWrapper::exec(const Event & e) { call(e); }
diff --git a/mwe/events/src/eventManager.cpp b/mwe/events/src/eventManager.cpp
new file mode 100644
index 0000000..9e7d880
--- /dev/null
+++ b/mwe/events/src/eventManager.cpp
@@ -0,0 +1,115 @@
+#include "eventManager.h"
+
+void EventManager::shutdown() { subscribers.clear(); }
+
+void EventManager::subscribe(int eventType, std::unique_ptr<IEventHandlerWrapper> && handler,
+ int eventId) {
+ if (eventId) {
+ std::unordered_map<
+ int, std::unordered_map<int, std::vector<std::unique_ptr<IEventHandlerWrapper>>>>::
+ iterator subscribers
+ = subscribersByEventId.find(eventType);
+
+ if (subscribers != subscribersByEventId.end()) {
+ std::unordered_map<int, std::vector<std::unique_ptr<IEventHandlerWrapper>>> &
+ handlersMap
+ = subscribers->second;
+ std::unordered_map<
+ int, std::vector<std::unique_ptr<IEventHandlerWrapper>>>::iterator handlers
+ = handlersMap.find(eventId);
+ if (handlers != handlersMap.end()) {
+ handlers->second.emplace_back(std::move(handler));
+ return;
+ }
+ }
+ subscribersByEventId[eventType][eventId].emplace_back(std::move(handler));
+
+ } else {
+ auto & handlers = subscribers[eventType];
+ handlers.emplace_back(std::move(handler));
+ }
+}
+
+void EventManager::unsubscribe(int eventType, const std::string & handlerName, int eventId) {
+ if (eventId) {
+ std::unordered_map<
+ int, std::unordered_map<int, std::vector<std::unique_ptr<IEventHandlerWrapper>>>>::
+ iterator subscriberList
+ = subscribersByEventId.find(eventType);
+ if (subscriberList != subscribersByEventId.end()) {
+ std::unordered_map<int, std::vector<std::unique_ptr<IEventHandlerWrapper>>> &
+ handlersMap
+ = subscriberList->second;
+ std::unordered_map<
+ int, std::vector<std::unique_ptr<IEventHandlerWrapper>>>::iterator handlers
+ = handlersMap.find(eventId);
+ if (handlers != handlersMap.end()) {
+ std::vector<std::unique_ptr<IEventHandlerWrapper>> & callbacks
+ = handlers->second;
+ for (std::vector<std::unique_ptr<IEventHandlerWrapper>>::iterator it
+ = callbacks.begin();
+ it != callbacks.end(); ++it) {
+ if (it->get()->getType() == handlerName) {
+ it = callbacks.erase(it);
+ return;
+ }
+ }
+ }
+ }
+ } else {
+ std::unordered_map<int, std::vector<std::unique_ptr<IEventHandlerWrapper>>>::iterator
+ handlersIt
+ = subscribers.find(eventType);
+ if (handlersIt != subscribers.end()) {
+ std::vector<std::unique_ptr<IEventHandlerWrapper>> & handlers = handlersIt->second;
+ for (std::vector<std::unique_ptr<IEventHandlerWrapper>>::iterator it
+ = handlers.begin();
+ it != handlers.end(); ++it) {
+ if (it->get()->getType() == handlerName) {
+ it = handlers.erase(it);
+ return;
+ }
+ }
+ }
+ }
+}
+
+void EventManager::triggerEvent(const Event & event_, int eventId) {
+ if (eventId > 0) {
+ auto handlersIt = subscribersByEventId[event_.getEventType()].find(eventId);
+ if (handlersIt != subscribersByEventId[event_.getEventType()].end()) {
+ std::vector<std::unique_ptr<IEventHandlerWrapper>> & callbacks
+ = handlersIt->second;
+ for (auto it = callbacks.begin(); it != callbacks.end();) {
+ (*it)->exec(event_);
+ if ((*it)->isDestroyOnSuccess()) {
+ it = callbacks.erase(it);
+ } else {
+ ++it;
+ }
+ }
+ }
+ } else {
+ auto & handlers = subscribers[event_.getEventType()];
+ for (std::unique_ptr<IEventHandlerWrapper> & handler : handlers) {
+ handler->exec(event_);
+ }
+ }
+}
+
+void EventManager::queueEvent(std::unique_ptr<Event> && event_, int eventId) {
+ eventsQueue.emplace_back(std::move(event_), eventId);
+}
+
+void EventManager::dispatchEvents() {
+ for (std::vector<std::pair<std::unique_ptr<Event>, int>>::iterator eventIt
+ = eventsQueue.begin();
+ eventIt != eventsQueue.end();) {
+ if (!eventIt->first.get()->getHandled()) {
+ triggerEvent(*eventIt->first.get(), eventIt->second);
+ eventIt = eventsQueue.erase(eventIt);
+ } else {
+ ++eventIt;
+ }
+ }
+}
diff --git a/mwe/events/src/iKeyListener.cpp b/mwe/events/src/iKeyListener.cpp
new file mode 100644
index 0000000..d5d1d90
--- /dev/null
+++ b/mwe/events/src/iKeyListener.cpp
@@ -0,0 +1,17 @@
+#include "iKeyListener.h"
+
+IKeyListener::~IKeyListener() { unsubscribeEvents(); }
+
+void IKeyListener::subscribeEvents(int listenerId) {
+ keyPressedHandler = [this](const KeyPressedEvent & event) { this->onKeyPressed(event); };
+ keyReleasedHandler
+ = [this](const KeyReleasedEvent & event) { this->onKeyReleased(event); };
+
+ subscribe<KeyPressedEvent>(keyPressedHandler, listenerId);
+ subscribe<KeyReleasedEvent>(keyReleasedHandler, listenerId);
+}
+
+void IKeyListener::unsubscribeEvents(int listenerId) {
+ unsubscribe<KeyPressedEvent>(keyPressedHandler, listenerId);
+ unsubscribe<KeyReleasedEvent>(keyReleasedHandler, listenerId);
+}
diff --git a/mwe/events/src/iMouseListener.cpp b/mwe/events/src/iMouseListener.cpp
new file mode 100644
index 0000000..53e6f80
--- /dev/null
+++ b/mwe/events/src/iMouseListener.cpp
@@ -0,0 +1,23 @@
+#include "iMouseListener.h"
+IMouseListener::~IMouseListener() { unsubscribeEvents(); }
+
+void IMouseListener::subscribeEvents(int listenerId) {
+ mouseClickHandler = [this](const MouseClickEvent & event) { this->onMouseClicked(event); };
+ mousePressHandler
+ = [this](const MousePressedEvent & event) { this->onMousePressed(event); };
+ mouseReleaseHandler
+ = [this](const MouseReleasedEvent & event) { this->onMouseReleased(event); };
+ mouseMoveHandler = [this](const MouseMovedEvent & event) { this->onMouseMoved(event); };
+
+ subscribe<MouseClickEvent>(mouseClickHandler, listenerId);
+ subscribe<MousePressedEvent>(mousePressHandler, listenerId);
+ subscribe<MouseReleasedEvent>(mouseReleaseHandler, listenerId);
+ subscribe<MouseMovedEvent>(mouseMoveHandler, listenerId);
+}
+
+void IMouseListener::unsubscribeEvents(int listenerId) {
+ unsubscribe<MouseClickEvent>(mouseClickHandler, listenerId);
+ unsubscribe<MousePressedEvent>(mousePressHandler, listenerId);
+ unsubscribe<MouseReleasedEvent>(mouseReleaseHandler, listenerId);
+ unsubscribe<MouseMovedEvent>(mouseMoveHandler, listenerId);
+}
diff --git a/mwe/events/src/inputSystem.cpp b/mwe/events/src/inputSystem.cpp
new file mode 100644
index 0000000..d740c9e
--- /dev/null
+++ b/mwe/events/src/inputSystem.cpp
@@ -0,0 +1,91 @@
+#include "inputSystem.h"
+
+InputSystem::InputSystem() {}
+
+void InputSystem::registerButton(Button * button) { buttons.push_back(button); }
+void InputSystem::registerTextInput(TextInput * input) { textInputs.push_back(input); }
+void InputSystem::registerText(Text * label) { texts.push_back(label); }
+
+void InputSystem::processInput() {
+ SDL_Event event;
+ while (SDL_PollEvent(&event)) {
+ switch (event.type) {
+ case SDL_QUIT:
+ triggerEvent(ShutDownEvent());
+ break;
+ case SDL_KEYDOWN:
+ triggerEvent(KeyPressedEvent(getCustomKey(event.key.keysym.sym)));
+ processKeyPress(event.key.keysym.sym);
+ break;
+ case SDL_TEXTINPUT:
+ // Process typed characters
+ processTextInput(event.text.text);
+ break;
+ case SDL_MOUSEBUTTONDOWN: {
+ int mouseX, mouseY;
+ SDL_GetMouseState(&mouseX, &mouseY);
+ processMouseClick(mouseX, mouseY);
+ triggerEvent(MousePressedEvent(mouseX, mouseY));
+ break;
+ }
+ }
+ }
+}
+
+void InputSystem::processMouseClick(int mouseX, int mouseY) {
+ for (auto * button : buttons) {
+ if (mouseX >= button->x && mouseX <= (button->x + button->width) && mouseY >= button->y
+ && mouseY <= (button->y + button->height)) {
+ button->onClick();
+ }
+ }
+ for (auto * textInput : textInputs) {
+ if (mouseX >= textInput->x && mouseX <= textInput->x + textInput->width
+ && mouseY >= textInput->y && mouseY <= textInput->y + textInput->height) {
+ textInput->isActive = true;
+ } else {
+ textInput->isActive = false;
+ }
+ }
+}
+void InputSystem::processKeyPress(Keycode key) {
+ // for (auto* textInput : textInputs) {
+ // if (textInput->isActive) {
+ // if (key == SDLK_RETURN || key == SDLK_KP_ENTER) {
+ // // Submit the text
+ // if (textInput->onSubmit) {
+ // textInput->onSubmit();
+ // }
+ // }
+ // else if (key == SDLK_BACKSPACE) {
+ // // Handle backspace
+ // if (!textInput->textBuffer.empty() && textInput->caretPosition > 0) {
+ // textInput->textBuffer.erase(textInput->caretPosition - 1, 1);
+ // textInput->caretPosition--;
+ // }
+ // }
+ // else if (key == SDLK_LEFT) {
+ // // Move caret left
+ // if (textInput->caretPosition > 0) {
+ // textInput->caretPosition--;
+ // }
+ // }
+ // else if (key == SDLK_RIGHT) {
+ // // Move caret right
+ // if (textInput->caretPosition < textInput->textBuffer.size()) {
+ // textInput->caretPosition++;
+ // }
+ // }
+ // }
+ // }
+}
+
+void InputSystem::processTextInput(const std::string & text) {
+ // for (auto* textInput : textInputs) {
+ // if (textInput->isActive) {
+ // // Insert text at caret position
+ // textInput->textBuffer.insert(textInput->caretPosition, text);
+ // textInput->caretPosition += text.length();
+ // }
+ // }
+}
diff --git a/mwe/events/src/keyCodes.cpp b/mwe/events/src/keyCodes.cpp
new file mode 100644
index 0000000..5f3aa96
--- /dev/null
+++ b/mwe/events/src/keyCodes.cpp
@@ -0,0 +1,139 @@
+#include "keyCodes.h"
+
+const std::unordered_map<SDL_Keycode, Keycode> sdlToCustom
+ = {{SDLK_SPACE, Space},
+ {SDLK_QUOTE, Apostrophe},
+ {SDLK_COMMA, Comma},
+ {SDLK_MINUS, Minus},
+ {SDLK_PERIOD, Period},
+ {SDLK_SLASH, Slash},
+
+ {SDLK_0, D0},
+ {SDLK_1, D1},
+ {SDLK_2, D2},
+ {SDLK_3, D3},
+ {SDLK_4, D4},
+ {SDLK_5, D5},
+ {SDLK_6, D6},
+ {SDLK_7, D7},
+ {SDLK_8, D8},
+ {SDLK_9, D9},
+
+ {SDLK_SEMICOLON, Semicolon},
+ {SDLK_EQUALS, Equal},
+
+ {SDLK_a, A},
+ {SDLK_b, B},
+ {SDLK_c, C},
+ {SDLK_d, D},
+ {SDLK_e, E},
+ {SDLK_f, F},
+ {SDLK_g, G},
+ {SDLK_h, H},
+ {SDLK_i, I},
+ {SDLK_j, J},
+ {SDLK_k, K},
+ {SDLK_l, L},
+ {SDLK_m, M},
+ {SDLK_n, N},
+ {SDLK_o, O},
+ {SDLK_p, P},
+ {SDLK_q, Q},
+ {SDLK_r, R},
+ {SDLK_s, S},
+ {SDLK_t, T},
+ {SDLK_u, U},
+ {SDLK_v, V},
+ {SDLK_w, W},
+ {SDLK_x, X},
+ {SDLK_y, Y},
+ {SDLK_z, Z},
+
+ {SDLK_LEFTBRACKET, LeftBracket},
+ {SDLK_BACKSLASH, Backslash},
+ {SDLK_RIGHTBRACKET, RightBracket},
+ {SDLK_BACKQUOTE, GraveAccent},
+
+ {SDLK_ESCAPE, Escape},
+ {SDLK_RETURN, Enter},
+ {SDLK_TAB, Tab},
+ {SDLK_BACKSPACE, Backspace},
+ {SDLK_INSERT, Insert},
+ {SDLK_DELETE, Delete},
+ {SDLK_RIGHT, Right},
+ {SDLK_LEFT, Left},
+ {SDLK_DOWN, Down},
+ {SDLK_UP, Up},
+ {SDLK_PAGEUP, PageUp},
+ {SDLK_PAGEDOWN, PageDown},
+ {SDLK_HOME, Home},
+ {SDLK_END, End},
+
+ {SDLK_CAPSLOCK, CapsLock},
+ {SDLK_SCROLLLOCK, ScrollLock},
+ {SDLK_NUMLOCKCLEAR, NumLock},
+ {SDLK_PRINTSCREEN, PrintScreen},
+ {SDLK_PAUSE, Pause},
+
+ {SDLK_F1, F1},
+ {SDLK_F2, F2},
+ {SDLK_F3, F3},
+ {SDLK_F4, F4},
+ {SDLK_F5, F5},
+ {SDLK_F6, F6},
+ {SDLK_F7, F7},
+ {SDLK_F8, F8},
+ {SDLK_F9, F9},
+ {SDLK_F10, F10},
+ {SDLK_F11, F11},
+ {SDLK_F12, F12},
+ {SDLK_F13, F13},
+ {SDLK_F14, F14},
+ {SDLK_F15, F15},
+ {SDLK_F16, F16},
+ {SDLK_F17, F17},
+ {SDLK_F18, F18},
+ {SDLK_F19, F19},
+ {SDLK_F20, F20},
+ {SDLK_F21, F21},
+ {SDLK_F22, F22},
+ {SDLK_F23, F23},
+ {SDLK_F24, F24},
+
+ {SDLK_KP_0, KP0},
+ {SDLK_KP_1, KP1},
+ {SDLK_KP_2, KP2},
+ {SDLK_KP_3, KP3},
+ {SDLK_KP_4, KP4},
+ {SDLK_KP_5, KP5},
+ {SDLK_KP_6, KP6},
+ {SDLK_KP_7, KP7},
+ {SDLK_KP_8, KP8},
+ {SDLK_KP_9, KP9},
+
+ {SDLK_KP_DECIMAL, KPDecimal},
+ {SDLK_KP_DIVIDE, KPDivide},
+ {SDLK_KP_MULTIPLY, KPMultiply},
+ {SDLK_KP_MINUS, KPSubtract},
+ {SDLK_KP_PLUS, KPAdd},
+ {SDLK_KP_ENTER, KPEnter},
+ {SDLK_KP_EQUALS, KPEqual},
+
+ {SDLK_LSHIFT, LeftShift},
+ {SDLK_LCTRL, LeftControl},
+ {SDLK_LALT, LeftAlt},
+ {SDLK_LGUI, LeftSuper},
+
+ {SDLK_RSHIFT, RightShift},
+ {SDLK_RCTRL, RightControl},
+ {SDLK_RALT, RightAlt},
+ {SDLK_RGUI, RightSuper},
+
+ {SDLK_MENU, Menu}};
+Keycode getCustomKey(SDL_Keycode sdlKey) {
+ auto it = sdlToCustom.find(sdlKey);
+ if (it != sdlToCustom.end()) {
+ return it->second;
+ }
+ return 0;
+}
diff --git a/mwe/events/src/keyListenerTest.cpp b/mwe/events/src/keyListenerTest.cpp
new file mode 100644
index 0000000..f45dffd
--- /dev/null
+++ b/mwe/events/src/keyListenerTest.cpp
@@ -0,0 +1,13 @@
+#include "keyListenerTest.h"
+
+KeyListenerTest::KeyListenerTest(int listenerId) { subscribeEvents(listenerId); }
+
+KeyListenerTest::~KeyListenerTest() { unsubscribeEvents(); }
+
+void KeyListenerTest::onKeyPressed(const KeyPressedEvent & event) {
+ std::cout << "Key pressed: " << event.getKeyCode() << std::endl;
+}
+
+void KeyListenerTest::onKeyReleased(const KeyReleasedEvent & event) {
+ std::cout << "Key released: " << event.getKeyCode() << std::endl;
+}
diff --git a/mwe/events/src/loopManager.cpp b/mwe/events/src/loopManager.cpp
new file mode 100644
index 0000000..c58a5e7
--- /dev/null
+++ b/mwe/events/src/loopManager.cpp
@@ -0,0 +1,99 @@
+#include "loopManager.h"
+
+LoopManager::LoopManager() : inputSystem(std::make_unique<InputSystem>()) {
+ shutdownHandler = [this](const ShutDownEvent & event) { this->onShutdown(event); };
+ subscribe(shutdownHandler);
+}
+void LoopManager::processInput() {
+ inputSystem->processInput();
+ // SDL_Event event;
+ // SDL_PollEvent(&event);
+ // switch (event.type) {
+ // case SDL_QUIT:
+ // gameRunning = false;
+ // break;
+ // case SDL_KEYDOWN:
+ // triggerEvent(KeyPressedEvent(getCustomKey(event.key.keysym.sym)));
+ // break;
+ // case SDL_MOUSEBUTTONDOWN:
+ // int x, y;
+ // SDL_GetMouseState(&x, &y);
+ // triggerEvent(MousePressedEvent(x, y));
+ // break;
+ // }
+}
+void LoopManager::setRunning(bool running) { this->gameRunning = running; }
+void LoopManager::fixedUpdate() {
+ //fprintf(stderr, "fixed update\n");
+}
+void LoopManager::loop() {
+ LoopTimer & timer = LoopTimer::getInstance();
+ timer.start();
+
+ while (gameRunning) {
+ timer.update();
+ processInput();
+ while (timer.getLag() >= timer.getFixedDeltaTime()) {
+ fixedUpdate();
+ timer.advanceFixedUpdate();
+ }
+
+ update();
+ render();
+
+ timer.enforceFrameRate();
+ }
+
+ window.destroyWindow();
+}
+void onKey(const KeyPressedEvent & e) {
+ int keyCode = e.getKeyCode();
+ std::cout << "keycode pressed: " << keyCode << std::endl;
+}
+void onMouse(const MousePressedEvent & e) {
+ fprintf(stderr, "mouse Position X: %d Y: %d\n", e.getMousePosition().first,
+ e.getMousePosition().second);
+}
+void LoopManager::setup() {
+ gameRunning = window.initWindow();
+ LoopTimer::getInstance().start();
+ LoopTimer::getInstance().setFPS(50);
+ EventHandler<KeyPressedEvent> callback = onKey;
+ subscribe<KeyPressedEvent>(callback, false);
+ EventHandler<MousePressedEvent> mouseCallback = onMouse;
+ subscribe<MousePressedEvent>(mouseCallback, false);
+ EventHandler<KeyPressedEvent> closeWindowCallback = [this](const KeyPressedEvent & e) {
+ if (e.getKeyCode() == Escape) {
+ this->setRunning(false);
+ }
+ };
+ subscribe<KeyPressedEvent>(closeWindowCallback, false);
+ Button * testButton = new Button(200, 200);
+ testButton->color = {100, 0, 100};
+ testButton->onClick = []() { std::cout << "Button was clicked" << std::endl; };
+ testButton->x = 200;
+ testButton->y = 200;
+ inputSystem->registerButton(testButton);
+
+ window.addUIObject(testButton);
+
+ TextInput * testInput = new TextInput(200, 200);
+ testInput->x = 100;
+ testInput->y = 100;
+ testInput->backgroundColor = {20, 50, 80};
+ inputSystem->registerTextInput(testInput);
+ window.addUIObject(testInput);
+}
+void LoopManager::render() {
+ //fprintf(stderr, "**********render********** \n");
+ if (gameRunning) {
+ window.renderUIObjects();
+ }
+}
+void LoopManager::onShutdown(const ShutDownEvent & e) { this->gameRunning = false; }
+void LoopManager::update() {
+ //fprintf(stderr, "**********normal update********** \n");
+ LoopTimer & timer = LoopTimer::getInstance();
+
+ float delta = timer.getDeltaTime();
+}
diff --git a/mwe/events/src/main.cpp b/mwe/events/src/main.cpp
new file mode 100644
index 0000000..ad0fd69
--- /dev/null
+++ b/mwe/events/src/main.cpp
@@ -0,0 +1,86 @@
+#include "customTypes.h"
+#include "event.h"
+#include "iKeyListener.h"
+#include "iMouseListener.h"
+#include "keyListenerTest.h"
+#include "loopManager.h"
+#include "mouseListenerTest.h"
+#include <SDL2/SDL.h>
+#include <iostream>
+#include <memory>
+class PlayerDamagedEvent : public Event {
+public:
+ PlayerDamagedEvent(int damage, int playerID)
+ : Event("PlayerDamaged"),
+ damage(damage),
+ playerID(playerID) {}
+
+ REGISTER_EVENT_TYPE(PlayerDamagedEvent);
+
+ int getDamage() const { return damage; }
+ int getPlayerID() const { return playerID; }
+
+private:
+ int damage;
+ int playerID;
+};
+void onPlayerDamaged(const PlayerDamagedEvent & e) {
+ std::cout << "Player " << e.getPlayerID() << " took " << e.getDamage() << " damage."
+ << std::endl;
+}
+
+void onKeyPressed1(const KeyPressedEvent & e) {
+ int keyCode = e.getKeyCode();
+ fprintf(stderr, "first function KeyCode %d\n", keyCode);
+}
+void onKeyPressed(const KeyPressedEvent & e) {
+ int keyCode = e.getKeyCode();
+ fprintf(stderr, "second function KeyCode %d\n", keyCode);
+}
+void CollisionHandler(const CollisionEvent & e) {
+ std::cout << "collision betwee object id: " << e.getCollisionData().objectIdA
+ << " and id: " << e.getCollisionData().objectIdB << std::endl;
+}
+void testCollisionEvent() {
+ Collision testCollision(1, 2, {3, 4}, {5, 6}, 7.8f);
+ subscribe<CollisionEvent>(CollisionHandler, 1);
+ // EventHandler<PlayerDamagedEvent>
+ triggerEvent(CollisionEvent(testCollision), 1);
+}
+int main(int argc, char * args[]) {
+ LoopManager gameLoop;
+ int testListenerId = 0;
+ KeyListenerTest keyListener(testListenerId);
+ MouseListenerTest mouseListener(testListenerId);
+ // custom event class poc
+ subscribe<PlayerDamagedEvent>(onPlayerDamaged);
+ triggerEvent(PlayerDamagedEvent(50, 1));
+ subscribe<KeyPressedEvent>(onKeyPressed, 1, false);
+ subscribe<KeyPressedEvent>(onKeyPressed1, false);
+ // queueEvent(std::move(anotherKeyPressEvent));
+ triggerEvent(KeyPressedEvent(42), 1);
+
+ EventManager::getInstance().dispatchEvents();
+ //collision event call
+ testCollisionEvent();
+
+ gameLoop.setup();
+ gameLoop.loop();
+ return 0;
+}
+// void collisionUpdate(){
+// int count;
+// //iedere collision
+// for (int i = 0; i < count; i++)
+// {
+// //trigger object 1
+// //triger object 2
+// triggerEvent(CollisionEvent(1,2),1);
+// triggerEvent(CollisionEvent(1,2),2);
+// }
+
+// }
+// int main(){
+
+// return 0;
+// }
diff --git a/mwe/events/src/mouseListenerTest.cpp b/mwe/events/src/mouseListenerTest.cpp
new file mode 100644
index 0000000..7b35f4e
--- /dev/null
+++ b/mwe/events/src/mouseListenerTest.cpp
@@ -0,0 +1,25 @@
+#include "mouseListenerTest.h"
+
+MouseListenerTest::MouseListenerTest(int listenerId) { subscribeEvents(listenerId); }
+
+MouseListenerTest::~MouseListenerTest() { unsubscribeEvents(); }
+
+void MouseListenerTest::onMouseClicked(const MouseClickEvent & event) {
+ std::cout << "Mouse clicked at: (" << event.getMousePosition().first << ", "
+ << event.getMousePosition().second << ")" << std::endl;
+}
+
+void MouseListenerTest::onMousePressed(const MousePressedEvent & event) {
+ std::cout << "Mouse button pressed at: (" << event.getMousePosition().first << ", "
+ << event.getMousePosition().second << ")" << std::endl;
+}
+
+void MouseListenerTest::onMouseReleased(const MouseReleasedEvent & event) {
+ std::cout << "Mouse button released at: (" << event.getMousePosition().first << ", "
+ << event.getMousePosition().second << ")" << std::endl;
+}
+
+void MouseListenerTest::onMouseMoved(const MouseMovedEvent & event) {
+ std::cout << "Mouse moved to: (" << event.getMousePosition().first << ", "
+ << event.getMousePosition().second << ")" << std::endl;
+}
diff --git a/mwe/events/src/timer.cpp b/mwe/events/src/timer.cpp
new file mode 100644
index 0000000..0f8339f
--- /dev/null
+++ b/mwe/events/src/timer.cpp
@@ -0,0 +1,52 @@
+#include "timer.h"
+
+LoopTimer::LoopTimer() {}
+LoopTimer & LoopTimer::getInstance() {
+ static LoopTimer instance;
+ return instance;
+}
+
+void LoopTimer::start() {
+ lastFrameTime = SDL_GetTicks64();
+ elapsedTime = 0;
+ elapsedFixedTime = 0;
+ deltaTime = 0;
+}
+
+// Update the timer, calculate deltaTime
+void LoopTimer::update() {
+ uint64_t currentFrameTime = SDL_GetTicks64();
+ deltaTime = (currentFrameTime - lastFrameTime) / 1000.0;
+
+ if (deltaTime > maximumDeltaTime) {
+ deltaTime = maximumDeltaTime;
+ }
+
+ elapsedTime += deltaTime;
+ lastFrameTime = currentFrameTime;
+}
+
+double LoopTimer::getDeltaTime() const { return deltaTime; }
+int LoopTimer::getCurrentTime() const { return SDL_GetTicks(); }
+
+void LoopTimer::advanceFixedUpdate() { elapsedFixedTime += fixedDeltaTime; }
+
+double LoopTimer::getFixedDeltaTime() const { return fixedDeltaTime; }
+
+void LoopTimer::setFPS(int FPS) {
+ this->FPS = FPS;
+ frameTargetTime = 1.0 / FPS;
+}
+
+int LoopTimer::getFPS() const { return FPS; }
+
+void LoopTimer::enforceFrameRate() {
+ uint64_t currentFrameTime = SDL_GetTicks64();
+ double frameDuration = (currentFrameTime - lastFrameTime) / 1000.0;
+
+ if (frameDuration < frameTargetTime) {
+ uint32_t delayTime = (uint32_t) ((frameTargetTime - frameDuration) * 1000.0);
+ SDL_Delay(delayTime);
+ }
+}
+double LoopTimer::getLag() const { return elapsedTime - elapsedFixedTime; }
diff --git a/mwe/events/src/uiObject.cpp b/mwe/events/src/uiObject.cpp
new file mode 100644
index 0000000..947d1a2
--- /dev/null
+++ b/mwe/events/src/uiObject.cpp
@@ -0,0 +1,31 @@
+#include "uiObject.h"
+
+// Constructor for UIObject
+UIObject::UIObject(int width, int height) : width(width), height(height) {}
+
+// Constructor for Button
+Button::Button(int width, int height) : UIObject(width, height) {}
+
+Text::Text(int width, int height)
+ : UIObject(width, height),
+ size(12),
+ font(nullptr),
+ color{255, 255, 255} { // Default size and color
+ alignment.horizontal = Alignment::Horizontal::CENTER;
+ alignment.vertical = Alignment::Vertical::MIDDLE;
+ alignment.mode = Alignment::PositioningMode::RELATIVE;
+}
+
+TextInput::TextInput(int width, int height)
+ : UIObject(width, height),
+ textBuffer(""),
+ placeholder(""),
+ isActive(false),
+ textColor{255, 255, 255},
+ backgroundColor{0, 0, 0},
+ maxLength(100),
+ font(nullptr) {
+ alignment.horizontal = Alignment::Horizontal::LEFT;
+ alignment.vertical = Alignment::Vertical::TOP;
+ alignment.mode = Alignment::PositioningMode::RELATIVE;
+}
diff --git a/mwe/events/src/uiRenderer.cpp b/mwe/events/src/uiRenderer.cpp
new file mode 100644
index 0000000..ca8d284
--- /dev/null
+++ b/mwe/events/src/uiRenderer.cpp
@@ -0,0 +1,104 @@
+#include "uiRenderer.h"
+
+// Constructor
+UIRenderer::UIRenderer(SDL_Renderer * renderer) : renderer(renderer) {}
+
+// Render function
+void UIRenderer::render(UIObject * uiObject) {
+ if (Button * button = dynamic_cast<Button *>(uiObject)) {
+ renderButton(button);
+ } else if (Text * text = dynamic_cast<Text *>(uiObject)) {
+ renderText(text);
+ } else if (TextInput * textInput = dynamic_cast<TextInput *>(uiObject)) {
+ renderTextInput(textInput);
+ }
+}
+
+// Private helper function to render a Button
+void UIRenderer::renderButton(Button * button) {
+ SDL_Rect buttonRect = {button->x, button->y, button->width, button->height};
+ SDL_SetRenderDrawColor(renderer, 100, 100, 255, 255); // Button color
+ SDL_RenderFillRect(renderer, &buttonRect);
+}
+
+// Private helper function to render a Text
+void UIRenderer::renderText(Text * text) {
+ if (text->font != nullptr) {
+ SDL_Color sdlColor = {text->color.red, text->color.green, text->color.blue, 255};
+ SDL_Surface * textSurface
+ = TTF_RenderText_Blended(text->font, text->text.c_str(), sdlColor);
+ if (!textSurface) {
+ std::cerr << "Error creating text surface: " << TTF_GetError() << std::endl;
+ return;
+ }
+
+ SDL_Texture * textTexture = SDL_CreateTextureFromSurface(renderer, textSurface);
+ if (!textTexture) {
+ std::cerr << "Error creating texture from surface: " << SDL_GetError()
+ << std::endl;
+ SDL_FreeSurface(textSurface);
+ return;
+ }
+
+ SDL_Rect textRect = {text->x, text->y, textSurface->w, textSurface->h};
+ SDL_RenderCopy(renderer, textTexture, nullptr, &textRect);
+ SDL_FreeSurface(textSurface);
+ SDL_DestroyTexture(textTexture);
+ }
+}
+
+void UIRenderer::renderTextInput(TextInput * textInput) {
+ // // Check if textInput or renderer is null to avoid segmentation faults
+ // if (!textInput || !renderer) {
+ // std::cerr << "Error: Null pointer detected for textInput or renderer." << std::endl;
+ // return;
+ // }
+
+ // // Render the background rectangle for the text input
+ // SDL_Rect inputRect = {textInput->x, textInput->y, textInput->width, textInput->height};
+ // SDL_SetRenderDrawColor(renderer, textInput->backgroundColor.red, textInput->backgroundColor.green, textInput->backgroundColor.blue, 255);
+ // SDL_RenderFillRect(renderer, &inputRect);
+
+ // // Check if font is valid
+ // if (!textInput->font) {
+ // std::cerr << "Error: Font is not loaded for textInput." << std::endl;
+ // return;
+ // }
+
+ // SDL_Color sdlColor = {textInput->textColor.red, textInput->textColor.green, textInput->textColor.blue, 255};
+
+ // if (!textInput->textBuffer.empty()) {
+ // // Render the text in the input field
+ // SDL_Surface* textSurface = TTF_RenderText_Blended(textInput->font, textInput->textBuffer.c_str(), sdlColor);
+ // if (textSurface) {
+ // SDL_Texture* textTexture = SDL_CreateTextureFromSurface(renderer, textSurface);
+ // if (textTexture) {
+ // SDL_Rect textRect = {textInput->x + 5, textInput->y + 5, textSurface->w, textSurface->h};
+ // SDL_RenderCopy(renderer, textTexture, nullptr, &textRect);
+ // SDL_DestroyTexture(textTexture);
+ // } else {
+ // std::cerr << "Error: Unable to create texture from text surface." << std::endl;
+ // }
+ // SDL_FreeSurface(textSurface);
+ // } else {
+ // std::cerr << "Error: Unable to create text surface." << std::endl;
+ // }
+ // } else if (!textInput->placeholder.empty()) {
+ // // Render the placeholder text
+ // SDL_Color placeholderColor = {128, 128, 128, 255}; // Light gray for placeholder
+ // SDL_Surface* placeholderSurface = TTF_RenderText_Blended(textInput->font, textInput->placeholder.c_str(), placeholderColor);
+ // if (placeholderSurface) {
+ // SDL_Texture* placeholderTexture = SDL_CreateTextureFromSurface(renderer, placeholderSurface);
+ // if (placeholderTexture) {
+ // SDL_Rect placeholderRect = {textInput->x + 5, textInput->y + 5, placeholderSurface->w, placeholderSurface->h};
+ // SDL_RenderCopy(renderer, placeholderTexture, nullptr, &placeholderRect);
+ // SDL_DestroyTexture(placeholderTexture);
+ // } else {
+ // std::cerr << "Error: Unable to create texture from placeholder surface." << std::endl;
+ // }
+ // SDL_FreeSurface(placeholderSurface);
+ // } else {
+ // std::cerr << "Error: Unable to create placeholder surface." << std::endl;
+ // }
+ // }
+}
diff --git a/mwe/events/src/window.cpp b/mwe/events/src/window.cpp
new file mode 100644
index 0000000..af2b627
--- /dev/null
+++ b/mwe/events/src/window.cpp
@@ -0,0 +1,45 @@
+#include "window.h"
+#include <iostream>
+
+WindowManager::WindowManager() { this->uiRenderer = nullptr; }
+
+WindowManager::~WindowManager() { destroyWindow(); }
+
+bool WindowManager::initWindow() {
+ if (SDL_Init(SDL_INIT_EVERYTHING) != 0) {
+ std::cerr << "Error initializing SDL.\n";
+ return false;
+ }
+
+ window = SDL_CreateWindow("SDL Tutorial", SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED,
+ SCREEN_WIDTH, SCREEN_HEIGHT, SDL_WINDOW_SHOWN);
+ if (!window) {
+ std::cerr << "Error creating SDL Window.\n";
+ return false;
+ }
+
+ renderer = SDL_CreateRenderer(window, -1, SDL_RENDERER_ACCELERATED);
+ if (!renderer) {
+ std::cerr << "Error creating SDL renderer.\n";
+ return false;
+ }
+
+ uiRenderer = new UIRenderer(renderer);
+ return true;
+}
+
+void WindowManager::destroyWindow() {
+ SDL_DestroyRenderer(renderer);
+ SDL_DestroyWindow(window);
+ SDL_Quit();
+}
+
+SDL_Renderer * WindowManager::getRenderer() { return renderer; }
+void WindowManager::addUIObject(UIObject * uiObject) { uiObjects.push_back(uiObject); }
+
+void WindowManager::renderUIObjects() {
+ for (UIObject * obj : uiObjects) {
+ uiRenderer->render(obj);
+ }
+ SDL_RenderPresent(this->renderer);
+}