diff options
author | Bertram <bertram@cegetel.net> | 2009-07-27 01:02:27 +0200 |
---|---|---|
committer | Bertram <bertram@cegetel.net> | 2009-07-27 01:02:27 +0200 |
commit | fa1a3ab995f037ddf33817a1b2ce143130a457f8 (patch) | |
tree | 4cfc52364c271a9a318a2fee4b611514d7941476 | |
parent | 7bc30f545784b26594803b559f1d76d5434027ea (diff) | |
download | mana-fa1a3ab995f037ddf33817a1b2ce143130a457f8.tar.gz mana-fa1a3ab995f037ddf33817a1b2ce143130a457f8.tar.bz2 mana-fa1a3ab995f037ddf33817a1b2ce143130a457f8.tar.xz mana-fa1a3ab995f037ddf33817a1b2ce143130a457f8.zip |
Added the ability to ask a ambient layer to keep its ratio when the resolution isn't the default.
You'll have to add this in map properties, for instance if you're want to keep ratio on overlay 0:
<map version="1.0" orientation="orthogonal" width="128" height="128" tilewidth="32" tileheight="32">
<properties>
...
<property name="overlay0keepratio" value="true"/>
...
</properties>
</map>
-rw-r--r-- | src/graphics.cpp | 42 | ||||
-rw-r--r-- | src/graphics.h | 10 | ||||
-rw-r--r-- | src/main.cpp | 3 | ||||
-rw-r--r-- | src/map.cpp | 3 | ||||
-rw-r--r-- | src/openglgraphics.cpp | 43 | ||||
-rw-r--r-- | src/openglgraphics.h | 7 | ||||
-rw-r--r-- | src/properties.h | 20 | ||||
-rw-r--r-- | src/resources/ambientoverlay.cpp | 42 | ||||
-rw-r--r-- | src/resources/ambientoverlay.h | 5 |
9 files changed, 165 insertions, 10 deletions
diff --git a/src/graphics.cpp b/src/graphics.cpp index b84e0bf6..75db11f4 100644 --- a/src/graphics.cpp +++ b/src/graphics.cpp @@ -221,6 +221,48 @@ void Graphics::drawImagePattern(Image *image, int x, int y, int w, int h) } } +void Graphics::drawRescaledImagePattern(Image *image, int x, int y, + int w, int h, int scaledWidth, int scaledHeight) +{ + // Check that preconditions for blitting are met. + if (!mScreen || !image) return; + if (!image->mImage) return; + + if (scaledHeight == 0 || scaledWidth == 0) return; + + Image *tmpImage = image->SDLgetScaledImage(scaledWidth, scaledHeight); + if (!tmpImage) return; + + const int iw = tmpImage->getWidth(); + const int ih = tmpImage->getHeight(); + + if (iw == 0 || ih == 0) return; + + for (int py = 0; py < h; py += ih) // Y position on pattern plane + { + int dh = (py + ih >= h) ? h - py : ih; + int srcY = tmpImage->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 = tmpImage->mBounds.x; + int dstX = x + px + mClipStack.top().xOffset; + + SDL_Rect dstRect; + SDL_Rect srcRect; + dstRect.x = dstX; dstRect.y = dstY; + srcRect.x = srcX; srcRect.y = srcY; + srcRect.w = dw; srcRect.h = dh; + + SDL_BlitSurface(tmpImage->mImage, &srcRect, mScreen, &dstRect); + } + } + + delete tmpImage; +} + void Graphics::drawImageRect(int x, int y, int w, int h, Image *topLeft, Image *topRight, Image *bottomLeft, Image *bottomRight, diff --git a/src/graphics.h b/src/graphics.h index eca7e1a5..b8e87af1 100644 --- a/src/graphics.h +++ b/src/graphics.h @@ -29,6 +29,9 @@ class ImageRect; struct SDL_Surface; +static const int defaultScreenWidth = 800; +static const int defaultScreenHeight = 600; + /** * 9 images defining a rectangle. 4 corners, 4 sides and a middle area. The * topology is as follows: @@ -143,6 +146,13 @@ class Graphics : public gcn::SDLGraphics int w, int h); /** + * Draw a pattern based on a rescaled version of the given image... + */ + virtual void drawRescaledImagePattern(Image *image, + int x, int y, int w, int h, + int scaledWidth, int scaledHeight); + + /** * Draws a rectangle using images. 4 corner images, 4 side images and 1 * image for the inside. */ diff --git a/src/main.cpp b/src/main.cpp index 6dd6ba6b..10145dfc 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -143,9 +143,6 @@ namespace } listener; } -static const int defaultScreenWidth = 800; -static const int defaultScreenHeight = 600; - static const int defaultSfxVolume = 100; static const int defaultMusicVolume = 60; diff --git a/src/map.cpp b/src/map.cpp index 61fcdfe8..38c49112 100644 --- a/src/map.cpp +++ b/src/map.cpp @@ -218,11 +218,12 @@ void Map::initializeOverlays() const float speedX = getFloatProperty(name + "scrollX"); const float speedY = getFloatProperty(name + "scrollY"); const float parallax = getFloatProperty(name + "parallax"); + const bool keepRatio = getBoolProperty(name + "keepratio"); if (img) { mOverlays.push_back( - new AmbientOverlay(img, parallax, speedX, speedY)); + new AmbientOverlay(img, parallax, speedX, speedY, keepRatio)); // The AmbientOverlay takes control over the image. img->decRef(); diff --git a/src/openglgraphics.cpp b/src/openglgraphics.cpp index 5c9e2049..4d66a919 100644 --- a/src/openglgraphics.cpp +++ b/src/openglgraphics.cpp @@ -277,6 +277,49 @@ void OpenGLGraphics::drawImagePattern(Image *image, int x, int y, int w, int h) glColor4ub(mColor.r, mColor.g, mColor.b, mColor.a); } +void OpenGLGraphics::drawRescaledImagePattern(Image *image, int x, int y, + int w, int h, + int scaledWidth, int scaledHeight) +{ + if (!image) + return; + + const int srcX = image->mBounds.x; + const int srcY = image->mBounds.y; + + const int iw = scaledWidth; + const int ih = scaledHeight; + if (iw == 0 || ih == 0) + return; + + glColor4f(1.0f, 1.0f, 1.0f, image->mAlpha); + + glBindTexture(Image::mTextureType, image->mGLImage); + + setTexturingAndBlending(true); + + // Draw a set of textured rectangles + glBegin(GL_QUADS); + + 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; + + drawRescaledQuad(image, srcX, srcY, dstX, dstY, + width, height, scaledWidth, scaledHeight); + } + } + + glEnd(); + + glColor4ub(mColor.r, mColor.g, mColor.b, mColor.a); +} + void OpenGLGraphics::updateScreen() { glFlush(); diff --git a/src/openglgraphics.h b/src/openglgraphics.h index 3553cac3..0bee48b4 100644 --- a/src/openglgraphics.h +++ b/src/openglgraphics.h @@ -59,6 +59,13 @@ class OpenGLGraphics : public Graphics int x, int y, int w, int h); + /** + * Draw a pattern based on a rescaled version of the given image... + */ + void drawRescaledImagePattern(Image *image, + int x, int y, int w, int h, + int scaledWidth, int scaledHeight); + void updateScreen(); void _beginDraw(); diff --git a/src/properties.h b/src/properties.h index a2ce5b88..75335377 100644 --- a/src/properties.h +++ b/src/properties.h @@ -74,6 +74,26 @@ class Properties } /** + * Gets a map property as a boolean. + * + * @param name The name of the property. + * @param def Default value, false by default. + * @return the value of the given property, or false when it doesn't + * exist. + */ + float getBoolProperty(const std::string &name, bool def = false) const + { + PropertyMap::const_iterator i = mProperties.find(name); + bool ret = def; + if (i != mProperties.end()) + { + if (i->second == "true") + ret = true; + } + return ret; + } + + /** * Returns whether a certain property is available. * * @param name The name of the property. diff --git a/src/resources/ambientoverlay.cpp b/src/resources/ambientoverlay.cpp index 93c7c3e1..8c851e2e 100644 --- a/src/resources/ambientoverlay.cpp +++ b/src/resources/ambientoverlay.cpp @@ -22,16 +22,41 @@ #include "resources/ambientoverlay.h" #include "resources/image.h" - +#include "resources/resourcemanager.h" #include "graphics.h" AmbientOverlay::AmbientOverlay(Image *img, float parallax, - float speedX, float speedY): + float speedX, float speedY, bool keepRatio): mImage(img), mParallax(parallax), mPosX(0), mPosY(0), - mSpeedX(speedX), mSpeedY(speedY) + mSpeedX(speedX), mSpeedY(speedY), + mKeepRatio(keepRatio) { - mImage->incRef(); + + if (keepRatio && !mImage->isAnOpenGLOne() + && defaultScreenWidth != 0 + && defaultScreenHeight != 0 + && graphics->getWidth() != defaultScreenWidth + && graphics->getHeight() != defaultScreenHeight) + { + // Rescale the overlay to keep the ratio as if we were on + // the default resolution... + Image *rescaledOverlay = mImage->SDLgetScaledImage( + (int) mImage->getWidth() / defaultScreenWidth * graphics->getWidth(), + (int) mImage->getHeight() / defaultScreenHeight * graphics->getHeight()); + + if (rescaledOverlay) + { + // Replace the resource with the new one... + std::string idPath = mImage->getIdPath() + "_rescaled"; + ResourceManager::getInstance()->addResource(idPath, rescaledOverlay); + mImage = rescaledOverlay; + } + else + mImage->incRef(); + } + else + mImage->incRef(); } AmbientOverlay::~AmbientOverlay() @@ -66,6 +91,13 @@ void AmbientOverlay::update(int timePassed, float dx, float dy) void AmbientOverlay::draw(Graphics *graphics, int x, int y) { - graphics->drawImagePattern(mImage, + if (!mImage->isAnOpenGLOne() || !mKeepRatio) + graphics->drawImagePattern(mImage, (int) -mPosX, (int) -mPosY, x + (int) mPosX, y + (int) mPosY); + else + graphics->drawRescaledImagePattern(mImage, + (int) -mPosX, (int) -mPosY, x + (int) mPosX, y + (int) mPosY, + (int) mImage->getWidth() / defaultScreenWidth * graphics->getWidth(), + (int) mImage->getHeight() / defaultScreenHeight * graphics->getHeight()); + } diff --git a/src/resources/ambientoverlay.h b/src/resources/ambientoverlay.h index 756d0eb7..f2d2e588 100644 --- a/src/resources/ambientoverlay.h +++ b/src/resources/ambientoverlay.h @@ -35,9 +35,11 @@ class AmbientOverlay * @param parallax scroll factor based on camera position * @param speedX scrolling speed in x-direction * @param speedY scrolling speed in y-direction + * @param keepRatio rescale the image to keep + * the same ratio than in 800x600 resolution mode. */ AmbientOverlay(Image *img, float parallax, - float speedX, float speedY); + float speedX, float speedY, bool keepRatio = false); ~AmbientOverlay(); @@ -52,6 +54,7 @@ class AmbientOverlay float mPosY; /**< Current layer Y position. */ float mSpeedX; /**< Scrolling speed in X direction. */ float mSpeedY; /**< Scrolling speed in Y direction. */ + bool mKeepRatio; /**< Keep overlay ratio on every resolution */ }; #endif |