From 237bec80f2af54f20616b123ba91692d2542bc01 Mon Sep 17 00:00:00 2001 From: David Capello Date: Mon, 6 Aug 2012 01:17:29 -0300 Subject: [PATCH] Add overlays (ui::Overlay and ui::OverlayManager classes). --- src/modules/gui.cpp | 13 +++++- src/she/display.h | 4 +- src/she/locked_surface.h | 3 +- src/she/she_alleg4.cpp | 17 ++++--- src/she/surface.h | 7 +++ src/ui/CMakeLists.txt | 2 + src/ui/gui.cpp | 3 ++ src/ui/gui.h | 2 + src/ui/overlay.cpp | 74 +++++++++++++++++++++++++++++ src/ui/overlay.h | 49 +++++++++++++++++++ src/ui/overlay_manager.cpp | 96 ++++++++++++++++++++++++++++++++++++++ src/ui/overlay_manager.h | 50 ++++++++++++++++++++ 12 files changed, 310 insertions(+), 10 deletions(-) create mode 100644 src/ui/overlay.cpp create mode 100644 src/ui/overlay.h create mode 100644 src/ui/overlay_manager.cpp create mode 100644 src/ui/overlay_manager.h diff --git a/src/modules/gui.cpp b/src/modules/gui.cpp index e74d2f835..c79e5ad4a 100644 --- a/src/modules/gui.cpp +++ b/src/modules/gui.cpp @@ -302,14 +302,23 @@ void gui_run() void gui_feedback() { + Manager* manager = Manager::getDefault(); + OverlayManager* overlays = OverlayManager::instance(); + jmouse_draw_cursor(); - if (!Manager::getDefault()->getDisplay()->flip()) { + // Draw overlays. + overlays->captureOverlappedAreas(); + overlays->drawOverlays(); + + if (!manager->getDisplay()->flip()) { // In case that the display was resized. gui_setup_screen(false); App::instance()->getMainWindow()->remap_window(); - Manager::getDefault()->invalidate(); + manager->invalidate(); } + else + overlays->restoreOverlappedAreas(); } // Sets the ji_screen variable. This routine should be called diff --git a/src/she/display.h b/src/she/display.h index f8f86c094..9f27e4353 100644 --- a/src/she/display.h +++ b/src/she/display.h @@ -10,6 +10,7 @@ namespace she { class Surface; + class NotDisposableSurface; // A display or window to show graphics. class Display { @@ -31,7 +32,8 @@ namespace she { virtual void setScale(int scale) = 0; // Returns the main surface to draw into this display. - virtual Surface* getSurface() = 0; + // You must not dispose this surface. + virtual NotDisposableSurface* getSurface() = 0; // Flips all graphics in the surface to the real display. Returns // false if the flip couldn't be done because the display was diff --git a/src/she/locked_surface.h b/src/she/locked_surface.h index efe162b3c..e40487acc 100644 --- a/src/she/locked_surface.h +++ b/src/she/locked_surface.h @@ -14,7 +14,8 @@ namespace she { virtual ~LockedSurface() { } virtual void unlock() = 0; virtual void clear() = 0; - virtual void blitTo(LockedSurface* dest, int x, int y) const = 0; + virtual void blitTo(LockedSurface* dest, int srcx, int srcy, int dstx, int dsty, int width, int height) const = 0; + virtual void drawAlphaSurface(const LockedSurface* src, int dstx, int dsty) = 0; }; } // namespace she diff --git a/src/she/she_alleg4.cpp b/src/she/she_alleg4.cpp index 3d71f8fa7..f0447af79 100644 --- a/src/she/she_alleg4.cpp +++ b/src/she/she_alleg4.cpp @@ -100,16 +100,21 @@ public: clear_to_color(m_bmp, 0); } - void blitTo(LockedSurface* dest, int x, int y) const { + void blitTo(LockedSurface* dest, int srcx, int srcy, int dstx, int dsty, int width, int height) const { ASSERT(m_bmp); ASSERT(dest); ASSERT(static_cast(dest)->m_bmp); blit(m_bmp, static_cast(dest)->m_bmp, - 0, 0, - x, y, - m_bmp->w, m_bmp->h); + srcx, srcy, + dstx, dsty, + width, height); + } + + void drawAlphaSurface(const LockedSurface* src, int dstx, int dsty) { + set_alpha_blender(); + draw_trans_sprite(m_bmp, static_cast(src)->m_bmp, dstx, dsty); } private: @@ -193,8 +198,8 @@ public: m_surface = newSurface; } - Surface* getSurface() { - return m_surface; + NotDisposableSurface* getSurface() { + return static_cast(m_surface); } bool flip() { diff --git a/src/she/surface.h b/src/she/surface.h index de1a56f8b..1ff79fba5 100644 --- a/src/she/surface.h +++ b/src/she/surface.h @@ -21,6 +21,13 @@ namespace she { virtual void* nativeHandle() = 0; }; + class NotDisposableSurface : public Surface { + public: + virtual ~NotDisposableSurface() { } + private: + virtual void dispose() = 0; + }; + } // namespace she #endif diff --git a/src/ui/CMakeLists.txt b/src/ui/CMakeLists.txt index 122ff475f..eae294857 100644 --- a/src/ui/CMakeLists.txt +++ b/src/ui/CMakeLists.txt @@ -27,6 +27,8 @@ add_library(ui-lib menu.cpp message.cpp message_loop.cpp + overlay.cpp + overlay_manager.cpp paint_event.cpp popup_window.cpp preferred_size_event.cpp diff --git a/src/ui/gui.cpp b/src/ui/gui.cpp index 0e8a6aaf7..382049f33 100644 --- a/src/ui/gui.cpp +++ b/src/ui/gui.cpp @@ -8,6 +8,7 @@ #include "ui/base.h" #include "ui/clipboard.h" +#include "ui/overlay_manager.h" #include "ui/theme.h" namespace ui { @@ -31,6 +32,8 @@ GuiSystem::GuiSystem() GuiSystem::~GuiSystem() { + OverlayManager::destroyInstance(); + // finish theme CurrentTheme::set(NULL); diff --git a/src/ui/gui.h b/src/ui/gui.h index 3632958ea..7ead7d565 100644 --- a/src/ui/gui.h +++ b/src/ui/gui.h @@ -34,6 +34,8 @@ #include "ui/menu.h" #include "ui/message.h" #include "ui/message_loop.h" +#include "ui/overlay.h" +#include "ui/overlay_manager.h" #include "ui/paint_event.h" #include "ui/popup_window.h" #include "ui/preferred_size_event.h" diff --git a/src/ui/overlay.cpp b/src/ui/overlay.cpp new file mode 100644 index 000000000..4de018c79 --- /dev/null +++ b/src/ui/overlay.cpp @@ -0,0 +1,74 @@ +// ASEPRITE gui library +// Copyright (C) 2001-2012 David Capello +// +// This source file is ditributed under a BSD-like license, please +// read LICENSE.txt for more information. + +#include "config.h" + +#include "ui/overlay.h" + +#include "she/locked_surface.h" +#include "she/scoped_surface_lock.h" +#include "she/system.h" +#include "ui/manager.h" + +namespace ui { + +Overlay::Overlay(she::Surface* overlaySurface, const gfx::Point& pos, ZOrder zorder) + : m_surface(overlaySurface) + , m_overlap(NULL) + , m_pos(pos) + , m_zorder(zorder) +{ +} + +Overlay::~Overlay() +{ + Manager* manager = Manager::getDefault(); + if (manager) + manager->invalidateRect(gfx::Rect(m_pos.x, m_pos.y, + m_surface->width(), + m_surface->height())); + m_surface->dispose(); + if (m_overlap) + m_overlap->dispose(); +} + +gfx::Rect Overlay::getBounds() const +{ + return gfx::Rect(m_pos.x, m_pos.y, m_surface->width(), m_surface->height()); +} + +void Overlay::drawOverlay(she::LockedSurface* screen) +{ + she::ScopedSurfaceLock lockedSurface(m_surface); + screen->drawAlphaSurface(lockedSurface, m_pos.x, m_pos.y); +} + +void Overlay::moveOverlay(const gfx::Point& newPos) +{ + m_pos = newPos; +} + +void Overlay::captureOverlappedArea(she::LockedSurface* screen) +{ + if (!m_overlap) + m_overlap = she::Instance()->createSurface(m_surface->width(), m_surface->height()); + + she::ScopedSurfaceLock lock(m_overlap); + screen->blitTo(lock, m_pos.x, m_pos.y, 0, 0, + m_overlap->width(), m_overlap->height()); +} + +void Overlay::restoreOverlappedArea(she::LockedSurface* screen) +{ + if (!m_overlap) + return; + + she::ScopedSurfaceLock lock(m_overlap); + lock->blitTo(screen, 0, 0, m_pos.x, m_pos.y, + m_overlap->width(), m_overlap->height()); +} + +} diff --git a/src/ui/overlay.h b/src/ui/overlay.h new file mode 100644 index 000000000..15d650679 --- /dev/null +++ b/src/ui/overlay.h @@ -0,0 +1,49 @@ +// ASEPRITE gui library +// Copyright (C) 2001-2012 David Capello +// +// This source file is ditributed under a BSD-like license, please +// read LICENSE.txt for more information. + +#ifndef UI_OVERLAY_H_INCLUDED +#define UI_OVERLAY_H_INCLUDED + +#include "gfx/fwd.h" +#include "gfx/point.h" +#include "ui/base.h" + +namespace she { + class Surface; + class LockedSurface; +} + +namespace ui { + + class Overlay { + public: + typedef int ZOrder; + + Overlay(she::Surface* overlaySurface, const gfx::Point& pos, ZOrder zorder = 0); + ~Overlay(); + + gfx::Rect getBounds() const; + + void captureOverlappedArea(she::LockedSurface* screen); + void restoreOverlappedArea(she::LockedSurface* screen); + + void drawOverlay(she::LockedSurface* screen); + void moveOverlay(const gfx::Point& newPos); + + bool operator<(const Overlay& other) const { + return m_zorder < other.m_zorder; + } + + private: + she::Surface* m_surface; + she::Surface* m_overlap; + gfx::Point m_pos; + ZOrder m_zorder; + }; + +} // namespace ui + +#endif diff --git a/src/ui/overlay_manager.cpp b/src/ui/overlay_manager.cpp new file mode 100644 index 000000000..26855bff1 --- /dev/null +++ b/src/ui/overlay_manager.cpp @@ -0,0 +1,96 @@ +// ASEPRITE gui library +// Copyright (C) 2001-2012 David Capello +// +// This source file is ditributed under a BSD-like license, please +// read LICENSE.txt for more information. + +#include "config.h" + +#include "ui/overlay_manager.h" + +#include "she/display.h" +#include "she/scoped_surface_lock.h" +#include "ui/manager.h" +#include "ui/overlay.h" + +#include + +namespace ui { + +static bool less_than(Overlay* x, Overlay* y) { + return *x < *y; +} + +OverlayManager* OverlayManager::m_singleton = NULL; + +OverlayManager* OverlayManager::instance() +{ + if (m_singleton == NULL) + m_singleton = new OverlayManager; + return m_singleton; +} + +void OverlayManager::destroyInstance() +{ + delete m_singleton; +} + +OverlayManager::OverlayManager() +{ +} + +OverlayManager::~OverlayManager() +{ +} + +void OverlayManager::addOverlay(Overlay* overlay) +{ + iterator it = std::lower_bound(begin(), end(), overlay, less_than); + m_overlays.insert(it, overlay); +} + +void OverlayManager::removeOverlay(Overlay* overlay) +{ + iterator it = std::find(begin(), end(), overlay); + ASSERT(it != end()); + if (it != end()) + m_overlays.erase(it); +} + +void OverlayManager::captureOverlappedAreas() +{ + Manager* manager = Manager::getDefault(); + if (!manager) + return; + + she::Surface* displaySurface = manager->getDisplay()->getSurface(); + she::ScopedSurfaceLock lockedDisplaySurface(displaySurface); + for (iterator it = begin(), end = this->end(); it != end; ++it) + (*it)->captureOverlappedArea(lockedDisplaySurface); +} + +void OverlayManager::restoreOverlappedAreas() +{ + Manager* manager = Manager::getDefault(); + if (!manager) + return; + + she::Surface* displaySurface = manager->getDisplay()->getSurface(); + she::ScopedSurfaceLock lockedDisplaySurface(displaySurface); + for (iterator it = begin(), end = this->end(); it != end; ++it) + (*it)->restoreOverlappedArea(lockedDisplaySurface); +} + +void OverlayManager::drawOverlays() +{ + Manager* manager = Manager::getDefault(); + if (!manager) + return; + + she::Surface* displaySurface = manager->getDisplay()->getSurface(); + she::ScopedSurfaceLock lockedDisplaySurface(displaySurface); + for (iterator it = begin(), end = this->end(); it != end; ++it) + (*it)->drawOverlay(lockedDisplaySurface); +} + +} // namespace ui diff --git a/src/ui/overlay_manager.h b/src/ui/overlay_manager.h new file mode 100644 index 000000000..6b73cda9c --- /dev/null +++ b/src/ui/overlay_manager.h @@ -0,0 +1,50 @@ +// ASEPRITE gui library +// Copyright (C) 2001-2012 David Capello +// +// This source file is ditributed under a BSD-like license, please +// read LICENSE.txt for more information. + +#ifndef UI_OVERLAY_MANAGER_H_INCLUDED +#define UI_OVERLAY_MANAGER_H_INCLUDED + +#include "ui/base.h" +#include + +namespace she { class Surface; } + +namespace ui { + + class Overlay; + + class OverlayManager { + friend class GuiSystem; // So it can call destroyInstance() from ~GuiSystem + static OverlayManager* m_singleton; + + OverlayManager(); + ~OverlayManager(); + + public: + static OverlayManager* instance(); + + void addOverlay(Overlay* overlay); + void removeOverlay(Overlay* overlay); + + void captureOverlappedAreas(); + void restoreOverlappedAreas(); + void drawOverlays(); + + private: + static void destroyInstance(); + + typedef std::vector OverlayList; + typedef OverlayList::iterator iterator; + + iterator begin() { return m_overlays.begin(); } + iterator end() { return m_overlays.end(); } + + OverlayList m_overlays; + }; + +} // namespace ui + +#endif