10294
|
1 |
/* $Id$ */
|
|
2 |
|
|
3 |
/** @file animated_tile.cpp Everything related to animated tiles. */
|
|
4 |
|
|
5 |
#include "stdafx.h"
|
|
6 |
#include "openttd.h"
|
|
7 |
#include "saveload.h"
|
|
8 |
#include "landscape.h"
|
|
9 |
#include "core/alloc_func.hpp"
|
|
10 |
#include "functions.h"
|
|
11 |
|
|
12 |
/** The table/list with animated tiles. */
|
|
13 |
TileIndex *_animated_tile_list = NULL;
|
|
14 |
/** The number of animated tiles in the current state. */
|
|
15 |
uint _animated_tile_count = 0;
|
|
16 |
/** The number of slots for animated tiles allocated currently. */
|
|
17 |
static uint _animated_tile_allocated = 0;
|
|
18 |
|
|
19 |
/**
|
|
20 |
* Removes the given tile from the animated tile table.
|
|
21 |
* @param tile the tile to remove
|
|
22 |
*/
|
|
23 |
void DeleteAnimatedTile(TileIndex tile)
|
|
24 |
{
|
|
25 |
for (TileIndex *ti = _animated_tile_list; ti < _animated_tile_list + _animated_tile_count; ti++) {
|
|
26 |
if (tile == *ti) {
|
|
27 |
/* Remove the hole
|
|
28 |
* The order of the remaining elements must stay the same, otherwise the animation loop
|
|
29 |
* may miss a tile; that's why we must use memmove instead of just moving the last element.
|
|
30 |
*/
|
|
31 |
memmove(ti, ti + 1, (_animated_tile_list + _animated_tile_count - (ti + 1)) * sizeof(*ti));
|
|
32 |
_animated_tile_count--;
|
|
33 |
MarkTileDirtyByTile(tile);
|
|
34 |
return;
|
|
35 |
}
|
|
36 |
}
|
|
37 |
}
|
|
38 |
|
|
39 |
/**
|
|
40 |
* Add the given tile to the animated tile table (if it does not exist
|
|
41 |
* on that table yet). Also increases the size of the table if necessary.
|
|
42 |
* @param tile the tile to make animated
|
|
43 |
*/
|
|
44 |
void AddAnimatedTile(TileIndex tile)
|
|
45 |
{
|
|
46 |
MarkTileDirtyByTile(tile);
|
|
47 |
|
|
48 |
for (const TileIndex *ti = _animated_tile_list; ti < _animated_tile_list + _animated_tile_count; ti++) {
|
|
49 |
if (tile == *ti) return;
|
|
50 |
}
|
|
51 |
|
|
52 |
/* Table not large enough, so make it larger */
|
|
53 |
if (_animated_tile_count == _animated_tile_allocated) {
|
|
54 |
_animated_tile_allocated *= 2;
|
|
55 |
_animated_tile_list = ReallocT<TileIndex>(_animated_tile_list, _animated_tile_allocated);
|
|
56 |
}
|
|
57 |
|
|
58 |
_animated_tile_list[_animated_tile_count] = tile;
|
|
59 |
_animated_tile_count++;
|
|
60 |
}
|
|
61 |
|
|
62 |
/**
|
|
63 |
* Animate all tiles in the animated tile list, i.e.\ call AnimateTile on them.
|
|
64 |
*/
|
|
65 |
void AnimateAnimatedTiles()
|
|
66 |
{
|
|
67 |
const TileIndex *ti = _animated_tile_list;
|
|
68 |
while (ti < _animated_tile_list + _animated_tile_count) {
|
|
69 |
const TileIndex curr = *ti;
|
|
70 |
AnimateTile(curr);
|
|
71 |
/* During the AnimateTile call, DeleteAnimatedTile could have been called,
|
|
72 |
* deleting an element we've already processed and pushing the rest one
|
|
73 |
* slot to the left. We can detect this by checking whether the index
|
|
74 |
* in the current slot has changed - if it has, an element has been deleted,
|
|
75 |
* and we should process the current slot again instead of going forward.
|
|
76 |
* NOTE: this will still break if more than one animated tile is being
|
|
77 |
* deleted during the same AnimateTile call, but no code seems to
|
|
78 |
* be doing this anyway.
|
|
79 |
*/
|
|
80 |
if (*ti == curr) ++ti;
|
|
81 |
}
|
|
82 |
}
|
|
83 |
|
|
84 |
/**
|
|
85 |
* Initialize all animated tile variables to some known begin point
|
|
86 |
*/
|
|
87 |
void InitializeAnimatedTiles()
|
|
88 |
{
|
|
89 |
_animated_tile_list = ReallocT<TileIndex>(_animated_tile_list, 256);
|
|
90 |
_animated_tile_count = 0;
|
|
91 |
_animated_tile_allocated = 256;
|
|
92 |
}
|
|
93 |
|
|
94 |
/**
|
|
95 |
* Save the ANIT chunk.
|
|
96 |
*/
|
|
97 |
static void Save_ANIT()
|
|
98 |
{
|
|
99 |
SlSetLength(_animated_tile_count * sizeof(*_animated_tile_list));
|
|
100 |
SlArray(_animated_tile_list, _animated_tile_count, SLE_UINT32);
|
|
101 |
}
|
|
102 |
|
|
103 |
/**
|
|
104 |
* Load the ANIT chunk; the chunk containing the animated tiles.
|
|
105 |
*/
|
|
106 |
static void Load_ANIT()
|
|
107 |
{
|
|
108 |
/* Before version 80 we did NOT have a variable length animated tile table */
|
|
109 |
if (CheckSavegameVersion(80)) {
|
|
110 |
/* In pre version 6, we has 16bit per tile, now we have 32bit per tile, convert it ;) */
|
|
111 |
SlArray(_animated_tile_list, 256, CheckSavegameVersion(6) ? (SLE_FILE_U16 | SLE_VAR_U32) : SLE_UINT32);
|
|
112 |
|
|
113 |
for (_animated_tile_count = 0; _animated_tile_count < 256; _animated_tile_count++) {
|
|
114 |
if (_animated_tile_list[_animated_tile_count] == 0) break;
|
|
115 |
}
|
|
116 |
return;
|
|
117 |
}
|
|
118 |
|
10776
|
119 |
_animated_tile_count = (uint)SlGetFieldLength() / sizeof(*_animated_tile_list);
|
10294
|
120 |
|
|
121 |
/* Determine a nice rounded size for the amount of allocated tiles */
|
|
122 |
_animated_tile_allocated = 256;
|
|
123 |
while (_animated_tile_allocated < _animated_tile_count) _animated_tile_allocated *= 2;
|
|
124 |
|
|
125 |
_animated_tile_list = ReallocT<TileIndex>(_animated_tile_list, _animated_tile_allocated);
|
|
126 |
SlArray(_animated_tile_list, _animated_tile_count, SLE_UINT32);
|
|
127 |
}
|
|
128 |
|
|
129 |
/**
|
|
130 |
* "Definition" imported by the saveload code to be able to load and save
|
|
131 |
* the animated tile table.
|
|
132 |
*/
|
|
133 |
extern const ChunkHandler _animated_tile_chunk_handlers[] = {
|
|
134 |
{ 'ANIT', Save_ANIT, Load_ANIT, CH_RIFF | CH_LAST},
|
|
135 |
};
|