00001 /* $Id$ */ 00002 00003 /* 00004 * This file is part of OpenTTD. 00005 * OpenTTD 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, version 2. 00006 * 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. 00007 * 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/>. 00008 */ 00009 00012 #include "stdafx.h" 00013 #include "core/alloc_func.hpp" 00014 #include "tile_cmd.h" 00015 #include "viewport_func.h" 00016 00018 TileIndex *_animated_tile_list = NULL; 00020 uint _animated_tile_count = 0; 00022 uint _animated_tile_allocated = 0; 00023 00028 void DeleteAnimatedTile(TileIndex tile) 00029 { 00030 for (TileIndex *ti = _animated_tile_list; ti < _animated_tile_list + _animated_tile_count; ti++) { 00031 if (tile == *ti) { 00032 /* Remove the hole 00033 * The order of the remaining elements must stay the same, otherwise the animation loop 00034 * may miss a tile; that's why we must use memmove instead of just moving the last element. 00035 */ 00036 memmove(ti, ti + 1, (_animated_tile_list + _animated_tile_count - (ti + 1)) * sizeof(*ti)); 00037 _animated_tile_count--; 00038 MarkTileDirtyByTile(tile); 00039 return; 00040 } 00041 } 00042 } 00043 00049 void AddAnimatedTile(TileIndex tile) 00050 { 00051 MarkTileDirtyByTile(tile); 00052 00053 for (const TileIndex *ti = _animated_tile_list; ti < _animated_tile_list + _animated_tile_count; ti++) { 00054 if (tile == *ti) return; 00055 } 00056 00057 /* Table not large enough, so make it larger */ 00058 if (_animated_tile_count == _animated_tile_allocated) { 00059 _animated_tile_allocated *= 2; 00060 _animated_tile_list = ReallocT<TileIndex>(_animated_tile_list, _animated_tile_allocated); 00061 } 00062 00063 _animated_tile_list[_animated_tile_count] = tile; 00064 _animated_tile_count++; 00065 } 00066 00070 void AnimateAnimatedTiles() 00071 { 00072 const TileIndex *ti = _animated_tile_list; 00073 while (ti < _animated_tile_list + _animated_tile_count) { 00074 const TileIndex curr = *ti; 00075 AnimateTile(curr); 00076 /* During the AnimateTile call, DeleteAnimatedTile could have been called, 00077 * deleting an element we've already processed and pushing the rest one 00078 * slot to the left. We can detect this by checking whether the index 00079 * in the current slot has changed - if it has, an element has been deleted, 00080 * and we should process the current slot again instead of going forward. 00081 * NOTE: this will still break if more than one animated tile is being 00082 * deleted during the same AnimateTile call, but no code seems to 00083 * be doing this anyway. 00084 */ 00085 if (*ti == curr) ++ti; 00086 } 00087 } 00088 00092 void InitializeAnimatedTiles() 00093 { 00094 _animated_tile_list = ReallocT<TileIndex>(_animated_tile_list, 256); 00095 _animated_tile_count = 0; 00096 _animated_tile_allocated = 256; 00097 }