texteff.c
branchcustombridgeheads
changeset 5623 ef2a8a524a95
parent 5026 c8b7148798ac
equal deleted inserted replaced
5622:2f0cb276d32a 5623:ef2a8a524a95
    14 #include "variables.h"
    14 #include "variables.h"
    15 #include "table/sprites.h"
    15 #include "table/sprites.h"
    16 #include <stdarg.h> /* va_list */
    16 #include <stdarg.h> /* va_list */
    17 #include "date.h"
    17 #include "date.h"
    18 
    18 
       
    19 enum {
       
    20 	MAX_TEXTMESSAGE_LENGTH = 150,
       
    21 	MAX_TEXT_MESSAGES      =  30,
       
    22 	MAX_CHAT_MESSAGES      =  10,
       
    23 	MAX_ANIMATED_TILES     = 256,
       
    24 };
       
    25 
    19 typedef struct TextEffect {
    26 typedef struct TextEffect {
    20 	StringID string_id;
    27 	StringID string_id;
    21 	int32 x;
    28 	int32 x;
    22 	int32 y;
    29 	int32 y;
    23 	int32 right;
    30 	int32 right;
    25 	uint16 duration;
    32 	uint16 duration;
    26 	uint32 params_1;
    33 	uint32 params_1;
    27 	uint32 params_2;
    34 	uint32 params_2;
    28 } TextEffect;
    35 } TextEffect;
    29 
    36 
    30 #define MAX_TEXTMESSAGE_LENGTH 150
       
    31 
    37 
    32 typedef struct TextMessage {
    38 typedef struct TextMessage {
    33 	char message[MAX_TEXTMESSAGE_LENGTH];
    39 	char message[MAX_TEXTMESSAGE_LENGTH];
    34 	uint16 color;
    40 	uint16 color;
    35 	Date end_date;
    41 	Date end_date;
    36 } TextMessage;
    42 } TextMessage;
    37 
    43 
    38 #define MAX_CHAT_MESSAGES 10
    44 static TextEffect _text_effect_list[MAX_TEXT_MESSAGES];
    39 static TextEffect _text_effect_list[30];
       
    40 static TextMessage _textmsg_list[MAX_CHAT_MESSAGES];
    45 static TextMessage _textmsg_list[MAX_CHAT_MESSAGES];
    41 TileIndex _animated_tile_list[256];
    46 TileIndex _animated_tile_list[MAX_ANIMATED_TILES];
    42 
    47 
    43 static bool _textmessage_dirty = false;
    48 static bool _textmessage_dirty = false;
    44 static bool _textmessage_visible = false;
    49 static bool _textmessage_visible = false;
    45 
    50 
    46 /* The chatbox grows from the bottom so the coordinates are pixels from
    51 /* The chatbox grows from the bottom so the coordinates are pixels from
   111 	for (i = 0; i < MAX_CHAT_MESSAGES; i++) {
   116 	for (i = 0; i < MAX_CHAT_MESSAGES; i++) {
   112 		_textmsg_list[i].message[0] = '\0';
   117 		_textmsg_list[i].message[0] = '\0';
   113 	}
   118 	}
   114 }
   119 }
   115 
   120 
   116 // Hide the textbox
   121 /* Hide the textbox */
   117 void UndrawTextMessage(void)
   122 void UndrawTextMessage(void)
   118 {
   123 {
   119 	if (_textmessage_visible) {
   124 	if (_textmessage_visible) {
   120 		// Sometimes we also need to hide the cursor
   125 		/* Sometimes we also need to hide the cursor
   121 		//   This is because both textmessage and the cursor take a shot of the
   126 		 *   This is because both textmessage and the cursor take a shot of the
   122 		//   screen before drawing.
   127 		 *   screen before drawing.
   123 		//   Now the textmessage takes his shot and paints his data before the cursor
   128 		 *   Now the textmessage takes his shot and paints his data before the cursor
   124 		//   does, so in the shot of the cursor is the screen-data of the textmessage
   129 		 *   does, so in the shot of the cursor is the screen-data of the textmessage
   125 		//   included when the cursor hangs somewhere over the textmessage. To
   130 		 *   included when the cursor hangs somewhere over the textmessage. To
   126 		//   avoid wrong repaints, we undraw the cursor in that case, and everything
   131 		 *   avoid wrong repaints, we undraw the cursor in that case, and everything
   127 		//   looks nicely ;)
   132 		 *   looks nicely ;)
   128 		// (and now hope this story above makes sense to you ;))
   133 		 * (and now hope this story above makes sense to you ;))
       
   134 		 */
   129 
   135 
   130 		if (_cursor.visible) {
   136 		if (_cursor.visible) {
   131 			if (_cursor.draw_pos.x + _cursor.draw_size.x >= _textmsg_box.x &&
   137 			if (_cursor.draw_pos.x + _cursor.draw_size.x >= _textmsg_box.x &&
   132 				_cursor.draw_pos.x <= _textmsg_box.x + _textmsg_box.width &&
   138 				_cursor.draw_pos.x <= _textmsg_box.x + _textmsg_box.width &&
   133 				_cursor.draw_pos.y + _cursor.draw_size.y >= _screen.height - _textmsg_box.y - _textmsg_box.height &&
   139 				_cursor.draw_pos.y + _cursor.draw_size.y >= _screen.height - _textmsg_box.y - _textmsg_box.height &&
   135 				UndrawMouseCursor();
   141 				UndrawMouseCursor();
   136 			}
   142 			}
   137 		}
   143 		}
   138 
   144 
   139 		_textmessage_visible = false;
   145 		_textmessage_visible = false;
   140 		// Put our 'shot' back to the screen
   146 		/* Put our 'shot' back to the screen */
   141 		memcpy_pitch(
   147 		memcpy_pitch(
   142 			_screen.dst_ptr + _textmsg_box.x + (_screen.height - _textmsg_box.y - _textmsg_box.height) * _screen.pitch,
   148 			_screen.dst_ptr + _textmsg_box.x + (_screen.height - _textmsg_box.y - _textmsg_box.height) * _screen.pitch,
   143 			_textmessage_backup,
   149 			_textmessage_backup,
   144 			_textmsg_box.width, _textmsg_box.height, _textmsg_box.width, _screen.pitch);
   150 			_textmsg_box.width, _textmsg_box.height, _textmsg_box.width, _screen.pitch);
   145 
   151 
   146 		// And make sure it is updated next time
   152 		/* And make sure it is updated next time */
   147 		_video_driver->make_dirty(_textmsg_box.x, _screen.height - _textmsg_box.y - _textmsg_box.height, _textmsg_box.width, _textmsg_box.height);
   153 		_video_driver->make_dirty(_textmsg_box.x, _screen.height - _textmsg_box.y - _textmsg_box.height, _textmsg_box.width, _textmsg_box.height);
   148 
   154 
   149 		_textmessage_dirty = true;
   155 		_textmessage_dirty = true;
   150 	}
   156 	}
   151 }
   157 }
   152 
   158 
   153 // Check if a message is expired every day
   159 /* Check if a message is expired every day */
   154 void TextMessageDailyLoop(void)
   160 void TextMessageDailyLoop(void)
   155 {
   161 {
   156 	uint i;
   162 	uint i;
   157 
   163 
   158 	for (i = 0; i < MAX_CHAT_MESSAGES; i++) {
   164 	for (i = 0; i < MAX_CHAT_MESSAGES; i++) {
   172 			i--;
   178 			i--;
   173 		}
   179 		}
   174 	}
   180 	}
   175 }
   181 }
   176 
   182 
   177 // Draw the textmessage-box
   183 /* Draw the textmessage-box */
   178 void DrawTextMessage(void)
   184 void DrawTextMessage(void)
   179 {
   185 {
   180 	uint y, count;
   186 	uint y, count;
   181 
   187 
   182 	if (!_textmessage_dirty) return;
   188 	if (!_textmessage_dirty) return;
   183 
   189 
   184 	// First undraw if needed
   190 	/* First undraw if needed */
   185 	UndrawTextMessage();
   191 	UndrawTextMessage();
   186 
   192 
   187 	if (_iconsole_mode == ICONSOLE_FULL) return;
   193 	if (_iconsole_mode == ICONSOLE_FULL) return;
   188 
   194 
   189 	/* Check if we have anything to draw at all */
   195 	/* Check if we have anything to draw at all */
   190 	count = GetTextMessageCount();
   196 	count = GetTextMessageCount();
   191 	if (count == 0) return;
   197 	if (count == 0) return;
   192 
   198 
   193 	// Make a copy of the screen as it is before painting (for undraw)
   199 	/* Make a copy of the screen as it is before painting (for undraw) */
   194 	memcpy_pitch(
   200 	memcpy_pitch(
   195 		_textmessage_backup,
   201 		_textmessage_backup,
   196 		_screen.dst_ptr + _textmsg_box.x + (_screen.height - _textmsg_box.y - _textmsg_box.height) * _screen.pitch,
   202 		_screen.dst_ptr + _textmsg_box.x + (_screen.height - _textmsg_box.y - _textmsg_box.height) * _screen.pitch,
   197 		_textmsg_box.width, _textmsg_box.height, _screen.pitch, _textmsg_box.width);
   203 		_textmsg_box.width, _textmsg_box.height, _screen.pitch, _textmsg_box.width);
   198 
   204 
   210 	/* Paint the messages starting with the lowest at the bottom */
   216 	/* Paint the messages starting with the lowest at the bottom */
   211 	for (y = 13; count-- != 0; y += 13) {
   217 	for (y = 13; count-- != 0; y += 13) {
   212 		DoDrawString(_textmsg_list[count].message, _textmsg_box.x + 3, _screen.height - _textmsg_box.y - y + 1, _textmsg_list[count].color);
   218 		DoDrawString(_textmsg_list[count].message, _textmsg_box.x + 3, _screen.height - _textmsg_box.y - y + 1, _textmsg_list[count].color);
   213  	}
   219  	}
   214 
   220 
   215 	// Make sure the data is updated next flush
   221 	/* Make sure the data is updated next flush */
   216 	_video_driver->make_dirty(_textmsg_box.x, _screen.height - _textmsg_box.y - _textmsg_box.height, _textmsg_box.width, _textmsg_box.height);
   222 	_video_driver->make_dirty(_textmsg_box.x, _screen.height - _textmsg_box.y - _textmsg_box.height, _textmsg_box.width, _textmsg_box.height);
   217 
   223 
   218 	_textmessage_visible = true;
   224 	_textmessage_visible = true;
   219 	_textmessage_dirty = false;
   225 	_textmessage_dirty = false;
   220 }
   226 }
   317 	}
   323 	}
   318 }
   324 }
   319 
   325 
   320 void DeleteAnimatedTile(TileIndex tile)
   326 void DeleteAnimatedTile(TileIndex tile)
   321 {
   327 {
   322 	TileIndex* ti;
   328 	TileIndex *ti;
   323 
   329 
   324 	for (ti = _animated_tile_list; ti != endof(_animated_tile_list); ti++) {
   330 	for (ti = _animated_tile_list; ti != endof(_animated_tile_list); ti++) {
   325 		if (tile == *ti) {
   331 		if (tile == *ti) {
   326 			/* remove the hole */
   332 			/* remove the hole */
   327 			memmove(ti, ti + 1, endof(_animated_tile_list) - 1 - ti);
   333 			memmove(ti, ti + 1, (lastof(_animated_tile_list) - ti) * sizeof(*ti));
   328 			/* and clear last item */
   334 			/* and clear last item */
   329 			endof(_animated_tile_list)[-1] = 0;
   335 			*lastof(_animated_tile_list) = 0;
   330 			MarkTileDirtyByTile(tile);
   336 			MarkTileDirtyByTile(tile);
   331 			return;
   337 			return;
   332 		}
   338 		}
   333 	}
   339 	}
   334 }
   340 }
   335 
   341 
   336 bool AddAnimatedTile(TileIndex tile)
   342 bool AddAnimatedTile(TileIndex tile)
   337 {
   343 {
   338 	TileIndex* ti;
   344 	TileIndex *ti;
   339 
   345 
   340 	for (ti = _animated_tile_list; ti != endof(_animated_tile_list); ti++) {
   346 	for (ti = _animated_tile_list; ti != endof(_animated_tile_list); ti++) {
   341 		if (tile == *ti || *ti == 0) {
   347 		if (tile == *ti || *ti == 0) {
   342 			*ti = tile;
   348 			*ti = tile;
   343 			MarkTileDirtyByTile(tile);
   349 			MarkTileDirtyByTile(tile);
   362 	memset(_animated_tile_list, 0, sizeof(_animated_tile_list));
   368 	memset(_animated_tile_list, 0, sizeof(_animated_tile_list));
   363 }
   369 }
   364 
   370 
   365 static void SaveLoad_ANIT(void)
   371 static void SaveLoad_ANIT(void)
   366 {
   372 {
   367 	// In pre version 6, we has 16bit per tile, now we have 32bit per tile, convert it ;)
   373 	/* In pre version 6, we has 16bit per tile, now we have 32bit per tile, convert it ;) */
   368 	if (CheckSavegameVersion(6)) {
   374 	if (CheckSavegameVersion(6)) {
   369 		SlArray(_animated_tile_list, lengthof(_animated_tile_list), SLE_FILE_U16 | SLE_VAR_U32);
   375 		SlArray(_animated_tile_list, lengthof(_animated_tile_list), SLE_FILE_U16 | SLE_VAR_U32);
   370 	} else {
   376 	} else {
   371 		SlArray(_animated_tile_list, lengthof(_animated_tile_list), SLE_UINT32);
   377 		SlArray(_animated_tile_list, lengthof(_animated_tile_list), SLE_UINT32);
   372 	}
   378 	}