/** * Shows a text dropdown menu. * rct2: 0x006ECFB9, although 0x006ECE50 is real version * * @param x (cx) * @param y (dx) * @param extray (di) * @param flags (bh) * @param num_items (bx) * @param colour (al) * @param custom_height (ah) requires flag set as well */ void window_dropdown_show_text_custom_width( int32_t x, int32_t y, int32_t extray, uint8_t colour, uint8_t custom_height, uint8_t flags, size_t num_items, int32_t width) { rct_window* w; input_set_flag((INPUT_FLAGS)(INPUT_FLAG_DROPDOWN_STAY_OPEN | INPUT_FLAG_DROPDOWN_MOUSE_UP), false); if (flags & DROPDOWN_FLAG_STAY_OPEN) input_set_flag(INPUT_FLAG_DROPDOWN_STAY_OPEN, true); window_dropdown_close(); // Set and calculate num items, rows and columns _dropdown_item_width = width; _dropdown_item_height = (flags & DROPDOWN_FLAG_CUSTOM_HEIGHT) ? custom_height : DROPDOWN_ITEM_HEIGHT; gDropdownNumItems = (int32_t)num_items; // There must always be at least one column to prevent dividing by zero if (gDropdownNumItems == 0) { _dropdown_num_columns = 1; _dropdown_num_rows = 0; } else { _dropdown_num_columns = (gDropdownNumItems + DROPDOWN_TEXT_MAX_ROWS - 1) / DROPDOWN_TEXT_MAX_ROWS; _dropdown_num_rows = (gDropdownNumItems + _dropdown_num_columns - 1) / _dropdown_num_columns; } // Text dropdowns are listed horizontally _dropdown_list_vertically = true; width = _dropdown_item_width * _dropdown_num_columns + 3; int32_t height = _dropdown_item_height * _dropdown_num_rows + 3; int32_t screenWidth = context_get_width(); int32_t screenHeight = context_get_height(); if (x + width > screenWidth) x = std::max(0, screenWidth - width); if (y + height > screenHeight) y = std::max(0, screenHeight - height); window_dropdown_widgets[WIDX_BACKGROUND].right = width; window_dropdown_widgets[WIDX_BACKGROUND].bottom = height; // Create the window w = window_create( x, y + extray, window_dropdown_widgets[WIDX_BACKGROUND].right + 1, window_dropdown_widgets[WIDX_BACKGROUND].bottom + 1, &window_dropdown_events, WC_DROPDOWN, WF_STICK_TO_FRONT); w->widgets = window_dropdown_widgets; if (colour & COLOUR_FLAG_TRANSLUCENT) w->flags |= WF_TRANSPARENT; w->colours[0] = colour; // Input state gDropdownHighlightedIndex = -1; std::fill_n(_dropdownItemsDisabled, sizeof(_dropdownItemsDisabled), false); std::fill_n(_dropdownItemsChecked, sizeof(_dropdownItemsChecked), false); gDropdownIsColour = false; gDropdownDefaultIndex = -1; input_set_state(INPUT_STATE_DROPDOWN_ACTIVE); }
void window_tooltip_show(rct_string_id id, int32_t x, int32_t y) { rct_window* w; int32_t width, height; w = window_find_by_class(WC_ERROR); if (w != nullptr) return; char* buffer = gCommonStringFormatBuffer; format_string(buffer, sizeof(gCommonStringFormatBuffer), id, gCommonFormatArgs); gCurrentFontSpriteBase = FONT_SPRITE_BASE_MEDIUM; int32_t tooltip_text_width; tooltip_text_width = gfx_get_string_width_new_lined(buffer); buffer = gCommonStringFormatBuffer; tooltip_text_width = std::min(tooltip_text_width, 196); gCurrentFontSpriteBase = FONT_SPRITE_BASE_MEDIUM; int32_t numLines, fontSpriteBase; tooltip_text_width = gfx_wrap_string(buffer, tooltip_text_width + 1, &numLines, &fontSpriteBase); _tooltipNumLines = numLines; width = tooltip_text_width + 3; height = ((numLines + 1) * font_get_line_height(gCurrentFontSpriteBase)) + 4; window_tooltip_widgets[WIDX_BACKGROUND].right = width; window_tooltip_widgets[WIDX_BACKGROUND].bottom = height; std::memcpy(_tooltipText, buffer, sizeof(_tooltipText)); int32_t screenWidth = context_get_width(); int32_t screenHeight = context_get_height(); x = std::clamp(x - (width / 2), 0, screenWidth - width); // TODO The cursor size will be relative to the window DPI. // The amount to offset the y should be adjusted. int32_t max_y = screenHeight - height; y += 26; // Normally, we'd display the tooltip 26 lower if (y > max_y) // If y is too large, the tooltip could be forced below the cursor if we'd just clamped y, // so we'll subtract a bit more y -= height + 40; y = std::clamp(y, 22, max_y); w = window_create(x, y, width, height, &window_tooltip_events, WC_TOOLTIP, WF_TRANSPARENT | WF_STICK_TO_FRONT); w->widgets = window_tooltip_widgets; reset_tooltip_not_shown(); }
/** * Creates the window containing the exit button on the title screen. * rct2: 0x0066B624 (part of 0x0066B3E8) */ rct_window* window_title_exit_open() { rct_window* window; window = window_create( context_get_width() - 40, context_get_height() - 64, 40, 64, &window_title_exit_events, WC_TITLE_EXIT, WF_STICK_TO_BACK | WF_TRANSPARENT); window->widgets = window_title_exit_widgets; window->enabled_widgets |= (1ULL << WIDX_EXIT); window_init_scroll_widgets(window); return window; }
/** * * rct2: 0x006D386D */ rct_window* window_install_track_open(const utf8* path) { _trackDesign = track_design_open(path); if (_trackDesign == nullptr) { context_show_error(STR_UNABLE_TO_LOAD_FILE, STR_NONE); return nullptr; } object_manager_unload_all_objects(); if (_trackDesign->type == RIDE_TYPE_NULL) { log_error("Failed to load track (ride type null): %s", path); return nullptr; } if (object_manager_load_object(&_trackDesign->vehicle_object) == nullptr) { log_error("Failed to load track (vehicle load fail): %s", path); return nullptr; } window_close_by_class(WC_EDITOR_OBJECT_SELECTION); window_close_construction_windows(); gTrackDesignSceneryToggle = false; _currentTrackPieceDirection = 2; int32_t screenWidth = context_get_width(); int32_t screenHeight = context_get_height(); int32_t x = screenWidth / 2 - 201; int32_t y = std::max(TOP_TOOLBAR_HEIGHT + 1, screenHeight / 2 - 200); rct_window* w = window_create(x, y, WW, WH, &window_install_track_events, WC_INSTALL_TRACK, 0); w->widgets = window_install_track_widgets; w->enabled_widgets = (1 << WIDX_CLOSE) | (1 << WIDX_ROTATE) | (1 << WIDX_TOGGLE_SCENERY) | (1 << WIDX_INSTALL) | (1 << WIDX_CANCEL); window_init_scroll_widgets(w); w->track_list.track_list_being_updated = false; window_push_others_right(w); _trackPath = path; _trackName = GetNameFromTrackPath(path); _trackDesignPreviewPixels.resize(4 * TRACK_PREVIEW_IMAGE_SIZE); window_install_track_update_preview(); window_invalidate(w); return w; }
/** * Creates the main editor top toolbar window. * rct2: 0x0066F052 (part of 0x0066EF38) */ void window_editor_bottom_toolbar_open() { rct_window * window = window_create(0, context_get_height() - 32, context_get_width(), 32, &window_editor_bottom_toolbar_events, WC_BOTTOM_TOOLBAR, WF_STICK_TO_FRONT | WF_TRANSPARENT | WF_NO_BACKGROUND); window->widgets = window_editor_bottom_toolbar_widgets; window->enabled_widgets |= (1 << WIDX_PREVIOUS_STEP_BUTTON) | (1 << WIDX_NEXT_STEP_BUTTON) | (1 << WIDX_PREVIOUS_IMAGE) | (1 << WIDX_NEXT_IMAGE); window_init_scroll_widgets(window); reset_researched_scenery_items(); }
/** * * rct2: 0x006CF1A2 */ void window_track_list_open(ride_list_item item) { window_close_construction_windows(); _window_track_list_item = item; track_list_load_designs(item); sint32 x, y; if (gScreenFlags & SCREEN_FLAGS_TRACK_MANAGER) { sint32 screenWidth = context_get_width(); sint32 screenHeight = context_get_height(); x = screenWidth / 2 - 300; y = max(TOP_TOOLBAR_HEIGHT + 1, screenHeight / 2 - 200); } else { x = 0; y = TOP_TOOLBAR_HEIGHT + 2; } rct_window *w = window_create( x, y, 600, 400, &window_track_list_events, WC_TRACK_DESIGN_LIST, 0 ); w->widgets = window_track_list_widgets; w->enabled_widgets = (1 << WIDX_CLOSE) | (1 << WIDX_ROTATE) | (1 << WIDX_TOGGLE_SCENERY) | (1 << WIDX_BACK); window_init_scroll_widgets(w); w->track_list.var_480 = 0xFFFF; w->track_list.var_484 = 0; w->track_list.reload_track_designs = false; w->selected_list_item = 0; if (_trackDesignsCount != 0 && !(gScreenFlags & SCREEN_FLAGS_TRACK_MANAGER)) { w->selected_list_item = 1; } gTrackDesignSceneryToggle = false; window_push_others_right(w); _currentTrackPieceDirection = 2; _trackDesignPreviewPixels = calloc(4, TRACK_PREVIEW_IMAGE_SIZE); _loadedTrackDesign = NULL; _loadedTrackDesignIndex = TRACK_DESIGN_INDEX_UNLOADED; }
/** * Creates the window containing the menu buttons on the title screen. * rct2: 0x0066B5C0 (part of 0x0066B3E8) */ rct_window * window_title_menu_open() { rct_window* window; window = window_create( 0, context_get_height() - 142, 0, 100, &window_title_menu_events, WC_TITLE_MENU, WF_STICK_TO_BACK | WF_TRANSPARENT | WF_NO_BACKGROUND ); window->widgets = window_title_menu_widgets; window->enabled_widgets = ( (1 << WIDX_START_NEW_GAME) | (1 << WIDX_CONTINUE_SAVED_GAME) | #ifndef DISABLE_NETWORK (1 << WIDX_MULTIPLAYER) | #endif (1 << WIDX_GAME_TOOLS) ); rct_widgetindex i = 0; sint32 x = 0; for (rct_widget *widget = window->widgets; widget->type != WWT_LAST; widget++) { if (widget_is_enabled(window, i)) { widget->left = x; widget->right = x + 81; x += 82; } else { widget->type = WWT_EMPTY; } i++; } window->width = x; window->x = (context_get_width() - window->width) / 2; window_init_scroll_widgets(window); return window; }
/** * Creates the main window that holds the main viewport. * rct2: 0x0066B3E8 */ rct_window * window_main_open() { window_main_widgets[0].right = context_get_width(); window_main_widgets[0].bottom = context_get_height(); rct_window * window = window_create( 0, 0, window_main_widgets[0].right, window_main_widgets[0].bottom, &window_main_events, WC_MAIN_WINDOW, WF_STICK_TO_BACK ); window->widgets = window_main_widgets; viewport_create(window, window->x, window->y, window->width, window->height, 0,0x0FFF,0x0FFF, 0, 0x1, -1); window->viewport->flags |= VIEWPORT_FLAG_SOUND_ON; gCurrentRotation = 0; gShowGridLinesRefCount = 0; gShowLandRightsRefCount = 0; gShowConstuctionRightsRefCount = 0; gFootpathSelectedType = 0; return window; }
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); } } }