Maelstrom: Added inter-frame polling to get a better read on ping times.

https://github.com/libsdl-org/Maelstrom/commit/30b32bc2ae414d9335d1b38d08a9dc54a0210096

From 30b32bc2ae414d9335d1b38d08a9dc54a0210096 Mon Sep 17 00:00:00 2001
From: Sam Lantinga <[EMAIL REDACTED]>
Date: Tue, 8 Nov 2011 02:07:03 -0500
Subject: [PATCH] Added inter-frame polling to get a better read on ping times.
 It turns out that the ping time to my iPad really is pretty bad over the
 wireless network.

---
 Maelstrom.h             |  1 +
 Maelstrom_Globals.h     |  1 +
 main.cpp                | 13 ++++++++++++-
 netlogic/game.cpp       |  6 +-----
 netlogic/gameinfo.cpp   | 12 ++++++------
 netlogic/lobby.cpp      |  2 +-
 netlogic/lobby.h        |  2 +-
 screenlib/UIManager.cpp | 13 +++++++++++++
 screenlib/UIManager.h   |  1 +
 screenlib/UIPanel.cpp   |  8 ++++++++
 screenlib/UIPanel.h     | 17 +++++++++++++++++
 11 files changed, 62 insertions(+), 14 deletions(-)

diff --git a/Maelstrom.h b/Maelstrom.h
index d407c1d4..857eefd9 100644
--- a/Maelstrom.h
+++ b/Maelstrom.h
@@ -37,6 +37,7 @@
 
 /* Time in 60'th of second between frames */
 #define FRAME_DELAY		2
+#define FRAME_DELAY_MS		((FRAME_DELAY*1000)/60)
 
 #define MAX_SPRITES		100
 #define MAX_SPRITE_FRAMES	60
diff --git a/Maelstrom_Globals.h b/Maelstrom_Globals.h
index 9d765a5e..a8757b6c 100644
--- a/Maelstrom_Globals.h
+++ b/Maelstrom_Globals.h
@@ -85,6 +85,7 @@ extern void   PrintUsage(void);
 extern int    DrawText(int x, int y, const char *text, MFont *font, Uint8 style,
 						Uint8 R, Uint8 G, Uint8 B);
 extern void   Message(const char *message);
+extern void   DelayFrame(void);
 
 // Functions from init.cpp
 extern void  SetStar(int which);
diff --git a/main.cpp b/main.cpp
index 0e4ae6b7..f0fad5e7 100644
--- a/main.cpp
+++ b/main.cpp
@@ -311,7 +311,7 @@ int main(int argc, char *argv[])
 				RunQuitGame(0);
 			}
 		}
-		Delay(FRAME_DELAY);
+		DelayFrame();
 	}
 
 	ui->HidePanel(PANEL_MAIN);
@@ -512,3 +512,14 @@ void Message(const char *message)
 		fontserv->FreeText(textimage);
 	}
 }
+
+void DelayFrame(void)
+{
+	Uint32 ticks;
+
+	while ( ((ticks=SDL_GetTicks())-gLastDrawn) < FRAME_DELAY_MS ) {
+		ui->Poll();
+		SDL_Delay(1);
+	}
+	gLastDrawn = ticks;
+}
diff --git a/netlogic/game.cpp b/netlogic/game.cpp
index e401b9c3..b5ad16bf 100644
--- a/netlogic/game.cpp
+++ b/netlogic/game.cpp
@@ -93,11 +93,7 @@ void NewGame(void)
 
 		/* Timing handling -- Delay the FRAME_DELAY */
 		if ( ! gNoDelay ) {
-			Uint32 ticks;
-			while ( ((ticks=Ticks)-gLastDrawn) < FRAME_DELAY ) {
-				SDL_Delay(1);
-			}
-			gLastDrawn = ticks;
+			DelayFrame();
 		}
 	}
 	
diff --git a/netlogic/gameinfo.cpp b/netlogic/gameinfo.cpp
index bfcb68f6..3fadff76 100644
--- a/netlogic/gameinfo.cpp
+++ b/netlogic/gameinfo.cpp
@@ -251,23 +251,23 @@ GameInfo::UpdatePingStatus()
 		sinceLastPing = int(now - player->ping.lastPing);
 		if (sinceLastPing < PING_INTERVAL) {
 			if (player->ping.roundTripTime <= 48) {
-//printf("Game 0x%8.8x: player 0x%8.8x round trip time %d (GOOD)\n", gameID, player->playerID, player->ping.roundTripTime);
+printf("Game 0x%8.8x: player 0x%8.8x round trip time %d (GOOD)\n", gameID, player->playerID, player->ping.roundTripTime);
 				player->ping.status = PING_GOOD;
 			} else if (player->ping.roundTripTime <= 64) {
-//printf("Game 0x%8.8x: player 0x%8.8x round trip time %d (OKAY)\n", gameID, player->playerID, player->ping.roundTripTime);
+printf("Game 0x%8.8x: player 0x%8.8x round trip time %d (OKAY)\n", gameID, player->playerID, player->ping.roundTripTime);
 				player->ping.status = PING_OKAY;
 			} else {
-//printf("Game 0x%8.8x: player 0x%8.8x round trip time %d (BAD)\n", gameID, player->playerID, player->ping.roundTripTime);
+printf("Game 0x%8.8x: player 0x%8.8x round trip time %d (BAD)\n", gameID, player->playerID, player->ping.roundTripTime);
 				player->ping.status = PING_BAD;
 			}
 		} else if (sinceLastPing < 2*PING_INTERVAL) {
-//printf("Game 0x%8.8x: player 0x%8.8x since last ping %d (OKAY)\n", gameID, player->playerID, sinceLastPing);
+printf("Game 0x%8.8x: player 0x%8.8x since last ping %d (OKAY)\n", gameID, player->playerID, sinceLastPing);
 			player->ping.status = PING_OKAY;
 		} else if (sinceLastPing < PING_TIMEOUT) {
-//printf("Game 0x%8.8x: player 0x%8.8x since last ping %d (BAD)\n", gameID, player->playerID, sinceLastPing);
+printf("Game 0x%8.8x: player 0x%8.8x since last ping %d (BAD)\n", gameID, player->playerID, sinceLastPing);
 			player->ping.status = PING_BAD;
 		} else {
-//printf("Game 0x%8.8x: player 0x%8.8x since last ping %d (TIMEDOUT)\n", gameID, player->playerID, sinceLastPing);
+printf("Game 0x%8.8x: player 0x%8.8x since last ping %d (TIMEDOUT)\n", gameID, player->playerID, sinceLastPing);
 			player->ping.status = PING_TIMEDOUT;
 		}
 
diff --git a/netlogic/lobby.cpp b/netlogic/lobby.cpp
index 02e3c19a..677271aa 100644
--- a/netlogic/lobby.cpp
+++ b/netlogic/lobby.cpp
@@ -176,7 +176,7 @@ LobbyDialogDelegate::OnHide()
 }
 
 void
-LobbyDialogDelegate::OnTick()
+LobbyDialogDelegate::OnPoll()
 {
 	if (m_state == STATE_NONE) {
 		// Neither host nor join is checked
diff --git a/netlogic/lobby.h b/netlogic/lobby.h
index 92c17e74..760c064e 100644
--- a/netlogic/lobby.h
+++ b/netlogic/lobby.h
@@ -47,7 +47,7 @@ class LobbyDialogDelegate : public UIDialogDelegate
 	override bool OnLoad();
 	override void OnShow();
 	override void OnHide();
-	override void OnTick();
+	override void OnPoll();
 
 protected:
 	bool GetElement(const char *name, UIElement *&element);
diff --git a/screenlib/UIManager.cpp b/screenlib/UIManager.cpp
index b9fbb98f..cd1520c6 100644
--- a/screenlib/UIManager.cpp
+++ b/screenlib/UIManager.cpp
@@ -222,6 +222,18 @@ UIManager::DeletePanel(UIPanel *panel)
 	}
 }
 
+void
+UIManager::Poll()
+{
+	int i;
+
+	for (i = 0; i < m_visible.length(); ++i) {
+		UIPanel *panel = m_visible[i];
+
+		panel->Poll();
+	}
+}
+
 void
 UIManager::Draw(bool fullUpdate)
 {
@@ -231,6 +243,7 @@ UIManager::Draw(bool fullUpdate)
 	for (i = 0; i < m_visible.length(); ++i) {
 		UIPanel *panel = m_visible[i];
 
+		panel->Poll();
 		panel->Tick();
 	}
 
diff --git a/screenlib/UIManager.h b/screenlib/UIManager.h
index bf0289d5..8f279c49 100644
--- a/screenlib/UIManager.h
+++ b/screenlib/UIManager.h
@@ -89,6 +89,7 @@ class UIManager : public UIArea, public UIFontInterface, public UISoundInterface
 		DeletePanel(GetPanel(name, false));
 	}
 
+	void Poll();
 	void Draw(bool fullUpdate = true);
 	bool HandleEvent(const SDL_Event &event);
 
diff --git a/screenlib/UIPanel.cpp b/screenlib/UIPanel.cpp
index 77e308c9..cdc1f980 100644
--- a/screenlib/UIPanel.cpp
+++ b/screenlib/UIPanel.cpp
@@ -135,6 +135,14 @@ UIPanel::HideAll()
 	}
 }
 
+void
+UIPanel::Poll()
+{
+	if (m_delegate) {
+		m_delegate->OnPoll();
+	}
+}
+
 void
 UIPanel::Tick()
 {
diff --git a/screenlib/UIPanel.h b/screenlib/UIPanel.h
index 137a6bc0..ed48467a 100644
--- a/screenlib/UIPanel.h
+++ b/screenlib/UIPanel.h
@@ -38,11 +38,27 @@ class UIPanelDelegate
 public:
 	UIPanelDelegate(UIPanel *panel) { m_panel = panel; }
 
+	// This is called after the panel is loaded
 	virtual bool OnLoad() { return true; }
+
+	// This is called after the panel is shown
 	virtual void OnShow() { }
+
+	// This is called after the panel is hidden
 	virtual void OnHide() { }
+
+	// This is called at least once per frame, before OnTick(),
+	// and more often if there is idle time between frames
+	virtual void OnPoll() { }
+
+	// This is called once per frame before the screen is drawn
 	virtual void OnTick() { }
+
+	// This is called after the panel is drawn, before the screen
+	// is updated, to allow any additional custom drawing.
 	virtual void OnDraw() { }
+
+	// This is called for events not handled by UI elements
 	virtual bool HandleEvent(const SDL_Event &event) { return false; }
 
 protected:
@@ -74,6 +90,7 @@ DECLARE_TYPESAFE_CLASS(UIBaseElement)
 
 	void HideAll();
 
+	virtual void Poll();
 	virtual void Tick();
 	override void Draw();
 	override bool HandleEvent(const SDL_Event &event);