From 78c5a8ac0ebfc1e55cb070c1b7f53e357479bd91 Mon Sep 17 00:00:00 2001
From: Sam Lantinga <[EMAIL REDACTED]>
Date: Thu, 2 Apr 2026 23:04:37 -0700
Subject: [PATCH] Draw the touch controls with 50% alpha
---
Data/UI/game.xml | 72 +++++++++++++++++++-------------------
screenlib/SDL_FrameBuf.h | 24 ++++++-------
screenlib/UIDrawEngine.cpp | 10 +++---
screenlib/UIElement.cpp | 12 +++++++
screenlib/UIElement.h | 3 ++
screenlib/UITexture.cpp | 4 ++-
screenlib/UITexture.h | 2 +-
7 files changed, 73 insertions(+), 54 deletions(-)
diff --git a/Data/UI/game.xml b/Data/UI/game.xml
index 5f574aa5..38d54aeb 100644
--- a/Data/UI/game.xml
+++ b/Data/UI/game.xml
@@ -102,89 +102,89 @@
<Area condition="!PHONE" name="touch_controls" show="false">
<Elements>
<!-- Touch controls -->
- <Button name="abort" action="CONTROL_ABORT" image="circle">
+ <Button name="abort" action="CONTROL_ABORT" image="circle" alpha="128">
<Size w="30" h="30"/>
<Anchor anchorFrom="TOPLEFT" anchorTo="TOPLEFT" x="20" y="8"/>
<Elements>
- <Image image="abort">
+ <Image image="abort" alpha="128">
<Size w="24" h="24"/>
<Anchor anchorFrom="CENTER" anchorTo="CENTER"/>
</Image>
</Elements>
</Button>
- <Button name="pause" action="CONTROL_PAUSE" image="circle">
+ <Button name="pause" action="CONTROL_PAUSE" image="circle" alpha="128">
<Size w="30" h="30"/>
<Anchor anchorFrom="TOPRIGHT" anchorTo="TOPRIGHT" x="-20" y="8"/>
<Elements>
- <Image image="pause">
+ <Image image="pause" alpha="128">
<Size w="24" h="24"/>
<Anchor anchorFrom="CENTER" anchorTo="CENTER"/>
</Image>
</Elements>
</Button>
- <Button name="zoom" action="CONTROL_ZOOM" image="circle">
+ <Button name="zoom" action="CONTROL_ZOOM" image="circle" alpha="128">
<Size w="30" h="30"/>
<Anchor anchorFrom="TOP" anchorTo="BOTTOM" anchor="pause" y="8"/>
<Elements>
- <Image name="zoom_in" image="zoom-in">
+ <Image name="zoom_in" image="zoom-in" alpha="128">
<Size w="24" h="24"/>
<Anchor anchorFrom="CENTER" anchorTo="CENTER"/>
</Image>
- <Image name="zoom_out" image="zoom-out">
+ <Image name="zoom_out" image="zoom-out" alpha="128">
<Size w="24" h="24"/>
<Anchor anchorFrom="CENTER" anchorTo="CENTER"/>
</Image>
</Elements>
</Button>
- <Thumbstick image="split-circle">
+ <Thumbstick image="split-circle" alpha="128">
<Size w="85" h="85"/>
<Anchor anchorFrom="BOTTOMLEFT" anchorTo="BOTTOMLEFT" x="20" y="-20"/>
<Action angle="90" arc="180" active_radius="0" action_enter="CONTROL_DOWN_RIGHT" action_leave="CONTROL_UP_RIGHT"/>
<Action angle="270" arc="180" active_radius="0" action_enter="CONTROL_DOWN_LEFT" action_leave="CONTROL_UP_LEFT"/>
<Elements>
- <Image image="rotate-left">
+ <Image image="rotate-left" alpha="128">
<Size w="30" h="30"/>
<Anchor anchorFrom="LEFT" anchorTo="LEFT" x="6"/>
</Image>
- <Image image="rotate-right">
+ <Image image="rotate-right" alpha="128">
<Size w="30" h="30"/>
<Anchor anchorFrom="RIGHT" anchorTo="RIGHT" x="-6"/>
</Image>
</Elements>
</Image>
- <Thumbstick name="fire" image="circle">
+ <Thumbstick name="fire" image="circle" alpha="128">
<Size w="40" h="40"/>
<Anchor anchorFrom="BOTTOMRIGHT" anchorTo="BOTTOMRIGHT" x="-60" y="-30"/>
<Action action_enter="CONTROL_DOWN_FIRE" action_leave="CONTROL_UP_FIRE"/>
<Elements>
- <Icon id="136">
+ <Icon id="136" alpha="128">
<Size w="16" h="16"/>
<Anchor anchorFrom="CENTER" anchorTo="CENTER"/>
</Icon>
</Elements>
</Thumbstick>
- <Thumbstick name="shield" image="circle">
+ <Thumbstick name="shield" image="circle" alpha="128">
<Size w="40" h="40"/>
<Anchor anchorFrom="BOTTOMRIGHT" anchorTo="BOTTOMRIGHT" x="-30" y="-60"/>
<Action action_enter="CONTROL_DOWN_SHIELD" action_leave="CONTROL_UP_SHIELD"/>
<Elements>
- <Image image="shield">
+ <Image image="shield" alpha="128">
<Size w="16" h="16"/>
<Anchor anchorFrom="CENTER" anchorTo="CENTER"/>
- </Icon>
+ </Image>
</Elements>
</Thumbstick>
- <Thumbstick name="thrust" image="circle">
+ <Thumbstick name="thrust" image="circle" alpha="128">
<Size w="40" h="40"/>
<Anchor anchorFrom="BOTTOMRIGHT" anchorTo="BOTTOMRIGHT" x="-90" y="-60"/>
<Action action_enter="CONTROL_DOWN_THRUST" action_leave="CONTROL_UP_THRUST"/>
<Elements>
- <Image image="thrust">
+ <Image image="thrust" alpha="128">
<Size w="16" h="16"/>
<Anchor anchorFrom="CENTER" anchorTo="CENTER"/>
- </Icon>
+ </Image>
</Elements>
</Thumbstick>
</Elements>
@@ -193,89 +193,89 @@
<Area condition="PHONE" name="touch_controls" show="false">
<Elements>
<!-- Touch controls -->
- <Button name="abort" action="CONTROL_ABORT" image="circle">
+ <Button name="abort" action="CONTROL_ABORT" image="circle" alpha="128">
<Size w="45" h="45"/>
<Anchor anchorFrom="TOPLEFT" anchorTo="TOPLEFT" x="30" y="12"/>
<Elements>
- <Image image="abort">
+ <Image image="abort" alpha="128">
<Size w="36" h="36"/>
<Anchor anchorFrom="CENTER" anchorTo="CENTER"/>
</Image>
</Elements>
</Button>
- <Button name="pause" action="CONTROL_PAUSE" image="circle">
+ <Button name="pause" action="CONTROL_PAUSE" image="circle" alpha="128">
<Size w="45" h="45"/>
<Anchor anchorFrom="TOPRIGHT" anchorTo="TOPRIGHT" x="-30" y="12"/>
<Elements>
- <Image image="pause">
+ <Image image="pause" alpha="128">
<Size w="36" h="36"/>
<Anchor anchorFrom="CENTER" anchorTo="CENTER"/>
</Image>
</Elements>
</Button>
- <Button name="zoom" action="CONTROL_ZOOM" image="circle">
+ <Button name="zoom" action="CONTROL_ZOOM" image="circle" alpha="128">
<Size w="45" h="45"/>
<Anchor anchorFrom="TOP" anchorTo="BOTTOM" anchor="pause" y="12"/>
<Elements>
- <Image name="zoom_in" image="zoom-in">
+ <Image name="zoom_in" image="zoom-in" alpha="128">
<Size w="36" h="36"/>
<Anchor anchorFrom="CENTER" anchorTo="CENTER"/>
</Image>
- <Image name="zoom_out" image="zoom-out">
+ <Image name="zoom_out" image="zoom-out" alpha="128">
<Size w="36" h="36"/>
<Anchor anchorFrom="CENTER" anchorTo="CENTER"/>
</Image>
</Elements>
</Button>
- <Thumbstick image="split-circle">
+ <Thumbstick image="split-circle" alpha="128">
<Size w="128" h="128"/>
<Anchor anchorFrom="BOTTOMLEFT" anchorTo="BOTTOMLEFT" x="30" y="-30"/>
<Action angle="90" arc="180" active_radius="0" action_enter="CONTROL_DOWN_RIGHT" action_leave="CONTROL_UP_RIGHT"/>
<Action angle="270" arc="180" active_radius="0" action_enter="CONTROL_DOWN_LEFT" action_leave="CONTROL_UP_LEFT"/>
<Elements>
- <Image image="rotate-left">
+ <Image image="rotate-left" alpha="128">
<Size w="45" h="45"/>
<Anchor anchorFrom="LEFT" anchorTo="LEFT" x="9"/>
</Image>
- <Image image="rotate-right">
+ <Image image="rotate-right" alpha="128">
<Size w="45" h="45"/>
<Anchor anchorFrom="RIGHT" anchorTo="RIGHT" x="-9"/>
</Image>
</Elements>
</Image>
- <Thumbstick name="fire" image="circle">
+ <Thumbstick name="fire" image="circle" alpha="128">
<Size w="60" h="60"/>
<Anchor anchorFrom="BOTTOMRIGHT" anchorTo="BOTTOMRIGHT" x="-90" y="-45"/>
<Action action_enter="CONTROL_DOWN_FIRE" action_leave="CONTROL_UP_FIRE"/>
<Elements>
- <Icon id="136">
+ <Icon id="136" alpha="128">
<Size w="24" h="24"/>
<Anchor anchorFrom="CENTER" anchorTo="CENTER"/>
</Icon>
</Elements>
</Thumbstick>
- <Thumbstick name="shield" image="circle">
+ <Thumbstick name="shield" image="circle" alpha="128">
<Size w="60" h="60"/>
<Anchor anchorFrom="BOTTOMRIGHT" anchorTo="BOTTOMRIGHT" x="-45" y="-90"/>
<Action action_enter="CONTROL_DOWN_SHIELD" action_leave="CONTROL_UP_SHIELD"/>
<Elements>
- <Image image="shield">
+ <Image image="shield" alpha="128">
<Size w="24" h="24"/>
<Anchor anchorFrom="CENTER" anchorTo="CENTER"/>
- </Icon>
+ </Image>
</Elements>
</Thumbstick>
- <Thumbstick name="thrust" image="circle">
+ <Thumbstick name="thrust" image="circle" alpha="128">
<Size w="60" h="60"/>
<Anchor anchorFrom="BOTTOMRIGHT" anchorTo="BOTTOMRIGHT" x="-135" y="-90"/>
<Action action_enter="CONTROL_DOWN_THRUST" action_leave="CONTROL_UP_THRUST"/>
<Elements>
- <Image image="thrust">
+ <Image image="thrust" alpha="128">
<Size w="24" h="24"/>
<Anchor anchorFrom="CENTER" anchorTo="CENTER"/>
- </Icon>
+ </Image>
</Elements>
</Thumbstick>
</Elements>
diff --git a/screenlib/SDL_FrameBuf.h b/screenlib/SDL_FrameBuf.h
index b33a0f0f..fa114604 100644
--- a/screenlib/SDL_FrameBuf.h
+++ b/screenlib/SDL_FrameBuf.h
@@ -138,22 +138,22 @@ class FrameBuf : public ErrorBase {
/* Drawing routines */
void Clear(int x, int y, int w, int h) {
- FillRect(x, y, w, h, 0);
+ FillRect(x, y, w, h, 0, SDL_ALPHA_OPAQUE);
}
void Clear(Uint32 color = 0) {
- UpdateDrawColor(color);
+ UpdateDrawColor(color, SDL_ALPHA_OPAQUE);
SDL_RenderClear(m_renderer);
}
- void DrawPoint(int x, int y, Uint32 color) {
- UpdateDrawColor(color);
+ void DrawPoint(int x, int y, Uint32 color, Uint8 alpha = SDL_ALPHA_OPAQUE) {
+ UpdateDrawColor(color, alpha);
SDL_RenderPoint(m_renderer, (float)x, (float)y);
}
- void DrawLine(int x1, int y1, int x2, int y2, Uint32 color) {
- UpdateDrawColor(color);
+ void DrawLine(int x1, int y1, int x2, int y2, Uint32 color, Uint8 alpha = SDL_ALPHA_OPAQUE) {
+ UpdateDrawColor(color, alpha);
SDL_RenderLine(m_renderer, (float)x1, (float)y1, (float)x2, (float)y2);
}
- void DrawRect(int x1, int y1, int w, int h, Uint32 color) {
- UpdateDrawColor(color);
+ void DrawRect(int x1, int y1, int w, int h, Uint32 color, Uint8 alpha = SDL_ALPHA_OPAQUE) {
+ UpdateDrawColor(color, alpha);
SDL_FRect rect;
rect.x = (float)x1;
@@ -162,8 +162,8 @@ class FrameBuf : public ErrorBase {
rect.h = (float)h;
SDL_RenderRect(m_renderer, &rect);
}
- void FillRect(int x1, int y1, int w, int h, Uint32 color) {
- UpdateDrawColor(color);
+ void FillRect(int x1, int y1, int w, int h, Uint32 color, Uint8 alpha = SDL_ALPHA_OPAQUE) {
+ UpdateDrawColor(color, alpha);
SDL_FRect rect;
rect.x = (float)x1;
@@ -216,12 +216,12 @@ class FrameBuf : public ErrorBase {
bool m_gamepadMouseDown = false;
array<SDL_Gamepad *> m_gamepads;
- void UpdateDrawColor(Uint32 color) {
+ void UpdateDrawColor(Uint32 color, Uint8 alpha) {
Uint8 r, g, b;
r = (color >> 16) & 0xFF;
g = (color >> 8) & 0xFF;
b = (color >> 0) & 0xFF;
- SDL_SetRenderDrawColor(m_renderer, r, g, b, SDL_ALPHA_OPAQUE);
+ SDL_SetRenderDrawColor(m_renderer, r, g, b, alpha);
}
void OpenGamepad(SDL_JoystickID id);
diff --git a/screenlib/UIDrawEngine.cpp b/screenlib/UIDrawEngine.cpp
index 074a703c..b8395df8 100644
--- a/screenlib/UIDrawEngine.cpp
+++ b/screenlib/UIDrawEngine.cpp
@@ -118,24 +118,24 @@ UIDrawEngine::OnDraw()
if (m_element->HasFill()) {
m_screen->FillRect(m_element->X(), m_element->Y(),
m_element->Width(), m_element->Height(),
- m_element->GetFillColor());
+ m_element->GetFillColor(), m_element->GetAlpha());
}
UITexture *background = m_element->GetBackground();
if (background) {
- background->Draw(m_screen, m_element->X(), m_element->Y(), m_element->Width(), m_element->Height());
+ background->Draw(m_screen, m_element->X(), m_element->Y(), m_element->Width(), m_element->Height(), m_element->GetAlpha());
}
if (m_element->HasBorder()) {
m_screen->DrawRect(m_element->X(), m_element->Y(),
m_element->Width(), m_element->Height(),
- m_element->GetCurrentColor());
+ m_element->GetCurrentColor(), m_element->GetAlpha());
}
UITexture *image = m_element->GetImage();
if (image) {
UIArea *area = m_element->GetImageArea();
- image->Draw(m_screen, area->X(), area->Y(), area->Width(), area->Height());
+ image->Draw(m_screen, area->X(), area->Y(), area->Width(), area->Height(), m_element->GetAlpha());
}
if (m_textImage) {
@@ -143,6 +143,8 @@ UIDrawEngine::OnDraw()
int x, y, shadowX, shadowY;
m_element->GetTextOffset(&x, &y);
+ SDL_SetTextureAlphaMod(m_textImage->Texture(), m_element->GetAlpha());
+
if (m_element->GetTextShadowOffset(&shadowX, &shadowY)) {
Uint8 r, g, b;
diff --git a/screenlib/UIElement.cpp b/screenlib/UIElement.cpp
index beb2df27..393e309a 100644
--- a/screenlib/UIElement.cpp
+++ b/screenlib/UIElement.cpp
@@ -37,6 +37,7 @@ UIElement::UIElement(UIBaseElement *parent, const char *name, UIDrawEngine *draw
m_fillColor = m_screen->MapRGB(0x00, 0x00, 0x00);
m_color = m_screen->MapRGB(0xFF, 0xFF, 0xFF);
m_disabledColor = m_screen->MapRGB(0x80, 0x80, 0x80);
+ m_alpha = SDL_ALPHA_OPAQUE;
m_fontName = NULL;
m_fontSize = 0;
m_fontStyle = UIFONT_STYLE_NORMAL;
@@ -134,6 +135,11 @@ UIElement::Load(rapidxml::xml_node<> *node, const UITemplates *templates)
SetDisabledColor(color);
}
+ int alpha;
+ if (LoadNumber(node, "alpha", alpha)) {
+ SetAlpha((Uint8)alpha);
+ }
+
attr = node->first_attribute("font", 0, false);
if (attr) {
if (!ParseFont(attr->value())) {
@@ -405,6 +411,12 @@ UIElement::SetDisabledColor(Uint32 color)
}
}
+void
+UIElement::SetAlpha(Uint8 alpha)
+{
+ m_alpha = alpha;
+}
+
void
UIElement::UpdateDisabledState()
{
diff --git a/screenlib/UIElement.h b/screenlib/UIElement.h
index cbb52da8..1efb9710 100644
--- a/screenlib/UIElement.h
+++ b/screenlib/UIElement.h
@@ -177,6 +177,8 @@ DECLARE_TYPESAFE_CLASS(UIBaseElement)
Uint32 GetCurrentColor() const {
return IsDisabled() ? GetDisabledColor() : GetColor();
}
+ void SetAlpha(Uint8 alpha);
+ Uint8 GetAlpha() const { return m_alpha; }
// Text information
void SetFont(const char *fontName, int fontSize, UIFontStyle fontStyle);
@@ -272,6 +274,7 @@ DECLARE_TYPESAFE_CLASS(UIBaseElement)
Uint32 m_fillColor;
Uint32 m_color;
Uint32 m_disabledColor;
+ Uint8 m_alpha;
char *m_fontName;
int m_fontSize;
UIFontStyle m_fontStyle;
diff --git a/screenlib/UITexture.cpp b/screenlib/UITexture.cpp
index bc5ce5b7..d7352d44 100644
--- a/screenlib/UITexture.cpp
+++ b/screenlib/UITexture.cpp
@@ -103,8 +103,10 @@ UITexture::SetStretchGrid(int cornerSize)
}
void
-UITexture::Draw(FrameBuf *screen, int x, int y, int w, int h)
+UITexture::Draw(FrameBuf *screen, int x, int y, int w, int h, Uint8 alpha)
{
+ SDL_SetTextureAlphaMod(m_texture, alpha);
+
if (m_stretch) {
SDL_Rect dstAreas[NUM_STRETCH_AREAS];
diff --git a/screenlib/UITexture.h b/screenlib/UITexture.h
index 59901161..916b07f6 100644
--- a/screenlib/UITexture.h
+++ b/screenlib/UITexture.h
@@ -60,7 +60,7 @@ class UITexture
void SetStretchGrid(int cornerSize);
bool IsStretching() const { return m_stretch; }
- void Draw(FrameBuf *screen, int x, int y, int w, int h);
+ void Draw(FrameBuf *screen, int x, int y, int w, int h, Uint8 alpha);
// When a texture is locked it shouldn't be freed
void SetLocked(bool locked) {