X-Git-Url: https://git.artsoft.org/?p=rocksndiamonds.git;a=blobdiff_plain;f=src%2Fevents.c;h=0edb3288b3eb61332992f298917806b6f1d31d6a;hp=b450c2b0d547a79f587da1a82cd8821ed83bb86f;hb=b4053d471953bea4a8acf654491f69db0ab6a2ab;hpb=520916c89d7d96944bf3d66e3caa5afd840df74c diff --git a/src/events.c b/src/events.c index b450c2b0..0edb3288 100644 --- a/src/events.c +++ b/src/events.c @@ -39,6 +39,12 @@ static int cursor_mode_last = CURSOR_DEFAULT; static unsigned int special_cursor_delay = 0; static unsigned int special_cursor_delay_value = 1000; + +/* forward declarations for internal use */ +static void HandleNoEvent(void); +static void HandleEventActions(void); + + /* event filter especially needed for SDL event filtering due to delay problems with lots of mouse motion events when mouse button not pressed (X11 can handle this with 'PointerMotionHintMask') */ @@ -128,6 +134,19 @@ static boolean SkipPressedMouseMotionEvent(const Event *event) return FALSE; } +static boolean WaitValidEvent(Event *event) +{ + WaitEvent(event); + + if (!FilterEvents(event)) + return FALSE; + + if (SkipPressedMouseMotionEvent(event)) + return FALSE; + + return TRUE; +} + /* this is especially needed for event modifications for the Android target: if mouse coordinates should be modified in the event filter function, using a properly installed SDL event filter does not work, because in @@ -139,20 +158,8 @@ static boolean SkipPressedMouseMotionEvent(const Event *event) boolean NextValidEvent(Event *event) { while (PendingEvent()) - { - boolean handle_this_event = FALSE; - - NextEvent(event); - - if (FilterEvents(event)) - handle_this_event = TRUE; - - if (SkipPressedMouseMotionEvent(event)) - handle_this_event = FALSE; - - if (handle_this_event) + if (WaitValidEvent(event)) return TRUE; - } return FALSE; } @@ -297,7 +304,8 @@ void HandleMouseCursor() cursor_inside_playfield && DelayReached(&special_cursor_delay, special_cursor_delay_value)) { - SetMouseCursor(CURSOR_PLAYFIELD); + if (level.game_engine_type != GAME_ENGINE_TYPE_MM) + SetMouseCursor(CURSOR_PLAYFIELD); } } else if (gfx.cursor_mode != CURSOR_DEFAULT) @@ -316,10 +324,10 @@ void EventLoop(void) if (PendingEvent()) HandleEvents(); else - HandleMouseCursor(); + HandleNoEvent(); - /* also execute after pending events have been processed before */ - HandleNoEvent(); + /* execute event related actions after pending events have been processed */ + HandleEventActions(); /* don't use all CPU time when idle; the main loop while playing has its own synchronization and is CPU friendly, too */ @@ -340,12 +348,10 @@ void EventLoop(void) void ClearEventQueue() { - while (PendingEvent()) - { - Event event; - - NextEvent(&event); + Event event; + while (NextValidEvent(&event)) + { switch (event.type) { case EVENT_BUTTONRELEASE: @@ -370,6 +376,13 @@ void ClearEventQueue() } } +void ClearPlayerMouseAction() +{ + local_player->mouse_action.lx = 0; + local_player->mouse_action.ly = 0; + local_player->mouse_action.button = 0; +} + void ClearPlayerAction() { int i; @@ -380,6 +393,29 @@ void ClearPlayerAction() stored_player[i].action = 0; ClearJoystickState(); + ClearPlayerMouseAction(); +} + +void SetPlayerMouseAction(int mx, int my, int button) +{ + int lx = getLevelFromScreenX(mx); + int ly = getLevelFromScreenY(my); + + ClearPlayerMouseAction(); + + if (!IN_GFX_FIELD_PLAY(mx, my) || !IN_LEV_FIELD(lx, ly)) + return; + + local_player->mouse_action.lx = lx; + local_player->mouse_action.ly = ly; + local_player->mouse_action.button = button; + + if (tape.recording && tape.pausing && tape.use_mouse) + { + /* prevent button release or motion events from un-pausing a paused game */ + if (button && !motion_status) + TapeTogglePause(TAPE_TOGGLE_MANUAL); + } } void SleepWhileUnmapped() @@ -392,7 +428,8 @@ void SleepWhileUnmapped() { Event event; - NextEvent(&event); + if (!WaitValidEvent(&event)) + continue; switch (event.type) { @@ -639,7 +676,10 @@ void HandleFingerEvent(FingerEvent *event) if (game_status != GAME_MODE_PLAYING) return; - if (strEqual(setup.touch.control_type, TOUCH_CONTROL_FOLLOW_FINGER)) + if (level.game_engine_type == GAME_ENGINE_TYPE_MM) + return; + + if (strEqual(setup.touch.control_type, TOUCH_CONTROL_OFF)) return; if (strEqual(setup.touch.control_type, TOUCH_CONTROL_VIRTUAL_BUTTONS)) @@ -787,6 +827,9 @@ void HandleFingerEvent(FingerEvent *event) return; } + if (!strEqual(setup.touch.control_type, TOUCH_CONTROL_WIPE_GESTURES)) + return; + // use touch direction control if (event->type == EVENT_FINGERPRESS) @@ -922,24 +965,131 @@ void HandleFingerEvent(FingerEvent *event) } } -static void HandleFollowFinger(int mx, int my, int button) +#endif + +static void HandleButtonOrFinger_MM(int mx, int my, int button) +{ + static int old_mx = 0, old_my = 0; + static int last_button = MB_LEFTBUTTON; + static boolean touched = FALSE; + static boolean tapped = FALSE; + + if (strEqual(setup.touch.control_type, TOUCH_CONTROL_WIPE_GESTURES)) + { + // screen tile was tapped (but finger not touching the screen anymore) + // (this point will also be reached without receiving a touch event) + if (tapped && !touched) + { + SetPlayerMouseAction(old_mx, old_my, MB_RELEASED); + + tapped = FALSE; + } + + // stop here if this function was not triggered by a touch event + if (button == -1) + return; + + if (button == MB_PRESSED && IN_GFX_FIELD_PLAY(mx, my)) + { + // finger started touching the screen + + touched = TRUE; + tapped = TRUE; + + if (!motion_status) + { + old_mx = mx; + old_my = my; + + ClearPlayerMouseAction(); + + Error(ERR_DEBUG, "---------- TOUCH ACTION STARTED ----------"); + } + } + else if (button == MB_RELEASED && touched) + { + // finger stopped touching the screen + + touched = FALSE; + + if (tapped) + SetPlayerMouseAction(old_mx, old_my, last_button); + else + SetPlayerMouseAction(old_mx, old_my, MB_RELEASED); + + Error(ERR_DEBUG, "---------- TOUCH ACTION STOPPED ----------"); + } + + if (touched) + { + // finger moved while touching the screen + + int old_x = getLevelFromScreenX(old_mx); + int old_y = getLevelFromScreenY(old_my); + int new_x = getLevelFromScreenX(mx); + int new_y = getLevelFromScreenY(my); + + if (new_x != old_x || new_y != old_y) + tapped = FALSE; + + if (new_x != old_x) + { + // finger moved left or right from (horizontal) starting position + + int button_nr = (new_x < old_x ? MB_LEFTBUTTON : MB_RIGHTBUTTON); + + SetPlayerMouseAction(old_mx, old_my, button_nr); + + last_button = button_nr; + + Error(ERR_DEBUG, "---------- TOUCH ACTION: ROTATING ----------"); + } + else + { + // finger stays at or returned to (horizontal) starting position + + SetPlayerMouseAction(old_mx, old_my, MB_RELEASED); + + Error(ERR_DEBUG, "---------- TOUCH ACTION PAUSED ----------"); + } + } + } + else if (strEqual(setup.touch.control_type, TOUCH_CONTROL_FOLLOW_FINGER)) + { + } +} + +static void HandleButtonOrFinger(int mx, int my, int button) { static int old_mx = 0, old_my = 0; static Key motion_key_x = KSYM_UNDEFINED; static Key motion_key_y = KSYM_UNDEFINED; + static boolean touched = FALSE; static boolean started_on_player = FALSE; static boolean player_is_dropping = FALSE; static int player_drop_count = 0; static int last_player_x = -1; static int last_player_y = -1; + if (game_status != GAME_MODE_PLAYING) + return; + + if (strEqual(setup.touch.control_type, TOUCH_CONTROL_OFF)) + return; + + if (level.game_engine_type == GAME_ENGINE_TYPE_MM) + { + HandleButtonOrFinger_MM(mx, my, button); + + return; + } + if (!strEqual(setup.touch.control_type, TOUCH_CONTROL_FOLLOW_FINGER)) return; if (button == MB_PRESSED && IN_GFX_FIELD_PLAY(mx, my)) { - touch_info[0].touched = TRUE; - touch_info[0].key = 0; + touched = TRUE; old_mx = mx; old_my = my; @@ -958,10 +1108,9 @@ static void HandleFollowFinger(int mx, int my, int button) Error(ERR_DEBUG, "---------- TOUCH ACTION STARTED ----------"); } } - else if (button == MB_RELEASED && touch_info[0].touched) + else if (button == MB_RELEASED && touched) { - touch_info[0].touched = FALSE; - touch_info[0].key = 0; + touched = FALSE; old_mx = 0; old_my = 0; @@ -993,7 +1142,7 @@ static void HandleFollowFinger(int mx, int my, int button) Error(ERR_DEBUG, "---------- TOUCH ACTION STOPPED ----------"); } - if (touch_info[0].touched) + if (touched) { int src_x = local_player->jx; int src_y = local_player->jy; @@ -1088,6 +1237,8 @@ static void HandleFollowFinger(int mx, int my, int button) } } +#if defined(TARGET_SDL2) + static boolean checkTextInputKeyModState() { // when playing, only handle raw key events and ignore text input @@ -1254,8 +1405,10 @@ void HandleButton(int mx, int my, int button, int button_nr) #if defined(PLATFORM_ANDROID) // when playing, only handle gadgets when using "follow finger" controls + // or when using touch controls in combination with the MM game engine boolean handle_gadgets = (game_status != GAME_MODE_PLAYING || + level.game_engine_type == GAME_ENGINE_TYPE_MM || strEqual(setup.touch.control_type, TOUCH_CONTROL_FOLLOW_FINGER)); if (handle_gadgets && @@ -1275,7 +1428,7 @@ void HandleButton(int mx, int my, int button, int button_nr) if (HandleGlobalAnimClicks(mx, my, button)) { /* do not handle this button event anymore */ - mx = my = -32; /* force mouse event to be outside screen tiles */ + return; /* force mouse event not to be handled at all */ } if (button_hold && game_status == GAME_MODE_PLAYING && tape.pausing) @@ -1323,14 +1476,15 @@ void HandleButton(int mx, int my, int button, int button_nr) HandleSetupScreen(mx, my, 0, 0, button); break; -#if defined(TARGET_SDL2) case GAME_MODE_PLAYING: - HandleFollowFinger(mx, my, button); -#endif + if (!strEqual(setup.touch.control_type, TOUCH_CONTROL_OFF)) + HandleButtonOrFinger(mx, my, button); + else + SetPlayerMouseAction(mx, my, button); #ifdef DEBUG - if (button == MB_PRESSED && !motion_status && IN_GFX_FIELD_PLAY(mx, my) && - GetKeyModState() & KMOD_Control) + if (button == MB_PRESSED && !motion_status && !button_hold && + IN_GFX_FIELD_PLAY(mx, my) && GetKeyModState() & KMOD_Control) DumpTileFromScreen(mx, my); #endif @@ -1441,6 +1595,11 @@ static void HandleKeysSpecial(Key key) { SaveNativeLevel(&level); } + else if (is_string_suffix(cheat_input, ":frames-per-second") || + is_string_suffix(cheat_input, ":fps")) + { + global.show_frames_per_second = !global.show_frames_per_second; + } } else if (game_status == GAME_MODE_PLAYING) { @@ -1470,7 +1629,7 @@ void HandleKeysDebug(Key key) if (game_status == GAME_MODE_PLAYING || !setup.debug.frame_delay_game_only) { - boolean mod_key_pressed = (GetKeyModState() != KMOD_None); + boolean mod_key_pressed = ((GetKeyModState() & KMOD_Valid) != KMOD_None); for (i = 0; i < NUM_DEBUG_FRAME_DELAY_KEYS; i++) { @@ -1554,10 +1713,7 @@ void HandleKey(Key key, int key_status) if (game_status == GAME_MODE_PLAYING) { /* only needed for single-step tape recording mode */ - static boolean clear_snap_button[MAX_PLAYERS] = { FALSE,FALSE,FALSE,FALSE }; - static boolean clear_drop_button[MAX_PLAYERS] = { FALSE,FALSE,FALSE,FALSE }; - static boolean element_snapped[MAX_PLAYERS] = { FALSE,FALSE,FALSE,FALSE }; - static boolean element_dropped[MAX_PLAYERS] = { FALSE,FALSE,FALSE,FALSE }; + static boolean has_snapped[MAX_PLAYERS] = { FALSE, FALSE, FALSE, FALSE }; int pnr; for (pnr = 0; pnr < MAX_PLAYERS; pnr++) @@ -1583,22 +1739,6 @@ void HandleKey(Key key, int key_status) key_action |= key_info[i].action | JOY_BUTTON_SNAP; } - /* clear delayed snap and drop actions in single step mode (see below) */ - if (tape.single_step) - { - if (clear_snap_button[pnr]) - { - stored_player[pnr].action &= ~KEY_BUTTON_SNAP; - clear_snap_button[pnr] = FALSE; - } - - if (clear_drop_button[pnr]) - { - stored_player[pnr].action &= ~KEY_BUTTON_DROP; - clear_drop_button[pnr] = FALSE; - } - } - if (key_status == KEY_PRESSED) stored_player[pnr].action |= key_action; else @@ -1610,65 +1750,32 @@ void HandleKey(Key key, int key_status) { TapeTogglePause(TAPE_TOGGLE_AUTOMATIC); - /* if snap key already pressed, don't snap when releasing (below) */ + /* if snap key already pressed, keep pause mode when releasing */ if (stored_player[pnr].action & KEY_BUTTON_SNAP) - element_snapped[pnr] = TRUE; - - /* if drop key already pressed, don't drop when releasing (below) */ - if (stored_player[pnr].action & KEY_BUTTON_DROP) - element_dropped[pnr] = TRUE; + has_snapped[pnr] = TRUE; } else if (key_status == KEY_PRESSED && key_action & KEY_BUTTON_DROP) { - if (level.game_engine_type == GAME_ENGINE_TYPE_EM || - level.game_engine_type == GAME_ENGINE_TYPE_SP) - { - if (level.game_engine_type == GAME_ENGINE_TYPE_SP && - getRedDiskReleaseFlag_SP() == 0) - stored_player[pnr].action &= ~KEY_BUTTON_DROP; + TapeTogglePause(TAPE_TOGGLE_AUTOMATIC); - TapeTogglePause(TAPE_TOGGLE_AUTOMATIC); + if (level.game_engine_type == GAME_ENGINE_TYPE_SP && + getRedDiskReleaseFlag_SP() == 0) + { + /* add a single inactive frame before dropping starts */ + stored_player[pnr].action &= ~KEY_BUTTON_DROP; + stored_player[pnr].force_dropping = TRUE; } } - else if (key_status == KEY_RELEASED && key_action & KEY_BUTTON) + else if (key_status == KEY_RELEASED && key_action & KEY_BUTTON_SNAP) { - if (key_action & KEY_BUTTON_SNAP) - { - /* if snap key was released without moving (see above), snap now */ - if (!element_snapped[pnr]) - { - TapeTogglePause(TAPE_TOGGLE_AUTOMATIC); - - stored_player[pnr].action |= KEY_BUTTON_SNAP; - - /* clear delayed snap button on next event */ - clear_snap_button[pnr] = TRUE; - } - - element_snapped[pnr] = FALSE; - } - - if (key_action & KEY_BUTTON_DROP && - level.game_engine_type == GAME_ENGINE_TYPE_RND) - { - /* if drop key was released without moving (see above), drop now */ - if (!element_dropped[pnr]) - { - TapeTogglePause(TAPE_TOGGLE_AUTOMATIC); - - if (level.game_engine_type != GAME_ENGINE_TYPE_SP || - getRedDiskReleaseFlag_SP() != 0) - stored_player[pnr].action |= KEY_BUTTON_DROP; - - /* clear delayed drop button on next event */ - clear_drop_button[pnr] = TRUE; - } + /* if snap key was pressed without direction, leave pause mode */ + if (!has_snapped[pnr]) + TapeTogglePause(TAPE_TOGGLE_AUTOMATIC); - element_dropped[pnr] = FALSE; - } + has_snapped[pnr] = FALSE; } } - else if (tape.recording && tape.pausing) + else if (tape.recording && tape.pausing && !tape.use_mouse) { /* prevent key release events from un-pausing a paused game */ if (key_status == KEY_PRESSED && key_action & KEY_ACTION) @@ -1937,9 +2044,23 @@ void HandleKey(Key key, int key_status) } void HandleNoEvent() +{ + HandleMouseCursor(); + + switch (game_status) + { + case GAME_MODE_PLAYING: + HandleButtonOrFinger(-1, -1, -1); + break; + } +} + +void HandleEventActions() { // if (button_status && game_status != GAME_MODE_PLAYING) - if (button_status && (game_status != GAME_MODE_PLAYING || tape.pausing)) + if (button_status && (game_status != GAME_MODE_PLAYING || + tape.pausing || + level.game_engine_type == GAME_ENGINE_TYPE_MM)) { HandleButton(0, 0, button_status, -button_status); } @@ -1963,12 +2084,6 @@ void HandleNoEvent() HandleLevelEditorIdle(); break; -#if defined(TARGET_SDL2) - case GAME_MODE_PLAYING: - HandleFollowFinger(-1, -1, -1); - break; -#endif - default: break; }