https://github.com/libsdl-org/Maelstrom/commit/ca76f0e28e3e00dfc864073b2d87f24c9dd443a1
From ca76f0e28e3e00dfc864073b2d87f24c9dd443a1 Mon Sep 17 00:00:00 2001
From: Sam Lantinga <[EMAIL REDACTED]>
Date: Tue, 25 Oct 2011 00:40:31 -0400
Subject: [PATCH] Added UI sounds for panels and buttons Added catch-all key
handling buttons
---
UI/loading.xml | 2 +-
UI/main.xml | 17 +++++-----
init.cpp | 8 ++++-
main.cpp | 47 +++-------------------------
screenlib/SDL_FrameBuf.cpp | 2 +-
screenlib/UIArea.h | 4 +--
screenlib/UIElementButton.cpp | 58 +++++++++++++++++++++++++++++------
screenlib/UIElementButton.h | 4 +++
screenlib/UIManager.cpp | 2 ++
screenlib/UIManager.h | 13 ++++++++
screenlib/UIPanel.cpp | 28 +++++++++++++++++
screenlib/UIPanel.h | 5 +++
12 files changed, 126 insertions(+), 64 deletions(-)
diff --git a/UI/loading.xml b/UI/loading.xml
index 54ce8163..902f5c77 100644
--- a/UI/loading.xml
+++ b/UI/loading.xml
@@ -1,4 +1,4 @@
-<UIPanel>
+<UIPanel enterSound="111" leaveSound="123">
<Elements>
<Title name="image" id="130">
<Anchor anchorFrom="CENTER" anchorTo="CENTER"/>
diff --git a/UI/main.xml b/UI/main.xml
index 9a66d696..5d9fb0d4 100644
--- a/UI/main.xml
+++ b/UI/main.xml
@@ -4,6 +4,9 @@
<Anchor anchorFrom="TOPLEFT" anchorTo="CENTER" x="-251" y="-187"/>
</Title>
+ <!-- Catch-all button to bonk when a key is pressed -->
+ <Button hotkey="any" clickSound="108"/>
+
<!-- screen frame -->
<Rectangle>
<Color r="0x75" g="0x75" b="0xFF"/>
@@ -203,35 +206,35 @@
</Label>
<!-- Instructions -->
- <KeyButton name="PlayButton" hotkey="P">
+ <KeyButton name="PlayButton" hotkey="P" clickSound="114">
<Anchor anchorFrom="TOPLEFT" anchorTo="TOPRIGHT" anchor="vertical_divider" x="9" y="10"/>
</KeyButton>
<Label fontName="Geneva" fontSize="9" fontStyle="BOLD" text=" Start playing Maelstrom">
<Color r="0xFF" g="0xFF" b="0x00"/>
<Anchor anchorFrom="BOTTOMLEFT" anchorTo="TOPRIGHT" anchor="PlayButton" x="3" y="21"/>
</Label>
- <KeyButton name="ControlsButton" hotkey="C">
+ <KeyButton name="ControlsButton" hotkey="C" clickSound="119">
<Anchor anchorFrom="TOPLEFT" anchorTo="TOPLEFT" anchor="PlayButton" y="34"/>
</KeyButton>
<Label fontName="Geneva" fontSize="9" fontStyle="BOLD" text=" Configure the game controls">
<Color r="0xFF" g="0xFF" b="0x00"/>
<Anchor anchorFrom="BOTTOMLEFT" anchorTo="TOPRIGHT" anchor="ControlsButton" x="3" y="21"/>
</Label>
- <KeyButton name="ZapButton" hotkey="Z">
+ <KeyButton name="ZapButton" hotkey="Z" clickSound="107">
<Anchor anchorFrom="TOPLEFT" anchorTo="TOPLEFT" anchor="ControlsButton" y="34"/>
</KeyButton>
<Label fontName="Geneva" fontSize="9" fontStyle="BOLD" text=" Zap the high scores">
<Color r="0xFF" g="0xFF" b="0x00"/>
<Anchor anchorFrom="BOTTOMLEFT" anchorTo="TOPRIGHT" anchor="ZapButton" x="3" y="21"/>
</Label>
- <KeyButton name="AboutButton" hotkey="A">
+ <KeyButton name="AboutButton" hotkey="A" clickSound="122">
<Anchor anchorFrom="TOPLEFT" anchorTo="TOPLEFT" anchor="ZapButton" y="34"/>
</KeyButton>
<Label fontName="Geneva" fontSize="9" fontStyle="BOLD" text=" About Maelstrom...">
<Color r="0xFF" g="0xFF" b="0x00"/>
<Anchor anchorFrom="BOTTOMLEFT" anchorTo="TOPRIGHT" anchor="AboutButton" x="3" y="21"/>
</Label>
- <KeyButton name="QuitButton" hotkey="Q">
+ <KeyButton name="QuitButton" hotkey="Q" clickSound="106">
<Anchor anchorFrom="TOPLEFT" anchorTo="TOPLEFT" anchor="AboutButton" y="68"/>
</KeyButton>
<Label fontName="Geneva" fontSize="9" fontStyle="BOLD" text=" Quit Maelstrom">
@@ -255,8 +258,8 @@
<!-- Hidden action buttons -->
<Button name="ToggleFullscreen" hotkey="ALT-Return"/>
- <Button name="Cheat" hotkey="L"/>
- <Button name="Special" hotkey="X"/>
+ <Button name="Cheat" hotkey="L" clickSound="124"/>
+ <Button name="Special" hotkey="X" clickSound="128"/>
<Button name="Screenshot" hotkey="F3"/>
<Button name="SetVolume0" hotkey="0"/>
<Button name="SetVolume1" hotkey="1"/>
diff --git a/init.cpp b/init.cpp
index d093d017..20772835 100644
--- a/init.cpp
+++ b/init.cpp
@@ -641,6 +641,12 @@ void CleanUp(void)
SDL_Quit();
}
+/* This function is called by the UI to play menu sounds */
+static void PlayUISound(void*, int soundID)
+{
+ sound->PlaySound(soundID, 5);
+}
+
/* ----------------------------------------------------------------- */
/* -- Perform some initializations and report failure if we choke */
int DoInitializations(Uint32 window_flags, Uint32 render_flags)
@@ -716,6 +722,7 @@ int DoInitializations(Uint32 window_flags, Uint32 render_flags)
/* Create the UI manager */
ui = new UIManager(screen, CreateMaelstromUIElement);
+ ui->SetSoundCallback(PlayUISound, NULL);
ui->SetLoadPath("UI");
/* Load the Sound Server and initialize sound */
@@ -771,7 +778,6 @@ int DoInitializations(Uint32 window_flags, Uint32 render_flags)
/* -- Throw up our intro screen */
ui->ShowPanel(PANEL_LOADING);
- sound->PlaySound(gPrizeAppears, 1);
ui->Draw();
/* -- Load in our sprites and other needed resources */
diff --git a/main.cpp b/main.cpp
index 7c6c9baf..6a9a4ed7 100644
--- a/main.cpp
+++ b/main.cpp
@@ -40,14 +40,10 @@ static void DrawMainScreen(void);
static void RunDoAbout(void)
{
gNoDelay = 0;
- Delay(SOUND_DELAY);
- sound->PlaySound(gNovaAppears, 5);
DoAbout();
}
static void RunConfigureControls(void)
{
- Delay(SOUND_DELAY);
- sound->PlaySound(gHomingAppears, 5);
ConfigureControls();
}
static void RunPlayGame(void)
@@ -55,14 +51,10 @@ static void RunPlayGame(void)
gStartLives = 3;
gStartLevel = 1;
gNoDelay = 0;
- sound->PlaySound(gNewLife, 5);
- Delay(SOUND_DELAY);
NewGame();
}
static void RunQuitGame(void)
{
- Delay(SOUND_DELAY);
- sound->PlaySound(gMultiplierGone, 5);
while ( sound->Playing() )
Delay(SOUND_DELAY);
gRunning = false;
@@ -101,8 +93,6 @@ static void SetSoundLevel(int volume)
}
static void RunZapScores(void)
{
- Delay(SOUND_DELAY);
- sound->PlaySound(gMultShotSound, 5);
if ( ZapHighScores() ) {
/* Fade the screen and redisplay scores */
screen->Fade();
@@ -117,8 +107,6 @@ static void RunToggleFullscreen(void)
}
static void RunCheat(void)
{
- Delay(SOUND_DELAY);
- sound->PlaySound(gLuckySound, 5);
gStartLevel = GetStartLevel();
if ( gStartLevel > 0 ) {
Delay(SOUND_DELAY);
@@ -127,12 +115,6 @@ static void RunCheat(void)
NewGame();
}
}
-static void RunSpecial(void)
-{
- Delay(SOUND_DELAY);
- sound->PlaySound(gEnemyAppears, 5);
- ShowDawn();
-}
static void RunScreenshot(void)
{
screen->ScreenDump("ScoreDump", 64, 48, 298, 384);
@@ -336,11 +318,10 @@ int main(int argc, char *argv[])
SetupMainScreen();
+ DropEvents();
gRunning = true;
- sound->PlaySound(gNovaBoom, 5);
- Delay(SOUND_DELAY);
- while ( sound->Playing() )
- Delay(SOUND_DELAY);
+// while ( sound->Playing() )
+// Delay(SOUND_DELAY);
ui->ShowPanel(PANEL_MAIN);
while ( gRunning ) {
@@ -355,26 +336,6 @@ int main(int argc, char *argv[])
if ( ui->HandleEvent(event) )
continue;
- /* -- Handle it! */
- if ( event.type == SDL_KEYDOWN ) {
- switch (event.key.keysym.sym) {
-
- // Ignore Shift, Ctrl, Alt keys
- case SDLK_LSHIFT:
- case SDLK_RSHIFT:
- case SDLK_LCTRL:
- case SDLK_RCTRL:
- case SDLK_LALT:
- case SDLK_RALT:
- break;
-
- // Dink! :-)
- default:
- Delay(SOUND_DELAY);
- sound->PlaySound(gSteelHit, 5);
- break;
- }
- } else
/* -- Handle window close requests */
if ( event.type == SDL_QUIT ) {
RunQuitGame();
@@ -466,7 +427,7 @@ void SetupMainScreen()
}
button = panel->GetElement<UIElementButton>("Special");
if (button) {
- button->SetClickCallback(RunSpecial);
+ button->SetClickCallback(ShowDawn);
}
button = panel->GetElement<UIElementButton>("Screenshot");
if (button) {
diff --git a/screenlib/SDL_FrameBuf.cpp b/screenlib/SDL_FrameBuf.cpp
index a190e6c9..9e6f1b05 100644
--- a/screenlib/SDL_FrameBuf.cpp
+++ b/screenlib/SDL_FrameBuf.cpp
@@ -131,7 +131,7 @@ void
FrameBuf:: Fade(void)
{
// Temporary for development
-//return;
+return;
const int max = 32;
Uint16 ramp[256];
diff --git a/screenlib/UIArea.h b/screenlib/UIArea.h
index 44771e54..45ca0033 100644
--- a/screenlib/UIArea.h
+++ b/screenlib/UIArea.h
@@ -105,10 +105,10 @@ class UIArea : public ErrorBase
}
void GetAnchorLocation(AnchorLocation spot, int *x, int *y) const;
- void Show() {
+ virtual void Show() {
m_shown = true;
}
- void Hide() {
+ virtual void Hide() {
m_shown = false;
}
bool IsShown() const {
diff --git a/screenlib/UIElementButton.cpp b/screenlib/UIElementButton.cpp
index ea2eec43..0bbe3ed4 100644
--- a/screenlib/UIElementButton.cpp
+++ b/screenlib/UIElementButton.cpp
@@ -50,6 +50,7 @@ UIElementButton::UIElementButton(UIPanel *panel, const char *name) :
m_hotkeyMod = KMOD_NONE;
m_mouseInside = false;
m_mousePressed = false;
+ m_clickSound = 0;
m_clickPanel = NULL;
m_callback = NULL;
}
@@ -90,14 +91,23 @@ UIElementButton::Load(rapidxml::xml_node<> *node)
value = hyphen+1;
}
- m_hotkey = SDL_GetKeyFromName(value);
- if (m_hotkey == SDLK_UNKNOWN) {
- SetError("Couldn't interpret hotkey value '%s'", value);
- return false;
+ if (strcmp(value, "any") == 0) {
+ /* This will be a catch-all button */
+ m_hotkey = ~0;
+ } else {
+ m_hotkey = SDL_GetKeyFromName(value);
+ if (m_hotkey == SDLK_UNKNOWN) {
+ SetError("Couldn't interpret hotkey value '%s'", value);
+ return false;
+ }
}
}
- attr = node->first_attribute("clickActivatePanel", 0, false);
+ attr = node->first_attribute("clickSound", 0, false);
+ if (attr) {
+ m_clickSound = atoi(attr->value());
+ }
+ attr = node->first_attribute("clickPanel", 0, false);
if (attr) {
const char *value = attr->value();
m_clickPanel = new char[strlen(value)+1];
@@ -106,6 +116,31 @@ UIElementButton::Load(rapidxml::xml_node<> *node)
return UIElement::Load(node);
}
+bool
+UIElementButton::ShouldHandleKey(SDL_Keycode key)
+{
+ if (key == m_hotkey) {
+ return true;
+ }
+ if (m_hotkey == ~0) {
+ switch (key) {
+ // Ignore modifier keys
+ case SDLK_LSHIFT:
+ case SDLK_RSHIFT:
+ case SDLK_LCTRL:
+ case SDLK_RCTRL:
+ case SDLK_LALT:
+ case SDLK_RALT:
+ case SDLK_LGUI:
+ case SDLK_RGUI:
+ return false;
+ default:
+ return true;
+ }
+ }
+ return false;
+}
+
bool
UIElementButton::HandleEvent(const SDL_Event &event)
{
@@ -144,7 +179,8 @@ UIElementButton::HandleEvent(const SDL_Event &event)
return true;
}
- if (event.type == SDL_KEYDOWN && event.key.keysym.sym == m_hotkey) {
+ if (event.type == SDL_KEYDOWN &&
+ ShouldHandleKey(event.key.keysym.sym)) {
if (!m_mousePressed) {
m_mousePressed = true;
OnMouseDown();
@@ -152,7 +188,8 @@ UIElementButton::HandleEvent(const SDL_Event &event)
return true;
}
- if (event.type == SDL_KEYUP && event.key.keysym.sym == m_hotkey) {
+ if (event.type == SDL_KEYUP &&
+ ShouldHandleKey(event.key.keysym.sym)) {
if (!m_hotkeyMod || (event.key.keysym.mod & m_hotkeyMod)) {
if (m_mousePressed) {
m_mousePressed = false;
@@ -169,12 +206,15 @@ UIElementButton::HandleEvent(const SDL_Event &event)
void
UIElementButton::OnClick()
{
- if (m_callback) {
- m_callback->OnClick();
+ if (m_clickSound) {
+ m_panel->GetUI()->PlaySound(m_clickSound);
}
if (m_clickPanel) {
m_panel->GetUI()->ShowPanel(m_clickPanel);
}
+ if (m_callback) {
+ m_callback->OnClick();
+ }
}
void
diff --git a/screenlib/UIElementButton.h b/screenlib/UIElementButton.h
index 2ffc170a..eeb63b81 100644
--- a/screenlib/UIElementButton.h
+++ b/screenlib/UIElementButton.h
@@ -61,9 +61,13 @@ class UIElementButton : public UIElement
int m_hotkeyMod;
bool m_mouseInside;
bool m_mousePressed;
+ int m_clickSound;
char *m_clickPanel;
UIButtonCallback *m_callback;
+protected:
+ bool ShouldHandleKey(SDL_Keycode key);
+
protected:
static UIElementType s_elementType;
diff --git a/screenlib/UIManager.cpp b/screenlib/UIManager.cpp
index ceee020f..d2a4b2ff 100644
--- a/screenlib/UIManager.cpp
+++ b/screenlib/UIManager.cpp
@@ -28,6 +28,8 @@
UIManager::UIManager(FrameBuf *screen, UIElementFactory factory) : UIArea(screen)
{
m_elementFactory = factory;
+ m_soundCallback = NULL;
+ m_soundCallbackParam = NULL;
m_loadPath = new char[2];
strcpy(m_loadPath, ".");
}
diff --git a/screenlib/UIManager.h b/screenlib/UIManager.h
index 8a7cc2dc..52c1d453 100644
--- a/screenlib/UIManager.h
+++ b/screenlib/UIManager.h
@@ -32,6 +32,7 @@ class UIPanel;
class UIElement;
typedef UIElement *(*UIElementFactory)(UIPanel *panel, const char *name);
+typedef void (*UISoundCallback)(void *, int soundID);
class UIManager : public UIArea
{
@@ -75,11 +76,23 @@ class UIManager : public UIArea
DeletePanel(GetPanel(name));
}
+ void SetSoundCallback(UISoundCallback callback, void *param) {
+ m_soundCallback = callback;
+ m_soundCallbackParam = param;
+ }
+ void PlaySound(int soundID) {
+ if (m_soundCallback) {
+ m_soundCallback(m_soundCallbackParam, soundID);
+ }
+ }
+
void Draw(bool fullUpdate = true);
bool HandleEvent(const SDL_Event &event);
protected:
UIElementFactory m_elementFactory;
+ UISoundCallback m_soundCallback;
+ void *m_soundCallbackParam;
char *m_loadPath;
array<UIPanel *> m_panels;
array<UIPanel *> m_visible;
diff --git a/screenlib/UIPanel.cpp b/screenlib/UIPanel.cpp
index 9cb59c72..36d24c82 100644
--- a/screenlib/UIPanel.cpp
+++ b/screenlib/UIPanel.cpp
@@ -38,6 +38,8 @@ UIPanel::UIPanel(UIManager *ui, const char *name) : UIArea(ui->GetScreen())
m_rect.h = m_screen->Height();
m_shown = false;
m_fullscreen = true;
+ m_enterSound = 0;
+ m_leaveSound = 0;
m_ui->AddPanel(this);
}
@@ -103,6 +105,14 @@ UIPanel::Load(const char *file)
m_fullscreen = false;
}
}
+ attr = node->first_attribute("enterSound", 0, false);
+ if (attr) {
+ m_enterSound = atoi(attr->value());
+ }
+ attr = node->first_attribute("leaveSound", 0, false);
+ if (attr) {
+ m_leaveSound = atoi(attr->value());
+ }
if (strcmp(node->name(), "UIPanel") != 0) {
SetError("Parse error: UIPanel root element expected");
delete[] buffer;
@@ -162,6 +172,24 @@ UIPanel::GetElement(const char *name)
return NULL;
}
+void
+UIPanel::Show()
+{
+ if (m_enterSound) {
+ m_ui->PlaySound(m_enterSound);
+ }
+ UIArea::Show();
+}
+
+void
+UIPanel::Hide()
+{
+ if (m_leaveSound) {
+ m_ui->PlaySound(m_leaveSound);
+ }
+ UIArea::Hide();
+}
+
void
UIPanel::Draw()
{
diff --git a/screenlib/UIPanel.h b/screenlib/UIPanel.h
index c09b4e1a..26ff81a2 100644
--- a/screenlib/UIPanel.h
+++ b/screenlib/UIPanel.h
@@ -70,6 +70,9 @@ class UIPanel : public UIArea
m_elements.remove(element);
}
+ virtual void Show();
+ virtual void Hide();
+
void Draw();
bool HandleEvent(const SDL_Event &event);
@@ -77,6 +80,8 @@ class UIPanel : public UIArea
UIManager *m_ui;
char *m_name;
bool m_fullscreen;
+ int m_enterSound;
+ int m_leaveSound;
array<UIElement *> m_elements;
UIElement *GetElement(const char *name);