123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312 |
- /* GCSx
- ** TILESET.CPP
- **
- ** Tileset support, objects and drawing
- ** Non-EDITOR members
- */
- /*****************************************************************************
- ** Copyright (C) 2003-2006 Janson
- **
- ** 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
- ** (at your option) 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, write to the Free Software
- ** Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111, USA.
- *****************************************************************************/
- #include "all.h"
- const TileSet* TileSet::activeGenTexture = NULL;
- TileSet::TileSet(class World* myWorld, int myId) : name(blankString), nameL(blankString) { start_func
- if (myId) assert(myWorld);
-
- id = myId;
- cached = 0;
- lockCount = 0;
- lockCountPlay = 0;
- cacheFile = NULL;
- texture = NULL;
- numTiles = 0;
- numTilesPerLine = TILE_DEFAULT_PERLINE;
- tiles = NULL;
- tsPerLine = 0;
- isFont = 0;
- defaultTransparent = 0;
- fontWidths = NULL;
- numCollisionMaps = 0;
- collisionMaps = NULL;
- world = myWorld;
- width = height = TILE_DEFAULT_SIZE;
- calculateCmSizes();
- }
- TileSet::~TileSet() { start_func
- if (tiles) SDL_FreeSurface(tiles);
- delete[] fontWidths;
- delete[] collisionMaps;
- delete cacheFile;
- delete texture;
-
- clipboardClearTileset(this);
- }
- void TileSet::calculateCmSizes() {
- cmHeight = height;
- cmWidth = width >> 5;
- if (width & 31) ++cmWidth;
- }
- void TileSet::cacheLoadTiles() throw_File { start_func
- // load tiles only
- try {
- assert(cacheFile);
- assert(cacheFile->getVersion() <= 1);
- assert(!tiles);
- cacheFile->rewind();
- if (numTiles) {
- int surfaceW = cacheFile->readInt();
- int surfaceH = cacheFile->readInt();
- int surfaceSize = cacheFile->readInt();
- if ((surfaceW != tsPerLine * width) ||
- (surfaceH != (numTiles + tsPerLine) / tsPerLine * height) ||
- (surfaceSize != surfaceW * surfaceH * 4)) {
- throw FileException("Corrupted tileset content");
- }
- tiles = createSurface32(surfaceW, surfaceH);
- // If pitch of created surface is "incorrect", we need to do extra work
- if (tiles->pitch == surfaceW * 4) {
- cacheFile->read(tiles->pixels, surfaceSize);
- }
- else {
- Uint8* dest = (Uint8*)tiles->pixels;
- for (int row = surfaceH; row > 0; --row) {
- cacheFile->read(dest, surfaceW * 4);
- dest += tiles->pitch;
- }
- }
- }
- }
- catch (...) {
- if (tiles) SDL_FreeSurface(tiles);
- tiles = NULL;
- throw;
- }
- }
-
- void TileSet::cacheLoad() throw_File { start_func
- if (cached) {
- try {
- // load into memory
- assert(!fontWidths);
- assert(!collisionMaps);
- // Rewinds for us
- cacheLoadTiles();
- if (numTiles) {
- if (isFont) {
- fontWidths = new Uint32[numTiles + 1];
- fontWidths[0] = 0; // 0 tile is assumed blank
- cacheFile->readIntBulk(fontWidths + 1, numTiles);
- // All sizes must be valid
- for (int pos = 1; pos <= numTiles; ++pos) {
- if (fontWidths[pos] > (Uint32)width) {
- throw FileException("Corrupted font width content");
- }
- }
- }
- }
- if (numCollisionMaps) {
- int size = (numCollisionMaps + 1) * cmWidth * cmHeight;
- collisionMaps = new Uint32[size];
- cacheFile->readIntBulk(collisionMaps, size);
- }
- // We retain this pointer and reuse it IF we
- // unlock to 0 AND aren't modified
- cached = 0;
- }
- catch (...) {
- if (tiles) SDL_FreeSurface(tiles);
- tiles = NULL;
- delete[] collisionMaps;
- collisionMaps = NULL;
- delete[] fontWidths;
- fontWidths = NULL;
- throw;
- }
- }
- }
- int TileSet::getGlyphWidth(int tile) const { start_func
- assert(isFont);
- assert(fontWidths);
- assert(tile >= 0);
- assert(tile <= numTiles);
-
- return fontWidths[tile];
- }
- void TileSet::loadHeader(FileRead* file) throw_File { start_func
- assert(world);
-
- if (file->getVersion() > 1) {
- throw FileException("Unsupported tileset version %d", file->getVersion());
- }
- file->readStr(name);
- nameL = name;
- toLower(nameL);
- width = file->readInt();
- height = file->readInt();
- calculateCmSizes();
- numTiles = file->readInt();
- numCollisionMaps = file->readInt();
- numTilesPerLine = file->readInt();
- tsPerLine = file->readInt();
- defaultTransparent = file->readInt();
- isFont = file->readInt();
- id = file->readInt();
-
- // Check validity
- if ((width < MIN_TILESIZE) || (height < MIN_TILESIZE) ||
- (width > MAX_TILESIZE) || (height > MAX_TILESIZE) ||
- (numTiles < 0) || (numTiles > MAX_TILES) ||
- (numTilesPerLine < 0) || (numTilesPerLine > MAX_TILES) ||
- (tsPerLine < 0) || (tsPerLine > numTiles) ||
- ((numCollisionMaps) && (isFont)) ||
- (!id)) {
- throw FileException("Corrupted tileset header");
- }
- }
- void TileSet::loadContent(FileRead* file) { start_func
- assert(world);
-
- delete cacheFile;
- cacheFile = file;
- cached = 1;
- }
- int TileSet::isContentCached() const { start_func
- return cached;
- }
- int TileSet::doLock(int play) throw_File { start_func
- // Load everything if this is our first unlock at all
- if ((lockCount == 0) && (lockCountPlay == 0))
- cacheLoad();
- // Otherwise- first play lock- everything is ok
- // First non-play lock- we need to reload tiles back in
- else if ((lockCount == 0) && (!play))
- cacheLoadTiles();
-
- if (play) {
- ++lockCountPlay;
- if (!texture) {
- activeGenTexture = this;
- texture = new TextureMap(numTiles, width, height, genTexture);
- activeGenTexture = NULL;
- }
- if ((!lockCount) && (tiles)) {
- SDL_FreeSurface(tiles);
- tiles = NULL;
- }
- }
- else {
- ++lockCount;
- }
- return lockCount + lockCountPlay;
- }
- int TileSet::doUnlock(int play) { start_func
- if (play) --lockCountPlay;
- else --lockCount;
- assert(lockCount >= 0);
- assert(lockCountPlay >= 0);
- if (cacheFile) {
- if ((lockCount == 0) && (tiles)) {
- SDL_FreeSurface(tiles);
- tiles = NULL;
- }
- if ((lockCountPlay == 0) && (texture)) {
- delete texture;
- texture = NULL;
- }
- if ((lockCountPlay == 0) && (lockCount == 0)) {
- // Fully recache ourselves
- cached = 1;
- delete[] fontWidths;
- fontWidths = NULL;
- }
- }
- return lockCount + lockCountPlay;
- }
- int TileSet::isLocked() const { start_func
- return lockCount;
- }
- int TileSet::markLock() throw_File { start_func
- return doLock(0);
- }
- int TileSet::markUnlock() { start_func
- return doUnlock(0);
- }
- int TileSet::markLockPlay() throw_File { start_func
- return doLock(1);
- }
- int TileSet::markUnlockPlay() { start_func
- return doUnlock(1);
- }
- const SDL_Surface* TileSet::getTileSurface(int tile, int& x, int& y) const { start_func
- assert(tiles);
- assert(!cached);
-
- if (tile < 1) return NULL;
- if (tile > numTiles) return NULL;
-
- x = tile % tsPerLine * width;
- y = tile / tsPerLine * height;
- return tiles;
- }
- const TextureMap* TileSet::getTexture() { start_func
- return texture;
- }
- void TileSet::genTexture(int position, const SDL_Surface*& src, int& x, int& y) { start_func
- assert(!activeGenTexture->cached);
- assert(position > 0);
- assert(position <= activeGenTexture->numTiles);
- assert(activeGenTexture->tiles);
-
- src = activeGenTexture->tiles;
- x = position % activeGenTexture->tsPerLine * activeGenTexture->width;
- y = position / activeGenTexture->tsPerLine * activeGenTexture->height;
- }
|