X-Git-Url: https://git.artsoft.org/?p=rocksndiamonds.git;a=blobdiff_plain;f=src%2Fevents.c;h=e07b8494cef2b9167b45382cb919bf5e69a3189f;hp=9526f198b7c3e228b4f13e1834eab148d07c4fd9;hb=8ab1a8040e3d3615ac2f6656f38fef8a809364a8;hpb=a59ebe8eb3a68db0a2ffcb8ce5127c767737d5ad diff --git a/src/events.c b/src/events.c index 9526f198..e07b8494 100644 --- a/src/events.c +++ b/src/events.c @@ -4,7 +4,7 @@ // (c) 1995-2014 by Artsoft Entertainment // Holger Schemel // info@artsoft.org -// http://www.artsoft.org/ +// https://www.artsoft.org/ // ---------------------------------------------------------------------------- // events.c // ============================================================================ @@ -39,11 +39,11 @@ static int cursor_mode_last = CURSOR_DEFAULT; static unsigned int special_cursor_delay = 0; static unsigned int special_cursor_delay_value = 1000; -static boolean virtual_button_pressed = FALSE; static boolean stop_processing_events = FALSE; // forward declarations for internal use +static void ClearTouchInfo(void); static void HandleNoEvent(void); static void HandleEventActions(void); @@ -95,6 +95,25 @@ static int FilterEvents(const Event *event) ((MotionEvent *)event)->y -= video.screen_yoffset; } + if (event->type == EVENT_BUTTONPRESS || + event->type == EVENT_BUTTONRELEASE || + event->type == EVENT_MOTIONNOTIFY) + { + // do not reset mouse cursor before all pending events have been processed + if (gfx.cursor_mode == cursor_mode_last && + ((game_status == GAME_MODE_TITLE && + gfx.cursor_mode == CURSOR_NONE) || + (game_status == GAME_MODE_PLAYING && + gfx.cursor_mode == CURSOR_PLAYFIELD))) + { + SetMouseCursor(CURSOR_DEFAULT); + + DelayReached(&special_cursor_delay, 0); + + cursor_mode_last = CURSOR_DEFAULT; + } + } + // non-motion events are directly passed to event handler functions if (event->type != EVENT_MOTIONNOTIFY) return 1; @@ -112,20 +131,6 @@ static int FilterEvents(const Event *event) gfx.mouse_x = motion->x; gfx.mouse_y = motion->y; - // do no reset mouse cursor before all pending events have been processed - if (gfx.cursor_mode == cursor_mode_last && - ((game_status == GAME_MODE_TITLE && - gfx.cursor_mode == CURSOR_NONE) || - (game_status == GAME_MODE_PLAYING && - gfx.cursor_mode == CURSOR_PLAYFIELD))) - { - SetMouseCursor(CURSOR_DEFAULT); - - DelayReached(&special_cursor_delay, 0); - - cursor_mode_last = CURSOR_DEFAULT; - } - // skip mouse motion events without pressed button outside level editor if (button_status == MB_RELEASED && game_status != GAME_MODE_EDITOR && game_status != GAME_MODE_PLAYING) @@ -209,6 +214,8 @@ static void HandleEvents(void) while (NextValidEvent(&event)) { + int game_status_last = game_status; + switch (event.type) { case EVENT_BUTTONPRESS: @@ -259,6 +266,10 @@ static void HandleEvents(void) break; } + // always handle events within delay period if game status has changed + if (game_status != game_status_last) + ResetDelayCounter(&event_frame_delay); + // do not handle events for longer than standard frame delay period if (DelayReached(&event_frame_delay, event_frame_delay_value)) break; @@ -323,6 +334,10 @@ static void HandleMouseCursor(void) { // when playing, display a special mouse pointer inside the playfield + // display normal pointer if mouse pressed + if (button_status != MB_RELEASED) + DelayReached(&special_cursor_delay, 0); + if (gfx.cursor_mode != CURSOR_PLAYFIELD && cursor_inside_playfield && DelayReached(&special_cursor_delay, special_cursor_delay_value)) @@ -399,6 +414,7 @@ void ClearEventQueue(void) button_status = MB_RELEASED; break; + case EVENT_FINGERRELEASE: case EVENT_KEYRELEASE: ClearPlayerAction(); break; @@ -434,6 +450,10 @@ void ClearPlayerAction(void) stored_player[i].snap_action = 0; } + // simulate finger release events for still pressed virtual buttons + overlay.grid_button_action = JOY_NO_ACTION; + + ClearTouchInfo(); ClearJoystickState(); ClearPlayerMouseAction(); } @@ -456,7 +476,7 @@ static void SetPlayerMouseAction(int mx, int my, int button) local_player->mouse_action.ly = ly; local_player->mouse_action.button = button; - if (tape.recording && tape.pausing && tape.use_mouse) + if (tape.recording && tape.pausing && tape.use_mouse_actions) { // un-pause a paused game only if mouse button was newly pressed down if (new_button) @@ -466,10 +486,36 @@ static void SetPlayerMouseAction(int mx, int my, int button) SetTileCursorXY(lx, ly); } +static Key GetKeyFromGridButton(int grid_button) +{ + return (grid_button == CHAR_GRID_BUTTON_LEFT ? setup.input[0].key.left : + grid_button == CHAR_GRID_BUTTON_RIGHT ? setup.input[0].key.right : + grid_button == CHAR_GRID_BUTTON_UP ? setup.input[0].key.up : + grid_button == CHAR_GRID_BUTTON_DOWN ? setup.input[0].key.down : + grid_button == CHAR_GRID_BUTTON_SNAP ? setup.input[0].key.snap : + grid_button == CHAR_GRID_BUTTON_DROP ? setup.input[0].key.drop : + KSYM_UNDEFINED); +} + +#if defined(PLATFORM_ANDROID) +static boolean CheckVirtualButtonPressed(int mx, int my, int button) +{ + float touch_x = (float)(mx + video.screen_xoffset) / video.screen_width; + float touch_y = (float)(my + video.screen_yoffset) / video.screen_height; + int x = touch_x * overlay.grid_xsize; + int y = touch_y * overlay.grid_ysize; + int grid_button = overlay.grid_button[x][y]; + Key key = GetKeyFromGridButton(grid_button); + int key_status = (button == MB_RELEASED ? KEY_RELEASED : KEY_PRESSED); + + return (key_status == KEY_PRESSED && key != KSYM_UNDEFINED); +} +#endif + void HandleButtonEvent(ButtonEvent *event) { #if DEBUG_EVENTS_BUTTON - Error(ERR_DEBUG, "BUTTON EVENT: button %d %s, x/y %d/%d\n", + Debug("event:button", "button %d %s, x/y %d/%d\n", event->button, event->type == EVENT_BUTTONPRESS ? "pressed" : "released", event->x, event->y); @@ -501,7 +547,7 @@ void HandleMotionEvent(MotionEvent *event) motion_status = TRUE; #if DEBUG_EVENTS_MOTION - Error(ERR_DEBUG, "MOTION EVENT: button %d moved, x/y %d/%d\n", + Debug("event:motion", "button %d moved, x/y %d/%d\n", button_status, event->x, event->y); #endif @@ -514,11 +560,11 @@ void HandleWheelEvent(WheelEvent *event) #if DEBUG_EVENTS_WHEEL #if 1 - Error(ERR_DEBUG, "WHEEL EVENT: mouse == %d, x/y == %d/%d\n", + Debug("event:wheel", "mouse == %d, x/y == %d/%d\n", event->which, event->x, event->y); #else // (SDL_MOUSEWHEEL_NORMAL/SDL_MOUSEWHEEL_FLIPPED needs SDL 2.0.4 or newer) - Error(ERR_DEBUG, "WHEEL EVENT: mouse == %d, x/y == %d/%d, direction == %s\n", + Debug("event:wheel", "mouse == %d, x/y == %d/%d, direction == %s\n", event->which, event->x, event->y, (event->direction == SDL_MOUSEWHEEL_NORMAL ? "SDL_MOUSEWHEEL_NORMAL" : "SDL_MOUSEWHEEL_FLIPPED")); @@ -569,7 +615,7 @@ void HandleWindowEvent(WindowEvent *event) subtype == SDL_WINDOWEVENT_CLOSE ? "SDL_WINDOWEVENT_CLOSE" : "(UNKNOWN)"); - Error(ERR_DEBUG, "WINDOW EVENT: '%s', %ld, %ld", + Debug("event:window", "name: '%s', data1: %ld, data2: %ld", event_name, event->data1, event->data2); #endif @@ -628,23 +674,15 @@ void HandleWindowEvent(WindowEvent *event) video.display_height = new_display_height; SDLSetScreenProperties(); + SetGadgetsPosition_OverlayTouchButtons(); // check if screen orientation has changed (should always be true here) if (nr != GRID_ACTIVE_NR()) { - int x, y; - if (game_status == GAME_MODE_SETUP) RedrawSetupScreenAfterScreenRotation(nr); - nr = GRID_ACTIVE_NR(); - - overlay.grid_xsize = setup.touch.grid_xsize[nr]; - overlay.grid_ysize = setup.touch.grid_ysize[nr]; - - for (x = 0; x < MAX_GRID_XSIZE; x++) - for (y = 0; y < MAX_GRID_YSIZE; y++) - overlay.grid_button[x][y] = setup.touch.grid_button[nr][x][y]; + SetOverlayGridSizeAndButtons(); } } } @@ -663,56 +701,41 @@ static struct byte action; } touch_info[NUM_TOUCH_FINGERS]; +static void SetTouchInfo(int pos, SDL_FingerID finger_id, int counter, + Key key, byte action) +{ + touch_info[pos].touched = (action != JOY_NO_ACTION); + touch_info[pos].finger_id = finger_id; + touch_info[pos].counter = counter; + touch_info[pos].key = key; + touch_info[pos].action = action; +} + +static void ClearTouchInfo(void) +{ + int i; + + for (i = 0; i < NUM_TOUCH_FINGERS; i++) + SetTouchInfo(i, 0, 0, 0, JOY_NO_ACTION); +} + static void HandleFingerEvent_VirtualButtons(FingerEvent *event) { -#if 1 int x = event->x * overlay.grid_xsize; int y = event->y * overlay.grid_ysize; int grid_button = overlay.grid_button[x][y]; int grid_button_action = GET_ACTION_FROM_GRID_BUTTON(grid_button); - Key key = (grid_button == CHAR_GRID_BUTTON_LEFT ? setup.input[0].key.left : - grid_button == CHAR_GRID_BUTTON_RIGHT ? setup.input[0].key.right : - grid_button == CHAR_GRID_BUTTON_UP ? setup.input[0].key.up : - grid_button == CHAR_GRID_BUTTON_DOWN ? setup.input[0].key.down : - grid_button == CHAR_GRID_BUTTON_SNAP ? setup.input[0].key.snap : - grid_button == CHAR_GRID_BUTTON_DROP ? setup.input[0].key.drop : - KSYM_UNDEFINED); -#else - float ypos = 1.0 - 1.0 / 3.0 * video.display_width / video.display_height; - float event_x = (event->x); - float event_y = (event->y - ypos) / (1 - ypos); - Key key = (event_x > 0 && event_x < 1.0 / 6.0 && - event_y > 2.0 / 3.0 && event_y < 1 ? - setup.input[0].key.snap : - event_x > 1.0 / 6.0 && event_x < 1.0 / 3.0 && - event_y > 2.0 / 3.0 && event_y < 1 ? - setup.input[0].key.drop : - event_x > 7.0 / 9.0 && event_x < 8.0 / 9.0 && - event_y > 0 && event_y < 1.0 / 3.0 ? - setup.input[0].key.up : - event_x > 6.0 / 9.0 && event_x < 7.0 / 9.0 && - event_y > 1.0 / 3.0 && event_y < 2.0 / 3.0 ? - setup.input[0].key.left : - event_x > 8.0 / 9.0 && event_x < 1 && - event_y > 1.0 / 3.0 && event_y < 2.0 / 3.0 ? - setup.input[0].key.right : - event_x > 7.0 / 9.0 && event_x < 8.0 / 9.0 && - event_y > 2.0 / 3.0 && event_y < 1 ? - setup.input[0].key.down : - KSYM_UNDEFINED); -#endif + Key key = GetKeyFromGridButton(grid_button); int key_status = (event->type == EVENT_FINGERRELEASE ? KEY_RELEASED : KEY_PRESSED); char *key_status_name = (key_status == KEY_RELEASED ? "KEY_RELEASED" : "KEY_PRESSED"); int i; - virtual_button_pressed = (key_status == KEY_PRESSED && key != KSYM_UNDEFINED); - // for any touch input event, enable overlay buttons (if activated) SetOverlayEnabled(TRUE); - Error(ERR_DEBUG, "::: key '%s' was '%s' [fingerId: %lld]", + Debug("event:finger", "key '%s' was '%s' [fingerId: %lld]", getKeyNameFromKey(key), key_status_name, event->fingerId); if (key_status == KEY_PRESSED) @@ -726,7 +749,7 @@ static void HandleFingerEvent_VirtualButtons(FingerEvent *event) if (touch_info[i].touched && touch_info[i].finger_id == event->fingerId) { - // Error(ERR_DEBUG, "MARK 1: %d", i); + // Debug("event:finger", "MARK 1: %d", i); break; } @@ -746,12 +769,12 @@ static void HandleFingerEvent_VirtualButtons(FingerEvent *event) oldest_pos = i; oldest_counter = touch_info[i].counter; - // Error(ERR_DEBUG, "MARK 2: %d", i); + // Debug("event:finger", "MARK 2: %d", i); } if (!touch_info[i].touched) { - // Error(ERR_DEBUG, "MARK 3: %d", i); + // Debug("event:finger", "MARK 3: %d", i); break; } @@ -762,7 +785,7 @@ static void HandleFingerEvent_VirtualButtons(FingerEvent *event) // all slots allocated -- use oldest slot i = oldest_pos; - // Error(ERR_DEBUG, "MARK 4: %d", i); + // Debug("event:finger", "MARK 4: %d", i); } } else @@ -773,7 +796,7 @@ static void HandleFingerEvent_VirtualButtons(FingerEvent *event) { HandleKey(key, KEY_RELEASED); - Error(ERR_DEBUG, "=> key == '%s', key_status == '%s' [slot %d] [1]", + Debug("event:finger", "key == '%s', key_status == '%s' [slot %d] [1]", getKeyNameFromKey(key), "KEY_RELEASED", i); } } @@ -792,7 +815,7 @@ static void HandleFingerEvent_VirtualButtons(FingerEvent *event) // undraw previous grid button when moving finger away overlay.grid_button_action &= ~touch_info[i].action; - Error(ERR_DEBUG, "=> key == '%s', key_status == '%s' [slot %d] [2]", + Debug("event:finger", "key == '%s', key_status == '%s' [slot %d] [2]", getKeyNameFromKey(touch_info[i].key), "KEY_RELEASED", i); } @@ -800,16 +823,12 @@ static void HandleFingerEvent_VirtualButtons(FingerEvent *event) { HandleKey(key, KEY_PRESSED); - Error(ERR_DEBUG, "=> key == '%s', key_status == '%s' [slot %d] [3]", + Debug("event:finger", "key == '%s', key_status == '%s' [slot %d] [3]", getKeyNameFromKey(key), "KEY_PRESSED", i); } } - touch_info[i].touched = TRUE; - touch_info[i].finger_id = event->fingerId; - touch_info[i].counter = Counter(); - touch_info[i].key = key; - touch_info[i].action = grid_button_action; + SetTouchInfo(i, event->fingerId, Counter(), key, grid_button_action); } else { @@ -817,15 +836,11 @@ static void HandleFingerEvent_VirtualButtons(FingerEvent *event) { HandleKey(touch_info[i].key, KEY_RELEASED); - Error(ERR_DEBUG, "=> key == '%s', key_status == '%s' [slot %d] [4]", + Debug("event:finger", "key == '%s', key_status == '%s' [slot %d] [4]", getKeyNameFromKey(touch_info[i].key), "KEY_RELEASED", i); } - touch_info[i].touched = FALSE; - touch_info[i].finger_id = 0; - touch_info[i].counter = 0; - touch_info[i].key = 0; - touch_info[i].action = JOY_NO_ACTION; + SetTouchInfo(i, 0, 0, 0, JOY_NO_ACTION); } } } @@ -860,7 +875,7 @@ static void HandleFingerEvent_WipeGestures(FingerEvent *event) motion_key_x = KSYM_UNDEFINED; motion_key_y = KSYM_UNDEFINED; - Error(ERR_DEBUG, "---------- MOVE STARTED (WAIT) ----------"); + Debug("event:finger", "---------- MOVE STARTED (WAIT) ----------"); } else { @@ -875,7 +890,7 @@ static void HandleFingerEvent_WipeGestures(FingerEvent *event) HandleKey(button_key, KEY_PRESSED); - Error(ERR_DEBUG, "---------- SNAP STARTED ----------"); + Debug("event:finger", "---------- SNAP STARTED ----------"); } } else if (event->type == EVENT_FINGERRELEASE) @@ -892,7 +907,7 @@ static void HandleFingerEvent_WipeGestures(FingerEvent *event) motion_key_x = KSYM_UNDEFINED; motion_key_y = KSYM_UNDEFINED; - Error(ERR_DEBUG, "---------- MOVE STOPPED ----------"); + Debug("event:finger", "---------- MOVE STOPPED ----------"); } else if (event->fingerId == button_id) { @@ -903,7 +918,7 @@ static void HandleFingerEvent_WipeGestures(FingerEvent *event) button_key = KSYM_UNDEFINED; - Error(ERR_DEBUG, "---------- SNAP STOPPED ----------"); + Debug("event:finger", "---------- SNAP STOPPED ----------"); } } else if (event->type == EVENT_FINGERMOTION) @@ -952,7 +967,7 @@ static void HandleFingerEvent_WipeGestures(FingerEvent *event) motion_key_x = new_motion_key_x; motion_key_y = new_motion_key_y; - Error(ERR_DEBUG, "---------- MOVE STARTED (MOVE) ----------"); + Debug("event:finger", "---------- MOVE STARTED (MOVE) ----------"); } } else if (event->fingerId == button_id) @@ -973,7 +988,7 @@ static void HandleFingerEvent_WipeGestures(FingerEvent *event) HandleKey(button_key, KEY_PRESSED); - Error(ERR_DEBUG, "---------- DROP STARTED ----------"); + Debug("event:finger", "---------- DROP STARTED ----------"); } } } @@ -982,7 +997,7 @@ static void HandleFingerEvent_WipeGestures(FingerEvent *event) void HandleFingerEvent(FingerEvent *event) { #if DEBUG_EVENTS_FINGER - Error(ERR_DEBUG, "FINGER EVENT: finger was %s, touch ID %lld, finger ID %lld, x/y %f/%f, dx/dy %f/%f, pressure %f", + Debug("event:finger", "finger was %s, touch ID %lld, finger ID %lld, x/y %f/%f, dx/dy %f/%f, pressure %f", event->type == EVENT_FINGERPRESS ? "pressed" : event->type == EVENT_FINGERRELEASE ? "released" : "moved", event->touchId, @@ -1049,7 +1064,7 @@ static void HandleButtonOrFinger_WipeGestures_MM(int mx, int my, int button) ClearPlayerMouseAction(); - Error(ERR_DEBUG, "---------- TOUCH ACTION STARTED ----------"); + Debug("event:finger", "---------- TOUCH ACTION STARTED ----------"); } } else if (button == MB_RELEASED && touched) @@ -1063,7 +1078,7 @@ static void HandleButtonOrFinger_WipeGestures_MM(int mx, int my, int button) else SetPlayerMouseAction(old_mx, old_my, MB_RELEASED); - Error(ERR_DEBUG, "---------- TOUCH ACTION STOPPED ----------"); + Debug("event:finger", "---------- TOUCH ACTION STOPPED ----------"); } if (touched) @@ -1088,7 +1103,7 @@ static void HandleButtonOrFinger_WipeGestures_MM(int mx, int my, int button) last_button = button_nr; - Error(ERR_DEBUG, "---------- TOUCH ACTION: ROTATING ----------"); + Debug("event:finger", "---------- TOUCH ACTION: ROTATING ----------"); } else { @@ -1096,7 +1111,7 @@ static void HandleButtonOrFinger_WipeGestures_MM(int mx, int my, int button) SetPlayerMouseAction(old_mx, old_my, MB_RELEASED); - Error(ERR_DEBUG, "---------- TOUCH ACTION PAUSED ----------"); + Debug("event:finger", "---------- TOUCH ACTION PAUSED ----------"); } } } @@ -1135,7 +1150,7 @@ static void HandleButtonOrFinger_FollowFinger_MM(int mx, int my, int button) ClearPlayerMouseAction(); - Error(ERR_DEBUG, "---------- TOUCH ACTION STARTED ----------"); + Debug("event:finger", "---------- TOUCH ACTION STARTED ----------"); } } else if (button == MB_RELEASED && touched) @@ -1149,7 +1164,7 @@ static void HandleButtonOrFinger_FollowFinger_MM(int mx, int my, int button) else SetPlayerMouseAction(old_mx, old_my, MB_RELEASED); - Error(ERR_DEBUG, "---------- TOUCH ACTION STOPPED ----------"); + Debug("event:finger", "---------- TOUCH ACTION STOPPED ----------"); } if (touched) @@ -1178,7 +1193,7 @@ static void HandleButtonOrFinger_FollowFinger_MM(int mx, int my, int button) tapped = FALSE; - Error(ERR_DEBUG, "---------- TOUCH ACTION: ROTATING ----------"); + Debug("event:finger", "---------- TOUCH ACTION: ROTATING ----------"); } else { @@ -1186,7 +1201,7 @@ static void HandleButtonOrFinger_FollowFinger_MM(int mx, int my, int button) SetPlayerMouseAction(old_mx, old_my, MB_RELEASED); - Error(ERR_DEBUG, "---------- TOUCH ACTION PAUSED ----------"); + Debug("event:finger", "---------- TOUCH ACTION PAUSED ----------"); } } } @@ -1221,7 +1236,7 @@ static void HandleButtonOrFinger_FollowFinger(int mx, int my, int button) motion_key_x = KSYM_UNDEFINED; motion_key_y = KSYM_UNDEFINED; - Error(ERR_DEBUG, "---------- TOUCH ACTION STARTED ----------"); + Debug("event:finger", "---------- TOUCH ACTION STARTED ----------"); } } else if (button == MB_RELEASED && touched) @@ -1240,13 +1255,13 @@ static void HandleButtonOrFinger_FollowFinger(int mx, int my, int button) { if (player_is_dropping) { - Error(ERR_DEBUG, "---------- DROP STOPPED ----------"); + Debug("event:finger", "---------- DROP STOPPED ----------"); HandleKey(setup.input[0].key.drop, KEY_RELEASED); } else { - Error(ERR_DEBUG, "---------- SNAP STOPPED ----------"); + Debug("event:finger", "---------- SNAP STOPPED ----------"); HandleKey(setup.input[0].key.snap, KEY_RELEASED); } @@ -1255,7 +1270,7 @@ static void HandleButtonOrFinger_FollowFinger(int mx, int my, int button) motion_key_x = KSYM_UNDEFINED; motion_key_y = KSYM_UNDEFINED; - Error(ERR_DEBUG, "---------- TOUCH ACTION STOPPED ----------"); + Debug("event:finger", "---------- TOUCH ACTION STOPPED ----------"); } if (touched) @@ -1282,7 +1297,7 @@ static void HandleButtonOrFinger_FollowFinger(int mx, int my, int button) int last_move_dir = (ABS(dx) > ABS(dy) ? MV_VERTICAL : MV_HORIZONTAL); if (level.game_engine_type == GAME_ENGINE_TYPE_EM) - level.native_em_level->ply[0]->last_move_dir = last_move_dir; + game_em.ply[0]->last_move_dir = last_move_dir; else local_player->last_move_dir = last_move_dir; @@ -1299,13 +1314,13 @@ static void HandleButtonOrFinger_FollowFinger(int mx, int my, int button) if (player_is_dropping) { - Error(ERR_DEBUG, "---------- DROP STARTED ----------"); + Debug("event:finger", "---------- DROP STARTED ----------"); HandleKey(setup.input[0].key.drop, KEY_PRESSED); } else { - Error(ERR_DEBUG, "---------- SNAP STARTED ----------"); + Debug("event:finger", "---------- SNAP STARTED ----------"); HandleKey(setup.input[0].key.snap, KEY_PRESSED); } @@ -1315,7 +1330,7 @@ static void HandleButtonOrFinger_FollowFinger(int mx, int my, int button) if (player_is_dropping && player_drop_count == getPlayerInventorySize(0)) { - Error(ERR_DEBUG, "---------- DROP -> SNAP ----------"); + Debug("event:finger", "---------- DROP -> SNAP ----------"); HandleKey(setup.input[0].key.drop, KEY_RELEASED); HandleKey(setup.input[0].key.snap, KEY_PRESSED); @@ -1326,7 +1341,7 @@ static void HandleButtonOrFinger_FollowFinger(int mx, int my, int button) if (new_motion_key_x != motion_key_x) { - Error(ERR_DEBUG, "---------- %s %s ----------", + Debug("event:finger", "---------- %s %s ----------", started_on_player && !player_is_dropping ? "SNAPPING" : "MOVING", dx < 0 ? "LEFT" : dx > 0 ? "RIGHT" : "PAUSED"); @@ -1338,7 +1353,7 @@ static void HandleButtonOrFinger_FollowFinger(int mx, int my, int button) if (new_motion_key_y != motion_key_y) { - Error(ERR_DEBUG, "---------- %s %s ----------", + Debug("event:finger", "---------- %s %s ----------", started_on_player && !player_is_dropping ? "SNAPPING" : "MOVING", dy < 0 ? "UP" : dy > 0 ? "DOWN" : "PAUSED"); @@ -1355,6 +1370,8 @@ static void HandleButtonOrFinger_FollowFinger(int mx, int my, int button) static void HandleButtonOrFinger(int mx, int my, int button) { + boolean valid_mouse_event = (mx != -1 && my != -1 && button != -1); + if (game_status != GAME_MODE_PLAYING) return; @@ -1371,16 +1388,27 @@ static void HandleButtonOrFinger(int mx, int my, int button) { if (strEqual(setup.touch.control_type, TOUCH_CONTROL_FOLLOW_FINGER)) HandleButtonOrFinger_FollowFinger(mx, my, button); + else if (game.use_mouse_actions && valid_mouse_event) + SetPlayerMouseAction(mx, my, button); } } -static boolean checkTextInputKeyModState(void) +static boolean checkTextInputKey(Key key) { // when playing, only handle raw key events and ignore text input if (game_status == GAME_MODE_PLAYING) return FALSE; - return ((GetKeyModState() & KMOD_TextInput) != KMOD_None); + // if Shift or right Alt key is pressed, handle key as text input + if ((GetKeyModState() & KMOD_TextInput) != KMOD_None) + return TRUE; + + // ignore raw keys as text input when not in text input mode + if (KSYM_RAW(key) && !textinput_status) + return FALSE; + + // else handle all printable keys as text input + return KSYM_PRINTABLE(key); } void HandleTextEvent(TextEvent *event) @@ -1389,7 +1417,7 @@ void HandleTextEvent(TextEvent *event) Key key = getKeyFromKeyName(text); #if DEBUG_EVENTS_TEXT - Error(ERR_DEBUG, "TEXT EVENT: text == '%s' [%d byte(s), '%c'/%d], resulting key == %d (%s) [%04x]", + Debug("event:text", "text == '%s' [%d byte(s), '%c'/%d], resulting key == %d (%s) [%04x]", text, strlen(text), text[0], (int)(text[0]), @@ -1398,16 +1426,12 @@ void HandleTextEvent(TextEvent *event) GetKeyModState()); #endif -#if !defined(HAS_SCREEN_KEYBOARD) - // non-mobile devices: only handle key input with modifier keys pressed here - // (every other key input is handled directly as physical key input event) - if (!checkTextInputKeyModState()) - return; -#endif - - // process text input as "classic" (with uppercase etc.) key input event - HandleKey(key, KEY_PRESSED); - HandleKey(key, KEY_RELEASED); + if (checkTextInputKey(key)) + { + // process printable keys (with uppercase etc.) in text input mode + HandleKey(key, KEY_PRESSED); + HandleKey(key, KEY_RELEASED); + } } void HandlePauseResumeEvent(PauseResumeEvent *event) @@ -1430,7 +1454,7 @@ void HandleKeyEvent(KeyEvent *event) Key keymod = (with_modifiers ? GetEventKey(event, FALSE) : key); #if DEBUG_EVENTS_KEY - Error(ERR_DEBUG, "KEY EVENT: key was %s, keysym.scancode == %d, keysym.sym == %d, keymod = %d, GetKeyModState() = 0x%04x, resulting key == %d (%s)", + Debug("event:key", "key was %s, keysym.scancode == %d, keysym.sym == %d, keymod = %d, GetKeyModState() = 0x%04x, resulting key == %d (%s)", event->type == EVENT_KEYPRESS ? "pressed" : "released", event->keysym.scancode, event->keysym.sym, @@ -1452,28 +1476,31 @@ void HandleKeyEvent(KeyEvent *event) if (key_status == KEY_PRESSED) SetOverlayEnabled(!GetOverlayEnabled()); } - else + else if (!textinput_status) { // for any other "real" key event, disable virtual buttons SetOverlayEnabled(FALSE); + + // for any other "real" key event, disable overlay touch buttons + runtime.uses_touch_device = FALSE; } #endif HandleKeyModState(keymod, key_status); - // only handle raw key input without text modifier keys pressed - if (!checkTextInputKeyModState()) + // process all keys if not in text input mode or if non-printable keys + if (!checkTextInputKey(key)) HandleKey(key, key_status); } static int HandleDropFileEvent(char *filename) { - Error(ERR_DEBUG, "DROP FILE EVENT: '%s'", filename); + Debug("event:dropfile", "filename == '%s'", filename); // check and extract dropped zip files into correct user data directory if (!strSuffixLower(filename, ".zip")) { - Error(ERR_WARN, "file '%s' not supported", filename); + Warn("file '%s' not supported", filename); return TREE_TYPE_UNDEFINED; } @@ -1484,7 +1511,7 @@ static int HandleDropFileEvent(char *filename) if (directory == NULL) { - Error(ERR_WARN, "zip file '%s' has invalid content!", filename); + Warn("zip file '%s' has invalid content!", filename); return TREE_TYPE_UNDEFINED; } @@ -1526,7 +1553,7 @@ static int HandleDropFileEvent(char *filename) static void HandleDropTextEvent(char *text) { - Error(ERR_DEBUG, "DROP TEXT EVENT: '%s'", text); + Debug("event:droptext", "text == '%s'", text); } static void HandleDropCompleteEvent(int num_level_sets_succeeded, @@ -1687,7 +1714,15 @@ void HandleButton(int mx, int my, int button, int button_nr) level.game_engine_type == GAME_ENGINE_TYPE_MM || strEqual(setup.touch.control_type, TOUCH_CONTROL_FOLLOW_FINGER) || (strEqual(setup.touch.control_type, TOUCH_CONTROL_VIRTUAL_BUTTONS) && - !virtual_button_pressed)); + !CheckVirtualButtonPressed(mx, my, button))); + + // always recognize potentially releasing already pressed gadgets + if (button == MB_RELEASED) + handle_gadgets = TRUE; + + // always recognize pressing or releasing overlay touch buttons + if (CheckPosition_OverlayTouchButtons(mx, my, button) && !motion_status) + handle_gadgets = TRUE; #endif if (HandleGlobalAnimClicks(mx, my, button, FALSE)) @@ -1720,7 +1755,12 @@ void HandleButton(int mx, int my, int button, int button_nr) break; case GAME_MODE_PSEUDO_TYPENAME: - HandleTypeName(0, KSYM_Return); + case GAME_MODE_PSEUDO_TYPENAMES: + HandleTypeName(KSYM_Return); + break; + + case GAME_MODE_NAMES: + HandleChoosePlayerName(mx, my, 0, 0, button); break; case GAME_MODE_LEVELS: @@ -1766,17 +1806,6 @@ void HandleButton(int mx, int my, int button, int button_nr) } } -static boolean is_string_suffix(char *string, char *suffix) -{ - int string_len = strlen(string); - int suffix_len = strlen(suffix); - - if (suffix_len > string_len) - return FALSE; - - return (strEqual(&string[string_len - suffix_len], suffix)); -} - #define MAX_CHEAT_INPUT_LEN 32 static void HandleKeysSpecial(Key key) @@ -1801,97 +1830,97 @@ static void HandleKeysSpecial(Key key) cheat_input[cheat_input_len] = '\0'; #if DEBUG_EVENTS_KEY - Error(ERR_DEBUG, "SPECIAL KEY '%s' [%d]\n", cheat_input, cheat_input_len); + Debug("event:key:special", "'%s' [%d]", cheat_input, cheat_input_len); #endif if (game_status == GAME_MODE_MAIN) { - if (is_string_suffix(cheat_input, ":insert-solution-tape") || - is_string_suffix(cheat_input, ":ist")) + if (strSuffix(cheat_input, ":insert-solution-tape") || + strSuffix(cheat_input, ":ist")) { InsertSolutionTape(); } - else if (is_string_suffix(cheat_input, ":play-solution-tape") || - is_string_suffix(cheat_input, ":pst")) + else if (strSuffix(cheat_input, ":play-solution-tape") || + strSuffix(cheat_input, ":pst")) { PlaySolutionTape(); } - else if (is_string_suffix(cheat_input, ":reload-graphics") || - is_string_suffix(cheat_input, ":rg")) + else if (strSuffix(cheat_input, ":reload-graphics") || + strSuffix(cheat_input, ":rg")) { ReloadCustomArtwork(1 << ARTWORK_TYPE_GRAPHICS); DrawMainMenu(); } - else if (is_string_suffix(cheat_input, ":reload-sounds") || - is_string_suffix(cheat_input, ":rs")) + else if (strSuffix(cheat_input, ":reload-sounds") || + strSuffix(cheat_input, ":rs")) { ReloadCustomArtwork(1 << ARTWORK_TYPE_SOUNDS); DrawMainMenu(); } - else if (is_string_suffix(cheat_input, ":reload-music") || - is_string_suffix(cheat_input, ":rm")) + else if (strSuffix(cheat_input, ":reload-music") || + strSuffix(cheat_input, ":rm")) { ReloadCustomArtwork(1 << ARTWORK_TYPE_MUSIC); DrawMainMenu(); } - else if (is_string_suffix(cheat_input, ":reload-artwork") || - is_string_suffix(cheat_input, ":ra")) + else if (strSuffix(cheat_input, ":reload-artwork") || + strSuffix(cheat_input, ":ra")) { ReloadCustomArtwork(1 << ARTWORK_TYPE_GRAPHICS | 1 << ARTWORK_TYPE_SOUNDS | 1 << ARTWORK_TYPE_MUSIC); DrawMainMenu(); } - else if (is_string_suffix(cheat_input, ":dump-level") || - is_string_suffix(cheat_input, ":dl")) + else if (strSuffix(cheat_input, ":dump-level") || + strSuffix(cheat_input, ":dl")) { DumpLevel(&level); } - else if (is_string_suffix(cheat_input, ":dump-tape") || - is_string_suffix(cheat_input, ":dt")) + else if (strSuffix(cheat_input, ":dump-tape") || + strSuffix(cheat_input, ":dt")) { DumpTape(&tape); } - else if (is_string_suffix(cheat_input, ":fix-tape") || - is_string_suffix(cheat_input, ":ft")) + else if (strSuffix(cheat_input, ":undo-tape") || + strSuffix(cheat_input, ":ut")) { - /* fix single-player tapes that contain player input for more than one - player (due to a bug in 3.3.1.2 and earlier versions), which results - in playing levels with more than one player in multi-player mode, - even though the tape was originally recorded in single-player mode */ - - // remove player input actions for all players but the first one - for (i = 1; i < MAX_PLAYERS; i++) - tape.player_participates[i] = FALSE; - - tape.changed = TRUE; + UndoTape(); + } + else if (strSuffix(cheat_input, ":fix-tape") || + strSuffix(cheat_input, ":ft")) + { + FixTape_ForceSinglePlayer(); } - else if (is_string_suffix(cheat_input, ":save-native-level") || - is_string_suffix(cheat_input, ":snl")) + else if (strSuffix(cheat_input, ":save-native-level") || + strSuffix(cheat_input, ":snl")) { SaveNativeLevel(&level); } - else if (is_string_suffix(cheat_input, ":frames-per-second") || - is_string_suffix(cheat_input, ":fps")) + else if (strSuffix(cheat_input, ":frames-per-second") || + strSuffix(cheat_input, ":fps")) { global.show_frames_per_second = !global.show_frames_per_second; } + else if (strSuffix(cheat_input, ":xsn")) + { + tile_cursor.xsn_debug = TRUE; + } } else if (game_status == GAME_MODE_PLAYING) { #ifdef DEBUG - if (is_string_suffix(cheat_input, ".q")) + if (strSuffix(cheat_input, ".q")) DEBUG_SetMaximumDynamite(); #endif } else if (game_status == GAME_MODE_EDITOR) { - if (is_string_suffix(cheat_input, ":dump-brush") || - is_string_suffix(cheat_input, ":DB")) + if (strSuffix(cheat_input, ":dump-brush") || + strSuffix(cheat_input, ":DB")) { DumpBrush(); } - else if (is_string_suffix(cheat_input, ":DDB")) + else if (strSuffix(cheat_input, ":DDB")) { DumpBrush_Small(); } @@ -1921,9 +1950,9 @@ static void HandleKeysSpecial(Key key) } // special key shortcuts for all game modes - if (is_string_suffix(cheat_input, ":dump-event-actions") || - is_string_suffix(cheat_input, ":dea") || - is_string_suffix(cheat_input, ":DEA")) + if (strSuffix(cheat_input, ":dump-event-actions") || + strSuffix(cheat_input, ":dea") || + strSuffix(cheat_input, ":DEA")) { DumpGadgetIdentifiers(); DumpScreenIdentifiers(); @@ -1956,13 +1985,13 @@ boolean HandleKeysDebug(Key key, int key_status) SetVideoFrameDelay(GameFrameDelay); if (GameFrameDelay > ONE_SECOND_DELAY) - Error(ERR_INFO, "frame delay == %d ms", GameFrameDelay); + Debug("event:key:debug", "frame delay == %d ms", GameFrameDelay); else if (GameFrameDelay != 0) - Error(ERR_INFO, "frame delay == %d ms (max. %d fps / %d %%)", + Debug("event:key:debug", "frame delay == %d ms (max. %d fps / %d %%)", GameFrameDelay, ONE_SECOND_DELAY / GameFrameDelay, GAME_FRAME_DELAY * 100 / GameFrameDelay); else - Error(ERR_INFO, "frame delay == 0 ms (maximum speed)"); + Debug("event:key:debug", "frame delay == 0 ms (maximum speed)"); return TRUE; } @@ -1975,14 +2004,14 @@ boolean HandleKeysDebug(Key key, int key_status) { options.debug = !options.debug; - Error(ERR_INFO, "debug mode %s", + Debug("event:key:debug", "debug mode %s", (options.debug ? "enabled" : "disabled")); return TRUE; } else if (key == KSYM_v) { - Error(ERR_INFO, "currently using game engine version %d", + Debug("event:key:debug", "currently using game engine version %d", game.engine_version); return TRUE; @@ -2081,43 +2110,46 @@ void HandleKey(Key key, int key_status) if (stored_player[pnr].snap_action) stored_player[pnr].action |= JOY_BUTTON_SNAP; - if (tape.single_step && tape.recording && tape.pausing && !tape.use_mouse) + if (tape.recording && tape.pausing && tape.use_key_actions) { - if (key_status == KEY_PRESSED && key_action & KEY_MOTION) + if (tape.single_step) { - TapeTogglePause(TAPE_TOGGLE_AUTOMATIC); + if (key_status == KEY_PRESSED && key_action & KEY_MOTION) + { + TapeTogglePause(TAPE_TOGGLE_AUTOMATIC); - // if snap key already pressed, keep pause mode when releasing - if (stored_player[pnr].action & KEY_BUTTON_SNAP) - has_snapped[pnr] = TRUE; - } - else if (key_status == KEY_PRESSED && key_action & KEY_BUTTON_DROP) - { - TapeTogglePause(TAPE_TOGGLE_AUTOMATIC); + // if snap key already pressed, keep pause mode when releasing + if (stored_player[pnr].action & KEY_BUTTON_SNAP) + has_snapped[pnr] = TRUE; + } + else if (key_status == KEY_PRESSED && key_action & KEY_BUTTON_DROP) + { + TapeTogglePause(TAPE_TOGGLE_AUTOMATIC); - if (level.game_engine_type == GAME_ENGINE_TYPE_SP && - getRedDiskReleaseFlag_SP() == 0) + 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_SNAP) { - // add a single inactive frame before dropping starts - stored_player[pnr].action &= ~KEY_BUTTON_DROP; - stored_player[pnr].force_dropping = TRUE; + // if snap key was pressed without direction, leave pause mode + if (!has_snapped[pnr]) + TapeTogglePause(TAPE_TOGGLE_AUTOMATIC); + + has_snapped[pnr] = FALSE; } } - else if (key_status == KEY_RELEASED && key_action & KEY_BUTTON_SNAP) + else { - // if snap key was pressed without direction, leave pause mode - if (!has_snapped[pnr]) - TapeTogglePause(TAPE_TOGGLE_AUTOMATIC); - - has_snapped[pnr] = FALSE; + // prevent key release events from un-pausing a paused game + if (key_status == KEY_PRESSED && key_action & KEY_ACTION) + TapeTogglePause(TAPE_TOGGLE_MANUAL); } } - 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) - TapeTogglePause(TAPE_TOGGLE_MANUAL); - } // for MM style levels, handle in-game keyboard input in HandleJoystick() if (level.game_engine_type == GAME_ENGINE_TYPE_MM) @@ -2160,7 +2192,7 @@ void HandleKey(Key key, int key_status) { setup.fullscreen = !setup.fullscreen; - ToggleFullscreenOrChangeWindowScalingIfNeeded(); + ToggleFullscreenIfNeeded(); if (game_status == GAME_MODE_SETUP) RedrawSetupScreenAfterFullscreenToggle(); @@ -2193,7 +2225,7 @@ void HandleKey(Key key, int key_status) else if (setup.window_scaling_percent > MAX_WINDOW_SCALING_PERCENT) setup.window_scaling_percent = MAX_WINDOW_SCALING_PERCENT; - ToggleFullscreenOrChangeWindowScalingIfNeeded(); + ChangeWindowScalingIfNeeded(); if (game_status == GAME_MODE_SETUP) RedrawSetupScreenAfterFullscreenToggle(); @@ -2276,11 +2308,13 @@ void HandleKey(Key key, int key_status) switch (game_status) { case GAME_MODE_PSEUDO_TYPENAME: - HandleTypeName(0, key); + case GAME_MODE_PSEUDO_TYPENAMES: + HandleTypeName(key); break; case GAME_MODE_TITLE: case GAME_MODE_MAIN: + case GAME_MODE_NAMES: case GAME_MODE_LEVELS: case GAME_MODE_LEVELNR: case GAME_MODE_SETUP: @@ -2298,6 +2332,8 @@ void HandleKey(Key key, int key_status) HandleTitleScreen(0, 0, 0, 0, MB_MENU_CHOICE); else if (game_status == GAME_MODE_MAIN) HandleMainMenu(0, 0, 0, 0, MB_MENU_CHOICE); + else if (game_status == GAME_MODE_NAMES) + HandleChoosePlayerName(0, 0, 0, 0, MB_MENU_CHOICE); else if (game_status == GAME_MODE_LEVELS) HandleChooseLevelSet(0, 0, 0, 0, MB_MENU_CHOICE); else if (game_status == GAME_MODE_LEVELNR) @@ -2316,6 +2352,8 @@ void HandleKey(Key key, int key_status) if (game_status == GAME_MODE_TITLE) HandleTitleScreen(0, 0, 0, 0, MB_MENU_LEAVE); + else if (game_status == GAME_MODE_NAMES) + HandleChoosePlayerName(0, 0, 0, 0, MB_MENU_LEAVE); else if (game_status == GAME_MODE_LEVELS) HandleChooseLevelSet(0, 0, 0, 0, MB_MENU_LEAVE); else if (game_status == GAME_MODE_LEVELNR) @@ -2329,7 +2367,9 @@ void HandleKey(Key key, int key_status) break; case KSYM_Page_Up: - if (game_status == GAME_MODE_LEVELS) + if (game_status == GAME_MODE_NAMES) + HandleChoosePlayerName(0, 0, 0, -1 * SCROLL_PAGE, MB_MENU_MARK); + else if (game_status == GAME_MODE_LEVELS) HandleChooseLevelSet(0, 0, 0, -1 * SCROLL_PAGE, MB_MENU_MARK); else if (game_status == GAME_MODE_LEVELNR) HandleChooseLevelNr(0, 0, 0, -1 * SCROLL_PAGE, MB_MENU_MARK); @@ -2342,7 +2382,9 @@ void HandleKey(Key key, int key_status) break; case KSYM_Page_Down: - if (game_status == GAME_MODE_LEVELS) + if (game_status == GAME_MODE_NAMES) + HandleChoosePlayerName(0, 0, 0, +1 * SCROLL_PAGE, MB_MENU_MARK); + else if (game_status == GAME_MODE_LEVELS) HandleChooseLevelSet(0, 0, 0, +1 * SCROLL_PAGE, MB_MENU_MARK); else if (game_status == GAME_MODE_LEVELNR) HandleChooseLevelNr(0, 0, 0, +1 * SCROLL_PAGE, MB_MENU_MARK); @@ -2526,6 +2568,7 @@ void HandleJoystick(void) } if (newbutton && (game_status == GAME_MODE_PSEUDO_TYPENAME || + game_status == GAME_MODE_PSEUDO_TYPENAMES || anyTextGadgetActive())) { // leave name input in main menu or text input gadget @@ -2572,6 +2615,7 @@ void HandleJoystick(void) { case GAME_MODE_TITLE: case GAME_MODE_MAIN: + case GAME_MODE_NAMES: case GAME_MODE_LEVELS: case GAME_MODE_LEVELNR: case GAME_MODE_SETUP: @@ -2585,6 +2629,8 @@ void HandleJoystick(void) HandleTitleScreen(0,0,dx,dy, newbutton ? MB_MENU_CHOICE : MB_MENU_MARK); else if (game_status == GAME_MODE_MAIN) HandleMainMenu(0,0,dx,dy, newbutton ? MB_MENU_CHOICE : MB_MENU_MARK); + else if (game_status == GAME_MODE_NAMES) + HandleChoosePlayerName(0,0,dx,dy,newbutton?MB_MENU_CHOICE:MB_MENU_MARK); else if (game_status == GAME_MODE_LEVELS) HandleChooseLevelSet(0,0,dx,dy,newbutton?MB_MENU_CHOICE : MB_MENU_MARK); else if (game_status == GAME_MODE_LEVELNR) @@ -2613,15 +2659,18 @@ void HandleJoystick(void) return; } - if (tape.single_step && tape.recording && tape.pausing && !tape.use_mouse) - { - if (joystick & JOY_ACTION) - TapeTogglePause(TAPE_TOGGLE_AUTOMATIC); - } - else if (tape.recording && tape.pausing && !tape.use_mouse) + if (tape.recording && tape.pausing && tape.use_key_actions) { - if (joystick & JOY_ACTION) - TapeTogglePause(TAPE_TOGGLE_MANUAL); + if (tape.single_step) + { + if (joystick & JOY_ACTION) + TapeTogglePause(TAPE_TOGGLE_AUTOMATIC); + } + else + { + if (joystick & JOY_ACTION) + TapeTogglePause(TAPE_TOGGLE_MANUAL); + } } if (level.game_engine_type == GAME_ENGINE_TYPE_MM)