/*******************************************************************************
This file is Part of the ZEngine Library for SDL Game Development.
Copyright (C) 2002 ConceptOfZero.net
Licensed under the BSD License, see licensing.txt.
The maintainer of this library is James Turk (james@conceptofzero.net)
and the home of this Library is http://www.conceptofzero.net/
*******************************************************************************/
/*!
\par File Header:
File: ZE_ZEngine.cpp
Description: Implementation source file for ZEngine library main singleton class.
Author(s): James Turk
$Id: ZE_ZEngine.cpp,v 1.6 2002/12/05 00:10:42 cozman Exp $
\file ZE_ZEngine.cpp
\brief Central source file for ZEngine.
Actual implementation of ZEngine singleton class at heart of ZEngine.
**/
#include "ZE_ZEngine.h"
namespace ZE
{
ZEngine *ZEngine::sInstance=NULL;
ZEngine::ZEngine()
{
mWidth = 640;
mHeight = 480;
mBPP = 16;
mFullscreen = true;
#ifdef USE_SDL_MIXER
mRate = 22050;
mStereo = false;
#endif
mScreen = NULL;
mActive = mQuit = false;
mKeyIsPressed = NULL;
mMouseX = mMouseY = 0;
mMouseB = 0;
for(int k = 0; k < SDLK_LAST; k++)
mKeyPress[k] = false;
mUnpauseOnActive = mPaused = false;
mLastPause = mPausedTime = mLastTime = 0;
mSecPerFrame = 0.0;
}
ZEngine* ZEngine::GetInstance()
{
if(!sInstance)
sInstance = new ZEngine;
return sInstance;
}
void ZEngine::ReleaseInstance()
{
if(sInstance)
{
sInstance->CloseDisplay();
delete sInstance;
}
sInstance = NULL;
}
string ZEngine::GetVersion()
{
return VERSION;
}
void ZEngine::SetupDisplay(int width, int height, int bpp, bool fullscreen)
{
mWidth = width;
mHeight = height;
mBPP = bpp;
mFullscreen = fullscreen;
}
#ifdef USE_SDL_MIXER
void ZEngine::SetupSound(int rate, bool stereo)
{
mRate = rate;
mStereo = stereo;
}
#endif
void ZEngine::CreateDisplay(string title, string icon)
{
Uint32 flags;
SDL_Surface *iconImg;
int rgb_size[3];
if(SDL_Init(SDL_INIT_VIDEO|SDL_INIT_TIMER|SDL_INIT_AUDIO) < 0)
{
LogError(FormatStr("SDL could not be Initialized: %s", SDL_GetError()));
CloseDisplay();
}
#ifdef USE_SDL_MIXER
Mix_OpenAudio(mRate, AUDIO_S16SYS, mStereo?2:1, 4096); //Open Audio Stream (Stereo?2:1 is conditional for number of channels)
#endif
switch (mBPP)
{
case 8:
rgb_size[0] = 3;
rgb_size[1] = 3;
rgb_size[2] = 2;
break;
case 15:
case 16:
rgb_size[0] = 5;
rgb_size[1] = 5;
rgb_size[2] = 5;
break;
default:
rgb_size[0] = 8;
rgb_size[1] = 8;
rgb_size[2] = 8;
break;
}
SDL_GL_SetAttribute(SDL_GL_RED_SIZE, rgb_size[0]);
SDL_GL_SetAttribute(SDL_GL_GREEN_SIZE, rgb_size[1]);
SDL_GL_SetAttribute(SDL_GL_BLUE_SIZE, rgb_size[2]);
SDL_GL_SetAttribute(SDL_GL_DEPTH_SIZE, mBPP);
SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1);
SDL_GL_SetAttribute(SDL_GL_STENCIL_SIZE, 0);
SDL_GL_SetAttribute(SDL_GL_ACCUM_RED_SIZE, 0);
SDL_GL_SetAttribute(SDL_GL_ACCUM_GREEN_SIZE, 0);
SDL_GL_SetAttribute(SDL_GL_ACCUM_BLUE_SIZE, 0);
SDL_GL_SetAttribute(SDL_GL_ACCUM_ALPHA_SIZE, 0);
flags = SDL_OPENGL;
//Window Manager settings//
SDL_EnableKeyRepeat(30,30);
if(!icon.length())
SDL_WM_SetCaption(title.c_str(),NULL);
else
{
SDL_WM_SetCaption(title.c_str(),icon.c_str());
iconImg = LoadImage(icon);
SDL_WM_SetIcon(iconImg,NULL);
FreeImage(iconImg);
}
//create SDL screen and update settings based on returned screen//
if(mFullscreen)
flags |= SDL_FULLSCREEN;
mScreen = SDL_SetVideoMode(mWidth, mHeight, mBPP, flags);
if(!mScreen)
{
LogError(FormatStr("Unable to set video mode %dx%d (%dBpp): %s",mWidth,mHeight,mBPP,SDL_GetError()));
CloseDisplay();
}
mWidth = mScreen->w;
mHeight = mScreen->h;
mBPP = mScreen->format->BitsPerPixel;
SetGL2D();
mKeyIsPressed = SDL_GetKeyState(NULL);
#ifdef USE_SDL_TTF
TTF_Init();
#endif
mLastTime = mPausedTime = SDL_GetTicks();
mActive = true;
}
void ZEngine::CloseDisplay()
{
#ifdef USE_SDL_TTF
TTF_Quit();
#endif
#ifdef USE_SDL_MIXER
Mix_CloseAudio();
#endif
#ifdef USE_PHYSFS
PHYSFS_deinit();
#endif
SDL_Quit();
}
SDL_Surface *ZEngine::Display()
{
return mScreen;
}
void ZEngine::UpdateScreen()
{
SDL_GL_SwapBuffers();
mSecPerFrame = (GetTime()-mLastTime)/1000.0;
mLastTime = GetTime();
}
void ZEngine::Clear(float red, float green, float blue, float alpha)
{
glClearColor(red,green,blue,alpha);
glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT);
glLoadIdentity();
}
void ZEngine::SetGL2D()
{
glPushAttrib(GL_ENABLE_BIT);
glDisable(GL_DEPTH_TEST);
glDisable(GL_CULL_FACE);
glEnable(GL_TEXTURE_2D);
/* This allows alpha blending of 2D textures with the scene*/
glEnable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA,GL_ONE_MINUS_SRC_ALPHA);
glViewport(0, 0, mWidth, mHeight);
glMatrixMode(GL_PROJECTION);
glPushMatrix();
glLoadIdentity();
glOrtho(0.0, (GLdouble)mWidth, (GLdouble)mHeight, 0.0, 0.0, 1.0);
glMatrixMode(GL_MODELVIEW);
glPushMatrix();
glLoadIdentity();
}
void ZEngine::Delay(Uint32 milliseconds)
{
SDL_Delay(milliseconds);
}
Uint32 ZEngine::GetTime()
{
if(mPaused)
return SDL_GetTicks() - (mPausedTime + (SDL_GetTicks() - mLastPause));
else
return SDL_GetTicks() - mPausedTime;
}
void ZEngine::PauseTimer()
{
if(!mPaused)
{
mLastPause = SDL_GetTicks();
mPaused = true;
}
}
void ZEngine::UnpauseTimer()
{
if(mPaused)
{
mPausedTime += (SDL_GetTicks() - mLastPause);
mPaused = false;
}
}
double ZEngine::GetFrameTime()
{
return mSecPerFrame;
}
bool ZEngine::IsPaused()
{
return mPaused;
}
bool ZEngine::IsActive()
{
return mActive;
}
void ZEngine::RequestQuit()
{
mQuit = true; //simply request a quit, nothing more
}
bool ZEngine::QuitRequested()
{
return mQuit;
}
void ZEngine::SetKeyRepeatRate(int rate)
{
SDL_EnableKeyRepeat(rate,rate);
}
bool ZEngine::KeyIsPressed(SDLKey key)
{
return mKeyIsPressed[key] == 1;
}
bool ZEngine::KeyPress(SDLKey key)
{
bool temp = mKeyPress[key];
mKeyPress[key] = false;
return temp;
}
void ZEngine::HideCursor()
{
SDL_ShowCursor(SDL_DISABLE);
}
void ZEngine::ShowCursor()
{
SDL_ShowCursor(SDL_ENABLE);
}
int ZEngine::MouseX()
{
return mMouseX;
}
int ZEngine::MouseY()
{
return mMouseY;
}
bool ZEngine::LButtonPressed()
{
return (mMouseB & SDL_BUTTON_LMASK) > 0;
}
bool ZEngine::RButtonPressed()
{
return (mMouseB & SDL_BUTTON_RMASK) > 0;
}
bool ZEngine::MouseInRect(SDL_Rect *rect)
{
return (mMouseX >= rect->x && mMouseX <= rect->x+rect->w &&
mMouseY >= rect->y && mMouseY <= rect->y+rect->h);
}
void ZEngine::CheckEvents()
{
SDL_Event event;
while(SDL_PollEvent(&event))
{
switch(event.type)
{
case SDL_VIDEOEXPOSE:
case SDL_ACTIVEEVENT:
if(event.active.state & SDL_APPACTIVE || event.active.state & SDL_APPINPUTFOCUS)
{
if( (event.type == SDL_ACTIVEEVENT && event.active.gain == 1) || event.type == SDL_VIDEOEXPOSE)
{
mActive = true;
if(mUnpauseOnActive)
UnpauseTimer();
}
else
{
mActive = mUnpauseOnActive = false;
if(!mPaused)
{
mUnpauseOnActive = true;
PauseTimer();
}
else
mUnpauseOnActive = false;
}
}
break;
case SDL_KEYDOWN:
mKeyPress[event.key.keysym.sym] = true;
break;
case SDL_KEYUP:
mKeyPress[event.key.keysym.sym] = false;
break;
case SDL_QUIT:
mQuit = true;
break;
default:
break;
}
}
mKeyIsPressed = SDL_GetKeyState(NULL); //recommended but not needed (says Sam)
//Alt-X or Alt-F4
if((mKeyIsPressed[SDLK_x] || mKeyIsPressed[SDLK_F4]) &&
(mKeyIsPressed[SDLK_LALT] || mKeyIsPressed[SDLK_RALT]))
mQuit = true;
mMouseB = SDL_GetMouseState(&mMouseX,&mMouseY);
}
#ifdef USE_PHYSFS
void ZEngine::InitPhysFS(string argv)
{
string::size_type pos;
PHYSFS_init(argv.c_str());
pos = argv.rfind(PHYSFS_getDirSeparator());
if(pos != string::npos)
AddPhysFSDir(argv.substr(0,pos));
}
void ZEngine::AddPhysFSDir(string dir)
{
PHYSFS_addToSearchPath(dir.c_str(),0);
}
#endif //USE_PHYSFS
SDL_Surface* ZEngine::LoadImage(string filename)
{
SDL_Surface *image;
//using physfs//
#ifdef USE_PHYSFS
SDL_RWops *rw;
rw = PHYSFSRWOPS_openRead(filename.c_str());
if(!rw)
LogError(FormatStr("PhysFS RWops failed: %s",SDL_GetError()));
#ifdef USE_SDL_IMAGE
image = IMG_Load_RW(rw,0);
#else
image = SDL_LoadBMP_RW(rw,0);
#endif //USE_SDL_IMAGE
SDL_FreeRW(rw);
//end using physfs//
//Just SDL//
#else
#ifdef USE_SDL_IMAGE
image = IMG_Load(filename.c_str());
#else
image = SDL_LoadBMP(filename.c_str());
#endif //USE_SDL_IMAGE
#endif //USE_PHYSFS
if(!image)
{
LogError(FormatStr("LoadImage could not load %s.",filename.c_str()));
return NULL;
}
else
return image;
}
#ifdef USE_SDL_MIXER
Mix_Chunk* ZEngine::LoadSound(string filename)
{
Mix_Chunk *sound;
#ifdef USE_PHYSFS
SDL_RWops *rw;
rw = PHYSFSRWOPS_openRead(filename.c_str());
sound = Mix_LoadWAV_RW(rw,0);
SDL_FreeRW(rw);
#else
sound = Mix_LoadWAV(filename.c_str());
#endif //USE_PHYSFS
if(!sound)
{
LogError(FormatStr("LoadImage could not load %s.",filename.c_str()));
return NULL;
}
else
return sound;
}
Mix_Music* ZEngine::LoadMusic(string filename)
{
Mix_Music *music;
//Currently SDL_Mixer doesn't support Music from a RW
//#ifdef USE_PHYSFS
// SDL_RWops *rw;
// rw = PHYSFSRWOPS_openRead(filename.c_str());
// mus.music = Mix_LoadMUS_RW(filename.c_str(),0);
// SDL_FreeRW(rw);
//#else
music = Mix_LoadMUS(filename.c_str());
//#endif //USE_PHYSFS
if(!music)
{
LogError(FormatStr("LoadMusic could not load %s.",filename.c_str()));
return NULL;
}
else
return music;
}
#endif
#ifdef USE_SDL_TTF
TTF_Font* ZEngine::LoadFont(string filename, int size)
{
TTF_Font *font;
//Currently SDL_ttf doesn't support Fonts from a RW
//#ifdef USE_PHYSFS
// SDL_RWops *rw;
// rw = PHYSFSRWOPS_openRead(filename.c_str());
// fnt.font = TTF_OpenFontRW(rw,0);
// SDL_FreeRW(rw);
//#else
font = TTF_OpenFont(filename.c_str(),size);
//#endif //USE_PHYSFS
if(!font)
{
LogError(FormatStr("LoadFont could not load %s.",filename.c_str()));
return NULL;
}
else
return font;
}
#endif
int ZEngine::Width()
{
return mWidth;
}
int ZEngine::Height()
{
return mHeight;
}
int ZEngine::BPP()
{
return mBPP;
}
bool ZEngine::IsFullscreen()
{
return mFullscreen;
}
}