/* _______ __ __ __ ______ __ __ _______ __ __
* / _____/\ / /\ / /\ / /\ / ____/\ / /\ / /\ / ___ /\ / |\/ /\
* / /\____\// / // / // / // /\___\// /_// / // /\_/ / // , |/ / /
* / / /__ / / // / // / // / / / ___ / // ___ / // /| ' / /
* / /_// /\ / /_// / // / // /_/_ / / // / // /\_/ / // / | / /
* /______/ //______/ //_/ //_____/\ /_/ //_/ //_/ //_/ //_/ /|_/ /
* \______\/ \______\/ \_\/ \_____\/ \_\/ \_\/ \_\/ \_\/ \_\/ \_\/
*
* Copyright (c) 2004, 2005, 2006, 2007 Olof Naessén and Per Larsson
*
* Js_./
* Per Larsson a.k.a finalman _RqZ{a<^_aa
* Olof Naessén a.k.a jansem/yakslem _asww7!uY`> )\a//
* _Qhm`] _f "'c 1!5m
* Visit: http://guichan.darkbits.org )Qk
ws?a-?' ._/L #'
* binary forms, with or without )4d[#7r, . ' )d`)[
* modification, are permitted provided _Q-5'5W..j/?' -?!\)cam'
* that the following conditions are met: j<. a J@\
* this list of conditions and the j(]1u
#endif
#if defined (__amigaos4__)
#include
#define glVertex3i glVertex3f
#elif defined(__APPLE__)
#include
#else
#include
#endif
#include "guichan/exception.hpp"
#include "guichan/image.hpp"
#include "guichan/opengl/openglimage.hpp"
namespace gcn
{
OpenGLGraphics::OpenGLGraphics()
{
setTargetPlane(640, 480);
mAlpha = false;
}
OpenGLGraphics::OpenGLGraphics(int width, int height)
{
setTargetPlane(width, height);
}
OpenGLGraphics::~OpenGLGraphics()
{
}
void OpenGLGraphics::_beginDraw()
{
glPushAttrib(
GL_COLOR_BUFFER_BIT |
GL_CURRENT_BIT |
GL_DEPTH_BUFFER_BIT |
GL_ENABLE_BIT |
GL_FOG_BIT |
GL_LIGHTING_BIT |
GL_LINE_BIT |
GL_POINT_BIT |
GL_POLYGON_BIT |
GL_SCISSOR_BIT |
GL_STENCIL_BUFFER_BIT |
GL_TEXTURE_BIT |
GL_TRANSFORM_BIT |
GL_POINT_BIT |
GL_LINE_BIT
);
glMatrixMode(GL_MODELVIEW);
glPushMatrix();
glLoadIdentity();
glMatrixMode(GL_TEXTURE);
glPushMatrix();
glLoadIdentity();
glMatrixMode(GL_PROJECTION);
glPushMatrix();
glLoadIdentity();
glOrtho(0.0, (double)mWidth, (double)mHeight, 0.0, -1.0, 1.0);
glDisable(GL_LIGHTING);
glDisable(GL_CULL_FACE);
glDisable(GL_DEPTH_TEST);
glDisable(GL_TEXTURE_2D);
glEnable(GL_SCISSOR_TEST);
glPointSize(1.0);
glLineWidth(1.0);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
pushClipArea(Rectangle(0, 0, mWidth, mHeight));
}
void OpenGLGraphics::_endDraw()
{
glMatrixMode(GL_MODELVIEW);
glPopMatrix();
glMatrixMode(GL_TEXTURE);
glPopMatrix();
glMatrixMode(GL_PROJECTION);
glPopMatrix();
glPopAttrib();
popClipArea();
}
bool OpenGLGraphics::pushClipArea(Rectangle area)
{
bool result = Graphics::pushClipArea(area);
glScissor(mClipStack.top().x,
mHeight - mClipStack.top().y - mClipStack.top().height,
mClipStack.top().width,
mClipStack.top().height);
return result;
}
void OpenGLGraphics::popClipArea()
{
Graphics::popClipArea();
if (mClipStack.empty())
{
return;
}
glScissor(mClipStack.top().x,
mHeight - mClipStack.top().y - mClipStack.top().height,
mClipStack.top().width,
mClipStack.top().height);
}
void OpenGLGraphics::setTargetPlane(int width, int height)
{
mWidth = width;
mHeight = height;
}
void OpenGLGraphics::drawImage(const Image* image, int srcX, int srcY,
int dstX, int dstY, int width,
int height)
{
const OpenGLImage* srcImage = dynamic_cast(image);
if (srcImage == NULL)
{
throw GCN_EXCEPTION("Trying to draw an image of unknown format, must be an OpenGLImage.");
}
dstX += mClipStack.top().xOffset;
dstY += mClipStack.top().yOffset;
// Find OpenGL texture coordinates
float texX1 = srcX / (float)srcImage->getTextureWidth();
float texY1 = srcY / (float)srcImage->getTextureHeight();
float texX2 = (srcX+width) / (float)srcImage->getTextureWidth();
float texY2 = (srcY+height) / (float)srcImage->getTextureHeight();
glBindTexture(GL_TEXTURE_2D, srcImage->getTextureHandle());
glEnable(GL_TEXTURE_2D);
// Check if blending already is enabled
if (!mAlpha)
{
glEnable(GL_BLEND);
}
// Draw a textured quad -- the image
glBegin(GL_QUADS);
glTexCoord2f(texX1, texY1);
glVertex3i(dstX, dstY, 0);
glTexCoord2f(texX1, texY2);
glVertex3i(dstX, dstY + height, 0);
glTexCoord2f(texX2, texY2);
glVertex3i(dstX + width, dstY + height, 0);
glTexCoord2f(texX2, texY1);
glVertex3i(dstX + width, dstY, 0);
glEnd();
glDisable(GL_TEXTURE_2D);
// Don't disable blending if the color has alpha
if (!mAlpha)
{
glDisable(GL_BLEND);
}
}
void OpenGLGraphics::drawPoint(int x, int y)
{
x += mClipStack.top().xOffset;
y += mClipStack.top().yOffset;
glBegin(GL_POINTS);
glVertex3i(x, y, 0);
glEnd();
}
void OpenGLGraphics::drawLine(int x1, int y1, int x2, int y2)
{
x1 += mClipStack.top().xOffset;
y1 += mClipStack.top().yOffset;
x2 += mClipStack.top().xOffset;
y2 += mClipStack.top().yOffset;
glBegin(GL_LINES);
glVertex3f(x1+0.5f, y1+0.5f, 0);
glVertex3f(x2+0.5f, y2+0.5f, 0);
glEnd();
glBegin(GL_POINTS);
glVertex3f(x2+0.5f, y2+0.5f, 0);
glEnd();
}
void OpenGLGraphics::drawRectangle(const Rectangle& rectangle)
{
glBegin(GL_LINE_LOOP);
glVertex3f(rectangle.x + mClipStack.top().xOffset + 0.5f,
rectangle.y + mClipStack.top().yOffset + 0.5f, 0);
glVertex3f(rectangle.x + rectangle.width - 0.5f + mClipStack.top().xOffset,
rectangle.y + mClipStack.top().yOffset + 0.5f, 0);
glVertex3f(rectangle.x + rectangle.width - 0.5f + mClipStack.top().xOffset,
rectangle.y + rectangle.height + mClipStack.top().yOffset - 0.5f, 0);
glVertex3f(rectangle.x + mClipStack.top().xOffset + 0.5f,
rectangle.y + rectangle.height + mClipStack.top().yOffset - 0.5f, 0);
glEnd();
}
void OpenGLGraphics::fillRectangle(const Rectangle& rectangle)
{
glBegin(GL_QUADS);
glVertex3i(rectangle.x + mClipStack.top().xOffset,
rectangle.y + mClipStack.top().yOffset, 0);
glVertex3i(rectangle.x + rectangle.width + mClipStack.top().xOffset,
rectangle.y + mClipStack.top().yOffset, 0);
glVertex3i(rectangle.x + rectangle.width + mClipStack.top().xOffset,
rectangle.y + rectangle.height + mClipStack.top().yOffset, 0);
glVertex3i(rectangle.x + mClipStack.top().xOffset,
rectangle.y + rectangle.height + mClipStack.top().yOffset, 0);
glEnd();
}
void OpenGLGraphics::setColor(const Color& color)
{
mColor = color;
glColor4ub(color.r, color.g, color.b, color.a);
mAlpha = color.a != 255;
if (mAlpha)
{
glEnable(GL_BLEND);
}
}
const Color& OpenGLGraphics::getColor()
{
return mColor;
}
}