1
0
mirror of https://github.com/ppy/osu.git synced 2024-12-14 19:22:54 +08:00
This commit is contained in:
HoutarouOreki 2018-07-18 01:35:06 +02:00
parent 3c1e445fdf
commit 523d47e815
10 changed files with 397 additions and 126 deletions

View File

@ -11,16 +11,22 @@ namespace osu.Game.Tests.Visual
public class TestCaseChangelog : OsuTestCase
{
private ChangelogOverlay changelog;
private int releaseStreamCount;
private int index;
protected override void LoadComplete()
{
base.LoadComplete();
Add(changelog = new ChangelogOverlay());
releaseStreamCount = changelog.streams.badgesContainer.Children.Count;
AddStep(@"Show", changelog.Show);
AddStep(@"Stable Release Stream", () => changelog.header.ShowReleaseStream("Stable", "Stable 20180626.1"));
AddStep(@"Lazer Release Stream", () => changelog.header.ShowReleaseStream("Lazer", "Lazer 2018.713.1"));
AddRepeatStep(@"Toggle Release Stream", () => {
changelog.streams.badgesContainer.Children[index].Activate();
index = (index == releaseStreamCount - 1) ? 0 : index + 1;
}, releaseStreamCount);
AddStep(@"Listing", changelog.header.ActivateListing);
}

View File

@ -0,0 +1,17 @@
// Copyright (c) 2007-2018 ppy Pty Ltd <contact@ppy.sh>.
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
using OpenTK.Graphics;
namespace osu.Game.Graphics
{
public class StreamColour
{
public readonly Color4 Stable = new Color4(102, 204, 255, 255);
public readonly Color4 StableFallback = new Color4(34, 153, 187, 255);
public readonly Color4 Beta = new Color4(255, 221, 85, 255);
public readonly Color4 CuttingEdge = new Color4(238, 170, 0, 255);
public readonly Color4 Lazer = new Color4(237, 18, 33, 255);
public readonly Color4 Web = new Color4(136, 102, 238, 255);
}
}

View File

@ -12,13 +12,12 @@ using osu.Framework.Graphics.Textures;
using osu.Game.Graphics;
using osu.Game.Graphics.Sprites;
using osu.Game.Overlays.Changelog.Header;
using System;
namespace osu.Game.Overlays.Changelog
{
public class ChangelogHeader : Container
{
private readonly Container coverContainer;
protected Color4 purple = new Color4(191, 4, 255, 255);
private readonly Sprite coverImage;
private readonly Sprite headerBadge; //50x50, margin-right: 20
@ -29,6 +28,8 @@ namespace osu.Game.Overlays.Changelog
private readonly TextBadgePairRelease releaseStream;
private readonly FillFlowContainer breadcrumbContainer;
public Action OnListingActivated;
private const float cover_height = 310;
private const float title_height = 50;
private const float icon_size = 50;
@ -38,137 +39,128 @@ namespace osu.Game.Overlays.Changelog
public ChangelogHeader()
{
RelativeSizeAxes = Axes.X;
Height = cover_height + 5; // 5 is for the "badge" that sticks a bit out of the bottom
Masking = true; // is masking necessary? since I see it nearly everywhere
Height = cover_height;
Children = new Drawable[]
{
coverContainer = new Container
coverImage = new Sprite
{
RelativeSizeAxes = Axes.X,
Height = cover_height,
RelativeSizeAxes = Axes.Both,
Size = new OpenTK.Vector2(1),
FillMode = FillMode.Fill,
Anchor = Anchor.Centre,
Origin = Anchor.Centre,
},
new Container // this is the line badge-Changelog-Stream
{
Height = title_height,
Anchor = Anchor.BottomLeft,
Origin = Anchor.BottomLeft,
Y = -version_height,
Children = new Drawable[]
{
coverImage = new Sprite
new CircularContainer // a purple circle
{
RelativeSizeAxes = Axes.Both,
Size = new OpenTK.Vector2(1),
FillMode = FillMode.Fill,
Anchor = Anchor.Centre,
Origin = Anchor.Centre,
},
new Container // this is the line badge-Changelog-Stream
{
Height = title_height,
Anchor = Anchor.BottomLeft,
Origin = Anchor.BottomLeft,
Y = -version_height,
X = icon_margin,
Masking = true,
BorderColour = purple,
BorderThickness = 3,
MaskingSmoothness = 1,
Size = new OpenTK.Vector2(50),
Children = new Drawable[]
{
new CircularContainer // a purple circle
headerBadge = new Sprite
{
X = icon_margin,
Masking = true,
BorderColour = purple,
BorderThickness = 3,
MaskingSmoothness = 1,
Size = new OpenTK.Vector2(50),
Children = new Drawable[]
{
headerBadge = new Sprite
{
RelativeSizeAxes = Axes.Both,
Size = new OpenTK.Vector2(0.8f),
Anchor = Anchor.Centre,
Origin = Anchor.Centre,
},
// this box has 2 functions:
// - ensures the circle doesn't disappear on the X and Y edges
// - lessens the white "contamination" on the circle (due to smoothing)
new Box
{
RelativeSizeAxes = Axes.Both,
Size = new OpenTK.Vector2(1),
Alpha = 0,
AlwaysPresent = true,
Colour = purple,
}
}
RelativeSizeAxes = Axes.Both,
Size = new OpenTK.Vector2(0.8f),
Anchor = Anchor.Centre,
Origin = Anchor.Centre,
},
headerTextContainer = new FillFlowContainer
// this box has 2 functions:
// - ensures the circle doesn't disappear on the X and Y edges
// - lessens the white "contamination" on the circle (due to smoothing)
new Box
{
AutoSizeAxes = Axes.Both,
Direction = FillDirection.Horizontal,
Anchor = Anchor.CentreLeft,
Origin = Anchor.CentreLeft,
X = icon_size + icon_margin * 2,
Children = new Drawable[]
{
title = new OsuSpriteText
{
Text = "Changelog ",
Font = @"Exo2.0-Light",
TextSize = 38, // web: 30
},
titleStream = new OsuSpriteText
{
Text = "Listing",
TextSize = 38, // web: 30
Font = @"Exo2.0-Light",
Colour = purple,
},
}
RelativeSizeAxes = Axes.Both,
Size = new OpenTK.Vector2(1),
Alpha = 0,
AlwaysPresent = true,
Colour = purple,
}
}
},
breadcrumbContainer = new FillFlowContainer // Listing > Lazer 2018.713.1
headerTextContainer = new FillFlowContainer
{
X = 2 * icon_margin + icon_size - 8,
Height = version_height,
Anchor = Anchor.BottomLeft,
Origin = Anchor.BottomLeft,
AutoSizeAxes = Axes.Both,
Direction = FillDirection.Horizontal,
Anchor = Anchor.CentreLeft,
Origin = Anchor.CentreLeft,
X = icon_size + icon_margin * 2,
Children = new Drawable[]
{
listing = new TextBadgePairListing(purple),
new Container() // without a container, moving the chevron wont work
title = new OsuSpriteText
{
Anchor = Anchor.CentreLeft,
Origin = Anchor.CentreLeft,
Margin = new MarginPadding()
{
Top = 10,
Left = 7,
Right = 9,
Bottom = 15,
},
Children = new Drawable[]
{
chevron = new SpriteIcon
{
Anchor = Anchor.Centre,
Origin = Anchor.Centre,
Size = new Vector2(7),
Colour = purple,
Icon = FontAwesome.fa_chevron_right,
Alpha = 0,
X = -200,
},
},
Text = "Changelog ",
Font = @"Exo2.0-Light",
TextSize = 38, // web: 30
},
titleStream = new OsuSpriteText
{
Text = "Listing",
TextSize = 38, // web: 30
Font = @"Exo2.0-Light",
Colour = purple,
},
}
}
}
},
breadcrumbContainer = new FillFlowContainer // Listing > Lazer 2018.713.1
{
X = 2 * icon_margin + icon_size - 8,
Height = version_height,
Anchor = Anchor.BottomLeft,
Origin = Anchor.BottomLeft,
Direction = FillDirection.Horizontal,
Children = new Drawable[]
{
listing = new TextBadgePairListing(purple),
new Container() // without a container, moving the chevron wont work
{
Anchor = Anchor.CentreLeft,
Origin = Anchor.CentreLeft,
Margin = new MarginPadding()
{
Top = 10,
Left = 7,
Right = 9,
Bottom = 15,
},
Children = new Drawable[]
{
chevron = new SpriteIcon
{
Anchor = Anchor.Centre,
Origin = Anchor.Centre,
Size = new Vector2(7),
Colour = purple,
Icon = FontAwesome.fa_chevron_right,
Alpha = 0,
X = -200,
},
releaseStream = new TextBadgePairRelease(purple, "Lazer")
},
},
new Box // purple line
{
Colour = purple,
RelativeSizeAxes = Axes.X,
Height = 3,
Anchor = Anchor.BottomLeft,
Origin = Anchor.CentreLeft,
},
}
}
releaseStream = new TextBadgePairRelease(purple, "Lazer")
},
},
new Box // purple line
{
Colour = purple,
RelativeSizeAxes = Axes.X,
Height = 3,
Anchor = Anchor.BottomLeft,
Origin = Anchor.CentreLeft,
},
};
// is this a bad way to do this?
@ -184,6 +176,7 @@ namespace osu.Game.Overlays.Changelog
releaseStream.Deactivate();
chevron.MoveToX(-20, 100).FadeOut(100);
ChangeHeaderText("Listing");
OnListingActivated?.Invoke();
};
};
}
@ -201,7 +194,7 @@ namespace osu.Game.Overlays.Changelog
}
public void ActivateListing() => listing.Activate();
[BackgroundDependencyLoader]
private void load(TextureStore textures)
{

View File

@ -0,0 +1,81 @@
// Copyright (c) 2007-2018 ppy Pty Ltd <contact@ppy.sh>.
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
using OpenTK.Graphics;
using osu.Framework.Configuration;
using osu.Framework.Extensions.Color4Extensions;
using osu.Framework.Graphics;
using osu.Framework.Graphics.Containers;
using osu.Framework.Graphics.Shapes;
using osu.Game.Graphics;
using osu.Game.Overlays.Changelog.Streams;
using System;
namespace osu.Game.Overlays.Changelog
{
public class ChangelogStreams : Container
{
private const float containerHeight = 106.5f;
private const float containerTopBottomMargin = 20;
private const float containerSideMargin = 85;
public Bindable<ReleaseStreamInfo> SelectedRelease = new Bindable<ReleaseStreamInfo>();
private readonly StreamColour streamColour;
public readonly FillFlowContainer<StreamBadge> badgesContainer;
public ChangelogStreams()
{
streamColour = new StreamColour();
Height = containerHeight;
RelativeSizeAxes = Axes.X;
Children = new Drawable[]
{
new Box
{
RelativeSizeAxes = Axes.Both,
Size = new OpenTK.Vector2(1),
Colour = new Color4(32, 24, 35, 255),
},
badgesContainer = new FillFlowContainer<StreamBadge>
{
Direction = FillDirection.Horizontal,
RelativeSizeAxes = Axes.Both,
Margin = new MarginPadding()
{
Top = containerTopBottomMargin,
Bottom = containerTopBottomMargin,
Left = containerSideMargin,
Right = containerSideMargin,
},
Children = new[]
{
new StreamBadge(streamColour.Stable, "Stable", "20180626.1", 16370, true),
new StreamBadge(streamColour.Beta, "Beta", "20180626", 186),
new StreamBadge(streamColour.Lazer, "Lazer", "2018.713.1"),
},
},
};
badgesContainer.OnLoadComplete = d =>
{
foreach (StreamBadge streamBadge in badgesContainer.Children)
{
streamBadge.OnActivation = () =>
{
SelectedRelease.Value = new ReleaseStreamInfo()
{
DisplayVersion = streamBadge.DisplayVersion,
IsFeatured = streamBadge.IsFeatured,
Name = streamBadge.Name,
Users = streamBadge.Users,
};
foreach (StreamBadge item in badgesContainer.Children)
{
if (item.Name != streamBadge.Name) item.Deactivate();
}
};
}
};
}
}
}

View File

@ -8,11 +8,10 @@ namespace osu.Game.Overlays.Changelog.Header
{
public class LineBadge : Circle
{
private const float transition_duration = 100;
private const float uncollapsed_height = 10;
public float TransitionDuration = 100;
public float UncollapsedHeight;
public float CollapsedHeight;
public float TransitionDuration => transition_duration;
public float UncollapsedHeight => uncollapsed_height;
protected bool isCollapsed;
public bool IsCollapsed
{
@ -20,14 +19,17 @@ namespace osu.Game.Overlays.Changelog.Header
set
{
isCollapsed = value;
this.ResizeHeightTo(value ? 1 : uncollapsed_height, transition_duration);
this.ResizeHeightTo(value ? CollapsedHeight : UncollapsedHeight, TransitionDuration);
}
}
public LineBadge()
public LineBadge(bool startCollapsed = true, float collapsedHeight = 1, float uncollapsedHeight = 10)
{
Anchor = Anchor.BottomCentre;
Origin = Anchor.Centre;
CollapsedHeight = collapsedHeight;
UncollapsedHeight = uncollapsedHeight;
Height = startCollapsed ? CollapsedHeight : UncollapsedHeight;
// this margin prevents jumps when changing text's font weight
Margin = new MarginPadding()

View File

@ -14,10 +14,11 @@ namespace osu.Game.Overlays.Changelog.Header
{
protected SpriteText text;
protected LineBadge lineBadge;
protected bool startCollapsed;
public Action OnActivation;
public Action OnDeactivation;
public void SetTextColour(ColourInfo newColour, double duration = 0, Easing easing = Easing.None)
{
text.FadeColour(newColour, duration, easing);
@ -77,7 +78,7 @@ namespace osu.Game.Overlays.Changelog.Header
}, duration);
}
public TextBadgePair(ColourInfo badgeColour, string displayText = "Listing")
public TextBadgePair(ColourInfo badgeColour, string displayText = "Listing", bool startBadgeCollapsed = true)
{
AutoSizeAxes = Axes.X;
RelativeSizeAxes = Axes.Y;
@ -97,7 +98,7 @@ namespace osu.Game.Overlays.Changelog.Header
Right = 10,
}
},
lineBadge = new LineBadge
lineBadge = new LineBadge(startCollapsed)
{
Colour = badgeColour,
}

View File

@ -12,7 +12,7 @@ namespace osu.Game.Overlays.Changelog.Header
{
private ColourInfo badgeColour;
public TextBadgePairListing(ColourInfo badgeColour) : base(badgeColour, "Listing")
public TextBadgePairListing(ColourInfo badgeColour) : base(badgeColour, "Listing", false)
{
this.badgeColour = badgeColour;
text.Font = "Exo2.0-Bold";

View File

@ -0,0 +1,25 @@
// Copyright (c) 2007-2018 ppy Pty Ltd <contact@ppy.sh>.
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
using System;
using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;
using System.Linq;
using Newtonsoft.Json;
using osu.Game.Database;
using osu.Game.IO.Serialization;
using osu.Game.Rulesets;
namespace osu.Game.Overlays.Changelog
{
[Serializable]
public class ReleaseStreamInfo : IJsonSerializable
{
public string Name;
public string DisplayVersion;
public float Users;
public bool IsFeatured;
}
}

View File

@ -0,0 +1,128 @@
// Copyright (c) 2007-2018 ppy Pty Ltd <contact@ppy.sh>.
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
using OpenTK;
using OpenTK.Graphics;
using osu.Framework.Graphics;
using osu.Framework.Graphics.Colour;
using osu.Framework.Graphics.Containers;
using osu.Framework.Graphics.Shapes;
using osu.Framework.Graphics.Sprites;
using osu.Framework.Input;
using System;
namespace osu.Game.Overlays.Changelog.Streams
{
public class StreamBadge : Container
{
private const float badgeHeight = 56.5f;
private const float badgeWidth = 100;
private const float badgeTopBottomMargin = 5;
private const float transition_duration = 100;
public Action OnActivation;
private bool isActive;
private Header.LineBadge lineBadge;
public string Name { get; private set; }
public string DisplayVersion { get; private set; }
public bool IsFeatured { get; private set; }
public float Users { get; private set; }
public StreamBadge(ColourInfo colour, string streamName, string streamBuild, float onlineUsers = 0, bool isFeatured = false)
{
Name = streamName;
DisplayVersion = streamBuild;
IsFeatured = isFeatured;
Users = onlineUsers;
Height = badgeHeight;
Width = isFeatured ? badgeWidth * 2 : badgeWidth;
Margin = new MarginPadding(5);
isActive = true;
Children = new Drawable[]
{
new FillFlowContainer<SpriteText>
{
AutoSizeAxes = Axes.X,
RelativeSizeAxes = Axes.Y,
Direction = FillDirection.Vertical,
Children = new[]
{
new SpriteText
{
Text = streamName,
Font = @"Exo2.0-Bold",
TextSize = 16,
Margin = new MarginPadding
{
Top = 5,
}
},
new SpriteText
{
Text = streamBuild,
Font = @"Exo2.0-Light",
TextSize = 21,
},
new SpriteText
{
Text = onlineUsers > 0 ?
string.Join(" ", onlineUsers.ToString("N0"), "users online"):
null,
TextSize = 12,
Font = @"Exo2.0-Regular",
Colour = new Color4(203, 164, 218, 255),
},
}
},
lineBadge = new Header.LineBadge(false, 2, 4)
{
Anchor = Anchor.TopCentre,
Width = 1,
Colour = colour,
RelativeSizeAxes = Axes.X,
},
};
}
public void Activate(bool withoutHeaderUpdate = false)
{
isActive = true;
this.FadeIn(transition_duration);
lineBadge.IsCollapsed = false;
if (!withoutHeaderUpdate) OnActivation?.Invoke();
}
public void Deactivate()
{
isActive = false;
this.FadeTo(0.5f, transition_duration);
lineBadge.IsCollapsed = true;
}
protected override bool OnClick(InputState state)
{
Activate();
return base.OnClick(state);
}
protected override bool OnHover(InputState state)
{
this.FadeIn(transition_duration);
lineBadge.IsCollapsed = false;
return base.OnHover(state);
}
protected override void OnHoverLost(InputState state)
{
if (!isActive)
{
this.FadeTo(0.5f, transition_duration);
lineBadge.IsCollapsed = true;
}
base.OnHoverLost(state);
}
}
}

View File

@ -10,6 +10,7 @@ using osu.Framework.Graphics.Shapes;
using osu.Game.Graphics;
using osu.Game.Graphics.Containers;
using osu.Game.Overlays.Changelog;
using osu.Game.Overlays.Changelog.Streams;
namespace osu.Game.Overlays
{
@ -17,7 +18,8 @@ namespace osu.Game.Overlays
{
private readonly ScrollContainer scroll;
public ChangelogHeader header;
public readonly ChangelogHeader header;
public readonly ChangelogStreams streams;
protected Color4 purple = new Color4(191, 4, 255, 255);
@ -62,10 +64,26 @@ namespace osu.Game.Overlays
Children = new Drawable[]
{
header = new ChangelogHeader(),
streams = new ChangelogStreams(),
},
},
},
};
streams.SelectedRelease.ValueChanged += r =>
{
if (streams.SelectedRelease != null)
header.ShowReleaseStream(r.Name, string.Join(" ", r.Name, r.DisplayVersion));
};
streams.badgesContainer.OnLoadComplete += d =>
{
header.OnListingActivated += () =>
{
foreach (StreamBadge item in streams.badgesContainer.Children)
{
item.Activate(true);
}
};
};
}
// receive input outside our bounds so we can trigger a close event on ourselves.