diff --git a/appveyor.yml b/appveyor.yml index cc6dfb9c88..b26a895788 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -20,4 +20,4 @@ build: verbosity: minimal after_build: - cmd: inspectcode /o="inspectcodereport.xml" /caches-home="inspectcode" osu.sln - - cmd: NVika parsereport "inspectcodereport.xml" \ No newline at end of file + - cmd: NVika parsereport "inspectcodereport.xml" --treatwarningsaserrors \ No newline at end of file diff --git a/osu-framework b/osu-framework index 925bbe42ba..3ad1dd52ae 160000 --- a/osu-framework +++ b/osu-framework @@ -1 +1 @@ -Subproject commit 925bbe42bab95078b9d33189205b5b1b76bf8e01 +Subproject commit 3ad1dd52ae511b816fb928f70ef811ec605c5c18 diff --git a/osu.Desktop.VisualTests/Tests/TestCaseManiaHitObjects.cs b/osu.Desktop.VisualTests/Tests/TestCaseManiaHitObjects.cs index 3113b63db1..c66b0b4db4 100644 --- a/osu.Desktop.VisualTests/Tests/TestCaseManiaHitObjects.cs +++ b/osu.Desktop.VisualTests/Tests/TestCaseManiaHitObjects.cs @@ -40,7 +40,7 @@ namespace osu.Desktop.VisualTests.Tests { Name = "Timing section", RelativeSizeAxes = Axes.Both, - RelativeCoordinateSpace = new Vector2(1, 10000), + RelativeChildSize = new Vector2(1, 10000), Children = new[] { new DrawableNote(new Note { StartTime = 5000 }) { AccentColour = Color4.Red }, @@ -62,7 +62,7 @@ namespace osu.Desktop.VisualTests.Tests { Name = "Timing section", RelativeSizeAxes = Axes.Both, - RelativeCoordinateSpace = new Vector2(1, 10000), + RelativeChildSize = new Vector2(1, 10000), Children = new[] { new DrawableHoldNote(new HoldNote diff --git a/osu.Game.Rulesets.Mania/Objects/Drawables/DrawableHoldNote.cs b/osu.Game.Rulesets.Mania/Objects/Drawables/DrawableHoldNote.cs index 5d7f3314cd..1d751b0293 100644 --- a/osu.Game.Rulesets.Mania/Objects/Drawables/DrawableHoldNote.cs +++ b/osu.Game.Rulesets.Mania/Objects/Drawables/DrawableHoldNote.cs @@ -55,7 +55,7 @@ namespace osu.Game.Rulesets.Mania.Objects.Drawables tickContainer = new Container { RelativeSizeAxes = Axes.Both, - RelativeCoordinateSpace = new Vector2(1, (float)HitObject.Duration) + RelativeChildSize = new Vector2(1, (float)HitObject.Duration) }, head = new DrawableHeadNote(this, key) { diff --git a/osu.Game.Rulesets.Mania/Timing/ControlPointContainer.cs b/osu.Game.Rulesets.Mania/Timing/ControlPointContainer.cs index 0a8bc2d44a..2619ce150c 100644 --- a/osu.Game.Rulesets.Mania/Timing/ControlPointContainer.cs +++ b/osu.Game.Rulesets.Mania/Timing/ControlPointContainer.cs @@ -97,7 +97,7 @@ namespace osu.Game.Rulesets.Mania.Timing // Adjust our height to account for the speed changes Height = (float)(1000 / timingChange.BeatLength / timingChange.SpeedMultiplier); - RelativeCoordinateSpace = new Vector2(1, (float)parent.TimeSpan); + RelativeChildSize = new Vector2(1, (float)parent.TimeSpan); // Scroll the content content.Y = (float)(timingChange.Time - Time.Current); @@ -146,7 +146,7 @@ namespace osu.Game.Rulesets.Mania.Timing float height = Children.Select(child => child.Y + child.Height).Max(); Height = height; - RelativeCoordinateSpace = new Vector2(1, height); + RelativeChildSize = new Vector2(1, height); base.InvalidateFromChild(invalidation); } diff --git a/osu.Game/Graphics/Cursor/OsuTooltipContainer.cs b/osu.Game/Graphics/Cursor/OsuTooltipContainer.cs index 46addf5ac2..815d820a47 100644 --- a/osu.Game/Graphics/Cursor/OsuTooltipContainer.cs +++ b/osu.Game/Graphics/Cursor/OsuTooltipContainer.cs @@ -1,6 +1,7 @@ // Copyright (c) 2007-2017 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +using OpenTK; using OpenTK.Graphics; using osu.Framework.Allocation; using osu.Framework.Extensions.Color4Extensions; @@ -24,6 +25,7 @@ namespace osu.Game.Graphics.Cursor { private readonly Box background; private readonly OsuSpriteText text; + private bool instantMovement = true; public override string TooltipText { @@ -32,7 +34,7 @@ namespace osu.Game.Graphics.Cursor if (value == text.Text) return; text.Text = value; - if (Alpha > 0) + if (IsPresent) { AutoSizeDuration = 250; background.FlashColour(OsuColour.Gray(0.4f), 1000, EasingTypes.OutQuint); @@ -80,6 +82,7 @@ namespace osu.Game.Graphics.Cursor protected override void PopIn() { + instantMovement |= !IsPresent; FadeIn(500, EasingTypes.OutQuint); } @@ -88,6 +91,19 @@ namespace osu.Game.Graphics.Cursor using (BeginDelayedSequence(150)) FadeOut(500, EasingTypes.OutQuint); } + + public override void Move(Vector2 pos) + { + if (instantMovement) + { + Position = pos; + instantMovement = false; + } + else + { + MoveTo(pos, 200, EasingTypes.OutQuint); + } + } } } } diff --git a/osu.Game/Online/Chat/Channel.cs b/osu.Game/Online/Chat/Channel.cs index 93fd0a8956..01685cc7dc 100644 --- a/osu.Game/Online/Chat/Channel.cs +++ b/osu.Game/Online/Chat/Channel.cs @@ -5,6 +5,7 @@ using System; using System.Collections.Generic; using System.Linq; using Newtonsoft.Json; +using osu.Framework.Configuration; using osu.Framework.Lists; namespace osu.Game.Online.Chat @@ -25,7 +26,7 @@ namespace osu.Game.Online.Chat public readonly SortedList Messages = new SortedList(Comparer.Default); - //internal bool Joined; + public Bindable Joined = new Bindable(); public bool ReadOnly => Name != "#lazer"; diff --git a/osu.Game/Overlays/Chat/ChannelListItem.cs b/osu.Game/Overlays/Chat/ChannelListItem.cs new file mode 100644 index 0000000000..9aa11cdd4f --- /dev/null +++ b/osu.Game/Overlays/Chat/ChannelListItem.cs @@ -0,0 +1,188 @@ +// Copyright (c) 2007-2017 ppy Pty Ltd . +// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE + +using System; +using OpenTK; +using OpenTK.Graphics; +using osu.Framework.Allocation; +using osu.Framework.Configuration; +using osu.Framework.Graphics; +using osu.Framework.Graphics.Containers; +using osu.Framework.Input; +using osu.Game.Graphics; +using osu.Game.Graphics.Sprites; +using osu.Game.Online.Chat; + +namespace osu.Game.Overlays.Chat +{ + public class ChannelListItem : ClickableContainer, IFilterable + { + private const float width_padding = 5; + private const float channel_width = 150; + private const float text_size = 15; + private const float transition_duration = 100; + + private readonly Channel channel; + + private readonly Bindable joinedBind = new Bindable(); + private readonly OsuSpriteText name; + private readonly OsuSpriteText topic; + private readonly TextAwesome joinedCheckmark; + + private Color4 joinedColour; + private Color4 topicColour; + private Color4 hoverColour; + + public string[] FilterTerms => new[] { channel.Name }; + public bool MatchingFilter + { + set + { + FadeTo(value ? 1f : 0f, 100); + } + } + + public Action OnRequestJoin; + public Action OnRequestLeave; + + public ChannelListItem(Channel channel) + { + this.channel = channel; + + RelativeSizeAxes = Axes.X; + AutoSizeAxes = Axes.Y; + + Action = () => { (channel.Joined ? OnRequestLeave : OnRequestJoin)?.Invoke(channel); }; + + Children = new Drawable[] + { + new FillFlowContainer + { + RelativeSizeAxes = Axes.X, + AutoSizeAxes = Axes.Y, + Direction = FillDirection.Horizontal, + Children = new Drawable[] + { + new Container + { + Children = new[] + { + joinedCheckmark = new TextAwesome + { + Anchor = Anchor.TopRight, + Origin = Anchor.TopRight, + Icon = FontAwesome.fa_check_circle, + TextSize = text_size, + Shadow = false, + Margin = new MarginPadding { Right = 10f }, + Alpha = 0f, + }, + }, + }, + new Container + { + Width = channel_width, + AutoSizeAxes = Axes.Y, + Children = new[] + { + name = new OsuSpriteText + { + Text = channel.ToString(), + TextSize = text_size, + Font = @"Exo2.0-Bold", + Shadow = false, + }, + }, + }, + new Container + { + RelativeSizeAxes = Axes.X, + Width = 0.7f, + AutoSizeAxes = Axes.Y, + Margin = new MarginPadding { Left = width_padding }, + Children = new[] + { + topic = new OsuSpriteText + { + Text = channel.Topic, + TextSize = text_size, + Font = @"Exo2.0-SemiBold", + Shadow = false, + Alpha = 0.8f, + }, + }, + }, + new FillFlowContainer + { + AutoSizeAxes = Axes.Both, + Direction = FillDirection.Horizontal, + Margin = new MarginPadding { Left = width_padding }, + Spacing = new Vector2(3f, 0f), + Children = new Drawable[] + { + new TextAwesome + { + Icon = FontAwesome.fa_user, + TextSize = text_size - 2, + Shadow = false, + Margin = new MarginPadding { Top = 1 }, + }, + new OsuSpriteText + { + Text = @"0", + TextSize = text_size, + Font = @"Exo2.0-SemiBold", + Shadow = false, + }, + }, + }, + }, + }, + }; + } + + [BackgroundDependencyLoader] + private void load(OsuColour colours) + { + topicColour = colours.Gray9; + joinedColour = colours.Blue; + hoverColour = colours.Yellow; + + joinedBind.ValueChanged += updateColour; + joinedBind.BindTo(channel.Joined); + } + + protected override bool OnHover(InputState state) + { + if (!channel.Joined.Value) + name.FadeColour(hoverColour, 50, EasingTypes.OutQuint); + + return base.OnHover(state); + } + + protected override void OnHoverLost(InputState state) + { + if (!channel.Joined.Value) + name.FadeColour(Color4.White, transition_duration); + } + + private void updateColour(bool joined) + { + if (joined) + { + name.FadeColour(Color4.White, transition_duration); + joinedCheckmark.FadeTo(1f, transition_duration); + topic.FadeTo(0.8f, transition_duration); + topic.FadeColour(Color4.White, transition_duration); + FadeColour(joinedColour, transition_duration); + } + else + { + joinedCheckmark.FadeTo(0f, transition_duration); + topic.FadeTo(1f, transition_duration); + topic.FadeColour(topicColour, transition_duration); + FadeColour(Color4.White, transition_duration); + } + } + } +} diff --git a/osu.Game/Overlays/Chat/ChannelSection.cs b/osu.Game/Overlays/Chat/ChannelSection.cs new file mode 100644 index 0000000000..f12ec53605 --- /dev/null +++ b/osu.Game/Overlays/Chat/ChannelSection.cs @@ -0,0 +1,63 @@ +// Copyright (c) 2007-2017 ppy Pty Ltd . +// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE + +using System.Collections.Generic; +using System.Linq; +using OpenTK; +using osu.Framework.Graphics; +using osu.Framework.Graphics.Containers; +using osu.Game.Graphics.Sprites; +using osu.Game.Online.Chat; + +namespace osu.Game.Overlays.Chat +{ + public class ChannelSection : Container, IHasFilterableChildren + { + private readonly OsuSpriteText header; + + public readonly FillFlowContainer ChannelFlow; + + public IEnumerable FilterableChildren => ChannelFlow.Children; + public string[] FilterTerms => new[] { Header }; + public bool MatchingFilter + { + set + { + FadeTo(value ? 1f : 0f, 100); + } + } + + public string Header + { + get { return header.Text; } + set { header.Text = value.ToUpper(); } + } + + public IEnumerable Channels + { + set { ChannelFlow.Children = value.Select(c => new ChannelListItem(c)); } + } + + public ChannelSection() + { + RelativeSizeAxes = Axes.X; + AutoSizeAxes = Axes.Y; + + Children = new Drawable[] + { + header = new OsuSpriteText + { + TextSize = 15, + Font = @"Exo2.0-Bold", + }, + ChannelFlow = new FillFlowContainer + { + RelativeSizeAxes = Axes.X, + AutoSizeAxes = Axes.Y, + Margin = new MarginPadding { Top = 25 }, + Spacing = new Vector2(0f, 5f), + }, + }; + } + } +} diff --git a/osu.Game/Overlays/Chat/ChannelSelectionOverlay.cs b/osu.Game/Overlays/Chat/ChannelSelectionOverlay.cs new file mode 100644 index 0000000000..cd736a5fe9 --- /dev/null +++ b/osu.Game/Overlays/Chat/ChannelSelectionOverlay.cs @@ -0,0 +1,184 @@ +// Copyright (c) 2007-2017 ppy Pty Ltd . +// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE + +using System; +using System.Collections.Generic; +using OpenTK; +using OpenTK.Graphics; +using osu.Framework.Allocation; +using osu.Framework.Extensions.Color4Extensions; +using osu.Framework.Graphics; +using osu.Framework.Graphics.Containers; +using osu.Framework.Graphics.Sprites; +using osu.Framework.Input; +using osu.Game.Graphics; +using osu.Game.Graphics.Backgrounds; +using osu.Game.Graphics.Sprites; +using osu.Game.Graphics.UserInterface; +using osu.Game.Online.Chat; + +namespace osu.Game.Overlays.Chat +{ + public class ChannelSelectionOverlay : FocusedOverlayContainer + { + public static readonly float WIDTH_PADDING = 170; + + private const float transition_duration = 500; + + private readonly Box bg; + private readonly Triangles triangles; + private readonly Box headerBg; + private readonly SearchTextBox search; + private readonly SearchContainer sectionsFlow; + + public Action OnRequestJoin; + public Action OnRequestLeave; + + public IEnumerable Sections + { + set + { + sectionsFlow.Children = value; + + foreach (ChannelSection s in sectionsFlow.Children) + { + foreach (ChannelListItem c in s.ChannelFlow.Children) + { + c.OnRequestJoin = channel => { OnRequestJoin?.Invoke(channel); }; + c.OnRequestLeave = channel => { OnRequestLeave?.Invoke(channel); }; + } + } + } + } + + public ChannelSelectionOverlay() + { + RelativeSizeAxes = Axes.X; + + Children = new Drawable[] + { + new Container + { + RelativeSizeAxes = Axes.Both, + Masking = true, + Children = new Drawable[] + { + bg = new Box + { + RelativeSizeAxes = Axes.Both, + }, + triangles = new Triangles + { + RelativeSizeAxes = Axes.Both, + TriangleScale = 5, + }, + }, + }, + new Container + { + RelativeSizeAxes = Axes.Both, + Padding = new MarginPadding { Top = 85, Right = WIDTH_PADDING }, + Children = new[] + { + new ScrollContainer + { + RelativeSizeAxes = Axes.Both, + Children = new[] + { + sectionsFlow = new SearchContainer + { + RelativeSizeAxes = Axes.X, + AutoSizeAxes = Axes.Y, + Direction = FillDirection.Vertical, + LayoutDuration = 200, + LayoutEasing = EasingTypes.OutQuint, + Spacing = new Vector2(0f, 20f), + Padding = new MarginPadding { Vertical = 20, Left = WIDTH_PADDING }, + }, + }, + }, + }, + }, + new Container + { + RelativeSizeAxes = Axes.X, + AutoSizeAxes = Axes.Y, + Children = new Drawable[] + { + headerBg = new Box + { + RelativeSizeAxes = Axes.Both, + }, + new FillFlowContainer + { + RelativeSizeAxes = Axes.X, + AutoSizeAxes = Axes.Y, + Direction = FillDirection.Vertical, + Spacing = new Vector2(0f, 10f), + Padding = new MarginPadding { Top = 10f, Bottom = 10f, Left = WIDTH_PADDING, Right = WIDTH_PADDING }, + Children = new Drawable[] + { + new OsuSpriteText + { + Text = @"Chat Channels", + TextSize = 20, + Shadow = false, + }, + search = new HeaderSearchTextBox + { + RelativeSizeAxes = Axes.X, + PlaceholderText = @"Search", + Exit = Hide, + }, + }, + }, + }, + }, + }; + + search.Current.ValueChanged += newValue => sectionsFlow.SearchTerm = newValue; + } + + [BackgroundDependencyLoader] + private void load(OsuColour colours) + { + bg.Colour = colours.Gray3; + triangles.ColourDark = colours.Gray3; + triangles.ColourLight = OsuColour.FromHex(@"353535"); + + headerBg.Colour = colours.Gray2.Opacity(0.75f); + } + + protected override void OnFocus(InputState state) + { + InputManager.ChangeFocus(search); + base.OnFocus(state); + } + + protected override void PopIn() + { + if (Alpha == 0) MoveToY(DrawHeight); + + FadeIn(transition_duration, EasingTypes.OutQuint); + MoveToY(0, transition_duration, EasingTypes.OutQuint); + + search.HoldFocus = true; + base.PopIn(); + } + + protected override void PopOut() + { + FadeOut(transition_duration, EasingTypes.InSine); + MoveToY(DrawHeight, transition_duration, EasingTypes.InSine); + + search.HoldFocus = false; + base.PopOut(); + } + + private class HeaderSearchTextBox : SearchTextBox + { + protected override Color4 BackgroundFocused => Color4.Black.Opacity(0.2f); + protected override Color4 BackgroundUnfocused => Color4.Black.Opacity(0.2f); + } + } +} diff --git a/osu.Game/Overlays/Chat/ChatTabControl.cs b/osu.Game/Overlays/Chat/ChatTabControl.cs index a281cff7db..23ddff9381 100644 --- a/osu.Game/Overlays/Chat/ChatTabControl.cs +++ b/osu.Game/Overlays/Chat/ChatTabControl.cs @@ -207,11 +207,15 @@ namespace osu.Game.Overlays.Chat { public override bool Active { - get { return base.Active; } + get { return false; } + // ReSharper disable once ValueParameterNotUsed set { - activeBindable.Value = value; - base.Active = value; + // we basically never want this tab to become active. + // this allows us to become a "toggle" tab. + // is a bit hacky, to say the least. + activeBindable.Value = !activeBindable.Value; + base.Active = false; } } @@ -220,6 +224,9 @@ namespace osu.Game.Overlays.Chat public ChannelSelectorTabItem(Channel value, Bindable active) : base(value) { activeBindable = active; + activeBindable.ValueChanged += v => selectorUpdateState(); + + Depth = float.MaxValue; Width = 45; @@ -235,6 +242,26 @@ namespace osu.Game.Overlays.Chat backgroundInactive = colour.Gray2; backgroundActive = colour.Gray3; } + + protected override void LoadComplete() + { + base.LoadComplete(); + + selectorUpdateState(); + } + + protected override void OnHoverLost(InputState state) + { + selectorUpdateState(); + } + + private void selectorUpdateState() + { + if (activeBindable.Value) + fadeActive(); + else + fadeInactive(); + } } } } diff --git a/osu.Game/Overlays/ChatOverlay.cs b/osu.Game/Overlays/ChatOverlay.cs index f81c0ea922..c32199f881 100644 --- a/osu.Game/Overlays/ChatOverlay.cs +++ b/osu.Game/Overlays/ChatOverlay.cs @@ -29,6 +29,7 @@ namespace osu.Game.Overlays public class ChatOverlay : FocusedOverlayContainer, IOnlineComponent { private const float textbox_height = 60; + private const float channel_selection_min_height = 0.3f; private ScheduledDelegate messageRequest; @@ -48,16 +49,21 @@ namespace osu.Game.Overlays private readonly ChatTabControl channelTabs; + private readonly Container chatContainer; private readonly Box chatBackground; private readonly Box tabBackground; private Bindable chatHeight; + private readonly Container channelSelectionContainer; + private readonly ChannelSelectionOverlay channelSelection; + + protected override bool InternalContains(Vector2 screenSpacePos) => chatContainer.Contains(screenSpacePos) || channelSelection.State == Visibility.Visible && channelSelection.Contains(screenSpacePos); + public ChatOverlay() { RelativeSizeAxes = Axes.Both; RelativePositionAxes = Axes.Both; - Size = new Vector2(1, DEFAULT_HEIGHT); Anchor = Anchor.BottomLeft; Origin = Anchor.BottomLeft; @@ -65,74 +71,120 @@ namespace osu.Game.Overlays Children = new Drawable[] { - new Container + channelSelectionContainer = new Container { - Name = @"chat area", RelativeSizeAxes = Axes.Both, - Padding = new MarginPadding { Top = TAB_AREA_HEIGHT }, - Children = new Drawable[] + Height = 1f - DEFAULT_HEIGHT, + Masking = true, + Children = new[] { - chatBackground = new Box + channelSelection = new ChannelSelectionOverlay { RelativeSizeAxes = Axes.Both, }, - currentChannelContainer = new Container + }, + }, + chatContainer = new Container + { + Name = @"chat container", + Anchor = Anchor.BottomLeft, + Origin = Anchor.BottomLeft, + RelativeSizeAxes = Axes.Both, + Height = DEFAULT_HEIGHT, + Children = new[] + { + new Container { + Name = @"chat area", RelativeSizeAxes = Axes.Both, - Padding = new MarginPadding + Padding = new MarginPadding { Top = TAB_AREA_HEIGHT }, + Children = new Drawable[] { - Bottom = textbox_height + padding - }, + chatBackground = new Box + { + RelativeSizeAxes = Axes.Both, + }, + currentChannelContainer = new Container + { + RelativeSizeAxes = Axes.Both, + Padding = new MarginPadding + { + Bottom = textbox_height + padding + }, + }, + new Container + { + Anchor = Anchor.BottomLeft, + Origin = Anchor.BottomLeft, + RelativeSizeAxes = Axes.X, + Height = textbox_height, + Padding = new MarginPadding + { + Top = padding * 2, + Bottom = padding * 2, + Left = ChatLine.LEFT_PADDING + padding * 2, + Right = padding * 2, + }, + Children = new Drawable[] + { + inputTextBox = new FocusedTextBox + { + RelativeSizeAxes = Axes.Both, + Height = 1, + PlaceholderText = "type your message", + Exit = () => State = Visibility.Hidden, + OnCommit = postMessage, + ReleaseFocusOnCommit = false, + HoldFocus = true, + } + } + } + } }, new Container { - Anchor = Anchor.BottomLeft, - Origin = Anchor.BottomLeft, + Name = @"tabs area", RelativeSizeAxes = Axes.X, - Height = textbox_height, - Padding = new MarginPadding - { - Top = padding * 2, - Bottom = padding * 2, - Left = ChatLine.LEFT_PADDING + padding * 2, - Right = padding * 2, - }, + Height = TAB_AREA_HEIGHT, Children = new Drawable[] { - inputTextBox = new FocusedTextBox + tabBackground = new Box { RelativeSizeAxes = Axes.Both, - Height = 1, - PlaceholderText = "type your message", - Exit = () => State = Visibility.Hidden, - OnCommit = postMessage, - HoldFocus = true, - } + Colour = Color4.Black, + }, + channelTabs = new ChatTabControl + { + RelativeSizeAxes = Axes.Both, + }, } - } - } - }, - new Container - { - Name = @"tabs area", - RelativeSizeAxes = Axes.X, - Height = TAB_AREA_HEIGHT, - Children = new Drawable[] - { - tabBackground = new Box - { - RelativeSizeAxes = Axes.Both, - Colour = Color4.Black, }, - channelTabs = new ChatTabControl - { - RelativeSizeAxes = Axes.Both, - }, - } + }, }, }; channelTabs.Current.ValueChanged += newChannel => CurrentChannel = newChannel; + channelTabs.ChannelSelectorActive.ValueChanged += value => channelSelection.State = value ? Visibility.Visible : Visibility.Hidden; + channelSelection.StateChanged += (overlay, state) => + { + channelTabs.ChannelSelectorActive.Value = state == Visibility.Visible; + + if (state == Visibility.Visible) + { + inputTextBox.HoldFocus = false; + if (1f - chatHeight.Value < channel_selection_min_height) + { + chatContainer.ResizeHeightTo(1f - channel_selection_min_height, 800, EasingTypes.OutQuint); + channelSelectionContainer.ResizeHeightTo(channel_selection_min_height, 800, EasingTypes.OutQuint); + channelSelection.Show(); + chatHeight.Value = 1f - channel_selection_min_height; + } + } + else + { + inputTextBox.HoldFocus = true; + } + }; } private double startDragChatHeight; @@ -205,8 +257,9 @@ namespace osu.Game.Overlays chatHeight = config.GetBindable(OsuSetting.ChatDisplayHeight); chatHeight.ValueChanged += h => { - Height = (float)h; - tabBackground.FadeTo(Height == 1 ? 1 : 0.8f, 200); + chatContainer.Height = (float)h; + channelSelectionContainer.Height = 1f - (float)h; + tabBackground.FadeTo(h == 1 ? 1 : 0.8f, 200); }; chatHeight.TriggerChange(); @@ -243,6 +296,16 @@ namespace osu.Game.Overlays addChannel(channels.Find(c => c.Name == @"#lazer")); addChannel(channels.Find(c => c.Name == @"#osu")); addChannel(channels.Find(c => c.Name == @"#lobby")); + + channelSelection.OnRequestJoin = addChannel; + channelSelection.Sections = new[] + { + new ChannelSection + { + Header = "All Channels", + Channels = channels, + }, + }; }); messageRequest = Scheduler.AddDelayed(fetchNewMessages, 1000, true); @@ -262,9 +325,7 @@ namespace osu.Game.Overlays set { - if (currentChannel == value) return; - - if (channelTabs.ChannelSelectorActive) return; + if (currentChannel == value || value == null) return; currentChannel = value; @@ -316,6 +377,8 @@ namespace osu.Game.Overlays if (CurrentChannel == null) CurrentChannel = channel; + + channel.Joined.Value = true; } private void fetchInitialMessages(Channel channel) diff --git a/osu.Game/Overlays/Music/PlaylistItem.cs b/osu.Game/Overlays/Music/PlaylistItem.cs index 0618f96cac..789e45adfc 100644 --- a/osu.Game/Overlays/Music/PlaylistItem.cs +++ b/osu.Game/Overlays/Music/PlaylistItem.cs @@ -22,7 +22,7 @@ namespace osu.Game.Overlays.Music private Color4 artistColour; private TextAwesome handle; - private Paragraph text; + private TextFlowContainer text; private IEnumerable titleSprites; private UnicodeBindableString titleBind; private UnicodeBindableString artistBind; @@ -77,7 +77,7 @@ namespace osu.Game.Overlays.Music Margin = new MarginPadding { Left = 5 }, Padding = new MarginPadding { Top = 2 }, }, - text = new Paragraph + text = new TextFlowContainer { RelativeSizeAxes = Axes.X, AutoSizeAxes = Axes.Y, diff --git a/osu.Game/Overlays/Settings/Sections/Input/MouseSettings.cs b/osu.Game/Overlays/Settings/Sections/Input/MouseSettings.cs index 9cf5c42319..311fa072c6 100644 --- a/osu.Game/Overlays/Settings/Sections/Input/MouseSettings.cs +++ b/osu.Game/Overlays/Settings/Sections/Input/MouseSettings.cs @@ -14,14 +14,31 @@ namespace osu.Game.Overlays.Settings.Sections.Input { protected override string Header => "Mouse"; + private readonly BindableBool rawInputToggle = new BindableBool(); + private Bindable activeInputHandlers; + private SensitivitySetting sensitivity; + [BackgroundDependencyLoader] private void load(OsuConfigManager osuConfig, FrameworkConfigManager config) { + activeInputHandlers = config.GetBindable(FrameworkSetting.ActiveInputHandlers); + rawInputToggle.Value = activeInputHandlers.Value.Contains("Raw"); + Children = new Drawable[] { + new SettingsCheckbox + { + LabelText = "Raw Input", + Bindable = rawInputToggle + }, + sensitivity = new SensitivitySetting + { + LabelText = "Cursor Sensitivity", + Bindable = config.GetBindable(FrameworkSetting.CursorSensitivity) + }, new SettingsEnumDropdown { - LabelText = "Confine mouse cursor", + LabelText = "Confine mouse cursor to window", Bindable = config.GetBindable(FrameworkSetting.ConfineMouseMode), }, new SettingsCheckbox @@ -35,11 +52,82 @@ namespace osu.Game.Overlays.Settings.Sections.Input Bindable = osuConfig.GetBindable(OsuSetting.MouseDisableButtons) }, }; + + rawInputToggle.ValueChanged += enabled => + { + // this is temporary until we support per-handler settings. + const string raw_mouse_handler = @"OpenTKRawMouseHandler"; + const string standard_mouse_handler = @"OpenTKMouseHandler"; + + activeInputHandlers.Value = enabled ? + activeInputHandlers.Value.Replace(standard_mouse_handler, raw_mouse_handler) : + activeInputHandlers.Value.Replace(raw_mouse_handler, standard_mouse_handler); + + sensitivity.Bindable.Disabled = !enabled; + }; + + rawInputToggle.TriggerChange(); + } + + private class SensitivitySetting : SettingsSlider + { + public override Bindable Bindable + { + get { return ((SensitivitySlider)Control).Sensitivity; } + + set + { + BindableDouble doubleValue = (BindableDouble)value; + + // create a second layer of bindable so we can only handle state changes when not being dragged. + ((SensitivitySlider)Control).Sensitivity = doubleValue; + + // this bindable will still act as the "interactive" bindable displayed during a drag. + base.Bindable = new BindableDouble(doubleValue.Value) + { + MinValue = doubleValue.MinValue, + MaxValue = doubleValue.MaxValue + }; + + // one-way binding to update the sliderbar with changes from external actions. + doubleValue.DisabledChanged += disabled => base.Bindable.Disabled = disabled; + doubleValue.ValueChanged += newValue => base.Bindable.Value = newValue; + } + } } private class SensitivitySlider : OsuSliderBar { - public override string TooltipText => Current.Value.ToString(@"0.##x"); + public Bindable Sensitivity; + + public SensitivitySlider() + { + KeyboardStep = 0.01f; + + Current.ValueChanged += newValue => + { + if (!isDragging && Sensitivity != null) + Sensitivity.Value = newValue; + }; + } + + private bool isDragging; + + protected override bool OnDragStart(InputState state) + { + isDragging = true; + return base.OnDragStart(state); + } + + protected override bool OnDragEnd(InputState state) + { + isDragging = false; + Current.TriggerChange(); + + return base.OnDragEnd(state); + } + + public override string TooltipText => Current.Disabled ? "Enable raw input to adjust sensitivity" : Current.Value.ToString(@"0.##x"); } } -} +} \ No newline at end of file diff --git a/osu.Game/Overlays/Settings/SettingsItem.cs b/osu.Game/Overlays/Settings/SettingsItem.cs index 7cddefb755..14b67dd6df 100644 --- a/osu.Game/Overlays/Settings/SettingsItem.cs +++ b/osu.Game/Overlays/Settings/SettingsItem.cs @@ -39,7 +39,7 @@ namespace osu.Game.Overlays.Settings // hold a reference to the provided bindable so we don't have to in every settings section. private Bindable bindable; - public Bindable Bindable + public virtual Bindable Bindable { get { diff --git a/osu.Game/Screens/Play/HUDOverlay.cs b/osu.Game/Screens/Play/HUDOverlay.cs index 616b28fa99..3248495b61 100644 --- a/osu.Game/Screens/Play/HUDOverlay.cs +++ b/osu.Game/Screens/Play/HUDOverlay.cs @@ -7,21 +7,24 @@ using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Framework.Input; using osu.Game.Configuration; +using osu.Game.Graphics; using osu.Game.Graphics.UserInterface; using osu.Game.Overlays; using osu.Game.Overlays.Notifications; using osu.Game.Rulesets.Scoring; using osu.Game.Rulesets.UI; using osu.Game.Screens.Play.HUD; +using OpenTK; using OpenTK.Input; namespace osu.Game.Screens.Play { - public abstract class HUDOverlay : Container + public class HUDOverlay : Container { private const int duration = 100; private readonly Container content; + public readonly KeyCounterCollection KeyCounter; public readonly RollingCounter ComboCounter; public readonly ScoreCounter ScoreCounter; @@ -35,16 +38,7 @@ namespace osu.Game.Screens.Play private static bool hasShownNotificationOnce; - protected abstract KeyCounterCollection CreateKeyCounter(); - protected abstract RollingCounter CreateComboCounter(); - protected abstract RollingCounter CreateAccuracyCounter(); - protected abstract ScoreCounter CreateScoreCounter(); - protected abstract HealthDisplay CreateHealthDisplay(); - protected abstract SongProgress CreateProgress(); - protected abstract ModDisplay CreateModsContainer(); - //protected abstract ReplaySettingsOverlay CreateReplaySettingsOverlay(); - - protected HUDOverlay() + public HUDOverlay() { RelativeSizeAxes = Axes.Both; @@ -67,7 +61,7 @@ namespace osu.Game.Screens.Play } [BackgroundDependencyLoader(true)] - private void load(OsuConfigManager config, NotificationManager notificationManager) + private void load(OsuConfigManager config, NotificationManager notificationManager, OsuColour colours) { showHud = config.GetBindable(OsuSetting.ShowInterface); showHud.ValueChanged += hudVisibility => content.FadeTo(hudVisibility ? 1 : 0, duration); @@ -82,14 +76,18 @@ namespace osu.Game.Screens.Play Text = @"The score overlay is currently disabled. You can toggle this by pressing Shift+Tab." }); } - } - public virtual void BindProcessor(ScoreProcessor processor) - { - ScoreCounter?.Current.BindTo(processor.TotalScore); - AccuracyCounter?.Current.BindTo(processor.Accuracy); - ComboCounter?.Current.BindTo(processor.Combo); - HealthDisplay?.Current.BindTo(processor.Health); + // todo: the stuff below should probably not be in this base implementation, but in each individual class. + ComboCounter.AccentColour = colours.BlueLighter; + AccuracyCounter.AccentColour = colours.BlueLighter; + ScoreCounter.AccentColour = colours.BlueLighter; + + var shd = HealthDisplay as StandardHealthDisplay; + if (shd != null) + { + shd.AccentColour = colours.BlueLighter; + shd.GlowColour = colours.BlueDarker; + } } public virtual void BindHitRenderer(HitRenderer hitRenderer) @@ -122,5 +120,82 @@ namespace osu.Game.Screens.Play return base.OnKeyDown(state, args); } + + protected virtual RollingCounter CreateAccuracyCounter() => new PercentageCounter + { + Anchor = Anchor.TopCentre, + Origin = Anchor.TopRight, + Position = new Vector2(0, 35), + TextSize = 20, + Margin = new MarginPadding { Right = 140 }, + }; + + protected virtual RollingCounter CreateComboCounter() => new SimpleComboCounter + { + Anchor = Anchor.TopCentre, + Origin = Anchor.TopLeft, + Position = new Vector2(0, 35), + Margin = new MarginPadding { Left = 140 }, + TextSize = 20, + }; + + protected virtual HealthDisplay CreateHealthDisplay() => new StandardHealthDisplay + { + Size = new Vector2(1, 5), + RelativeSizeAxes = Axes.X, + Margin = new MarginPadding { Top = 20 } + }; + + protected virtual KeyCounterCollection CreateKeyCounter() => new KeyCounterCollection + { + IsCounting = true, + FadeTime = 50, + Anchor = Anchor.BottomRight, + Origin = Anchor.BottomRight, + Margin = new MarginPadding(10), + Y = -TwoLayerButton.SIZE_RETRACTED.Y, + }; + + protected virtual ScoreCounter CreateScoreCounter() => new ScoreCounter(6) + { + Anchor = Anchor.TopCentre, + Origin = Anchor.TopCentre, + TextSize = 40, + Position = new Vector2(0, 30), + }; + + protected virtual SongProgress CreateProgress() => new SongProgress + { + Anchor = Anchor.BottomLeft, + Origin = Anchor.BottomLeft, + RelativeSizeAxes = Axes.X, + }; + + protected virtual ModDisplay CreateModsContainer() => new ModDisplay + { + Anchor = Anchor.TopRight, + Origin = Anchor.TopRight, + AutoSizeAxes = Axes.Both, + Margin = new MarginPadding { Top = 20, Right = 10 }, + }; + + //protected virtual ReplaySettingsOverlay CreateReplaySettingsOverlay() => new ReplaySettingsOverlay + //{ + // Anchor = Anchor.TopRight, + // Origin = Anchor.TopRight, + // Margin = new MarginPadding { Top = 100, Right = 10 }, + //}; + + public virtual void BindProcessor(ScoreProcessor processor) + { + ScoreCounter?.Current.BindTo(processor.TotalScore); + AccuracyCounter?.Current.BindTo(processor.Accuracy); + ComboCounter?.Current.BindTo(processor.Combo); + HealthDisplay?.Current.BindTo(processor.Health); + + var shd = HealthDisplay as StandardHealthDisplay; + if (shd != null) + processor.NewJudgement += shd.Flash; + } } } diff --git a/osu.Game/Screens/Play/Player.cs b/osu.Game/Screens/Play/Player.cs index 707d026e2b..d4b8445ed9 100644 --- a/osu.Game/Screens/Play/Player.cs +++ b/osu.Game/Screens/Play/Player.cs @@ -170,7 +170,7 @@ namespace osu.Game.Screens.Play HitRenderer, } }, - hudOverlay = new StandardHUDOverlay + hudOverlay = new HUDOverlay { Anchor = Anchor.Centre, Origin = Anchor.Centre diff --git a/osu.Game/Screens/Play/StandardHUDOverlay.cs b/osu.Game/Screens/Play/StandardHUDOverlay.cs deleted file mode 100644 index 50add4a19b..0000000000 --- a/osu.Game/Screens/Play/StandardHUDOverlay.cs +++ /dev/null @@ -1,105 +0,0 @@ -// Copyright (c) 2007-2017 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE - -using osu.Framework.Allocation; -using osu.Framework.Graphics; -using osu.Game.Graphics; -using osu.Game.Graphics.UserInterface; -using osu.Game.Rulesets.Scoring; -using osu.Game.Screens.Play.HUD; -using OpenTK; - -namespace osu.Game.Screens.Play -{ - public class StandardHUDOverlay : HUDOverlay - { - protected override RollingCounter CreateAccuracyCounter() => new PercentageCounter - { - Anchor = Anchor.TopCentre, - Origin = Anchor.TopRight, - Position = new Vector2(0, 35), - TextSize = 20, - Margin = new MarginPadding { Right = 140 }, - }; - - protected override RollingCounter CreateComboCounter() => new SimpleComboCounter - { - Anchor = Anchor.TopCentre, - Origin = Anchor.TopLeft, - Position = new Vector2(0, 35), - Margin = new MarginPadding { Left = 140 }, - TextSize = 20, - }; - - protected override HealthDisplay CreateHealthDisplay() => new StandardHealthDisplay - { - Size = new Vector2(1, 5), - RelativeSizeAxes = Axes.X, - Margin = new MarginPadding { Top = 20 } - }; - - protected override KeyCounterCollection CreateKeyCounter() => new KeyCounterCollection - { - IsCounting = true, - FadeTime = 50, - Anchor = Anchor.BottomRight, - Origin = Anchor.BottomRight, - Margin = new MarginPadding(10), - Y = -TwoLayerButton.SIZE_RETRACTED.Y, - }; - - protected override ScoreCounter CreateScoreCounter() => new ScoreCounter(6) - { - Anchor = Anchor.TopCentre, - Origin = Anchor.TopCentre, - TextSize = 40, - Position = new Vector2(0, 30), - }; - - protected override SongProgress CreateProgress() => new SongProgress - { - Anchor = Anchor.BottomLeft, - Origin = Anchor.BottomLeft, - RelativeSizeAxes = Axes.X, - }; - - protected override ModDisplay CreateModsContainer() => new ModDisplay - { - Anchor = Anchor.TopRight, - Origin = Anchor.TopRight, - AutoSizeAxes = Axes.Both, - Margin = new MarginPadding { Top = 20, Right = 10 }, - }; - - //protected override ReplaySettingsOverlay CreateReplaySettingsOverlay() => new ReplaySettingsOverlay - //{ - // Anchor = Anchor.TopRight, - // Origin = Anchor.TopRight, - // Margin = new MarginPadding { Top = 100, Right = 10 }, - //}; - - [BackgroundDependencyLoader] - private void load(OsuColour colours) - { - ComboCounter.AccentColour = colours.BlueLighter; - AccuracyCounter.AccentColour = colours.BlueLighter; - ScoreCounter.AccentColour = colours.BlueLighter; - - var shd = HealthDisplay as StandardHealthDisplay; - if (shd != null) - { - shd.AccentColour = colours.BlueLighter; - shd.GlowColour = colours.BlueDarker; - } - } - - public override void BindProcessor(ScoreProcessor processor) - { - base.BindProcessor(processor); - - var shd = HealthDisplay as StandardHealthDisplay; - if (shd != null) - processor.NewJudgement += shd.Flash; - } - } -} diff --git a/osu.Game/osu.Game.csproj b/osu.Game/osu.Game.csproj index 50df0008f0..20aa765502 100644 --- a/osu.Game/osu.Game.csproj +++ b/osu.Game/osu.Game.csproj @@ -253,7 +253,6 @@ - @@ -443,6 +442,9 @@ + + +