Changeset - r15677:fa81b10db8cc
[Not reviewed]
master
0 3 0
michi_cc - 14 years ago 2010-08-03 17:48:07
michi_cc@openttd.org
(svn r20353) -Add: [NewGRF] Support for callback 0x147 ("add sprite offset") for canals.
3 files changed with 111 insertions and 32 deletions:
0 comments (0 inline, 0 general)
src/newgrf_canal.cpp
Show inline comments
 
@@ -96,12 +96,54 @@ static void NewCanalResolver(ResolverObj
 
SpriteID GetCanalSprite(CanalFeature feature, TileIndex tile)
 
{
 
	ResolverObject object;
 
	const SpriteGroup *group;
 

	
 
	NewCanalResolver(&object, tile, _water_feature[feature].grffile);
 

	
 
	group = SpriteGroup::Resolve(_water_feature[feature].group, &object);
 
	if (group == NULL) return 0;
 

	
 
	return group->GetResult();
 
}
 

	
 
/**
 
 * Run a specific callback for canals.
 
 * @param callback Callback ID.
 
 * @param param1   Callback parameter 1.
 
 * @param param2   Callback parameter 2.
 
 * @param feature  For which feature to run the callback.
 
 * @param tile     Tile index of canal.
 
 * @return Callback result or CALLBACK_FAILED if the callback failed.
 
 */
 
uint16 GetCanalCallback(CallbackID callback, uint32 param1, uint32 param2, CanalFeature feature, TileIndex tile)
 
{
 
	ResolverObject object;
 
	const SpriteGroup *group;
 

	
 
	NewCanalResolver(&object, tile, _water_feature[feature].grffile);
 

	
 
	object.callback = callback;
 
	object.callback_param1 = param1;
 
	object.callback_param2 = param2;
 

	
 
	group = SpriteGroup::Resolve(_water_feature[feature].group, &object);
 
	if (group == NULL) return CALLBACK_FAILED;
 

	
 
	return group->GetCallbackResult();
 
}
 

	
 
/**
 
 * Get the new sprite offset for a water tile.
 
 * @param tile       Tile index of the canal/water tile.
 
 * @param feature    For which feature to get the new sprite offset.
 
 * @param cur_offset Current sprite offset.
 
 * @return New sprite offset.
 
 */
 
uint GetCanalSpriteOffset(CanalFeature feature, TileIndex tile, uint cur_offset)
 
{
 
	if (HasBit(_water_feature[feature].callback_mask, CBM_CANAL_SPRITE_OFFSET)) {
 
		uint16 cb = GetCanalCallback(CBID_CANALS_SPRITE_OFFSET, cur_offset, 0, feature, tile);
 
		if (cb != CALLBACK_FAILED) return cur_offset + cb;
 
	}
 
	return cur_offset;
 
}
src/newgrf_canal.h
Show inline comments
 
@@ -6,24 +6,25 @@
 
 * OpenTTD 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 OpenTTD. If not, see <http://www.gnu.org/licenses/>.
 
 */
 

	
 
/** @file newgrf_canal.h Handling of NewGRF canals. */
 

	
 
#ifndef NEWGRF_CANAL_H
 
#define NEWGRF_CANAL_H
 

	
 
#include "gfx_type.h"
 
#include "tile_type.h"
 
#include "newgrf_generic.h"
 
#include "newgrf_callbacks.h"
 

	
 
/**
 
 * List of different canal 'features'.
 
 * Each feature gets an entry in the canal spritegroup table
 
 */
 
enum CanalFeature {
 
	CF_WATERSLOPE,
 
	CF_LOCKS,
 
	CF_DIKES,
 
	CF_ICON,
 
	CF_DOCKS,
 
	CF_RIVER_SLOPE,
 
@@ -48,13 +49,16 @@ struct WaterFeature {
 
/** Table of canal 'feature' sprite groups */
 
extern WaterFeature _water_feature[CF_END];
 

	
 

	
 
/**
 
 * Lookup the base sprite to use for a canal.
 
 * @param feature Which canal feature we want.
 
 * @param tile Tile index of canal, if appropriate.
 
 * @return Base sprite returned by GRF, or 0 if none.
 
 */
 
SpriteID GetCanalSprite(CanalFeature feature, TileIndex tile);
 

	
 
uint16 GetCanalCallback(CallbackID callback, uint32 param1, uint32 param2, CanalFeature feature, TileIndex tile);
 
uint GetCanalSpriteOffset(CanalFeature feature, TileIndex tile, uint cur_offset);
 

	
 
#endif /* NEWGRF_CANAL_H */
src/water_cmd.cpp
Show inline comments
 
@@ -498,112 +498,144 @@ static bool IsWateredTile(TileIndex tile
 
			if ((IsTileType(src_tile, MP_STATION) && IsOilRig(src_tile)) ||
 
			    (IsTileType(src_tile, MP_INDUSTRY) && GetIndustryIndex(src_tile) == GetIndustryIndex(tile))) return true;
 

	
 
			return IsIndustryTileOnWater(tile);
 
		}
 

	
 
		case MP_TUNNELBRIDGE: return GetTunnelBridgeTransportType(tile) == TRANSPORT_WATER && ReverseDiagDir(GetTunnelBridgeDirection(tile)) == DirToDiagDir(from);
 

	
 
		default:          return false;
 
	}
 
}
 

	
 
static void DrawWaterEdges(SpriteID base, TileIndex tile)
 
/**
 
 * Draw a water sprite, potentially with a NewGRF-modified sprite offset.
 
 * @param base    Sprite base.
 
 * @param offset  Sprite offset.
 
 * @param feature The type of sprite that is drawn.
 
 * @param tile    Tile index to draw.
 
 */
 
static void DrawWaterSprite(SpriteID base, uint offset, CanalFeature feature, TileIndex tile)
 
{
 
	if (base != SPR_FLAT_WATER_TILE) {
 
		/* Only call offset callback if the sprite is NewGRF-provided. */
 
		offset = GetCanalSpriteOffset(feature, tile, offset);
 
	}
 
	DrawGroundSprite(base + offset, PAL_NONE);
 
}
 

	
 
/**
 
 * Draw canal or river edges.
 
 * @param canal  True if canal edges should be drawn, false for river edges.
 
 * @param offset Sprite offset.
 
 * @param tile   Tile to draw.
 
 */
 
static void DrawWaterEdges(bool canal, uint offset, TileIndex tile)
 
{
 
	CanalFeature feature;
 
	SpriteID base = 0;
 
	if (canal) {
 
		feature = CF_DIKES;
 
		base = GetCanalSprite(CF_DIKES, tile);
 
		if (base == 0) base = SPR_CANAL_DIKES_BASE;
 
	} else {
 
		feature = CF_RIVER_EDGE;
 
		base = GetCanalSprite(CF_RIVER_EDGE, tile);
 
		if (base == 0) return; // Don't draw if no sprites provided.
 
	}
 

	
 
	uint wa;
 

	
 
	/* determine the edges around with water. */
 
	wa  = IsWateredTile(TILE_ADDXY(tile, -1,  0), DIR_SW) << 0;
 
	wa += IsWateredTile(TILE_ADDXY(tile,  0,  1), DIR_NW) << 1;
 
	wa += IsWateredTile(TILE_ADDXY(tile,  1,  0), DIR_NE) << 2;
 
	wa += IsWateredTile(TILE_ADDXY(tile,  0, -1), DIR_SE) << 3;
 

	
 
	if (!(wa & 1)) DrawGroundSprite(base,     PAL_NONE);
 
	if (!(wa & 2)) DrawGroundSprite(base + 1, PAL_NONE);
 
	if (!(wa & 4)) DrawGroundSprite(base + 2, PAL_NONE);
 
	if (!(wa & 8)) DrawGroundSprite(base + 3, PAL_NONE);
 
	if (!(wa & 1)) DrawWaterSprite(base, offset,     feature, tile);
 
	if (!(wa & 2)) DrawWaterSprite(base, offset + 1, feature, tile);
 
	if (!(wa & 4)) DrawWaterSprite(base, offset + 2, feature, tile);
 
	if (!(wa & 8)) DrawWaterSprite(base, offset + 3, feature, tile);
 

	
 
	/* right corner */
 
	switch (wa & 0x03) {
 
		case 0: DrawGroundSprite(base + 4, PAL_NONE); break;
 
		case 3: if (!IsWateredTile(TILE_ADDXY(tile, -1, 1), DIR_W)) DrawGroundSprite(base + 8, PAL_NONE); break;
 
		case 0: DrawWaterSprite(base, offset + 4, feature, tile); break;
 
		case 3: if (!IsWateredTile(TILE_ADDXY(tile, -1, 1), DIR_W)) DrawWaterSprite(base, offset + 8, feature, tile); break;
 
	}
 

	
 
	/* bottom corner */
 
	switch (wa & 0x06) {
 
		case 0: DrawGroundSprite(base + 5, PAL_NONE); break;
 
		case 6: if (!IsWateredTile(TILE_ADDXY(tile, 1, 1), DIR_N)) DrawGroundSprite(base + 9, PAL_NONE); break;
 
		case 0: DrawWaterSprite(base, offset + 5, feature, tile); break;
 
		case 6: if (!IsWateredTile(TILE_ADDXY(tile, 1, 1), DIR_N)) DrawWaterSprite(base, offset + 9, feature, tile); break;
 
	}
 

	
 
	/* left corner */
 
	switch (wa & 0x0C) {
 
		case  0: DrawGroundSprite(base + 6, PAL_NONE); break;
 
		case 12: if (!IsWateredTile(TILE_ADDXY(tile, 1, -1), DIR_E)) DrawGroundSprite(base + 10, PAL_NONE); break;
 
		case  0: DrawWaterSprite(base, offset + 6, feature, tile); break;
 
		case 12: if (!IsWateredTile(TILE_ADDXY(tile, 1, -1), DIR_E)) DrawWaterSprite(base, offset + 10, feature, tile); break;
 
	}
 

	
 
	/* upper corner */
 
	switch (wa & 0x09) {
 
		case 0: DrawGroundSprite(base + 7, PAL_NONE); break;
 
		case 9: if (!IsWateredTile(TILE_ADDXY(tile, -1, -1), DIR_S)) DrawGroundSprite(base + 11, PAL_NONE); break;
 
		case 0: DrawWaterSprite(base, offset + 7, feature, tile); break;
 
		case 9: if (!IsWateredTile(TILE_ADDXY(tile, -1, -1), DIR_S)) DrawWaterSprite(base, offset + 11, feature, tile); break;
 
	}
 
}
 

	
 
/** Draw a plain sea water tile with no edges */
 
static void DrawSeaWater(TileIndex tile)
 
{
 
	DrawGroundSprite(SPR_FLAT_WATER_TILE, PAL_NONE);
 
}
 

	
 
/** draw a canal styled water tile with dikes around */
 
static void DrawCanalWater(TileIndex tile)
 
{
 
	SpriteID image = SPR_FLAT_WATER_TILE;
 
	if (HasBit(_water_feature[CF_WATERSLOPE].flags, CFF_HAS_FLAT_SPRITE)) {
 
		/* First water slope sprite is flat water. */
 
		image = GetCanalSprite(CF_WATERSLOPE, tile);
 
		if (image == 0) image = SPR_FLAT_WATER_TILE;
 
	}
 
	DrawGroundSprite(image, PAL_NONE);
 
	DrawWaterSprite(image, 0, CF_WATERSLOPE, tile);
 

	
 
	/* Test for custom graphics, else use the default */
 
	SpriteID dikes_base = GetCanalSprite(CF_DIKES, tile);
 
	if (dikes_base == 0) dikes_base = SPR_CANAL_DIKES_BASE;
 

	
 
	DrawWaterEdges(dikes_base, tile);
 
	DrawWaterEdges(true, 0, tile);
 
}
 

	
 
struct LocksDrawTileStruct {
 
	int8 delta_x, delta_y, delta_z;
 
	byte width, height, depth;
 
	SpriteID image;
 
};
 

	
 
#include "table/water_land.h"
 

	
 
/**
 
 * Draw a build sprite sequence for water tiles.
 
 * If buildings are invisible, nothing will be drawn.
 
 * @param ti      Tile info.
 
 * @param wdts    Sprite sequence to draw.
 
 * @param base    Base sprite.
 
 * @param offset  Additional sprite offset.
 
 * @param palette Palette to use.
 
 */
 
static void DrawWaterTileStruct(const TileInfo *ti, const WaterDrawTileStruct *wdts, SpriteID base, uint offset, PaletteID palette)
 
static void DrawWaterTileStruct(const TileInfo *ti, const WaterDrawTileStruct *wdts, SpriteID base, uint offset, PaletteID palette, CanalFeature feature)
 
{
 
	/* Don't draw if buildings are invisible. */
 
	if (IsInvisibilitySet(TO_BUILDINGS)) return;
 

	
 
	for (; wdts->delta_x != 0x80; wdts++) {
 
		AddSortableSpriteToDraw(base + wdts->image + offset, palette,
 
		uint tile_offs = offset + wdts->image;
 
		if (feature < CF_END) tile_offs = GetCanalSpriteOffset(feature, ti->tile, tile_offs);
 
		AddSortableSpriteToDraw(base + tile_offs, palette,
 
			ti->x + wdts->delta_x, ti->y + wdts->delta_y,
 
			wdts->size_x, wdts->size_y,
 
			wdts->size_z, ti->z + wdts->delta_z,
 
			IsTransparencySet(TO_BUILDINGS));
 
	}
 
}
 

	
 
/** Draw a lock tile. */
 
static void DrawWaterLock(const TileInfo *ti)
 
{
 
	const WaterDrawTileStruct *wdts = _lock_display_seq[GetSection(ti->tile)];
 

	
 
@@ -627,70 +659,71 @@ static void DrawWaterLock(const TileInfo
 
	DrawGroundSprite(image, PAL_NONE);
 

	
 
	/* Draw structures. */
 
	uint     zoffs = 0;
 
	SpriteID base  = GetCanalSprite(CF_LOCKS, ti->tile);
 

	
 
	if (base == 0) {
 
		/* If no custom graphics, use defaults. */
 
		base = SPR_LOCK_BASE;
 
		zoffs = ti->z > wdts[3].delta_y ? 24 : 0;
 
	}
 

	
 
	DrawWaterTileStruct(ti, wdts, base, zoffs, PAL_NONE);
 
	DrawWaterTileStruct(ti, wdts, base, zoffs, PAL_NONE, CF_LOCKS);
 
}
 

	
 
/** Draw a ship depot tile. */
 
static void DrawWaterDepot(const TileInfo *ti)
 
{
 
	DrawWaterClassGround(ti);
 
	/* Skip first entry in _shipdepot_display_seq as this is the ground sprite. */
 
	DrawWaterTileStruct(ti, _shipdepot_display_seq[GetSection(ti->tile)] + 1, 0, 0, COMPANY_SPRITE_COLOUR(GetTileOwner(ti->tile)));
 
	DrawWaterTileStruct(ti, _shipdepot_display_seq[GetSection(ti->tile)] + 1, 0, 0, COMPANY_SPRITE_COLOUR(GetTileOwner(ti->tile)), CF_END);
 
}
 

	
 
static void DrawRiverWater(const TileInfo *ti)
 
{
 
	SpriteID image = SPR_FLAT_WATER_TILE;
 
	SpriteID edges_base = GetCanalSprite(CF_RIVER_EDGE, ti->tile);
 
	uint     offset = 0;
 
	uint     edges_offset = 0;
 

	
 
	if (ti->tileh != SLOPE_FLAT || HasBit(_water_feature[CF_RIVER_SLOPE].flags, CFF_HAS_FLAT_SPRITE)) {
 
		image = GetCanalSprite(CF_RIVER_SLOPE, ti->tile);
 
		if (image == 0) {
 
			switch (ti->tileh) {
 
				case SLOPE_NW: image = SPR_WATER_SLOPE_Y_DOWN; break;
 
				case SLOPE_SW: image = SPR_WATER_SLOPE_X_UP;   break;
 
				case SLOPE_SE: image = SPR_WATER_SLOPE_Y_UP;   break;
 
				case SLOPE_NE: image = SPR_WATER_SLOPE_X_DOWN; break;
 
				default:       image = SPR_FLAT_WATER_TILE;    break;
 
			}
 
		} else {
 
			/* Flag bit 0 indicates that the first sprite is flat water. */
 
			uint offset = HasBit(_water_feature[CF_RIVER_SLOPE].flags, CFF_HAS_FLAT_SPRITE) ? 1 : 0;
 
			offset = HasBit(_water_feature[CF_RIVER_SLOPE].flags, CFF_HAS_FLAT_SPRITE) ? 1 : 0;
 

	
 
			switch (ti->tileh) {
 
				case SLOPE_SE:              edges_base += 12; break;
 
				case SLOPE_NE: offset += 1; edges_base += 24; break;
 
				case SLOPE_SW: offset += 2; edges_base += 36; break;
 
				case SLOPE_NW: offset += 3; edges_base += 48; break;
 
				case SLOPE_SE:              edges_offset += 12; break;
 
				case SLOPE_NE: offset += 1; edges_offset += 24; break;
 
				case SLOPE_SW: offset += 2; edges_offset += 36; break;
 
				case SLOPE_NW: offset += 3; edges_offset += 48; break;
 
				default:       offset  = 0; break;
 
			}
 

	
 
			image += offset;
 
			offset = GetCanalSpriteOffset(CF_RIVER_SLOPE, ti->tile, offset);
 
		}
 
	}
 

	
 
	DrawGroundSprite(image, PAL_NONE);
 
	DrawGroundSprite(image + offset, PAL_NONE);
 

	
 
	/* Draw river edges if available. */
 
	if (edges_base > 48) DrawWaterEdges(edges_base, ti->tile);
 
	DrawWaterEdges(false, edges_offset, ti->tile);
 
}
 

	
 
void DrawShoreTile(Slope tileh)
 
{
 
	/* Converts the enum Slope into an offset based on SPR_SHORE_BASE.
 
	 * This allows to calculate the proper sprite to display for this Slope */
 
	static const byte tileh_to_shoresprite[32] = {
 
		0, 1, 2, 3, 4, 16, 6, 7, 8, 9, 17, 11, 12, 13, 14, 0,
 
		0, 0, 0, 0, 0,  0, 0, 0, 0, 0,  0,  5,  0, 10, 15, 0,
 
	};
 

	
 
	assert(!IsHalftileSlope(tileh)); // Halftile slopes need to get handled earlier.
0 comments (0 inline, 0 general)