https://github.com/libsdl-org/Maelstrom/commit/2326838e34b5e09be00a9ca4fcf0f4c92fe4114a
From 2326838e34b5e09be00a9ca4fcf0f4c92fe4114a Mon Sep 17 00:00:00 2001
From: Sam Lantinga <[EMAIL REDACTED]>
Date: Sun, 21 Oct 2012 13:46:37 -0700
Subject: [PATCH] Added separate drawing layers so popups can draw over the
rest of the UI.
---
game/MacDialog.cpp | 76 +++++++++++++++++++------------------
game/MacDialog.h | 2 +-
game/about.cpp | 6 ++-
game/about.h | 2 +-
game/game.cpp | 6 ++-
game/game.h | 2 +-
screenlib/UIBaseElement.cpp | 47 ++++++++++++++++++++++-
screenlib/UIBaseElement.h | 15 +++++++-
screenlib/UIElement.cpp | 6 +--
screenlib/UIElement.h | 2 +-
screenlib/UIManager.cpp | 4 +-
screenlib/UIPanel.cpp | 10 ++---
screenlib/UIPanel.h | 7 +---
13 files changed, 124 insertions(+), 61 deletions(-)
diff --git a/game/MacDialog.cpp b/game/MacDialog.cpp
index ca9a5242..0f88b7d8 100644
--- a/game/MacDialog.cpp
+++ b/game/MacDialog.cpp
@@ -84,51 +84,55 @@ MacDialog::Show()
}
void
-MacDialog::Draw()
+MacDialog::Draw(DRAWLEVEL drawLevel)
{
- int x, y, w, h;
- int maxx, maxy;
+ if (drawLevel == DRAWLEVEL_BACKGROUND) {
+ int x, y, w, h;
+ int maxx, maxy;
+
+ if (m_step < EXPAND_STEPS) {
+ w = (Width()*m_step)/EXPAND_STEPS;
+ h = (Height()*m_step)/EXPAND_STEPS;
+ x = X() + Width()/2 - (w/2);
+ y = Y() + Height()/2 - (h/2);
+ } else {
+ w = Width();
+ h = Height();
+ x = X();
+ y = Y();
+ }
- if (m_step < EXPAND_STEPS) {
- w = (Width()*m_step)/EXPAND_STEPS;
- h = (Height()*m_step)/EXPAND_STEPS;
- x = X() + Width()/2 - (w/2);
- y = Y() + Height()/2 - (h/2);
- } else {
- w = Width();
- h = Height();
- x = X();
- y = Y();
+ /* The border is 4 pixels around the area of the dialog */
+ w += 8;
+ h += 8;
+ x -= 4;
+ y -= 4;
+ maxx = x+w-1;
+ maxy = y+h-1;
+
+ /* Draw the dialog border and background color */
+ m_screen->DrawLine(x, y, maxx, y, m_colors[COLOR_LIGHT]);
+ m_screen->DrawLine(x, y, x, maxy, m_colors[COLOR_LIGHT]);
+ m_screen->DrawLine(x, maxy, maxx, maxy, m_colors[COLOR_DARK]);
+ m_screen->DrawLine(maxx, y, maxx, maxy, m_colors[COLOR_DARK]);
+ m_screen->DrawRect(x+1, y+1, w-2, h-2, m_colors[COLOR_MEDIUM]);
+ m_screen->DrawLine(x+2, y+2, maxx-2, y+2, m_colors[COLOR_DARK]);
+ m_screen->DrawLine(x+2, y+2, x+2, maxy-2, m_colors[COLOR_DARK]);
+ m_screen->DrawLine(x+3, maxy-2, maxx-2, maxy-2, m_colors[COLOR_LIGHT]);
+ m_screen->DrawLine(maxx-2, y+3, maxx-2, maxy-2, m_colors[COLOR_LIGHT]);
+ m_screen->DrawRect(x+3, y+3, w-6, h-6, m_colors[COLOR_BLACK]);
+ m_screen->FillRect(x+4, y+4, w-8, h-8, m_colors[COLOR_WHITE]);
}
- /* The border is 4 pixels around the area of the dialog */
- w += 8;
- h += 8;
- x -= 4;
- y -= 4;
- maxx = x+w-1;
- maxy = y+h-1;
-
- /* Draw the dialog border and background color */
- m_screen->DrawLine(x, y, maxx, y, m_colors[COLOR_LIGHT]);
- m_screen->DrawLine(x, y, x, maxy, m_colors[COLOR_LIGHT]);
- m_screen->DrawLine(x, maxy, maxx, maxy, m_colors[COLOR_DARK]);
- m_screen->DrawLine(maxx, y, maxx, maxy, m_colors[COLOR_DARK]);
- m_screen->DrawRect(x+1, y+1, w-2, h-2, m_colors[COLOR_MEDIUM]);
- m_screen->DrawLine(x+2, y+2, maxx-2, y+2, m_colors[COLOR_DARK]);
- m_screen->DrawLine(x+2, y+2, x+2, maxy-2, m_colors[COLOR_DARK]);
- m_screen->DrawLine(x+3, maxy-2, maxx-2, maxy-2, m_colors[COLOR_LIGHT]);
- m_screen->DrawLine(maxx-2, y+3, maxx-2, maxy-2, m_colors[COLOR_LIGHT]);
- m_screen->DrawRect(x+3, y+3, w-6, h-6, m_colors[COLOR_BLACK]);
- m_screen->FillRect(x+4, y+4, w-8, h-8, m_colors[COLOR_WHITE]);
-
/* Don't draw the controls until we've finished expanding */
if (m_step < EXPAND_STEPS) {
- ++m_step;
+ if (drawLevel == NUM_DRAWLEVELS-1) {
+ ++m_step;
+ }
return;
}
- UIDialog::Draw();
+ UIDialog::Draw(drawLevel);
}
//////////////////////////////////////////////////////////////////////////////
diff --git a/game/MacDialog.h b/game/MacDialog.h
index 03dc4617..b2492b86 100644
--- a/game/MacDialog.h
+++ b/game/MacDialog.h
@@ -35,7 +35,7 @@ DECLARE_TYPESAFE_CLASS(UIDialog)
override bool Load(rapidxml::xml_node<> *node, const UITemplates *templates);
override void Show();
- override void Draw();
+ override void Draw(DRAWLEVEL drawLevel);
protected:
enum {
diff --git a/game/about.cpp b/game/about.cpp
index ff949a42..b8ea844c 100644
--- a/game/about.cpp
+++ b/game/about.cpp
@@ -92,10 +92,14 @@ AboutPanelDelegate::OnHide()
}
void
-AboutPanelDelegate::OnDraw()
+AboutPanelDelegate::OnDraw(DRAWLEVEL drawLevel)
{
int i;
+ if ( drawLevel != DRAWLEVEL_NORMAL ) {
+ return;
+ }
+
for ( i=0; i<numsprites; ++i ) {
objects[i]->Move(0);
objects[i]->BlitSprite();
diff --git a/game/about.h b/game/about.h
index 8d610a9a..9e8c8194 100644
--- a/game/about.h
+++ b/game/about.h
@@ -39,7 +39,7 @@ class AboutPanelDelegate : public UIPanelDelegate
virtual void OnShow();
virtual void OnHide();
- virtual void OnDraw();
+ virtual void OnDraw(DRAWLEVEL drawLevel);
protected:
int numsprites;
diff --git a/game/game.cpp b/game/game.cpp
index f3f0e28e..d56cab8b 100644
--- a/game/game.cpp
+++ b/game/game.cpp
@@ -404,10 +404,14 @@ GamePanelDelegate::OnTick()
}
void
-GamePanelDelegate::OnDrawBackground()
+GamePanelDelegate::OnDraw(DRAWLEVEL drawLevel)
{
int i;
+ if (drawLevel != DRAWLEVEL_BACKGROUND) {
+ return;
+ }
+
/* Draw the status frame */
DrawStatus(false);
diff --git a/game/game.h b/game/game.h
index a3d17984..d5d7ba45 100644
--- a/game/game.h
+++ b/game/game.h
@@ -37,7 +37,7 @@ class GamePanelDelegate : public UIPanelDelegate
virtual void OnShow();
virtual void OnHide();
virtual void OnTick();
- virtual void OnDrawBackground();
+ virtual void OnDraw(DRAWLEVEL drawLevel);
virtual bool OnAction(UIBaseElement *sender, const char *action);
protected:
diff --git a/screenlib/UIBaseElement.cpp b/screenlib/UIBaseElement.cpp
index f6cc2eea..8c7abfb7 100644
--- a/screenlib/UIBaseElement.cpp
+++ b/screenlib/UIBaseElement.cpp
@@ -42,6 +42,7 @@ UIBaseElement::UIBaseElement(UIManager *ui, const char *name) :
m_shown = true;
m_disabled = false;
m_parentDisabled = false;
+ m_drawLevel = DRAWLEVEL_NORMAL;
}
UIBaseElement::UIBaseElement(UIBaseElement *parent, const char *name) :
@@ -54,6 +55,7 @@ UIBaseElement::UIBaseElement(UIBaseElement *parent, const char *name) :
m_shown = true;
m_disabled = false;
m_parentDisabled = parent->IsDisabled();
+ m_drawLevel = DRAWLEVEL_NORMAL;
}
UIBaseElement::~UIBaseElement()
@@ -95,6 +97,11 @@ UIBaseElement::Load(rapidxml::xml_node<> *node, const UITemplates *templates)
}
}
+ DRAWLEVEL drawLevel;
+ if (LoadDrawLevel(node, "drawLevel", drawLevel)) {
+ SetDrawLevel(drawLevel);
+ }
+
return true;
}
@@ -173,11 +180,21 @@ UIBaseElement::UpdateDisabledState()
}
void
-UIBaseElement::Draw()
+UIBaseElement::SetDrawLevel(DRAWLEVEL drawLevel)
+{
+ m_drawLevel = drawLevel;
+
+ for (int i = 0; i < m_elements.length(); ++i) {
+ m_elements[i]->SetDrawLevel(drawLevel);
+ }
+}
+
+void
+UIBaseElement::Draw(DRAWLEVEL drawLevel)
{
for (int i = 0; i < m_elements.length(); ++i) {
if (m_elements[i]->IsShown()) {
- m_elements[i]->Draw();
+ m_elements[i]->Draw(drawLevel);
}
}
}
@@ -242,3 +259,29 @@ UIBaseElement::LoadElements(rapidxml::xml_node<> *node, const UITemplates *templ
}
return true;
}
+
+bool
+UIBaseElement::LoadDrawLevel(rapidxml::xml_node<> *node, const char *name, DRAWLEVEL &value)
+{
+ rapidxml::xml_attribute<> *attr;
+
+ attr = node->first_attribute(name, 0, false);
+ if (attr) {
+ static const char *s_drawLevels[] = {
+ "background",
+ "normal",
+ "popup"
+ };
+ SDL_COMPILE_TIME_ASSERT(drawLevels, SDL_arraysize(s_drawLevels) == NUM_DRAWLEVELS);
+
+ for (int i = 0; i < NUM_DRAWLEVELS; ++i) {
+ if (SDL_strcasecmp(attr->value(), s_drawLevels[i]) == 0) {
+ value = (DRAWLEVEL)i;
+ return true;
+ }
+ }
+ fprintf(stderr, "Warning: Unknown draw level: %s\n", attr->value());
+ return false;
+ }
+ return false;
+}
diff --git a/screenlib/UIBaseElement.h b/screenlib/UIBaseElement.h
index a0c85e5d..685f09b4 100644
--- a/screenlib/UIBaseElement.h
+++ b/screenlib/UIBaseElement.h
@@ -35,6 +35,14 @@ class UITemplates;
typedef int UIElementType;
+enum DRAWLEVEL
+{
+ DRAWLEVEL_BACKGROUND,
+ DRAWLEVEL_NORMAL,
+ DRAWLEVEL_POPUP,
+ NUM_DRAWLEVELS
+};
+
class UIBaseElement : public UIArea
{
public:
@@ -194,7 +202,10 @@ class UIBaseElement : public UIArea
return m_disabled || m_parentDisabled;
}
- virtual void Draw();
+ void SetDrawLevel(DRAWLEVEL drawLevel);
+ DRAWLEVEL GetDrawLevel() const { return m_drawLevel; }
+
+ virtual void Draw(DRAWLEVEL drawLevel);
virtual bool HandleEvent(const SDL_Event &event);
virtual void Action(UIBaseElement *sender, const char *action);
@@ -210,12 +221,14 @@ class UIBaseElement : public UIArea
bool m_shown;
bool m_disabled;
bool m_parentDisabled;
+ DRAWLEVEL m_drawLevel;
array<UIBaseElement *> m_elements;
protected:
UIBaseElement *CreateElement(const char *type);
bool LoadElements(rapidxml::xml_node<> *node, const UITemplates *templates);
+ bool LoadDrawLevel(rapidxml::xml_node<> *node, const char *name, DRAWLEVEL &value);
virtual void UpdateDisabledState();
diff --git a/screenlib/UIElement.cpp b/screenlib/UIElement.cpp
index 6c64c131..b4b73109 100644
--- a/screenlib/UIElement.cpp
+++ b/screenlib/UIElement.cpp
@@ -504,13 +504,13 @@ UIElement::SetImage(UITexture *image)
}
void
-UIElement::Draw()
+UIElement::Draw(DRAWLEVEL drawLevel)
{
- if (m_drawEngine) {
+ if (m_drawEngine && drawLevel == GetDrawLevel()) {
m_drawEngine->OnDraw();
}
- UIBaseElement::Draw();
+ UIBaseElement::Draw(drawLevel);
}
bool
diff --git a/screenlib/UIElement.h b/screenlib/UIElement.h
index ae60c774..7e3f39cc 100644
--- a/screenlib/UIElement.h
+++ b/screenlib/UIElement.h
@@ -168,7 +168,7 @@ DECLARE_TYPESAFE_CLASS(UIBaseElement)
}
// Draw!
- override void Draw();
+ override void Draw(DRAWLEVEL drawLevel);
// Events
override bool HandleEvent(const SDL_Event &event);
diff --git a/screenlib/UIManager.cpp b/screenlib/UIManager.cpp
index e14bf46f..48f32007 100644
--- a/screenlib/UIManager.cpp
+++ b/screenlib/UIManager.cpp
@@ -320,7 +320,9 @@ UIManager::Draw(bool fullUpdate)
for (i = 0; i < m_visible.length(); ++i) {
UIPanel *panel = m_visible[i];
- panel->Draw();
+ for (int drawLevel = 0; drawLevel < NUM_DRAWLEVELS; ++drawLevel) {
+ panel->Draw((DRAWLEVEL)drawLevel);
+ }
}
if (fullUpdate) {
m_screen->Update();
diff --git a/screenlib/UIPanel.cpp b/screenlib/UIPanel.cpp
index 5919d0ef..d59f6dbd 100644
--- a/screenlib/UIPanel.cpp
+++ b/screenlib/UIPanel.cpp
@@ -152,16 +152,12 @@ UIPanel::Tick()
}
void
-UIPanel::Draw()
+UIPanel::Draw(DRAWLEVEL drawLevel)
{
- if (m_delegate) {
- m_delegate->OnDrawBackground();
- }
-
- UIBaseElement::Draw();
+ UIBaseElement::Draw(drawLevel);
if (m_delegate) {
- m_delegate->OnDraw();
+ m_delegate->OnDraw(drawLevel);
}
}
diff --git a/screenlib/UIPanel.h b/screenlib/UIPanel.h
index ed294c14..5c364376 100644
--- a/screenlib/UIPanel.h
+++ b/screenlib/UIPanel.h
@@ -55,12 +55,9 @@ class UIPanelDelegate
// This is called once per frame before the screen is drawn
virtual void OnTick() { }
- // This is called before the panel is drawn
- virtual void OnDrawBackground() { }
-
// This is called after the panel is drawn, before the screen
// is updated, to allow any additional custom drawing.
- virtual void OnDraw() { }
+ virtual void OnDraw(DRAWLEVEL drawLevel) { }
// This is called for events not handled by UI elements
virtual bool HandleEvent(const SDL_Event &event) { return false; }
@@ -99,7 +96,7 @@ DECLARE_TYPESAFE_CLASS(UIBaseElement)
virtual void Poll();
virtual void Tick();
- override void Draw();
+ override void Draw(DRAWLEVEL drawLevel);
override bool HandleEvent(const SDL_Event &event);
override void Action(UIBaseElement *sender, const char *action);