#include "editor.h"
#include "files.h"
#include "tape.h"
-#include "cartoons.h"
+#include "anim.h"
#include "network.h"
return FALSE;
}
-void EventLoop(void)
+void HandleEvents()
{
- static unsigned int sync_frame_delay = 0;
- unsigned int sync_frame_delay_value = GAME_FRAME_DELAY;
+ Event event;
+ unsigned int event_frame_delay = 0;
+ unsigned int event_frame_delay_value = GAME_FRAME_DELAY;
- while (1)
+ ResetDelayCounter(&event_frame_delay);
+
+ while (NextValidEvent(&event))
{
- if (PendingEvent()) /* got event */
+ switch (event.type)
{
- // use separate frame delay counter to not reset main delay counter
- unsigned int sync_frame_delay2 = 0;
- unsigned int sync_frame_delay_value2 = sync_frame_delay_value;
- Event event;
-
- ResetDelayCounter(&sync_frame_delay2);
+ case EVENT_BUTTONPRESS:
+ case EVENT_BUTTONRELEASE:
+ HandleButtonEvent((ButtonEvent *) &event);
+ break;
- while (NextValidEvent(&event))
- {
- switch (event.type)
- {
- case EVENT_BUTTONPRESS:
- case EVENT_BUTTONRELEASE:
- HandleButtonEvent((ButtonEvent *) &event);
- break;
-
- case EVENT_MOTIONNOTIFY:
- HandleMotionEvent((MotionEvent *) &event);
- break;
+ case EVENT_MOTIONNOTIFY:
+ HandleMotionEvent((MotionEvent *) &event);
+ break;
#if defined(TARGET_SDL2)
- case SDL_WINDOWEVENT:
- HandleWindowEvent((WindowEvent *) &event);
- break;
-
- case EVENT_FINGERPRESS:
- case EVENT_FINGERRELEASE:
- case EVENT_FINGERMOTION:
- HandleFingerEvent((FingerEvent *) &event);
- break;
-
- case EVENT_TEXTINPUT:
- HandleTextEvent((TextEvent *) &event);
- break;
-
- case SDL_APP_WILLENTERBACKGROUND:
- case SDL_APP_DIDENTERBACKGROUND:
- case SDL_APP_WILLENTERFOREGROUND:
- case SDL_APP_DIDENTERFOREGROUND:
- HandlePauseResumeEvent((PauseResumeEvent *) &event);
- break;
-#endif
-
- case EVENT_KEYPRESS:
- case EVENT_KEYRELEASE:
- HandleKeyEvent((KeyEvent *) &event);
- break;
-
- default:
- HandleOtherEvents(&event);
- break;
- }
+ case SDL_WINDOWEVENT:
+ HandleWindowEvent((WindowEvent *) &event);
+ break;
- // do not handle events for longer than standard frame delay period
- if (DelayReached(&sync_frame_delay2, sync_frame_delay_value2))
- break;
- }
- }
+ case EVENT_FINGERPRESS:
+ case EVENT_FINGERRELEASE:
+ case EVENT_FINGERMOTION:
+ HandleFingerEvent((FingerEvent *) &event);
+ break;
- // always handle non-event game actions for every game frame interval
- {
- if (game_status == GAME_MODE_TITLE)
- {
- /* when showing title screens, hide mouse pointer (if not moved) */
+ case EVENT_TEXTINPUT:
+ HandleTextEvent((TextEvent *) &event);
+ break;
- if (gfx.cursor_mode != CURSOR_NONE &&
- DelayReached(&special_cursor_delay, special_cursor_delay_value))
- {
- SetMouseCursor(CURSOR_NONE);
- }
- }
- else if (game_status == GAME_MODE_PLAYING && (!tape.pausing ||
- tape.single_step))
- {
- /* when playing, display a special mouse pointer inside the playfield */
+ case SDL_APP_WILLENTERBACKGROUND:
+ case SDL_APP_DIDENTERBACKGROUND:
+ case SDL_APP_WILLENTERFOREGROUND:
+ case SDL_APP_DIDENTERFOREGROUND:
+ HandlePauseResumeEvent((PauseResumeEvent *) &event);
+ break;
+#endif
- if (gfx.cursor_mode != CURSOR_PLAYFIELD &&
- cursor_inside_playfield &&
- DelayReached(&special_cursor_delay, special_cursor_delay_value))
- {
- SetMouseCursor(CURSOR_PLAYFIELD);
- }
- }
- else if (gfx.cursor_mode != CURSOR_DEFAULT)
- {
- SetMouseCursor(CURSOR_DEFAULT);
- }
+ case EVENT_KEYPRESS:
+ case EVENT_KEYRELEASE:
+ HandleKeyEvent((KeyEvent *) &event);
+ break;
- /* this is set after all pending events have been processed */
- cursor_mode_last = gfx.cursor_mode;
+ default:
+ HandleOtherEvents(&event);
+ break;
}
- /* also execute after pending events have been processed before */
- HandleNoEvent();
-
- /* don't use all CPU time when idle; the main loop while playing
- has its own synchronization and is CPU friendly, too */
-
- if (game_status == GAME_MODE_PLAYING)
- HandleGameActions();
-
- /* refresh window contents from drawing buffer, if needed */
- BackToFront();
-
- if (game_status != GAME_MODE_PLAYING)
- WaitUntilDelayReached(&sync_frame_delay, sync_frame_delay_value);
-
- if (game_status == GAME_MODE_QUIT)
- return;
+ // do not handle events for longer than standard frame delay period
+ if (DelayReached(&event_frame_delay, event_frame_delay_value))
+ break;
}
}
}
}
+void HandleMouseCursor()
+{
+ if (game_status == GAME_MODE_TITLE)
+ {
+ /* when showing title screens, hide mouse pointer (if not moved) */
+
+ if (gfx.cursor_mode != CURSOR_NONE &&
+ DelayReached(&special_cursor_delay, special_cursor_delay_value))
+ {
+ SetMouseCursor(CURSOR_NONE);
+ }
+ }
+ else if (game_status == GAME_MODE_PLAYING && (!tape.pausing ||
+ tape.single_step))
+ {
+ /* when playing, display a special mouse pointer inside the playfield */
+
+ if (gfx.cursor_mode != CURSOR_PLAYFIELD &&
+ cursor_inside_playfield &&
+ DelayReached(&special_cursor_delay, special_cursor_delay_value))
+ {
+ SetMouseCursor(CURSOR_PLAYFIELD);
+ }
+ }
+ else if (gfx.cursor_mode != CURSOR_DEFAULT)
+ {
+ SetMouseCursor(CURSOR_DEFAULT);
+ }
+
+ /* this is set after all pending events have been processed */
+ cursor_mode_last = gfx.cursor_mode;
+}
+
+void EventLoop(void)
+{
+ while (1)
+ {
+ if (PendingEvent())
+ HandleEvents();
+ else
+ HandleMouseCursor();
+
+ /* also execute after pending events have been processed before */
+ HandleNoEvent();
+
+ /* don't use all CPU time when idle; the main loop while playing
+ has its own synchronization and is CPU friendly, too */
+
+ if (game_status == GAME_MODE_PLAYING)
+ HandleGameActions();
+
+ /* always copy backbuffer to visible screen for every video frame */
+ BackToFront();
+
+ /* reset video frame delay to default (may change again while playing) */
+ SetVideoFrameDelay(GAME_FRAME_DELAY);
+
+ if (game_status == GAME_MODE_QUIT)
+ return;
+ }
+}
+
void ClearEventQueue()
{
while (PendingEvent())
event_name, event->data1, event->data2);
#endif
+#if 0
+ // (not needed, as the screen gets redrawn every 20 ms anyway)
if (event->event == SDL_WINDOWEVENT_SIZE_CHANGED ||
event->event == SDL_WINDOWEVENT_RESIZED ||
event->event == SDL_WINDOWEVENT_EXPOSED)
SDLRedrawWindow();
+#endif
if (event->event == SDL_WINDOWEVENT_RESIZED && !video.fullscreen_enabled)
{
int new_xpercent = (100 * new_window_width / video.width);
int new_ypercent = (100 * new_window_height / video.height);
- setup.window_scaling_percent = video.window_scaling_percent =
- MIN(MAX(MIN_WINDOW_SCALING_PERCENT, MIN(new_xpercent, new_ypercent)),
+ // (extreme window scaling allowed, but cannot be saved permanently)
+ video.window_scaling_percent = MIN(new_xpercent, new_ypercent);
+ setup.window_scaling_percent =
+ MIN(MAX(MIN_WINDOW_SCALING_PERCENT, video.window_scaling_percent),
MAX_WINDOW_SCALING_PERCENT);
video.window_width = new_window_width;
void HandleKey(Key key, int key_status)
{
boolean anyTextGadgetActiveOrJustFinished = anyTextGadgetActive();
+ static boolean ignore_repeated_key = FALSE;
static struct SetupKeyboardInfo ski;
static struct SetupShortcutInfo ssi;
static struct
key_joystick_mapping = 0;
if (key_status == KEY_RELEASED)
+ {
+ // reset flag to ignore repeated "key pressed" events after key release
+ ignore_repeated_key = FALSE;
+
return;
+ }
if ((key == KSYM_F11 ||
((key == KSYM_Return ||
key == KSYM_KP_Enter) && (GetKeyModState() & KMOD_Alt))) &&
- video.fullscreen_available)
+ video.fullscreen_available &&
+ !ignore_repeated_key)
{
setup.fullscreen = !setup.fullscreen;
if (game_status == GAME_MODE_SETUP)
RedrawSetupScreenAfterFullscreenToggle();
+ // set flag to ignore repeated "key pressed" events
+ ignore_repeated_key = TRUE;
+
return;
}
key == KSYM_plus ||
key == KSYM_0) &&
((GetKeyModState() & KMOD_Control) ||
- (GetKeyModState() & KMOD_Alt)) &&
+ (GetKeyModState() & KMOD_Alt) ||
+ (GetKeyModState() & KMOD_Meta)) &&
video.window_scaling_available &&
!video.fullscreen_enabled)
{
{
case GAME_MODE_MAIN:
DrawPreviewLevelAnimation();
- DoAnimation();
- break;
-
- case GAME_MODE_LEVELS:
- case GAME_MODE_LEVELNR:
- case GAME_MODE_SETUP:
- case GAME_MODE_INFO:
- case GAME_MODE_SCORES:
- DoAnimation();
break;
case GAME_MODE_EDITOR: