aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorVicent Marti2008-07-17 21:58:43 +0000
committerVicent Marti2008-07-17 21:58:43 +0000
commit4645e706a8c62fb291efb987dca9fa82394139ee (patch)
tree8155832408c5b2297f3459a617c9460c27eac248
parent6214815e6eff5b91887e5e1dd4d6463c2000f024 (diff)
downloadscummvm-rg350-4645e706a8c62fb291efb987dca9fa82394139ee.tar.gz
scummvm-rg350-4645e706a8c62fb291efb987dca9fa82394139ee.tar.bz2
scummvm-rg350-4645e706a8c62fb291efb987dca9fa82394139ee.zip
Rendering pipeline (almost) fixed. This time for real.
svn-id: r33092
-rw-r--r--graphics/VectorRenderer.cpp9
-rw-r--r--gui/ThemeRenderer.cpp81
-rw-r--r--gui/ThemeRenderer.h29
-rw-r--r--gui/dialog.cpp6
-rw-r--r--gui/newgui.cpp69
-rw-r--r--gui/newgui.h11
-rw-r--r--gui/theme.h14
7 files changed, 159 insertions, 60 deletions
diff --git a/graphics/VectorRenderer.cpp b/graphics/VectorRenderer.cpp
index a8915eb0a6..f2ce0e26b8 100644
--- a/graphics/VectorRenderer.cpp
+++ b/graphics/VectorRenderer.cpp
@@ -487,11 +487,7 @@ drawTabAlg(int x1, int y1, int w, int h, int r, PixelType color, VectorRenderer:
int real_radius = r;
int short_h = h - r + 2;
int long_h = h;
- PixelType color1, color2;
-
- if (fill_m == kFillForeground || fill_m == kFillBackground)
- color1 = color2 = color;
-
+
if (fill_m == kFillDisabled) {
while (sw++ < Base::_strokeWidth) {
colorFill(ptr_fill + sp + r, ptr_fill + w + 1 + sp - r, color);
@@ -543,6 +539,9 @@ drawTabAlg(int x1, int y1, int w, int h, int r, PixelType color, VectorRenderer:
}
} else {
__BE_RESET();
+
+ PixelType color1, color2;
+ color1 = color2 = color;
while (x++ < y) {
__BE_ALGORITHM();
diff --git a/gui/ThemeRenderer.cpp b/gui/ThemeRenderer.cpp
index 7b64baba11..9b3d115576 100644
--- a/gui/ThemeRenderer.cpp
+++ b/gui/ThemeRenderer.cpp
@@ -76,7 +76,8 @@ const char *ThemeRenderer::kDrawDataStrings[] = {
ThemeRenderer::ThemeRenderer(Common::String themeName, GraphicsMode mode) :
_vectorRenderer(0), _system(0), _graphicsMode(kGfxDisabled),
- _screen(0), _backBuffer(0), _bytesPerPixel(0), _initOk(false), _themeOk(false), _enabled(false) {
+ _screen(0), _backBuffer(0), _bytesPerPixel(0), _initOk(false),
+ _themeOk(false), _enabled(false), _dialogCount(0), _cachedDialog(0) {
_system = g_system;
_parser = new ThemeParser(this);
@@ -238,8 +239,11 @@ bool ThemeRenderer::loadTheme(Common::String themeName) {
warning("Error when parsing custom theme '%s': Missing data assets.", themeName.c_str());
return false;
#endif
- } else if (_widgets[i]->_cached) {
- // draw the cached widget to the cache surface
+ } else {
+ calcBackgroundOffset((DrawData)i);
+
+ // TODO: draw the cached widget to the cache surface
+ if (_widgets[i]->_cached) {}
}
}
@@ -293,6 +297,14 @@ void ThemeRenderer::drawCached(DrawData type, const Common::Rect &r) {
void ThemeRenderer::drawDD(DrawData type, const Common::Rect &r, uint32 dynamicData) {
if (_widgets[type] == 0)
return;
+
+ Common::Rect extendedRect = r;
+ extendedRect.grow(kDirtyRectangleThreshold);
+ extendedRect.right += _widgets[type]->_backgroundOffset;
+ extendedRect.bottom += _widgets[type]->_backgroundOffset;
+
+ restoreBackground(extendedRect);
+ addDirtyRect(extendedRect);
if (isWidgetCached(type, r)) {
drawCached(type, r);
@@ -312,6 +324,33 @@ void ThemeRenderer::drawDDText(DrawData type, const Common::Rect &r, const Commo
}
}
+void ThemeRenderer::calcBackgroundOffset(DrawData type) {
+ uint maxShadow = 0;
+ for (Common::List<Graphics::DrawStep>::const_iterator step = _widgets[type]->_steps.begin();
+ step != _widgets[type]->_steps.end(); ++step) {
+ if (((*step).autoWidth || (*step).autoHeight) && (*step).shadow > maxShadow)
+ maxShadow = (*step).shadow;
+ }
+
+ _widgets[type]->_backgroundOffset = maxShadow;
+}
+
+void ThemeRenderer::restoreBackground(Common::Rect r, bool special) {
+/* const OverlayColor *src = (const OverlayColor*)_backBuffer->getBasePtr(r.left, r.top);
+ OverlayColor *dst = (OverlayColor*)_screen->getBasePtr(r.left, r.top);
+
+ int h = r.height();
+ int w = r.width();
+ while (h--) {
+ memcpy(dst, src, w * sizeof(OverlayColor));
+ src += _backBuffer->w;
+ dst += _screen->w;
+ }*/
+
+ debugWidgetPosition("", r);
+ printf(" BG_RESTORE ");
+}
+
void ThemeRenderer::drawButton(const Common::Rect &r, const Common::String &str, WidgetStateInfo state, uint16 hints) {
if (!ready())
return;
@@ -327,8 +366,6 @@ void ThemeRenderer::drawButton(const Common::Rect &r, const Common::String &str,
drawDD(dd, r);
drawDDText(dd, r, str);
-
- addDirtyRect(r);
}
void ThemeRenderer::drawLineSeparator(const Common::Rect &r, WidgetStateInfo state) {
@@ -336,7 +373,6 @@ void ThemeRenderer::drawLineSeparator(const Common::Rect &r, WidgetStateInfo sta
return;
drawDD(kDDSeparator, r);
- addDirtyRect(r);
}
void ThemeRenderer::drawCheckbox(const Common::Rect &r, const Common::String &str, bool checked, WidgetStateInfo state) {
@@ -355,8 +391,6 @@ void ThemeRenderer::drawCheckbox(const Common::Rect &r, const Common::String &st
r2.right = r.right;
drawDDText(checked ? kDDCheckboxEnabled : kDDCheckboxDisabled, r2, str);
-
- addDirtyRect(r);
}
void ThemeRenderer::drawSlider(const Common::Rect &r, int width, WidgetStateInfo state) {
@@ -369,8 +403,6 @@ void ThemeRenderer::drawSlider(const Common::Rect &r, int width, WidgetStateInfo
r2.setWidth(MIN((int16)width, r.width()));
drawDD(kDDSliderFull, r2);
-
- addDirtyRect(r);
}
void ThemeRenderer::drawScrollbar(const Common::Rect &r, int sliderY, int sliderHeight, ScrollbarState sb_state, WidgetStateInfo state) {
@@ -379,8 +411,6 @@ void ThemeRenderer::drawScrollbar(const Common::Rect &r, int sliderY, int slider
drawDD(kDDScrollbarBase, r);
// TODO: Need to find a scrollbar in the GUI for testing... :p
-
- addDirtyRect(r);
}
void ThemeRenderer::drawDialogBackground(const Common::Rect &r, uint16 hints, WidgetStateInfo state) {
@@ -396,8 +426,6 @@ void ThemeRenderer::drawDialogBackground(const Common::Rect &r, uint16 hints, Wi
} else {
drawDD(kDDDefaultBackground, r);
}
-
- addDirtyRect(r);
}
void ThemeRenderer::drawCaret(const Common::Rect &r, bool erase, WidgetStateInfo state) {
@@ -405,7 +433,6 @@ void ThemeRenderer::drawCaret(const Common::Rect &r, bool erase, WidgetStateInfo
return;
debugWidgetPosition("Caret", r);
- addDirtyRect(r);
}
void ThemeRenderer::drawPopUpWidget(const Common::Rect &r, const Common::String &sel, int deltax, WidgetStateInfo state, TextAlign align) {
@@ -420,8 +447,6 @@ void ThemeRenderer::drawPopUpWidget(const Common::Rect &r, const Common::String
Common::Rect text(r.left, r.top, r.right - 16, r.bottom);
drawDDText(dd, text, sel);
}
-
- addDirtyRect(r);
}
void ThemeRenderer::drawSurface(const Common::Rect &r, const Graphics::Surface &surface, WidgetStateInfo state, int alpha, bool themeTrans) {
@@ -452,8 +477,6 @@ void ThemeRenderer::drawWidgetBackground(const Common::Rect &r, uint16 hints, Wi
drawDD(kDDWidgetBackgroundDefault, r);
break;
}
-
- addDirtyRect(r);
}
void ThemeRenderer::drawTab(const Common::Rect &r, int tabHeight, int tabWidth, const Common::Array<Common::String> &tabs, int active, uint16 hints, int titleVPad, WidgetStateInfo state) {
@@ -514,4 +537,24 @@ void ThemeRenderer::renderDirtyScreen() {
_dirtyScreen.clear();
}
+void ThemeRenderer::openDialog(bool top) {
+ if (_dialogCount++ == 0)
+ return;
+
+ _cachedDialog = _dialogCount - 1;
+ memcpy(_backBuffer->pixels, _screen->pixels, _screen->w * _screen->h * _screen->bytesPerPixel);
+}
+
+bool ThemeRenderer::closeDialog() {
+ assert(_dialogCount);
+
+ _dialogCount--;
+
+ if (_dialogCount != _cachedDialog)
+ return false;
+
+ memcpy(_screen->pixels, _backBuffer->pixels, _screen->w * _screen->h * _screen->bytesPerPixel);
+ return true;
+}
+
} // end of namespace GUI.
diff --git a/gui/ThemeRenderer.h b/gui/ThemeRenderer.h
index a5fccd8163..11728f8e6e 100644
--- a/gui/ThemeRenderer.h
+++ b/gui/ThemeRenderer.h
@@ -42,13 +42,23 @@ namespace GUI {
struct WidgetDrawData;
struct WidgetDrawData {
+ /** List of all the steps needed to draw this widget */
Common::List<Graphics::DrawStep> _steps;
+
+ /** Single step that defines the text shown inside the widget */
Graphics::TextStep _textStep;
bool _hasText;
+ /** Extra space that the widget occupies when it's drawn.
+ E.g. when taking into account rounded corners, drop shadows, etc
+ Used when restoring the widget background */
+ uint16 _backgroundOffset;
+
+ /** Sets whether the widget is cached beforehand. */
bool _cached;
+
+ /** Texture where the cached widget is stored. */
Graphics::Surface *_surfaceCache;
- uint32 _cachedW, _cachedH;
~WidgetDrawData() {
_steps.clear();
@@ -145,14 +155,18 @@ public:
void refresh() {}
void enable();
void disable();
- void openDialog() {}
- void closeAllDialogs() {}
+
+ void closeAllDialogs() {
+ _dialogCount = 0;
+ _cachedDialog = 0;
+ }
void updateScreen(); //{}
void resetDrawArea() {}
- void openDialog(bool top) {}
+ void openDialog(bool top);// {}
+ bool closeDialog();// {}
/** Font management */
const Graphics::Font *getFont(FontStyle font) const { return _font; }
@@ -177,7 +191,7 @@ public:
void drawChar(const Common::Rect &r, byte ch, const Graphics::Font *font, WidgetStateInfo state) {}
bool addDirtyRect(Common::Rect r, bool backup = false, bool special = false) {
- r.grow(kDirtyRectangleThreshold);
+// r.grow(kDirtyRectangleThreshold);
_dirtyScreen.push_back(r);
return true;
}
@@ -260,13 +274,14 @@ protected:
bool isWidgetCached(DrawData type, const Common::Rect &r);
void drawCached(DrawData type, const Common::Rect &r);
+ void calcBackgroundOffset(DrawData type);
inline void drawDD(DrawData type, const Common::Rect &r, uint32 dynamicData = 0);
inline void drawDDText(DrawData type, const Common::Rect &r, const Common::String &text);
inline void debugWidgetPosition(const char *name, const Common::Rect &r);
// TODO
- void restoreBackground(Common::Rect r, bool special = false) {}
+ void restoreBackground(Common::Rect r, bool special = false);
int getTabSpacing() const {
return 0;
@@ -295,6 +310,8 @@ protected:
Graphics::Surface *_screen;
Graphics::Surface *_backBuffer;
+ uint32 _dialogCount;
+ uint32 _cachedDialog;
int _bytesPerPixel;
GraphicsMode _graphicsMode;
diff --git a/gui/dialog.cpp b/gui/dialog.cpp
index ef396301be..0594941d65 100644
--- a/gui/dialog.cpp
+++ b/gui/dialog.cpp
@@ -132,7 +132,11 @@ void Dialog::releaseFocus() {
}
void Dialog::draw() {
- g_gui._needRedraw = true;
+ //TANOKU - FIXME when is this enabled? what does this do?
+ // Update: called on tab drawing, mainly...
+ // we can pass this as open a new dialog or something
+// g_gui._needRedraw = true;
+ g_gui._redrawStatus = GUI::NewGui::kRedrawTopDialog;
}
void Dialog::drawDialog() {
diff --git a/gui/newgui.cpp b/gui/newgui.cpp
index 4d0b3905b9..f3734c6ee0 100644
--- a/gui/newgui.cpp
+++ b/gui/newgui.cpp
@@ -81,7 +81,7 @@ void GuiObject::reflowLayout() {
}
// Constructor
-NewGui::NewGui() : _needRedraw(false),
+NewGui::NewGui() : _redrawStatus(kRedrawDisabled),
_stateIsSaved(false), _cursorAnimateCounter(0), _cursorAnimateTimer(0) {
_theme = 0;
_useStdCursor = false;
@@ -187,29 +187,48 @@ bool NewGui::loadNewTheme(const Common::String &style) {
void NewGui::redraw() {
int i;
- // Restore the overlay to its initial state, then draw all dialogs.
- // This is necessary to get the blending right.
- _theme->clearAll();
+ if (_redrawStatus == kRedrawDisabled)
+ return;
- _theme->closeAllDialogs();
- //for (i = 0; i < _dialogStack.size(); ++i)
- // _theme->closeDialog();
+ switch (_redrawStatus) {
+ case kRedrawCloseDialog:
+ printf("Dialog closed!\n");
+ if (_theme->closeDialog())
+ break;
- for (i = 0; i < _dialogStack.size(); i++) {
- // Special treatment when topmost dialog has dimsInactive() set to false
- // This is the case for PopUpWidget which should not dim a dialog
- // which it belongs to
- if ((i == _dialogStack.size() - 2) && !_dialogStack[i + 1]->dimsInactive())
- _theme->openDialog(true);
- else if ((i != (_dialogStack.size() - 1)) || !_dialogStack[i]->dimsInactive())
- _theme->openDialog(false);
- else
+ case kRedrawFull:
+ _theme->clearAll();
+ _theme->closeAllDialogs();
+
+ for (i = 0; i < _dialogStack.size(); i++) {
+ if ((i == _dialogStack.size() - 2) && !_dialogStack[i + 1]->dimsInactive())
+ _theme->openDialog(true);
+ else if ((i != (_dialogStack.size() - 1)) || !_dialogStack[i]->dimsInactive())
+ _theme->openDialog(false);
+ else
+ _theme->openDialog(true);
+
+ _dialogStack[i]->drawDialog();
+ }
+ break;
+
+ case kRedrawTopDialog:
+ _dialogStack.top()->drawDialog();
+ printf("Top dialog redraw!\n");
+ break;
+
+ case kRedrawOpenDialog:
_theme->openDialog(true);
+ _dialogStack.top()->drawDialog();
+ printf("Dialog opened!\n");
+ break;
- _dialogStack[i]->drawDialog();
+ default:
+ return;
}
_theme->updateScreen();
+ _redrawStatus = kRedrawDisabled;
}
Dialog *NewGui::getTopDialog() const {
@@ -240,10 +259,7 @@ void NewGui::runLoop() {
Common::EventManager *eventMan = _system->getEventManager();
while (!_dialogStack.empty() && activeDialog == getTopDialog()) {
- if (_needRedraw) {
- redraw();
- _needRedraw = false;
- }
+ redraw();
// Don't "tickle" the dialog until the theme has had a chance
// to re-allocate buffers in case of a scaler change.
@@ -274,6 +290,7 @@ void NewGui::runLoop() {
_theme->refresh();
_themeChange = false;
+ _redrawStatus = kRedrawFull;
redraw();
}
@@ -330,11 +347,6 @@ void NewGui::runLoop() {
_system->delayMillis(10);
}
- // HACK: since we reopen all dialogs anyway on redraw
- // we for now use Theme::closeAllDialogs here, until
- // we properly add (and implement) Theme::closeDialog
- _theme->closeAllDialogs();
-
if (didSaveState) {
_theme->disable();
restoreState();
@@ -366,7 +378,7 @@ void NewGui::restoreState() {
void NewGui::openDialog(Dialog *dialog) {
_dialogStack.push(dialog);
- _needRedraw = true;
+ _redrawStatus = kRedrawOpenDialog;
// We reflow the dialog just before opening it. If the screen changed
// since the last time we looked, also refresh the loaded theme,
@@ -393,7 +405,7 @@ void NewGui::closeTopDialog() {
// Remove the dialog from the stack
_dialogStack.pop();
- _needRedraw = true;
+ _redrawStatus = kRedrawCloseDialog;
}
void NewGui::setupCursor() {
@@ -451,6 +463,7 @@ void NewGui::screenChange() {
// We need to redraw immediately. Otherwise
// some other event may cause a widget to be
// redrawn before redraw() has been called.
+ _redrawStatus = kRedrawFull;
redraw();
}
diff --git a/gui/newgui.h b/gui/newgui.h
index 4cf082c877..ae58b2efe8 100644
--- a/gui/newgui.h
+++ b/gui/newgui.h
@@ -90,12 +90,21 @@ public:
void screenChange();
+ enum RedrawStatus {
+ kRedrawDisabled = 0,
+ kRedrawOpenDialog,
+ kRedrawCloseDialog,
+ kRedrawTopDialog,
+ kRedrawFull
+ };
+
protected:
OSystem *_system;
Theme *_theme;
- bool _needRedraw;
+// bool _needRedraw;
+ RedrawStatus _redrawStatus;
int _lastScreenChangeID;
DialogStack _dialogStack;
diff --git a/gui/theme.h b/gui/theme.h
index e9ce8bb01d..91f59d961c 100644
--- a/gui/theme.h
+++ b/gui/theme.h
@@ -239,6 +239,20 @@ public:
virtual void closeAllDialogs() = 0;
/**
+ * Closes the topmost dialog, and redraws the screen
+ * accordingly.
+ *
+ * TODO: Make this purely virtual by making ThemeClassic
+ * and ThemeModern implement it too.
+ *
+ * @returns True if the dialog was sucessfully closed.
+ * If we weren't able to restore the screen after closing
+ * the dialog, we return false, which means we need to redraw
+ * the dialog stack from scratch.
+ */
+ virtual bool closeDialog() { return false; }
+
+ /**
* Clear the complete GUI screen.
*/
virtual void clearAll() = 0;