zengine/src/ZE_ZImage.cpp

410 lines
10 KiB
C++
Raw Normal View History

/*******************************************************************************
2002-12-29 06:50:19 +00:00
This file is Part of the ZEngine Library for 2D game development.
Copyright (C) 2002, 2003 James Turk
2002-12-29 06:50:19 +00:00
Licensed under a BSD-style license.
The maintainer of this library is James Turk (james@conceptofzero.net)
2002-12-29 06:50:19 +00:00
and the home of this Library is http://www.zengine.sourceforge.net
*******************************************************************************/
2002-12-29 07:09:44 +00:00
2003-05-07 20:34:50 +00:00
/**
\file ZE_ZImage.cpp
\brief Source file for ZImage.
Implementation of ZImage, the Image class for ZEngine.
2003-08-07 05:54:45 +00:00
<br>$Id: ZE_ZImage.cpp,v 1.40 2003/08/07 05:54:45 cozman Exp $<br>
2003-05-07 20:34:50 +00:00
\author James Turk
**/
#include "ZE_ZImage.h"
namespace ZE
{
2003-06-11 05:51:15 +00:00
ZImage::ZImage() :
rEngine(ZEngine::GetInstance()),
rImage(NULL),
rAlpha(255)
{
Release();
}
2003-06-11 05:51:15 +00:00
ZImage::ZImage(const ZImage &rhs) :
rEngine(ZEngine::GetInstance()),
rImage(NULL),
rAlpha(rhs.Alpha())
2003-01-24 02:47:06 +00:00
{
OpenFromImage(rhs.Surface(),0,0,(Sint16)rhs.Width(),(Sint16)rhs.Height());
}
2003-06-11 05:51:15 +00:00
ZImage::ZImage(std::string filename) :
rEngine(ZEngine::GetInstance()),
rImage(NULL),
rAlpha(255)
{
Open(filename);
}
2003-06-11 05:51:15 +00:00
ZImage::ZImage(SDL_Surface *surface) :
rEngine(ZEngine::GetInstance()),
rImage(NULL),
rAlpha(255)
{
Attach(surface);
}
2003-06-11 05:51:15 +00:00
ZImage::ZImage(SDL_Surface *img, Sint16 x, Sint16 y, Sint16 w, Sint16 h) :
rEngine(ZEngine::GetInstance()),
rImage(NULL),
rAlpha(255)
{
OpenFromImage(img,x,y,w,h);
}
2003-06-11 05:51:15 +00:00
ZImage::ZImage(const ZImage &img, Sint16 x, Sint16 y, Sint16 w, Sint16 h) :
rEngine(ZEngine::GetInstance()),
rImage(NULL),
rAlpha(255)
{
OpenFromImage(img.Surface(),x,y,w,h); //call SDL_Surface* version instead of taking the long way
}
ZImage::~ZImage()
{
Release();
}
2003-06-11 00:15:07 +00:00
void ZImage::Open(std::string filename)
{
SDL_Surface *image;
image = rEngine->LoadImage(filename.c_str());
Attach(image);
}
void ZImage::OpenFromImage(SDL_Surface *image, Sint16 x, Sint16 y, Sint16 w, Sint16 h)
{
SDL_Surface *screen = rEngine->Display();
SDL_Surface *cutImg = NULL;
SDL_Rect rect;
SDL_VideoInfo *videoInfo;
//either set hardware or software surface//
videoInfo = const_cast<SDL_VideoInfo*>(SDL_GetVideoInfo());
rect.x = x;
rect.y = y;
rect.w = w;
rect.h = h;
if(!image)
2003-01-13 06:00:38 +00:00
rEngine->ReportError(ZERR_NOIMAGE,"OpenFromImage");
2003-07-11 20:51:44 +00:00
cutImg = SDL_CreateRGBSurface(0, rect.w, rect.h, rEngine->DisplayDepth(),
screen->format->Rmask, screen->format->Gmask, screen->format->Bmask, screen->format->Amask);
if(!cutImg)
2003-01-13 06:00:38 +00:00
rEngine->ReportError(ZERR_SDL_INTERNAL,FormatStr("SDL_CreateRGBSurface failed in ZImage::OpenFromImage: %s.",SDL_GetError()));
SDL_BlitSurface(image,&rect,cutImg,NULL);
Attach(cutImg);
}
void ZImage::OpenFromImage(const ZImage &img, Sint16 x, Sint16 y, Sint16 w, Sint16 h)
{
OpenFromImage(img.Surface(),x,y,w,h);
}
2003-08-02 01:18:45 +00:00
#if (GFX_BACKEND == ZE_OGL)
2003-08-01 21:56:58 +00:00
2003-06-11 05:51:15 +00:00
//attach is really the core of ZImage, everything calls it, it converts SDL_Surface->OpenGL Texture->ZImage
void ZImage::Attach(SDL_Surface *surface)
{
GLfloat coord[4];
2003-06-11 05:51:15 +00:00
Release(); //avoid most user inflicted memory leaks associated with ZImage
2003-01-24 10:27:42 +00:00
//surface conversion//
SDL_Surface *temp = surface;
2003-06-11 05:51:15 +00:00
surface = SDL_DisplayFormatAlpha(temp); //TTF_RenderTextBlended relys on this
2003-01-24 10:27:42 +00:00
if(surface)
{
FreeImage(temp);
}
else //can't convert
{
rEngine->ReportError(ZERR_SDL_INTERNAL,FormatStr("SDL_DisplayFormatAlpha failed in ZImage::Attach: %s",SDL_GetError()));
surface = temp;
}
if(surface)
{
rWidth = surface->w;
rHeight = surface->h;
2003-07-05 00:40:44 +00:00
rTexID = SDL_GL_LoadTexture(surface,coord); //major helper, not written by me, from libsdl.org
2002-12-02 05:18:52 +00:00
rTexMinX = coord[0];
rTexMinY = coord[1];
rTexMaxX = coord[2];
rTexMaxY = coord[3];
rImage = surface;
}
else
2003-01-13 06:00:38 +00:00
rEngine->ReportError(ZERR_NOIMAGE,"Attach");
}
2002-12-27 18:56:17 +00:00
void ZImage::Reload()
{
2003-06-11 05:51:15 +00:00
//this little hack helps to reload images to OpenGL surfaces after loss
2002-12-27 18:56:17 +00:00
SDL_Surface *temp = rImage;
2003-06-11 05:51:15 +00:00
rImage = NULL;
2002-12-27 18:56:17 +00:00
Attach(temp);
}
void ZImage::Release()
{
2003-06-11 05:51:15 +00:00
//set everything back the way it came
if(glIsTexture(rTexID))
glDeleteTextures(1,&rTexID);
2002-12-02 05:18:52 +00:00
rTexMinX = rTexMinY = rTexMaxX = rTexMaxY = 0.0f;
rTexID = rWidth = rHeight = 0;
FreeImage(rImage);
}
2003-01-25 19:56:05 +00:00
void ZImage::SetAlpha(Uint8 alpha)
{
rAlpha = alpha;
}
void ZImage::SetColorKey(Uint8 red, Uint8 green, Uint8 blue)
{
Uint32 color = SDL_MapRGB(rImage->format,red,green,blue);
if(rImage)
{
if(SDL_SetColorKey(rImage, SDL_SRCCOLORKEY, color) < 0)
2003-01-13 06:00:38 +00:00
rEngine->ReportError(ZERR_SDL_INTERNAL,FormatStr("SDL_SetColorKey failed in ZImage::SetColorKey: %s",SDL_GetError()));
else
2003-06-11 05:51:15 +00:00
Reload(); //do the reattach hack, this gets a new OpenGL surface for the same image
}
else
2003-01-24 10:27:42 +00:00
rEngine->ReportError(ZERR_NOIMAGE,"SetColorKey");
}
void ZImage::Draw(int x, int y) const
{
2003-08-07 05:54:45 +00:00
Draw(x,y);
}
2003-01-16 05:45:58 +00:00
void ZImage::Draw(float x, float y) const
{
2003-06-11 05:51:15 +00:00
glColor4ub(255,255,255,rAlpha); //sets the color correctly
Bind();
2003-06-11 05:51:15 +00:00
glBegin(GL_TRIANGLE_STRIP); //triangle strips, speedier?
2002-12-02 05:18:52 +00:00
glTexCoord2f(rTexMinX,rTexMinY); glVertex2f(x,y);
glTexCoord2f(rTexMaxX,rTexMinY); glVertex2f(x+rWidth,y);
glTexCoord2f(rTexMinX,rTexMaxY); glVertex2f(x,y+rHeight);
glTexCoord2f(rTexMaxX,rTexMaxY); glVertex2f(x+rWidth,y+rHeight);
2002-12-02 00:36:35 +00:00
glEnd();
2003-06-11 05:51:15 +00:00
glColor4ub(255,255,255,255); //be responsible, return to standard color state
2002-12-02 00:36:35 +00:00
}
2003-01-16 05:45:58 +00:00
void ZImage::DrawRotated(int x, int y, float angle) const
{
DrawRotated(static_cast<float>(x),static_cast<float>(y),angle);
}
void ZImage::DrawRotated(float x, float y, float angle) const
2002-12-02 00:36:35 +00:00
{
2003-06-11 05:51:15 +00:00
//center point
float cX,cY;
2002-12-02 00:36:35 +00:00
cX = rWidth/2.0f;
cY = rHeight/2.0f;
glPushMatrix();
2003-06-11 05:51:15 +00:00
glTranslatef(x+cX,y+cY,0); //translate to center
glRotatef(angle,0,0,1.0f); //rotate on z axis, to keep x&y parallel to 2D plane
glColor4ub(255,255,255,rAlpha);
2002-12-02 00:36:35 +00:00
Bind();
2003-06-11 05:51:15 +00:00
//draw is modified to be based around center//
2002-12-02 00:36:35 +00:00
glBegin(GL_TRIANGLE_STRIP);
glTexCoord2f(rTexMinX,rTexMinY); glVertex2f(-cX,-cY);
glTexCoord2f(rTexMaxX,rTexMinY); glVertex2f(-cX+rWidth,-cY);
glTexCoord2f(rTexMinX,rTexMaxY); glVertex2f(-cX,-cY+rHeight);
glTexCoord2f(rTexMaxX,rTexMaxY); glVertex2f(-cX+rWidth,-cY+rHeight);
glEnd();
2002-12-02 00:36:35 +00:00
glPopMatrix();
}
2003-08-01 21:56:58 +00:00
void ZImage::Flip(bool horizontal, bool vertical)
{
GLfloat temp;
//all that a flip does is invert the Min/Max coordinates
if(horizontal)
{
temp = rTexMinX;
rTexMinX = rTexMaxX;
rTexMaxX = temp;
}
if(vertical)
{
temp = rTexMinY;
rTexMinY = rTexMaxY;
rTexMaxY = temp;
}
}
//stretching and resizing is very inexpensive, done via variables
void ZImage::Stretch(float xFactor, float yFactor)
{
2003-08-07 05:54:45 +00:00
rWidth = xFactor*rWidth;
rHeight = yFactor*rHeight;
2003-08-01 21:56:58 +00:00
}
2003-08-07 05:54:45 +00:00
void ZImage::Resize(float width, float height)
2003-08-01 21:56:58 +00:00
{
rWidth = width;
rHeight = height;
}
//this is available for other uses of ZEngine
void ZImage::Bind() const
{
if(rTexID)
glBindTexture(GL_TEXTURE_2D, rTexID);
else
rEngine->ReportError(ZERR_NOIMAGE,"Bind");
}
2003-01-16 05:45:58 +00:00
bool ZImage::IsLoaded() const
{
return glIsTexture(rTexID) == GL_TRUE;
}
2003-08-02 01:18:45 +00:00
#elif (GFX_BACKEND == ZE_SDL)
2003-08-01 21:56:58 +00:00
void ZImage::Attach(SDL_Surface *surface)
{
Release();
//surface conversion//
SDL_Surface *temp = surface;
surface = SDL_DisplayFormatAlpha(temp); //TTF_RenderTextBlended relys on this
if(surface)
{
FreeImage(temp);
}
else //can't convert
{
rEngine->ReportError(ZERR_SDL_INTERNAL,FormatStr("SDL_DisplayFormatAlpha failed in ZImage::Attach: %s",SDL_GetError()));
surface = temp;
}
if(surface)
rImage = surface;
else
rEngine->ReportError(ZERR_NOIMAGE,"Attach");
}
void ZImage::Reload()
{
//currently a no-op
}
void ZImage::Release()
{
FreeImage(rImage);
}
void ZImage::SetAlpha(Uint8 alpha)
{
rAlpha = alpha;
if(rImage)
{
if(SDL_SetAlpha(rImage, SDL_SRCALPHA, alpha) < 0)
rEngine->ReportError(ZERR_SDL_INTERNAL,FormatStr("SDL_SetAlpha failed in ZImage::SetAlpha: %s",SDL_GetError()));
}
else
rEngine->ReportError(ZERR_NOIMAGE,"SetAlpha");
}
void ZImage::SetColorKey(Uint8 red, Uint8 green, Uint8 blue)
{
Uint32 color = SDL_MapRGBA(rImage->format,red,green,blue,255);
if(rImage)
{
if(SDL_SetColorKey(rImage, SDL_RLEACCEL|SDL_SRCCOLORKEY, color) < 0)
rEngine->ReportError(ZERR_SDL_INTERNAL,FormatStr("SDL_SetColorKey failed in ZImage::SetColorKey: %s",SDL_GetError()));
//surface conversion//
SDL_Surface *temp = rImage;
rImage = SDL_DisplayFormatAlpha(temp); //TTF_RenderTextBlended relys on this
if(rImage)
{
FreeImage(temp);
}
else //can't convert
{
rEngine->ReportError(ZERR_SDL_INTERNAL,FormatStr("SDL_DisplayFormatAlpha failed in ZImage::SetColorKey: %s",SDL_GetError()));
rImage = temp;
}
}
else
rEngine->ReportError(ZERR_NOIMAGE,"SetColorKey");
}
void ZImage::Draw(int x, int y) const
{
SDL_Rect rect;
rect.x = static_cast<Sint16>(x);
rect.y = static_cast<Sint16>(y);
SDL_BlitSurface(rImage, NULL, rEngine->Display(), &rect);
}
bool ZImage::IsLoaded() const
{
return rImage ? true : false;
}
#endif //GFX_BACKEND
2003-01-16 05:45:58 +00:00
SDL_Surface* ZImage::Surface() const
{
return rImage;
}
2003-08-07 05:54:45 +00:00
#if (GFX_BACKEND == ZE_OGL)
float ZImage::Width() const
{
return rWidth;
}
float ZImage::Height() const
{
return rHeight;
}
#elif (GFX_BACKEND == ZE_SDL)
2003-01-16 05:45:58 +00:00
int ZImage::Width() const
{
2003-08-01 21:56:58 +00:00
return rImage->w;
}
2003-01-16 05:45:58 +00:00
int ZImage::Height() const
{
2003-08-01 21:56:58 +00:00
return rImage->h;
}
2003-08-07 05:54:45 +00:00
#endif //GFX_BACKEND
2003-01-25 19:56:05 +00:00
Uint8 ZImage::Alpha() const
{
return rAlpha;
}
}