From b401b3dbc17b21cfb148715225dad30fcf7975e6 Mon Sep 17 00:00:00 2001 From: Nat Quayle Nelson Date: Sat, 15 Mar 2025 16:50:17 -0500 Subject: [PATCH] tiny 'arrow' buttons use event loop to allow cancel click --- src/game/boe.actions.cpp | 130 +++++++++++++++++++------------------- src/game/boe.graphics.cpp | 39 ++++++++++-- src/game/boe.graphics.hpp | 3 +- 3 files changed, 100 insertions(+), 72 deletions(-) diff --git a/src/game/boe.actions.cpp b/src/game/boe.actions.cpp index b315cab9..abb74728 100644 --- a/src/game/boe.actions.cpp +++ b/src/game/boe.actions.cpp @@ -1612,8 +1612,8 @@ bool handle_action(const sf::Event& event, cFramerateLimiter& fps_limiter) { if(point_in_area.in(pc_help_button)) { rectangle help_button = pc_help_button; help_button.offset(pc_win_ul); - arrow_button_click(help_button); - show_dialog_action("help-party"); + if(arrow_button_click(help_button, &fps_limiter)) + show_dialog_action("help-party"); } for(int i = 0; i < 6; i++) for(auto j : pc_buttons[i].keys()) @@ -1623,27 +1623,27 @@ bool handle_action(const sf::Event& event, cFramerateLimiter& fps_limiter) { break; rectangle button_rect = pc_buttons[i][j]; button_rect.offset(pc_win_ul); - arrow_button_click(button_rect); - switch(j) { - case PCBTN_NAME: - handle_switch_pc(i, need_redraw, need_reprint); - break; - case PCBTN_HP: - handle_print_pc_hp(i, need_reprint); - break; - case PCBTN_SP: - handle_print_pc_sp(i, need_reprint); - break; - case PCBTN_INFO: - give_pc_info(i); - // don't call advance_time - return false; - case PCBTN_TRADE: - handle_trade_places(i, need_reprint); - break; - case MAX_ePlayerButton: - break; // Not a button - } + if(arrow_button_click(button_rect, &fps_limiter)) + switch(j) { + case PCBTN_NAME: + handle_switch_pc(i, need_redraw, need_reprint); + break; + case PCBTN_HP: + handle_print_pc_hp(i, need_reprint); + break; + case PCBTN_SP: + handle_print_pc_sp(i, need_reprint); + break; + case PCBTN_INFO: + give_pc_info(i); + // don't call advance_time + return false; + case PCBTN_TRADE: + handle_trade_places(i, need_reprint); + break; + case MAX_ePlayerButton: + break; // Not a button + } } put_pc_screen(); put_item_screen(stat_window); @@ -1664,21 +1664,21 @@ bool handle_action(const sf::Event& event, cFramerateLimiter& fps_limiter) { if(item_bottom_button_active[i] > 0 && point_in_area.in(item_screen_button_rects[i])) { rectangle button_rect = item_screen_button_rects[i]; button_rect.offset(item_win_ul); - arrow_button_click(button_rect); - switch(i) { - case 6: // special screen - set_stat_window(ITEM_WIN_SPECIAL, true); - break; - case 7: - set_stat_window(ITEM_WIN_QUESTS, true); - break; - case 8: // help - show_dialog_action("help-inventory"); - break; - default: - handle_switch_pc_items(i, need_redraw); - break; - } + if(arrow_button_click(button_rect, &fps_limiter)) + switch(i) { + case 6: // special screen + set_stat_window(ITEM_WIN_SPECIAL, true); + break; + case 7: + set_stat_window(ITEM_WIN_QUESTS, true); + break; + case 8: // help + show_dialog_action("help-inventory"); + break; + default: + handle_switch_pc_items(i, need_redraw); + break; + } } if(stat_window <= ITEM_WIN_QUESTS) { for(int i = 0; i < 8; i++) @@ -1686,33 +1686,33 @@ bool handle_action(const sf::Event& event, cFramerateLimiter& fps_limiter) { if(item_area_button_active[i][j] && point_in_area.in(item_buttons[i][j])) { rectangle button_rect = item_buttons[i][j]; button_rect.offset(item_win_ul); - arrow_button_click(button_rect); - - item_hit = item_sbar->getPosition() + i; - switch(j) { - case ITEMBTN_NAME: case ITEMBTN_ICON: // equip - handle_equip_item(item_hit, need_redraw); - break; - case ITEMBTN_USE: - handle_use_item(item_hit, did_something, need_redraw); - break; - case ITEMBTN_GIVE: - handle_give_item(item_hit, did_something, need_redraw); - break; - case ITEMBTN_DROP: - if(stat_window == ITEM_WIN_SPECIAL) { - use_spec_item(spec_item_array[item_hit], need_redraw); - } else handle_drop_item(item_hit, need_redraw); - break; - case ITEMBTN_INFO: - show_item_info(item_hit); - break; - case ITEMBTN_SPEC: // sell? That this code was reached indicates that the item was sellable - // (Based on item_area_button_active) - handle_item_shop_action(item_hit); - break; - case MAX_eItemButton: - break; // Not a button + if(arrow_button_click(button_rect, &fps_limiter)){ + item_hit = item_sbar->getPosition() + i; + switch(j) { + case ITEMBTN_NAME: case ITEMBTN_ICON: // equip + handle_equip_item(item_hit, need_redraw); + break; + case ITEMBTN_USE: + handle_use_item(item_hit, did_something, need_redraw); + break; + case ITEMBTN_GIVE: + handle_give_item(item_hit, did_something, need_redraw); + break; + case ITEMBTN_DROP: + if(stat_window == ITEM_WIN_SPECIAL) { + use_spec_item(spec_item_array[item_hit], need_redraw); + } else handle_drop_item(item_hit, need_redraw); + break; + case ITEMBTN_INFO: + show_item_info(item_hit); + break; + case ITEMBTN_SPEC: // sell? That this code was reached indicates that the item was sellable + // (Based on item_area_button_active) + handle_item_shop_action(item_hit); + break; + case MAX_eItemButton: + break; // Not a button + } } } } diff --git a/src/game/boe.graphics.cpp b/src/game/boe.graphics.cpp index dc7e71a7..c00e8df3 100644 --- a/src/game/boe.graphics.cpp +++ b/src/game/boe.graphics.cpp @@ -482,21 +482,48 @@ void draw_start_button(eStartButton which_position,short which_button) { win_draw_string(mainPtr(),to_rect,button_labels[which_position],eTextMode::CENTRE,style); } -void arrow_button_click(rectangle button_rect) { +bool arrow_button_click(rectangle button_rect, cFramerateLimiter* fps_limiter) { if(recording){ - // This action is purely cosmetic, for playing the animation and sound accompanying a click on a button whose real action - // is recorded afterward + // In a replay, this action is purely cosmetic, for playing the animation and sound + // accompanying a click on a button whose real action is recorded afterward record_action("arrow_button_click", boost::lexical_cast(button_rect)); } + + // Draw depressed: mainPtr().setActive(); clip_rect(mainPtr(), button_rect); - // TODO: Mini-event loop so that the click doesn't happen until releasing the mouse button - refresh_stat_areas(1); mainPtr().display(); - play_sound(37, time_in_ticks(5)); + + // Mini-event loop so that the click doesn't happen until releasing the mouse button: + bool done = false, clicked = false, depressed = true; + if(replaying) clicked = true; + else{ + sf::Event e; + while(!done){ + refresh_stat_areas(depressed ? 1 : 0); + while(pollEvent(mainPtr(), e)){ + if(e.type == sf::Event::MouseButtonReleased){ + done = true; + location clickPos(e.mouseButton.x, e.mouseButton.y); + clickPos = mainPtr().mapPixelToCoords(clickPos); + clicked = button_rect.contains(clickPos); + depressed = false; + break; + } else if(e.type == sf::Event::MouseMoved){ + location toPos(e.mouseMove.x, e.mouseMove.y); + toPos = mainPtr().mapPixelToCoords(toPos); + depressed = button_rect.contains(toPos); + } + } + fps_limiter->frame_finished(); + } + } + undo_clip(mainPtr()); + play_sound(37, time_in_ticks(5)); refresh_stat_areas(0); + return clicked; } diff --git a/src/game/boe.graphics.hpp b/src/game/boe.graphics.hpp index 769a7ef3..73ec0b0f 100644 --- a/src/game/boe.graphics.hpp +++ b/src/game/boe.graphics.hpp @@ -4,6 +4,7 @@ #include #include "location.hpp" +#include "tools/framerate_limiter.hpp" enum { REFRESH_NONE = 0, @@ -33,7 +34,7 @@ void draw_startup(short but_type); void draw_anim(); void place_anim(); void draw_start_button(eStartButton which_position,short which_button); -void arrow_button_click(rectangle button_rect); +bool arrow_button_click(rectangle button_rect, cFramerateLimiter* fps_limiter = nullptr); void end_startup(); void load_main_screen(); void redraw_screen(int refresh);