Changeset - r18093:bb567a02767f
[Not reviewed]
master
0 7 0
frosch - 13 years ago 2011-09-11 15:10:09
frosch@openttd.org
(svn r22924) -Codechange: Enhance NewGRFSpriteLayout for drawing construction stages in spritelayouts with inconsistent number of sprites per spriteset.
7 files changed with 86 insertions and 20 deletions:
0 comments (0 inline, 0 general)
src/newgrf.cpp
Show inline comments
 
@@ -607,9 +607,11 @@ static void MapSpriteMappingRecolour(Pal
 
 * @param use_cur_spritesets  Whether to use currently referenceable action 1 sets.
 
 * @param feature             GrfSpecFeature to use spritesets from.
 
 * @param [out] grf_sprite    Read sprite and palette.
 
 * @param [out] max_sprite_offset  Optionally returns the number of sprites in the spriteset of the sprite. (0 if no spritset)
 
 * @param [out] max_palette_offset Optionally returns the number of sprites in the spriteset of the palette. (0 if no spritset)
 
 * @return Read TileLayoutFlags.
 
 */
 
static TileLayoutFlags ReadSpriteLayoutSprite(ByteReader *buf, bool read_flags, bool invert_action1_flag, bool use_cur_spritesets, byte feature, PalSpriteID *grf_sprite)
 
static TileLayoutFlags ReadSpriteLayoutSprite(ByteReader *buf, bool read_flags, bool invert_action1_flag, bool use_cur_spritesets, int feature, PalSpriteID *grf_sprite, uint16 *max_sprite_offset = NULL, uint16 *max_palette_offset = NULL)
 
{
 
	grf_sprite->sprite = buf->ReadWord();
 
	grf_sprite->pal = buf->ReadWord();
 
@@ -628,6 +630,7 @@ static TileLayoutFlags ReadSpriteLayoutS
 
			grf_sprite->pal = PAL_NONE;
 
		} else {
 
			SpriteID sprite = use_cur_spritesets ? _cur.GetSprite(feature, index) : index;
 
			if (max_sprite_offset != NULL) *max_sprite_offset = use_cur_spritesets ? _cur.GetNumEnts(feature, index) : UINT16_MAX;
 
			SB(grf_sprite->sprite, 0, SPRITE_WIDTH, sprite);
 
			SetBit(grf_sprite->sprite, SPRITE_MODIFIER_CUSTOM_SPRITE);
 
		}
 
@@ -645,6 +648,7 @@ static TileLayoutFlags ReadSpriteLayoutS
 
			grf_sprite->pal = PAL_NONE;
 
		} else {
 
			SpriteID sprite = use_cur_spritesets ? _cur.GetSprite(feature, index) : index;
 
			if (max_palette_offset != NULL) *max_palette_offset = use_cur_spritesets ? _cur.GetNumEnts(feature, index) : UINT16_MAX;
 
			SB(grf_sprite->pal, 0, SPRITE_WIDTH, sprite);
 
			SetBit(grf_sprite->pal, SPRITE_MODIFIER_CUSTOM_SPRITE);
 
		}
 
@@ -726,8 +730,13 @@ static bool ReadSpriteLayout(ByteReader 
 
	if (!allow_var10) valid_flags &= ~TLF_VAR10_FLAGS;
 
	dts->Allocate(num_building_sprites); // allocate before reading groundsprite flags
 

	
 
	uint16 *max_sprite_offset = AllocaM(uint16, num_building_sprites + 1);
 
	uint16 *max_palette_offset = AllocaM(uint16, num_building_sprites + 1);
 
	MemSetT(max_sprite_offset, 0, num_building_sprites + 1);
 
	MemSetT(max_palette_offset, 0, num_building_sprites + 1);
 

	
 
	/* Groundsprite */
 
	TileLayoutFlags flags = ReadSpriteLayoutSprite(buf, has_flags, false, use_cur_spritesets, feature, &dts->ground);
 
	TileLayoutFlags flags = ReadSpriteLayoutSprite(buf, has_flags, false, use_cur_spritesets, feature, &dts->ground, max_sprite_offset, max_palette_offset);
 
	if (_cur.skip_sprites < 0) return true;
 

	
 
	if (flags & ~(valid_flags & ~TLF_NON_GROUND_FLAGS)) {
 
@@ -742,7 +751,7 @@ static bool ReadSpriteLayout(ByteReader 
 
	for (uint i = 0; i < num_building_sprites; i++) {
 
		DrawTileSeqStruct *seq = const_cast<DrawTileSeqStruct*>(&dts->seq[i]);
 

	
 
		flags = ReadSpriteLayoutSprite(buf, has_flags, false, use_cur_spritesets, feature, &seq->image);
 
		flags = ReadSpriteLayoutSprite(buf, has_flags, false, use_cur_spritesets, feature, &seq->image, max_sprite_offset + i + 1, max_palette_offset + i + 1);
 
		if (_cur.skip_sprites < 0) return true;
 

	
 
		if (flags & ~valid_flags) {
 
@@ -766,6 +775,42 @@ static bool ReadSpriteLayout(ByteReader 
 
		if (_cur.skip_sprites < 0) return true;
 
	}
 

	
 
	/* Check if the number of sprites per spriteset is consistent */
 
	bool is_consistent = true;
 
	dts->consistent_max_offset = 0;
 
	for (uint i = 0; i < num_building_sprites + 1; i++) {
 
		if (max_sprite_offset[i] > 0) {
 
			if (dts->consistent_max_offset == 0) {
 
				dts->consistent_max_offset = max_sprite_offset[i];
 
			} else if (dts->consistent_max_offset != max_sprite_offset[i]) {
 
				is_consistent = false;
 
				break;
 
			}
 
		}
 
		if (max_palette_offset[i] > 0) {
 
			if (dts->consistent_max_offset == 0) {
 
				dts->consistent_max_offset = max_palette_offset[i];
 
			} else if (dts->consistent_max_offset != max_palette_offset[i]) {
 
				is_consistent = false;
 
				break;
 
			}
 
		}
 
	}
 

	
 
	/* When the Action1 sets are unknown, everything should be 0 (no spriteset usage) or UINT16_MAX (some spriteset usage) */
 
	assert(use_cur_spritesets || (is_consistent && (dts->consistent_max_offset == 0 || dts->consistent_max_offset == UINT16_MAX)));
 

	
 
	if (!is_consistent || dts->registers != NULL) {
 
		dts->consistent_max_offset = 0;
 
		if (dts->registers == NULL) dts->AllocateRegisters();
 

	
 
		for (uint i = 0; i < num_building_sprites + 1; i++) {
 
			TileLayoutRegisters &regs = const_cast<TileLayoutRegisters&>(dts->registers[i]);
 
			regs.max_sprite_offset = max_sprite_offset[i];
 
			regs.max_palette_offset = max_palette_offset[i];
 
		}
 
	}
 

	
 
	return false;
 
}
 

	
 
@@ -1584,6 +1629,7 @@ static ChangeInfoResult StationChangeInf
 

	
 
				for (uint t = 0; t < statspec->tiles; t++) {
 
					NewGRFSpriteLayout *dts = &statspec->renderdata[t];
 
					dts->consistent_max_offset = UINT16_MAX; // Spritesets are unknown, so no limit.
 

	
 
					if (buf->HasData(4) && *(uint32*)buf->Data() == 0) {
 
						buf->Skip(4);
 
@@ -4403,13 +4449,6 @@ static void NewSpriteGroup(ByteReader *b
 
					assert(TileLayoutSpriteGroup::CanAllocateItem());
 
					TileLayoutSpriteGroup *group = new TileLayoutSpriteGroup();
 
					act_group = group;
 
					/* num_building_stages should be 1, if we are only using non-custom sprites */
 
					if (_cur.HasValidSpriteSets(feature)) {
 
						/* This assumes that all spritesets have the same number of sprites. */
 
						group->num_building_stages = max(1u, _cur.GetNumEnts(feature, 0));
 
					} else {
 
						group->num_building_stages = 1;
 
					}
 

	
 
					/* On error, bail out immediately. Temporary GRF data was already freed */
 
					if (ReadSpriteLayout(buf, num_building_sprites, true, feature, false, type == 0, &group->dts)) return;
src/newgrf_commons.cpp
Show inline comments
 
@@ -571,10 +571,11 @@ void NewGRFSpriteLayout::AllocateRegiste
 
 * @param orig_offset          Offset to apply to non-action-1 sprites.
 
 * @param newgrf_ground_offset Offset to apply to action-1 ground sprites.
 
 * @param newgrf_offset        Offset to apply to action-1 non-ground sprites.
 
 * @param constr_stage         Construction stage (0-3) to apply to all action-1 sprites.
 
 * @param separate_ground      Whether the ground sprite shall be resolved by a separate action-1-2-3 chain by default.
 
 * @return Bitmask of values for variable 10 to resolve action-1-2-3 chains for.
 
 */
 
uint32 NewGRFSpriteLayout::PrepareLayout(uint32 orig_offset, uint32 newgrf_ground_offset, uint32 newgrf_offset, bool separate_ground) const
 
uint32 NewGRFSpriteLayout::PrepareLayout(uint32 orig_offset, uint32 newgrf_ground_offset, uint32 newgrf_offset, uint constr_stage, bool separate_ground) const
 
{
 
	result_seq.Clear();
 
	uint32 var10_values = 0;
 
@@ -611,6 +612,7 @@ uint32 NewGRFSpriteLayout::PrepareLayout
 
		if (!(flags & TLF_SPRITE)) {
 
			if (HasBit(result->image.sprite, SPRITE_MODIFIER_CUSTOM_SPRITE)) {
 
				result->image.sprite += ground ? newgrf_ground_offset : newgrf_offset;
 
				if (constr_stage > 0 && regs != NULL) result->image.sprite += GetConstructionStageOffset(constr_stage, regs->max_sprite_offset);
 
			} else {
 
				result->image.sprite += orig_offset;
 
			}
 
@@ -626,6 +628,7 @@ uint32 NewGRFSpriteLayout::PrepareLayout
 
		if (!(flags & TLF_PALETTE)) {
 
			if (HasBit(result->image.pal, SPRITE_MODIFIER_CUSTOM_SPRITE)) {
 
				result->image.sprite += ground ? newgrf_ground_offset : newgrf_offset;
 
				if (constr_stage > 0 && regs != NULL) result->image.sprite += GetConstructionStageOffset(constr_stage, regs->max_palette_offset);
 
			}
 
		}
 

	
 
@@ -663,7 +666,14 @@ void NewGRFSpriteLayout::ProcessRegister
 
					result->image.sprite = 0;
 
				} else {
 
					if (HasBit(result->image.sprite, SPRITE_MODIFIER_CUSTOM_SPRITE)) result->image.sprite += resolved_sprite;
 
					if (flags & TLF_SPRITE) result->image.sprite += (int16)GetRegister(regs->sprite); // mask to 16 bits to avoid trouble
 
					if (flags & TLF_SPRITE) {
 
						int16 offset = (int16)GetRegister(regs->sprite); // mask to 16 bits to avoid trouble
 
						if (!HasBit(result->image.sprite, SPRITE_MODIFIER_CUSTOM_SPRITE) || (offset >= 0 && offset < regs->max_sprite_offset)) {
 
							result->image.sprite += offset;
 
						} else {
 
							result->image.sprite = SPR_IMG_QUERY;
 
						}
 
					}
 

	
 
					if (result->IsParentSprite()) {
 
						if (flags & TLF_BB_XY_OFFSET) {
 
@@ -686,7 +696,15 @@ void NewGRFSpriteLayout::ProcessRegister
 
			if (var10 == resolved_var10) {
 
				/* Apply registers */
 
				if (HasBit(result->image.pal, SPRITE_MODIFIER_CUSTOM_SPRITE)) result->image.pal += resolved_sprite;
 
				if (flags & TLF_PALETTE) result->image.pal += (int16)GetRegister(regs->palette); // mask to 16 bits to avoid trouble
 
				if (flags & TLF_PALETTE) {
 
					int16 offset = (int16)GetRegister(regs->palette); // mask to 16 bits to avoid trouble
 
					if (!HasBit(result->image.pal, SPRITE_MODIFIER_CUSTOM_SPRITE) || (offset >= 0 && offset < regs->max_palette_offset)) {
 
						result->image.pal += offset;
 
					} else {
 
						result->image.sprite = SPR_IMG_QUERY;
 
						result->image.pal = PAL_NONE;
 
					}
 
				}
 
			}
 
		}
 

	
src/newgrf_commons.h
Show inline comments
 
@@ -96,6 +96,8 @@ struct TileLayoutRegisters {
 
	uint8 dodraw;          ///< Register deciding whether the sprite shall be drawn at all. Non-zero means drawing.
 
	uint8 sprite;          ///< Register specifying a signed offset for the sprite.
 
	uint8 palette;         ///< Register specifying a signed offset for the palette.
 
	uint16 max_sprite_offset;  ///< Maximum offset to add to the sprite. (limited by size of the spriteset)
 
	uint16 max_palette_offset; ///< Maximum offset to add to the palette. (limited by size of the spriteset)
 
	union {
 
		uint8 parent[3];   ///< Registers for signed offsets for the bounding box position of parent sprites.
 
		uint8 child[2];    ///< Registers for signed offsets for the position of child sprites.
 
@@ -114,6 +116,12 @@ static const uint TLR_MAX_VAR10 = 7; ///
 
struct NewGRFSpriteLayout : ZeroedMemoryAllocator, DrawTileSprites {
 
	const TileLayoutRegisters *registers;
 

	
 
	/**
 
	 * Number of sprites in all referenced spritesets.
 
	 * If these numbers are inconsistent, then this is 0 and the real values are in \c registers.
 
	 */
 
	uint consistent_max_offset;
 

	
 
	void Allocate(uint num_sprites);
 
	void AllocateRegisters();
 
	void Clone(const DrawTileSeqStruct *source);
 
@@ -147,7 +155,7 @@ struct NewGRFSpriteLayout : ZeroedMemory
 
		return this->registers != NULL;
 
	}
 

	
 
	uint32 PrepareLayout(uint32 orig_offset, uint32 newgrf_ground_offset, uint32 newgrf_offset, bool separate_ground) const;
 
	uint32 PrepareLayout(uint32 orig_offset, uint32 newgrf_ground_offset, uint32 newgrf_offset, uint constr_stage, bool separate_ground) const;
 
	void ProcessRegisters(uint8 resolved_var10, uint32 resolved_sprite, bool separate_ground) const;
 

	
 
	/**
src/newgrf_spritegroup.cpp
Show inline comments
 
@@ -236,12 +236,14 @@ const SpriteGroup *RealSpriteGroup::Reso
 
 */
 
const DrawTileSprites *TileLayoutSpriteGroup::ProcessRegisters(uint8 *stage) const
 
{
 
	if (stage != NULL) *stage = GetConstructionStageOffset(*stage, this->num_building_stages);
 
	if (!this->dts.NeedsPreprocessing()) return &this->dts;
 
	if (!this->dts.NeedsPreprocessing()) {
 
		if (stage != NULL && this->dts.consistent_max_offset > 0) *stage = GetConstructionStageOffset(*stage, this->dts.consistent_max_offset);
 
		return &this->dts;
 
	}
 

	
 
	static DrawTileSprites result;
 
	uint8 actual_stage = stage != NULL ? *stage : 0;
 
	this->dts.PrepareLayout(0, actual_stage, actual_stage, false);
 
	this->dts.PrepareLayout(0, 0, 0, actual_stage, false);
 
	this->dts.ProcessRegisters(0, 0, false);
 
	result.seq = this->dts.GetLayout(&result.ground);
 

	
src/newgrf_spritegroup.h
Show inline comments
 
@@ -288,7 +288,6 @@ struct TileLayoutSpriteGroup : SpriteGro
 
	TileLayoutSpriteGroup() : SpriteGroup(SGT_TILELAYOUT) {}
 
	~TileLayoutSpriteGroup() {}
 

	
 
	byte num_building_stages;    ///< Number of building stages to show for this house/industry tile
 
	NewGRFSpriteLayout dts;
 

	
 
	const DrawTileSprites *ProcessRegisters(uint8 *stage) const;
src/newgrf_station.cpp
Show inline comments
 
@@ -838,7 +838,7 @@ bool DrawStationTile(int x, int y, RailT
 
	if (layout != NULL) {
 
		/* Sprite layout which needs preprocessing */
 
		bool separate_ground = HasBit(statspec->flags, SSF_SEPARATE_GROUND);
 
		uint32 var10_values = layout->PrepareLayout(total_offset, rti->fallback_railtype, 0, separate_ground);
 
		uint32 var10_values = layout->PrepareLayout(total_offset, rti->fallback_railtype, 0, 0, separate_ground);
 
		uint8 var10;
 
		FOR_EACH_SET_BIT(var10, var10_values) {
 
			uint32 var10_relocation = GetCustomStationRelocation(statspec, NULL, INVALID_TILE, var10);
src/station_cmd.cpp
Show inline comments
 
@@ -2687,7 +2687,7 @@ draw_default_foundation:
 
		if (layout != NULL) {
 
			/* Sprite layout which needs preprocessing */
 
			bool separate_ground = HasBit(statspec->flags, SSF_SEPARATE_GROUND);
 
			uint32 var10_values = layout->PrepareLayout(total_offset, rti->fallback_railtype, 0, separate_ground);
 
			uint32 var10_values = layout->PrepareLayout(total_offset, rti->fallback_railtype, 0, 0, separate_ground);
 
			uint8 var10;
 
			FOR_EACH_SET_BIT(var10, var10_values) {
 
				uint32 var10_relocation = GetCustomStationRelocation(statspec, st, ti->tile, var10);
0 comments (0 inline, 0 general)