diff options
Diffstat (limited to 'src/crepe/system/InputSystem.cpp')
-rw-r--r-- | src/crepe/system/InputSystem.cpp | 187 |
1 files changed, 187 insertions, 0 deletions
diff --git a/src/crepe/system/InputSystem.cpp b/src/crepe/system/InputSystem.cpp new file mode 100644 index 0000000..afd71fe --- /dev/null +++ b/src/crepe/system/InputSystem.cpp @@ -0,0 +1,187 @@ +#include "../ComponentManager.h" +#include "../api/Button.h" +#include "../api/EventManager.h" + +#include "InputSystem.h" + +using namespace crepe; + +void InputSystem::update() { + ComponentManager & mgr = this->component_manager; + EventManager & event_mgr = EventManager::get_instance(); + std::vector<SDLContext::EventData> event_list = SDLContext::get_instance().get_events(); + RefVector<Button> buttons = mgr.get_components_by_type<Button>(); + RefVector<Camera> cameras = mgr.get_components_by_type<Camera>(); + OptionalRef<Camera> curr_cam_ref; + // Find the active camera + for (Camera & cam : cameras) { + if (!cam.active) continue; + curr_cam_ref = cam; + break; + } + if (!curr_cam_ref) return; + Camera & current_cam = curr_cam_ref; + RefVector<Transform> transform_vec + = mgr.get_components_by_id<Transform>(current_cam.game_object_id); + Transform & cam_transform = transform_vec.front().get(); + int camera_origin_x + = cam_transform.position.x + current_cam.offset.x - (current_cam.viewport_size.x / 2); + int camera_origin_y + = cam_transform.position.y + current_cam.offset.y - (current_cam.viewport_size.y / 2); + + for (const SDLContext::EventData & event : event_list) { + int world_mouse_x = event.mouse_position.first + camera_origin_x; + int world_mouse_y = event.mouse_position.second + camera_origin_y; + // check if the mouse is within the viewport + bool mouse_in_viewport + = !(world_mouse_x < camera_origin_x + || world_mouse_x > camera_origin_x + current_cam.viewport_size.x + || world_mouse_y < camera_origin_y + || world_mouse_y > camera_origin_y + current_cam.viewport_size.y); + + switch (event.event_type) { + case SDLContext::EventType::KEYDOWN: + event_mgr.queue_event<KeyPressEvent>(KeyPressEvent{ + .repeat = event.key_repeat, + .key = event.key, + }); + break; + case SDLContext::EventType::KEYUP: + event_mgr.queue_event<KeyReleaseEvent>(KeyReleaseEvent{ + .key = event.key, + }); + break; + case SDLContext::EventType::MOUSEDOWN: + if (!mouse_in_viewport) { + break; + } + event_mgr.queue_event<MousePressEvent>(MousePressEvent{ + .mouse_x = world_mouse_x, + .mouse_y = world_mouse_y, + .button = event.mouse_button, + }); + this->last_mouse_down_position = {world_mouse_x, world_mouse_y}; + this->last_mouse_button = event.mouse_button; + break; + case SDLContext::EventType::MOUSEUP: { + if (!mouse_in_viewport) { + break; + } + event_mgr.queue_event<MouseReleaseEvent>(MouseReleaseEvent{ + .mouse_x = world_mouse_x, + .mouse_y = world_mouse_y, + .button = event.mouse_button, + }); + //check if its a click by checking the last button down + int delta_x = world_mouse_x - this->last_mouse_down_position.x; + int delta_y = world_mouse_y - this->last_mouse_down_position.y; + + if (this->last_mouse_button == event.mouse_button + && std::abs(delta_x) <= click_tolerance + && std::abs(delta_y) <= click_tolerance) { + event_mgr.queue_event<MouseClickEvent>(MouseClickEvent{ + .mouse_x = world_mouse_x, + .mouse_y = world_mouse_y, + .button = event.mouse_button, + }); + + this->handle_click(event.mouse_button, world_mouse_x, world_mouse_y); + } + } break; + case SDLContext::EventType::MOUSEMOVE: + if (!mouse_in_viewport) { + break; + } + event_mgr.queue_event<MouseMoveEvent>(MouseMoveEvent{ + .mouse_x = world_mouse_x, + .mouse_y = world_mouse_y, + .delta_x = event.rel_mouse_move.first, + .delta_y = event.rel_mouse_move.second, + }); + this->handle_move(event, world_mouse_x, world_mouse_y); + break; + case SDLContext::EventType::MOUSEWHEEL: + event_mgr.queue_event<MouseScrollEvent>(MouseScrollEvent{ + .mouse_x = world_mouse_x, + .mouse_y = world_mouse_y, + .scroll_direction = event.scroll_direction, + .scroll_delta = event.scroll_delta, + }); + break; + case SDLContext::EventType::SHUTDOWN: + event_mgr.queue_event<ShutDownEvent>(ShutDownEvent{}); + break; + default: + break; + } + } +} +void InputSystem::handle_move(const SDLContext::EventData & event_data, + const int world_mouse_x, const int world_mouse_y) { + ComponentManager & mgr = this->component_manager; + + RefVector<Button> buttons = mgr.get_components_by_type<Button>(); + + for (Button & button : buttons) { + RefVector<Transform> transform_vec + = mgr.get_components_by_id<Transform>(button.game_object_id); + Transform & transform(transform_vec.front().get()); + + bool was_hovering = button.hover; + if (button.active + && this->is_mouse_inside_button(world_mouse_x, world_mouse_y, button, transform)) { + button.hover = true; + if (!was_hovering && button.on_mouse_enter) { + button.on_mouse_enter(); + } + } else { + button.hover = false; + // Trigger the on_exit callback if the hover state just changed to false + if (was_hovering && button.on_mouse_exit) { + button.on_mouse_exit(); + } + } + } +} + +void InputSystem::handle_click(const MouseButton & mouse_button, const int world_mouse_x, + const int world_mouse_y) { + ComponentManager & mgr = this->component_manager; + + RefVector<Button> buttons = mgr.get_components_by_type<Button>(); + + for (Button & button : buttons) { + RefVector<Transform> transform_vec + = mgr.get_components_by_id<Transform>(button.game_object_id); + Transform & transform = transform_vec.front().get(); + + if (button.active + && this->is_mouse_inside_button(world_mouse_x, world_mouse_y, button, transform)) { + this->handle_button_press(button); + } + } +} + +bool InputSystem::is_mouse_inside_button(const int mouse_x, const int mouse_y, + const Button & button, const Transform & transform) { + int actual_x = transform.position.x + button.offset.x; + int actual_y = transform.position.y + button.offset.y; + + int half_width = button.dimensions.x / 2; + int half_height = button.dimensions.y / 2; + + // Check if the mouse is within the button's boundaries + return mouse_x >= actual_x - half_width && mouse_x <= actual_x + half_width + && mouse_y >= actual_y - half_height && mouse_y <= actual_y + half_height; +} + +void InputSystem::handle_button_press(Button & button) { + if (button.is_toggle) { + if (!button.is_pressed && button.on_click) { + button.on_click(); + } + button.is_pressed = !button.is_pressed; + } else if (button.on_click) { + button.on_click(); + } +} |