From 65806c12855f17174557b6b43b0e9eb574997be9 Mon Sep 17 00:00:00 2001 From: Linus Probert Date: Wed, 14 Feb 2018 23:14:30 +0100 Subject: [PATCH] Fixed menu-mouse-click crash. Not sure about this. Having click events on buttons that destroy the actual button might seem pretty stupid. But I think I'd rather have that then having to think about menu memory allocation maintenance constantly. --- TODO.txt | 2 +- src/gui_button.c | 3 +- src/menu.c | 82 +++++++++++++++++++++++++++++++++--------------- 3 files changed, 60 insertions(+), 27 deletions(-) diff --git a/TODO.txt b/TODO.txt index 3954fc7..ffdddd6 100644 --- a/TODO.txt +++ b/TODO.txt @@ -31,7 +31,7 @@ x Menus x In game menu x Player death (GAME_OVER state) (graphic or text?) o Sound? -- Fix crash when clicking menu items with pointer +x Fix crash when clicking menu items with pointer - Make things less difficult and more interesting - Interesting items - A different license perhaps? diff --git a/src/gui_button.c b/src/gui_button.c index cd50d04..e8c1429 100644 --- a/src/gui_button.c +++ b/src/gui_button.c @@ -29,7 +29,8 @@ gui_button_handle_event(GuiButton *button, SDL_Event *event) if (event->button.button != SDL_BUTTON_LEFT) return; - if (button->hover && button->event) + Position p = { event->button.x, event->button.y }; + if (position_in_rect(&p, &button->area) && button->event) button->event(button->usrdata); } else if (event->type == SDL_MOUSEMOTION) { diff --git a/src/menu.c b/src/menu.c index 4c1a7fb..478274d 100644 --- a/src/menu.c +++ b/src/menu.c @@ -23,56 +23,86 @@ menu_create(void) return menu; } -void -menu_handle_event(Menu *m, SDL_Event *event) +static void +handle_keyboard_event(Menu *m, SDL_Event *event) { - LinkedList *items; - bool reset_buttons = false; - bool trigger_button = false; + int lastSelect = -1; if (keyboard_direction_press(UP, event)) { + lastSelect = m->selected; m->selected--; - reset_buttons = true; } else if (keyboard_direction_press(DOWN, event)) { + lastSelect = m->selected; m->selected++; - reset_buttons = true; } else if (keyboard_press(SDLK_RETURN, event)) { - trigger_button = true; - } - m->selected = m->selected % linkedlist_size(m->items); - - if (trigger_button) { MenuItem *item = linkedlist_get(&m->items, m->selected); if (item->button->event) item->button->event(item->button->usrdata); return; + } else { + return; } + m->selected = m->selected % linkedlist_size(m->items); - if (reset_buttons) + if (lastSelect != -1) mixer_play_effect(CLICK); - int current_select = 0; - bool mouse_selection = false; - items = m->items; - while (items) { - MenuItem *item = items->data; - items = items->next; - if (reset_buttons) - item->button->hover = false; + ((MenuItem*) linkedlist_get(&m->items, lastSelect))->button->hover = false; + ((MenuItem*) linkedlist_get(&m->items, m->selected))->button->hover = true; +} +static void +handle_mouse_motion_event(Menu *m, SDL_Event *event) +{ + LinkedList *items; + MenuItem *item; + int current_select; + bool activeItemFound = false; + + items = m->items; + current_select = 0; + while (items) { + item = items->data; + items = items->next; + + item->button->hover = false; gui_button_handle_event(item->button, event); if (item->button->hover) { - m->selected = current_select; - mouse_selection = true; + if (current_select != m->selected) { + mixer_play_effect(CLICK); + m->selected = current_select; + } + activeItemFound = true; } - current_select++; } - if (!mouse_selection) + if (!activeItemFound) ((MenuItem*) linkedlist_get(&m->items, m->selected))->button->hover = true; } +static void +handle_mouse_button_event(Menu *m, SDL_Event *event) +{ + /* NOTE: In some cases the button/item is destroyed by the click action + * make sure you don't 'use' items after a click event has fired. It + * might break. */ + + MenuItem *item = linkedlist_get(&m->items, m->selected); + gui_button_handle_event(item->button, event); +} + +void +menu_handle_event(Menu *m, SDL_Event *event) +{ + if (event->type == SDL_KEYDOWN) + handle_keyboard_event(m, event); + else if (event->type == SDL_MOUSEMOTION) + handle_mouse_motion_event(m, event); + else if (event->type == SDL_MOUSEBUTTONDOWN) + handle_mouse_button_event(m, event); +} + void menu_item_add(Menu *m, Sprite *s1, Sprite *s2, void (*event)(void*)) { @@ -87,6 +117,8 @@ menu_item_add(Menu *m, Sprite *s1, Sprite *s2, void (*event)(void*)) item->sprite->textures[0]->dim.height }; item->button = gui_button_create(area, event, NULL); + if (linkedlist_size(m->items) == 0) + item->button->hover = true; linkedlist_append(&m->items, item); }