diff options
author | Andrei Karas <akaras@inbox.ru> | 2011-03-26 05:07:12 +0200 |
---|---|---|
committer | Andrei Karas <akaras@inbox.ru> | 2011-03-26 05:50:44 +0200 |
commit | 8403dcf857c9cc639e8162edd5d4df4af07274bc (patch) | |
tree | 2f127213e0df4691b06c549a8f20b3d5225b9220 /src | |
parent | fc24490f1ecd186f3c294915fadee62c3053d841 (diff) | |
download | mv-8403dcf857c9cc639e8162edd5d4df4af07274bc.tar.gz mv-8403dcf857c9cc639e8162edd5d4df4af07274bc.tar.bz2 mv-8403dcf857c9cc639e8162edd5d4df4af07274bc.tar.xz mv-8403dcf857c9cc639e8162edd5d4df4af07274bc.zip |
Precalculation vertexes for improving draw speed.
Implemented in Software and fast OpenGL backends.
Not all controls using this mode because some limitations.
Known issue: impossible compile without opengl.
Will be fixed in next commits.
Diffstat (limited to 'src')
-rw-r--r-- | src/CMakeLists.txt | 2 | ||||
-rw-r--r-- | src/Makefile.am | 2 | ||||
-rw-r--r-- | src/client.cpp | 2 | ||||
-rw-r--r-- | src/graphics.cpp | 217 | ||||
-rw-r--r-- | src/graphics.h | 29 | ||||
-rw-r--r-- | src/graphicsvertexes.cpp | 144 | ||||
-rw-r--r-- | src/graphicsvertexes.h | 155 | ||||
-rw-r--r-- | src/gui/widgets/button.cpp | 64 | ||||
-rw-r--r-- | src/gui/widgets/button.h | 13 | ||||
-rw-r--r-- | src/gui/widgets/popup.cpp | 39 | ||||
-rw-r--r-- | src/gui/widgets/popup.h | 11 | ||||
-rw-r--r-- | src/gui/widgets/progressbar.cpp | 68 | ||||
-rw-r--r-- | src/gui/widgets/progressbar.h | 19 | ||||
-rw-r--r-- | src/gui/widgets/scrollarea.cpp | 56 | ||||
-rw-r--r-- | src/gui/widgets/scrollarea.h | 7 | ||||
-rw-r--r-- | src/gui/widgets/tab.cpp | 34 | ||||
-rw-r--r-- | src/gui/widgets/tab.h | 11 | ||||
-rw-r--r-- | src/gui/widgets/window.cpp | 28 | ||||
-rw-r--r-- | src/gui/widgets/window.h | 5 | ||||
-rw-r--r-- | src/opengl1graphics.cpp | 27 | ||||
-rw-r--r-- | src/opengl1graphics.h | 10 | ||||
-rw-r--r-- | src/openglgraphics.cpp | 212 | ||||
-rw-r--r-- | src/openglgraphics.h | 11 |
23 files changed, 1138 insertions, 28 deletions
diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 262475989..873638df1 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -492,6 +492,8 @@ SET(SRCS game.h graphics.cpp graphics.h + graphicsvertexes.cpp + graphicsvertexes.h guichanfwd.h guild.cpp guild.h diff --git a/src/Makefile.am b/src/Makefile.am index ac89d665f..825b40718 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -385,6 +385,8 @@ manaplus_SOURCES = gui/widgets/avatarlistbox.cpp \ game.h \ graphics.cpp \ graphics.h \ + graphicsvertexes.cpp \ + graphicsvertexes.h \ guichanfwd.h \ guild.cpp \ guild.h \ diff --git a/src/client.cpp b/src/client.cpp index 0179c0f51..8fa9a1c8c 100644 --- a/src/client.cpp +++ b/src/client.cpp @@ -28,6 +28,7 @@ #include "emoteshortcut.h" #include "event.h" #include "game.h" +#include "graphicsvertexes.h" #include "itemshortcut.h" #include "dropshortcut.h" #include "keyboardconfig.h" @@ -399,6 +400,7 @@ Client::Client(const Options &options): // Setup image loading for the right image format Image::setLoadAsOpenGL(useOpenGL); + GraphicsVertexes::setLoadAsOpenGL(useOpenGL); // Create the graphics context switch(useOpenGL) diff --git a/src/graphics.cpp b/src/graphics.cpp index 5bc909c8e..e221f9fdb 100644 --- a/src/graphics.cpp +++ b/src/graphics.cpp @@ -23,6 +23,8 @@ #include <cassert> #include "graphics.h" + +#include "graphicsvertexes.h" #include "log.h" #include "resources/image.h" @@ -152,8 +154,6 @@ bool Graphics::drawRescaledImage(Image *image, int srcX, int srcY, return false; Image *tmpImage = image->SDLgetScaledImage(desiredWidth, desiredHeight); -// logger->log("SDLgetScaledImage " + tmpImage->getIdPath() -// + toString(desiredWidth) + "," + toString(desiredHeight)); bool returnValue = false; @@ -269,6 +269,53 @@ void Graphics::drawImagePattern(Image *image, int x, int y, int w, int h) } } +void Graphics::drawImagePatternDebug(GraphicsVertexes* vert, Image *image, int x, int y, int w, int h) +{ + // Check that preconditions for blitting are met. + if (!mTarget || !image) + return; + if (!image->mSDLSurface) + return; + + const int iw = image->getWidth(); + const int ih = image->getHeight(); + + if (iw == 0 || ih == 0) + return; + + std::list<DoubleRect*> *arr = vert->getRectsSDL(); + std::list<DoubleRect*>::iterator it; + it = arr->begin(); + + for (int py = 0; py < h; py += ih) // Y position on pattern plane + { + int dh = (py + ih >= h) ? h - py : ih; + int srcY = image->mBounds.y; + int dstY = y + py + mClipStack.top().yOffset; + + for (int px = 0; px < w; px += iw) // X position on pattern plane + { + int dw = (px + iw >= w) ? w - px : iw; + int srcX = image->mBounds.x; + int dstX = x + px + mClipStack.top().xOffset; + + SDL_Rect dstRect; + SDL_Rect srcRect; + dstRect.x = static_cast<short>(dstX); + dstRect.y = static_cast<short>(dstY); + srcRect.x = static_cast<short>(srcX); + srcRect.y = static_cast<short>(srcY); + srcRect.w = static_cast<Uint16>(dw); + srcRect.h = static_cast<Uint16>(dh); + + SDL_BlitSurface(image->mSDLSurface, &srcRect, mTarget, &dstRect); + + ++it; + } + } +} + + void Graphics::drawRescaledImagePattern(Image *image, int x, int y, int w, int h, int scaledWidth, int scaledHeight) @@ -286,9 +333,6 @@ void Graphics::drawRescaledImagePattern(Image *image, int x, int y, if (!tmpImage) return; -// logger->log("SDLgetScaledImageS " + tmpImage->getIdPath() -// + toString(scaledWidth) + "," + toString(scaledHeight)); - const int iw = tmpImage->getWidth(); const int ih = tmpImage->getHeight(); @@ -388,6 +432,159 @@ void Graphics::drawImageRect(int x, int y, int w, int h, imgRect.grid[4]); } +void Graphics::drawImageRect2(GraphicsVertexes* vert, const ImageRect &imgRect) +{ + vert->setPtr(0); + + const bool drawMain = imgRect.grid[4] && imgRect.grid[0] && imgRect.grid[2] + && imgRect.grid[6] && imgRect.grid[8]; + + if (drawMain) + { + // center + drawImagePattern2(vert, imgRect.grid[4]); + } + vert->incPtr(); + + // top + drawImagePattern2(vert, imgRect.grid[1]); + vert->incPtr(); + + // bottom + drawImagePattern2(vert, imgRect.grid[7]); + vert->incPtr(); + + // left + drawImagePattern2(vert, imgRect.grid[3]); + vert->incPtr(); + + // right + drawImagePattern2(vert, imgRect.grid[5]); + vert->incPtr(); + + // Draw the corners + if (drawMain) + { + drawImage(imgRect.grid[0], 0, 0); + drawImage(imgRect.grid[2], vert->mW - imgRect.grid[2]->getWidth(), 0); + drawImage(imgRect.grid[6], 0, vert->mH - imgRect.grid[6]->getHeight()); + drawImage(imgRect.grid[8], + vert->mW - imgRect.grid[8]->getWidth(), + vert->mH - imgRect.grid[8]->getHeight()); + } +} + +void Graphics::drawImagePattern2(GraphicsVertexes *vert, Image *img) +{ + std::list<DoubleRect*> *arr = vert->getRectsSDL(); + std::list<DoubleRect*>::iterator it; + + for (it = arr->begin(); it != arr->end(); ++it) + SDL_BlitSurface(img->mSDLSurface, &(*it)->src, mTarget, &(*it)->dst); +} + +bool Graphics::calcImageRect(GraphicsVertexes* vert, + int x, int y, int w, int h, + Image *topLeft, Image *topRight, + Image *bottomLeft, Image *bottomRight, + Image *top, Image *right, + Image *bottom, Image *left, + Image *center) +{ + const bool drawMain = center && topLeft && topRight + && bottomLeft && bottomRight; + + vert->init(x, y, w, h); + pushClipArea(gcn::Rectangle(vert->mX, vert->mY, vert->mW, vert->mH)); + + // Draw the center area + if (center && drawMain) + { + calcImagePattern(vert, center, + topLeft->getWidth(), topLeft->getHeight(), + w - topLeft->getWidth() - topRight->getWidth(), + h - topLeft->getHeight() - bottomLeft->getHeight()); + } + else + { + vert->incPtr(1); + } + + // Draw the sides + if (top && left && bottom && right) + { + calcImagePattern(vert, top, + left->getWidth(), 0, + w - left->getWidth() - right->getWidth(), top->getHeight()); + calcImagePattern(vert, bottom, + left->getWidth(), h - bottom->getHeight(), + w - left->getWidth() - right->getWidth(), + bottom->getHeight()); + calcImagePattern(vert, left, + 0, top->getHeight(), + left->getWidth(), + h - top->getHeight() - bottom->getHeight()); + calcImagePattern(vert, right, + w - right->getWidth(), top->getHeight(), + right->getWidth(), + h - top->getHeight() - bottom->getHeight()); + } + else + { + vert->incPtr(4); + } + + popClipArea(); + return 0; +} + +void Graphics::calcImagePattern(GraphicsVertexes* vert, + Image *image, int x, int y, int w, int h) +{ + // Check that preconditions for blitting are met. + if (!vert || !mTarget || !image || !image->mSDLSurface || !vert->sdl) + { + vert->incPtr(1); + return; + } + vert->clearSDL(); + + const int iw = image->getWidth(); + const int ih = image->getHeight(); + + if (iw == 0 || ih == 0) + { + vert->incPtr(1); + return; + } + + for (int py = 0; py < h; py += ih) // Y position on pattern plane + { + int dh = (py + ih >= h) ? h - py : ih; + int srcY = image->mBounds.y; + int dstY = y + py + mClipStack.top().yOffset; + + for (int px = 0; px < w; px += iw) // X position on pattern plane + { + int dw = (px + iw >= w) ? w - px : iw; + int srcX = image->mBounds.x; + int dstX = x + px + mClipStack.top().xOffset; + + SDL_Rect dstRect; + SDL_Rect srcRect; + dstRect.x = static_cast<short>(dstX); + dstRect.y = static_cast<short>(dstY); + srcRect.x = static_cast<short>(srcX); + srcRect.y = static_cast<short>(srcY); + srcRect.w = static_cast<Uint16>(dw); + srcRect.h = static_cast<Uint16>(dh); + + vert->pushSDL(srcRect, dstRect); + } + } + vert->incPtr(1); +} + void Graphics::updateScreen() { SDL_Flip(mTarget); @@ -425,3 +622,13 @@ bool Graphics::drawNet(int x1, int y1, int x2, int y2, int width, int height) return true; } + +bool Graphics::calcWindow(GraphicsVertexes* vert, + int x, int y, int w, int h, + const ImageRect &imgRect) +{ + return calcImageRect(vert, x, y, w, h, + imgRect.grid[0], imgRect.grid[2], imgRect.grid[6], imgRect.grid[8], + imgRect.grid[1], imgRect.grid[5], imgRect.grid[7], imgRect.grid[3], + imgRect.grid[4]); +} diff --git a/src/graphics.h b/src/graphics.h index a8e593ba1..23ce0bb91 100644 --- a/src/graphics.h +++ b/src/graphics.h @@ -25,12 +25,15 @@ #include <guichan/sdl/sdlgraphics.hpp> +//include "graphicsvertexes.h" + #ifdef __GNUC__ #define _UNUSED_ __attribute__ ((unused)) #else #define _UNUSED_ #endif +class GraphicsVertexes; class Image; class ImageRect; @@ -161,6 +164,8 @@ class Graphics : public gcn::SDLGraphics int x, int y, int w, int h); + void drawImagePatternDebug(GraphicsVertexes* vert, Image *image, int x, int y, int w, int h); + /** * Draw a pattern based on a rescaled version of the given image... */ @@ -187,6 +192,27 @@ class Graphics : public gcn::SDLGraphics void drawImageRect(int x, int y, int w, int h, const ImageRect &imgRect); + virtual bool calcImageRect(GraphicsVertexes* vert, + int x, int y, int w, int h, + Image *topLeft, Image *topRight, + Image *bottomLeft, Image *bottomRight, + Image *top, Image *right, + Image *bottom, Image *left, + Image *center); + + virtual void calcImagePattern(GraphicsVertexes* vert, Image *image, + int x, int y, + int w, int h); + + virtual void drawImageRect2(GraphicsVertexes* vert, + const ImageRect &imgRect); + + virtual void drawImagePattern2(GraphicsVertexes *vert, Image *img); + + bool calcWindow(GraphicsVertexes* vert, + int x, int y, int w, int h, + const ImageRect &imgRect); + /** * Draws a rectangle using images. 4 corner images, 4 side images and 1 * image for the inside. @@ -228,6 +254,9 @@ class Graphics : public gcn::SDLGraphics gcn::Font *getFont() const { return mFont; } + gcn::ClipRectangle &getTopClip() + { return mClipStack.top(); } + protected: int mWidth; int mHeight; diff --git a/src/graphicsvertexes.cpp b/src/graphicsvertexes.cpp new file mode 100644 index 000000000..1170d55fd --- /dev/null +++ b/src/graphicsvertexes.cpp @@ -0,0 +1,144 @@ +/* + * The ManaPlus Client + * Copyright (C) 2011 The ManaPlus Developers + * + * This file is part of The ManaPlus Client. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +#include "graphicsvertexes.h" + +#include "main.h" + +#include "utils/dtor.h" + +#ifdef USE_OPENGL +int GraphicsVertexes::mUseOpenGL = 0; +const unsigned int vertexBufSize = 500; +#endif + + +SDLGraphicsVertexes::SDLGraphicsVertexes() +{ + +} + +SDLGraphicsVertexes::~SDLGraphicsVertexes() +{ + delete_all(mList); +} + + +OpenGLGraphicsVertexes::OpenGLGraphicsVertexes() : + mFloatTexArray(0), + mIntTexArray(0), + mIntVertArray(0) +{ +} + +OpenGLGraphicsVertexes::~OpenGLGraphicsVertexes() +{ + clear(); +} + +void OpenGLGraphicsVertexes::clear() +{ + delete_all(mFloatTexPool); + mFloatTexPool.clear(); + delete_all(mIntVertPool); + mIntVertPool.clear(); + delete_all(mIntTexPool); + mIntTexPool.clear(); + mVp.clear(); +} + +void OpenGLGraphicsVertexes::init() +{ + clear(); +} + +GLfloat *OpenGLGraphicsVertexes::switchFloatTexArray() +{ + mFloatTexArray = new GLfloat[vertexBufSize * 4 + 30]; + mFloatTexPool.push_back(mFloatTexArray); + return mFloatTexArray; +} + +GLint *OpenGLGraphicsVertexes::switchIntVertArray() +{ + mIntVertArray = new GLint[vertexBufSize * 4 + 30]; + mIntVertPool.push_back(mIntVertArray); + return mIntVertArray; +} + +GLint *OpenGLGraphicsVertexes::switchIntTexArray() +{ + mIntTexArray = new GLint[vertexBufSize * 4 + 30]; + mIntTexPool.push_back(mIntTexArray); + return mIntTexArray; +} + +void OpenGLGraphicsVertexes::switchVp(int n) +{ + mVp.push_back(n); +} + +GraphicsVertexes::GraphicsVertexes() : + mX(0), mY(0), + mW(0), mH(0), + mPtr(0) +{ +} + +GraphicsVertexes::~GraphicsVertexes() +{ +} + +void GraphicsVertexes::init(int x, int y, int w, int h) +{ + mPtr = 0; + mX = x; + mY = y; + mW = w; + mH = h; + for (int f = 0; f < 10; f ++) + { + sdl[mPtr].mList.clear(); + ogl[mPtr].init(); + } +} + +void GraphicsVertexes::setLoadAsOpenGL(int useOpenGL) +{ + mUseOpenGL = useOpenGL; +} + +void GraphicsVertexes::pushSDL(SDL_Rect r1, SDL_Rect r2) +{ + DoubleRect *r = new DoubleRect(); + r->src = r1; + r->dst = r2; + sdl[mPtr].mList.push_back(r); +} + +void GraphicsVertexes::clearSDL() +{ + sdl[mPtr].mList.clear(); +} + +std::list<DoubleRect*> *GraphicsVertexes::getRectsSDL() +{ + return &sdl[mPtr].mList; +} diff --git a/src/graphicsvertexes.h b/src/graphicsvertexes.h new file mode 100644 index 000000000..1efb74f01 --- /dev/null +++ b/src/graphicsvertexes.h @@ -0,0 +1,155 @@ +/* + * The ManaPlus Client + * Copyright (C) 2011 The ManaPlus Developers + * + * This file is part of The ManaPlus Client. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +#ifndef GRAPHICSVERTEXES_H +#define GRAPHICSVERTEXES_H + + +#include "main.h" + +#include "graphics.h" + +#ifdef USE_OPENGL +#define NO_SDL_GLEXT + +#include <SDL_opengl.h> +#endif + +#include <string> +#include <list> +#include <vector> + +//include <guichan/sdl/sdlgraphics.hpp> + + +struct DoubleRect +{ + SDL_Rect src; + SDL_Rect dst; +}; + +class SDLGraphicsVertexes +{ + public: + SDLGraphicsVertexes(); + + ~SDLGraphicsVertexes(); + + std::list<DoubleRect*> mList; +}; + + +class OpenGL1GraphicsVertexes +{ +}; + +class OpenGLGraphicsVertexes +{ + public: + OpenGLGraphicsVertexes(); + + ~OpenGLGraphicsVertexes(); + + GLfloat *switchFloatTexArray(); + + GLint *switchIntVertArray(); + + GLint *switchIntTexArray(); + + void init(); + + void clear(); + + std::vector<GLfloat*> &getFloatTexPool() + { return mFloatTexPool; } + + std::vector<GLint*> &getIntVertPool() + { return mIntVertPool; } + + std::vector<GLint*> &getIntTexPool() + { return mIntTexPool; } + + void switchVp(int n); + + std::vector<int> &getVp() + { return mVp; } + + private: + GLfloat *mFloatTexArray; + GLint *mIntTexArray; + GLint *mIntVertArray; + std::vector<GLfloat*> mFloatTexPool; + std::vector<GLint*> mIntVertPool; + std::vector<GLint*> mIntTexPool; + std::vector<int> mVp; +}; + +class GraphicsVertexes +{ + public: + GraphicsVertexes(); + + ~GraphicsVertexes(); + + static void setLoadAsOpenGL(int useOpenGL); + + SDLGraphicsVertexes sdl[5]; + + OpenGL1GraphicsVertexes ogl1[5]; + + OpenGLGraphicsVertexes ogl[5]; + + void init(int x, int y, int w, int h); + + void pushSDL(SDL_Rect r1, SDL_Rect r2); + + void clearSDL(); + + std::list<DoubleRect*> *getRectsSDL(); + + void incPtr(int num = 1) + { mPtr += num; } + + void setPtr(int num) + { mPtr = num; } + + OpenGLGraphicsVertexes* getOGL() + { return &ogl[mPtr]; } + + int getX() + { return mX; } + + int getY() + { return mY; } + + int getW() + { return mW; } + + int getH() + { return mH; } + + int mX, mY, mW, mH; + int mPtr; + + private: + static int mUseOpenGL; +}; + +#endif // GRAPHICSVERTEXES_H diff --git a/src/gui/widgets/button.cpp b/src/gui/widgets/button.cpp index 89e270595..a8e8b656d 100644 --- a/src/gui/widgets/button.cpp +++ b/src/gui/widgets/button.cpp @@ -25,6 +25,7 @@ #include "client.h" #include "configuration.h" #include "graphics.h" +#include "graphicsvertexes.h" #include "log.h" #include "gui/palette.h" @@ -67,7 +68,12 @@ static ButtonData const data[BUTTON_COUNT] = ImageRect Button::button[BUTTON_COUNT]; Button::Button(): - mDescription(""), mClickCount(0) + mDescription(""), mClickCount(0), + mVertexes(new GraphicsVertexes()), + mRedraw(true), + mMode(0), + mXOffset(0), + mYOffset(0) { init(); } @@ -75,7 +81,9 @@ Button::Button(): Button::Button(const std::string &caption, const std::string &actionEventId, gcn::ActionListener *listener): gcn::Button(caption), - mDescription(""), mClickCount(0) + mDescription(""), mClickCount(0), + mVertexes(new GraphicsVertexes()), + mRedraw(true) { init(); setActionEventId(actionEventId); @@ -88,6 +96,8 @@ void Button::init() { setFrameSize(0); + addWidgetListener(this); + if (mInstances == 0) { // Load the skin @@ -175,8 +185,44 @@ void Button::draw(gcn::Graphics *graphics) updateAlpha(); - static_cast<Graphics*>(graphics)-> - drawImageRect(0, 0, getWidth(), getHeight(), button[mode]); + + bool recalc = false; + if (mRedraw) + { + recalc = true; + } + else + { + // because we dont know where parent windows was moved, + // need recalc vertexes + gcn::ClipRectangle &rect = static_cast<Graphics*>( + graphics)->getTopClip(); + if (rect.xOffset != mXOffset || rect.yOffset != mYOffset) + { + recalc = true; + mXOffset = rect.xOffset; + mYOffset = rect.yOffset; + } + else if (mMode != mode) + { + recalc = true; + mMode = mode; + } + } + + if (recalc) + { + mRedraw = false; + mMode = mode; + static_cast<Graphics*>(graphics)->calcWindow(mVertexes, 0, 0, + getWidth(), getHeight(), button[mode]); + } + + static_cast<Graphics*>(graphics)->drawImageRect2( + mVertexes, button[mode]); + +// static_cast<Graphics*>(graphics)-> +// drawImageRect(0, 0, getWidth(), getHeight(), button[mode]); if (mode == BUTTON_DISABLED) graphics->setColor(Theme::getThemeColor(Theme::BUTTON_DISABLED)); @@ -226,3 +272,13 @@ void Button::mouseReleased(gcn::MouseEvent& mouseEvent) mouseEvent.consume(); } } + +void Button::widgetResized(const gcn::Event &event _UNUSED_) +{ + mRedraw = true; +} + +void Button::widgetMoved(const gcn::Event &event _UNUSED_) +{ + mRedraw = true; +} diff --git a/src/gui/widgets/button.h b/src/gui/widgets/button.h index e7446cd26..8c43b6ddd 100644 --- a/src/gui/widgets/button.h +++ b/src/gui/widgets/button.h @@ -25,7 +25,9 @@ #include <guichan/widgets/button.hpp> #include <guichan/mouseevent.hpp> +#include <guichan/widgetlistener.hpp> +class GraphicsVertexes; class ImageRect; /** @@ -33,7 +35,7 @@ class ImageRect; * * \ingroup GUI */ -class Button : public gcn::Button +class Button : public gcn::Button, public gcn::WidgetListener { public: /** @@ -80,6 +82,10 @@ class Button : public gcn::Button int getTag() { return mTag; } + void widgetResized(const gcn::Event &event); + + void widgetMoved(const gcn::Event &event); + private: void init(); @@ -90,6 +96,11 @@ class Button : public gcn::Button std::string mDescription; unsigned mClickCount; int mTag; + GraphicsVertexes *mVertexes; + bool mRedraw; + int mMode; + int mXOffset; + int mYOffset; }; #endif diff --git a/src/gui/widgets/popup.cpp b/src/gui/widgets/popup.cpp index 3d9c3b449..7519d1583 100644 --- a/src/gui/widgets/popup.cpp +++ b/src/gui/widgets/popup.cpp @@ -25,12 +25,14 @@ #include "configuration.h" #include "graphics.h" +#include "graphicsvertexes.h" #include "log.h" #include "gui/theme.h" #include "gui/viewport.h" #include "gui/widgets/windowcontainer.h" +#include "gui/widgets/window.h" #include "resources/image.h" @@ -41,13 +43,17 @@ Popup::Popup(const std::string &name, const std::string &skin): mMinWidth(100), mMinHeight(40), mMaxWidth(graphics->getWidth()), - mMaxHeight(graphics->getHeight()) + mMaxHeight(graphics->getHeight()), + mVertexes(new GraphicsVertexes()), + mRedraw(true) { logger->log("Popup::Popup(\"%s\")", name.c_str()); if (!windowContainer) throw GCN_EXCEPTION("Popup::Popup(): no windowContainer set"); + addWidgetListener(this); + setPadding(3); // Loads the skin @@ -64,6 +70,9 @@ Popup::~Popup() { logger->log("Popup::~Popup(\"%s\")", mPopupName.c_str()); + delete mVertexes; + mVertexes = 0; + if (mSkin) mSkin->instances--; } @@ -77,7 +86,16 @@ void Popup::draw(gcn::Graphics *graphics) { Graphics *g = static_cast<Graphics*>(graphics); - g->drawImageRect(0, 0, getWidth(), getHeight(), mSkin->getBorder()); + if (mRedraw) + { + mRedraw = false; + g->calcWindow(mVertexes, 0, 0, getWidth(), + getHeight(), mSkin->getBorder()); + } + + g->drawImageRect2(mVertexes, mSkin->getBorder()); + +// g->drawImageRect(0, 0, getWidth(), getHeight(), mSkin->getBorder()); drawChildren(graphics); } @@ -103,6 +121,7 @@ void Popup::setContentSize(int width, int height) height = getMaxHeight(); setSize(width, height); + mRedraw = true; } void Popup::setLocationRelativeTo(gcn::Widget *widget) @@ -118,6 +137,7 @@ void Popup::setLocationRelativeTo(gcn::Widget *widget) setPosition(getX() + (wx + (widget->getWidth() - getWidth()) / 2 - x), getY() + (wy + (widget->getHeight() - getHeight()) / 2 - y)); + mRedraw = true; } void Popup::setMinWidth(int width) @@ -161,15 +181,28 @@ void Popup::position(int x, int y) setPosition(posX, posY); setVisible(true); requestMoveToTop(); + mRedraw = true; } void Popup::mouseMoved(gcn::MouseEvent &event _UNUSED_) { if (viewport) viewport->hideBeingPopup(); + mRedraw = true; } void Popup::hide() { setVisible(false); -}
\ No newline at end of file + mRedraw = true; +} + +void Popup::widgetResized(const gcn::Event &event _UNUSED_) +{ + mRedraw = true; +} + +void Popup::widgetMoved(const gcn::Event &event _UNUSED_) +{ + mRedraw = true; +} diff --git a/src/gui/widgets/popup.h b/src/gui/widgets/popup.h index 302e55656..963477fbb 100644 --- a/src/gui/widgets/popup.h +++ b/src/gui/widgets/popup.h @@ -30,6 +30,7 @@ #include "gui/widgets/container.h" #include <guichan/mouselistener.hpp> +#include <guichan/widgetlistener.hpp> #ifdef __GNUC__ #define _UNUSED_ __attribute__ ((unused)) @@ -37,6 +38,7 @@ #define _UNUSED_ #endif +class GraphicsVertexes; class Skin; class WindowContainer; @@ -52,7 +54,8 @@ class WindowContainer; * * \ingroup GUI */ -class Popup : public Container, public gcn::MouseListener +class Popup : public Container, public gcn::MouseListener, + public gcn::WidgetListener { public: /** @@ -161,6 +164,10 @@ class Popup : public Container, public gcn::MouseListener void hide(); + void widgetResized(const gcn::Event &event); + + void widgetMoved(const gcn::Event &event); + private: std::string mPopupName; /**< Name of the popup */ int mMinWidth; /**< Minimum popup width */ @@ -170,6 +177,8 @@ class Popup : public Container, public gcn::MouseListener int mPadding; /**< Holds the padding of the popup. */ Skin *mSkin; /**< Skin in use by this popup */ + GraphicsVertexes *mVertexes; + bool mRedraw; }; #endif diff --git a/src/gui/widgets/progressbar.cpp b/src/gui/widgets/progressbar.cpp index c612ed36a..0916d9976 100644 --- a/src/gui/widgets/progressbar.cpp +++ b/src/gui/widgets/progressbar.cpp @@ -25,6 +25,7 @@ #include "client.h" #include "configuration.h" #include "graphics.h" +#include "graphicsvertexes.h" #include "textrenderer.h" #include "gui/gui.h" @@ -47,7 +48,9 @@ ProgressBar::ProgressBar(float progress, gcn::Widget(), mSmoothProgress(true), mProgressPalette(color), - mSmoothColorChange(true) + mSmoothColorChange(true), + mVertexes(new GraphicsVertexes()), + mRedraw(true) { // The progress value is directly set at load time: if (progress > 1.0f || progress < 0.0f) @@ -59,6 +62,8 @@ ProgressBar::ProgressBar(float progress, mColor = Theme::getProgressColor(color >= 0 ? color : 0, mProgress); mColorToGo = mColor; + addWidgetListener(this); + setSize(width, height); if (mInstances == 0) @@ -98,6 +103,8 @@ ProgressBar::~ProgressBar() if (mInstances == 0) for_each(mBorder.grid, mBorder.grid + 9, dtor<Image*>()); + delete mVertexes; + mVertexes = 0; } void ProgressBar::logic() @@ -157,7 +164,7 @@ void ProgressBar::draw(gcn::Graphics *graphics) rect.y = 0; render(static_cast<Graphics*>(graphics), rect, mColor, - mProgress, mText); + mProgress, mText, mVertexes, &mRedraw); } void ProgressBar::setProgress(float progress) @@ -191,6 +198,53 @@ void ProgressBar::setColor(const gcn::Color &color) void ProgressBar::render(Graphics *graphics, const gcn::Rectangle &area, const gcn::Color &color, float progress, + const std::string &text, GraphicsVertexes *vert, + bool *redraw) +{ + gcn::Font *oldFont = graphics->getFont(); + gcn::Color oldColor = graphics->getColor(); + + if (*redraw) + { + *redraw = false; + static_cast<Graphics*>(graphics)->calcWindow(vert, + area.x, area.y, area.width, area.height, mBorder); + } + + static_cast<Graphics*>(graphics)->drawImageRect2(vert, mBorder); + +// graphics->drawImageRect(area.x, area.y, area.width, area.height, mBorder); +// graphics->drawImageRect(area, mBorder); + + // The bar + if (progress > 0) + { + graphics->setColor(color); + graphics->fillRectangle(gcn::Rectangle(static_cast<int>(area.x + 4), + static_cast<int>(area.y + 4), + static_cast<int>(static_cast<float>(progress) + * static_cast<float>(area.width - 8)), + static_cast<int>(area.height - 8))); + } + + // The label + if (!text.empty()) + { + const int textX = area.x + area.width / 2; + const int textY = area.y + (area.height - boldFont->getHeight()) / 2; + + TextRenderer::renderText(graphics, text, textX, textY, + gcn::Graphics::CENTER, + Theme::getThemeColor(Theme::PROGRESS_BAR), + gui->getFont(), true, false); + } + + graphics->setFont(oldFont); + graphics->setColor(oldColor); +} + +void ProgressBar::render(Graphics *graphics, const gcn::Rectangle &area, + const gcn::Color &color, float progress, const std::string &text) { gcn::Font *oldFont = graphics->getFont(); @@ -224,3 +278,13 @@ void ProgressBar::render(Graphics *graphics, const gcn::Rectangle &area, graphics->setFont(oldFont); graphics->setColor(oldColor); } + +void ProgressBar::widgetResized(const gcn::Event &event _UNUSED_) +{ + mRedraw = true; +} + +void ProgressBar::widgetMoved(const gcn::Event &event _UNUSED_) +{ + mRedraw = true; +} diff --git a/src/gui/widgets/progressbar.h b/src/gui/widgets/progressbar.h index ba10f3027..52a26ddac 100644 --- a/src/gui/widgets/progressbar.h +++ b/src/gui/widgets/progressbar.h @@ -27,7 +27,10 @@ #include <string> +#include <guichan/widgetlistener.hpp> + class Graphics; +class GraphicsVertexes; class ImageRect; /** @@ -35,7 +38,7 @@ class ImageRect; * * \ingroup GUI */ -class ProgressBar : public gcn::Widget +class ProgressBar : public gcn::Widget, public gcn::WidgetListener { public: /** @@ -117,8 +120,20 @@ class ProgressBar : public gcn::Widget */ static void render(Graphics *graphics, const gcn::Rectangle &area, const gcn::Color &color, float progress, + const std::string &text, + GraphicsVertexes *vert, bool *redraw); + + /** + * Renders a progressbar with the given properties. + */ + static void render(Graphics *graphics, const gcn::Rectangle &area, + const gcn::Color &color, float progress, const std::string &text = ""); + void widgetResized(const gcn::Event &event); + + void widgetMoved(const gcn::Event &event); + private: float mProgress, mProgressToGo; bool mSmoothProgress; @@ -129,6 +144,8 @@ class ProgressBar : public gcn::Widget bool mSmoothColorChange; std::string mText; + GraphicsVertexes *mVertexes; + bool mRedraw; static ImageRect mBorder; static int mInstances; diff --git a/src/gui/widgets/scrollarea.cpp b/src/gui/widgets/scrollarea.cpp index b11213239..2cc745ccd 100644 --- a/src/gui/widgets/scrollarea.cpp +++ b/src/gui/widgets/scrollarea.cpp @@ -25,6 +25,7 @@ #include "client.h" #include "configuration.h" #include "graphics.h" +#include "graphicsvertexes.h" #include "log.h" #include "gui/theme.h" @@ -45,7 +46,11 @@ ScrollArea::ScrollArea(): mX(0), mY(0), mHasMouse(false), - mOpaque(true) + mOpaque(true), + mVertexes(new GraphicsVertexes()), + mRedraw(true), + mXOffset(0), + mYOffset(0) { addWidgetListener(this); init(); @@ -56,8 +61,13 @@ ScrollArea::ScrollArea(gcn::Widget *widget): mX(0), mY(0), mHasMouse(false), - mOpaque(true) + mOpaque(true), + mVertexes(new GraphicsVertexes()), + mRedraw(true), + mXOffset(0), + mYOffset(0) { + addWidgetListener(this); init(); } @@ -91,6 +101,8 @@ ScrollArea::~ScrollArea() if (buttons[RIGHT][1]) buttons[RIGHT][1]->decRef(); } + delete mVertexes; + mVertexes = 0; } void ScrollArea::init() @@ -286,6 +298,7 @@ void ScrollArea::draw(gcn::Graphics *graphics) drawHMarker(graphics); } + if (mHBarVisible && mVBarVisible) { graphics->setColor(getBaseColor()); @@ -300,6 +313,7 @@ void ScrollArea::draw(gcn::Graphics *graphics) drawChildren(graphics); } +//void ScrollArea::drawFrame(gcn::Graphics *graphics _UNUSED_) void ScrollArea::drawFrame(gcn::Graphics *graphics) { if (mOpaque) @@ -308,8 +322,38 @@ void ScrollArea::drawFrame(gcn::Graphics *graphics) const int w = getWidth() + bs * 2; const int h = getHeight() + bs * 2; + bool recalc = false; + if (mRedraw) + { + recalc = true; + } + else + { + // because we dont know where parent windows was moved, + // need recalc vertexes + gcn::ClipRectangle &rect = static_cast<Graphics*>( + graphics)->getTopClip(); + if (rect.xOffset != mXOffset || rect.yOffset != mYOffset) + { + recalc = true; + mXOffset = rect.xOffset; + mYOffset = rect.yOffset; + } + } + + if (recalc) + { + mRedraw = false; + static_cast<Graphics*>(graphics)->calcWindow( + mVertexes, 0, 0, w, h, background); + } + + static_cast<Graphics*>(graphics)-> - drawImageRect(0, 0, w, h, background); + drawImageRect2(mVertexes, background); + +// static_cast<Graphics*>(graphics)-> +// drawImageRect(0, 0, w, h, background); } } @@ -441,6 +485,12 @@ void ScrollArea::mouseExited(gcn::MouseEvent& event _UNUSED_) void ScrollArea::widgetResized(const gcn::Event &event _UNUSED_) { + mRedraw = true; getContent()->setSize(getWidth() - 2 * getFrameSize(), getHeight() - 2 * getFrameSize()); } + +void ScrollArea::widgetMoved(const gcn::Event& event _UNUSED_) +{ + mRedraw = true; +} diff --git a/src/gui/widgets/scrollarea.h b/src/gui/widgets/scrollarea.h index 49d5e7f28..e613170fa 100644 --- a/src/gui/widgets/scrollarea.h +++ b/src/gui/widgets/scrollarea.h @@ -32,6 +32,7 @@ #define _UNUSED_ #endif +class GraphicsVertexes; class Image; class ImageRect; @@ -113,6 +114,8 @@ class ScrollArea : public gcn::ScrollArea, public gcn::WidgetListener void widgetResized(const gcn::Event &event); + void widgetMoved(const gcn::Event &event); + protected: enum BUTTON_DIR { @@ -147,6 +150,10 @@ class ScrollArea : public gcn::ScrollArea, public gcn::WidgetListener int mX, mY; bool mHasMouse; bool mOpaque; + GraphicsVertexes *mVertexes; + bool mRedraw; + int mXOffset; + int mYOffset; }; #endif diff --git a/src/gui/widgets/tab.cpp b/src/gui/widgets/tab.cpp index 6a2b05cd4..78165dc18 100644 --- a/src/gui/widgets/tab.cpp +++ b/src/gui/widgets/tab.cpp @@ -25,6 +25,7 @@ #include "client.h" #include "configuration.h" #include "graphics.h" +#include "graphicsvertexes.h" #include "log.h" #include "gui/palette.h" @@ -68,7 +69,10 @@ static TabData const data[TAB_COUNT] = ImageRect Tab::tabImg[TAB_COUNT]; Tab::Tab() : gcn::Tab(), - mTabColor(&Theme::getThemeColor(Theme::TAB)) + mTabColor(&Theme::getThemeColor(Theme::TAB)), + mVertexes(new GraphicsVertexes()), + mRedraw(true), + mMode(0) { init(); } @@ -82,6 +86,8 @@ Tab::~Tab() for (int mode = 0; mode < TAB_COUNT; mode++) for_each(tabImg[mode].grid, tabImg[mode].grid + 9, dtor<Image*>()); } + delete mVertexes; + mVertexes = 0; } void Tab::init() @@ -90,6 +96,8 @@ void Tab::init() setFrameSize(0); mFlash = 0; + addWidgetListener(this); + if (mInstances == 0) { // Load the skin @@ -179,8 +187,18 @@ void Tab::draw(gcn::Graphics *graphics) updateAlpha(); // draw tab - static_cast<Graphics*>(graphics)-> - drawImageRect(0, 0, getWidth(), getHeight(), tabImg[mode]); + if (mRedraw || mode != mMode) + { + mMode = mode; + mRedraw = false; + static_cast<Graphics*>(graphics)->calcWindow(mVertexes, 0, 0, getWidth(), + getHeight(), tabImg[mode]); + } + + static_cast<Graphics*>(graphics)->drawImageRect2(mVertexes, tabImg[mode]); + +// static_cast<Graphics*>(graphics)-> +// drawImageRect(0, 0, getWidth(), getHeight(), tabImg[mode]); // draw label drawChildren(graphics); @@ -195,3 +213,13 @@ void Tab::setFlash(int flash) { mFlash = flash; } + +void Tab::widgetResized(const gcn::Event &event _UNUSED_) +{ + mRedraw = true; +} + +void Tab::widgetMoved(const gcn::Event &event _UNUSED_) +{ + mRedraw = true; +} diff --git a/src/gui/widgets/tab.h b/src/gui/widgets/tab.h index 637234c89..f9f1fa4da 100644 --- a/src/gui/widgets/tab.h +++ b/src/gui/widgets/tab.h @@ -24,7 +24,9 @@ #define TAB_H #include <guichan/widgets/tab.hpp> +#include <guichan/widgetlistener.hpp> +class GraphicsVertexes; class ImageRect; class TabbedArea; @@ -32,7 +34,7 @@ class TabbedArea; * A tab, the same as the Guichan tab in 0.8, but extended to allow * transparency. */ -class Tab : public gcn::Tab +class Tab : public gcn::Tab, public gcn::WidgetListener { public: Tab(); @@ -61,6 +63,10 @@ class Tab : public gcn::Tab int getFlash() { return mFlash; } + void widgetResized(const gcn::Event &event); + + void widgetMoved(const gcn::Event &event); + protected: friend class TabbedArea; virtual void setCurrent() @@ -76,6 +82,9 @@ class Tab : public gcn::Tab const gcn::Color *mTabColor; int mFlash; + GraphicsVertexes *mVertexes; + bool mRedraw; + int mMode; }; #endif diff --git a/src/gui/widgets/window.cpp b/src/gui/widgets/window.cpp index 1037296b6..8c33b4787 100644 --- a/src/gui/widgets/window.cpp +++ b/src/gui/widgets/window.cpp @@ -24,6 +24,7 @@ #include "client.h" #include "configuration.h" +#include "graphicsvertexes.h" #include "log.h" #include "gui/gui.h" @@ -60,7 +61,9 @@ Window::Window(const std::string &caption, bool modal, Window *parent, mMinWinWidth(100), mMinWinHeight(40), mMaxWinWidth(graphics->getWidth()), - mMaxWinHeight(graphics->getHeight()) + mMaxWinHeight(graphics->getHeight()), + mVertexes(new GraphicsVertexes()), + mRedraw(true) { logger->log("Window::Window(\"%s\")", caption.c_str()); @@ -106,6 +109,8 @@ Window::~Window() // need mWidgets.clean ? removeWidgetListener(this); + delete mVertexes; + mVertexes = 0; instances--; @@ -125,7 +130,19 @@ void Window::draw(gcn::Graphics *graphics) Graphics *g = static_cast<Graphics*>(graphics); - g->drawImageRect(0, 0, getWidth(), getHeight(), mSkin->getBorder()); + if (mRedraw) + { + mRedraw = false; + g->calcWindow(mVertexes, 0, 0, getWidth(), + getHeight(), mSkin->getBorder()); + } + + g->drawImageRect2(mVertexes, mSkin->getBorder()); + +/* + g->drawImageRect(0, 0, getWidth(), + getHeight(), mSkin->getBorder()); +*/ // Draw title if (mShowTitle) @@ -303,12 +320,19 @@ void Window::widgetResized(const gcn::Event &event _UNUSED_) getHeight() - mGrip->getHeight() - area.y); } + if (mLayout) { int w = area.width; int h = area.height; mLayout->reflow(w, h); } + mRedraw = true; +} + +void Window::widgetMoved(const gcn::Event& event _UNUSED_) +{ + mRedraw = true; } void Window::widgetHidden(const gcn::Event &event _UNUSED_) diff --git a/src/gui/widgets/window.h b/src/gui/widgets/window.h index 4125f1986..6f856fc62 100644 --- a/src/gui/widgets/window.h +++ b/src/gui/widgets/window.h @@ -37,6 +37,7 @@ #endif class ContainerPlacer; +class GraphicsVertexes; class Layout; class LayoutCell; class ResizeGrip; @@ -114,6 +115,8 @@ class Window : public gcn::Window, gcn::WidgetListener */ void widgetResized(const gcn::Event &event); + virtual void widgetMoved(const gcn::Event& event); + /** * Called whenever the widget is hidden. */ @@ -437,6 +440,8 @@ class Window : public gcn::Window, gcn::WidgetListener * where two borders are moved at the same time. */ static const int resizeBorderWidth = 10; + GraphicsVertexes *mVertexes; + bool mRedraw; }; #endif diff --git a/src/opengl1graphics.cpp b/src/opengl1graphics.cpp index 3dfe06ecf..e1d44de23 100644 --- a/src/opengl1graphics.cpp +++ b/src/opengl1graphics.cpp @@ -20,9 +20,11 @@ * along with this program. If not, see <http://www.gnu.org/licenses/>. */ -#include "log.h" #include "opengl1graphics.h" +#include "graphicsvertexes.h" +#include "log.h" + #include "resources/image.h" #ifdef USE_OPENGL @@ -391,6 +393,29 @@ void OpenGL1Graphics::drawRescaledImagePattern(Image *image, int x, int y, static_cast<GLubyte>(mColor.b), static_cast<GLubyte>(mColor.a)); } +bool OpenGL1Graphics::calcImageRect(GraphicsVertexes* vert, + int x, int y, int w, int h, + Image *topLeft _UNUSED_, + Image *topRight _UNUSED_, + Image *bottomLeft _UNUSED_, + Image *bottomRight _UNUSED_, + Image *top _UNUSED_, Image *right _UNUSED_, + Image *bottom _UNUSED_, + Image *left _UNUSED_, + Image *center _UNUSED_) +{ + vert->init(x, y, w, h); + return true; +} + +void OpenGL1Graphics::drawImageRect2(GraphicsVertexes* vert, const ImageRect &imgRect) +{ + drawImageRect(vert->getX(), vert->getY(), vert->getW(), vert->getH(), + imgRect.grid[0], imgRect.grid[2], imgRect.grid[6], imgRect.grid[8], + imgRect.grid[1], imgRect.grid[5], imgRect.grid[7], imgRect.grid[3], + imgRect.grid[4]); +} + void OpenGL1Graphics::updateScreen() { glFlush(); diff --git a/src/opengl1graphics.h b/src/opengl1graphics.h index 04555e589..0c29ec1ca 100644 --- a/src/opengl1graphics.h +++ b/src/opengl1graphics.h @@ -91,6 +91,16 @@ class OpenGL1Graphics : public Graphics int x, int y, int w, int h, int scaledWidth, int scaledHeight); + bool calcImageRect(GraphicsVertexes* vert, + int x, int y, int w, int h, + Image *topLeft, Image *topRight, + Image *bottomLeft, Image *bottomRight, + Image *top, Image *right, + Image *bottom, Image *left, + Image *center); + + void drawImageRect2(GraphicsVertexes* vert, const ImageRect &imgRect); + void updateScreen(); void _beginDraw(); diff --git a/src/openglgraphics.cpp b/src/openglgraphics.cpp index 302c895d0..f30d20666 100644 --- a/src/openglgraphics.cpp +++ b/src/openglgraphics.cpp @@ -24,8 +24,8 @@ #ifdef USE_OPENGL +#include "graphicsvertexes.h" #include "openglgraphics.h" - #include "log.h" #include "resources/image.h" @@ -617,6 +617,198 @@ void OpenGLGraphics::drawRescaledImagePattern(Image *image, int x, int y, static_cast<GLubyte>(mColor.a)); } +void OpenGLGraphics::drawImagePattern2(GraphicsVertexes *vert, Image *image) +{ + if (!image) + return; + + OpenGLGraphicsVertexes *ogl = vert->getOGL(); + + glColor4f(1.0f, 1.0f, 1.0f, image->mAlpha); + bindTexture(Image::mTextureType, image->mGLImage); + setTexturingAndBlending(true); + + std::vector<GLint*> &intVertPool = ogl->getIntVertPool(); + std::vector<GLint*>::iterator iv; + std::vector<int> &vp = ogl->getVp(); + std::vector<int>::iterator ivp; + + // Draw a set of textured rectangles + if (image->getTextureType() == GL_TEXTURE_2D) + { + std::vector<GLfloat*> &floatTexPool = ogl->getFloatTexPool(); + std::vector<GLfloat*>::iterator ft; + + for (iv = intVertPool.begin(), ft = floatTexPool.begin(), + ivp = vp.begin(); + iv != intVertPool.end(), ft != floatTexPool.end(), + ivp != vp.end(); + ++ iv, ++ ft, ++ ivp) + { + drawQuadArrayfi(*iv, *ft, *ivp); + } + } + else + { + std::vector<GLint*> &intTexPool = ogl->getIntTexPool(); + std::vector<GLint*>::iterator it; + + for (iv = intVertPool.begin(), it = intTexPool.begin(), + ivp = vp.begin(); + iv != intVertPool.end(), it != intTexPool.end(), + ivp != vp.end(); + ++ iv, ++ it, ++ ivp) + { + drawQuadArrayii(*iv, *it, *ivp); + } + } + + glColor4ub(static_cast<GLubyte>(mColor.r), + static_cast<GLubyte>(mColor.g), + static_cast<GLubyte>(mColor.b), + static_cast<GLubyte>(mColor.a)); + +} + +void OpenGLGraphics::calcImagePattern(GraphicsVertexes* vert, Image *image, + int x, int y, int w, int h) +{ + if (!image) + { + vert->incPtr(1); + return; + } + + const int srcX = image->mBounds.x; + const int srcY = image->mBounds.y; + + const int iw = image->getWidth(); + const int ih = image->getHeight(); + + if (iw == 0 || ih == 0) + { + vert->incPtr(1); + return; + } + + const float tw = static_cast<float>(image->getTextureWidth()); + const float th = static_cast<float>(image->getTextureHeight()); + + unsigned int vp = 0; + const unsigned int vLimit = vertexBufSize * 4; + + OpenGLGraphicsVertexes *ogl = vert->getOGL(); + ogl->init(); + + // Draw a set of textured rectangles + if (image->getTextureType() == GL_TEXTURE_2D) + { + float texX1 = static_cast<float>(srcX) / tw; + float texY1 = static_cast<float>(srcY) / th; + + GLfloat *floatTexArray = ogl->switchFloatTexArray(); + GLint *intVertArray = ogl->switchIntVertArray(); + + for (int py = 0; py < h; py += ih) + { + const int height = (py + ih >= h) ? h - py : ih; + const int dstY = y + py; + for (int px = 0; px < w; px += iw) + { + int width = (px + iw >= w) ? w - px : iw; + int dstX = x + px; + + float texX2 = static_cast<float>(srcX + width) / tw; + float texY2 = static_cast<float>(srcY + height) / th; + + floatTexArray[vp + 0] = texX1; + floatTexArray[vp + 1] = texY1; + + floatTexArray[vp + 2] = texX2; + floatTexArray[vp + 3] = texY1; + + floatTexArray[vp + 4] = texX2; + floatTexArray[vp + 5] = texY2; + + floatTexArray[vp + 6] = texX1; + floatTexArray[vp + 7] = texY2; + + intVertArray[vp + 0] = dstX; + intVertArray[vp + 1] = dstY; + + intVertArray[vp + 2] = dstX + width; + intVertArray[vp + 3] = dstY; + + intVertArray[vp + 4] = dstX + width; + intVertArray[vp + 5] = dstY + height; + + intVertArray[vp + 6] = dstX; + intVertArray[vp + 7] = dstY + height; + + vp += 8; + if (vp >= vLimit) + { + floatTexArray = ogl->switchFloatTexArray(); + intVertArray = ogl->switchIntVertArray(); + ogl->switchVp(vp); + vp = 0; + } + } + } + } + else + { + GLint *intTexArray = ogl->switchIntTexArray(); + GLint *intVertArray = ogl->switchIntVertArray(); + + for (int py = 0; py < h; py += ih) + { + const int height = (py + ih >= h) ? h - py : ih; + const int dstY = y + py; + for (int px = 0; px < w; px += iw) + { + int width = (px + iw >= w) ? w - px : iw; + int dstX = x + px; + + intTexArray[vp + 0] = srcX; + intTexArray[vp + 1] = srcY; + + intTexArray[vp + 2] = srcX + width; + intTexArray[vp + 3] = srcY; + + intTexArray[vp + 4] = srcX + width; + intTexArray[vp + 5] = srcY + height; + + intTexArray[vp + 6] = srcX; + intTexArray[vp + 7] = srcY + height; + + intVertArray[vp + 0] = dstX; + intVertArray[vp + 1] = dstY; + + intVertArray[vp + 2] = dstX + width; + intVertArray[vp + 3] = dstY; + + intVertArray[vp + 4] = dstX + width; + intVertArray[vp + 5] = dstY + height; + + intVertArray[vp + 6] = dstX; + intVertArray[vp + 7] = dstY + height; + + vp += 8; + if (vp >= vLimit) + { + intTexArray = ogl->switchIntTexArray(); + intVertArray = ogl->switchIntVertArray(); + ogl->switchVp(vp); + vp = 0; + } + } + } + } + ogl->switchVp(vp); + vert->incPtr(1); +} + void OpenGLGraphics::updateScreen() { glFlush(); @@ -930,6 +1122,15 @@ inline void OpenGLGraphics::drawQuadArrayfi(int size) glDrawArrays(GL_QUADS, 0, size / 2); } +inline void OpenGLGraphics::drawQuadArrayfi(GLint *intVertArray, + GLfloat *floatTexArray, int size) +{ + glVertexPointer(2, GL_INT, 0, intVertArray); + glTexCoordPointer(2, GL_FLOAT, 0, floatTexArray); + + glDrawArrays(GL_QUADS, 0, size / 2); +} + inline void OpenGLGraphics::drawQuadArrayii(int size) { glVertexPointer(2, GL_INT, 0, mIntVertArray); @@ -938,6 +1139,15 @@ inline void OpenGLGraphics::drawQuadArrayii(int size) glDrawArrays(GL_QUADS, 0, size / 2); } +inline void OpenGLGraphics::drawQuadArrayii(GLint *intVertArray, + GLint *intTexArray, int size) +{ + glVertexPointer(2, GL_INT, 0, intVertArray); + glTexCoordPointer(2, GL_INT, 0, intTexArray); + + glDrawArrays(GL_QUADS, 0, size / 2); +} + inline void OpenGLGraphics::drawLineArrayi(int size) { glVertexPointer(2, GL_INT, 0, mIntVertArray); diff --git a/src/openglgraphics.h b/src/openglgraphics.h index 0eaaf0f18..c06f36228 100644 --- a/src/openglgraphics.h +++ b/src/openglgraphics.h @@ -91,6 +91,11 @@ class OpenGLGraphics : public Graphics int x, int y, int w, int h, int scaledWidth, int scaledHeight); + void calcImagePattern(GraphicsVertexes* vert, Image *image, + int x, int y, int w, int h); + + void drawImagePattern2(GraphicsVertexes *vert, Image *image); + void updateScreen(); void _beginDraw(); @@ -115,8 +120,14 @@ class OpenGLGraphics : public Graphics void drawQuadArrayfi(int size); + void drawQuadArrayfi(GLint *intVertArray, GLfloat *floatTexArray, + int size); + void drawQuadArrayii(int size); + void drawQuadArrayii(GLint *intVertArray, GLint *intTexArray, + int size); + void drawLineArrayi(int size); void drawLineArrayf(int size); |