Changeset - r25183:289c3db1f02c
[Not reviewed]
master
0 1 0
Peter Nelson - 3 years ago 2021-04-11 22:26:57
peter1138@openttd.org
Feature: Show previous chat history when the chat message box is open
1 file changed with 37 insertions and 6 deletions:
0 comments (0 inline, 0 general)
src/network/network_chat_gui.cpp
Show inline comments
 
@@ -49,19 +49,42 @@ static std::deque<ChatMessage> _chatmsg_
 
static bool _chatmessage_dirty = false;   ///< Does the chat message need repainting?
 
static bool _chatmessage_visible = false; ///< Is a chat message visible.
 
static bool _chat_tab_completion_active;  ///< Whether tab completion is active.
 
static uint MAX_CHAT_MESSAGES = 0;        ///< The limit of chat messages to show.
 

	
 
/**
 
 * Time the chat history was marked dirty. This is used to determine if expired
 
 * messages have recently expired and should cause a redraw to hide them.
 
 */
 
static std::chrono::steady_clock::time_point _chatmessage_dirty_time;
 

	
 
/**
 
 * The chatbox grows from the bottom so the coordinates are pixels from
 
 * the left and pixels from the bottom. The height is the maximum height.
 
 */
 
static PointDimension _chatmsg_box;
 
static uint8 *_chatmessage_backup = nullptr; ///< Backup in case text is moved.
 

	
 
/**
 
 * Test if there are any chat messages to display.
 
 * @param show_all Set if all messages should be included, instead of unexpired only.
 
 * @return True iff there are chat messages to display.
 
 */
 
static inline bool HaveChatMessages(bool show_all)
 
{
 
	if (show_all) return _chatmsg_list.size() != 0;
 

	
 
	auto now = std::chrono::steady_clock::now();
 
	for (auto &cmsg : _chatmsg_list) {
 
		if (cmsg.remove_time >= now) return true;
 
	}
 

	
 
	return false;
 
}
 

	
 
/**
 
 * Add a text message to the 'chat window' to be shown
 
 * @param colour The colour this message is to be shown in
 
 * @param duration The duration of the chat message in seconds
 
 * @param message message itself in printf() style
 
 */
 
void CDECL NetworkAddChatMessage(TextColour colour, uint duration, const char *message, ...)
 
@@ -81,12 +104,13 @@ void CDECL NetworkAddChatMessage(TextCol
 

	
 
	ChatMessage *cmsg = &_chatmsg_list.emplace_front();
 
	strecpy(cmsg->message, buf, lastof(cmsg->message));
 
	cmsg->colour = (colour & TC_IS_PALETTE_COLOUR) ? colour : TC_WHITE;
 
	cmsg->remove_time = std::chrono::steady_clock::now() + std::chrono::seconds(duration);
 

	
 
	_chatmessage_dirty_time = std::chrono::steady_clock::now();
 
	_chatmessage_dirty = true;
 
}
 

	
 
/** Initialize all font-dependent chat box sizes. */
 
void NetworkReInitChatBoxSize()
 
{
 
@@ -146,43 +170,47 @@ void NetworkUndrawChatMessage()
 
		_chatmessage_visible = false;
 
		/* Put our 'shot' back to the screen */
 
		blitter->CopyFromBuffer(blitter->MoveTo(_screen.dst_ptr, x, y), _chatmessage_backup, width, height);
 
		/* And make sure it is updated next time */
 
		VideoDriver::GetInstance()->MakeDirty(x, y, width, height);
 

	
 
		_chatmessage_dirty_time = std::chrono::steady_clock::now();
 
		_chatmessage_dirty = true;
 
	}
 
}
 

	
 
/** Check if a message is expired. */
 
void NetworkChatMessageLoop()
 
{
 
	for (auto it = _chatmsg_list.begin(); it != _chatmsg_list.end();) {
 
	auto now = std::chrono::steady_clock::now();
 
	for (auto &cmsg : _chatmsg_list) {
 
		/* Message has expired, remove from the list */
 
		if (std::chrono::steady_clock::now() > it->remove_time) {
 
			it = _chatmsg_list.erase(it);
 
		if (now > cmsg.remove_time && _chatmessage_dirty_time < cmsg.remove_time) {
 
			_chatmessage_dirty_time = now;
 
			_chatmessage_dirty = true;
 
		} else {
 
			it++;
 
			break;
 
		}
 
	}
 
}
 

	
 
/** Draw the chat message-box */
 
void NetworkDrawChatMessage()
 
{
 
	Blitter *blitter = BlitterFactory::GetCurrentBlitter();
 
	if (!_chatmessage_dirty) return;
 

	
 
	const Window *w = FindWindowByClass(WC_SEND_NETWORK_MSG);
 
	bool show_all = (w != nullptr);
 

	
 
	/* First undraw if needed */
 
	NetworkUndrawChatMessage();
 

	
 
	if (_iconsole_mode == ICONSOLE_FULL) return;
 

	
 
	/* Check if we have anything to draw at all */
 
	if (_chatmsg_list.size() == 0) return;
 
	if (!HaveChatMessages(show_all)) return;
 

	
 
	int x      = _chatmsg_box.x;
 
	int y      = _screen.height - _chatmsg_box.y - _chatmsg_box.height;
 
	int width  = _chatmsg_box.width;
 
	int height = _chatmsg_box.height;
 
	if (y < 0) {
 
@@ -198,14 +226,16 @@ void NetworkDrawChatMessage()
 

	
 
	/* Make a copy of the screen as it is before painting (for undraw) */
 
	blitter->CopyToBuffer(blitter->MoveTo(_screen.dst_ptr, x, y), _chatmessage_backup, width, height);
 

	
 
	_cur_dpi = &_screen; // switch to _screen painting
 

	
 
	auto now = std::chrono::steady_clock::now();
 
	int string_height = 0;
 
	for (auto &cmsg : _chatmsg_list) {
 
		if (!show_all && cmsg.remove_time < now) continue;
 
		SetDParamStr(0, cmsg.message);
 
		string_height += GetStringLineCount(STR_JUST_RAW_STRING, width - 1) * FONT_HEIGHT_NORMAL + NETWORK_CHAT_LINE_SPACING;
 
	}
 

	
 
	string_height = std::min<uint>(string_height, MAX_CHAT_MESSAGES * (FONT_HEIGHT_NORMAL + NETWORK_CHAT_LINE_SPACING));
 

	
 
@@ -217,12 +247,13 @@ void NetworkDrawChatMessage()
 
		);
 

	
 
	/* Paint the chat messages starting with the lowest at the bottom */
 
	int ypos = bottom - 2;
 

	
 
	for (auto &cmsg : _chatmsg_list) {
 
		if (!show_all && cmsg.remove_time < now) continue;
 
		ypos = DrawStringMultiLine(_chatmsg_box.x + 3, _chatmsg_box.x + _chatmsg_box.width - 1, top, ypos, cmsg.message, cmsg.colour, SA_LEFT | SA_BOTTOM | SA_FORCE) - NETWORK_CHAT_LINE_SPACING;
 
		if (ypos < top) break;
 
	}
 

	
 
	/* Make sure the data is updated next flush */
 
	VideoDriver::GetInstance()->MakeDirty(x, y, width, height);
0 comments (0 inline, 0 general)