OpenTTD Source: src/music_gui.cpp Source File

OpenTTD Source 15.3

music_gui.cpp
Go to the documentation of this file.
1/*
2 * This file is part of OpenTTD.
3 * OpenTTD is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, version 2.
4 * OpenTTD is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
5 * See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with OpenTTD. If not, see <https://www.gnu.org/licenses/old-licenses/gpl-2.0>.
6 */
7
10#include "stdafx.h"
11#include "openttd.h"
12#include "base_media_base.h"
13#include "base_media_music.h"
14#include "music/music_driver.hpp"
15#include "window_gui.h"
16#include "strings_func.h"
17#include "window_func.h"
18#include "sound_func.h"
19#include "gfx_func.h"
20#include "zoom_func.h"
21#include "core/random_func.hpp"
22#include "error.h"
23#include "core/geometry_func.hpp"
24#include "string_func.h"
25#include "settings_type.h"
26#include "settings_gui.h"
27#include "dropdown_func.h"
28#include "dropdown_type.h"
29#include "slider_func.h"
30#include "mixer.h"
31
32#include "widgets/music_widget.h"
33
34#include "table/strings.h"
35#include "table/sprites.h"
36
37#include "safeguards.h"
38
39
40 struct MusicSystem {
41 struct PlaylistEntry : MusicSongInfo {
42 const MusicSet *set;
43 uint set_index;
44
45 PlaylistEntry(const MusicSet *set, uint set_index) : MusicSongInfo(set->songinfo[set_index]), set(set), set_index(set_index) { }
46 bool IsValid() const { return !this->songname.empty(); }
47 };
48 typedef std::vector<PlaylistEntry> Playlist;
49
50 enum PlaylistChoices : uint8_t {
51 PLCH_ALLMUSIC,
52 PLCH_OLDSTYLE,
53 PLCH_NEWSTYLE,
54 PLCH_EZYSTREET,
55 PLCH_CUSTOM1,
56 PLCH_CUSTOM2,
57 PLCH_THEMEONLY,
58 PLCH_MAX,
59 };
60
61 Playlist active_playlist{};
62 Playlist music_set{};
63
64 PlaylistChoices selected_playlist{};
65
66 void BuildPlaylists();
67
68 void ChangePlaylist(PlaylistChoices pl);
69 void ChangeMusicSet(const std::string &set_name);
70 void Shuffle();
71 void Unshuffle();
72
73 void Play();
74 void Stop();
75 void Next();
76 void Prev();
77 void CheckStatus();
78
79 bool IsPlaying() const;
80 bool IsShuffle() const;
81 PlaylistEntry GetCurrentSong() const;
82
83 bool IsCustomPlaylist() const;
84 void PlaylistAdd(size_t song_index);
85 void PlaylistRemove(size_t song_index);
86 void PlaylistClear();
87
88private:
89 uint GetSetIndex();
90 void SetPositionBySetIndex(uint set_index);
91 void ChangePlaylistPosition(int ofs);
92 int playlist_position = 0;
93
94 void SaveCustomPlaylist(PlaylistChoices pl);
95
96 std::array<Playlist, PLCH_MAX> standard_playlists{};
97};
98
99 MusicSystem _music;
100
101
103 void MusicSystem::BuildPlaylists()
104{
105 const MusicSet *set = BaseMusic::GetUsedSet();
106
107 /* Clear current playlists */
108 for (auto &playlist : this->standard_playlists) playlist.clear();
109 this->music_set.clear();
110
111 /* Build standard playlists, and a list of available music */
112 for (uint i = 0; i < NUM_SONGS_AVAILABLE; i++) {
113 PlaylistEntry entry(set, i);
114 if (!entry.IsValid()) continue;
115
116 this->music_set.push_back(entry);
117
118 /* Add theme song to theme-only playlist */
119 if (i == 0) this->standard_playlists[PLCH_THEMEONLY].push_back(std::move(entry));
120
121 /* Don't add the theme song to standard playlists */
122 if (i > 0) {
123 this->standard_playlists[PLCH_ALLMUSIC].push_back(entry);
124 uint theme = (i - 1) / NUM_SONGS_CLASS;
125 this->standard_playlists[PLCH_OLDSTYLE + theme].push_back(std::move(entry));
126 }
127 }
128
129 /* Load custom playlists
130 * Song index offsets are 1-based, zero indicates invalid/end-of-list value */
131 for (uint i = 0; i < NUM_SONGS_PLAYLIST; i++) {
132 if (_settings_client.music.custom_1[i] > 0 && _settings_client.music.custom_1[i] <= NUM_SONGS_AVAILABLE) {
133 PlaylistEntry entry(set, _settings_client.music.custom_1[i] - 1);
134 if (entry.IsValid()) this->standard_playlists[PLCH_CUSTOM1].push_back(std::move(entry));
135 }
136 if (_settings_client.music.custom_2[i] > 0 && _settings_client.music.custom_2[i] <= NUM_SONGS_AVAILABLE) {
137 PlaylistEntry entry(set, _settings_client.music.custom_2[i] - 1);
138 if (entry.IsValid()) this->standard_playlists[PLCH_CUSTOM2].push_back(std::move(entry));
139 }
140 }
141}
142
147 void MusicSystem::ChangePlaylist(PlaylistChoices pl)
148{
149 assert(pl < PLCH_MAX && pl >= PLCH_ALLMUSIC);
150
151 if (pl != PLCH_THEMEONLY) _settings_client.music.playlist = pl;
152
153 if (_game_mode != GM_MENU || pl == PLCH_THEMEONLY) {
154 this->selected_playlist = pl;
155 this->active_playlist = this->standard_playlists[this->selected_playlist];
156 this->playlist_position = 0;
157
158 if (_settings_client.music.shuffle) this->Shuffle();
159 if (_settings_client.music.playing) this->Play();
160 }
161
162 InvalidateWindowData(WC_MUSIC_TRACK_SELECTION, 0);
163 InvalidateWindowData(WC_MUSIC_WINDOW, 0);
164}
165
170 void MusicSystem::ChangeMusicSet(const std::string &set_name)
171{
172 BaseMusic::SetSetByName(set_name);
173 BaseMusic::ini_set = set_name;
174
175 this->BuildPlaylists();
176 this->ChangePlaylist(this->selected_playlist);
177
178 InvalidateWindowData(WC_GAME_OPTIONS, WN_GAME_OPTIONS_GAME_OPTIONS, 0, true);
179 InvalidateWindowData(WC_MUSIC_TRACK_SELECTION, 0, 1, true);
180 InvalidateWindowData(WC_MUSIC_WINDOW, 0, 1, true);
181}
182
187 void MusicSystem::SetPositionBySetIndex(uint set_index)
188{
189 auto it = std::ranges::find(this->active_playlist, set_index, &PlaylistEntry::set_index);
190 if (it != std::end(this->active_playlist)) this->playlist_position = std::distance(std::begin(this->active_playlist), it);
191}
192
197uint MusicSystem::GetSetIndex()
198{
199 return static_cast<size_t>(this->playlist_position) < this->active_playlist.size()
200 ? this->active_playlist[this->playlist_position].set_index
201 : UINT_MAX;
202}
203
207 void MusicSystem::Shuffle()
208{
209 _settings_client.music.shuffle = true;
210
211 uint set_index = this->GetSetIndex();
212 this->active_playlist = this->standard_playlists[this->selected_playlist];
213 for (size_t i = 0; i < this->active_playlist.size(); i++) {
214 size_t shuffle_index = InteractiveRandom() % (this->active_playlist.size() - i);
215 std::swap(this->active_playlist[i], this->active_playlist[i + shuffle_index]);
216 }
217 this->SetPositionBySetIndex(set_index);
218
219 InvalidateWindowData(WC_MUSIC_TRACK_SELECTION, 0);
220 InvalidateWindowData(WC_MUSIC_WINDOW, 0);
221}
222
226 void MusicSystem::Unshuffle()
227{
228 _settings_client.music.shuffle = false;
229
230 uint set_index = this->GetSetIndex();
231 this->active_playlist = this->standard_playlists[this->selected_playlist];
232 this->SetPositionBySetIndex(set_index);
233
234 InvalidateWindowData(WC_MUSIC_TRACK_SELECTION, 0);
235 InvalidateWindowData(WC_MUSIC_WINDOW, 0);
236}
237
239 void MusicSystem::Play()
240{
241 /* Always set the playing flag, even if there is no music */
242 _settings_client.music.playing = true;
243 MusicDriver::GetInstance()->StopSong();
244 /* Make sure playlist_position is a valid index, if playlist has changed etc. */
245 this->ChangePlaylistPosition(0);
246
247 /* If there is no music, don't try to play it */
248 if (this->active_playlist.empty()) return;
249
250 MusicSongInfo song = this->active_playlist[this->playlist_position];
251 if (_game_mode == GM_MENU && this->selected_playlist == PLCH_THEMEONLY) song.loop = true;
252 MusicDriver::GetInstance()->PlaySong(song);
253
254 InvalidateWindowData(WC_MUSIC_WINDOW, 0);
255}
256
258 void MusicSystem::Stop()
259{
260 MusicDriver::GetInstance()->StopSong();
261 _settings_client.music.playing = false;
262
263 InvalidateWindowData(WC_MUSIC_WINDOW, 0);
264}
265
267 void MusicSystem::Next()
268{
269 this->ChangePlaylistPosition(+1);
270 if (_settings_client.music.playing) this->Play();
271
272 InvalidateWindowData(WC_MUSIC_WINDOW, 0);
273}
274
276 void MusicSystem::Prev()
277{
278 this->ChangePlaylistPosition(-1);
279 if (_settings_client.music.playing) this->Play();
280
281 InvalidateWindowData(WC_MUSIC_WINDOW, 0);
282}
283
285 void MusicSystem::CheckStatus()
286{
287 if ((_game_mode == GM_MENU) != (this->selected_playlist == PLCH_THEMEONLY)) {
288 /* Make sure the theme-only playlist is active when on the title screen, and not during gameplay */
289 this->ChangePlaylist((_game_mode == GM_MENU) ? PLCH_THEMEONLY : (PlaylistChoices)_settings_client.music.playlist);
290 }
291 if (this->active_playlist.empty()) return;
292 /* If we were supposed to be playing, but music has stopped, move to next song */
293 if (this->IsPlaying() && !MusicDriver::GetInstance()->IsSongPlaying()) this->Next();
294}
295
297 bool MusicSystem::IsPlaying() const
298{
299 return _settings_client.music.playing && !this->active_playlist.empty();
300}
301
303 bool MusicSystem::IsShuffle() const
304{
305 return _settings_client.music.shuffle;
306}
307
309 MusicSystem::PlaylistEntry MusicSystem::GetCurrentSong() const
310{
311 if (!this->IsPlaying()) return PlaylistEntry(BaseMusic::GetUsedSet(), 0);
312 return this->active_playlist[this->playlist_position];
313}
314
316 bool MusicSystem::IsCustomPlaylist() const
317{
318 return (this->selected_playlist == PLCH_CUSTOM1) || (this->selected_playlist == PLCH_CUSTOM2);
319}
320
326 void MusicSystem::PlaylistAdd(size_t song_index)
327{
328 if (!this->IsCustomPlaylist()) return;
329
330 /* Pick out song from the music set */
331 if (song_index >= this->music_set.size()) return;
332 PlaylistEntry entry = this->music_set[song_index];
333
334 /* Check for maximum length */
335 if (this->standard_playlists[this->selected_playlist].size() >= NUM_SONGS_PLAYLIST) return;
336
337 /* Add it to the appropriate playlist, and the display */
338 this->standard_playlists[this->selected_playlist].push_back(entry);
339
340 /* Add it to the active playlist, if playback is shuffled select a random position to add at */
341 if (this->active_playlist.empty()) {
342 this->active_playlist.push_back(std::move(entry));
343 if (this->IsPlaying()) this->Play();
344 } else if (this->IsShuffle()) {
345 /* Generate a random position between 0 and n (inclusive, new length) to insert at */
346 size_t maxpos = this->active_playlist.size() + 1;
347 size_t newpos = InteractiveRandom() % maxpos;
348 this->active_playlist.insert(this->active_playlist.begin() + newpos, entry);
349 /* Make sure to shift up the current playback position if the song was inserted before it */
350 if ((int)newpos <= this->playlist_position) this->playlist_position++;
351 } else {
352 this->active_playlist.push_back(std::move(entry));
353 }
354
355 this->SaveCustomPlaylist(this->selected_playlist);
356
357 InvalidateWindowData(WC_MUSIC_TRACK_SELECTION, 0);
358}
359
364 void MusicSystem::PlaylistRemove(size_t song_index)
365{
366 if (!this->IsCustomPlaylist()) return;
367
368 if (song_index >= this->active_playlist.size()) return;
369
370 PlaylistEntry song = this->active_playlist[song_index];
371 this->active_playlist.erase(std::next(std::begin(this->active_playlist), song_index));
372
373 Playlist &playlist = this->standard_playlists[this->selected_playlist];
374 auto it = std::end(playlist);
375 if (this->IsShuffle()) {
376 /* Playlist is shuffled, so remove the first instance. */
377 it = std::ranges::find_if(playlist, [&song](const auto &s) { return s.filename == song.filename && s.cat_index == song.cat_index; });
378 } else if (song_index < playlist.size()) {
379 /* Not shuffled, we can remove the entry directly. */
380 it = std::next(std::begin(playlist), song_index);
381 }
382
383 if (it == std::end(playlist)) return;
384 it = playlist.erase(it);
385
386 /* If it's the current song restart playback. */
387 if (this->IsPlaying() && std::distance(std::begin(playlist), it) == this->playlist_position) this->Play();
388
389 this->SaveCustomPlaylist(this->selected_playlist);
390
391 InvalidateWindowData(WC_MUSIC_TRACK_SELECTION, 0);
392}
393
398 void MusicSystem::PlaylistClear()
399{
400 if (!this->IsCustomPlaylist()) return;
401
402 this->standard_playlists[this->selected_playlist].clear();
403 this->ChangePlaylist(this->selected_playlist);
404
405 this->SaveCustomPlaylist(this->selected_playlist);
406}
407
413 void MusicSystem::ChangePlaylistPosition(int ofs)
414{
415 if (this->active_playlist.empty()) {
416 this->playlist_position = 0;
417 } else {
418 this->playlist_position += ofs;
419 while (this->playlist_position >= (int)this->active_playlist.size()) this->playlist_position -= (int)this->active_playlist.size();
420 while (this->playlist_position < 0) this->playlist_position += (int)this->active_playlist.size();
421 }
422}
423
428 void MusicSystem::SaveCustomPlaylist(PlaylistChoices pl)
429{
430 uint8_t *settings_pl;
431 if (pl == PLCH_CUSTOM1) {
432 settings_pl = _settings_client.music.custom_1;
433 } else if (pl == PLCH_CUSTOM2) {
434 settings_pl = _settings_client.music.custom_2;
435 } else {
436 return;
437 }
438
439 size_t num = 0;
440 std::fill_n(settings_pl, NUM_SONGS_PLAYLIST, 0);
441
442 for (const auto &song : this->standard_playlists[pl]) {
443 /* Music set indices in the settings playlist are 1-based, 0 means unused slot */
444 settings_pl[num++] = (uint8_t)song.set_index + 1;
445 }
446}
447
448
453 void MusicLoop()
454{
455 _music.CheckStatus();
456}
457
462 void ChangeMusicSet(int index)
463{
464 if (BaseMusic::GetIndexOfUsedSet() == index) return;
465 _music.ChangeMusicSet(BaseMusic::GetSet(index)->name);
466}
467
472 void InitializeMusic()
473{
474 _music.BuildPlaylists();
475}
476
477
478 struct MusicTrackSelectionWindow : public Window {
479 MusicTrackSelectionWindow(WindowDesc &desc, WindowNumber number) : Window(desc)
480 {
481 this->InitNested(number);
482 this->LowerWidget(WID_MTS_LIST_LEFT);
483 this->LowerWidget(WID_MTS_LIST_RIGHT);
484 this->SetWidgetDisabledState(WID_MTS_CLEAR, _settings_client.music.playlist <= 3);
485 this->LowerWidget(WID_MTS_ALL + _settings_client.music.playlist);
486 }
487
488 std::string GetWidgetString(WidgetID widget, StringID stringid) const override
489 {
490 switch (widget) {
491 case WID_MTS_PLAYLIST:
492 return GetString(STR_PLAYLIST_PROGRAM, STR_MUSIC_PLAYLIST_ALL + _settings_client.music.playlist);
493
494 case WID_MTS_CAPTION:
495 return GetString(STR_PLAYLIST_MUSIC_SELECTION_SETNAME, BaseMusic::GetUsedSet()->name);
496
497 default:
498 return this->Window::GetWidgetString(widget, stringid);
499 }
500 }
501
507 void OnInvalidateData([[maybe_unused]] int data = 0, [[maybe_unused]] bool gui_scope = true) override
508 {
509 if (!gui_scope) return;
510 for (int i = 0; i < 6; i++) {
511 this->SetWidgetLoweredState(WID_MTS_ALL + i, i == _settings_client.music.playlist);
512 }
513 this->SetWidgetDisabledState(WID_MTS_CLEAR, _settings_client.music.playlist <= 3);
514
515 if (data == 1) {
516 this->ReInit();
517 } else {
518 this->SetDirty();
519 }
520 }
521
522 void UpdateWidgetSize(WidgetID widget, Dimension &size, [[maybe_unused]] const Dimension &padding, [[maybe_unused]] Dimension &fill, [[maybe_unused]] Dimension &resize) override
523 {
524 switch (widget) {
525 case WID_MTS_PLAYLIST: {
526 Dimension d = {0, 0};
527
528 for (int i = 0; i < 6; i++) {
529 d = maxdim(d, GetStringBoundingBox(GetString(STR_PLAYLIST_PROGRAM, STR_MUSIC_PLAYLIST_ALL + i)));
530 }
531 d.width += padding.width;
532 d.height += padding.height;
533 size = maxdim(size, d);
534 break;
535 }
536
537 case WID_MTS_LIST_LEFT: case WID_MTS_LIST_RIGHT: {
538 Dimension d = {0, 0};
539
540 for (const auto &song : _music.music_set) {
541 d = maxdim(d, GetStringBoundingBox(GetString(STR_PLAYLIST_TRACK_NAME, song.tracknr, 2, song.songname)));
542 }
543 d.height *= std::max(NUM_SONGS_AVAILABLE, NUM_SONGS_PLAYLIST);
544
545 d.width += padding.width;
546 d.height += padding.height;
547 size = maxdim(size, d);
548 break;
549 }
550 }
551 }
552
553 void DrawWidget(const Rect &r, WidgetID widget) const override
554 {
555 switch (widget) {
556 case WID_MTS_LIST_LEFT: {
557 GfxFillRect(r.Shrink(WidgetDimensions::scaled.bevel), PC_BLACK);
558
559 Rect tr = r.Shrink(WidgetDimensions::scaled.framerect);
560 for (const auto &song : _music.music_set) {
561 DrawString(tr, GetString(STR_PLAYLIST_TRACK_NAME, song.tracknr, 2, song.songname));
562 tr.top += GetCharacterHeight(FS_SMALL);
563 }
564 break;
565 }
566
567 case WID_MTS_LIST_RIGHT: {
568 GfxFillRect(r.Shrink(WidgetDimensions::scaled.bevel), PC_BLACK);
569
570 Rect tr = r.Shrink(WidgetDimensions::scaled.framerect);
571 for (const auto &song : _music.active_playlist) {
572 DrawString(tr, GetString(STR_PLAYLIST_TRACK_NAME, song.tracknr, 2, song.songname));
573 tr.top += GetCharacterHeight(FS_SMALL);
574 }
575 break;
576 }
577 }
578 }
579
580 void OnClick([[maybe_unused]] Point pt, WidgetID widget, [[maybe_unused]] int click_count) override
581 {
582 switch (widget) {
583 case WID_MTS_LIST_LEFT: { // add to playlist
584 int y = this->GetRowFromWidget(pt.y, widget, WidgetDimensions::scaled.framerect.top, GetCharacterHeight(FS_SMALL));
585 _music.PlaylistAdd(y);
586 break;
587 }
588
589 case WID_MTS_LIST_RIGHT: { // remove from playlist
590 int y = this->GetRowFromWidget(pt.y, widget, WidgetDimensions::scaled.framerect.top, GetCharacterHeight(FS_SMALL));
591 _music.PlaylistRemove(y);
592 break;
593 }
594
595 case WID_MTS_MUSICSET: {
596 int selected = 0;
597 ShowDropDownList(this, BuildSetDropDownList<BaseMusic>(&selected), selected, widget);
598 break;
599 }
600
601 case WID_MTS_CLEAR: // clear
602 _music.PlaylistClear();
603 break;
604
605 case WID_MTS_ALL: case WID_MTS_OLD: case WID_MTS_NEW:
606 case WID_MTS_EZY: case WID_MTS_CUSTOM1: case WID_MTS_CUSTOM2: // set playlist
607 _music.ChangePlaylist((MusicSystem::PlaylistChoices)(widget - WID_MTS_ALL));
608 break;
609 }
610 }
611
612 void OnDropdownSelect(WidgetID widget, int index, int) override
613 {
614 switch (widget) {
615 case WID_MTS_MUSICSET:
616 ChangeMusicSet(index);
617 break;
618 default:
619 NOT_REACHED();
620 }
621 }
622};
623
624static constexpr std::initializer_list<NWidgetPart> _nested_music_track_selection_widgets = {
625 NWidget(NWID_HORIZONTAL),
626 NWidget(WWT_CLOSEBOX, COLOUR_GREY),
627 NWidget(WWT_CAPTION, COLOUR_GREY, WID_MTS_CAPTION),
628 NWidget(WWT_DROPDOWN, COLOUR_GREY, WID_MTS_MUSICSET), SetStringTip(STR_PLAYLIST_CHANGE_SET, STR_PLAYLIST_TOOLTIP_CHANGE_SET),
629 EndContainer(),
630 NWidget(WWT_PANEL, COLOUR_GREY),
631 NWidget(NWID_HORIZONTAL), SetPIP(2, 4, 2),
632 /* Left panel. */
633 NWidget(NWID_VERTICAL),
634 NWidget(WWT_LABEL, INVALID_COLOUR), SetFill(1, 0), SetStringTip(STR_PLAYLIST_TRACK_INDEX),
635 NWidget(WWT_PANEL, COLOUR_GREY, WID_MTS_LIST_LEFT), SetFill(1, 1), SetMinimalSize(180, 194), SetToolTip(STR_PLAYLIST_TOOLTIP_CLICK_TO_ADD_TRACK), EndContainer(),
636 NWidget(NWID_SPACER), SetFill(1, 0), SetMinimalSize(0, 2),
637 EndContainer(),
638 /* Middle buttons. */
639 NWidget(NWID_VERTICAL),
640 NWidget(NWID_SPACER), SetMinimalSize(60, 30), // Space above the first button from the title bar.
641 NWidget(WWT_TEXTBTN, COLOUR_GREY, WID_MTS_ALL), SetFill(1, 0), SetStringTip(STR_MUSIC_PLAYLIST_ALL, STR_MUSIC_TOOLTIP_SELECT_ALL_TRACKS_PROGRAM),
642 NWidget(WWT_TEXTBTN, COLOUR_GREY, WID_MTS_OLD), SetFill(1, 0), SetStringTip(STR_MUSIC_PLAYLIST_OLD_STYLE, STR_MUSIC_TOOLTIP_SELECT_OLD_STYLE_MUSIC),
643 NWidget(WWT_TEXTBTN, COLOUR_GREY, WID_MTS_NEW), SetFill(1, 0), SetStringTip(STR_MUSIC_PLAYLIST_NEW_STYLE, STR_MUSIC_TOOLTIP_SELECT_NEW_STYLE_MUSIC),
644 NWidget(WWT_TEXTBTN, COLOUR_GREY, WID_MTS_EZY), SetFill(1, 0), SetStringTip(STR_MUSIC_PLAYLIST_EZY_STREET, STR_MUSIC_TOOLTIP_SELECT_EZY_STREET_STYLE),
645 NWidget(WWT_TEXTBTN, COLOUR_GREY, WID_MTS_CUSTOM1), SetFill(1, 0), SetStringTip(STR_MUSIC_PLAYLIST_CUSTOM_1, STR_MUSIC_TOOLTIP_SELECT_CUSTOM_1_USER_DEFINED),
646 NWidget(WWT_TEXTBTN, COLOUR_GREY, WID_MTS_CUSTOM2), SetFill(1, 0), SetStringTip(STR_MUSIC_PLAYLIST_CUSTOM_2, STR_MUSIC_TOOLTIP_SELECT_CUSTOM_2_USER_DEFINED),
647 NWidget(NWID_SPACER), SetMinimalSize(0, 16), // Space above 'clear' button
648 NWidget(WWT_PUSHTXTBTN, COLOUR_GREY, WID_MTS_CLEAR), SetFill(1, 0), SetStringTip(STR_PLAYLIST_CLEAR, STR_PLAYLIST_TOOLTIP_CLEAR_CURRENT_PROGRAM_CUSTOM1),
649 NWidget(NWID_SPACER), SetFill(0, 1),
650 EndContainer(),
651 /* Right panel. */
652 NWidget(NWID_VERTICAL),
653 NWidget(WWT_LABEL, INVALID_COLOUR, WID_MTS_PLAYLIST), SetFill(1, 0),
654 NWidget(WWT_PANEL, COLOUR_GREY, WID_MTS_LIST_RIGHT), SetFill(1, 1), SetMinimalSize(180, 194), SetToolTip(STR_PLAYLIST_TOOLTIP_CLICK_TO_REMOVE_TRACK), EndContainer(),
655 NWidget(NWID_SPACER), SetFill(1, 0), SetMinimalSize(0, 2),
656 EndContainer(),
657 EndContainer(),
658 EndContainer(),
659};
660
661static WindowDesc _music_track_selection_desc(
662 WDP_AUTO, {}, 0, 0,
663 WC_MUSIC_TRACK_SELECTION, WC_NONE,
664 {},
665 _nested_music_track_selection_widgets
666);
667
668static void ShowMusicTrackSelection()
669{
670 AllocateWindowDescFront<MusicTrackSelectionWindow>(_music_track_selection_desc, 0);
671}
672
673 struct MusicWindow : public Window {
674 MusicWindow(WindowDesc &desc, WindowNumber number) : Window(desc)
675 {
676 this->InitNested(number);
677 this->LowerWidget(_settings_client.music.playlist + WID_M_ALL);
678 this->SetWidgetLoweredState(WID_M_SHUFFLE, _settings_client.music.shuffle);
679
680 UpdateDisabledButtons();
681 }
682
683 void UpdateDisabledButtons()
684 {
685 /* Disable stop and play if there is no music. */
686 this->SetWidgetsDisabledState(BaseMusic::GetUsedSet()->num_available == 0, WID_M_STOP, WID_M_PLAY);
687 /* Disable most music control widgets if there is no music, or we are in the intro menu. */
688 this->SetWidgetsDisabledState(
689 BaseMusic::GetUsedSet()->num_available == 0 || _game_mode == GM_MENU,
690 WID_M_PREV, WID_M_NEXT, WID_M_SHUFFLE,
691 WID_M_ALL, WID_M_OLD, WID_M_NEW, WID_M_EZY, WID_M_CUSTOM1, WID_M_CUSTOM2
692 );
693 /* Also disable programme button in the intro menu (not in game; it is desirable to allow change of music set.) */
694 this->SetWidgetsDisabledState(_game_mode == GM_MENU, WID_M_PROGRAMME);
695 }
696
697 void UpdateWidgetSize(WidgetID widget, Dimension &size, [[maybe_unused]] const Dimension &padding, [[maybe_unused]] Dimension &fill, [[maybe_unused]] Dimension &resize) override
698 {
699 switch (widget) {
700 /* Make sure that WID_M_SHUFFLE and WID_M_PROGRAMME have the same size.
701 * This can't be done by using NWidContainerFlag::EqualSize as the WID_M_INFO is
702 * between those widgets and of different size. */
703 case WID_M_SHUFFLE: case WID_M_PROGRAMME: {
704 Dimension d = maxdim(GetStringBoundingBox(STR_MUSIC_PROGRAM), GetStringBoundingBox(STR_MUSIC_SHUFFLE));
705 d.width += padding.width;
706 d.height += padding.height;
707 size = maxdim(size, d);
708 break;
709 }
710
711 case WID_M_TRACK_NR: {
712 Dimension d = GetStringBoundingBox(STR_MUSIC_TRACK_NONE);
713 d = maxdim(d, GetStringBoundingBox(GetString(STR_MUSIC_TRACK_DIGIT, GetParamMaxDigits(2, FS_SMALL), 2)));
714 d.width += padding.width;
715 d.height += padding.height + WidgetDimensions::scaled.fullbevel.bottom;
716 size = maxdim(size, d);
717 break;
718 }
719
720 case WID_M_TRACK_NAME: {
721 Dimension d = GetStringBoundingBox(STR_MUSIC_TITLE_NONE);
722 for (const auto &song : _music.music_set) {
723 d = maxdim(d, GetStringBoundingBox(GetString(STR_MUSIC_TITLE_NAME, song.songname)));
724 }
725 d.width += padding.width;
726 d.height += padding.height + WidgetDimensions::scaled.fullbevel.bottom;
727 size = maxdim(size, d);
728 break;
729 }
730
731 /* Hack-ish: set the proper widget data; only needs to be done once
732 * per (Re)Init as that's the only time the language changes. */
733 case WID_M_PREV: this->GetWidget<NWidgetCore>(WID_M_PREV)->SetSprite(_current_text_dir == TD_RTL ? SPR_IMG_SKIP_TO_NEXT : SPR_IMG_SKIP_TO_PREV); break;
734 case WID_M_NEXT: this->GetWidget<NWidgetCore>(WID_M_NEXT)->SetSprite(_current_text_dir == TD_RTL ? SPR_IMG_SKIP_TO_PREV : SPR_IMG_SKIP_TO_NEXT); break;
735 case WID_M_PLAY: this->GetWidget<NWidgetCore>(WID_M_PLAY)->SetSprite(_current_text_dir == TD_RTL ? SPR_IMG_PLAY_MUSIC_RTL : SPR_IMG_PLAY_MUSIC); break;
736 }
737 }
738
739 void DrawWidget(const Rect &r, WidgetID widget) const override
740 {
741 switch (widget) {
742 case WID_M_TRACK_NR: {
743 GfxFillRect(r.Shrink(WidgetDimensions::scaled.bevel), PC_BLACK);
744 if (BaseMusic::GetUsedSet()->num_available == 0) {
745 break;
746 }
747 Rect ir = r.Shrink(WidgetDimensions::scaled.framerect);
748 if (_music.IsPlaying()) {
749 DrawString(ir, GetString(STR_MUSIC_TRACK_DIGIT, _music.GetCurrentSong().tracknr, 2), TC_FROMSTRING, SA_HOR_CENTER);
750 } else {
751 DrawString(ir, STR_MUSIC_TRACK_NONE, TC_FROMSTRING, SA_HOR_CENTER);
752 }
753 break;
754 }
755
756 case WID_M_TRACK_NAME: {
757 GfxFillRect(r.Shrink(WidgetDimensions::scaled.bevel), PC_BLACK);
758 Rect ir = r.Shrink(WidgetDimensions::scaled.framerect);
759
760 MusicSystem::PlaylistEntry entry(_music.GetCurrentSong());
761 if (BaseMusic::GetUsedSet()->num_available == 0) {
762 DrawString(ir, STR_MUSIC_TITLE_NOMUSIC, TC_FROMSTRING, SA_HOR_CENTER);
763 } else if (_music.IsPlaying()) {
764 DrawString(ir, GetString(STR_MUSIC_TITLE_NAME, entry.songname), TC_FROMSTRING, SA_HOR_CENTER);
765 } else {
766 DrawString(ir, STR_MUSIC_TITLE_NONE, TC_FROMSTRING, SA_HOR_CENTER);
767 }
768
769 break;
770 }
771
772 case WID_M_MUSIC_VOL:
773 DrawSliderWidget(r, COLOUR_GREY, COLOUR_GREY, TC_BLACK, 0, INT8_MAX, 0, _settings_client.music.music_vol, nullptr);
774 break;
775
776 case WID_M_EFFECT_VOL:
777 DrawSliderWidget(r, COLOUR_GREY, COLOUR_GREY, TC_BLACK, 0, INT8_MAX, 0, _settings_client.music.effect_vol, nullptr);
778 break;
779 }
780 }
781
787 void OnInvalidateData([[maybe_unused]] int data = 0, [[maybe_unused]] bool gui_scope = true) override
788 {
789 if (!gui_scope) return;
790 for (int i = 0; i < 6; i++) {
791 this->SetWidgetLoweredState(WID_M_ALL + i, i == _settings_client.music.playlist);
792 }
793
794 UpdateDisabledButtons();
795
796 if (data == 1) {
797 this->ReInit();
798 } else {
799 this->SetDirty();
800 }
801 }
802
803 void OnClick([[maybe_unused]] Point pt, WidgetID widget, [[maybe_unused]] int click_count) override
804 {
805 switch (widget) {
806 case WID_M_PREV: // skip to prev
807 _music.Prev();
808 break;
809
810 case WID_M_NEXT: // skip to next
811 _music.Next();
812 break;
813
814 case WID_M_STOP: // stop playing
815 _music.Stop();
816 break;
817
818 case WID_M_PLAY: // start playing
819 _music.Play();
820 break;
821
822 case WID_M_MUSIC_VOL: case WID_M_EFFECT_VOL: { // volume sliders
823 uint8_t &vol = (widget == WID_M_MUSIC_VOL) ? _settings_client.music.music_vol : _settings_client.music.effect_vol;
824 if (ClickSliderWidget(this->GetWidget<NWidgetBase>(widget)->GetCurrentRect(), pt, 0, INT8_MAX, 0, vol)) {
825 if (widget == WID_M_MUSIC_VOL) {
826 MusicDriver::GetInstance()->SetVolume(vol);
827 } else {
828 SetEffectVolume(vol);
829 }
830 this->SetWidgetDirty(widget);
831 SetWindowClassesDirty(WC_GAME_OPTIONS);
832 }
833
834 if (click_count > 0) this->mouse_capture_widget = widget;
835 break;
836 }
837
838 case WID_M_SHUFFLE: // toggle shuffle
839 if (_music.IsShuffle()) {
840 _music.Unshuffle();
841 } else {
842 _music.Shuffle();
843 }
844 this->SetWidgetLoweredState(WID_M_SHUFFLE, _music.IsShuffle());
845 this->SetWidgetDirty(WID_M_SHUFFLE);
846 break;
847
848 case WID_M_PROGRAMME: // show track selection
849 ShowMusicTrackSelection();
850 break;
851
852 case WID_M_ALL: case WID_M_OLD: case WID_M_NEW:
853 case WID_M_EZY: case WID_M_CUSTOM1: case WID_M_CUSTOM2: // playlist
854 _music.ChangePlaylist((MusicSystem::PlaylistChoices)(widget - WID_M_ALL));
855 break;
856 }
857 }
858};
859
860static constexpr std::initializer_list<NWidgetPart> _nested_music_window_widgets = {
861 NWidget(NWID_HORIZONTAL),
862 NWidget(WWT_CLOSEBOX, COLOUR_GREY),
863 NWidget(WWT_CAPTION, COLOUR_GREY), SetStringTip(STR_MUSIC_JAZZ_JUKEBOX_CAPTION, STR_TOOLTIP_WINDOW_TITLE_DRAG_THIS),
864 NWidget(WWT_SHADEBOX, COLOUR_GREY),
865 NWidget(WWT_STICKYBOX, COLOUR_GREY),
866 EndContainer(),
867
868 NWidget(NWID_HORIZONTAL),
869 NWidget(NWID_VERTICAL),
870 NWidget(WWT_PANEL, COLOUR_GREY), SetFill(1, 1), EndContainer(),
871 NWidget(NWID_HORIZONTAL),
872 NWidget(WWT_PUSHIMGBTN, COLOUR_GREY, WID_M_PREV), SetToolbarMinimalSize(1), SetSpriteTip(SPR_IMG_SKIP_TO_PREV, STR_MUSIC_TOOLTIP_SKIP_TO_PREVIOUS_TRACK),
873 NWidget(WWT_PUSHIMGBTN, COLOUR_GREY, WID_M_NEXT), SetToolbarMinimalSize(1), SetSpriteTip(SPR_IMG_SKIP_TO_NEXT, STR_MUSIC_TOOLTIP_SKIP_TO_NEXT_TRACK_IN_SELECTION),
874 NWidget(WWT_PUSHIMGBTN, COLOUR_GREY, WID_M_STOP), SetToolbarMinimalSize(1), SetSpriteTip(SPR_IMG_STOP_MUSIC, STR_MUSIC_TOOLTIP_STOP_PLAYING_MUSIC),
875 NWidget(WWT_PUSHIMGBTN, COLOUR_GREY, WID_M_PLAY), SetToolbarMinimalSize(1), SetSpriteTip(SPR_IMG_PLAY_MUSIC, STR_MUSIC_TOOLTIP_START_PLAYING_MUSIC),
876 EndContainer(),
877 NWidget(WWT_PANEL, COLOUR_GREY), SetFill(1, 1), EndContainer(),
878 EndContainer(),
879 NWidget(WWT_PANEL, COLOUR_GREY, WID_M_SLIDERS),
880 NWidget(NWID_HORIZONTAL), SetPIP(WidgetDimensions::unscaled.hsep_wide, WidgetDimensions::unscaled.hsep_wide, WidgetDimensions::unscaled.hsep_wide),
881 NWidget(NWID_VERTICAL), SetPIP(0, WidgetDimensions::unscaled.vsep_normal, WidgetDimensions::unscaled.vsep_normal), SetPIPRatio(1, 0, 1),
882 NWidget(WWT_LABEL, INVALID_COLOUR), SetFill(1, 0), SetStringTip(STR_MUSIC_MUSIC_VOLUME),
883 NWidget(WWT_EMPTY, INVALID_COLOUR, WID_M_MUSIC_VOL), SetMinimalSize(67, 0), SetMinimalTextLines(1, 0), SetFill(1, 0), SetToolTip(STR_MUSIC_TOOLTIP_DRAG_SLIDERS_TO_SET_MUSIC),
884 EndContainer(),
885 NWidget(NWID_VERTICAL), SetPIP(0, WidgetDimensions::unscaled.vsep_normal, WidgetDimensions::unscaled.vsep_normal), SetPIPRatio(1, 0, 1),
886 NWidget(WWT_LABEL, INVALID_COLOUR), SetFill(1, 0), SetStringTip(STR_MUSIC_EFFECTS_VOLUME),
887 NWidget(WWT_EMPTY, INVALID_COLOUR, WID_M_EFFECT_VOL), SetMinimalSize(67, 0), SetMinimalTextLines(1, 0), SetFill(1, 0), SetToolTip(STR_MUSIC_TOOLTIP_DRAG_SLIDERS_TO_SET_MUSIC),
888 EndContainer(),
889 EndContainer(),
890 EndContainer(),
891 EndContainer(),
892 NWidget(WWT_PANEL, COLOUR_GREY, WID_M_BACKGROUND),
893 NWidget(NWID_HORIZONTAL),
894 NWidget(NWID_VERTICAL), SetPIPRatio(1, 0, 1), SetPadding(WidgetDimensions::unscaled.frametext),
895 NWidget(WWT_TEXTBTN, COLOUR_GREY, WID_M_SHUFFLE), SetMinimalSize(50, 0), SetStringTip(STR_MUSIC_SHUFFLE, STR_MUSIC_TOOLTIP_TOGGLE_PROGRAM_SHUFFLE),
896 EndContainer(),
897 NWidget(NWID_VERTICAL), SetPIP(WidgetDimensions::unscaled.vsep_normal, WidgetDimensions::unscaled.vsep_normal, WidgetDimensions::unscaled.vsep_normal), SetPIPRatio(1, 0, 1),
898 NWidget(WWT_LABEL, INVALID_COLOUR, WID_M_TRACK), SetFill(0, 0), SetStringTip(STR_MUSIC_TRACK),
899 NWidget(WWT_INSET, COLOUR_GREY, WID_M_TRACK_NR), SetFill(0, 0), EndContainer(),
900 EndContainer(),
901 NWidget(NWID_VERTICAL), SetPIP(WidgetDimensions::unscaled.vsep_normal, WidgetDimensions::unscaled.vsep_normal, WidgetDimensions::unscaled.vsep_normal), SetPIPRatio(1, 0, 1),
902 NWidget(WWT_LABEL, INVALID_COLOUR, WID_M_TRACK_TITLE), SetFill(1, 0), SetStringTip(STR_MUSIC_XTITLE),
903 NWidget(WWT_INSET, COLOUR_GREY, WID_M_TRACK_NAME), SetFill(1, 0), EndContainer(),
904 EndContainer(),
905 NWidget(NWID_VERTICAL), SetPIPRatio(1, 0, 1), SetPadding(WidgetDimensions::unscaled.frametext),
906 NWidget(WWT_PUSHTXTBTN, COLOUR_GREY, WID_M_PROGRAMME), SetMinimalSize(50, 0), SetStringTip(STR_MUSIC_PROGRAM, STR_MUSIC_TOOLTIP_SHOW_MUSIC_TRACK_SELECTION),
907 EndContainer(),
908 EndContainer(),
909 EndContainer(),
910 NWidget(NWID_HORIZONTAL, NWidContainerFlag::EqualSize),
911 NWidget(WWT_TEXTBTN, COLOUR_GREY, WID_M_ALL), SetFill(1, 0), SetStringTip(STR_MUSIC_PLAYLIST_ALL, STR_MUSIC_TOOLTIP_SELECT_ALL_TRACKS_PROGRAM),
912 NWidget(WWT_TEXTBTN, COLOUR_GREY, WID_M_OLD), SetFill(1, 0), SetStringTip(STR_MUSIC_PLAYLIST_OLD_STYLE, STR_MUSIC_TOOLTIP_SELECT_OLD_STYLE_MUSIC),
913 NWidget(WWT_TEXTBTN, COLOUR_GREY, WID_M_NEW), SetFill(1, 0), SetStringTip(STR_MUSIC_PLAYLIST_NEW_STYLE, STR_MUSIC_TOOLTIP_SELECT_NEW_STYLE_MUSIC),
914 NWidget(WWT_TEXTBTN, COLOUR_GREY, WID_M_EZY), SetFill(1, 0), SetStringTip(STR_MUSIC_PLAYLIST_EZY_STREET, STR_MUSIC_TOOLTIP_SELECT_EZY_STREET_STYLE),
915 NWidget(WWT_TEXTBTN, COLOUR_GREY, WID_M_CUSTOM1), SetFill(1, 0), SetStringTip(STR_MUSIC_PLAYLIST_CUSTOM_1, STR_MUSIC_TOOLTIP_SELECT_CUSTOM_1_USER_DEFINED),
916 NWidget(WWT_TEXTBTN, COLOUR_GREY, WID_M_CUSTOM2), SetFill(1, 0), SetStringTip(STR_MUSIC_PLAYLIST_CUSTOM_2, STR_MUSIC_TOOLTIP_SELECT_CUSTOM_2_USER_DEFINED),
917 EndContainer(),
918};
919
920static WindowDesc _music_window_desc(
921 WDP_AUTO, "music", 0, 0,
922 WC_MUSIC_WINDOW, WC_NONE,
923 {},
924 _nested_music_window_widgets
925);
926
927void ShowMusicWindow()
928{
929 AllocateWindowDescFront<MusicWindow>(_music_window_desc, 0);
930}
base_media_base.h
Generic functions for replacing base data (graphics, sounds).
base_media_music.h
Generic functions for replacing base music data.
NUM_SONGS_AVAILABLE
static const uint NUM_SONGS_AVAILABLE
Maximum number of songs in the full playlist; theme song + the classes.
Definition base_media_music.h:20
NUM_SONGS_CLASS
static const uint NUM_SONGS_CLASS
Maximum number of songs in the 'class' playlists.
Definition base_media_music.h:16
NUM_SONGS_PLAYLIST
static const uint NUM_SONGS_PLAYLIST
Maximum number of songs in the (custom) playlist.
Definition base_media_music.h:23
BaseMedia< MusicSet >::GetUsedSet
static const MusicSet * GetUsedSet()
Return the used set.
Definition base_media_func.h:400
BaseMedia< MusicSet >::GetSet
static const MusicSet * GetSet(int index)
Get the name of the graphics set at the specified index.
Definition base_media_func.h:385
BaseMedia< MusicSet >::GetIndexOfUsedSet
static int GetIndexOfUsedSet()
Get the index of the currently active graphics set.
Definition base_media_func.h:369
BaseMedia< MusicSet >::SetSetByName
static bool SetSetByName(const std::string &name)
Set the set to be used.
Definition base_media_func.h:267
BaseMusic::ini_set
static std::string ini_set
The set as saved in the config file.
Definition base_media_music.h:66
MusicDriver::StopSong
virtual void StopSong()=0
Stop playing the current song.
MusicDriver::GetInstance
static MusicDriver * GetInstance()
Get the currently active instance of the music driver.
Definition music_driver.hpp:46
MusicDriver::PlaySong
virtual void PlaySong(const MusicSongInfo &song)=0
Play a particular song.
MusicDriver::SetVolume
virtual void SetVolume(uint8_t vol)=0
Set the volume, if possible.
WidgetDimensions::framerect
RectPadding framerect
Standard padding inside many panels.
Definition window_gui.h:40
WidgetDimensions::scaled
static WidgetDimensions scaled
Widget dimensions scaled for current zoom level.
Definition window_gui.h:30
WidgetDimensions::fullbevel
RectPadding fullbevel
Always-scaled bevel thickness.
Definition window_gui.h:39
WidgetDimensions::unscaled
static const WidgetDimensions unscaled
Unscaled widget dimensions.
Definition window_gui.h:93
WidgetDimensions::bevel
RectPadding bevel
Bevel thickness, affected by "scaled bevels" game option.
Definition window_gui.h:38
ShowDropDownList
void ShowDropDownList(Window *w, DropDownList &&list, int selected, WidgetID button, uint width, DropDownOptions options)
Show a drop down list.
Definition dropdown.cpp:418
dropdown_func.h
Functions related to the drop down widget.
dropdown_type.h
Types related to the drop down widget.
error.h
Functions related to errors.
GetCharacterHeight
int GetCharacterHeight(FontSize size)
Get height of a character for a given font size.
Definition fontcache.cpp:87
maxdim
Dimension maxdim(const Dimension &d1, const Dimension &d2)
Compute bounding box of both dimensions.
Definition geometry_func.cpp:22
geometry_func.hpp
Geometry functions.
GetStringBoundingBox
Dimension GetStringBoundingBox(std::string_view str, FontSize start_fontsize)
Return the string dimension in pixels.
Definition gfx.cpp:897
DrawString
int DrawString(int left, int right, int top, std::string_view str, TextColour colour, StringAlignment align, bool underline, FontSize fontsize)
Draw string, possibly truncated to make it fit in its allocated space.
Definition gfx.cpp:668
GfxFillRect
void GfxFillRect(int left, int top, int right, int bottom, const std::variant< PixelColour, PaletteID > &colour, FillRectMode mode)
Applies a certain FillRectMode-operation to a rectangle [left, right] x [top, bottom] on the screen.
Definition gfx.cpp:115
gfx_func.h
Functions related to the gfx engine.
FS_SMALL
@ FS_SMALL
Index of the small font in the font tables.
Definition gfx_type.h:250
SA_HOR_CENTER
@ SA_HOR_CENTER
Horizontally center the text.
Definition gfx_type.h:389
SetFill
constexpr NWidgetPart SetFill(uint16_t fill_x, uint16_t fill_y)
Widget part function for setting filling.
Definition widget_type.h:1222
SetSpriteTip
constexpr NWidgetPart SetSpriteTip(SpriteID sprite, StringID tip={})
Widget part function for setting the sprite and tooltip.
Definition widget_type.h:1254
SetToolbarMinimalSize
constexpr NWidgetPart SetToolbarMinimalSize(int width)
Widget part function to setting the minimal size for a toolbar button.
Definition widget_type.h:1178
SetPIP
constexpr NWidgetPart SetPIP(uint8_t pre, uint8_t inter, uint8_t post)
Widget part function for setting a pre/inter/post spaces.
Definition widget_type.h:1378
SetPadding
constexpr NWidgetPart SetPadding(uint8_t top, uint8_t right, uint8_t bottom, uint8_t left)
Widget part function for setting additional space around a widget.
Definition widget_type.h:1335
SetStringTip
constexpr NWidgetPart SetStringTip(StringID string, StringID tip={})
Widget part function for setting the string and tooltip.
Definition widget_type.h:1243
SetMinimalSize
constexpr NWidgetPart SetMinimalSize(int16_t x, int16_t y)
Widget part function for setting the minimal size.
Definition widget_type.h:1159
SetToolTip
constexpr NWidgetPart SetToolTip(StringID tip)
Widget part function for setting tooltip and clearing the widget data.
Definition widget_type.h:1321
EndContainer
constexpr NWidgetPart EndContainer()
Widget part function for denoting the end of a container (horizontal, vertical, WWT_FRAME,...
Definition widget_type.h:1232
NWidget
constexpr NWidgetPart NWidget(WidgetType tp, Colours col, WidgetID idx=INVALID_WIDGET)
Widget part function for starting a new 'real' widget.
Definition widget_type.h:1427
SetMinimalTextLines
constexpr NWidgetPart SetMinimalTextLines(uint8_t lines, uint8_t spacing, FontSize size=FS_NORMAL)
Widget part function for setting the minimal text lines.
Definition widget_type.h:1190
SetPIPRatio
constexpr NWidgetPart SetPIPRatio(uint8_t ratio_pre, uint8_t ratio_inter, uint8_t ratio_post)
Widget part function for setting a pre/inter/post ratio.
Definition widget_type.h:1390
Window::SetDirty
void SetDirty() const
Mark entire window as dirty (in need of re-paint)
Definition window.cpp:968
mixer.h
Functions to mix sound samples.
music_driver.hpp
Base for all music playback.
MusicLoop
void MusicLoop()
Check music playback status and start/stop/song-finished.
Definition music_gui.cpp:453
ChangeMusicSet
void ChangeMusicSet(int index)
Change the configured music set and reset playback.
Definition music_gui.cpp:462
InitializeMusic
void InitializeMusic()
Prepare the music system for use.
Definition music_gui.cpp:472
music_widget.h
Types related to the music widgets.
WID_MTS_OLD
@ WID_MTS_OLD
Old button.
Definition music_widget.h:21
WID_MTS_CUSTOM2
@ WID_MTS_CUSTOM2
Custom2 button.
Definition music_widget.h:25
WID_MTS_ALL
@ WID_MTS_ALL
All button.
Definition music_widget.h:20
WID_MTS_CUSTOM1
@ WID_MTS_CUSTOM1
Custom1 button.
Definition music_widget.h:24
WID_MTS_LIST_LEFT
@ WID_MTS_LIST_LEFT
Left button.
Definition music_widget.h:16
WID_MTS_EZY
@ WID_MTS_EZY
Ezy button.
Definition music_widget.h:23
WID_MTS_CLEAR
@ WID_MTS_CLEAR
Clear button.
Definition music_widget.h:26
WID_MTS_LIST_RIGHT
@ WID_MTS_LIST_RIGHT
Right button.
Definition music_widget.h:18
WID_MTS_NEW
@ WID_MTS_NEW
New button.
Definition music_widget.h:22
WID_MTS_PLAYLIST
@ WID_MTS_PLAYLIST
Playlist.
Definition music_widget.h:17
WID_MTS_MUSICSET
@ WID_MTS_MUSICSET
Music set selection.
Definition music_widget.h:19
WID_MTS_CAPTION
@ WID_MTS_CAPTION
Window caption.
Definition music_widget.h:15
WID_M_PREV
@ WID_M_PREV
Previous button.
Definition music_widget.h:31
WID_M_TRACK_NAME
@ WID_M_TRACK_NAME
Track name.
Definition music_widget.h:42
WID_M_NEXT
@ WID_M_NEXT
Next button.
Definition music_widget.h:32
WID_M_NEW
@ WID_M_NEW
New button.
Definition music_widget.h:47
WID_M_TRACK_TITLE
@ WID_M_TRACK_TITLE
Track title.
Definition music_widget.h:41
WID_M_STOP
@ WID_M_STOP
Stop button.
Definition music_widget.h:33
WID_M_BACKGROUND
@ WID_M_BACKGROUND
Background of the window.
Definition music_widget.h:38
WID_M_ALL
@ WID_M_ALL
All button.
Definition music_widget.h:45
WID_M_CUSTOM2
@ WID_M_CUSTOM2
Custom2 button.
Definition music_widget.h:50
WID_M_CUSTOM1
@ WID_M_CUSTOM1
Custom1 button.
Definition music_widget.h:49
WID_M_TRACK
@ WID_M_TRACK
Track playing.
Definition music_widget.h:39
WID_M_OLD
@ WID_M_OLD
Old button.
Definition music_widget.h:46
WID_M_SLIDERS
@ WID_M_SLIDERS
Sliders.
Definition music_widget.h:35
WID_M_SHUFFLE
@ WID_M_SHUFFLE
Shuffle button.
Definition music_widget.h:43
WID_M_EZY
@ WID_M_EZY
Ezy button.
Definition music_widget.h:48
WID_M_MUSIC_VOL
@ WID_M_MUSIC_VOL
Music volume.
Definition music_widget.h:36
WID_M_EFFECT_VOL
@ WID_M_EFFECT_VOL
Effect volume.
Definition music_widget.h:37
WID_M_TRACK_NR
@ WID_M_TRACK_NR
Track number.
Definition music_widget.h:40
WID_M_PROGRAMME
@ WID_M_PROGRAMME
Program button.
Definition music_widget.h:44
WID_M_PLAY
@ WID_M_PLAY
Play button.
Definition music_widget.h:34
openttd.h
Some generic types.
PC_BLACK
static constexpr PixelColour PC_BLACK
Black palette colour.
Definition palette_func.h:96
random_func.hpp
Pseudo random number generator.
safeguards.h
A number of safeguards to prevent using unsafe methods.
_settings_client
ClientSettings _settings_client
The current settings for this game.
Definition settings.cpp:60
settings_gui.h
Functions for setting GUIs.
settings_type.h
Types related to global configuration settings.
DrawSliderWidget
void DrawSliderWidget(Rect r, Colours wedge_colour, Colours handle_colour, TextColour text_colour, int min_value, int max_value, int nmarks, int value, SliderMarkFunc *mark_func)
Draw a slider widget with knob at given value.
Definition slider.cpp:34
ClickSliderWidget
bool ClickSliderWidget(Rect r, Point pt, int min_value, int max_value, int nmarks, int &value)
Handle click on a slider widget to change the value.
Definition slider.cpp:94
sound_func.h
Functions related to sound.
sprites.h
This file contains all sprite-related enums and defines.
stdafx.h
Definition of base types and functions in a cross-platform compatible way.
string_func.h
Functions related to low-level strings.
GetString
std::string GetString(StringID string)
Resolve the given StringID into a std::string with formatting but no parameters.
Definition strings.cpp:424
_current_text_dir
TextDirection _current_text_dir
Text direction of the currently selected language.
Definition strings.cpp:56
GetParamMaxDigits
uint64_t GetParamMaxDigits(uint count, FontSize size)
Get some number that is suitable for string size computations.
Definition strings.cpp:218
strings_func.h
Functions related to OTTD's strings.
StringID
uint32_t StringID
Numeric value that represents a string, independent of the selected language.
Definition strings_type.h:19
TD_RTL
@ TD_RTL
Text is written right-to-left by default.
Definition strings_type.h:27
ClientSettings::music
MusicSettings music
settings related to music/sound
Definition settings_type.h:654
Coord2D< int >
Dimension
Dimensions (a width and height) of a rectangle in 2D.
Definition geometry_type.hpp:56
MusicSet
All data of a music set.
Definition base_media_music.h:53
MusicSettings::effect_vol
uint8_t effect_vol
The requested effects volume.
Definition settings_type.h:286
MusicSettings::playing
bool playing
Whether music is playing.
Definition settings_type.h:289
MusicSettings::music_vol
uint8_t music_vol
The requested music volume.
Definition settings_type.h:285
MusicSettings::custom_1
uint8_t custom_1[33]
The order of the first custom playlist.
Definition settings_type.h:287
MusicSettings::custom_2
uint8_t custom_2[33]
The order of the second custom playlist.
Definition settings_type.h:288
MusicSettings::playlist
uint8_t playlist
The playlist (number) to play.
Definition settings_type.h:284
MusicSettings::shuffle
bool shuffle
Whether to shuffle the music.
Definition settings_type.h:290
MusicSongInfo
Metadata about a music track.
Definition base_media_music.h:35
MusicSongInfo::songname
std::string songname
name of song displayed in UI
Definition base_media_music.h:36
MusicSongInfo::tracknr
uint8_t tracknr
track number of song displayed in UI
Definition base_media_music.h:41
MusicSongInfo::filename
std::string filename
file on disk containing song (when used in MusicSet class)
Definition base_media_music.h:37
MusicSongInfo::loop
bool loop
song should play in a tight loop if possible, never ending
Definition base_media_music.h:43
MusicSongInfo::cat_index
int cat_index
entry index in CAT file, for filetype==MTT_MPSMIDI
Definition base_media_music.h:38
MusicSystem::PlaylistEntry
Definition music_gui.cpp:41
MusicSystem::PlaylistEntry::set
const MusicSet * set
music set the song comes from
Definition music_gui.cpp:42
MusicSystem::PlaylistEntry::set_index
uint set_index
index of song in set
Definition music_gui.cpp:43
MusicSystem
Definition music_gui.cpp:40
MusicSystem::SaveCustomPlaylist
void SaveCustomPlaylist(PlaylistChoices pl)
Save a custom playlist to settings after modification.
Definition music_gui.cpp:428
MusicSystem::CheckStatus
void CheckStatus()
Check that music is playing if it should, and that appropriate playlist is active for game/main menu.
Definition music_gui.cpp:285
MusicSystem::ChangeMusicSet
void ChangeMusicSet(const std::string &set_name)
Change to named music set, and reset playback.
Definition music_gui.cpp:170
MusicSystem::ChangePlaylist
void ChangePlaylist(PlaylistChoices pl)
Switch to another playlist, or reload the current one.
Definition music_gui.cpp:147
MusicSystem::Shuffle
void Shuffle()
Enable shuffle mode.
Definition music_gui.cpp:207
MusicSystem::Stop
void Stop()
Stop playback and set flag that we don't intend to play music.
Definition music_gui.cpp:258
MusicSystem::BuildPlaylists
void BuildPlaylists()
Rebuild all playlists for the current music set.
Definition music_gui.cpp:103
MusicSystem::Next
void Next()
Skip to next track.
Definition music_gui.cpp:267
MusicSystem::Play
void Play()
Start/restart playback at current song.
Definition music_gui.cpp:239
MusicSystem::IsPlaying
bool IsPlaying() const
Is the player getting music right now?
Definition music_gui.cpp:297
MusicSystem::Unshuffle
void Unshuffle()
Disable shuffle mode.
Definition music_gui.cpp:226
MusicSystem::PlaylistRemove
void PlaylistRemove(size_t song_index)
Remove a song from a custom playlist.
Definition music_gui.cpp:364
MusicSystem::GetCurrentSong
PlaylistEntry GetCurrentSong() const
Return the current song, or a dummy if none.
Definition music_gui.cpp:309
MusicSystem::PlaylistAdd
void PlaylistAdd(size_t song_index)
Append a song to a custom playlist.
Definition music_gui.cpp:326
MusicSystem::ChangePlaylistPosition
void ChangePlaylistPosition(int ofs)
Change playlist position pointer by the given offset, making sure to keep it within valid range.
Definition music_gui.cpp:413
MusicSystem::active_playlist
Playlist active_playlist
current play order of songs, including any shuffle
Definition music_gui.cpp:61
MusicSystem::Prev
void Prev()
Skip to previous track.
Definition music_gui.cpp:276
MusicSystem::PlaylistClear
void PlaylistClear()
Remove all songs from the current custom playlist.
Definition music_gui.cpp:398
MusicSystem::SetPositionBySetIndex
void SetPositionBySetIndex(uint set_index)
Set playlist position by set index.
Definition music_gui.cpp:187
MusicSystem::IsCustomPlaylist
bool IsCustomPlaylist() const
Is one of the custom playlists selected?
Definition music_gui.cpp:316
MusicSystem::IsShuffle
bool IsShuffle() const
Is shuffle mode enabled?
Definition music_gui.cpp:303
MusicSystem::music_set
Playlist music_set
all songs in current music set, in set order
Definition music_gui.cpp:62
MusicSystem::GetSetIndex
uint GetSetIndex()
Get set index from current playlist position.
Definition music_gui.cpp:197
MusicTrackSelectionWindow
Definition music_gui.cpp:478
MusicTrackSelectionWindow::UpdateWidgetSize
void UpdateWidgetSize(WidgetID widget, Dimension &size, const Dimension &padding, Dimension &fill, Dimension &resize) override
Update size and resize step of a widget in the window.
Definition music_gui.cpp:522
MusicTrackSelectionWindow::GetWidgetString
std::string GetWidgetString(WidgetID widget, StringID stringid) const override
Get the raw string for a widget.
Definition music_gui.cpp:488
MusicTrackSelectionWindow::OnClick
void OnClick(Point pt, WidgetID widget, int click_count) override
A click with the left mouse button has been made on the window.
Definition music_gui.cpp:580
MusicTrackSelectionWindow::DrawWidget
void DrawWidget(const Rect &r, WidgetID widget) const override
Draw the contents of a nested widget.
Definition music_gui.cpp:553
MusicTrackSelectionWindow::OnInvalidateData
void OnInvalidateData(int data=0, bool gui_scope=true) override
Some data on this window has become invalid.
Definition music_gui.cpp:507
MusicTrackSelectionWindow::OnDropdownSelect
void OnDropdownSelect(WidgetID widget, int index, int) override
A dropdown option associated to this window has been selected.
Definition music_gui.cpp:612
MusicWindow
Definition music_gui.cpp:673
MusicWindow::OnClick
void OnClick(Point pt, WidgetID widget, int click_count) override
A click with the left mouse button has been made on the window.
Definition music_gui.cpp:803
MusicWindow::UpdateWidgetSize
void UpdateWidgetSize(WidgetID widget, Dimension &size, const Dimension &padding, Dimension &fill, Dimension &resize) override
Update size and resize step of a widget in the window.
Definition music_gui.cpp:697
MusicWindow::DrawWidget
void DrawWidget(const Rect &r, WidgetID widget) const override
Draw the contents of a nested widget.
Definition music_gui.cpp:739
MusicWindow::OnInvalidateData
void OnInvalidateData(int data=0, bool gui_scope=true) override
Some data on this window has become invalid.
Definition music_gui.cpp:787
Rect
Specification of a rectangle with absolute coordinates of all edges.
Definition geometry_type.hpp:101
Rect::Shrink
Rect Shrink(int s) const
Copy and shrink Rect by s pixels.
Definition geometry_type.hpp:124
WindowDesc
High level window description.
Definition window_gui.h:168
WindowNumber
Number to differentiate different windows of the same class.
Definition window_type.h:760
Window
Data structure for an opened window.
Definition window_gui.h:274
Window::ReInit
void ReInit(int rx=0, int ry=0, bool reposition=false)
Re-initialize a window, and optionally change its size.
Definition window.cpp:980
Window::SetWidgetDirty
void SetWidgetDirty(WidgetID widget_index) const
Invalidate a widget, i.e.
Definition window.cpp:558
Window::GetWidgetString
virtual std::string GetWidgetString(WidgetID widget, StringID stringid) const
Get the raw string for a widget.
Definition window.cpp:506
Window::mouse_capture_widget
WidgetID mouse_capture_widget
ID of current mouse capture widget (e.g. dragged scrollbar). INVALID_WIDGET if no widget has mouse ca...
Definition window_gui.h:327
Window::resize
ResizeInfo resize
Resize information.
Definition window_gui.h:315
Window::SetWidgetsDisabledState
void SetWidgetsDisabledState(bool disab_stat, Args... widgets)
Sets the enabled/disabled status of a list of widgets.
Definition window_gui.h:516
Window::SetWidgetLoweredState
void SetWidgetLoweredState(WidgetID widget_index, bool lowered_stat)
Sets the lowered/raised status of a widget.
Definition window_gui.h:442
Window::GetRowFromWidget
int GetRowFromWidget(int clickpos, WidgetID widget, int padding, int line_height=-1) const
Compute the row of a widget that a user clicked in.
Definition window.cpp:212
Window::LowerWidget
void LowerWidget(WidgetID widget_index)
Marks a widget as lowered.
Definition window_gui.h:461
Window::InitNested
void InitNested(WindowNumber number=0)
Perform complete initialization of the Window with nested widgets, to allow use.
Definition window.cpp:1823
Window::SetWidgetDisabledState
void SetWidgetDisabledState(WidgetID widget_index, bool disab_stat)
Sets the enabled/disabled status of a widget.
Definition window_gui.h:382
WWT_PUSHTXTBTN
@ WWT_PUSHTXTBTN
Normal push-button (no toggle button) with text caption.
Definition widget_type.h:105
WWT_INSET
@ WWT_INSET
Pressed (inset) panel, most commonly used as combo box text area.
Definition widget_type.h:40
WWT_PUSHIMGBTN
@ WWT_PUSHIMGBTN
Normal push-button (no toggle button) with image caption.
Definition widget_type.h:106
WWT_LABEL
@ WWT_LABEL
Centered label.
Definition widget_type.h:48
NWID_SPACER
@ NWID_SPACER
Invisible widget that takes some space.
Definition widget_type.h:70
NWID_HORIZONTAL
@ NWID_HORIZONTAL
Horizontal container.
Definition widget_type.h:66
WWT_TEXTBTN
@ WWT_TEXTBTN
(Toggle) Button with text
Definition widget_type.h:44
WWT_PANEL
@ WWT_PANEL
Simple depressed panel.
Definition widget_type.h:39
WWT_STICKYBOX
@ WWT_STICKYBOX
Sticky box (at top-right of a window, after WWT_DEFSIZEBOX)
Definition widget_type.h:57
WWT_SHADEBOX
@ WWT_SHADEBOX
Shade box (at top-right of a window, between WWT_DEBUGBOX and WWT_DEFSIZEBOX)
Definition widget_type.h:55
WWT_CAPTION
@ WWT_CAPTION
Window caption (window title between closebox and stickybox)
Definition widget_type.h:52
NWID_VERTICAL
@ NWID_VERTICAL
Vertical container.
Definition widget_type.h:68
WWT_CLOSEBOX
@ WWT_CLOSEBOX
Close box (at top-left of a window)
Definition widget_type.h:60
WWT_EMPTY
@ WWT_EMPTY
Empty widget, place holder to reserve space in widget tree.
Definition widget_type.h:37
WWT_DROPDOWN
@ WWT_DROPDOWN
Drop down list.
Definition widget_type.h:61
EqualSize
@ EqualSize
Containers should keep all their (resizing) children equally large.
Definition widget_type.h:544
SetWindowClassesDirty
void SetWindowClassesDirty(WindowClass cls)
Mark all windows of a particular class as dirty (in need of repainting)
Definition window.cpp:3205
InvalidateWindowData
void InvalidateWindowData(WindowClass cls, WindowNumber number, int data, bool gui_scope)
Mark window data of the window of a given class and specific window number as invalid (in need of re-...
Definition window.cpp:3297
window_func.h
Window functions not directly related to making/drawing windows.
window_gui.h
Functions, definitions and such used only by the GUI.
WDP_AUTO
@ WDP_AUTO
Find a place automatically.
Definition window_gui.h:144
WidgetID
int WidgetID
Widget ID.
Definition window_type.h:20
WN_GAME_OPTIONS_GAME_OPTIONS
@ WN_GAME_OPTIONS_GAME_OPTIONS
Game options.
Definition window_type.h:31
WC_NONE
@ WC_NONE
No window, redirects to WC_MAIN_WINDOW.
Definition window_type.h:50
WC_MUSIC_TRACK_SELECTION
@ WC_MUSIC_TRACK_SELECTION
Music track selection; Window numbers:
Definition window_type.h:624
WC_MUSIC_WINDOW
@ WC_MUSIC_WINDOW
Music window; Window numbers:
Definition window_type.h:618
WC_GAME_OPTIONS
@ WC_GAME_OPTIONS
Game options window; Window numbers:
Definition window_type.h:635
zoom_func.h
Functions related to zooming.