/** Draw the chat message-box */ void NetworkDrawChatMessage() { Blitter *blitter = BlitterFactoryBase::GetCurrentBlitter(); if (!_chatmessage_dirty) return; /* First undraw if needed */ NetworkUndrawChatMessage(); if (_iconsole_mode == ICONSOLE_FULL) return; /* Check if we have anything to draw at all */ uint count = GetChatMessageCount(); if (count == 0) 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) { height = max(height + y, min(_chatmsg_box.height, _screen.height)); y = 0; } if (x + width >= _screen.width) { width = _screen.width - x; } if (width <= 0 || height <= 0) return; assert(blitter->BufferSize(width, height) <= (int)(_chatmsg_box.width * _chatmsg_box.height * blitter->GetBytesPerPixel())); /* 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 /* Paint a half-transparent box behind the chat messages */ GfxFillRect( _chatmsg_box.x, _screen.height - _chatmsg_box.y - count * (FONT_HEIGHT_NORMAL + NETWORK_CHAT_LINE_SPACING) - 2, _chatmsg_box.x + _chatmsg_box.width - 1, _screen.height - _chatmsg_box.y - 2, PALETTE_TO_TRANSPARENT, FILLRECT_RECOLOUR // black, but with some alpha for background ); /* Paint the chat messages starting with the lowest at the bottom */ for (uint y = FONT_HEIGHT_NORMAL + NETWORK_CHAT_LINE_SPACING; count-- != 0; y += (FONT_HEIGHT_NORMAL + NETWORK_CHAT_LINE_SPACING)) { DrawString(_chatmsg_box.x + 3, _chatmsg_box.x + _chatmsg_box.width - 1, _screen.height - _chatmsg_box.y - y + 1, _chatmsg_list[count].message, _chatmsg_list[count].colour); } /* Make sure the data is updated next flush */ _video_driver->MakeDirty(x, y, width, height); _chatmessage_visible = true; _chatmessage_dirty = false; }
/** Hide the chatbox */ void NetworkUndrawChatMessage() { /* Sometimes we also need to hide the cursor * This is because both textmessage and the cursor take a shot of the * screen before drawing. * Now the textmessage takes his shot and paints his data before the cursor * does, so in the shot of the cursor is the screen-data of the textmessage * included when the cursor hangs somewhere over the textmessage. To * avoid wrong repaints, we undraw the cursor in that case, and everything * looks nicely ;) * (and now hope this story above makes sense to you ;)) */ if (_cursor.visible && _cursor.draw_pos.x + _cursor.draw_size.x >= _chatmsg_box.x && _cursor.draw_pos.x <= _chatmsg_box.x + _chatmsg_box.width && _cursor.draw_pos.y + _cursor.draw_size.y >= _screen.height - _chatmsg_box.y - _chatmsg_box.height && _cursor.draw_pos.y <= _screen.height - _chatmsg_box.y) { UndrawMouseCursor(); } if (_chatmessage_visible) { Blitter *blitter = BlitterFactory::GetCurrentBlitter(); 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) { height = max(height + y, min(_chatmsg_box.height, _screen.height)); y = 0; } if (x + width >= _screen.width) { width = _screen.width - x; } if (width <= 0 || height <= 0) return; _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 */ _video_driver->MakeDirty(x, y, width, height); _chatmessage_dirty = true; } }
/** Draw the chat message-box */ void NetworkDrawChatMessage() { Blitter *blitter = BlitterFactory::GetCurrentBlitter(); if (!_chatmessage_dirty) return; /* First undraw if needed */ NetworkUndrawChatMessage(); if (_iconsole_mode == ICONSOLE_FULL) return; /* Check if we have anything to draw at all */ uint count = GetChatMessageCount(); if (count == 0) 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) { height = max(height + y, min(_chatmsg_box.height, _screen.height)); y = 0; } if (x + width >= _screen.width) { width = _screen.width - x; } if (width <= 0 || height <= 0) return; assert(blitter->BufferSize(width, height) <= (int)(_chatmsg_box.width * _chatmsg_box.height * blitter->GetBytesPerPixel())); /* 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 int string_height = 0; for (uint i = 0; i < count; i++) { SetDParamStr(0, _chatmsg_list[i].message); string_height += GetStringLineCount(STR_JUST_RAW_STRING, width - 1) * FONT_HEIGHT_NORMAL + NETWORK_CHAT_LINE_SPACING; } string_height = min(string_height, MAX_CHAT_MESSAGES * (FONT_HEIGHT_NORMAL + NETWORK_CHAT_LINE_SPACING)); int top = _screen.height - _chatmsg_box.y - string_height - 2; int bottom = _screen.height - _chatmsg_box.y - 2; /* Paint a half-transparent box behind the chat messages */ GfxFillRect(_chatmsg_box.x, top - 2, _chatmsg_box.x + _chatmsg_box.width - 1, bottom, PALETTE_TO_TRANSPARENT, FILLRECT_RECOLOUR // black, but with some alpha for background ); /* Paint the chat messages starting with the lowest at the bottom */ int ypos = bottom - 2; for (int i = count - 1; i >= 0; i--) { ypos = DrawStringMultiLine(_chatmsg_box.x + 3, _chatmsg_box.x + _chatmsg_box.width - 1, top, ypos, _chatmsg_list[i].message, _chatmsg_list[i].colour, SA_LEFT | SA_BOTTOM | SA_FORCE) - NETWORK_CHAT_LINE_SPACING; if (ypos < top) break; } /* Make sure the data is updated next flush */ _video_driver->MakeDirty(x, y, width, height); _chatmessage_visible = true; _chatmessage_dirty = false; }
/** * Callback of the screenshot generator that dumps the current video buffer. * @see ScreenshotCallback */ static void CurrentScreenCallback(void *userdata, void *buf, uint y, uint pitch, uint n) { Blitter *blitter = BlitterFactoryBase::GetCurrentBlitter(); void *src = blitter->MoveTo(_screen.dst_ptr, 0, y); blitter->CopyImageToBuffer(src, buf, _screen.width, n, pitch); }