Maelstrom: The about screens are fully functional

https://github.com/libsdl-org/Maelstrom/commit/5ed8a48d862d2024ebb2bb937fedaaf8f3f20f56

From 5ed8a48d862d2024ebb2bb937fedaaf8f3f20f56 Mon Sep 17 00:00:00 2001
From: Sam Lantinga <[EMAIL REDACTED]>
Date: Tue, 25 Oct 2011 02:34:00 -0400
Subject: [PATCH] The about screens are fully functional

---
 Makefile.am        |   2 +
 UI/about_game.xml  |  25 +++++
 UIElementIcon.cpp  |  32 ++++++
 UIElementIcon.h    |  30 ++++++
 UIElementTitle.cpp |   2 +-
 UIElements.cpp     |   7 +-
 main.cpp           |  33 ++++--
 netlogic/about.cpp | 261 +++++++++++++--------------------------------
 8 files changed, 191 insertions(+), 201 deletions(-)
 create mode 100644 UIElementIcon.cpp
 create mode 100644 UIElementIcon.h

diff --git a/Makefile.am b/Makefile.am
index 732e7897..43ffce36 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -29,6 +29,8 @@ Maelstrom_SOURCES =		\
 	rect.h			\
 	scores.cpp		\
 	scores.h		\
+	UIElementIcon.cpp	\
+	UIElementIcon.h		\
 	UIElementKeyButton.cpp	\
 	UIElementKeyButton.h	\
 	UIElementLabel.cpp	\
diff --git a/UI/about_game.xml b/UI/about_game.xml
index 0f62b0b5..f74bd6d8 100644
--- a/UI/about_game.xml
+++ b/UI/about_game.xml
@@ -39,6 +39,31 @@
 			<Anchor anchorFrom="CENTER" anchorTo="CENTER"/>
 		</Rectangle>
 
+		<!-- Shield icon -->
+		<Icon id="137">
+			<Anchor anchorFrom="TOPLEFT" anchorTo="TOPLEFT" anchor="image" x="25" y="314"/>
+		</Icon>
+		<!-- Airbrakes icon -->
+		<Icon id="129">
+			<Anchor anchorFrom="TOPLEFT" anchorTo="TOPLEFT" anchor="image" x="41" y="314"/>
+		</Icon>
+		<!-- Longfire icon -->
+		<Icon id="136">
+			<Anchor anchorFrom="TOPLEFT" anchorTo="TOPLEFT" anchor="image" x="25" y="328"/>
+		</Icon>
+		<!-- Triplefire icon -->
+		<Icon id="135">
+			<Anchor anchorFrom="TOPLEFT" anchorTo="TOPLEFT" anchor="image" x="41" y="328"/>
+		</Icon>
+		<!-- Autofire icon -->
+		<Icon id="128">
+			<Anchor anchorFrom="TOPLEFT" anchorTo="TOPLEFT" anchor="image" x="25" y="342"/>
+		</Icon>
+		<!-- Lucky icon -->
+		<Icon id="133">
+			<Anchor anchorFrom="TOPLEFT" anchorTo="TOPLEFT" anchor="image" x="41" y="342"/>
+		</Icon>
+
 		<!-- Buttons -->
 		<Button hotkey="any" clickPanel="main" clickSound="106"/>
 		<Button hotkey="Return" clickPanel="about_credits" clickSound="102">
diff --git a/UIElementIcon.cpp b/UIElementIcon.cpp
new file mode 100644
index 00000000..9edd4368
--- /dev/null
+++ b/UIElementIcon.cpp
@@ -0,0 +1,32 @@
+
+#include "UIElementIcon.h"
+#include "load.h"
+
+UIElementType UIElementIcon::s_elementType;
+
+
+UIElementIcon::UIElementIcon(UIPanel *panel, const char *name) :
+	UIElementTexture(panel, name)
+{
+}
+
+bool
+UIElementIcon::Load(rapidxml::xml_node<> *node)
+{
+	rapidxml::xml_attribute<> *attr;
+
+	attr = node->first_attribute("id", 0, false);
+	if (!attr) {
+		SetError("Element '%s' missing attribute 'id'", node->name());
+		return false;
+	}
+
+	SDL_Texture *texture = GetCIcon(m_screen, atoi(attr->value()));
+	if (!texture) {
+		SetError("Unable to load icon %d", atoi(attr->value()));
+		return false;
+	}
+	SetTexture(texture);
+
+	return UIElementTexture::Load(node);
+}
diff --git a/UIElementIcon.h b/UIElementIcon.h
new file mode 100644
index 00000000..a0622fb0
--- /dev/null
+++ b/UIElementIcon.h
@@ -0,0 +1,30 @@
+#ifndef _UIElementIcon_h
+#define _UIElementIcon_h
+
+#include "screenlib/UIElementTexture.h"
+
+
+class UIElementIcon : public UIElementTexture
+{
+public:
+	UIElementIcon(UIPanel *panel, const char *name = "");
+
+	virtual bool IsA(UIElementType type) {
+		return UIElementTexture::IsA(type) || type == GetType();
+	}
+
+	virtual bool Load(rapidxml::xml_node<> *node);
+
+protected:
+	static UIElementType s_elementType;
+
+public:
+	static UIElementType GetType() {
+		if (!s_elementType) {
+			s_elementType = GenerateType();
+		}
+		return s_elementType;
+	}
+};
+
+#endif // _UIElementIcon_h
diff --git a/UIElementTitle.cpp b/UIElementTitle.cpp
index 19d2a61c..62bf7f86 100644
--- a/UIElementTitle.cpp
+++ b/UIElementTitle.cpp
@@ -17,7 +17,7 @@ UIElementTitle::Load(rapidxml::xml_node<> *node)
 
 	attr = node->first_attribute("id", 0, false);
 	if (!attr) {
-		SetError("Element 'Title' missing attribute 'id'");
+		SetError("Element '%s' missing attribute 'id'", node->name());
 		return false;
 	}
 
diff --git a/UIElements.cpp b/UIElements.cpp
index cbfa0af5..4f0cebef 100644
--- a/UIElements.cpp
+++ b/UIElements.cpp
@@ -3,6 +3,7 @@
 #include "screenlib/UIElementButton.h"
 #include "screenlib/UIElementLine.h"
 #include "screenlib/UIElementRect.h"
+#include "UIElementIcon.h"
 #include "UIElementKeyButton.h"
 #include "UIElementLabel.h"
 #include "UIElementTitle.h"
@@ -19,10 +20,12 @@ CreateMaelstromUIElement(UIPanel *panel, const char *name)
 		return new UIElementLabel(panel);
 	} else if (strcasecmp(name, "Button") == 0) {
 		return new UIElementButton(panel);
-	} else if (strcasecmp(name, "Title") == 0) {
-		return new UIElementTitle(panel);
 	} else if (strcasecmp(name, "KeyButton") == 0) {
 		return new UIElementKeyButton(panel);
+	} else if (strcasecmp(name, "Icon") == 0) {
+		return new UIElementIcon(panel);
+	} else if (strcasecmp(name, "Title") == 0) {
+		return new UIElementTitle(panel);
 	}
 	return NULL;
 }
diff --git a/main.cpp b/main.cpp
index 36f28ecc..9ce28fa7 100644
--- a/main.cpp
+++ b/main.cpp
@@ -14,6 +14,7 @@
 #include "load.h"
 #include "fastrand.h"
 #include "checksum.h"
+#include "about.h"
 
 #include "UIElementLabel.h"
 #include "UIElementKeyButton.h"
@@ -325,23 +326,26 @@ int main(int argc, char *argv[])
 
 	while ( gRunning ) {
 		
-		/* Update the screen if necessary */
+		/* -- Update the screen if necessary */
 		if ( gUpdateBuffer )
 			DrawMainScreen();
 
-		/* -- Get an event */
-		screen->WaitEvent(&event);
+		ui->Draw();
 
-		if ( ui->HandleEvent(event) )
-			continue;
+		/* -- Get events */
+		while ( screen->PollEvent(&event) ) {
+			if ( ui->HandleEvent(event) )
+				continue;
 
-		/* -- Handle window close requests */
-		if ( event.type == SDL_QUIT ) {
-			RunQuitGame();
+			/* -- Handle window close requests */
+			if ( event.type == SDL_QUIT ) {
+				RunQuitGame();
+			}
 		}
+		Delay(FRAME_DELAY);
 	}
-	screen->Fade();
-	Delay(60);
+
+	ui->HidePanel(PANEL_MAIN);
 	return(0);
 }	/* -- main */
 
@@ -376,7 +380,7 @@ void SetupMainScreen()
 	UIElementLabel *label;
 	UIElementButton *button;
 
-	panel = ui->GetPanel("main");
+	panel = ui->GetPanel(PANEL_MAIN);
 	if (!panel) {
 		return;
 	}
@@ -471,6 +475,13 @@ void SetupMainScreen()
 	}
 
 	DrawMainScreen();
+
+
+	/* Hook up functionality for other panels */
+	panel = ui->GetPanel("about_game");
+	if (panel) {
+		panel->SetPanelDelegate(new AboutPanelDelegate);
+	}
 }
 
 
diff --git a/netlogic/about.cpp b/netlogic/about.cpp
index 1392a3ed..041e6f13 100644
--- a/netlogic/about.cpp
+++ b/netlogic/about.cpp
@@ -1,202 +1,89 @@
 
 #include "Maelstrom_Globals.h"
 #include "object.h"
-#include "load.h"
+#include "about.h"
 
-#define	ICON_V_OFF	14
 
-#define KEYPRESS(X)	(X.type == SDL_KEYDOWN)
-#define BUTTONPRESS(X)	(X.type == SDL_MOUSEBUTTONDOWN)
-
-/* ----------------------------------------------------------------- */
-/* -- Tell 'em about the game */
+AboutPanelDelegate::AboutPanelDelegate()
+{
+	numsprites = 0;
+}
 
-void DoAbout(void)
+AboutPanelDelegate::~AboutPanelDelegate()
 {
-	SDL_Texture *title = NULL;
-	SDL_Event event;
-	Uint32 clr, ltClr, ltrClr;
-	Bool done = false;
-	int idOn = 133;
-	Bool next_screen = true;
-	int width, height;
-	int xOff, yOff;
-	int numsprites=0, i;
-	Object *objects[MAX_SPRITES];
+	assert(numsprites == 0);
+}
 
-	/* Set up the colors */
-	clr = screen->MapRGB(30000>>8, 30000>>8, 0xFF);
-	ltClr = screen->MapRGB(40000>>8, 40000>>8, 0xFF);
-	ltrClr = screen->MapRGB(50000>>8, 50000>>8, 0xFF);
+void
+AboutPanelDelegate::OnShow()
+{
+	int x, y, off;
 
 	gNoDelay = 0;
 
-	while ( ! done ) {
-		/* -- Handle updates */
-		if ( next_screen ) {
-			screen->Fade();
-
-			if ( title ) {
-				screen->FreeImage(title);
-			}
-			title = Load_Title(screen, idOn);
-			if ( title == NULL ) {
-				error("Can't load 'about' title! (ID=%d)\n", idOn);
-				break;
-			}
-
-			if ( idOn == 134 ) {
-				int x, y, off;
-
-				x = (80) * SCALE_FACTOR;
-				y = (136) * SCALE_FACTOR;
-				off = 39 * SCALE_FACTOR;
-
-				objects[numsprites++] = 
-					new Object(x, y, 0, 0, gPlayerShip, 1);
-				y += off;
-				objects[numsprites++] = 
-					new Object(x, y, 0, 0, gPrize, 2);
-				y += off;
-				objects[numsprites++] = 
-					new Object(x, y, 0, 0, gBonusBlit, 2);
-				y += off;
-				objects[numsprites++] = 
-					new Object(x, y, 0, 0, gMult[3], 1);
-				y += off;
-				objects[numsprites++] = 
-					new Object(x, y, 0, 0, gDamagedShip, 1);
-				y += off;
-
-				/* -- Now for the second column */
-				x = (340) * SCALE_FACTOR;
-				y = (136) * SCALE_FACTOR;
-				off = 39 * SCALE_FACTOR;
-
-				objects[numsprites++] = 
-					new Object(x, y, 0, 0, gRock1R, 1);
-				y += off;
-				objects[numsprites++] = 
-					new Object(x, y, 0, 0, gSteelRoidR, 1);
-				y += off;
-				objects[numsprites++] = 
-					new Object(x, y, 0, 0, gNova, 4);
-				y += off;
-				objects[numsprites++] = 
-					new Object(x, y, 0, 0, gMineBlitL, 1);
-				y += off;
-				objects[numsprites++] = 
-					new Object(x, y, 0, 0, gVortexBlit, 3);
-				y += off;
-				objects[numsprites++] = 
-					new Object(x, y, 0, 0, gEnemyShip, 1);
-				y += off;
-
-			}
-		}
-
-		screen->Clear();
-
-		/* -- Draw the screen frame */
-		width = 512;
-		height = 384;
-		xOff = ((gScrnRect.right - gScrnRect.left) - width) /2;
-		yOff = ((gScrnRect.bottom - gScrnRect.top) - height)/2;
-
-		screen->DrawRect(xOff-1,yOff-1,width+2,height+2,clr);
-		screen->DrawRect(xOff-2,yOff-2,width+4,height+4,clr);
-		screen->DrawRect(xOff-3,yOff-3,width+6,height+6,ltClr);
-		screen->DrawRect(xOff-4,yOff-4,width+8,height+8,ltClr);
-		screen->DrawRect(xOff-5,yOff-5,width+10,height+10,ltrClr);
-		screen->DrawRect(xOff-6,yOff-6,width+12,height+12,ltClr);
-		screen->DrawRect(xOff-7,yOff-7,width+14,height+14,clr);
-		screen->DrawRect(xOff,yOff,width,height,ltClr);
-
-		/* -- Now draw the picture */
-		screen->QueueBlit(xOff, yOff, title, NOCLIP);
-
-		/* Draw color icons if this is Game screen */
-		if ( idOn == 134 ) {
-			int x, y;
-
-			/* Now for the icons */
-			x = xOff+25;
-			y = yOff+314;
-			screen->QueueBlit(x, y, gShieldIcon, NOCLIP);
-			screen->QueueBlit(x+16, y, gAirBrakesIcon, NOCLIP);
-			y += ICON_V_OFF;
-			screen->QueueBlit(x, y, gLongFireIcon, NOCLIP);
-			screen->QueueBlit(x+16, y, gTripleFireIcon, NOCLIP);
-			y += ICON_V_OFF;
-			screen->QueueBlit(x, y, gAutoFireIcon, NOCLIP);
-			screen->QueueBlit(x+16, y, gLuckOfTheIrishIcon, NOCLIP);
-		}
-		if ( idOn == 135 ) {
-			MFont *font;
-			SDL_Texture *text1, *text2;
-
-			/* Put in the right credits / mask the old... */
-			clr = screen->MapRGB(0x00, 0x00, 0x00);
-			screen->FillRect(xOff+166,yOff+282,338,62,clr);
-			font = fonts[NEWYORK_18];
-			text1 = fontserv->TextImage("Port to Linux:   ",
-				font, STYLE_NORM, 0xFF, 0xFF, 0x55);
-			text2 = fontserv->TextImage("Sam Lantinga",
-				font, STYLE_NORM, 0xFF, 0xFF, 0xFF);
-			screen->QueueBlit(xOff+178, yOff+298, text1, NOCLIP);
-			screen->QueueBlit(xOff+178+screen->GetImageWidth(text1), yOff+298, text2, NOCLIP);
-			fontserv->FreeText(text1);
-			fontserv->FreeText(text2);
-		}
-
-		/* Rotate any sprites */
-		for ( i=0; i<numsprites; ++i ) {
-			objects[i]->Move(0);
-			objects[i]->BlitSprite();
-		}
-		screen->Update();
-
-		if ( next_screen ) {
-			screen->Fade();
-			next_screen = false;
-		}
-
-		/* Wait for keyboard input */
-		while ( SDL_PollEvent(&event) ) {
-		
-			if ( KEYPRESS(event) || BUTTONPRESS(event) ) {
-				int sound_to_play = 0;
+	x = (80) * SCALE_FACTOR;
+	y = (136) * SCALE_FACTOR;
+	off = 39 * SCALE_FACTOR;
+
+	objects[numsprites++] = 
+		new Object(x, y, 0, 0, gPlayerShip, 1);
+	y += off;
+	objects[numsprites++] = 
+		new Object(x, y, 0, 0, gPrize, 2);
+	y += off;
+	objects[numsprites++] = 
+		new Object(x, y, 0, 0, gBonusBlit, 2);
+	y += off;
+	objects[numsprites++] = 
+		new Object(x, y, 0, 0, gMult[3], 1);
+	y += off;
+	objects[numsprites++] = 
+		new Object(x, y, 0, 0, gDamagedShip, 1);
+	y += off;
+
+	/* -- Now for the second column */
+	x = (340) * SCALE_FACTOR;
+	y = (136) * SCALE_FACTOR;
+	off = 39 * SCALE_FACTOR;
+
+	objects[numsprites++] = 
+		new Object(x, y, 0, 0, gRock1R, 1);
+	y += off;
+	objects[numsprites++] = 
+		new Object(x, y, 0, 0, gSteelRoidR, 1);
+	y += off;
+	objects[numsprites++] = 
+		new Object(x, y, 0, 0, gNova, 4);
+	y += off;
+	objects[numsprites++] = 
+		new Object(x, y, 0, 0, gMineBlitL, 1);
+	y += off;
+	objects[numsprites++] = 
+		new Object(x, y, 0, 0, gVortexBlit, 3);
+	y += off;
+	objects[numsprites++] = 
+		new Object(x, y, 0, 0, gEnemyShip, 1);
+	y += off;
+
+}
+
+void
+AboutPanelDelegate::OnHide()
+{
+	int i;
 
-				next_screen = (
-					(event.type == SDL_MOUSEBUTTONDOWN) ||
-					(event.key.keysym.sym == SDLK_RETURN)
-					);
-			
-				if ( next_screen ) {
-					sound_to_play = gExplosionSound;
-				} else {
-					done = true;
-					sound_to_play = gMultiplierGone;
-				}
-				
-				if ( ++idOn > 135 ) {
-					done = true;
-					sound_to_play = gPrettyGood;
-				}
-				Delay(SOUND_DELAY);
-				sound->PlaySound(sound_to_play, 5);
+	for ( i=0; i<numsprites; ++i )
+		delete objects[i];
+	numsprites = 0;
+}
 
-				for ( i=0; i<numsprites; ++i )
-					delete objects[i];
-				numsprites = 0;
-			}
-		}
-		Delay(1);
+void
+AboutPanelDelegate::OnDraw()
+{
+	int i;
 
+	for ( i=0; i<numsprites; ++i ) {
+		objects[i]->Move(0);
+		objects[i]->BlitSprite();
 	}
-	if ( title ) {
-		screen->FreeImage(title);
-	}
-	screen->Fade();
-	gUpdateBuffer = true;
-}	/* -- DoAbout */
+}