Initial commit
This commit is contained in:
211
engines/ultima/ultima4/views/tileview.cpp
Normal file
211
engines/ultima/ultima4/views/tileview.cpp
Normal file
@@ -0,0 +1,211 @@
|
||||
/* ScummVM - Graphic Adventure Engine
|
||||
*
|
||||
* ScummVM is the legal property of its developers, whose names
|
||||
* are too numerous to list here. Please refer to the COPYRIGHT
|
||||
* file distributed with this source distribution.
|
||||
*
|
||||
* 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 3 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, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "ultima/ultima4/core/config.h"
|
||||
#include "ultima/ultima4/gfx/image.h"
|
||||
#include "ultima/ultima4/gfx/imagemgr.h"
|
||||
#include "ultima/ultima4/core/settings.h"
|
||||
#include "ultima/ultima4/core/utils.h"
|
||||
#include "ultima/ultima4/gfx/screen.h"
|
||||
#include "ultima/ultima4/map/tile.h"
|
||||
#include "ultima/ultima4/map/tileanim.h"
|
||||
#include "ultima/ultima4/map/tileset.h"
|
||||
#include "ultima/ultima4/views/tileview.h"
|
||||
#include "ultima/ultima4/ultima4.h"
|
||||
#include "common/system.h"
|
||||
|
||||
namespace Ultima {
|
||||
namespace Ultima4 {
|
||||
|
||||
TileView::TileView(int x, int y, int columns, int rows) :
|
||||
View(x, y, columns * TILE_WIDTH, rows * TILE_HEIGHT) {
|
||||
_columns = columns;
|
||||
_rows = rows;
|
||||
_tileWidth = TILE_WIDTH;
|
||||
_tileHeight = TILE_HEIGHT;
|
||||
_tileSet = g_tileSets->get("base");
|
||||
_animated = Image::create(SCALED(_tileWidth), SCALED(_tileHeight), g_system->getScreenFormat());
|
||||
_dest = nullptr;
|
||||
}
|
||||
|
||||
TileView::TileView(int x, int y, int columns, int rows, const Common::String &tileset) :
|
||||
View(x, y, columns * TILE_WIDTH, rows * TILE_HEIGHT) {
|
||||
_columns = columns;
|
||||
_rows = rows;
|
||||
_tileWidth = TILE_WIDTH;
|
||||
_tileHeight = TILE_HEIGHT;
|
||||
_tileSet = g_tileSets->get(tileset);
|
||||
_animated = Image::create(SCALED(_tileWidth), SCALED(_tileHeight), g_system->getScreenFormat());
|
||||
_dest = nullptr;
|
||||
}
|
||||
|
||||
TileView::~TileView() {
|
||||
delete _animated;
|
||||
}
|
||||
|
||||
void TileView::reinit() {
|
||||
View::reinit();
|
||||
_tileSet = g_tileSets->get("base");
|
||||
|
||||
// Scratchpad needs to be re-inited if we rescale...
|
||||
if (_animated) {
|
||||
delete _animated;
|
||||
_animated = nullptr;
|
||||
}
|
||||
_animated = Image::create(SCALED(_tileWidth), SCALED(_tileHeight), _dest ? _dest->format() : g_system->getScreenFormat());
|
||||
}
|
||||
|
||||
void TileView::loadTile(MapTile &mapTile) {
|
||||
// This attempts to preload tiles in advance
|
||||
Tile *tile = _tileSet->get(mapTile._id);
|
||||
if (tile) {
|
||||
tile->getImage();
|
||||
}
|
||||
// But may fail if the tiles don't exist directly in the expected imagesets
|
||||
}
|
||||
|
||||
void TileView::drawTile(MapTile &mapTile, bool focus, int x, int y) {
|
||||
Tile *tile = _tileSet->get(mapTile._id);
|
||||
Image *image = tile->getImage();
|
||||
|
||||
assertMsg(x < _columns, "x value of %d out of range", x);
|
||||
assertMsg(y < _rows, "y value of %d out of range", y);
|
||||
|
||||
// Blank scratch pad
|
||||
_animated->fillRect(0, 0, SCALED(_tileWidth), SCALED(_tileHeight), 0, 0, 0, 255);
|
||||
|
||||
// Draw blackness on the tile.
|
||||
_animated->drawSubRectOn(_dest, SCALED(x * _tileWidth + _bounds.left),
|
||||
SCALED(y * _tileHeight + _bounds.top), 0, 0,
|
||||
SCALED(_tileWidth), SCALED(_tileHeight));
|
||||
|
||||
// Draw the tile to the screen
|
||||
if (tile->getAnim()) {
|
||||
// First, create our animated version of the tile
|
||||
#ifdef IOS_ULTIMA4
|
||||
animated->clearImageContents();
|
||||
#endif
|
||||
tile->getAnim()->draw(_animated, tile, mapTile, DIR_NONE);
|
||||
|
||||
// Then draw it to the screen
|
||||
_animated->drawSubRectOn(_dest, SCALED(x * _tileWidth + _bounds.left),
|
||||
SCALED(y * _tileHeight + _bounds.top), 0, 0,
|
||||
SCALED(_tileWidth), SCALED(_tileHeight));
|
||||
} else {
|
||||
image->drawSubRectOn(_dest, SCALED(x * _tileWidth + _bounds.left),
|
||||
SCALED(y * _tileHeight + _bounds.top),
|
||||
0, SCALED(_tileHeight * mapTile._frame),
|
||||
SCALED(_tileWidth), SCALED(_tileHeight));
|
||||
}
|
||||
|
||||
// Draw the focus around the tile if it has the focus
|
||||
if (focus)
|
||||
drawFocus(x, y);
|
||||
}
|
||||
|
||||
void TileView::drawTile(Std::vector<MapTile> &tiles, bool focus, int x, int y) {
|
||||
assertMsg(x < _columns, "x value of %d out of range", x);
|
||||
assertMsg(y < _rows, "y value of %d out of range", y);
|
||||
|
||||
// Clear tile contents
|
||||
_animated->fillRect(0, 0, SCALED(_tileWidth), SCALED(_tileHeight), 0, 0, 0, 255);
|
||||
_animated->drawSubRectOn(_dest,
|
||||
SCALED(x * _tileWidth + _bounds.left), SCALED(y * _tileHeight + _bounds.top),
|
||||
0, 0,
|
||||
SCALED(_tileWidth), SCALED(_tileHeight)
|
||||
);
|
||||
|
||||
// Iterate through rendering each of the needed tiles
|
||||
for (int t = tiles.size() - 1; t >= 0; --t) {
|
||||
MapTile &frontTile = tiles[t];
|
||||
Tile *frontTileType = _tileSet->get(frontTile._id);
|
||||
|
||||
if (!frontTileType) {
|
||||
// TODO: This leads to an error. It happens after graphics mode changes.
|
||||
return;
|
||||
}
|
||||
|
||||
// Get the image for the tile
|
||||
Image *image = frontTileType->getImage();
|
||||
|
||||
// Draw the tile to the screen
|
||||
if (frontTileType->getAnim()) {
|
||||
// First, create our animated version of the tile
|
||||
frontTileType->getAnim()->draw(_animated, frontTileType, frontTile, DIR_NONE);
|
||||
} else {
|
||||
if (!image)
|
||||
// FIXME: This is a problem, error message it.
|
||||
return;
|
||||
image->drawSubRectOn(_animated, 0, 0,
|
||||
0, SCALED(_tileHeight * frontTile._frame),
|
||||
SCALED(_tileWidth), SCALED(_tileHeight)
|
||||
);
|
||||
}
|
||||
|
||||
// Then draw it to the screen
|
||||
_animated->drawSubRectOn(_dest, SCALED(x * _tileWidth + _bounds.left),
|
||||
SCALED(y * _tileHeight + _bounds.top), 0, 0,
|
||||
SCALED(_tileWidth), SCALED(_tileHeight)
|
||||
);
|
||||
}
|
||||
|
||||
// Draw the focus around the tile if it has the focus
|
||||
if (focus)
|
||||
drawFocus(x, y);
|
||||
}
|
||||
|
||||
void TileView::drawFocus(int x, int y) {
|
||||
assertMsg(x < _columns, "x value of %d out of range", x);
|
||||
assertMsg(y < _rows, "y value of %d out of range", y);
|
||||
|
||||
// Draw the focus rectangle around the tile
|
||||
if ((g_screen->_currentCycle * 4 / SCR_CYCLE_PER_SECOND) % 2) {
|
||||
// left edge
|
||||
_screen->fillRect(SCALED(x * _tileWidth + _bounds.left),
|
||||
SCALED(y * _tileHeight + _bounds.top),
|
||||
SCALED(2), SCALED(_tileHeight), 0xff, 0xff, 0xff);
|
||||
|
||||
// top edge
|
||||
_screen->fillRect(SCALED(x * _tileWidth + _bounds.left),
|
||||
SCALED(y * _tileHeight + _bounds.top),
|
||||
SCALED(_tileWidth), SCALED(2),
|
||||
0xff, 0xff, 0xff);
|
||||
|
||||
// Right edge
|
||||
_screen->fillRect(SCALED((x + 1) * _tileWidth + _bounds.left - 2),
|
||||
SCALED(y * _tileHeight + _bounds.top),
|
||||
SCALED(2), SCALED(_tileHeight),
|
||||
0xff, 0xff, 0xff);
|
||||
|
||||
// Bottom edge
|
||||
_screen->fillRect(SCALED(x * _tileWidth + _bounds.left),
|
||||
SCALED((y + 1) * _tileHeight + _bounds.top - 2),
|
||||
SCALED(_tileWidth), SCALED(2),
|
||||
0xff, 0xff, 0xff);
|
||||
}
|
||||
}
|
||||
|
||||
void TileView::setTileset(Tileset *tileset) {
|
||||
this->_tileSet = tileset;
|
||||
}
|
||||
|
||||
} // End of namespace Ultima4
|
||||
} // End of namespace Ultima
|
||||
Reference in New Issue
Block a user