1
0
mirror of https://github.com/ppy/osu.git synced 2024-12-15 04:13:00 +08:00

Merge branch 'master' of git://github.com/ppy/osu into direct-previews

This commit is contained in:
Jorolf 2017-09-17 22:40:14 +02:00
commit f8b09df13c
60 changed files with 1328 additions and 141 deletions

View File

@ -1,3 +1,4 @@
# 2017-09-14
clone_depth: 1
version: '{branch}-{build}'
configuration: Debug

@ -1 +1 @@
Subproject commit f039a8cb707296238d22b6c382af862725c05928
Subproject commit 3f4545aae82650dc87cac7dd5df64e6e47918da1

View File

@ -17,8 +17,8 @@ namespace osu.Desktop.Deploy
{
internal static class Program
{
private const string nuget_path = @"packages\NuGet.CommandLine.4.1.0\tools\NuGet.exe";
private const string squirrel_path = @"packages\squirrel.windows.1.7.5\tools\Squirrel.exe";
private const string nuget_path = @"packages\NuGet.CommandLine.4.3.0\tools\NuGet.exe";
private const string squirrel_path = @"packages\squirrel.windows.1.7.8\tools\Squirrel.exe";
private const string msbuild_path = @"C:\Program Files (x86)\MSBuild\14.0\Bin\MSBuild.exe";
public static string StagingFolder = ConfigurationManager.AppSettings["StagingFolder"];
@ -100,7 +100,7 @@ namespace osu.Desktop.Deploy
updateAssemblyInfo(version);
write("Running build process...");
runCommand(msbuild_path, $"/v:quiet /m /t:{TargetName.Replace('.', '_')} /p:OutputPath={stagingPath};Configuration=Release {SolutionName}.sln");
runCommand(msbuild_path, $"/v:quiet /m /t:{TargetName.Replace('.', '_')} /p:OutputPath={stagingPath};Targets=\"Clean;Build\";Configuration=Release {SolutionName}.sln");
write("Creating NuGet deployment package...");
runCommand(nuget_path, $"pack {NuSpecName} -Version {version} -Properties Configuration=Deploy -OutputDirectory {stagingPath} -BasePath {stagingPath}");

View File

@ -0,0 +1,90 @@
// Copyright (c) 2007-2017 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.Allocation;
using osu.Framework.Configuration;
using osu.Framework.Graphics;
using osu.Framework.Graphics.Containers;
using osu.Framework.Graphics.Shapes;
using osu.Framework.Timing;
using osu.Game;
using osu.Game.Beatmaps;
using osu.Game.Overlays;
using osu.Game.Storyboards.Drawables;
namespace osu.Desktop.Tests.Visual
{
internal class TestCaseStoryboard : OsuTestCase
{
public override string Description => @"Tests storyboards.";
private readonly Bindable<WorkingBeatmap> beatmapBacking = new Bindable<WorkingBeatmap>();
private readonly Container<DrawableStoryboard> storyboardContainer;
private DrawableStoryboard storyboard;
public TestCaseStoryboard()
{
Clock = new FramedClock();
Add(new Container
{
RelativeSizeAxes = Axes.Both,
Children = new Drawable[]
{
new Box
{
RelativeSizeAxes = Axes.Both,
Colour = Color4.Black,
},
storyboardContainer = new Container<DrawableStoryboard>
{
RelativeSizeAxes = Axes.Both,
},
},
});
Add(new MusicController
{
Origin = Anchor.TopRight,
Anchor = Anchor.TopRight,
State = Visibility.Visible,
});
AddStep("Restart", restart);
AddToggleStep("Passing", passing => { if (storyboard != null) storyboard.Passing = passing; });
}
[BackgroundDependencyLoader]
private void load(OsuGameBase game)
{
beatmapBacking.BindTo(game.Beatmap);
beatmapBacking.ValueChanged += beatmapChanged;
}
private void beatmapChanged(WorkingBeatmap working)
=> loadStoryboard(working);
private void restart()
{
var track = beatmapBacking.Value.Track;
track.Reset();
loadStoryboard(beatmapBacking.Value);
track.Start();
}
private void loadStoryboard(WorkingBeatmap working)
{
if (storyboard != null)
storyboardContainer.Remove(storyboard);
var decoupledClock = new DecoupleableInterpolatingFramedClock { IsCoupled = true };
decoupledClock.ChangeSource(working.Track);
storyboardContainer.Clock = decoupledClock;
storyboardContainer.Add(storyboard = working.Beatmap.Storyboard.CreateDrawable());
storyboard.Passing = false;
}
}
}

View File

@ -33,13 +33,10 @@ namespace osu.Desktop.Tests.Visual
Rank = 2148,
PP = 4567.89m
},
AllRankHistories = new User.RankHistories
RankHistory = new User.RankHistoryData
{
Osu = new User.RankHistory
{
Mode = @"osu",
Data = Enumerable.Range(2345,45).Concat(Enumerable.Range(2109,40)).ToArray()
}
Mode = @"osu",
Data = Enumerable.Range(2345, 45).Concat(Enumerable.Range(2109, 40)).ToArray()
}
}, false));
AddStep("Show ppy", () => profile.ShowUser(new User

View File

@ -92,6 +92,7 @@
<Compile Include="Visual\TestCaseMenuButtonSystem.cs" />
<Compile Include="Visual\TestCaseMenuOverlays.cs" />
<Compile Include="Visual\TestCaseMods.cs" />
<Compile Include="Visual\TestCaseStoryboard.cs" />
<Compile Include="Visual\TestCaseMusicController.cs" />
<Compile Include="Visual\TestCaseNotificationOverlay.cs" />
<Compile Include="Visual\TestCaseOnScreenDisplay.cs" />

View File

@ -69,7 +69,8 @@
<DebugType>none</DebugType>
<Optimize>true</Optimize>
<OutputPath>bin\Release\</OutputPath>
<DefineConstants>CuttingEdge NoUpdate</DefineConstants>
<DefineConstants>
</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
<NoStdLib>true</NoStdLib>
@ -104,6 +105,7 @@
<ErrorReport>prompt</ErrorReport>
<CodeAnalysisRuleSet>AllRules.ruleset</CodeAnalysisRuleSet>
<StartArguments>--tests</StartArguments>
<Prefer32Bit>false</Prefer32Bit>
</PropertyGroup>
<ItemGroup>
<Reference Include="DeltaCompressionDotNet, Version=1.1.0.0, Culture=neutral, PublicKeyToken=1d14d6e5194e7f4a, processorArchitecture=MSIL">

View File

@ -4,6 +4,9 @@
using osu.Game.Graphics;
using osu.Game.Rulesets.Mods;
using System;
using System.Linq;
using osu.Framework.Extensions.IEnumerableExtensions;
using osu.Framework.MathUtils;
using osu.Game.Beatmaps;
using osu.Game.Rulesets.Mania.Objects;
using osu.Game.Rulesets.Mania.Replays;
@ -83,12 +86,22 @@ namespace osu.Game.Rulesets.Mania.Mods
public override Type[] IncompatibleMods => new[] { typeof(ModFlashlight) };
}
public class ManiaModRandom : Mod
public class ManiaModRandom : Mod, IApplicableMod<ManiaHitObject>
{
public override string Name => "Random";
public override string ShortenedName => "RD";
public override FontAwesome Icon => FontAwesome.fa_osu_dice;
public override string Description => @"Shuffle around the notes!";
public override double ScoreMultiplier => 1;
public void ApplyToRulesetContainer(RulesetContainer<ManiaHitObject> rulesetContainer)
{
int availableColumns = ((ManiaRulesetContainer)rulesetContainer).AvailableColumns;
var shuffledColumns = Enumerable.Range(0, availableColumns).OrderBy(item => RNG.Next()).ToList();
rulesetContainer.Objects.OfType<ManiaHitObject>().ForEach(h => h.Column = shuffledColumns[h.Column]);
}
}
public abstract class ManiaKeyMod : Mod

View File

@ -8,6 +8,7 @@ using System.Collections.Generic;
using System.Linq;
using osu.Game.Beatmaps.ControlPoints;
using osu.Game.IO.Serialization;
using osu.Game.Storyboards;
namespace osu.Game.Beatmaps
{
@ -40,6 +41,11 @@ namespace osu.Game.Beatmaps
/// </summary>
public double TotalBreakTime => Breaks.Sum(b => b.Duration);
/// <summary>
/// The Beatmap's Storyboard.
/// </summary>
public Storyboard Storyboard = new Storyboard();
/// <summary>
/// Constructs a new beatmap.
/// </summary>
@ -51,6 +57,7 @@ namespace osu.Game.Beatmaps
Breaks = original?.Breaks ?? Breaks;
ComboColors = original?.ComboColors ?? ComboColors;
HitObjects = original?.HitObjects ?? HitObjects;
Storyboard = original?.Storyboard ?? Storyboard;
}
}

View File

@ -10,6 +10,10 @@ using osu.Game.Beatmaps.Timing;
using osu.Game.Beatmaps.Legacy;
using osu.Game.Rulesets.Objects.Legacy;
using osu.Game.Beatmaps.ControlPoints;
using osu.Game.Storyboards;
using OpenTK;
using osu.Framework.Graphics;
using osu.Framework.IO.File;
namespace osu.Game.Beatmaps.Formats
{
@ -238,42 +242,231 @@ namespace osu.Game.Beatmaps.Formats
}
}
private void handleEvents(Beatmap beatmap, string line)
private void handleEvents(Beatmap beatmap, string line, ref StoryboardSprite storyboardSprite, ref CommandTimelineGroup timelineGroup)
{
var depth = 0;
while (line.StartsWith(" ") || line.StartsWith("_"))
{
++depth;
line = line.Substring(1);
}
decodeVariables(ref line);
string[] split = line.Split(',');
EventType type;
if (!Enum.TryParse(split[0], out type))
throw new InvalidDataException($@"Unknown event type {split[0]}");
// Todo: Implement the rest
switch (type)
if (depth == 0)
{
case EventType.Video:
case EventType.Background:
string filename = split[2].Trim('"');
storyboardSprite = null;
if (type == EventType.Background)
beatmap.BeatmapInfo.Metadata.BackgroundFile = filename;
EventType type;
if (!Enum.TryParse(split[0], out type))
throw new InvalidDataException($@"Unknown event type {split[0]}");
break;
case EventType.Break:
var breakEvent = new BreakPeriod
{
StartTime = double.Parse(split[1], NumberFormatInfo.InvariantInfo),
EndTime = double.Parse(split[2], NumberFormatInfo.InvariantInfo)
};
switch (type)
{
case EventType.Video:
case EventType.Background:
string filename = split[2].Trim('"');
if (!breakEvent.HasEffect)
return;
if (type == EventType.Background)
beatmap.BeatmapInfo.Metadata.BackgroundFile = filename;
beatmap.Breaks.Add(breakEvent);
break;
break;
case EventType.Break:
var breakEvent = new BreakPeriod
{
StartTime = double.Parse(split[1], NumberFormatInfo.InvariantInfo),
EndTime = double.Parse(split[2], NumberFormatInfo.InvariantInfo)
};
if (!breakEvent.HasEffect)
return;
beatmap.Breaks.Add(breakEvent);
break;
case EventType.Sprite:
{
var layer = parseLayer(split[1]);
var origin = parseOrigin(split[2]);
var path = cleanFilename(split[3]);
var x = float.Parse(split[4], NumberFormatInfo.InvariantInfo);
var y = float.Parse(split[5], NumberFormatInfo.InvariantInfo);
storyboardSprite = new StoryboardSprite(path, origin, new Vector2(x, y));
beatmap.Storyboard.GetLayer(layer).Add(storyboardSprite);
}
break;
case EventType.Animation:
{
var layer = parseLayer(split[1]);
var origin = parseOrigin(split[2]);
var path = cleanFilename(split[3]);
var x = float.Parse(split[4], NumberFormatInfo.InvariantInfo);
var y = float.Parse(split[5], NumberFormatInfo.InvariantInfo);
var frameCount = int.Parse(split[6]);
var frameDelay = double.Parse(split[7], NumberFormatInfo.InvariantInfo);
var loopType = split.Length > 8 ? (AnimationLoopType)Enum.Parse(typeof(AnimationLoopType), split[8]) : AnimationLoopType.LoopForever;
storyboardSprite = new StoryboardAnimation(path, origin, new Vector2(x, y), frameCount, frameDelay, loopType);
beatmap.Storyboard.GetLayer(layer).Add(storyboardSprite);
}
break;
case EventType.Sample:
{
var time = double.Parse(split[1], CultureInfo.InvariantCulture);
var layer = parseLayer(split[2]);
var path = cleanFilename(split[3]);
var volume = split.Length > 4 ? float.Parse(split[4], CultureInfo.InvariantCulture) : 100;
beatmap.Storyboard.GetLayer(layer).Add(new StoryboardSample(path, time, volume));
}
break;
}
}
else
{
if (depth < 2)
timelineGroup = storyboardSprite?.TimelineGroup;
var commandType = split[0];
switch (commandType)
{
case "T":
{
var triggerName = split[1];
var startTime = split.Length > 2 ? double.Parse(split[2], CultureInfo.InvariantCulture) : double.MinValue;
var endTime = split.Length > 3 ? double.Parse(split[3], CultureInfo.InvariantCulture) : double.MaxValue;
var groupNumber = split.Length > 4 ? int.Parse(split[4]) : 0;
timelineGroup = storyboardSprite?.AddTrigger(triggerName, startTime, endTime, groupNumber);
}
break;
case "L":
{
var startTime = double.Parse(split[1], CultureInfo.InvariantCulture);
var loopCount = int.Parse(split[2]);
timelineGroup = storyboardSprite?.AddLoop(startTime, loopCount);
}
break;
default:
{
if (string.IsNullOrEmpty(split[3]))
split[3] = split[2];
var easing = (Easing)int.Parse(split[1]);
var startTime = double.Parse(split[2], CultureInfo.InvariantCulture);
var endTime = double.Parse(split[3], CultureInfo.InvariantCulture);
switch (commandType)
{
case "F":
{
var startValue = float.Parse(split[4], CultureInfo.InvariantCulture);
var endValue = split.Length > 5 ? float.Parse(split[5], CultureInfo.InvariantCulture) : startValue;
timelineGroup?.Alpha.Add(easing, startTime, endTime, startValue, endValue);
}
break;
case "S":
{
var startValue = float.Parse(split[4], CultureInfo.InvariantCulture);
var endValue = split.Length > 5 ? float.Parse(split[5], CultureInfo.InvariantCulture) : startValue;
timelineGroup?.Scale.Add(easing, startTime, endTime, new Vector2(startValue), new Vector2(endValue));
}
break;
case "V":
{
var startX = float.Parse(split[4], CultureInfo.InvariantCulture);
var startY = float.Parse(split[5], CultureInfo.InvariantCulture);
var endX = split.Length > 6 ? float.Parse(split[6], CultureInfo.InvariantCulture) : startX;
var endY = split.Length > 7 ? float.Parse(split[7], CultureInfo.InvariantCulture) : startY;
timelineGroup?.Scale.Add(easing, startTime, endTime, new Vector2(startX, startY), new Vector2(endX, endY));
}
break;
case "R":
{
var startValue = float.Parse(split[4], CultureInfo.InvariantCulture);
var endValue = split.Length > 5 ? float.Parse(split[5], CultureInfo.InvariantCulture) : startValue;
timelineGroup?.Rotation.Add(easing, startTime, endTime, MathHelper.RadiansToDegrees(startValue), MathHelper.RadiansToDegrees(endValue));
}
break;
case "M":
{
var startX = float.Parse(split[4], CultureInfo.InvariantCulture);
var startY = float.Parse(split[5], CultureInfo.InvariantCulture);
var endX = split.Length > 6 ? float.Parse(split[6], CultureInfo.InvariantCulture) : startX;
var endY = split.Length > 7 ? float.Parse(split[7], CultureInfo.InvariantCulture) : startY;
timelineGroup?.X.Add(easing, startTime, endTime, startX, endX);
timelineGroup?.Y.Add(easing, startTime, endTime, startY, endY);
}
break;
case "MX":
{
var startValue = float.Parse(split[4], CultureInfo.InvariantCulture);
var endValue = split.Length > 5 ? float.Parse(split[5], CultureInfo.InvariantCulture) : startValue;
timelineGroup?.X.Add(easing, startTime, endTime, startValue, endValue);
}
break;
case "MY":
{
var startValue = float.Parse(split[4], CultureInfo.InvariantCulture);
var endValue = split.Length > 5 ? float.Parse(split[5], CultureInfo.InvariantCulture) : startValue;
timelineGroup?.Y.Add(easing, startTime, endTime, startValue, endValue);
}
break;
case "C":
{
var startRed = float.Parse(split[4], CultureInfo.InvariantCulture);
var startGreen = float.Parse(split[5], CultureInfo.InvariantCulture);
var startBlue = float.Parse(split[6], CultureInfo.InvariantCulture);
var endRed = split.Length > 7 ? float.Parse(split[7], CultureInfo.InvariantCulture) : startRed;
var endGreen = split.Length > 8 ? float.Parse(split[8], CultureInfo.InvariantCulture) : startGreen;
var endBlue = split.Length > 9 ? float.Parse(split[9], CultureInfo.InvariantCulture) : startBlue;
timelineGroup?.Colour.Add(easing, startTime, endTime,
new Color4(startRed / 255f, startGreen / 255f, startBlue / 255f, 1),
new Color4(endRed / 255f, endGreen / 255f, endBlue / 255f, 1));
}
break;
case "P":
{
var type = split[4];
switch (type)
{
case "A": timelineGroup?.BlendingMode.Add(easing, startTime, endTime, BlendingMode.Additive, startTime == endTime ? BlendingMode.Additive : BlendingMode.Inherit); break;
case "H": timelineGroup?.FlipH.Add(easing, startTime, endTime, true, startTime == endTime); break;
case "V": timelineGroup?.FlipV.Add(easing, startTime, endTime, true, startTime == endTime); break;
}
}
break;
default:
throw new InvalidDataException($@"Unknown command type: {commandType}");
}
}
break;
}
}
}
private static string cleanFilename(string path)
=> FileSafety.PathStandardise(path.Trim('\"'));
private static Anchor parseOrigin(string value)
{
var origin = (LegacyOrigins)Enum.Parse(typeof(LegacyOrigins), value);
switch (origin)
{
case LegacyOrigins.TopLeft: return Anchor.TopLeft;
case LegacyOrigins.TopCentre: return Anchor.TopCentre;
case LegacyOrigins.TopRight: return Anchor.TopRight;
case LegacyOrigins.CentreLeft: return Anchor.CentreLeft;
case LegacyOrigins.Centre: return Anchor.Centre;
case LegacyOrigins.CentreRight: return Anchor.CentreRight;
case LegacyOrigins.BottomLeft: return Anchor.BottomLeft;
case LegacyOrigins.BottomCentre: return Anchor.BottomCentre;
case LegacyOrigins.BottomRight: return Anchor.BottomRight;
}
throw new InvalidDataException($@"Unknown origin: {value}");
}
private static string parseLayer(string value)
=> Enum.Parse(typeof(StoryLayer), value).ToString();
private void handleTimingPoints(Beatmap beatmap, string line)
{
string[] split = line.Split(',');
@ -414,6 +607,8 @@ namespace osu.Game.Beatmaps.Formats
Section section = Section.None;
bool hasCustomColours = false;
StoryboardSprite storyboardSprite = null;
CommandTimelineGroup timelineGroup = null;
string line;
while ((line = stream.ReadLine()) != null)
@ -421,7 +616,7 @@ namespace osu.Game.Beatmaps.Formats
if (string.IsNullOrEmpty(line))
continue;
if (line.StartsWith(" ") || line.StartsWith("_") || line.StartsWith("//"))
if (line.StartsWith("//"))
continue;
if (line.StartsWith(@"osu file format v"))
@ -452,7 +647,7 @@ namespace osu.Game.Beatmaps.Formats
handleDifficulty(beatmap, line);
break;
case Section.Events:
handleEvents(beatmap, line);
handleEvents(beatmap, line, ref storyboardSprite, ref timelineGroup);
break;
case Section.TimingPoints:
handleTimingPoints(beatmap, line);
@ -509,5 +704,27 @@ namespace osu.Game.Beatmaps.Formats
Sample = 5,
Animation = 6
}
internal enum LegacyOrigins
{
TopLeft,
Centre,
CentreLeft,
TopRight,
BottomCentre,
TopCentre,
Custom,
CentreRight,
BottomLeft,
BottomRight
};
internal enum StoryLayer
{
Background = 0,
Fail = 1,
Pass = 2,
Foreground = 3
}
}
}

View File

@ -100,8 +100,11 @@ namespace osu.Game.Beatmaps
public void TransferTo(WorkingBeatmap other)
{
if (track != null && BeatmapInfo.AudioEquals(other.BeatmapInfo))
other.track = track;
lock (trackLock)
{
if (track != null && BeatmapInfo.AudioEquals(other.BeatmapInfo))
other.track = track;
}
if (background != null && BeatmapInfo.BackgroundEquals(other.BeatmapInfo))
other.background = background;

View File

@ -1,6 +1,7 @@
// Copyright (c) 2007-2017 ppy Pty Ltd <contact@ppy.sh>.
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
using System.Collections.Generic;
using OpenTK.Graphics;
using osu.Framework.Allocation;
using osu.Framework.Audio;
@ -112,7 +113,7 @@ namespace osu.Game.Graphics.UserInterface
return base.OnMouseUp(state, args);
}
public string[] FilterTerms => new[] { Text };
public IEnumerable<string> FilterTerms => new[] { Text };
public bool MatchingFilter
{

View File

@ -27,42 +27,45 @@ namespace osu.Game.Online.API
internal bool AuthenticateWithLogin(string username, string password)
{
var req = new AccessTokenRequestPassword(username, password)
using (var req = new AccessTokenRequestPassword(username, password)
{
Url = $@"{endpoint}/oauth/token",
Method = HttpMethod.POST,
ClientId = clientId,
ClientSecret = clientSecret
};
try
})
{
req.BlockingPerform();
}
catch
{
return false;
}
try
{
req.BlockingPerform();
}
catch
{
return false;
}
Token = req.ResponseObject;
return true;
Token = req.ResponseObject;
return true;
}
}
internal bool AuthenticateWithRefresh(string refresh)
{
try
{
var req = new AccessTokenRequestRefresh(refresh)
using (var req = new AccessTokenRequestRefresh(refresh)
{
Url = $@"{endpoint}/oauth/token",
Method = HttpMethod.POST,
ClientId = clientId,
ClientSecret = clientSecret
};
req.BlockingPerform();
})
{
req.BlockingPerform();
Token = req.ResponseObject;
return true;
Token = req.ResponseObject;
return true;
}
}
catch
{

View File

@ -5,7 +5,6 @@ using System;
using System.Collections.Generic;
using System.Linq;
using Newtonsoft.Json;
using osu.Framework.IO.Network;
using osu.Game.Beatmaps;
using osu.Game.Users;
using osu.Game.Rulesets.Replays;
@ -19,6 +18,9 @@ namespace osu.Game.Online.API.Requests
public GetScoresRequest(BeatmapInfo beatmap)
{
if (!beatmap.OnlineBeatmapID.HasValue)
throw new InvalidOperationException($"Cannot lookup a beatmap's scores without having a populated {nameof(BeatmapInfo.OnlineBeatmapID)}.");
this.beatmap = beatmap;
Success += onSuccess;
@ -30,14 +32,6 @@ namespace osu.Game.Online.API.Requests
score.ApplyBeatmap(beatmap);
}
protected override WebRequest CreateWebRequest()
{
var req = base.CreateWebRequest();
//req.AddParameter(@"c", beatmap.Hash);
//req.AddParameter(@"f", beatmap.Path);
return req;
}
protected override string Target => $@"beatmaps/{beatmap.OnlineBeatmapID}/scores";
}

View File

@ -200,10 +200,9 @@ namespace osu.Game
globalBinding = new GlobalKeyBindingInputManager(this)
{
RelativeSizeAxes = Axes.Both,
Child = new OsuTooltipContainer(Cursor)
Child = content = new OsuTooltipContainer(Cursor)
{
RelativeSizeAxes = Axes.Both,
Child = content = new OsuContextMenuContainer { RelativeSizeAxes = Axes.Both },
}
}
}

View File

@ -2,6 +2,7 @@
// 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;
@ -34,7 +35,7 @@ namespace osu.Game.Overlays.Chat
private Color4 topicColour;
private Color4 hoverColour;
public string[] FilterTerms => new[] { channel.Name };
public IEnumerable<string> FilterTerms => new[] { channel.Name };
public bool MatchingFilter
{
set

View File

@ -18,7 +18,7 @@ namespace osu.Game.Overlays.Chat
public readonly FillFlowContainer<ChannelListItem> ChannelFlow;
public IEnumerable<IFilterable> FilterableChildren => ChannelFlow.Children;
public string[] FilterTerms => new[] { Header };
public IEnumerable<string> FilterTerms => new[] { Header };
public bool MatchingFilter
{
set

View File

@ -1,7 +1,6 @@
// Copyright (c) 2007-2017 ppy Pty Ltd <contact@ppy.sh>.
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
using System;
using OpenTK;
using OpenTK.Graphics;
using osu.Framework.Allocation;
@ -13,6 +12,9 @@ using osu.Game.Graphics.Containers;
using osu.Game.Graphics.Sprites;
using osu.Game.Online.Chat;
using osu.Game.Users;
using osu.Framework.Graphics.Cursor;
using osu.Framework.Graphics.UserInterface;
using osu.Game.Graphics.UserInterface;
namespace osu.Game.Overlays.Chat
{
@ -63,8 +65,6 @@ namespace osu.Game.Overlays.Chat
private const float message_padding = 200;
private const float text_size = 20;
private Action<User> loadProfile;
private Color4 customUsernameColour;
private OsuSpriteText timestamp;
@ -100,10 +100,9 @@ namespace osu.Game.Overlays.Chat
}
[BackgroundDependencyLoader(true)]
private void load(OsuColour colours, UserProfileOverlay profile)
private void load(OsuColour colours)
{
customUsernameColour = colours.ChatBlue;
loadProfile = u => profile?.ShowUser(u);
}
private bool senderHasBackground => !string.IsNullOrEmpty(message.Sender.Colour);
@ -171,13 +170,12 @@ namespace osu.Game.Overlays.Chat
FixedWidth = true,
TextSize = text_size * 0.75f,
},
new ClickableContainer
new MessageSender(message.Sender)
{
AutoSizeAxes = Axes.Both,
Origin = Anchor.TopRight,
Anchor = Anchor.TopRight,
Child = effectedUsername,
Action = () => loadProfile(message.Sender),
},
}
},
@ -210,5 +208,26 @@ namespace osu.Game.Overlays.Chat
username.Text = $@"{message.Sender.Username}" + (senderHasBackground ? "" : ":");
contentFlow.Text = message.Content;
}
private class MessageSender : ClickableContainer, IHasContextMenu
{
private readonly User sender;
public MessageSender(User sender)
{
this.sender = sender;
}
[BackgroundDependencyLoader(true)]
private void load(UserProfileOverlay profile)
{
Action = () => profile?.ShowUser(sender);
}
public MenuItem[] ContextMenuItems => new MenuItem[]
{
new OsuMenuItem("View Profile", MenuItemType.Highlighted, Action),
};
}
}
}

View File

@ -10,23 +10,13 @@ using osu.Framework.Allocation;
using osu.Framework.Graphics;
using osu.Framework.Graphics.Containers;
using osu.Game.Graphics.Containers;
using osu.Game.Graphics.Cursor;
using osu.Game.Online.Chat;
namespace osu.Game.Overlays.Chat
{
public class DrawableChannel : Container
{
private class ChatLineContainer : FillFlowContainer<ChatLine>
{
protected override int Compare(Drawable x, Drawable y)
{
var xC = (ChatLine)x;
var yC = (ChatLine)y;
return xC.Message.CompareTo(yC.Message);
}
}
public readonly Channel Channel;
private readonly ChatLineContainer flow;
private readonly ScrollContainer scroll;
@ -45,12 +35,17 @@ namespace osu.Game.Overlays.Chat
// Some chat lines have effects that slightly protrude to the bottom,
// which we do not want to mask away, hence the padding.
Padding = new MarginPadding { Bottom = 5 },
Child = flow = new ChatLineContainer
Child = new OsuContextMenuContainer
{
Padding = new MarginPadding { Left = 20, Right = 20 },
RelativeSizeAxes = Axes.X,
AutoSizeAxes = Axes.Y,
Direction = FillDirection.Vertical,
Child = flow = new ChatLineContainer
{
Padding = new MarginPadding { Left = 20, Right = 20 },
RelativeSizeAxes = Axes.X,
AutoSizeAxes = Axes.Y,
Direction = FillDirection.Vertical,
}
},
}
};
@ -124,5 +119,16 @@ namespace osu.Game.Overlays.Chat
}
private void scrollToEnd() => ScheduleAfterChildren(() => scroll.ScrollToEnd());
private class ChatLineContainer : FillFlowContainer<ChatLine>
{
protected override int Compare(Drawable x, Drawable y)
{
var xC = (ChatLine)x;
var yC = (ChatLine)y;
return xC.Message.CompareTo(yC.Message);
}
}
}
}

View File

@ -47,7 +47,7 @@ namespace osu.Game.Overlays.KeyBinding
private FillFlowContainer<KeyButton> buttons;
public string[] FilterTerms => new[] { text.Text }.Concat(bindings.Select(b => b.KeyCombination.ReadableString())).ToArray();
public IEnumerable<string> FilterTerms => new[] { text.Text }.Concat(bindings.Select(b => b.KeyCombination.ReadableString()));
public KeyBindingRow(object action, IEnumerable<Framework.Input.Bindings.KeyBinding> bindings)
{
@ -371,4 +371,4 @@ namespace osu.Game.Overlays.KeyBinding
}
}
}
}
}

View File

@ -3,12 +3,12 @@
using osu.Framework.Allocation;
using osu.Framework.Graphics;
using osu.Framework.Graphics.Containers;
using osu.Game.Graphics;
using osu.Game.Overlays.Settings.Sections.General;
using OpenTK.Graphics;
using osu.Framework.Graphics.Shapes;
using osu.Game.Graphics.Containers;
using osu.Game.Graphics.Cursor;
namespace osu.Game.Overlays
{
@ -34,7 +34,7 @@ namespace osu.Game.Overlays
Colour = Color4.Black,
Alpha = 0.6f,
},
new Container
new OsuContextMenuContainer
{
Width = 360,
AutoSizeAxes = Axes.Y,

View File

@ -129,7 +129,7 @@ namespace osu.Game.Overlays.Music
return true;
}
public string[] FilterTerms { get; private set; }
public IEnumerable<string> FilterTerms { get; private set; }
private bool matching = true;

View File

@ -229,7 +229,7 @@ namespace osu.Game.Overlays.Music
private class ItemSearchContainer : FillFlowContainer<PlaylistItem>, IHasFilterableChildren
{
public string[] FilterTerms => new string[] { };
public IEnumerable<string> FilterTerms => new string[] { };
public bool MatchingFilter
{
set

View File

@ -70,7 +70,7 @@ namespace osu.Game.Overlays.Profile
}
};
ranks = user.AllRankHistories?.Osu?.Data ?? new[] { user.Statistics.Rank };
ranks = user.RankHistory?.Data ?? new[] { user.Statistics.Rank };
}
private void updateRankTexts()

View File

@ -28,7 +28,7 @@ namespace osu.Game.Overlays.Settings.Sections.Debug
{
RelativeSizeAxes = Axes.X,
Text = "Force garbage collection",
Action = () => GC.Collect()
Action = GC.Collect
},
};
}

View File

@ -366,10 +366,6 @@ namespace osu.Game.Overlays.Settings.Sections.General
BackgroundColour = colours.Gray3;
}
}
}
private enum UserAction

View File

@ -27,7 +27,7 @@ namespace osu.Game.Overlays.Settings.Sections.General
{
RelativeSizeAxes = Axes.X,
Text = "Open osu! folder",
Action = () => storage.OpenInNativeExplorer(),
Action = storage.OpenInNativeExplorer,
}
};
}

View File

@ -18,7 +18,7 @@ namespace osu.Game.Overlays.Settings.Sections.Input
{
RelativeSizeAxes = Axes.X,
Text = "Key Configuration",
Action = () => keyConfig.ToggleVisibility()
Action = keyConfig.ToggleVisibility
},
};
}

View File

@ -1,6 +1,7 @@
// Copyright (c) 2007-2017 ppy Pty Ltd <contact@ppy.sh>.
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
using System.Collections.Generic;
using OpenTK.Graphics;
using osu.Framework.Configuration;
using osu.Framework.Graphics;
@ -53,7 +54,7 @@ namespace osu.Game.Overlays.Settings
}
}
public string[] FilterTerms => new[] { LabelText };
public IEnumerable<string> FilterTerms => new[] { LabelText };
public bool MatchingFilter
{

View File

@ -23,7 +23,7 @@ namespace osu.Game.Overlays.Settings
public abstract string Header { get; }
public IEnumerable<IFilterable> FilterableChildren => Children.OfType<IFilterable>();
public string[] FilterTerms => new[] { Header };
public IEnumerable<string> FilterTerms => new[] { Header };
private const int header_size = 26;
private const int header_margin = 25;

View File

@ -20,7 +20,7 @@ namespace osu.Game.Overlays.Settings
protected abstract string Header { get; }
public IEnumerable<IFilterable> FilterableChildren => Children.OfType<IFilterable>();
public string[] FilterTerms => new[] { Header };
public IEnumerable<string> FilterTerms => new[] { Header };
public bool MatchingFilter
{
set

View File

@ -9,6 +9,7 @@ using OpenTK.Graphics;
using osu.Framework.Graphics;
using osu.Framework.Graphics.Containers;
using osu.Game.Graphics;
using osu.Game.Graphics.Cursor;
using osu.Game.Graphics.UserInterface;
using osu.Game.Online.API;
using osu.Game.Online.API.Requests;
@ -63,12 +64,17 @@ namespace osu.Game.Overlays
ScrollFlow.Children = new[]
{
panelFlow = new FillFlowContainer<UserPanel>
new OsuContextMenuContainer
{
RelativeSizeAxes = Axes.X,
AutoSizeAxes = Axes.Y,
Margin = new MarginPadding { Top = 20 },
Spacing = new Vector2(10f),
Child = panelFlow = new FillFlowContainer<UserPanel>
{
RelativeSizeAxes = Axes.X,
AutoSizeAxes = Axes.Y,
Margin = new MarginPadding { Top = 20 },
Spacing = new Vector2(10f),
}
},
};

View File

@ -50,7 +50,7 @@ namespace osu.Game.Screens.Menu
OnEdit = delegate { Push(new Editor()); },
OnSolo = delegate { Push(consumeSongSelect()); },
OnMulti = delegate { Push(new Lobby()); },
OnExit = delegate { Exit(); },
OnExit = Exit,
}
}
},

View File

@ -108,8 +108,11 @@ namespace osu.Game.Screens.Play
private void pushWhenLoaded()
{
if (!player.IsLoaded)
if (player.LoadState != LoadState.Ready)
{
Schedule(pushWhenLoaded);
return;
}
contentOut();

View File

@ -3,6 +3,7 @@
using System.Linq;
using System.Collections.Generic;
using System.Diagnostics;
using osu.Game.Rulesets.Objects.Types;
using osu.Game.Rulesets.Objects;
@ -34,10 +35,12 @@ namespace osu.Game.Screens.Play
foreach (var h in objects)
{
IHasEndTime end = h as IHasEndTime;
var endTime = (h as IHasEndTime)?.EndTime ?? h.StartTime;
Debug.Assert(endTime >= h.StartTime);
int startRange = (int)((h.StartTime - firstHit) / interval);
int endRange = (int)(((end?.EndTime > 0 ? end.EndTime : h.StartTime) - firstHit) / interval);
int endRange = (int)((endTime - firstHit) / interval);
for (int i = startRange; i <= endRange; i++)
Values[i]++;
}

View File

@ -19,6 +19,7 @@ using osu.Framework.Threading;
using osu.Framework.Configuration;
using osu.Game.Beatmaps;
using osu.Game.Graphics.Containers;
using osu.Game.Graphics.Cursor;
namespace osu.Game.Screens.Select
{
@ -86,9 +87,14 @@ namespace osu.Game.Screens.Select
public BeatmapCarousel()
{
Add(scrollableContent = new Container<Panel>
Add(new OsuContextMenuContainer
{
RelativeSizeAxes = Axes.X,
AutoSizeAxes = Axes.Y,
Child = scrollableContent = new Container<Panel>
{
RelativeSizeAxes = Axes.X,
}
});
}

View File

@ -130,7 +130,7 @@ namespace osu.Game.Screens.Select.Leaderboards
Scores = null;
getScoresRequest?.Cancel();
if (api == null || Beatmap == null) return;
if (api == null || Beatmap?.OnlineBeatmapID == null) return;
loading.Show();

View File

@ -106,7 +106,7 @@ namespace osu.Game.Screens.Select
Origin = Anchor.CentreRight,
SelectionChanged = carouselSelectionChanged,
BeatmapsChanged = carouselBeatmapsLoaded,
DeleteRequested = b => promptDelete(b),
DeleteRequested = promptDelete,
RestoreRequested = s => { foreach (var b in s.Beatmaps) manager.Restore(b); },
HideDifficultyRequested = b => manager.Hide(b),
StartRequested = () => carouselRaisedStart(),

View File

@ -237,7 +237,7 @@ namespace osu.Game.Screens.Tournament
RelativeSizeAxes = Axes.X,
Text = "Reset",
Action = () => reset(false)
Action = () => reset()
}
}
}

View File

@ -0,0 +1,35 @@
// Copyright (c) 2007-2017 ppy Pty Ltd <contact@ppy.sh>.
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
using System.Collections.Generic;
namespace osu.Game.Storyboards
{
public class CommandLoop : CommandTimelineGroup
{
public double LoopStartTime;
public int LoopCount;
public override double StartTime => LoopStartTime;
public override double EndTime => LoopStartTime + CommandsDuration * LoopCount;
public CommandLoop(double startTime, int loopCount)
{
LoopStartTime = startTime;
LoopCount = loopCount;
}
public override IEnumerable<CommandTimeline<T>.TypedCommand> GetCommands<T>(CommandTimelineSelector<T> timelineSelector, double offset = 0)
{
for (var loop = 0; loop < LoopCount; loop++)
{
var loopOffset = LoopStartTime + loop * CommandsDuration;
foreach (var command in base.GetCommands(timelineSelector, offset + loopOffset))
yield return command;
}
}
public override string ToString()
=> $"{LoopStartTime} x{LoopCount}";
}
}

View File

@ -0,0 +1,77 @@
// Copyright (c) 2007-2017 ppy Pty Ltd <contact@ppy.sh>.
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
using osu.Framework.Caching;
using osu.Framework.Graphics;
using System;
using System.Collections.Generic;
using System.Linq;
namespace osu.Game.Storyboards
{
public class CommandTimeline<T> : ICommandTimeline
{
private readonly List<TypedCommand> commands = new List<TypedCommand>();
public IEnumerable<TypedCommand> Commands => commands.OrderBy(c => c.StartTime);
public bool HasCommands => commands.Count > 0;
private Cached<double> startTimeBacking;
public double StartTime => startTimeBacking.IsValid ? startTimeBacking : (startTimeBacking.Value = HasCommands ? commands.Min(c => c.StartTime) : double.MinValue);
private Cached<double> endTimeBacking;
public double EndTime => endTimeBacking.IsValid ? endTimeBacking : (endTimeBacking.Value = HasCommands ? commands.Max(c => c.EndTime) : double.MaxValue);
public T StartValue => HasCommands ? commands.OrderBy(c => c.StartTime).First().StartValue : default(T);
public T EndValue => HasCommands ? commands.OrderByDescending(c => c.EndTime).First().EndValue : default(T);
public void Add(Easing easing, double startTime, double endTime, T startValue, T endValue)
{
if (endTime < startTime)
return;
commands.Add(new TypedCommand { Easing = easing, StartTime = startTime, EndTime = endTime, StartValue = startValue, EndValue = endValue, });
startTimeBacking.Invalidate();
endTimeBacking.Invalidate();
}
public override string ToString()
=> $"{commands.Count} command(s)";
public class TypedCommand : ICommand
{
public Easing Easing { get; set; }
public double StartTime { get; set; }
public double EndTime { get; set; }
public double Duration => EndTime - StartTime;
public T StartValue;
public T EndValue;
public int CompareTo(ICommand other)
{
var result = StartTime.CompareTo(other.StartTime);
if (result != 0) return result;
return EndTime.CompareTo(other.EndTime);
}
public override string ToString()
=> $"{StartTime} -> {EndTime}, {StartValue} -> {EndValue} {Easing}";
}
}
public interface ICommandTimeline
{
double StartTime { get; }
double EndTime { get; }
bool HasCommands { get; }
}
public interface ICommand : IComparable<ICommand>
{
Easing Easing { get; set; }
double StartTime { get; set; }
double EndTime { get; set; }
double Duration { get; }
}
}

View File

@ -0,0 +1,68 @@
// Copyright (c) 2007-2017 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 System.Collections.Generic;
using System.Linq;
namespace osu.Game.Storyboards
{
public delegate CommandTimeline<T> CommandTimelineSelector<T>(CommandTimelineGroup commandTimelineGroup);
public class CommandTimelineGroup
{
public CommandTimeline<float> X = new CommandTimeline<float>();
public CommandTimeline<float> Y = new CommandTimeline<float>();
public CommandTimeline<Vector2> Scale = new CommandTimeline<Vector2>();
public CommandTimeline<float> Rotation = new CommandTimeline<float>();
public CommandTimeline<Color4> Colour = new CommandTimeline<Color4>();
public CommandTimeline<float> Alpha = new CommandTimeline<float>();
public CommandTimeline<BlendingMode> BlendingMode = new CommandTimeline<BlendingMode>();
public CommandTimeline<bool> FlipH = new CommandTimeline<bool>();
public CommandTimeline<bool> FlipV = new CommandTimeline<bool>();
public IEnumerable<ICommandTimeline> Timelines
{
get
{
yield return X;
yield return Y;
yield return Scale;
yield return Rotation;
yield return Colour;
yield return Alpha;
yield return BlendingMode;
yield return FlipH;
yield return FlipV;
}
}
public double CommandsStartTime => Timelines.Where(t => t.HasCommands).Min(t => t.StartTime);
public double CommandsEndTime => Timelines.Where(t => t.HasCommands).Max(t => t.EndTime);
public double CommandsDuration => CommandsEndTime - CommandsStartTime;
public virtual double StartTime => CommandsStartTime;
public virtual double EndTime => CommandsEndTime;
public double Duration => EndTime - StartTime;
public bool HasCommands => Timelines.Any(t => t.HasCommands);
public virtual IEnumerable<CommandTimeline<T>.TypedCommand> GetCommands<T>(CommandTimelineSelector<T> timelineSelector, double offset = 0)
{
if (offset != 0)
return timelineSelector(this).Commands.Select(command =>
new CommandTimeline<T>.TypedCommand
{
Easing = command.Easing,
StartTime = offset + command.StartTime,
EndTime = offset + command.EndTime,
StartValue = command.StartValue,
EndValue = command.EndValue,
});
return timelineSelector(this).Commands;
}
}
}

View File

@ -0,0 +1,24 @@
// Copyright (c) 2007-2017 ppy Pty Ltd <contact@ppy.sh>.
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
namespace osu.Game.Storyboards
{
public class CommandTrigger : CommandTimelineGroup
{
public string TriggerName;
public double TriggerStartTime;
public double TriggerEndTime;
public int GroupNumber;
public CommandTrigger(string triggerName, double startTime, double endTime, int groupNumber)
{
TriggerName = triggerName;
TriggerStartTime = startTime;
TriggerEndTime = endTime;
GroupNumber = groupNumber;
}
public override string ToString()
=> $"{TriggerName} {TriggerStartTime} -> {TriggerEndTime} ({GroupNumber})";
}
}

View File

@ -0,0 +1,59 @@
// Copyright (c) 2007-2017 ppy Pty Ltd <contact@ppy.sh>.
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
using OpenTK;
using osu.Framework.Allocation;
using osu.Framework.Graphics;
using osu.Framework.Graphics.Containers;
using osu.Framework.Graphics.Textures;
using osu.Game.IO;
namespace osu.Game.Storyboards.Drawables
{
public class DrawableStoryboard : Container<DrawableStoryboardLayer>
{
public Storyboard Storyboard { get; private set; }
protected override Vector2 DrawScale => new Vector2(Parent.DrawHeight / 480);
public override bool HandleInput => false;
private bool passing = true;
public bool Passing
{
get { return passing; }
set
{
if (passing == value) return;
passing = value;
updateLayerVisibility();
}
}
private DependencyContainer dependencies;
protected override IReadOnlyDependencyContainer CreateLocalDependencies(IReadOnlyDependencyContainer parent) =>
dependencies = new DependencyContainer(base.CreateLocalDependencies(parent));
public DrawableStoryboard(Storyboard storyboard)
{
Storyboard = storyboard;
Size = new Vector2(640, 480);
Anchor = Anchor.Centre;
Origin = Anchor.Centre;
}
[BackgroundDependencyLoader]
private void load(FileStore fileStore)
{
dependencies.Cache(new TextureStore(new RawTextureLoaderStore(fileStore.Store), false) { ScaleAdjust = 1, });
foreach (var layer in Storyboard.Layers)
Add(layer.CreateDrawable());
}
private void updateLayerVisibility()
{
foreach (var layer in Children)
layer.Enabled = passing ? layer.Layer.EnabledWhenPassing : layer.Layer.EnabledWhenFailing;
}
}
}

View File

@ -0,0 +1,87 @@
// Copyright (c) 2007-2017 ppy Pty Ltd <contact@ppy.sh>.
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
using OpenTK;
using osu.Framework.Allocation;
using osu.Framework.Graphics;
using osu.Framework.Graphics.Animations;
using osu.Framework.Graphics.Textures;
using System.Linq;
namespace osu.Game.Storyboards.Drawables
{
public class DrawableStoryboardAnimation : TextureAnimation, IFlippable
{
public StoryboardAnimation Animation { get; private set; }
protected override bool ShouldBeAlive => Animation.HasCommands && base.ShouldBeAlive;
public override bool RemoveWhenNotAlive => !Animation.HasCommands || base.RemoveWhenNotAlive;
public bool FlipH { get; set; }
public bool FlipV { get; set; }
protected override Vector2 DrawScale
=> new Vector2(FlipH ? -base.DrawScale.X : base.DrawScale.X, FlipV ? -base.DrawScale.Y : base.DrawScale.Y);
public override Anchor Origin
{
get
{
var origin = base.Origin;
if (FlipH)
{
if (origin.HasFlag(Anchor.x0))
origin = Anchor.x2 | (origin & (Anchor.y0 | Anchor.y1 | Anchor.y2));
else if (origin.HasFlag(Anchor.x2))
origin = Anchor.x0 | (origin & (Anchor.y0 | Anchor.y1 | Anchor.y2));
}
if (FlipV)
{
if (origin.HasFlag(Anchor.y0))
origin = Anchor.y2 | (origin & (Anchor.x0 | Anchor.x1 | Anchor.x2));
else if (origin.HasFlag(Anchor.y2))
origin = Anchor.y0 | (origin & (Anchor.x0 | Anchor.x1 | Anchor.x2));
}
return origin;
}
}
public override bool IsPresent
=> !float.IsNaN(DrawPosition.X) && !float.IsNaN(DrawPosition.Y) && base.IsPresent;
public DrawableStoryboardAnimation(StoryboardAnimation animation)
{
Animation = animation;
Origin = animation.Origin;
Position = animation.InitialPosition;
Repeat = animation.LoopType == AnimationLoopType.LoopForever;
if (animation.HasCommands)
{
LifetimeStart = animation.StartTime;
LifetimeEnd = animation.EndTime;
}
}
[BackgroundDependencyLoader]
private void load(OsuGameBase game, TextureStore textureStore)
{
var basePath = Animation.Path.ToLowerInvariant();
for (var frame = 0; frame < Animation.FrameCount; frame++)
{
var framePath = basePath.Replace(".", frame + ".");
var path = game.Beatmap.Value.BeatmapSetInfo.Files.FirstOrDefault(f => f.Filename.ToLowerInvariant() == framePath)?.FileInfo.StoragePath;
if (path == null)
continue;
var texture = textureStore.Get(path);
AddFrame(texture, Animation.FrameDelay);
}
Animation.ApplyTransforms(this);
}
}
}

View File

@ -0,0 +1,37 @@
// Copyright (c) 2007-2017 ppy Pty Ltd <contact@ppy.sh>.
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
using osu.Framework.Allocation;
using osu.Framework.Graphics;
using osu.Framework.Graphics.Containers;
namespace osu.Game.Storyboards.Drawables
{
public class DrawableStoryboardLayer : Container
{
public StoryboardLayer Layer { get; private set; }
public bool Enabled;
public override bool IsPresent => Enabled && base.IsPresent;
public DrawableStoryboardLayer(StoryboardLayer layer)
{
Layer = layer;
RelativeSizeAxes = Axes.Both;
Anchor = Anchor.Centre;
Origin = Anchor.Centre;
Enabled = layer.EnabledWhenPassing;
}
[BackgroundDependencyLoader]
private void load()
{
foreach (var element in Layer.Elements)
{
var drawable = element.CreateDrawable();
if (drawable != null)
Add(drawable);
}
}
}
}

View File

@ -0,0 +1,80 @@
// Copyright (c) 2007-2017 ppy Pty Ltd <contact@ppy.sh>.
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
using OpenTK;
using osu.Framework.Allocation;
using osu.Framework.Graphics;
using osu.Framework.Graphics.Sprites;
using osu.Framework.Graphics.Textures;
using System.Linq;
namespace osu.Game.Storyboards.Drawables
{
public class DrawableStoryboardSprite : Sprite, IFlippable
{
public StoryboardSprite Sprite { get; private set; }
protected override bool ShouldBeAlive => Sprite.HasCommands && base.ShouldBeAlive;
public override bool RemoveWhenNotAlive => !Sprite.HasCommands || base.RemoveWhenNotAlive;
public bool FlipH { get; set; }
public bool FlipV { get; set; }
protected override Vector2 DrawScale
=> new Vector2(FlipH ? -base.DrawScale.X : base.DrawScale.X, FlipV ? -base.DrawScale.Y : base.DrawScale.Y);
public override Anchor Origin
{
get
{
var origin = base.Origin;
if (FlipH)
{
if (origin.HasFlag(Anchor.x0))
origin = Anchor.x2 | (origin & (Anchor.y0 | Anchor.y1 | Anchor.y2));
else if (origin.HasFlag(Anchor.x2))
origin = Anchor.x0 | (origin & (Anchor.y0 | Anchor.y1 | Anchor.y2));
}
if (FlipV)
{
if (origin.HasFlag(Anchor.y0))
origin = Anchor.y2 | (origin & (Anchor.x0 | Anchor.x1 | Anchor.x2));
else if (origin.HasFlag(Anchor.y2))
origin = Anchor.y0 | (origin & (Anchor.x0 | Anchor.x1 | Anchor.x2));
}
return origin;
}
}
public override bool IsPresent
=> !float.IsNaN(DrawPosition.X) && !float.IsNaN(DrawPosition.Y) && base.IsPresent;
public DrawableStoryboardSprite(StoryboardSprite sprite)
{
Sprite = sprite;
Origin = sprite.Origin;
Position = sprite.InitialPosition;
if (sprite.HasCommands)
{
LifetimeStart = sprite.StartTime;
LifetimeEnd = sprite.EndTime;
}
}
[BackgroundDependencyLoader]
private void load(OsuGameBase game, TextureStore textureStore)
{
var spritePath = Sprite.Path.ToLowerInvariant();
var path = game.Beatmap.Value.BeatmapSetInfo.Files.FirstOrDefault(f => f.Filename.ToLowerInvariant() == spritePath)?.FileInfo.StoragePath;
if (path == null)
return;
Texture = textureStore.Get(path);
Sprite.ApplyTransforms(this);
}
}
}

View File

@ -0,0 +1,30 @@
// Copyright (c) 2007-2017 ppy Pty Ltd <contact@ppy.sh>.
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
using osu.Framework.Graphics;
using osu.Framework.Graphics.Transforms;
namespace osu.Game.Storyboards.Drawables
{
public static class DrawablesExtensions
{
/// <summary>
/// Adjusts <see cref="Drawable.Blending"/> after a delay.
/// </summary>
/// <returns>A <see cref="TransformSequence{T}"/> to which further transforms can be added.</returns>
public static TransformSequence<T> TransformBlendingMode<T>(this T drawable, BlendingMode newValue, double delay = 0)
where T : Drawable
=> drawable.TransformTo(drawable.PopulateTransform(new TransformBlendingMode(), newValue, delay));
}
public class TransformBlendingMode : Transform<BlendingMode, Drawable>
{
private BlendingMode valueAt(double time)
=> time < EndTime ? StartValue : EndValue;
public override string TargetMember => nameof(Drawable.Blending);
protected override void Apply(Drawable d, double time) => d.Blending = valueAt(time);
protected override void ReadIntoStartValue(Drawable d) => StartValue = d.Blending.Mode;
}
}

View File

@ -0,0 +1,55 @@
// Copyright (c) 2007-2017 ppy Pty Ltd <contact@ppy.sh>.
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
using osu.Framework.Graphics;
using osu.Framework.Graphics.Transforms;
namespace osu.Game.Storyboards.Drawables
{
public interface IFlippable : ITransformable
{
bool FlipH { get; set; }
bool FlipV { get; set; }
}
public class TransformFlipH : Transform<bool, IFlippable>
{
private bool valueAt(double time)
=> time < EndTime ? StartValue : EndValue;
public override string TargetMember => nameof(IFlippable.FlipH);
protected override void Apply(IFlippable d, double time) => d.FlipH = valueAt(time);
protected override void ReadIntoStartValue(IFlippable d) => StartValue = d.FlipH;
}
public class TransformFlipV : Transform<bool, IFlippable>
{
private bool valueAt(double time)
=> time < EndTime ? StartValue : EndValue;
public override string TargetMember => nameof(IFlippable.FlipV);
protected override void Apply(IFlippable d, double time) => d.FlipV = valueAt(time);
protected override void ReadIntoStartValue(IFlippable d) => StartValue = d.FlipV;
}
public static class FlippableExtensions
{
/// <summary>
/// Adjusts <see cref="IFlippable.FlipH"/> after a delay.
/// </summary>
/// <returns>A <see cref="TransformSequence{T}"/> to which further transforms can be added.</returns>
public static TransformSequence<T> TransformFlipH<T>(this T flippable, bool newValue, double delay = 0)
where T : IFlippable
=> flippable.TransformTo(flippable.PopulateTransform(new TransformFlipH(), newValue, delay));
/// <summary>
/// Adjusts <see cref="IFlippable.FlipV"/> after a delay.
/// </summary>
/// <returns>A <see cref="TransformSequence{T}"/> to which further transforms can be added.</returns>
public static TransformSequence<T> TransformFlipV<T>(this T flippable, bool newValue, double delay = 0)
where T : IFlippable
=> flippable.TransformTo(flippable.PopulateTransform(new TransformFlipV(), newValue, delay));
}
}

View File

@ -0,0 +1,13 @@
// Copyright (c) 2007-2017 ppy Pty Ltd <contact@ppy.sh>.
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
using osu.Framework.Graphics;
namespace osu.Game.Storyboards
{
public interface IStoryboardElement
{
string Path { get; }
Drawable CreateDrawable();
}
}

View File

@ -0,0 +1,35 @@
// Copyright (c) 2007-2017 ppy Pty Ltd <contact@ppy.sh>.
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
using osu.Game.Storyboards.Drawables;
using System.Collections.Generic;
using System.Linq;
namespace osu.Game.Storyboards
{
public class Storyboard
{
private readonly Dictionary<string, StoryboardLayer> layers = new Dictionary<string, StoryboardLayer>();
public IEnumerable<StoryboardLayer> Layers => layers.Values;
public Storyboard()
{
layers.Add("Background", new StoryboardLayer("Background", 3));
layers.Add("Fail", new StoryboardLayer("Fail", 2) { EnabledWhenPassing = false, });
layers.Add("Pass", new StoryboardLayer("Pass", 1) { EnabledWhenFailing = false, });
layers.Add("Foreground", new StoryboardLayer("Foreground", 0));
}
public StoryboardLayer GetLayer(string name)
{
StoryboardLayer layer;
if (!layers.TryGetValue(name, out layer))
layers[name] = layer = new StoryboardLayer(name, layers.Values.Min(l => l.Depth) - 1);
return layer;
}
public DrawableStoryboard CreateDrawable()
=> new DrawableStoryboard(this);
}
}

View File

@ -0,0 +1,33 @@
// Copyright (c) 2007-2017 ppy Pty Ltd <contact@ppy.sh>.
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
using OpenTK;
using osu.Framework.Graphics;
using osu.Game.Storyboards.Drawables;
namespace osu.Game.Storyboards
{
public class StoryboardAnimation : StoryboardSprite
{
public int FrameCount;
public double FrameDelay;
public AnimationLoopType LoopType;
public StoryboardAnimation(string path, Anchor origin, Vector2 initialPosition, int frameCount, double frameDelay, AnimationLoopType loopType)
: base(path, origin, initialPosition)
{
FrameCount = frameCount;
FrameDelay = frameDelay;
LoopType = loopType;
}
public override Drawable CreateDrawable()
=> new DrawableStoryboardAnimation(this);
}
public enum AnimationLoopType
{
LoopForever,
LoopOnce,
}
}

View File

@ -0,0 +1,33 @@
// Copyright (c) 2007-2017 ppy Pty Ltd <contact@ppy.sh>.
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
using osu.Game.Storyboards.Drawables;
using System.Collections.Generic;
namespace osu.Game.Storyboards
{
public class StoryboardLayer
{
public string Name;
public int Depth;
public bool EnabledWhenPassing = true;
public bool EnabledWhenFailing = true;
private readonly List<IStoryboardElement> elements = new List<IStoryboardElement>();
public IEnumerable<IStoryboardElement> Elements => elements;
public StoryboardLayer(string name, int depth)
{
Name = name;
Depth = depth;
}
public void Add(IStoryboardElement element)
{
elements.Add(element);
}
public DrawableStoryboardLayer CreateDrawable()
=> new DrawableStoryboardLayer(this) { Depth = Depth, };
}
}

View File

@ -0,0 +1,24 @@
// Copyright (c) 2007-2017 ppy Pty Ltd <contact@ppy.sh>.
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
using osu.Framework.Graphics;
namespace osu.Game.Storyboards
{
public class StoryboardSample : IStoryboardElement
{
public string Path { get; set; }
public double Time;
public float Volume;
public StoryboardSample(string path, double time, float volume)
{
Path = path;
Time = time;
Volume = volume;
}
public Drawable CreateDrawable()
=> null;
}
}

View File

@ -0,0 +1,113 @@
// Copyright (c) 2007-2017 ppy Pty Ltd <contact@ppy.sh>.
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
using OpenTK;
using osu.Framework.Graphics;
using osu.Game.Storyboards.Drawables;
using System;
using System.Collections.Generic;
using System.Linq;
namespace osu.Game.Storyboards
{
public class StoryboardSprite : IStoryboardElement
{
private readonly List<CommandLoop> loops = new List<CommandLoop>();
private readonly List<CommandTrigger> triggers = new List<CommandTrigger>();
public string Path { get; set; }
public Anchor Origin;
public Vector2 InitialPosition;
public readonly CommandTimelineGroup TimelineGroup = new CommandTimelineGroup();
public double StartTime => Math.Min(
TimelineGroup.HasCommands ? TimelineGroup.CommandsStartTime : double.MaxValue,
loops.Any(l => l.HasCommands) ? loops.Where(l => l.HasCommands).Min(l => l.StartTime) : double.MaxValue);
public double EndTime => Math.Max(
TimelineGroup.HasCommands ? TimelineGroup.CommandsEndTime : double.MinValue,
loops.Any(l => l.HasCommands) ? loops.Where(l => l.HasCommands).Max(l => l.EndTime) : double.MinValue);
public bool HasCommands => TimelineGroup.HasCommands || loops.Any(l => l.HasCommands);
private delegate void DrawablePropertyInitializer<in T>(Drawable drawable, T value);
private delegate void DrawableTransformer<in T>(Drawable drawable, T value, double duration, Easing easing);
public StoryboardSprite(string path, Anchor origin, Vector2 initialPosition)
{
Path = path;
Origin = origin;
InitialPosition = initialPosition;
}
public CommandLoop AddLoop(double startTime, int loopCount)
{
var loop = new CommandLoop(startTime, loopCount);
loops.Add(loop);
return loop;
}
public CommandTrigger AddTrigger(string triggerName, double startTime, double endTime, int groupNumber)
{
var trigger = new CommandTrigger(triggerName, startTime, endTime, groupNumber);
triggers.Add(trigger);
return trigger;
}
public virtual Drawable CreateDrawable()
=> new DrawableStoryboardSprite(this);
public void ApplyTransforms(Drawable drawable, IEnumerable<Tuple<CommandTimelineGroup, double>> triggeredGroups = null)
{
applyCommands(drawable, getCommands(g => g.X, triggeredGroups), (d, value) => d.X = value, (d, value, duration, easing) => d.MoveToX(value, duration, easing));
applyCommands(drawable, getCommands(g => g.Y, triggeredGroups), (d, value) => d.Y = value, (d, value, duration, easing) => d.MoveToY(value, duration, easing));
applyCommands(drawable, getCommands(g => g.Scale, triggeredGroups), (d, value) => d.Scale = value, (d, value, duration, easing) => d.ScaleTo(value, duration, easing));
applyCommands(drawable, getCommands(g => g.Rotation, triggeredGroups), (d, value) => d.Rotation = value, (d, value, duration, easing) => d.RotateTo(value, duration, easing));
applyCommands(drawable, getCommands(g => g.Colour, triggeredGroups), (d, value) => d.Colour = value, (d, value, duration, easing) => d.FadeColour(value, duration, easing));
applyCommands(drawable, getCommands(g => g.Alpha, triggeredGroups), (d, value) => d.Alpha = value, (d, value, duration, easing) => d.FadeTo(value, duration, easing));
applyCommands(drawable, getCommands(g => g.BlendingMode, triggeredGroups), (d, value) => d.Blending = value, (d, value, duration, easing) => d.TransformBlendingMode(value, duration), false);
var flippable = drawable as IFlippable;
if (flippable != null)
{
applyCommands(drawable, getCommands(g => g.FlipH, triggeredGroups), (d, value) => flippable.FlipH = value, (d, value, duration, easing) => flippable.TransformFlipH(value, duration), false);
applyCommands(drawable, getCommands(g => g.FlipV, triggeredGroups), (d, value) => flippable.FlipV = value, (d, value, duration, easing) => flippable.TransformFlipV(value, duration), false);
}
}
private void applyCommands<T>(Drawable drawable, IEnumerable<CommandTimeline<T>.TypedCommand> commands, DrawablePropertyInitializer<T> initializeProperty, DrawableTransformer<T> transform, bool alwaysInitialize = true)
where T : struct
{
var initialized = false;
foreach (var command in commands.OrderBy(l => l))
{
if (!initialized)
{
if (alwaysInitialize || command.StartTime == command.EndTime)
initializeProperty.Invoke(drawable, command.StartValue);
initialized = true;
}
using (drawable.BeginAbsoluteSequence(command.StartTime))
{
transform(drawable, command.StartValue, 0, Easing.None);
transform(drawable, command.EndValue, command.Duration, command.Easing);
}
}
}
private IEnumerable<CommandTimeline<T>.TypedCommand> getCommands<T>(CommandTimelineSelector<T> timelineSelector, IEnumerable<Tuple<CommandTimelineGroup, double>> triggeredGroups)
{
var commands = TimelineGroup.GetCommands(timelineSelector);
foreach (var loop in loops)
commands = commands.Concat(loop.GetCommands(timelineSelector));
if (triggeredGroups != null)
foreach (var pair in triggeredGroups)
commands = commands.Concat(pair.Item1.GetCommands(timelineSelector, pair.Item2));
return commands;
}
public override string ToString()
=> $"{Path}, {Origin}, {InitialPosition}";
}
}

View File

@ -26,7 +26,7 @@ namespace osu.Game.Users
private void load(TextureStore textures)
{
Texture texture = null;
if (user?.Id > 1) texture = textures.Get($@"https://a.ppy.sh/{user.Id}");
if (user != null && user.Id > 1) texture = textures.Get($@"https://a.ppy.sh/{user.Id}");
if (texture == null) texture = textures.Get(@"Online/avatar-guest");
Add(new Sprite

View File

@ -122,25 +122,10 @@ namespace osu.Game.Users
public int Available;
}
[JsonProperty(@"defaultStatistics")]
[JsonProperty(@"statistics")]
public UserStatistics Statistics;
public class RankHistories
{
[JsonProperty(@"osu")]
public RankHistory Osu;
[JsonProperty(@"taiko")]
public RankHistory Taiko;
[JsonProperty(@"fruits")]
public RankHistory Fruits;
[JsonProperty(@"mania")]
public RankHistory Mania;
}
public class RankHistory
public class RankHistoryData
{
[JsonProperty(@"mode")]
public string Mode;
@ -149,7 +134,7 @@ namespace osu.Game.Users
public int[] Data;
}
[JsonProperty(@"allRankHistories")]
public RankHistories AllRankHistories;
[JsonProperty(@"rankHistory")]
public RankHistoryData RankHistory;
}
}

View File

@ -13,10 +13,13 @@ using osu.Framework.Graphics.Shapes;
using osu.Game.Graphics;
using osu.Game.Graphics.Sprites;
using osu.Game.Overlays;
using osu.Framework.Graphics.UserInterface;
using osu.Game.Graphics.UserInterface;
using osu.Framework.Graphics.Cursor;
namespace osu.Game.Users
{
public class UserPanel : ClickableContainer
public class UserPanel : ClickableContainer, IHasContextMenu
{
private readonly User user;
private const float height = 100;
@ -31,6 +34,8 @@ namespace osu.Game.Users
public new Action Action;
protected Action ViewProfile;
public UserPanel(User user)
{
this.user = user;
@ -171,7 +176,7 @@ namespace osu.Game.Users
Status.ValueChanged += displayStatus;
Status.ValueChanged += status => statusBg.FadeColour(status?.GetAppropriateColour(colours) ?? colours.Gray5, 500, Easing.OutQuint);
base.Action = () =>
base.Action = ViewProfile = () =>
{
Action?.Invoke();
profile?.ShowUser(user);
@ -203,5 +208,10 @@ namespace osu.Game.Users
statusMessage.Text = status.Message;
}
}
public MenuItem[] ContextMenuItems => new MenuItem[]
{
new OsuMenuItem("View Profile", MenuItemType.Highlighted, ViewProfile),
};
}
}

View File

@ -81,6 +81,22 @@
<Compile Include="Beatmaps\DifficultyCalculator.cs" />
<Compile Include="Beatmaps\DummyWorkingBeatmap.cs" />
<Compile Include="Beatmaps\IO\LegacyFilesystemReader.cs" />
<Compile Include="Storyboards\Drawables\IFlippable.cs" />
<Compile Include="Storyboards\Drawables\DrawableStoryboardLayer.cs" />
<Compile Include="Storyboards\Drawables\DrawableStoryboard.cs" />
<Compile Include="Storyboards\Drawables\DrawableStoryboardAnimation.cs" />
<Compile Include="Storyboards\Drawables\DrawableStoryboardSprite.cs" />
<Compile Include="Storyboards\StoryboardAnimation.cs" />
<Compile Include="Storyboards\Drawables\DrawablesExtensions.cs" />
<Compile Include="Storyboards\IStoryboardElement.cs" />
<Compile Include="Storyboards\CommandTimeline.cs" />
<Compile Include="Storyboards\CommandTimelineGroup.cs" />
<Compile Include="Storyboards\CommandTrigger.cs" />
<Compile Include="Storyboards\CommandLoop.cs" />
<Compile Include="Storyboards\StoryboardSample.cs" />
<Compile Include="Storyboards\StoryboardSprite.cs" />
<Compile Include="Storyboards\StoryboardLayer.cs" />
<Compile Include="Storyboards\Storyboard.cs" />
<Compile Include="Database\StoreVersion.cs" />
<Compile Include="Graphics\Containers\OsuClickableContainer.cs" />
<Compile Include="Graphics\Containers\OsuFocusedOverlayContainer.cs" />

View File

@ -42,6 +42,7 @@
<s:String x:Key="/Default/CodeInspection/Highlighting/InspectionSeverities/=FieldCanBeMadeReadOnly_002ELocal/@EntryIndexedValue">WARNING</s:String>
<s:String x:Key="/Default/CodeInspection/Highlighting/InspectionSeverities/=ForCanBeConvertedToForeach/@EntryIndexedValue">WARNING</s:String>
<s:String x:Key="/Default/CodeInspection/Highlighting/InspectionSeverities/=InconsistentNaming/@EntryIndexedValue">ERROR</s:String>
<s:String x:Key="/Default/CodeInspection/Highlighting/InspectionSeverities/=InheritdocConsiderUsage/@EntryIndexedValue">HINT</s:String>
<s:String x:Key="/Default/CodeInspection/Highlighting/InspectionSeverities/=InvertIf/@EntryIndexedValue">HINT</s:String>
<s:String x:Key="/Default/CodeInspection/Highlighting/InspectionSeverities/=InvokeAsExtensionMethod/@EntryIndexedValue">WARNING</s:String>
<s:String x:Key="/Default/CodeInspection/Highlighting/InspectionSeverities/=JoinDeclarationAndInitializer/@EntryIndexedValue">WARNING</s:String>
@ -56,6 +57,8 @@
<s:String x:Key="/Default/CodeInspection/Highlighting/InspectionSeverities/=NestedStringInterpolation/@EntryIndexedValue">WARNING</s:String>
<s:String x:Key="/Default/CodeInspection/Highlighting/InspectionSeverities/=NotAccessedField_002EGlobal/@EntryIndexedValue">HINT</s:String>
<s:String x:Key="/Default/CodeInspection/Highlighting/InspectionSeverities/=ParameterHidesMember/@EntryIndexedValue">HINT</s:String>
<s:String x:Key="/Default/CodeInspection/Highlighting/InspectionSeverities/=ParameterOnlyUsedForPreconditionCheck_002EGlobal/@EntryIndexedValue">HINT</s:String>
<s:String x:Key="/Default/CodeInspection/Highlighting/InspectionSeverities/=ParameterOnlyUsedForPreconditionCheck_002ELocal/@EntryIndexedValue">HINT</s:String>
<s:String x:Key="/Default/CodeInspection/Highlighting/InspectionSeverities/=PossibleMultipleEnumeration/@EntryIndexedValue">HINT</s:String>
<s:String x:Key="/Default/CodeInspection/Highlighting/InspectionSeverities/=PrivateVariableCanBeMadeReadonly/@EntryIndexedValue">WARNING</s:String>
<s:String x:Key="/Default/CodeInspection/Highlighting/InspectionSeverities/=PublicConstructorInAbstractClass/@EntryIndexedValue">WARNING</s:String>
@ -617,6 +620,7 @@ Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu-frame
<s:String x:Key="/Default/CodeStyle/Naming/JavaScriptNaming/UserRules/=TS_005FENUM/@EntryIndexedValue">&lt;Policy Inspect="True" Prefix="" Suffix="" Style="AaBb" /&gt;</s:String>
<s:String x:Key="/Default/CodeStyle/Naming/JavaScriptNaming/UserRules/=TS_005FENUM_005FMEMBER/@EntryIndexedValue">&lt;Policy Inspect="True" Prefix="" Suffix="" Style="AaBb" /&gt;</s:String>
<s:String x:Key="/Default/CodeStyle/Naming/JavaScriptNaming/UserRules/=TS_005FINTERFACE/@EntryIndexedValue">&lt;Policy Inspect="True" Prefix="I" Suffix="" Style="AaBb" /&gt;</s:String>
<s:String x:Key="/Default/CodeStyle/Naming/JavaScriptNaming/UserRules/=TS_005FMIXED_005FENUM/@EntryIndexedValue">&lt;Policy Inspect="True" Prefix="" Suffix="" Style="AaBb" /&gt;</s:String>
<s:String x:Key="/Default/CodeStyle/Naming/JavaScriptNaming/UserRules/=TS_005FMODULE/@EntryIndexedValue">&lt;Policy Inspect="True" Prefix="" Suffix="" Style="AaBb" /&gt;</s:String>
<s:String x:Key="/Default/CodeStyle/Naming/JavaScriptNaming/UserRules/=TS_005FMODULE_005FEXPORTED/@EntryIndexedValue">&lt;Policy Inspect="True" Prefix="" Suffix="" Style="aaBb" /&gt;</s:String>
<s:String x:Key="/Default/CodeStyle/Naming/JavaScriptNaming/UserRules/=TS_005FMODULE_005FLOCAL/@EntryIndexedValue">&lt;Policy Inspect="True" Prefix="" Suffix="" Style="aaBb" /&gt;</s:String>