1
0
mirror of https://github.com/ppy/osu.git synced 2024-09-21 18:47:27 +08:00

Merge branch 'master' into limit-game-access

Conflicts:
	osu.Desktop.VisualTests/Tests/TestCaseChatDisplay.cs
	osu.Game/GameModes/Menu/ButtonSystem.cs
	osu.Game/Online/Chat/Display/ChatLine.cs
	osu.Game/OsuGame.cs
	osu.Game/Overlays/ToolbarButton.cs
This commit is contained in:
Dean Herbert 2016-10-12 20:05:46 +09:00
commit aa96d98822
20 changed files with 908 additions and 558 deletions

View File

@ -12,7 +12,7 @@ namespace osu.Framework.VisualTests
[STAThread]
public static void Main(string[] args)
{
BasicGameHost host = Host.GetSuitableHost(@"visual-tests");
BasicGameHost host = Host.GetSuitableHost(@"osu-visual-tests");
host.Add(new VisualTestGame());
host.Run();
}

View File

@ -5,7 +5,6 @@ using OpenTK;
using osu.Framework.GameModes.Testing;
using osu.Framework.Graphics;
using osu.Framework.Graphics.Containers;
using osu.Framework.Graphics.Transformations;
using osu.Framework.Threading;
using osu.Game;
using osu.Game.Online.API;
@ -15,7 +14,7 @@ using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using osu.Framework.Graphics.Sprites;
using osu.Game.Online.Chat.Display.osu.Online.Social;
using osu.Game.Online.Chat.Display;
using osu.Framework;
namespace osu.Desktop.Tests
@ -27,14 +26,13 @@ namespace osu.Desktop.Tests
public override string Name => @"Chat";
public override string Description => @"Testing API polling";
private List<Channel> channels = new List<Channel>();
private FlowContainer flow;
FlowContainer flow;
private Scheduler scheduler = new Scheduler();
private APIAccess api;
private long? lastMessageId;
private ChannelDisplay channelDisplay;
public override void Load(BaseGame game)
{
@ -47,28 +45,10 @@ namespace osu.Desktop.Tests
{
base.Reset();
lastMessageId = null;
if (api.State != APIAccess.APIState.Online)
api.OnStateChange += delegate { initializeChannels(); };
else
initializeChannels();
Add(new ScrollContainer()
{
Size = new Vector2(1, 0.5f),
Children = new Drawable[]
{
flow = new FlowContainer
{
Direction = FlowDirection.VerticalOnly,
RelativeSizeAxes = Axes.X,
LayoutDuration = 100,
LayoutEasing = EasingTypes.Out,
Spacing = new Vector2(1, 1)
}
}
});
}
protected override void Update()
@ -77,60 +57,87 @@ namespace osu.Desktop.Tests
base.Update();
}
private long? lastMessageId;
List<Channel> careChannels;
private void initializeChannels()
{
careChannels = new List<Channel>();
if (api.State != APIAccess.APIState.Online)
return;
Add(flow = new FlowContainer
{
RelativeSizeAxes = Axes.Both,
Direction = FlowDirection.VerticalOnly
});
SpriteText loading;
Add(loading = new SpriteText
{
Text = @"Loading available channels...",
Anchor = Anchor.Centre,
Origin = Anchor.Centre,
TextSize = 40,
});
messageRequest?.Cancel();
ListChannelsRequest req = new ListChannelsRequest();
req.Success += delegate (List<Channel> channels)
{
this.channels = channels;
messageRequest = scheduler.AddDelayed(requestNewMessages, 1000, true);
Scheduler.Add(delegate
{
loading.FadeOut(100);
});
addChannel(channels.Find(c => c.Name == @"#osu"));
addChannel(channels.Find(c => c.Name == @"#lobby"));
addChannel(channels.Find(c => c.Name == @"#english"));
messageRequest = scheduler.AddDelayed(() => FetchNewMessages(api), 1000, true);
};
api.Queue(req);
}
private void requestNewMessages()
private void addChannel(Channel channel)
{
messageRequest.Wait();
flow.Add(channelDisplay = new ChannelDisplay(channel)
{
Size = new Vector2(1, 0.3f)
});
Channel channel = channels.Find(c => c.Name == "#osu");
careChannels.Add(channel);
}
GetMessagesRequest gm = new GetMessagesRequest(new List<Channel> { channel }, lastMessageId);
gm.Success += delegate (List<Message> messages)
GetMessagesRequest fetchReq;
public void FetchNewMessages(APIAccess api)
{
if (fetchReq != null) return;
fetchReq = new GetMessagesRequest(careChannels, lastMessageId);
fetchReq.Success += delegate (List<Message> messages)
{
foreach (Message m in messages)
{
//m.LineWidth = this.Size.X; //this is kinda ugly.
//m.Drawable.Depth = m.Id;
//m.Drawable.FadeInFromZero(800);
//flow.Add(m.Drawable);
//if (osu.Messages.Count > 50)
//{
// osu.Messages[0].Drawable.Expire();
// osu.Messages.RemoveAt(0);
//}
flow.Add(new ChatLine(m));
channel.Messages.Add(m);
careChannels.Find(c => c.Id == m.ChannelId).AddNewMessages(m);
}
lastMessageId = messages.LastOrDefault()?.Id ?? lastMessageId;
Debug.Write("success!");
messageRequest.Continue();
fetchReq = null;
};
gm.Failure += delegate
fetchReq.Failure += delegate
{
Debug.Write("failure!");
messageRequest.Continue();
fetchReq = null;
};
api.Queue(gm);
api.Queue(fetchReq);
}
}
}

View File

@ -0,0 +1,314 @@
using OpenTK;
using OpenTK.Graphics;
using OpenTK.Input;
using osu.Framework;
using osu.Framework.Graphics;
using osu.Framework.Graphics.Containers;
using osu.Framework.Graphics.Drawables;
using osu.Framework.Graphics.Primitives;
using osu.Framework.Graphics.Sprites;
using osu.Framework.Graphics.Transformations;
using osu.Framework.Input;
using osu.Game.Graphics;
using System;
namespace osu.Game.GameModes.Menu
{
/// <summary>
/// Button designed specifically for the osu!next main menu.
/// In order to correctly flow, we have to use a negative margin on the parent container (due to the parallelogram shape).
/// </summary>
public class Button : AutoSizeContainer, IStateful<ButtonState>
{
private Container iconText;
private WedgedBox box;
private Color4 colour;
private TextAwesome icon;
private string internalName;
private readonly FontAwesome symbol;
private Action clickAction;
private readonly float extraWidth;
private Key triggerKey;
private string text;
public override Quad ScreenSpaceInputQuad => box.ScreenSpaceInputQuad;
public Button(string text, string internalName, FontAwesome symbol, Color4 colour, Action clickAction = null, float extraWidth = 0, Key triggerKey = Key.Unknown)
{
this.internalName = internalName;
this.symbol = symbol;
this.colour = colour;
this.clickAction = clickAction;
this.extraWidth = extraWidth;
this.triggerKey = triggerKey;
this.text = text;
}
public override void Load(BaseGame game)
{
base.Load(game);
Alpha = 0;
Children = new Drawable[]
{
box = new WedgedBox(new Vector2(ButtonSystem.button_width + Math.Abs(extraWidth), ButtonSystem.button_area_height), ButtonSystem.wedge_width)
{
Anchor = Anchor.Centre,
Origin = Anchor.Centre,
Colour = colour,
Scale = new Vector2(0, 1)
},
iconText = new AutoSizeContainer
{
Position = new Vector2(extraWidth / 2, 0),
Anchor = Anchor.Centre,
Origin = Anchor.Centre,
Children = new Drawable[]
{
icon = new TextAwesome
{
Anchor = Anchor.Centre,
TextSize = 30,
Position = new Vector2(0, 0),
Icon = symbol
},
new SpriteText
{
Direction = FlowDirection.HorizontalOnly,
Anchor = Anchor.Centre,
Origin = Anchor.Centre,
TextSize = 16,
Position = new Vector2(0, 35),
Text = text
}
}
}
};
}
protected override bool OnHover(InputState state)
{
if (State != ButtonState.Expanded) return true;
//if (OsuGame.Instance.IsActive)
// Game.Audio.PlaySamplePositional($@"menu-{internalName}-hover", @"menuclick");
box.ScaleTo(new Vector2(1.5f, 1), 500, EasingTypes.OutElastic);
int duration = 0; //(int)(Game.Audio.BeatLength / 2);
if (duration == 0) duration = 250;
icon.ClearTransformations();
icon.ScaleTo(1, 500, EasingTypes.OutElasticHalf);
double offset = 0; //(1 - Game.Audio.SyncBeatProgress) * duration;
double startTime = Time + offset;
icon.RotateTo(10, offset, EasingTypes.InOutSine);
icon.ScaleTo(new Vector2(1, 0.9f), offset, EasingTypes.Out);
icon.Transforms.Add(new TransformRotation(Clock)
{
StartValue = -10,
EndValue = 10,
StartTime = startTime,
EndTime = startTime + duration * 2,
Easing = EasingTypes.InOutSine,
LoopCount = -1,
LoopDelay = duration * 2
});
icon.Transforms.Add(new TransformPosition(Clock)
{
StartValue = Vector2.Zero,
EndValue = new Vector2(0, -10),
StartTime = startTime,
EndTime = startTime + duration,
Easing = EasingTypes.Out,
LoopCount = -1,
LoopDelay = duration
});
icon.Transforms.Add(new TransformScaleVector(Clock)
{
StartValue = new Vector2(1, 0.9f),
EndValue = Vector2.One,
StartTime = startTime,
EndTime = startTime + duration,
Easing = EasingTypes.Out,
LoopCount = -1,
LoopDelay = duration
});
icon.Transforms.Add(new TransformPosition(Clock)
{
StartValue = new Vector2(0, -10),
EndValue = Vector2.Zero,
StartTime = startTime + duration,
EndTime = startTime + duration * 2,
Easing = EasingTypes.In,
LoopCount = -1,
LoopDelay = duration
});
icon.Transforms.Add(new TransformScaleVector(Clock)
{
StartValue = Vector2.One,
EndValue = new Vector2(1, 0.9f),
StartTime = startTime + duration,
EndTime = startTime + duration * 2,
Easing = EasingTypes.In,
LoopCount = -1,
LoopDelay = duration
});
icon.Transforms.Add(new TransformRotation(Clock)
{
StartValue = 10,
EndValue = -10,
StartTime = startTime + duration * 2,
EndTime = startTime + duration * 4,
Easing = EasingTypes.InOutSine,
LoopCount = -1,
LoopDelay = duration * 2
});
return true;
}
protected override void OnHoverLost(InputState state)
{
icon.ClearTransformations();
icon.RotateTo(0, 500, EasingTypes.Out);
icon.MoveTo(Vector2.Zero, 500, EasingTypes.Out);
icon.ScaleTo(0.7f, 500, EasingTypes.OutElasticHalf);
icon.ScaleTo(Vector2.One, 200, EasingTypes.Out);
if (State == ButtonState.Expanded)
box.ScaleTo(new Vector2(1, 1), 500, EasingTypes.OutElastic);
}
protected override bool OnMouseDown(InputState state, MouseDownEventArgs args)
{
trigger();
return true;
}
protected override bool OnKeyDown(InputState state, KeyDownEventArgs args)
{
base.OnKeyDown(state, args);
if (triggerKey == args.Key && triggerKey != Key.Unknown)
{
trigger();
return true;
}
return false;
}
private void trigger()
{
//Game.Audio.PlaySamplePositional($@"menu-{internalName}-click", internalName.Contains(@"back") ? @"menuback" : @"menuhit");
clickAction?.Invoke();
//box.FlashColour(ColourHelper.Lighten2(colour, 0.7f), 200);
}
public override bool HandleInput => state != ButtonState.Exploded && box.Scale.X >= 0.8f;
protected override void Update()
{
iconText.Alpha = MathHelper.Clamp((box.Scale.X - 0.5f) / 0.3f, 0, 1);
base.Update();
}
public int ContractStyle;
ButtonState state;
public ButtonState State
{
get { return state; }
set
{
if (state == value)
return;
state = value;
switch (state)
{
case ButtonState.Contracted:
switch (ContractStyle)
{
default:
box.ScaleTo(new Vector2(0, 1), 500, EasingTypes.OutExpo);
FadeOut(500);
break;
case 1:
box.ScaleTo(new Vector2(0, 1), 400, EasingTypes.InSine);
FadeOut(800);
break;
}
break;
case ButtonState.Expanded:
const int expand_duration = 500;
box.ScaleTo(new Vector2(1, 1), expand_duration, EasingTypes.OutExpo);
FadeIn(expand_duration / 6);
break;
case ButtonState.Exploded:
const int explode_duration = 200;
box.ScaleTo(new Vector2(2, 1), explode_duration, EasingTypes.OutExpo);
FadeOut(explode_duration / 4 * 3);
break;
}
}
}
/// <summary>
/// ________
/// / /
/// / /
/// /_______/
/// </summary>
class WedgedBox : Box
{
float wedgeWidth;
public WedgedBox(Vector2 boxSize, float wedgeWidth)
{
Size = boxSize;
this.wedgeWidth = wedgeWidth;
}
/// <summary>
/// Custom DrawQuad used to create the slanted effect.
/// </summary>
protected override Quad DrawQuad
{
get
{
Quad q = base.DrawQuad;
//Will become infinite if we don't limit its maximum size.
float wedge = Math.Min(q.Width, wedgeWidth / Scale.X);
q.TopLeft.X += wedge;
q.BottomRight.X -= wedge;
return q;
}
}
}
}
public enum ButtonState
{
Contracted,
Expanded,
Exploded
}
}

View File

@ -20,7 +20,7 @@ using osu.Framework;
namespace osu.Game.GameModes.Menu
{
public partial class ButtonSystem : Container
public partial class ButtonSystem : Container, IStateful<MenuState>
{
public Action OnEdit;
public Action OnExit;
@ -33,9 +33,10 @@ namespace osu.Game.GameModes.Menu
private FlowContainerWithOrigin buttonFlow;
const float button_area_height = 100;
const float button_width = 140f;
const float wedge_width = 20;
//todo: make these non-internal somehow.
internal const float button_area_height = 100;
internal const float button_width = 140f;
internal const float wedge_width = 20;
public const int EXIT_DELAY = 3000;
@ -50,15 +51,6 @@ namespace osu.Game.GameModes.Menu
List<Button> buttonsTopLevel = new List<Button>();
List<Button> buttonsPlay = new List<Button>();
public enum MenuState
{
Initial,
TopLevel,
Play,
EnteringMode,
Exit,
}
public ButtonSystem()
{
RelativeSizeAxes = Axes.Both;
@ -89,6 +81,7 @@ namespace osu.Game.GameModes.Menu
},
buttonFlow = new FlowContainerWithOrigin
{
Direction = FlowDirection.HorizontalOnly,
Anchor = Anchor.Centre,
Spacing = new Vector2(-wedge_width, 0),
Children = new Drawable[]
@ -129,16 +122,19 @@ namespace osu.Game.GameModes.Menu
protected override bool OnKeyDown(InputState state, KeyDownEventArgs args)
{
if (args.Key == Key.Escape)
switch (args.Key)
{
if (State == MenuState.Initial)
return false;
case Key.Space:
osuLogo.TriggerClick(state);
return true;
case Key.Escape:
if (State == MenuState.Initial)
return false;
State = MenuState.Initial;
return true;
State = MenuState.Initial;
return true;
}
osuLogo.TriggerClick(state);
return true;
}
@ -209,10 +205,10 @@ namespace osu.Game.GameModes.Menu
osuLogo.ScaleTo(1, 800, EasingTypes.OutExpo);
foreach (Button b in buttonsTopLevel)
b.State = Button.ButtonState.Contracted;
b.State = ButtonState.Contracted;
foreach (Button b in buttonsPlay)
b.State = Button.ButtonState.Contracted;
b.State = ButtonState.Contracted;
break;
case MenuState.TopLevel:
buttonAreaBackground.ScaleTo(Vector2.One, 200, EasingTypes.Out);
@ -227,17 +223,17 @@ namespace osu.Game.GameModes.Menu
buttonArea.Delay(150, true);
foreach (Button b in buttonsTopLevel)
b.State = Button.ButtonState.Expanded;
b.State = ButtonState.Expanded;
foreach (Button b in buttonsPlay)
b.State = Button.ButtonState.Contracted;
b.State = ButtonState.Contracted;
break;
case MenuState.Play:
foreach (Button b in buttonsTopLevel)
b.State = Button.ButtonState.Exploded;
b.State = ButtonState.Exploded;
foreach (Button b in buttonsPlay)
b.State = Button.ButtonState.Expanded;
b.State = ButtonState.Expanded;
break;
case MenuState.EnteringMode:
buttonAreaBackground.ScaleTo(new Vector2(2, 0), 300, EasingTypes.InSine);
@ -248,19 +244,19 @@ namespace osu.Game.GameModes.Menu
settingsButton.ContractStyle = 1;
foreach (Button b in buttonsTopLevel)
b.State = Button.ButtonState.Contracted;
b.State = ButtonState.Contracted;
foreach (Button b in buttonsPlay)
b.State = Button.ButtonState.Contracted;
b.State = ButtonState.Contracted;
break;
case MenuState.Exit:
buttonArea.FadeOut(200);
foreach (Button b in buttonsTopLevel)
b.State = Button.ButtonState.Contracted;
b.State = ButtonState.Contracted;
foreach (Button b in buttonsPlay)
b.State = Button.ButtonState.Contracted;
b.State = ButtonState.Contracted;
osuLogo.Delay(150);
@ -270,8 +266,8 @@ namespace osu.Game.GameModes.Menu
break;
}
backButton.State = state == MenuState.Play ? Button.ButtonState.Expanded : Button.ButtonState.Contracted;
settingsButton.State = state == MenuState.TopLevel ? Button.ButtonState.Expanded : Button.ButtonState.Contracted;
backButton.State = state == MenuState.Play ? ButtonState.Expanded : ButtonState.Contracted;
settingsButton.State = state == MenuState.TopLevel ? ButtonState.Expanded : ButtonState.Contracted;
if (lastState == MenuState.Initial)
buttonArea.DelayReset();
@ -286,337 +282,14 @@ namespace osu.Game.GameModes.Menu
iconFacade.Width = osuLogo.SizeForFlow * 0.5f;
base.Update();
}
}
/// <summary>
/// A flow container with an origin based on one of its contained drawables.
/// </summary>
private class FlowContainerWithOrigin : FlowContainer
{
/// <summary>
/// A target drawable which this flowcontainer should be centered around.
/// This target MUST be in this FlowContainer's *direct* children.
/// </summary>
internal Drawable CentreTarget;
public override Anchor Origin => Anchor.Custom;
public override Vector2 OriginPosition
{
get
{
if (CentreTarget == null)
return base.OriginPosition;
return CentreTarget.Position + CentreTarget.Size / 2;
}
}
public FlowContainerWithOrigin()
{
Direction = FlowDirection.HorizontalOnly;
}
}
/// <summary>
/// Button designed specifically for the osu!next main menu.
/// In order to correctly flow, we have to use a negative margin on the parent container (due to the parallelogram shape).
/// </summary>
private class Button : AutoSizeContainer
{
private Container iconText;
private WedgedBox box;
private Color4 colour;
private TextAwesome icon;
private string internalName;
private readonly FontAwesome symbol;
private Action clickAction;
private readonly float extraWidth;
private Key triggerKey;
private string text;
public override Quad ScreenSpaceInputQuad => box.ScreenSpaceInputQuad;
public Button(string text, string internalName, FontAwesome symbol, Color4 colour, Action clickAction = null, float extraWidth = 0, Key triggerKey = Key.Unknown)
{
this.internalName = internalName;
this.symbol = symbol;
this.colour = colour;
this.clickAction = clickAction;
this.extraWidth = extraWidth;
this.triggerKey = triggerKey;
this.text = text;
}
public override void Load(BaseGame game)
{
base.Load(game);
Alpha = 0;
Children = new Drawable[]
{
box = new WedgedBox(new Vector2(button_width + Math.Abs(extraWidth), button_area_height), wedge_width)
{
Anchor = Anchor.Centre,
Origin = Anchor.Centre,
Colour = colour,
Scale = new Vector2(0, 1)
},
iconText = new AutoSizeContainer
{
Position = new Vector2(extraWidth / 2, 0),
Anchor = Anchor.Centre,
Origin = Anchor.Centre,
Children = new Drawable[]
{
icon = new TextAwesome
{
Anchor = Anchor.Centre,
TextSize = 30,
Position = new Vector2(0, 0),
Icon = symbol
},
new SpriteText
{
Direction = FlowDirection.HorizontalOnly,
Anchor = Anchor.Centre,
Origin = Anchor.Centre,
TextSize = 16,
Position = new Vector2(0, 35),
Text = text
}
}
}
};
}
protected override bool OnHover(InputState state)
{
if (State != ButtonState.Expanded) return true;
//if (OsuGame.Instance.IsActive)
// Game.Audio.PlaySamplePositional($@"menu-{internalName}-hover", @"menuclick");
box.ScaleTo(new Vector2(1.5f, 1), 500, EasingTypes.OutElastic);
int duration = 0; //(int)(Game.Audio.BeatLength / 2);
if (duration == 0) duration = 250;
icon.ClearTransformations();
icon.ScaleTo(1, 500, EasingTypes.OutElasticHalf);
double offset = 0; //(1 - Game.Audio.SyncBeatProgress) * duration;
double startTime = Time + offset;
icon.RotateTo(10, offset, EasingTypes.InOutSine);
icon.ScaleTo(new Vector2(1, 0.9f), offset, EasingTypes.Out);
icon.Transforms.Add(new TransformRotation(Clock)
{
StartValue = -10,
EndValue = 10,
StartTime = startTime,
EndTime = startTime + duration * 2,
Easing = EasingTypes.InOutSine,
LoopCount = -1,
LoopDelay = duration * 2
});
icon.Transforms.Add(new TransformPosition(Clock)
{
StartValue = Vector2.Zero,
EndValue = new Vector2(0, -10),
StartTime = startTime,
EndTime = startTime + duration,
Easing = EasingTypes.Out,
LoopCount = -1,
LoopDelay = duration
});
icon.Transforms.Add(new TransformScaleVector(Clock)
{
StartValue = new Vector2(1, 0.9f),
EndValue = Vector2.One,
StartTime = startTime,
EndTime = startTime + duration,
Easing = EasingTypes.Out,
LoopCount = -1,
LoopDelay = duration
});
icon.Transforms.Add(new TransformPosition(Clock)
{
StartValue = new Vector2(0, -10),
EndValue = Vector2.Zero,
StartTime = startTime + duration,
EndTime = startTime + duration * 2,
Easing = EasingTypes.In,
LoopCount = -1,
LoopDelay = duration
});
icon.Transforms.Add(new TransformScaleVector(Clock)
{
StartValue = Vector2.One,
EndValue = new Vector2(1, 0.9f),
StartTime = startTime + duration,
EndTime = startTime + duration * 2,
Easing = EasingTypes.In,
LoopCount = -1,
LoopDelay = duration
});
icon.Transforms.Add(new TransformRotation(Clock)
{
StartValue = 10,
EndValue = -10,
StartTime = startTime + duration * 2,
EndTime = startTime + duration * 4,
Easing = EasingTypes.InOutSine,
LoopCount = -1,
LoopDelay = duration * 2
});
return true;
}
protected override void OnHoverLost(InputState state)
{
icon.ClearTransformations();
icon.RotateTo(0, 500, EasingTypes.Out);
icon.MoveTo(Vector2.Zero, 500, EasingTypes.Out);
icon.ScaleTo(0.7f, 500, EasingTypes.OutElasticHalf);
icon.ScaleTo(Vector2.One, 200, EasingTypes.Out);
if (State == ButtonState.Expanded)
box.ScaleTo(new Vector2(1, 1), 500, EasingTypes.OutElastic);
}
protected override bool OnMouseDown(InputState state, MouseDownEventArgs args)
{
trigger();
return true;
}
protected override bool OnKeyDown(InputState state, KeyDownEventArgs args)
{
base.OnKeyDown(state, args);
if (triggerKey == args.Key && triggerKey != Key.Unknown)
{
trigger();
return true;
}
return false;
}
private void trigger()
{
//Game.Audio.PlaySamplePositional($@"menu-{internalName}-click", internalName.Contains(@"back") ? @"menuback" : @"menuhit");
clickAction?.Invoke();
//box.FlashColour(ColourHelper.Lighten2(colour, 0.7f), 200);
}
public override bool HandleInput => state != ButtonState.Exploded && box.Scale.X >= 0.8f;
protected override void Update()
{
iconText.Alpha = MathHelper.Clamp((box.Scale.X - 0.5f) / 0.3f, 0, 1);
base.Update();
}
public int ContractStyle;
ButtonState state;
public ButtonState State
{
get { return state; }
set
{
if (state == value)
return;
state = value;
switch (state)
{
case ButtonState.Contracted:
switch (ContractStyle)
{
default:
box.ScaleTo(new Vector2(0, 1), 500, EasingTypes.OutExpo);
FadeOut(500);
break;
case 1:
box.ScaleTo(new Vector2(0, 1), 400, EasingTypes.InSine);
FadeOut(800);
break;
}
break;
case ButtonState.Expanded:
const int expand_duration = 500;
box.ScaleTo(new Vector2(1, 1), expand_duration, EasingTypes.OutExpo);
FadeIn(expand_duration / 6);
break;
case ButtonState.Exploded:
const int explode_duration = 200;
box.ScaleTo(new Vector2(2, 1), explode_duration, EasingTypes.OutExpo);
FadeOut(explode_duration / 4 * 3);
break;
}
}
}
public enum ButtonState
{
Contracted,
Expanded,
Exploded
}
/// <summary>
/// ________
/// / /
/// / /
/// /_______/
/// </summary>
class WedgedBox : Box
{
float wedgeWidth;
public WedgedBox(Vector2 boxSize, float wedgeWidth)
{
Size = boxSize;
this.wedgeWidth = wedgeWidth;
}
/// <summary>
/// Custom DrawQuad used to create the slanted effect.
/// </summary>
protected override Quad DrawQuad
{
get
{
Quad q = base.DrawQuad;
//Will become infinite if we don't limit its maximum size.
float wedge = Math.Min(q.Width, wedgeWidth / Scale.X);
q.TopLeft.X += wedge;
q.BottomRight.X -= wedge;
return q;
}
}
}
}
internal class MenuVisualisation : Drawable
{
}
public enum MenuState
{
Initial,
TopLevel,
Play,
EnteringMode,
Exit,
}
}

View File

@ -0,0 +1,31 @@
using OpenTK;
using osu.Framework.Graphics;
using osu.Framework.Graphics.Containers;
namespace osu.Game.GameModes.Menu
{
/// <summary>
/// A flow container with an origin based on one of its contained drawables.
/// </summary>
public class FlowContainerWithOrigin : FlowContainer
{
/// <summary>
/// A target drawable which this flowcontainer should be centered around.
/// This target should be a direct child of this FlowContainer.
/// </summary>
public Drawable CentreTarget;
public override Anchor Origin => Anchor.Custom;
public override Vector2 OriginPosition
{
get
{
if (CentreTarget == null)
return base.OriginPosition;
return CentreTarget.Position + CentreTarget.Size / 2;
}
}
}
}

View File

@ -63,7 +63,7 @@ namespace osu.Game.GameModes.Menu
logo.ScaleTo(0);
logo.ScaleTo(1,5900, EasingTypes.OutQuint);
logo.ScaleTo(1, 5900, EasingTypes.OutQuint);
logo.FadeIn(30000, EasingTypes.OutQuint);
}
@ -82,7 +82,7 @@ namespace osu.Game.GameModes.Menu
protected override void OnResuming(GameMode last)
{
//we are just an intro. if we are resumed, we just want to exit after a short delay (to allow the last mode to transition out).
Scheduler.AddDelayed(Exit, 300);
Scheduler.AddDelayed(Exit, 600);
base.OnResuming(last);
}

View File

@ -1,8 +1,6 @@
//Copyright (c) 2007-2016 ppy Pty Ltd <contact@ppy.sh>.
//Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
using osu.Framework.Audio.Sample;
using osu.Framework.Audio.Track;
using osu.Framework.GameModes;
using osu.Framework.GameModes.Testing;
using osu.Framework.Graphics;
@ -66,7 +64,7 @@ namespace osu.Game.GameModes.Menu
const float length = 400;
buttons.State = ButtonSystem.MenuState.EnteringMode;
buttons.State = MenuState.EnteringMode;
Content.FadeOut(length, EasingTypes.InSine);
Content.MoveTo(new Vector2(-800, 0), length, EasingTypes.InSine);
@ -78,7 +76,7 @@ namespace osu.Game.GameModes.Menu
const float length = 300;
buttons.State = ButtonSystem.MenuState.TopLevel;
buttons.State = MenuState.TopLevel;
Content.FadeIn(length, EasingTypes.OutQuint);
Content.MoveTo(new Vector2(0, 0), length, EasingTypes.OutQuint);

View File

@ -0,0 +1,13 @@
using osu.Framework.Graphics;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace osu.Game.GameModes.Menu
{
internal class MenuVisualisation : Drawable
{
}
}

View File

@ -18,7 +18,7 @@ namespace osu.Game.GameModes.Menu
{
private Sprite logo;
private Container logoBounceContainer;
private ButtonSystem.MenuVisualisation vis;
private MenuVisualisation vis;
public Action Action;
@ -70,7 +70,7 @@ namespace osu.Game.GameModes.Menu
}
}
},
vis = new ButtonSystem.MenuVisualisation
vis = new MenuVisualisation
{
Anchor = Anchor.Centre,
Origin = Anchor.Centre,

View File

@ -0,0 +1,21 @@
//Copyright (c) 2007-2016 ppy Pty Ltd <contact@ppy.sh>.
//Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
using System;
using osu.Framework.Graphics;
using osu.Framework.Input;
namespace osu.Game.Input
{
public class GlobalHotkeys : Drawable
{
public Func<InputState, KeyDownEventArgs, bool> Handler;
public override bool HandleInput => true;
protected override bool OnKeyDown(InputState state, KeyDownEventArgs args)
{
return Handler(state, args);
}
}
}

View File

@ -1,8 +1,14 @@
//Copyright (c) 2007-2016 ppy Pty Ltd <contact@ppy.sh>.
//Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using Newtonsoft.Json;
using osu.Framework.Configuration;
using osu.Game.Online.API;
using osu.Game.Online.API.Requests;
namespace osu.Game.Online.Chat
{
@ -24,9 +30,28 @@ namespace osu.Game.Online.Chat
//internal bool Joined;
public const int MAX_HISTORY = 100;
[JsonConstructor]
public Channel()
{
}
public event Action<Message[]> NewMessagesArrived;
public void AddNewMessages(params Message[] messages)
{
Messages.AddRange(messages);
purgeOldMessages();
NewMessagesArrived?.Invoke(messages);
}
private void purgeOldMessages()
{
int messageCount = Messages.Count;
if (messageCount > MAX_HISTORY)
Messages.RemoveRange(0, messageCount - MAX_HISTORY);
}
}
}

View File

@ -0,0 +1,81 @@
//Copyright (c) 2007-2016 ppy Pty Ltd <contact@ppy.sh>.
//Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
using System;
using System.Collections.Generic;
using System.Linq;
using osu.Framework.Graphics;
using osu.Framework.Graphics.Containers;
using osu.Framework.Graphics.Sprites;
using osu.Framework.Graphics.Transformations;
using osu.Game.Online.Chat.Display.osu.Online.Social;
using OpenTK;
using osu.Framework;
namespace osu.Game.Online.Chat.Display
{
public class ChannelDisplay : Container
{
private readonly Channel channel;
private FlowContainer flow;
public ChannelDisplay(Channel channel)
{
this.channel = channel;
newMessages(channel.Messages);
channel.NewMessagesArrived += newMessages;
RelativeSizeAxes = Axes.Both;
Children = new Drawable[]
{
new SpriteText
{
Text = channel.Name,
TextSize = 50,
Alpha = 0.3f,
Anchor = Anchor.Centre,
Origin = Anchor.Centre
},
new ScrollContainer
{
Children = new Drawable[]
{
flow = new FlowContainer
{
Direction = FlowDirection.VerticalOnly,
RelativeSizeAxes = Axes.X,
Spacing = new Vector2(1, 1)
}
}
}
};
}
protected override void Dispose(bool isDisposing)
{
base.Dispose(isDisposing);
channel.NewMessagesArrived -= newMessages;
}
public override void Load(BaseGame game)
{
base.Load(game);
newMessages(channel.Messages);
}
private void newMessages(IEnumerable<Message> newMessages)
{
if (!IsLoaded) return;
var displayMessages = newMessages.Skip(Math.Max(0, newMessages.Count() - Channel.MAX_HISTORY));
//up to last Channel.MAX_HISTORY messages
foreach (Message m in displayMessages)
flow.Add(new ChatLine(m));
while (flow.Children.Count() > Channel.MAX_HISTORY)
flow.Remove(flow.Children.First());
}
}
}

View File

@ -1,6 +1,8 @@
//Copyright (c) 2007-2016 ppy Pty Ltd <contact@ppy.sh>.
//Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
using System;
using osu.Framework.Configuration;
using osu.Framework.Graphics;
using osu.Framework.Graphics.Containers;
using osu.Framework.Graphics.Drawables;
@ -8,6 +10,7 @@ using osu.Framework.Graphics.Sprites;
using OpenTK;
using OpenTK.Graphics;
using osu.Framework;
using osu.Framework.Graphics.Primitives;
namespace osu.Game.Online.Chat.Display
{
@ -15,48 +18,59 @@ namespace osu.Game.Online.Chat.Display
{
public class ChatLine : AutoSizeContainer
{
private readonly Message msg;
public readonly Message Message;
public ChatLine(Message msg)
public ChatLine(Message message)
{
this.msg = msg;
this.Message = message;
}
const float padding = 200;
const float text_size = 20;
public override void Load(BaseGame game)
{
base.Load(game);
RelativeSizeAxes = Axes.X;
Add(new Box
Children = new Drawable[]
{
RelativeSizeAxes = Axes.Both,
Colour = Color4.Aqua,
Alpha = 0.2f
});
Add(new SpriteText
{
Text = msg.Timestamp.ToLocalTime().ToLongTimeString(),
Colour = new Color4(128, 128, 128, 255)
});
Add(new SpriteText
{
Text = msg.User.Name,
Origin = Anchor.TopRight,
RelativePositionAxes = Axes.X,
Position = new Vector2(0.14f,0),
});
Add(new SpriteText
{
Text = msg.Content,
RelativePositionAxes = Axes.X,
Position = new Vector2(0.15f, 0),
RelativeSizeAxes = Axes.X,
Size = new Vector2(0.85f, 1),
});
new Container
{
Size = new Vector2(padding, text_size),
Children = new Drawable[]
{
new SpriteText
{
Text = Message.Timestamp.ToLocalTime().ToLongTimeString(),
TextSize = text_size,
Colour = new Color4(128, 128, 128, 255)
},
new SpriteText
{
Text = Message.User.Name,
TextSize = text_size,
Origin = Anchor.TopRight,
Anchor = Anchor.TopRight,
}
}
},
new Container
{
RelativeSizeAxes = Axes.X,
Padding = new MarginPadding { Left = padding + 10 },
Children = new Drawable[]
{
new SpriteText
{
Text = Message.Content,
TextSize = text_size,
RelativeSizeAxes = Axes.X,
}
}
}
};
}
}
}

View File

@ -12,10 +12,10 @@ namespace osu.Game.Online.Chat
public long Id;
[JsonProperty(@"user_id")]
public string UserId;
public int UserId;
[JsonProperty(@"channel_id")]
public string ChannelId;
public int ChannelId;
[JsonProperty(@"timestamp")]
public DateTime Timestamp;

View File

@ -8,6 +8,7 @@ using osu.Game.Configuration;
using osu.Game.GameModes.Menu;
using OpenTK;
using osu.Framework.Graphics;
using osu.Framework.Graphics.Containers;
using osu.Framework.Graphics.Sprites;
using osu.Framework.Platform;
using osu.Game.GameModes;
@ -16,12 +17,16 @@ using osu.Game.GameModes.Play;
using osu.Game.Graphics.Containers;
using osu.Game.Overlays;
using osu.Framework;
using osu.Framework.Input;
using osu.Game.Input;
using OpenTK.Input;
namespace osu.Game
{
public class OsuGame : OsuGameBase
{
public Toolbar Toolbar;
public ChatConsole Chat;
public MainMenu MainMenu => intro?.ChildGameMode as MainMenu;
private Intro intro;
@ -52,15 +57,24 @@ namespace osu.Game
OnPlayModeChange = delegate (PlayMode m) { PlayMode.Value = m; },
Alpha = 0.001f,
},
Chat = new ChatConsole(API),
new VolumeControl
{
VolumeGlobal = Audio.Volume,
VolumeSample = Audio.VolumeSample,
VolumeTrack = Audio.VolumeTrack
},
new GlobalHotkeys //exists because UserInputManager is at a level below us.
{
Handler = globalHotkeyPressed
}
});
Toolbar.SetState(ToolbarState.Hidden, true);
Toolbar.State = ToolbarState.Hidden;
Toolbar.Flush();
Chat.State = ChatConsoleState.Hidden;
Chat.Flush();
intro.ModePushed += modeAdded;
intro.Exited += modeRemoved;
@ -72,6 +86,18 @@ namespace osu.Game
Cursor.Alpha = 0;
}
private bool globalHotkeyPressed(InputState state, KeyDownEventArgs args)
{
switch (args.Key)
{
case Key.F8:
Chat.State = Chat.State == ChatConsoleState.Hidden ? ChatConsoleState.Visible : ChatConsoleState.Hidden;
return true;
}
return base.OnKeyDown(state, args);
}
public Action<GameMode> ModeChanged;
private void modeChanged(GameMode newMode)
@ -83,11 +109,12 @@ namespace osu.Game
//central game mode change logic.
if (newMode is Player || newMode is Intro)
{
Toolbar.SetState(ToolbarState.Hidden);
Toolbar.State = ToolbarState.Hidden;
Chat.State = ChatConsoleState.Hidden;
}
else
{
Toolbar.SetState(ToolbarState.Visible);
Toolbar.State = ToolbarState.Visible;
}
Cursor.FadeIn(100);
@ -102,7 +129,10 @@ namespace osu.Game
{
if (!intro.DidLoadMenu || intro.ChildGameMode != null)
{
intro.MakeCurrent();
Scheduler.Add(delegate
{
intro.MakeCurrent();
});
return true;
}

View File

@ -0,0 +1,175 @@
//Copyright (c) 2007-2016 ppy Pty Ltd <contact@ppy.sh>.
//Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using osu.Framework.Graphics;
using osu.Framework.Graphics.Containers;
using osu.Framework.Graphics.Drawables;
using osu.Framework.Graphics.Sprites;
using osu.Framework.Graphics.Transformations;
using osu.Framework.Threading;
using osu.Game.Online.API;
using osu.Game.Online.API.Requests;
using osu.Game.Online.Chat;
using osu.Game.Online.Chat.Display;
using OpenTK;
using OpenTK.Graphics;
using osu.Framework.Input;
using OpenTK.Input;
using osu.Framework;
namespace osu.Game.Overlays
{
public class ChatConsole : Container, IStateful<ChatConsoleState>
{
private ChannelDisplay channelDisplay;
private ScheduledDelegate messageRequest;
private Container content;
protected override Container Content => content;
private APIAccess api;
public ChatConsole(APIAccess api)
{
this.api = api;
RelativeSizeAxes = Axes.X;
Size = new Vector2(1, 300);
Anchor = Anchor.BottomLeft;
Origin = Anchor.BottomLeft;
AddInternal(new Drawable[]
{
new Box
{
Depth = float.MinValue,
RelativeSizeAxes = Axes.Both,
Colour = new Color4(0.1f, 0.1f, 0.1f, 0.4f),
},
content = new Container
{
RelativeSizeAxes = Axes.Both,
}
});
}
public override void Load(BaseGame game)
{
base.Load(game);
initializeChannels();
}
private long? lastMessageId;
List<Channel> careChannels;
private void initializeChannels()
{
careChannels = new List<Channel>();
//if (api.State != APIAccess.APIState.Online)
// return;
SpriteText loading;
Add(loading = new SpriteText
{
Text = @"Loading available channels...",
Anchor = Anchor.Centre,
Origin = Anchor.Centre,
TextSize = 40,
});
messageRequest?.Cancel();
ListChannelsRequest req = new ListChannelsRequest();
req.Success += delegate (List<Channel> channels)
{
Scheduler.Add(delegate
{
loading.FadeOut(100);
addChannel(channels.Find(c => c.Name == @"#osu"));
});
//addChannel(channels.Find(c => c.Name == @"#lobby"));
//addChannel(channels.Find(c => c.Name == @"#english"));
messageRequest = Scheduler.AddDelayed(() => FetchNewMessages(api), 1000, true);
};
api.Queue(req);
}
private void addChannel(Channel channel)
{
Add(channelDisplay = new ChannelDisplay(channel));
careChannels.Add(channel);
}
GetMessagesRequest fetchReq;
public void FetchNewMessages(APIAccess api)
{
if (fetchReq != null) return;
fetchReq = new GetMessagesRequest(careChannels, lastMessageId);
fetchReq.Success += delegate (List<Message> messages)
{
foreach (Message m in messages)
{
careChannels.Find(c => c.Id == m.ChannelId).AddNewMessages(m);
}
lastMessageId = messages.LastOrDefault()?.Id ?? lastMessageId;
Debug.Write("success!");
fetchReq = null;
};
fetchReq.Failure += delegate
{
Debug.Write("failure!");
fetchReq = null;
};
api.Queue(fetchReq);
}
private ChatConsoleState state;
public ChatConsoleState State
{
get { return state; }
set
{
state = value;
const int transition_length = 500;
switch (state)
{
case ChatConsoleState.Hidden:
MoveToY(-Size.Y, transition_length, EasingTypes.InQuint);
FadeOut(transition_length, EasingTypes.InQuint);
break;
case ChatConsoleState.Visible:
MoveToY(0, transition_length, EasingTypes.OutQuint);
FadeIn(transition_length, EasingTypes.OutQuint);
break;
}
}
}
}
public enum ChatConsoleState
{
Visible,
Hidden,
}
}

View File

@ -16,7 +16,7 @@ using osu.Framework;
namespace osu.Game.Overlays
{
public class Toolbar : Container
public class Toolbar : Container, IStateful<ToolbarState>
{
const float height = 50;
@ -26,20 +26,28 @@ namespace osu.Game.Overlays
private ToolbarModeSelector modeSelector;
public void SetState(ToolbarState state, bool instant = false)
{
int time = instant ? 0 : 200;
private ToolbarState state;
switch (state)
public ToolbarState State
{
get { return state; }
set
{
case ToolbarState.Hidden:
MoveToY(-Size.Y, time, EasingTypes.InQuint);
FadeOut(time);
break;
case ToolbarState.Visible:
MoveToY(0, time, EasingTypes.OutQuint);
FadeIn(time);
break;
state = value;
const int transition_time = 200;
switch (state)
{
case ToolbarState.Hidden:
MoveToY(-Size.Y, transition_time, EasingTypes.InQuint);
FadeOut(transition_time, EasingTypes.InQuint);
break;
case ToolbarState.Visible:
MoveToY(0, transition_time, EasingTypes.OutQuint);
FadeIn(transition_time, EasingTypes.OutQuint);
break;
}
}
}

View File

@ -11,6 +11,7 @@ using osu.Game.Graphics;
using OpenTK;
using OpenTK.Graphics;
using osu.Framework;
using osu.Framework.Graphics.Primitives;
namespace osu.Game.Overlays
{
@ -30,7 +31,6 @@ namespace osu.Game.Overlays
set
{
DrawableText.Text = value;
paddingIcon.Alpha = string.IsNullOrEmpty(value) ? 0 : 1;
}
}
@ -56,110 +56,73 @@ namespace osu.Game.Overlays
protected TextAwesome DrawableIcon;
protected SpriteText DrawableText;
protected Box HoverBackground;
private Drawable paddingLeft;
private Drawable paddingRight;
private Drawable paddingIcon;
private FlowContainer tooltipContainer;
private SpriteText tooltip1;
private SpriteText tooltip2;
public new float Padding
{
get { return paddingLeft.Size.X; }
set
{
paddingLeft.Size = new Vector2(value, 1);
paddingRight.Size = new Vector2(value, 1);
tooltipContainer.Position = new Vector2(value, tooltipContainer.Position.Y);
}
}
public ToolbarButton()
{
HoverBackground = new Box
Children = new Drawable[]
{
RelativeSizeAxes = Axes.Both,
Additive = true,
Colour = new Color4(60, 60, 60, 255),
Alpha = 0,
};
DrawableIcon = new TextAwesome
{
Anchor = Anchor.CentreLeft,
Origin = Anchor.CentreLeft,
};
DrawableText = new SpriteText
{
Anchor = Anchor.CentreLeft,
Origin = Anchor.CentreLeft,
};
tooltipContainer = new FlowContainer
{
Direction = FlowDirection.VerticalOnly,
Anchor = Anchor.BottomLeft,
Position = new Vector2(0, -5),
Alpha = 0,
Children = new[]
HoverBackground = new Box
{
tooltip1 = new SpriteText()
RelativeSizeAxes = Axes.Both,
Additive = true,
Colour = new Color4(60, 60, 60, 255),
Alpha = 0,
},
new FlowContainer
{
Direction = FlowDirection.HorizontalOnly,
Anchor = Anchor.TopCentre,
Origin = Anchor.TopCentre,
Padding = new MarginPadding { Left = 5, Right = 5 },
RelativeSizeAxes = Axes.Y,
Children = new Drawable[]
{
TextSize = 22,
DrawableIcon = new TextAwesome
{
Anchor = Anchor.CentreLeft,
Origin = Anchor.CentreLeft,
},
DrawableText = new SpriteText
{
Margin = new MarginPadding { Left = 5 },
Anchor = Anchor.CentreLeft,
Origin = Anchor.CentreLeft,
},
},
tooltip2 = new SpriteText
},
tooltipContainer = new FlowContainer
{
Direction = FlowDirection.VerticalOnly,
Anchor = Anchor.BottomLeft,
Position = new Vector2(5, -5),
Alpha = 0,
Children = new[]
{
TextSize = 15
tooltip1 = new SpriteText()
{
TextSize = 22,
},
tooltip2 = new SpriteText
{
TextSize = 15
}
}
}
};
paddingLeft = new Container { RelativeSizeAxes = Axes.Y };
paddingRight = new Container { RelativeSizeAxes = Axes.Y };
paddingIcon = new Container
{
Size = new Vector2(5, 0),
Alpha = 0
};
Padding = 10;
RelativeSizeAxes = Axes.Y;
Size = new Vector2(WIDTH, 1);
}
public override void Load(BaseGame game)
{
base.Load(game);
Children = new Drawable[]
{
HoverBackground,
new FlowContainer
{
Direction = FlowDirection.HorizontalOnly,
Anchor = Anchor.TopCentre,
Origin = Anchor.TopCentre,
RelativeSizeAxes = Axes.Y,
Children = new Drawable[]
{
paddingLeft,
DrawableIcon,
paddingIcon,
DrawableText,
paddingRight
},
},
tooltipContainer
};
}
protected override void Update()
{
base.Update();
//todo: find a way to avoid using this (autosize needs to be able to ignore certain drawables.. in this case the tooltip)
Size = new Vector2(WIDTH + DrawableText.Size.X, 1);
Size = new Vector2(WIDTH + (DrawableText.IsVisible ? DrawableText.Size.X : 0), 1);
}
protected override bool OnClick(InputState state)

View File

@ -76,9 +76,12 @@
<Compile Include="GameModes\Charts\ChartInfo.cs" />
<Compile Include="GameModes\Edit\Editor.cs" />
<Compile Include="GameModes\GameModeWhiteBox.cs" />
<Compile Include="GameModes\Menu\Button.cs" />
<Compile Include="GameModes\Menu\FlowContainerWithOrigin.cs" />
<Compile Include="GameModes\Menu\Intro.cs" />
<Compile Include="GameModes\Menu\ButtonSystem.cs" />
<Compile Include="GameModes\Menu\MainMenu.cs" />
<Compile Include="GameModes\Menu\MenuVisualisation.cs" />
<Compile Include="GameModes\Menu\OsuLogo.cs" />
<Compile Include="GameModes\Multiplayer\Lobby.cs" />
<Compile Include="GameModes\Multiplayer\Match.cs" />
@ -103,6 +106,7 @@
<Compile Include="GameModes\Play\Taiko\TaikoHitRenderer.cs" />
<Compile Include="GameModes\Play\Taiko\TaikoPlayfield.cs" />
<Compile Include="GameModes\Edit\EditSongSelect.cs" />
<Compile Include="Input\GlobalHotkeys.cs" />
<Compile Include="Graphics\Background\Background.cs" />
<Compile Include="Graphics\Containers\ParallaxContainer.cs" />
<Compile Include="Graphics\Cursor\OsuCursorContainer.cs" />
@ -129,11 +133,13 @@
<Compile Include="Online\API\SecurePassword.cs" />
<Compile Include="Online\API\Requests\ListChannels.cs" />
<Compile Include="Online\Chat\Channel.cs" />
<Compile Include="Online\Chat\Display\ChannelDisplay.cs" />
<Compile Include="Online\Chat\Display\ChatLine.cs" />
<Compile Include="Online\Chat\Message.cs" />
<Compile Include="Online\User.cs" />
<Compile Include="OsuGame.cs" />
<Compile Include="OsuGameBase.cs" />
<Compile Include="Overlays\ChatConsole.cs" />
<Compile Include="Overlays\Options.cs" />
<Compile Include="Overlays\Toolbar.cs" />
<Compile Include="Overlays\ToolbarButton.cs" />

View File

@ -19,8 +19,6 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "osu.Framework.Desktop", "os
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "osu.Desktop.VisualTests", "osu.Desktop.VisualTests\osu.Desktop.VisualTests.csproj", "{69051C69-12AE-4E7D-A3E6-460D2E282312}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "osu.Game.Tests", "osu.Game.Tests\osu.Game.Tests.csproj", "{54377672-20B1-40AF-8087-5CF73BF3953A}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
@ -58,12 +56,6 @@ Global
{69051C69-12AE-4E7D-A3E6-460D2E282312}.Deploy|Any CPU.ActiveCfg = Debug|Any CPU
{69051C69-12AE-4E7D-A3E6-460D2E282312}.Release|Any CPU.ActiveCfg = Release|Any CPU
{69051C69-12AE-4E7D-A3E6-460D2E282312}.Release|Any CPU.Build.0 = Release|Any CPU
{54377672-20B1-40AF-8087-5CF73BF3953A}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{54377672-20B1-40AF-8087-5CF73BF3953A}.Debug|Any CPU.Build.0 = Debug|Any CPU
{54377672-20B1-40AF-8087-5CF73BF3953A}.Deploy|Any CPU.ActiveCfg = Release|Any CPU
{54377672-20B1-40AF-8087-5CF73BF3953A}.Deploy|Any CPU.Build.0 = Release|Any CPU
{54377672-20B1-40AF-8087-5CF73BF3953A}.Release|Any CPU.ActiveCfg = Release|Any CPU
{54377672-20B1-40AF-8087-5CF73BF3953A}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
@ -75,7 +67,6 @@ Global
{D9A367C9-4C1A-489F-9B05-A0CEA2B53B58} = {0D37A2AD-80A4-464F-A1DE-1560B70F1CE3}
{65DC628F-A640-4111-AB35-3A5652BC1E17} = {7A75DFA2-DE65-4458-98AF-26AF96FFD6DC}
{69051C69-12AE-4E7D-A3E6-460D2E282312} = {0D37A2AD-80A4-464F-A1DE-1560B70F1CE3}
{54377672-20B1-40AF-8087-5CF73BF3953A} = {0D37A2AD-80A4-464F-A1DE-1560B70F1CE3}
EndGlobalSection
GlobalSection(MonoDevelopProperties) = preSolution
Policies = $0