mirror of https://github.com/OpenRCT2/OpenRCT2.git
Merge 4165bcc4d3
into d58673105d
This commit is contained in:
commit
a428cb9ee8
|
@ -119,6 +119,7 @@ Appreciation for contributors who have provided substantial work, but are no lon
|
|||
* Tiago Reul (reul) - Misc.
|
||||
* Fredrik Tegnell (fredriktegnell) - Misc.
|
||||
* Alex Parisi (alex-parisi) - Added API for returning metadata from all registered plugins.
|
||||
* John Dolph (johnwdolph) - Ride music UI, misc.
|
||||
|
||||
## Bug fixes & Refactors
|
||||
* Claudio Tiecher (janclod)
|
||||
|
|
|
@ -194,6 +194,8 @@ enum {
|
|||
WIDX_PLAY_MUSIC = 14,
|
||||
WIDX_MUSIC,
|
||||
WIDX_MUSIC_DROPDOWN,
|
||||
WIDX_MUSIC_IMAGE,
|
||||
WIDX_MUSIC_DATA,
|
||||
|
||||
WIDX_SAVE_TRACK_DESIGN = 14,
|
||||
WIDX_SELECT_NEARBY_SCENERY,
|
||||
|
@ -336,9 +338,11 @@ static Widget _colourWidgets[] = {
|
|||
// 0x009AE4C8
|
||||
static Widget _musicWidgets[] = {
|
||||
MAIN_RIDE_WIDGETS,
|
||||
MakeWidget({ 7, 47}, {302, 12}, WindowWidgetType::Checkbox, WindowColour::Secondary, STR_PLAY_MUSIC, STR_SELECT_MUSIC_TIP ),
|
||||
MakeWidget({ 7, 62}, {302, 12}, WindowWidgetType::DropdownMenu, WindowColour::Secondary, STR_EMPTY ),
|
||||
MakeWidget({297, 63}, { 11, 10}, WindowWidgetType::Button, WindowColour::Secondary, STR_DROPDOWN_GLYPH, STR_SELECT_MUSIC_STYLE_TIP),
|
||||
MakeWidget({ 7, 47}, {302, 12}, WindowWidgetType::Checkbox, WindowColour::Secondary, STR_PLAY_MUSIC, STR_SELECT_MUSIC_TIP ),
|
||||
MakeWidget({ 7, 62}, {302, 12}, WindowWidgetType::DropdownMenu, WindowColour::Secondary, STR_EMPTY ),
|
||||
MakeWidget({297, 63}, { 11, 10}, WindowWidgetType::Button, WindowColour::Secondary, STR_DROPDOWN_GLYPH, STR_SELECT_MUSIC_STYLE_TIP),
|
||||
MakeWidget({154, 62}, {114, 114}, WindowWidgetType::FlatBtn, WindowColour::Secondary ),
|
||||
MakeWidget({ 7, 90}, {500, 450}, WindowWidgetType::Scroll, WindowColour::Secondary, SCROLL_BOTH ),
|
||||
kWidgetsEnd,
|
||||
};
|
||||
|
||||
|
@ -961,6 +965,8 @@ static_assert(std::size(RatingNames) == 6);
|
|||
{
|
||||
case WINDOW_RIDE_PAGE_GRAPHS:
|
||||
return GraphsScrollGetSize(scrollIndex);
|
||||
case WINDOW_RIDE_PAGE_MUSIC:
|
||||
return MusicScrollGetSize(scrollIndex);
|
||||
}
|
||||
return {};
|
||||
}
|
||||
|
@ -986,6 +992,9 @@ static_assert(std::size(RatingNames) == 6);
|
|||
case WINDOW_RIDE_PAGE_GRAPHS:
|
||||
GraphsOnScrollDraw(dpi, scrollIndex);
|
||||
break;
|
||||
case WINDOW_RIDE_PAGE_MUSIC:
|
||||
MusicOnScrollDraw(dpi, scrollIndex);
|
||||
break;
|
||||
}
|
||||
}
|
||||
virtual void OnToolDown(WidgetIndex widgetIndex, const ScreenCoordsXY& screenCoords) override
|
||||
|
@ -4830,6 +4839,7 @@ static_assert(std::size(RatingNames) == 6);
|
|||
{
|
||||
int32_t activateMusic = (ride->lifecycle_flags & RIDE_LIFECYCLE_MUSIC) ? 0 : 1;
|
||||
SetOperatingSetting(rideId, RideSetSetting::Music, activateMusic);
|
||||
ride->window_invalidate_flags |= RIDE_INVALIDATE_RIDE_MUSIC;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -4860,8 +4870,21 @@ static_assert(std::size(RatingNames) == 6);
|
|||
|
||||
void MusicResize()
|
||||
{
|
||||
flags |= WF_RESIZABLE;
|
||||
WindowSetResize(*this, 316, 81, 316, 81);
|
||||
if (auto ride = GetRide(rideId); ride != nullptr)
|
||||
{
|
||||
// Expand the window when music is playing
|
||||
auto isMusicActivated = (ride->lifecycle_flags & RIDE_LIFECYCLE_MUSIC) != 0;
|
||||
if (isMusicActivated)
|
||||
{
|
||||
WindowSetResize(*this, 316, 207, 500, 450);
|
||||
}
|
||||
else
|
||||
{
|
||||
height = 81;
|
||||
width = 316;
|
||||
WindowSetResize(*this, 316, 81, 500, 450);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static std::string GetMusicString(ObjectEntryIndex musicObjectIndex)
|
||||
|
@ -4965,6 +4988,92 @@ static_assert(std::size(RatingNames) == 6);
|
|||
frame_no++;
|
||||
OnPrepareDraw();
|
||||
WidgetInvalidate(*this, WIDX_TAB_6);
|
||||
|
||||
if (auto ride = GetRide(rideId); ride != nullptr && ride->window_invalidate_flags & RIDE_INVALIDATE_RIDE_MUSIC)
|
||||
{
|
||||
ride->window_invalidate_flags &= ~RIDE_INVALIDATE_RIDE_MUSIC;
|
||||
Invalidate();
|
||||
OnResize();
|
||||
OnPrepareDraw();
|
||||
Invalidate();
|
||||
}
|
||||
|
||||
WidgetScrollUpdateThumbs(*this, WIDX_MUSIC_DATA);
|
||||
}
|
||||
|
||||
ScreenSize MusicScrollGetSize(int32_t scrollIndex)
|
||||
{
|
||||
OnPrepareDraw();
|
||||
|
||||
ScreenSize size{};
|
||||
// Set minimum size
|
||||
size.height = widgets[WIDX_MUSIC_DATA].height() - 2;
|
||||
size.width = widgets[WIDX_MUSIC_DATA].width() - 2;
|
||||
|
||||
auto ride = GetRide(rideId);
|
||||
if (ride != nullptr)
|
||||
{
|
||||
auto musicObj = ride->GetMusicObject();
|
||||
|
||||
if (musicObj != nullptr)
|
||||
{
|
||||
// scroll width (based on characters in longest row)
|
||||
int32_t newWidth = 0;
|
||||
for (size_t i = 0; i < musicObj->GetTrackCount(); i++)
|
||||
{
|
||||
const auto* track = musicObj->GetTrack(i);
|
||||
if (track->Name.empty())
|
||||
continue;
|
||||
|
||||
int32_t rowLength = static_cast<int32_t>(track->Name.size() + track->Composer.size());
|
||||
if (rowLength > newWidth)
|
||||
{
|
||||
newWidth = rowLength;
|
||||
}
|
||||
}
|
||||
newWidth = newWidth * (SCROLLABLE_ROW_HEIGHT - 6) + 10;
|
||||
|
||||
auto left = newWidth - widgets[WIDX_MUSIC_DATA].right + widgets[WIDX_MUSIC_DATA].left + 13;
|
||||
if (left < 0)
|
||||
{
|
||||
scrolls[0].flags &= ~HSCROLLBAR_VISIBLE;
|
||||
left = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
scrolls[0].flags |= HSCROLLBAR_VISIBLE;
|
||||
}
|
||||
|
||||
if (left < scrolls[0].h_left)
|
||||
{
|
||||
scrolls[0].h_left = left;
|
||||
Invalidate();
|
||||
}
|
||||
|
||||
// scroll height (based on number of rows)
|
||||
const auto newHeight = static_cast<int32_t>(musicObj->GetTrackCount() * SCROLLABLE_ROW_HEIGHT);
|
||||
auto top = newHeight - widgets[WIDX_MUSIC_DATA].bottom + widgets[WIDX_MUSIC_DATA].top + 13;
|
||||
if (top < 0)
|
||||
{
|
||||
top = 0;
|
||||
scrolls[0].flags &= ~VSCROLLBAR_VISIBLE;
|
||||
}
|
||||
else
|
||||
{
|
||||
scrolls[0].flags |= VSCROLLBAR_VISIBLE;
|
||||
}
|
||||
|
||||
if (top < scrolls[0].v_top)
|
||||
{
|
||||
scrolls[0].v_top = top;
|
||||
Invalidate();
|
||||
}
|
||||
|
||||
size = { newWidth, newHeight };
|
||||
}
|
||||
}
|
||||
|
||||
return size;
|
||||
}
|
||||
|
||||
void MusicOnPrepareDraw()
|
||||
|
@ -4987,27 +5096,68 @@ static_assert(std::size(RatingNames) == 6);
|
|||
|
||||
// Set selected music
|
||||
StringId musicName = STR_NONE;
|
||||
auto& objManager = GetContext()->GetObjectManager();
|
||||
auto musicObj = static_cast<MusicObject*>(objManager.GetLoadedObject(ObjectType::Music, ride->music));
|
||||
auto musicObj = ride->GetMusicObject();
|
||||
if (musicObj != nullptr)
|
||||
{
|
||||
musicName = musicObj->NameStringId;
|
||||
}
|
||||
widgets[WIDX_MUSIC].text = musicName;
|
||||
|
||||
// Set music activated
|
||||
auto isMusicActivated = (ride->lifecycle_flags & RIDE_LIFECYCLE_MUSIC) != 0;
|
||||
|
||||
if (isMusicActivated)
|
||||
{
|
||||
// resize widgets
|
||||
widgets[WIDX_MUSIC_DATA].bottom = height - 32;
|
||||
|
||||
bool hasPreview = musicObj->HasPreview();
|
||||
if (hasPreview)
|
||||
{
|
||||
WidgetSetVisible(*this, WIDX_MUSIC_IMAGE, true);
|
||||
widgets[WIDX_MUSIC_DATA].right = width - 129;
|
||||
widgets[WIDX_MUSIC_IMAGE].left = width - 121;
|
||||
widgets[WIDX_MUSIC_IMAGE].right = width - 8;
|
||||
}
|
||||
else
|
||||
{
|
||||
widgets[WIDX_MUSIC_DATA].right = width - 8;
|
||||
WidgetSetVisible(*this, WIDX_MUSIC_IMAGE, false);
|
||||
}
|
||||
// enable window resize
|
||||
flags |= WF_RESIZABLE;
|
||||
|
||||
widgets[WIDX_MUSIC].right = widgets[WIDX_MUSIC_DATA].right;
|
||||
widgets[WIDX_MUSIC_DROPDOWN].right = widgets[WIDX_MUSIC_DATA].right - 1;
|
||||
widgets[WIDX_MUSIC_DROPDOWN].left = widgets[WIDX_MUSIC_DATA].right - 11;
|
||||
|
||||
pressed_widgets |= (1uLL << WIDX_PLAY_MUSIC);
|
||||
pressed_widgets |= (1uLL << WIDX_MUSIC_IMAGE);
|
||||
disabled_widgets &= ~(1uLL << WIDX_MUSIC);
|
||||
disabled_widgets &= ~(1uLL << WIDX_MUSIC_DROPDOWN);
|
||||
disabled_widgets |= (1uLL << WIDX_MUSIC_IMAGE);
|
||||
disabled_widgets &= ~(1uLL << WIDX_MUSIC_DATA);
|
||||
|
||||
WidgetSetVisible(*this, WIDX_MUSIC_DATA, true);
|
||||
}
|
||||
else
|
||||
{
|
||||
// hide widgets not applicable
|
||||
WidgetSetVisible(*this, WIDX_MUSIC_IMAGE, false);
|
||||
WidgetSetVisible(*this, WIDX_MUSIC_DATA, false);
|
||||
|
||||
// disable resizing
|
||||
flags &= ~WF_RESIZABLE;
|
||||
|
||||
widgets[WIDX_MUSIC].right = width - 8;
|
||||
widgets[WIDX_MUSIC_DROPDOWN].right = width - 9;
|
||||
widgets[WIDX_MUSIC_DROPDOWN].left = width - 19;
|
||||
|
||||
pressed_widgets &= ~(1uLL << WIDX_PLAY_MUSIC);
|
||||
pressed_widgets |= (1uLL << WIDX_MUSIC_IMAGE);
|
||||
disabled_widgets |= (1uLL << WIDX_MUSIC);
|
||||
disabled_widgets |= (1uLL << WIDX_MUSIC_DROPDOWN);
|
||||
disabled_widgets |= (1uLL << WIDX_MUSIC_IMAGE);
|
||||
disabled_widgets |= (1uLL << WIDX_MUSIC_DATA);
|
||||
}
|
||||
|
||||
AnchorBorderWidgets();
|
||||
|
@ -5018,6 +5168,111 @@ static_assert(std::size(RatingNames) == 6);
|
|||
{
|
||||
DrawWidgets(dpi);
|
||||
DrawTabImages(dpi);
|
||||
auto ride = GetRide(rideId);
|
||||
if (ride == nullptr)
|
||||
return;
|
||||
|
||||
// draw music data only when music is activated
|
||||
auto isMusicActivated = (ride->lifecycle_flags & RIDE_LIFECYCLE_MUSIC) != 0;
|
||||
if (isMusicActivated)
|
||||
{
|
||||
auto screenPos = windowPos
|
||||
+ ScreenCoordsXY{ widgets[WIDX_PAGE_BACKGROUND].left, widgets[WIDX_PAGE_BACKGROUND].top + 1 };
|
||||
screenPos.y += DrawTextWrapped(
|
||||
dpi, screenPos + ScreenCoordsXY{ widgets[WIDX_MUSIC_DATA].left, 33 }, width,
|
||||
STR_MUSIC_OBJECT_TRACK_HEADER)
|
||||
+ 2;
|
||||
|
||||
auto musicObj = ride->GetMusicObject();
|
||||
|
||||
bool hasPreview = musicObj->HasPreview();
|
||||
if (hasPreview)
|
||||
{
|
||||
const auto& previewWidget = widgets[WIDX_MUSIC_IMAGE];
|
||||
|
||||
int32_t _width = previewWidget.width() - 1;
|
||||
int32_t _height = previewWidget.height() - 1;
|
||||
|
||||
// draw background rectangle for image preview
|
||||
GfxFillRect(
|
||||
dpi,
|
||||
{ windowPos + ScreenCoordsXY{ previewWidget.left + 1, previewWidget.top + 1 },
|
||||
windowPos + ScreenCoordsXY{ previewWidget.right - 1, previewWidget.bottom - 1 } },
|
||||
ColourMapA[colours[1]].darkest);
|
||||
|
||||
// Draw preview image
|
||||
DrawPixelInfo clipDPI;
|
||||
screenPos = windowPos + ScreenCoordsXY{ previewWidget.left + 1, previewWidget.top + 1 };
|
||||
if (ClipDrawPixelInfo(clipDPI, dpi, screenPos, _width, _height))
|
||||
{
|
||||
musicObj->DrawPreview(clipDPI, _width, _height);
|
||||
}
|
||||
}
|
||||
|
||||
// Draw object author (will be blank space if no author in file or a non JSON object)
|
||||
{
|
||||
auto ft = Formatter();
|
||||
std::string authorsString;
|
||||
for (size_t i = 0; i < musicObj->GetAuthors().size(); i++)
|
||||
{
|
||||
if (i > 0)
|
||||
{
|
||||
authorsString.append(", ");
|
||||
}
|
||||
authorsString.append(musicObj->GetAuthors()[i]);
|
||||
}
|
||||
ft.Add<StringId>(STR_STRING);
|
||||
ft.Add<const char*>(authorsString.c_str());
|
||||
|
||||
screenPos = windowPos
|
||||
+ ScreenCoordsXY{ widgets[WIDX_PAGE_BACKGROUND].left + 1, widgets[WIDX_PAGE_BACKGROUND].top + 1 };
|
||||
|
||||
DrawTextEllipsised(
|
||||
dpi,
|
||||
{ windowPos.x + widgets[WIDX_PAGE_BACKGROUND].left + widgets[WIDX_MUSIC_DATA].left,
|
||||
screenPos.y + height - 72 },
|
||||
widgets[WIDX_MUSIC_DATA].right - widgets[WIDX_MUSIC_DATA].left + 127, STR_WINDOW_COLOUR_2_STRINGID, ft,
|
||||
{ TextAlignment::LEFT });
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void MusicOnScrollDraw(DrawPixelInfo& dpi, int32_t scrollIndex)
|
||||
{
|
||||
GfxClear(dpi, ColourMapA[colours[1]].mid_light);
|
||||
|
||||
auto ride = GetRide(rideId);
|
||||
if (ride == nullptr)
|
||||
return;
|
||||
|
||||
// draw music data only when music is activated
|
||||
auto isMusicActivated = (ride->lifecycle_flags & RIDE_LIFECYCLE_MUSIC) != 0;
|
||||
if (isMusicActivated)
|
||||
{
|
||||
auto dpiCoords = ScreenCoordsXY{ dpi.x, dpi.y };
|
||||
GfxFillRect(
|
||||
dpi, { dpiCoords, dpiCoords + ScreenCoordsXY{ dpi.width, dpi.height } }, ColourMapA[colours[1]].mid_light);
|
||||
|
||||
auto musicObj = ride->GetMusicObject();
|
||||
|
||||
auto y = 0;
|
||||
for (size_t i = 0; i < musicObj->GetTrackCount(); i++)
|
||||
{
|
||||
const auto* track = musicObj->GetTrack(i);
|
||||
if (track->Name.empty())
|
||||
continue;
|
||||
|
||||
auto stringId = track->Composer.empty() ? STR_MUSIC_OBJECT_TRACK_LIST_ITEM
|
||||
: STR_MUSIC_OBJECT_TRACK_LIST_ITEM_WITH_COMPOSER;
|
||||
auto ft = Formatter();
|
||||
ft.Add<const char*>(track->Name.c_str());
|
||||
ft.Add<const char*>(track->Composer.c_str());
|
||||
|
||||
DrawTextBasic(dpi, { 0, y }, stringId, ft);
|
||||
|
||||
y += SCROLLABLE_ROW_HEIGHT;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#pragma endregion
|
||||
|
|
|
@ -98,6 +98,11 @@ void MusicObject::DrawPreview(DrawPixelInfo& dpi, int32_t width, int32_t height)
|
|||
DrawTextBasic(dpi, { x, y }, STR_WINDOW_NO_IMAGE, {}, { TextAlignment::CENTRE });
|
||||
}
|
||||
|
||||
bool MusicObject::HasPreview() const
|
||||
{
|
||||
return _hasPreview;
|
||||
}
|
||||
|
||||
void MusicObject::ReadJson(IReadObjectContext* context, json_t& root)
|
||||
{
|
||||
_originalStyleId = {};
|
||||
|
|
|
@ -60,6 +60,7 @@ public:
|
|||
void Unload() override;
|
||||
|
||||
void DrawPreview(DrawPixelInfo& dpi, int32_t width, int32_t height) const override;
|
||||
bool HasPreview() const;
|
||||
|
||||
std::optional<uint8_t> GetOriginalStyleId() const;
|
||||
bool SupportsRideType(ride_type_t rideType);
|
||||
|
|
|
@ -812,6 +812,7 @@ enum
|
|||
RIDE_INVALIDATE_RIDE_LIST = 1 << 3,
|
||||
RIDE_INVALIDATE_RIDE_OPERATING = 1 << 4,
|
||||
RIDE_INVALIDATE_RIDE_MAINTENANCE = 1 << 5,
|
||||
RIDE_INVALIDATE_RIDE_MUSIC = 1 << 6,
|
||||
};
|
||||
|
||||
enum
|
||||
|
|
Loading…
Reference in New Issue