static void window_loadsave_paint(rct_window *w, rct_drawpixelinfo *dpi) { window_draw_widgets(w, dpi); if (_shortenedDirectory[0] == '\0') { shorten_path(_shortenedDirectory, sizeof(_shortenedDirectory), _directory, w->width - 8); } utf8 buffer[256]; // Format text utf8 *ch = buffer; ch = utf8_write_codepoint(ch, FORMAT_MEDIUMFONT); ch = utf8_write_codepoint(ch, FORMAT_BLACK); safe_strcpy(ch, _shortenedDirectory, sizeof(buffer) - (ch - buffer)); // Draw shadow gfx_draw_string(dpi, buffer, 0, w->x + 4, w->y + 20); rct_string_id id = STR_NONE; // Name button text if (gConfigGeneral.load_save_sort == SORT_NAME_ASCENDING) id = STR_UP; else if (gConfigGeneral.load_save_sort == SORT_NAME_DESCENDING) id = STR_DOWN; gfx_draw_string_centred_clipped(dpi, STR_NAME, &id, 1, w->x + 4 + (w->width - 8) / 4, w->y + 50, (w->width - 8) / 2); // Date button text if (gConfigGeneral.load_save_sort == SORT_DATE_ASCENDING) id = STR_UP; else if (gConfigGeneral.load_save_sort == SORT_DATE_DESCENDING) id = STR_DOWN; else id = STR_NONE; gfx_draw_string_centred_clipped(dpi, STR_DATE, &id, 1, w->x + 4 + (w->width - 8) * 3 / 4, w->y + 50, (w->width - 8) / 2); }
void window_player_overview_paint(rct_window *w, rct_drawpixelinfo *dpi) { window_draw_widgets(w, dpi); window_player_draw_tab_images(dpi, w); sint32 player = network_get_player_index((uint8)w->number); if (player == -1) { return; } // Draw current group sint32 groupindex = network_get_group_index(network_get_player_group(player)); if (groupindex != -1) { rct_widget* widget = &window_player_overview_widgets[WIDX_GROUP]; char buffer[300]; char* lineCh; lineCh = buffer; lineCh = utf8_write_codepoint(lineCh, FORMAT_WINDOW_COLOUR_2); safe_strcpy(lineCh, network_get_group_name(groupindex), sizeof(buffer) - (lineCh - buffer)); set_format_arg(0, const char *, buffer); gfx_draw_string_centred_clipped( dpi, STR_STRING, gCommonFormatArgs, COLOUR_BLACK, w->x + (widget->left + widget->right - 11) / 2, w->y + widget->top, widget->right - widget->left - 8 ); }
void format_string_part_from_raw(utf8 **dest, const utf8 *src, char **args) { unsigned int code; while (1) { code = utf8_get_next(src, &src); if (code < ' ') { if (code == 0) { *(*dest)++ = code; break; } else if (code <= 4) { *(*dest)++ = code; *(*dest)++ = *src++; } else if (code <= 16) { *(*dest)++ = code; } else if (code <= 22) { *(*dest)++ = code; *(*dest)++ = *src++; *(*dest)++ = *src++; } else { *(*dest)++ = code; *(*dest)++ = *src++; *(*dest)++ = *src++; *(*dest)++ = *src++; *(*dest)++ = *src++; } } else if (code <= 'z') { *(*dest)++ = code; } else if (code < FORMAT_COLOUR_CODE_START || code == FORMAT_COMMA1DP16) { format_string_code(code, dest, args); } else { *dest = utf8_write_codepoint(*dest, code); } } }
GameActionResult::Ptr Execute() const override { rct_banner* banner = &gBanners[_bannerIndex]; utf8 *buffer = gCommonStringFormatBuffer; utf8 *dst = buffer; dst = utf8_write_codepoint(dst, FORMAT_COLOUR_CODE_START + banner->text_colour); String::Set(dst, sizeof(gCommonStringFormatBuffer) - (dst - buffer), _name.c_str(), _name.size()); rct_string_id string_id = user_string_allocate(USER_STRING_DUPLICATION_PERMITTED, buffer); if (string_id == 0) { return MakeResult(GA_ERROR::NO_FREE_ELEMENTS, STR_ERR_CANT_SET_BANNER_TEXT); } rct_string_id prev_string_id = banner->string_idx; banner->string_idx = string_id; user_string_free(prev_string_id); auto intent = Intent(INTENT_ACTION_UPDATE_BANNER); intent.putExtra(INTENT_EXTRA_BANNER_INDEX, _bannerIndex); context_broadcast_intent(&intent); return MakeResult(); }
static void window_player_list_scrollpaint(rct_window *w, rct_drawpixelinfo *dpi, int scrollIndex) { int y; gfx_fill_rect(dpi, dpi->x, dpi->y, dpi->x + dpi->width - 1, dpi->y + dpi->height - 1, ColourMapA[w->colours[1]].mid_light); y = 0; for (int i = 0; i < network_get_num_players(); i++) { if (y > dpi->y + dpi->height) { break; } if (y + 11 >= dpi->y) { char buffer[300]; char* lineCh = buffer; int colour = 0; if (i == w->selected_list_item) { gfx_fill_rect(dpi, 0, y, 800, y + 9, 0x02000031); safe_strncpy(&buffer[0], network_get_player_name(i), sizeof(buffer)); colour = w->colours[2]; } else { if (network_get_player_flags(i) & NETWORK_PLAYER_FLAG_ISSERVER) { lineCh = utf8_write_codepoint(lineCh, FORMAT_BABYBLUE); } else { lineCh = utf8_write_codepoint(lineCh, FORMAT_BLACK); } safe_strncpy(lineCh, network_get_player_name(i), sizeof(buffer) - (lineCh - buffer)); } gfx_clip_string(buffer, 230); gfx_draw_string(dpi, buffer, colour, 0, y - 1); lineCh = buffer; int ping = network_get_player_ping(i); if (ping <= 100) { lineCh = utf8_write_codepoint(lineCh, FORMAT_GREEN); } else if (ping <= 250) { lineCh = utf8_write_codepoint(lineCh, FORMAT_YELLOW); } else { lineCh = utf8_write_codepoint(lineCh, FORMAT_RED); } sprintf(lineCh, "%d ms", ping); gfx_draw_string(dpi, buffer, colour, 240, y - 1); } y += 10; } }
void chat_draw() { if (network_get_mode() == NETWORK_MODE_NONE || network_get_status() != NETWORK_STATUS_CONNECTED || network_get_authstatus() != NETWORK_AUTH_OK) { gChatOpen = false; return; } rct_drawpixelinfo *dpi = (rct_drawpixelinfo*)RCT2_ADDRESS_SCREEN_DPI; _chatLeft = 10; _chatTop = RCT2_GLOBAL(RCT2_ADDRESS_SCREEN_HEIGHT, uint16) - 40 - ((CHAT_HISTORY_SIZE + 1) * 10); _chatRight = RCT2_GLOBAL(RCT2_ADDRESS_SCREEN_WIDTH, uint16) - 10; _chatBottom = RCT2_GLOBAL(RCT2_ADDRESS_SCREEN_HEIGHT, uint16) - 45; char lineBuffer[CHAT_INPUT_SIZE + 10]; char* lineCh = lineBuffer; int x = _chatLeft; int y = _chatBottom - (15 * 2); RCT2_GLOBAL(RCT2_ADDRESS_CURRENT_FONT_SPRITE_BASE, uint16) = 224; RCT2_GLOBAL(RCT2_ADDRESS_CURRENT_FONT_FLAGS, uint16) = 0; for (int i = 0; i < CHAT_HISTORY_SIZE; i++, y -= 15) { if (!gChatOpen && SDL_TICKS_PASSED(SDL_GetTicks(), chat_history_get_time(i) + 10000)) { break; } safe_strcpy(lineBuffer, chat_history_get(i), CHAT_INPUT_SIZE + 10); gfx_set_dirty_blocks(x, y, x + gfx_get_string_width(lineBuffer), y + 12); gfx_draw_string(dpi, lineBuffer, 255, x, y); } if (gChatOpen) { lineCh = utf8_write_codepoint(lineCh, FORMAT_OUTLINE); lineCh = utf8_write_codepoint(lineCh, FORMAT_CELADON); safe_strcpy(lineCh, _chatCurrentLine, CHAT_INPUT_SIZE); y = _chatBottom - 15; gfx_set_dirty_blocks(x, y, x + gfx_get_string_width(lineBuffer) + 7, y + 12); gfx_draw_string(dpi, lineBuffer, 255, x, y); if (_chatCaretTicks < 15) { memcpy(lineBuffer, _chatCurrentLine, gTextInput.selection_offset); lineBuffer[gTextInput.selection_offset] = 0; int caretX = x + gfx_get_string_width(lineBuffer); int caretY = y + 15; gfx_fill_rect(dpi, caretX, caretY, caretX + 6, caretY + 1, 0x38); } } }
static void window_network_status_paint(rct_window *w, rct_drawpixelinfo *dpi) { window_draw_widgets(w, dpi); RCT2_GLOBAL(RCT2_ADDRESS_CURRENT_FONT_SPRITE_BASE, uint16) = 224; char buffer[sizeof(window_network_status_text) + 10]; char* lineCh = buffer; lineCh = utf8_write_codepoint(lineCh, FORMAT_BLACK); strcpy(lineCh, window_network_status_text); gfx_clip_string(buffer, 230); int x = w->x + (w->width / 2); int y = w->y + (w->height / 2); x -= gfx_get_string_width(buffer) / 2; gfx_draw_string(dpi, buffer, 0, x, y); }
void textinputbuffer_insert_codepoint(textinputbuffer * tib, uint32 codepoint) { size_t codepointLength = utf8_get_codepoint_length(codepoint); size_t remainingSize = tib->max_size - tib->current_size; if (codepointLength <= remainingSize) { utf8 * insertPtr = tib->buffer + tib->selection_offset; if (tib->selection_offset < tib->current_size) { // Shift bytes (including null terminator) right to make room for new codepoint utf8 * targetShiftPtr = insertPtr + codepointLength; size_t shiftSize = tib->current_size - tib->selection_offset + 1; memmove(targetShiftPtr, insertPtr, shiftSize); } else { // Character is appended onto the end, so set byte after it to null terminator tib->buffer[tib->current_size + codepointLength] = 0; } utf8_write_codepoint(insertPtr, codepoint); tib->selection_offset += codepointLength; tib->current_size += codepointLength; tib->length++; } }
static void window_multiplayer_groups_paint(rct_window *w, rct_drawpixelinfo *dpi) { window_draw_widgets(w, dpi); window_multiplayer_draw_tab_images(w, dpi); rct_widget* widget = &window_multiplayer_groups_widgets[WIDX_DEFAULT_GROUP]; sint32 group = network_get_group_index(network_get_default_group()); if (group != -1) { char buffer[300]; char* lineCh; lineCh = buffer; lineCh = utf8_write_codepoint(lineCh, FORMAT_WINDOW_COLOUR_2); safe_strcpy(lineCh, network_get_group_name(group), sizeof(buffer) - (lineCh - buffer)); set_format_arg(0, const char *, buffer); gfx_draw_string_centred_clipped( dpi, STR_STRING, gCommonFormatArgs, COLOUR_BLACK, w->x + (widget->left + widget->right - 11) / 2, w->y + widget->top, widget->right - widget->left - 8 ); }
static void window_multiplayer_players_scrollpaint(rct_window *w, rct_drawpixelinfo *dpi, sint32 scrollIndex) { sint32 y; y = 0; for (sint32 i = 0; i < network_get_num_players(); i++) { if (y > dpi->y + dpi->height) { break; } if (y + 11 >= dpi->y) { char buffer[300]; // Draw player name char* lineCh = buffer; sint32 colour = COLOUR_BLACK; if (i == w->selected_list_item) { gfx_filter_rect(dpi, 0, y, 800, y + 9, PALETTE_DARKEN_1); safe_strcpy(buffer, network_get_player_name(i), sizeof(buffer)); colour = w->colours[2]; } else { if (network_get_player_flags(i) & NETWORK_PLAYER_FLAG_ISSERVER) { lineCh = utf8_write_codepoint(lineCh, FORMAT_BABYBLUE); } else { lineCh = utf8_write_codepoint(lineCh, FORMAT_BLACK); } safe_strcpy(lineCh, network_get_player_name(i), sizeof(buffer) - (lineCh - buffer)); } gfx_clip_string(buffer, 230); gfx_draw_string(dpi, buffer, colour, 0, y - 1); // Draw group name lineCh = buffer; sint32 group = network_get_group_index(network_get_player_group(i)); if (group != -1) { lineCh = utf8_write_codepoint(lineCh, FORMAT_BLACK); safe_strcpy(lineCh, network_get_group_name(group), sizeof(buffer) - (lineCh - buffer)); gfx_clip_string(buffer, 80); gfx_draw_string(dpi, buffer, colour, 173, y - 1); } // Draw last action sint32 action = network_get_player_last_action(i, 2000); set_format_arg(0, rct_string_id, STR_ACTION_NA); if (action != -999) { set_format_arg(0, rct_string_id, network_get_action_name_string_id(action)); } gfx_draw_string_left_clipped(dpi, STR_BLACK_STRING, gCommonFormatArgs, COLOUR_BLACK, 256, y - 1, 100); // Draw ping lineCh = buffer; sint32 ping = network_get_player_ping(i); if (ping <= 100) { lineCh = utf8_write_codepoint(lineCh, FORMAT_GREEN); } else if (ping <= 250) { lineCh = utf8_write_codepoint(lineCh, FORMAT_YELLOW); } else { lineCh = utf8_write_codepoint(lineCh, FORMAT_RED); } snprintf(lineCh, sizeof(buffer) - (lineCh - buffer), "%d ms", ping); gfx_draw_string(dpi, buffer, colour, 356, y - 1); } y += 10; } }
static money32 BannerSetName(uint8 bannerIndex, uint16 nameChunkIndex, uint32 nameChunk1, uint32 nameChunk2, uint32 nameChunk3, uint8 flags) { static char newName[128]; if (bannerIndex >= MAX_BANNERS) { log_warning("Invalid game command for setting banner name, banner id = %d", bannerIndex); return MONEY32_UNDEFINED; } rct_banner* banner = &gBanners[bannerIndex]; gCommandExpenditureType = RCT_EXPENDITURE_TYPE_RIDE_RUNNING_COSTS; size_t indexToOffset[3] = { 24, 0, 12 }; if (nameChunkIndex > Util::CountOf(indexToOffset)) { log_warning("Invalid chunk index for setting banner name, banner id = %d, index = %d", bannerIndex, nameChunkIndex); return MONEY32_UNDEFINED; } size_t nameChunkOffset = std::min<size_t>(indexToOffset[nameChunkIndex], Util::CountOf(newName) - 12); std::memcpy(&newName[0 + nameChunkOffset], &nameChunk1, sizeof(uint32)); std::memcpy(&newName[4 + nameChunkOffset], &nameChunk2, sizeof(uint32)); std::memcpy(&newName[8 + nameChunkOffset], &nameChunk3, sizeof(uint32)); if (nameChunkIndex != 0) { return 0; } if (!(flags & GAME_COMMAND_FLAG_APPLY)) { return 0; } utf8 *buffer = gCommonStringFormatBuffer; utf8 *dst = buffer; dst = utf8_write_codepoint(dst, FORMAT_COLOUR_CODE_START + banner->text_colour); String::Set(dst, 256, newName, 32); rct_string_id stringId = user_string_allocate(USER_STRING_DUPLICATION_PERMITTED, buffer); if (stringId != 0) { rct_string_id prevStringId = banner->string_idx; banner->string_idx = stringId; user_string_free(prevStringId); auto intent = Intent(INTENT_ACTION_UPDATE_BANNER); intent.putExtra(INTENT_EXTRA_BANNER_INDEX, bannerIndex); context_broadcast_intent(&intent); } else { gGameCommandErrorText = STR_ERR_CANT_SET_BANNER_TEXT; return MONEY32_UNDEFINED; } return 0; }
static void window_text_input_paint(rct_window *w, rct_drawpixelinfo *dpi) { window_draw_widgets(w, dpi); sint32 y = w->y + 25; sint32 no_lines = 0; sint32 font_height = 0; gfx_draw_string_centred(dpi, input_text_description, w->x + WW / 2, y, w->colours[1], &TextInputDescriptionArgs); y += 25; gCurrentFontSpriteBase = FONT_SPRITE_BASE_MEDIUM; gCurrentFontFlags = 0; char wrapped_string[512]; safe_strcpy(wrapped_string, text_input, 512); // String length needs to add 12 either side of box // +13 for cursor when max length. gfx_wrap_string(wrapped_string, WW - (24 + 13), &no_lines, &font_height); gfx_fill_rect_inset(dpi, w->x + 10, y, w->x + WW - 10, y + 10 * (no_lines + 1) + 3, w->colours[1], INSET_RECT_F_60); y += 1; char* wrap_pointer = wrapped_string; size_t char_count = 0; uint8 cur_drawn = 0; sint32 cursorX = 0, cursorY = 0; for (sint32 line = 0; line <= no_lines; line++) { gfx_draw_string(dpi, wrap_pointer, w->colours[1], w->x + 12, y); size_t string_length = get_string_size(wrap_pointer) - 1; if (!cur_drawn && (gTextInput.selection_offset <= char_count + string_length)) { // Make a copy of the string for measuring the width. char temp_string[512] = { 0 }; memcpy(temp_string, wrap_pointer, gTextInput.selection_offset - char_count); cursorX = w->x + 13 + gfx_get_string_width(temp_string); cursorY = y; sint32 width = 6; if (gTextInput.selection_offset < strlen(text_input)){ // Make a 1 utf8-character wide string for measuring the width // of the currently selected character. utf8 tmp[5] = { 0 }; // This is easier than setting temp_string[0..5] uint32 codepoint = utf8_get_next(text_input + gTextInput.selection_offset, NULL); utf8_write_codepoint(tmp, codepoint); width = max(gfx_get_string_width(tmp) - 2, 4); } if (w->frame_no > 15){ uint8 colour = ColourMapA[w->colours[1]].mid_light; gfx_fill_rect(dpi, cursorX, y + 9, cursorX + width, y + 9, colour + 5); } cur_drawn++; } wrap_pointer += string_length + 1; if (text_input[char_count + string_length] == ' ')char_count++; char_count += string_length; y += 10; } if (!cur_drawn) { cursorX = gLastDrawStringX; cursorY = y - 10; } // IME composition if (gTextInputCompositionActive) { draw_ime_composition(dpi, cursorX, cursorY); } }
/** * * rct2: 0x0066792F * * bx: title * dx: message */ void window_error_open(rct_string_id title, rct_string_id message) { utf8 *dst; char *args; int numLines, fontHeight, x, y, width, height, maxY; rct_window *w; window_close_by_class(WC_ERROR); dst = _window_error_text; args = (char*)0x0013CE952; // Format the title dst = utf8_write_codepoint(dst, FORMAT_BLACK); if (title != (rct_string_id)STR_NONE) { format_string(dst, title, args); dst = get_string_end(dst); } // Format the message if (message != (rct_string_id)STR_NONE) { dst = utf8_write_codepoint(dst, FORMAT_NEWLINE); format_string(dst, message, args); dst = get_string_end(dst); } log_verbose("show error, %s", _window_error_text + 1); // Check if there is any text to display if (dst == _window_error_text + 1) return; RCT2_GLOBAL(RCT2_ADDRESS_CURRENT_FONT_SPRITE_BASE, uint16) = 224; width = gfx_get_string_width_new_lined(_window_error_text); width = min(196, width); RCT2_GLOBAL(RCT2_ADDRESS_CURRENT_FONT_SPRITE_BASE, uint16) = 224; gfx_wrap_string(_window_error_text, width + 1, &numLines, &fontHeight); _window_error_num_lines = numLines; width = width + 3; height = (numLines + 1) * 10 + 4; window_error_widgets[WIDX_BACKGROUND].right = width; window_error_widgets[WIDX_BACKGROUND].bottom = height; x = RCT2_GLOBAL(0x0142406C, sint32) - (width / 2); x = clamp(0, x, RCT2_GLOBAL(RCT2_ADDRESS_SCREEN_WIDTH, uint16)); y = RCT2_GLOBAL(0x01424070, sint32) + 26; y = max(22, y); maxY = RCT2_GLOBAL(RCT2_ADDRESS_SCREEN_HEIGHT, uint16) - height; if (y > maxY) { y = y - height - 40; y = min(y, maxY); } w = window_create(x, y, width, height, &window_error_events, WC_ERROR, WF_STICK_TO_FRONT | WF_TRANSPARENT | WF_RESIZABLE); w->widgets = window_error_widgets; w->error.var_480 = 0; if (!(RCT2_GLOBAL(0x009A8C29, uint8) & 1)) sound_play_panned(SOUND_ERROR, 0, w->x + (w->width / 2), 0, 0); }
/** * * rct2: 0x006850BD */ static void window_editor_inventions_list_scrollpaint(rct_window* w, rct_drawpixelinfo* dpi, int32_t scrollIndex) { // Draw background uint8_t paletteIndex = ColourMapA[w->colours[1]].mid_light; gfx_clear(dpi, paletteIndex); rct_research_item* researchItem = gResearchItems; int32_t researchItemEndMarker; if (scrollIndex == 1) { // Skip pre-researched items for (; researchItem->rawValue != RESEARCHED_ITEMS_SEPARATOR; researchItem++) { } researchItem++; researchItemEndMarker = RESEARCHED_ITEMS_END; } else { researchItemEndMarker = RESEARCHED_ITEMS_SEPARATOR; } int16_t boxWidth = (w->widgets[WIDX_RESEARCH_ORDER_SCROLL].right - w->widgets[WIDX_RESEARCH_ORDER_SCROLL].left); int16_t columnSplitOffset = boxWidth / 2; int32_t itemY = -SCROLLABLE_ROW_HEIGHT; do { itemY += SCROLLABLE_ROW_HEIGHT; if (itemY + SCROLLABLE_ROW_HEIGHT < dpi->y || itemY >= dpi->y + dpi->height) continue; if (w->research_item == researchItem) { int32_t top, bottom; if (_editorInventionsListDraggedItem == nullptr) { // Highlight top = itemY; bottom = itemY + SCROLLABLE_ROW_HEIGHT - 1; } else { // Drop horizontal rule top = itemY - 1; bottom = itemY; } gfx_filter_rect(dpi, 0, top, boxWidth, bottom, PALETTE_DARKEN_1); } if (researchItem->rawValue == RESEARCHED_ITEMS_SEPARATOR || researchItem->rawValue == RESEARCHED_ITEMS_END) continue; if (researchItem == _editorInventionsListDraggedItem) continue; utf8 groupNameBuffer[256], vehicleNameBuffer[256]; utf8* groupNamePtr = groupNameBuffer; utf8* vehicleNamePtr = vehicleNameBuffer; uint8_t colour; if (research_item_is_always_researched(researchItem)) { if (w->research_item == researchItem && _editorInventionsListDraggedItem == nullptr) gCurrentFontSpriteBase = FONT_SPRITE_BASE_MEDIUM_EXTRA_DARK; else gCurrentFontSpriteBase = FONT_SPRITE_BASE_MEDIUM_DARK; colour = w->colours[1] | COLOUR_FLAG_INSET; } else { // TODO: this is actually just a black colour. colour = COLOUR_BRIGHT_GREEN | COLOUR_FLAG_TRANSLUCENT; gCurrentFontSpriteBase = FONT_SPRITE_BASE_MEDIUM; groupNamePtr = utf8_write_codepoint(groupNamePtr, colour); vehicleNamePtr = utf8_write_codepoint(vehicleNamePtr, colour); } rct_string_id itemNameId = research_item_get_name(researchItem); if (researchItem->type == RESEARCH_ENTRY_TYPE_RIDE && !RideGroupManager::RideTypeIsIndependent(researchItem->baseRideType)) { const auto rideEntry = get_ride_entry(researchItem->entryIndex); const rct_string_id rideGroupName = get_ride_naming(researchItem->baseRideType, rideEntry).name; format_string( groupNamePtr, std::size(groupNameBuffer), STR_INVENTIONS_LIST_RIDE_AND_VEHICLE_NAME, (void*)&rideGroupName); format_string(vehicleNamePtr, std::size(vehicleNameBuffer), itemNameId, nullptr); } else { format_string(groupNamePtr, std::size(groupNameBuffer), itemNameId, nullptr); vehicleNamePtr = nullptr; } // Draw group name gfx_clip_string(groupNameBuffer, columnSplitOffset); gfx_draw_string(dpi, groupNameBuffer, colour, 1, itemY); // Draw vehicle name if (vehicleNamePtr) { gfx_clip_string(vehicleNameBuffer, columnSplitOffset - 11); gfx_draw_string(dpi, vehicleNameBuffer, colour, columnSplitOffset + 1, itemY); } } while (researchItem++->rawValue != researchItemEndMarker); }
/** * * rct2: 0x0066E4EE */ static void window_news_scrollpaint(rct_window *w, rct_drawpixelinfo *dpi, int scrollIndex) { int i, x, y, yy, press; y = 0; for (i = 11; i < 61; i++) { rct_news_item * const newsItem = news_item_get(i); if (news_item_is_empty(i)) break; if (y >= dpi->y + dpi->height) break; if (y + 42 < dpi->y) { y += 42; continue; } // Background gfx_fill_rect_inset(dpi, -1, y, 383, y + 41, w->colours[1], 0x24); // Date text RCT2_GLOBAL(RCT2_ADDRESS_COMMON_FORMAT_ARGS, uint16) = STR_DATE_DAY_1 + newsItem->day - 1; RCT2_GLOBAL(RCT2_ADDRESS_COMMON_FORMAT_ARGS + 2, uint16) = STR_MONTH_MARCH + (newsItem->month_year % 8); gfx_draw_string_left(dpi, 2235, (void*)RCT2_ADDRESS_COMMON_FORMAT_ARGS, 2, 4, y); // Item text utf8 buffer[400]; utf8 *ch = buffer; ch = utf8_write_codepoint(ch, FORMAT_SMALLFONT); memcpy(ch, newsItem->text, 256); ch = buffer; gfx_draw_string_left_wrapped(dpi, &ch, 2, y + 10, 325, 1170, 14); // Subject button if ((RCT2_ADDRESS(0x0097BE7C, uint8)[newsItem->type] & 2) && !(newsItem->flags & 1)) { x = 328; yy = y + 14; press = 0; if (w->news.var_480 != -1) { const uint8 idx = 11 + w->news.var_480; news_item_is_valid_idx(idx); if (i == idx && w->news.var_482 == 1) press = 0x20; } gfx_fill_rect_inset(dpi, x, yy, x + 23, yy + 23, w->colours[2], press); switch (newsItem->type) { case NEWS_ITEM_RIDE: gfx_draw_sprite(dpi, SPR_RIDE, x, yy, 0); break; case NEWS_ITEM_PEEP: case NEWS_ITEM_PEEP_ON_RIDE: { rct_drawpixelinfo cliped_dpi; if (!clip_drawpixelinfo(&cliped_dpi, dpi, x + 1, yy + 1, 22, 22)) { break; } rct_peep* peep = GET_PEEP(newsItem->assoc); int clip_x = 10, clip_y = 19; // If normal peep set sprite to normal (no food) // If staff set sprite to staff sprite int sprite_type = 0; if (peep->type == PEEP_TYPE_STAFF){ sprite_type = peep->sprite_type; if (peep->staff_type == STAFF_TYPE_ENTERTAINER){ clip_y += 3; } } uint32 image_id = g_sprite_entries[sprite_type].sprite_image->base_image; image_id += 0xA0000001; image_id |= (peep->tshirt_colour << 19) | (peep->trousers_colour << 24); gfx_draw_sprite(&cliped_dpi, image_id, clip_x, clip_y, 0); break; } case NEWS_ITEM_MONEY: gfx_draw_sprite(dpi, SPR_FINANCE, x, yy, 0); break; case NEWS_ITEM_RESEARCH: gfx_draw_sprite(dpi, newsItem->assoc < 0x10000 ? SPR_NEW_RIDE : SPR_SCENERY, x, yy, 0); break; case NEWS_ITEM_PEEPS: gfx_draw_sprite(dpi, SPR_GUESTS, x, yy, 0); break; case NEWS_ITEM_AWARD: gfx_draw_sprite(dpi, SPR_AWARD, x, yy, 0); break; case NEWS_ITEM_GRAPH: gfx_draw_sprite(dpi, SPR_GRAPH, x, yy, 0); break; } } // Location button if ((RCT2_ADDRESS(0x0097BE7C, uint8)[newsItem->type] & 1) && !(newsItem->flags & 1)) { x = 352; yy = y + 14; press = 0; if (w->news.var_480 != -1) { const uint8 idx = 11 + w->news.var_480; news_item_is_valid_idx(idx); if (i == idx && w->news.var_482 == 2) press = 0x20; } gfx_fill_rect_inset(dpi, x, yy, x + 23, yy + 23, w->colours[2], press); gfx_draw_sprite(dpi, SPR_LOCATE, x, yy, 0); } y += 42; } }
void chat_draw(rct_drawpixelinfo* dpi, uint8_t chatBackgroundColor) { if (!chat_available()) { gChatOpen = false; return; } _chatLeft = 10; _chatRight = std::min((context_get_width() - 10), CHAT_MAX_WINDOW_WIDTH); _chatWidth = _chatRight - _chatLeft; _chatBottom = context_get_height() - 45; _chatTop = _chatBottom - 10; char lineBuffer[CHAT_INPUT_SIZE + 10]; char* lineCh = lineBuffer; char* inputLine = _chatCurrentLine; int32_t inputLineHeight = 10; // Draw chat window if (gChatOpen) { inputLineHeight = chat_string_wrapped_get_height((void*)&inputLine, _chatWidth - 10); _chatTop -= inputLineHeight; for (int32_t i = 0; i < CHAT_HISTORY_SIZE; i++) { if (strlen(chat_history_get(i)) == 0) { continue; } safe_strcpy(lineBuffer, chat_history_get(i), sizeof(lineBuffer)); int32_t lineHeight = chat_string_wrapped_get_height((void*)&lineCh, _chatWidth - 10); _chatTop -= (lineHeight + 5); } _chatHeight = _chatBottom - _chatTop; if (_chatTop < 50) { _chatTop = 50; } else if (_chatHeight < 150) { // Min height _chatTop = _chatBottom - 150; _chatHeight = 150; } gfx_set_dirty_blocks(_chatLeft, _chatTop - 5, _chatRight, _chatBottom + 5); // Background area + Textbox gfx_filter_rect(dpi, _chatLeft, _chatTop - 5, _chatRight, _chatBottom + 5, PALETTE_51); // Opaque gray background gfx_fill_rect_inset( dpi, _chatLeft, _chatTop - 5, _chatRight, _chatBottom + 5, chatBackgroundColor, INSET_RECT_FLAG_FILL_NONE); gfx_fill_rect_inset( dpi, _chatLeft + 1, _chatTop - 4, _chatRight - 1, _chatBottom - inputLineHeight - 6, chatBackgroundColor, INSET_RECT_FLAG_BORDER_INSET); gfx_fill_rect_inset( dpi, _chatLeft + 1, _chatBottom - inputLineHeight - 5, _chatRight - 1, _chatBottom + 4, chatBackgroundColor, INSET_RECT_FLAG_BORDER_INSET); // Textbox } int32_t x = _chatLeft + 5; int32_t y = _chatBottom - inputLineHeight - 20; int32_t stringHeight = 0; // Draw chat history for (int32_t i = 0; i < CHAT_HISTORY_SIZE; i++, y -= stringHeight) { uint32_t expireTime = chat_history_get_time(i) + 10000; if (!gChatOpen && platform_get_ticks() > expireTime) { break; } safe_strcpy(lineBuffer, chat_history_get(i), sizeof(lineBuffer)); stringHeight = chat_history_draw_string(dpi, (void*)&lineCh, x, y, _chatWidth - 10) + 5; gfx_set_dirty_blocks(x, y - stringHeight, x + _chatWidth, y + 20); if ((y - stringHeight) < 50) { break; } } // Draw current chat input if (gChatOpen) { lineCh = utf8_write_codepoint(lineCh, FORMAT_OUTLINE); lineCh = utf8_write_codepoint(lineCh, FORMAT_CELADON); safe_strcpy(lineCh, _chatCurrentLine, sizeof(_chatCurrentLine)); y = _chatBottom - inputLineHeight - 5; lineCh = lineBuffer; inputLineHeight = gfx_draw_string_left_wrapped( dpi, (void*)&lineCh, x, y + 3, _chatWidth - 10, STR_STRING, TEXT_COLOUR_255); gfx_set_dirty_blocks(x, y, x + _chatWidth, y + inputLineHeight + 15); // TODO: Show caret if the input text has multiple lines if (_chatCaretTicks < 15 && gfx_get_string_width(lineBuffer) < (_chatWidth - 10)) { std::memcpy(lineBuffer, _chatCurrentLine, _chatTextInputSession->SelectionStart); lineBuffer[_chatTextInputSession->SelectionStart] = 0; int32_t caretX = x + gfx_get_string_width(lineBuffer); int32_t caretY = y + 14; gfx_fill_rect(dpi, caretX, caretY, caretX + 6, caretY + 1, PALETTE_INDEX_56); } } }
static money32 BannerSetStyle(uint8 bannerIndex, uint8 colour, uint8 textColour, uint8 bannerFlags, uint8 flags) { if (bannerIndex >= MAX_BANNERS) { gGameCommandErrorText = STR_INVALID_SELECTION_OF_OBJECTS; return MONEY32_UNDEFINED; } rct_banner* banner = &gBanners[bannerIndex]; rct_tile_element* tileElement = banner_get_tile_element(bannerIndex); if (tileElement == nullptr) { return MONEY32_UNDEFINED; } if (!(flags & GAME_COMMAND_FLAG_APPLY)) { return 0; } banner->colour = colour; banner->text_colour = textColour; banner->flags = bannerFlags; tileElement->properties.banner.flags = 0xFF; if (banner->flags & BANNER_FLAG_NO_ENTRY) { tileElement->properties.banner.flags &= ~(1 << tileElement->properties.banner.position); } sint32 colourCodepoint = FORMAT_COLOUR_CODE_START + banner->text_colour; utf8 buffer[256]; format_string(buffer, 256, banner->string_idx, nullptr); sint32 firstCodepoint = utf8_get_next(buffer, nullptr); if (firstCodepoint >= FORMAT_COLOUR_CODE_START && firstCodepoint <= FORMAT_COLOUR_CODE_END) { utf8_write_codepoint(buffer, colourCodepoint); } else { utf8_insert_codepoint(buffer, colourCodepoint); } rct_string_id stringId = user_string_allocate(USER_STRING_DUPLICATION_PERMITTED, buffer); if (stringId != 0) { rct_string_id prevStringId = banner->string_idx; banner->string_idx = stringId; user_string_free(prevStringId); auto intent = Intent(INTENT_ACTION_UPDATE_BANNER); intent.putExtra(INTENT_EXTRA_BANNER_INDEX, bannerIndex); context_broadcast_intent(&intent); } else { gGameCommandErrorText = STR_ERR_CANT_SET_BANNER_TEXT; return MONEY32_UNDEFINED; } return 0; }
/** * * rct2: 0x0066792F * * bx: title * dx: message */ void window_error_open(rct_string_id title, rct_string_id message) { utf8 *dst; sint32 numLines, fontHeight, x, y, width, height, maxY; rct_window *w; window_close_by_class(WC_ERROR); dst = _window_error_text; // Format the title dst = utf8_write_codepoint(dst, FORMAT_BLACK); if (title != STR_NONE) { format_string(dst, 512 - (dst - _window_error_text), title, gCommonFormatArgs); dst = get_string_end(dst); } // Format the message if (message != STR_NONE) { dst = utf8_write_codepoint(dst, FORMAT_NEWLINE); format_string(dst, 512 - (dst - _window_error_text), message, gCommonFormatArgs); dst = get_string_end(dst); } log_verbose("show error, %s", _window_error_text + 1); // Check if there is any text to display if (dst == _window_error_text + 1) return; gCurrentFontSpriteBase = FONT_SPRITE_BASE_MEDIUM; width = gfx_get_string_width_new_lined(_window_error_text); width = min(196, width); gCurrentFontSpriteBase = FONT_SPRITE_BASE_MEDIUM; gfx_wrap_string(_window_error_text, width + 1, &numLines, &fontHeight); _window_error_num_lines = numLines; width = width + 3; height = (numLines + 1) * 10 + 4; window_error_widgets[WIDX_BACKGROUND].right = width; window_error_widgets[WIDX_BACKGROUND].bottom = height; x = gCursorState.x - (width / 2); x = clamp(0, x, gScreenWidth); y = gCursorState.y + 26; y = max(22, y); maxY = gScreenHeight - height; if (y > maxY) { y = y - height - 40; y = min(y, maxY); } w = window_create(x, y, width, height, &window_error_events, WC_ERROR, WF_STICK_TO_FRONT | WF_TRANSPARENT | WF_RESIZABLE); w->widgets = window_error_widgets; w->error.var_480 = 0; if (!gDisableErrorWindowSound) { audio_play_sound_panned(SOUND_ERROR, 0, w->x + (w->width / 2), 0, 0); } }