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

Merge branch 'master' into fix-missing-metadata

This commit is contained in:
Dean Herbert 2017-12-11 16:04:08 +09:00 committed by GitHub
commit 3880c7157b
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
56 changed files with 1086 additions and 338 deletions

@ -1 +1 @@
Subproject commit 797a351db2e852fef5296453641ffbf6b2f6dc11
Subproject commit 8480ab5009b2b4a7810a817a12433959424d5339

View File

@ -93,6 +93,8 @@ namespace osu.Game.Rulesets.Catch
public override string Description => "osu!catch";
public override string ShortName => "fruits";
public override Drawable CreateIcon() => new SpriteIcon { Icon = FontAwesome.fa_osu_fruits_o };
public override DifficultyCalculator CreateDifficultyCalculator(Beatmap beatmap, Mod[] mods = null) => new CatchDifficultyCalculator(beatmap);

View File

@ -90,6 +90,9 @@
<Private>True</Private>
</ProjectReference>
</ItemGroup>
<ItemGroup>
<Service Include="{82A7F48D-3B50-4B1E-B82E-3ADA8210C358}" />
</ItemGroup>
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
<!-- To modify your build process, add your task inside one of the targets below and uncomment it.
Other similar extension points exist, see Microsoft.Common.targets.

View File

@ -105,6 +105,8 @@ namespace osu.Game.Rulesets.Mania
public override string Description => "osu!mania";
public override string ShortName => "mania";
public override Drawable CreateIcon() => new SpriteIcon { Icon = FontAwesome.fa_osu_mania_o };
public override DifficultyCalculator CreateDifficultyCalculator(Beatmap beatmap, Mod[] mods = null) => new ManiaDifficultyCalculator(beatmap);

View File

@ -114,6 +114,9 @@
<Private>True</Private>
</ProjectReference>
</ItemGroup>
<ItemGroup>
<Service Include="{82A7F48D-3B50-4B1E-B82E-3ADA8210C358}" />
</ItemGroup>
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
<!-- To modify your build process, add your task inside one of the targets below and uncomment it.
Other similar extension points exist, see Microsoft.Common.targets.

View File

@ -124,6 +124,8 @@ namespace osu.Game.Rulesets.Osu
public override string Description => "osu!";
public override string ShortName => "osu";
public override SettingsSubsection CreateSettings() => new OsuSettings();
public override int LegacyID => 0;

View File

@ -20,8 +20,6 @@ namespace osu.Game.Rulesets.Osu.UI.Cursor
{
internal class CursorTrail : Drawable
{
public override bool HandleInput => true;
private int currentIndex;
private Shader shader;

View File

@ -123,7 +123,9 @@
<Private>True</Private>
</ProjectReference>
</ItemGroup>
<ItemGroup />
<ItemGroup>
<Service Include="{82A7F48D-3B50-4B1E-B82E-3ADA8210C358}" />
</ItemGroup>
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
<!-- To modify your build process, add your task inside one of the targets below and uncomment it.
Other similar extension points exist, see Microsoft.Common.targets.

View File

@ -95,6 +95,8 @@ namespace osu.Game.Rulesets.Taiko
public override string Description => "osu!taiko";
public override string ShortName => "taiko";
public override Drawable CreateIcon() => new SpriteIcon { Icon = FontAwesome.fa_osu_taiko_o };
public override DifficultyCalculator CreateDifficultyCalculator(Beatmap beatmap, Mod[] mods = null) => new TaikoDifficultyCalculator(beatmap);

View File

@ -111,6 +111,9 @@
<Private>True</Private>
</ProjectReference>
</ItemGroup>
<ItemGroup>
<Service Include="{82A7F48D-3B50-4B1E-B82E-3ADA8210C358}" />
</ItemGroup>
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
<!-- To modify your build process, add your task inside one of the targets below and uncomment it.
Other similar extension points exist, see Microsoft.Common.targets.

View File

@ -0,0 +1,47 @@
// 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 System.Collections.Generic;
using osu.Framework.Graphics;
using osu.Framework.Graphics.Containers;
using osu.Framework.Graphics.Shapes;
using osu.Game.Graphics;
using osu.Game.Overlays.Profile.Sections;
using osu.Game.Overlays.Profile.Sections.Historical;
using osu.Game.Users;
namespace osu.Game.Tests.Visual
{
internal class TestCaseHistoricalSection : OsuTestCase
{
public override IReadOnlyList<Type> RequiredTypes =>
new[]
{
typeof(HistoricalSection),
typeof(PaginatedMostPlayedBeatmapContainer),
typeof(DrawableMostPlayedRow),
typeof(DrawableProfileRow)
};
public TestCaseHistoricalSection()
{
HistoricalSection section;
Add(new Box
{
RelativeSizeAxes = Axes.Both,
Colour = OsuColour.Gray(0.2f)
});
Add(new ScrollContainer
{
RelativeSizeAxes = Axes.Both,
Child = section = new HistoricalSection(),
});
AddStep("Show peppy", () => section.User.Value = new User { Id = 2 });
AddStep("Show WubWoofWolf", () => section.User.Value = new User { Id = 39828 });
}
}
}

View File

@ -15,7 +15,7 @@ namespace osu.Game.Tests.Visual
{
internal class TestCaseUserRanks : OsuTestCase
{
public override IReadOnlyList<Type> RequiredTypes => new[] { typeof(DrawableScore), typeof(RanksSection) };
public override IReadOnlyList<Type> RequiredTypes => new[] { typeof(DrawableProfileScore), typeof(RanksSection) };
public TestCaseUserRanks()
{

View File

@ -110,6 +110,7 @@
<Compile Include="Visual\TestCaseEditorSummaryTimeline.cs" />
<Compile Include="Visual\TestCaseGamefield.cs" />
<Compile Include="Visual\TestCaseGraph.cs" />
<Compile Include="Visual\TestCaseHistoricalSection.cs" />
<Compile Include="Visual\TestCaseIconButton.cs" />
<Compile Include="Visual\TestCaseIntroSequence.cs" />
<Compile Include="Visual\TestCaseKeyConfiguration.cs" />

View File

@ -115,6 +115,7 @@ namespace osu.Game.Beatmaps
// Metadata
public string Version { get; set; }
[JsonProperty("difficulty_rating")]
public double StarDifficulty { get; set; }
public bool Equals(BeatmapInfo other)

View File

@ -497,8 +497,13 @@ namespace osu.Game.Beatmaps
using (var stream = new StreamReader(reader.GetStream(mapName)))
metadata = Decoder.GetDecoder(stream).DecodeBeatmap(stream).Metadata;
// check if a set already exists with the same online id.
beatmapSet = beatmaps.BeatmapSets.FirstOrDefault(b => b.OnlineBeatmapSetID == metadata.OnlineBeatmapSetID) ?? new BeatmapSetInfo
if (metadata.OnlineBeatmapSetID != null)
beatmapSet = beatmaps.BeatmapSets.FirstOrDefault(b => b.OnlineBeatmapSetID == metadata.OnlineBeatmapSetID);
if (beatmapSet == null)
beatmapSet = new BeatmapSetInfo
{
OnlineBeatmapSetID = metadata.OnlineBeatmapSetID,
Beatmaps = new List<BeatmapInfo>(),
@ -507,6 +512,7 @@ namespace osu.Game.Beatmaps
Metadata = metadata
};
var mapNames = reader.Filenames.Where(f => f.EndsWith(".osu"));
foreach (var name in mapNames)
@ -525,7 +531,7 @@ namespace osu.Game.Beatmaps
beatmap.BeatmapInfo.Hash = ms.ComputeSHA2Hash();
beatmap.BeatmapInfo.MD5Hash = ms.ComputeMD5Hash();
var existing = beatmaps.Beatmaps.FirstOrDefault(b => b.Hash == beatmap.BeatmapInfo.Hash || b.OnlineBeatmapID == beatmap.BeatmapInfo.OnlineBeatmapID);
var existing = beatmaps.Beatmaps.FirstOrDefault(b => b.Hash == beatmap.BeatmapInfo.Hash || beatmap.BeatmapInfo.OnlineBeatmapID != null && b.OnlineBeatmapID == beatmap.BeatmapInfo.OnlineBeatmapID);
if (existing == null)
{

View File

@ -11,21 +11,44 @@ namespace osu.Game.Beatmaps.Drawables
public class BeatmapSetCover : Sprite
{
private readonly BeatmapSetInfo set;
public BeatmapSetCover(BeatmapSetInfo set)
private readonly BeatmapSetCoverType type;
public BeatmapSetCover(BeatmapSetInfo set, BeatmapSetCoverType type = BeatmapSetCoverType.Cover)
{
if (set == null)
throw new ArgumentNullException(nameof(set));
this.set = set;
this.type = type;
}
[BackgroundDependencyLoader]
private void load(TextureStore textures)
{
string resource = set.OnlineInfo.Covers.Cover;
string resource = null;
switch (type)
{
case BeatmapSetCoverType.Cover:
resource = set.OnlineInfo.Covers.Cover;
break;
case BeatmapSetCoverType.Card:
resource = set.OnlineInfo.Covers.Card;
break;
case BeatmapSetCoverType.List:
resource = set.OnlineInfo.Covers.List;
break;
}
if (resource != null)
Texture = textures.Get(resource);
}
}
public enum BeatmapSetCoverType
{
Cover,
Card,
List,
}
}

View File

@ -63,6 +63,8 @@ namespace osu.Game.Beatmaps
public override string Description => "dummy";
public override string ShortName => "dummy";
public DummyRuleset(RulesetInfo rulesetInfo)
: base(rulesetInfo)
{

View File

@ -93,6 +93,7 @@ namespace osu.Game.Database
modelBuilder.Entity<FileInfo>().HasIndex(b => b.ReferenceCount);
modelBuilder.Entity<RulesetInfo>().HasIndex(b => b.Available);
modelBuilder.Entity<RulesetInfo>().HasIndex(b => b.ShortName).IsUnique();
modelBuilder.Entity<BeatmapInfo>().HasOne(b => b.BaseDifficulty);
}

View File

@ -0,0 +1,307 @@
// <auto-generated />
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Infrastructure;
using Microsoft.EntityFrameworkCore.Metadata;
using Microsoft.EntityFrameworkCore.Migrations;
using Microsoft.EntityFrameworkCore.Storage;
using osu.Game.Database;
using System;
namespace osu.Game.Migrations
{
[DbContext(typeof(OsuDbContext))]
[Migration("20171209034410_AddRulesetInfoShortName")]
partial class AddRulesetInfoShortName
{
protected override void BuildTargetModel(ModelBuilder modelBuilder)
{
#pragma warning disable 612, 618
modelBuilder
.HasAnnotation("ProductVersion", "2.0.0-rtm-26452");
modelBuilder.Entity("osu.Game.Beatmaps.BeatmapDifficulty", b =>
{
b.Property<int>("ID")
.ValueGeneratedOnAdd();
b.Property<float>("ApproachRate");
b.Property<float>("CircleSize");
b.Property<float>("DrainRate");
b.Property<float>("OverallDifficulty");
b.Property<float>("SliderMultiplier");
b.Property<float>("SliderTickRate");
b.HasKey("ID");
b.ToTable("BeatmapDifficulty");
});
modelBuilder.Entity("osu.Game.Beatmaps.BeatmapInfo", b =>
{
b.Property<int>("ID")
.ValueGeneratedOnAdd();
b.Property<int>("AudioLeadIn");
b.Property<int>("BaseDifficultyID");
b.Property<int>("BeatDivisor");
b.Property<int>("BeatmapSetInfoID");
b.Property<bool>("Countdown");
b.Property<double>("DistanceSpacing");
b.Property<int>("GridSize");
b.Property<string>("Hash");
b.Property<bool>("Hidden");
b.Property<bool>("LetterboxInBreaks");
b.Property<string>("MD5Hash");
b.Property<int?>("MetadataID");
b.Property<int?>("OnlineBeatmapID");
b.Property<string>("Path");
b.Property<int>("RulesetID");
b.Property<bool>("SpecialStyle");
b.Property<float>("StackLeniency");
b.Property<double>("StarDifficulty");
b.Property<string>("StoredBookmarks");
b.Property<double>("TimelineZoom");
b.Property<string>("Version");
b.Property<bool>("WidescreenStoryboard");
b.HasKey("ID");
b.HasIndex("BaseDifficultyID");
b.HasIndex("BeatmapSetInfoID");
b.HasIndex("Hash")
.IsUnique();
b.HasIndex("MD5Hash")
.IsUnique();
b.HasIndex("MetadataID");
b.HasIndex("OnlineBeatmapID")
.IsUnique();
b.HasIndex("RulesetID");
b.ToTable("BeatmapInfo");
});
modelBuilder.Entity("osu.Game.Beatmaps.BeatmapMetadata", b =>
{
b.Property<int>("ID")
.ValueGeneratedOnAdd();
b.Property<string>("Artist");
b.Property<string>("ArtistUnicode");
b.Property<string>("AudioFile");
b.Property<string>("AuthorString")
.HasColumnName("Author");
b.Property<string>("BackgroundFile");
b.Property<int>("PreviewTime");
b.Property<string>("Source");
b.Property<string>("Tags");
b.Property<string>("Title");
b.Property<string>("TitleUnicode");
b.HasKey("ID");
b.ToTable("BeatmapMetadata");
});
modelBuilder.Entity("osu.Game.Beatmaps.BeatmapSetFileInfo", b =>
{
b.Property<int>("ID")
.ValueGeneratedOnAdd();
b.Property<int>("BeatmapSetInfoID");
b.Property<int>("FileInfoID");
b.Property<string>("Filename")
.IsRequired();
b.HasKey("ID");
b.HasIndex("BeatmapSetInfoID");
b.HasIndex("FileInfoID");
b.ToTable("BeatmapSetFileInfo");
});
modelBuilder.Entity("osu.Game.Beatmaps.BeatmapSetInfo", b =>
{
b.Property<int>("ID")
.ValueGeneratedOnAdd();
b.Property<bool>("DeletePending");
b.Property<string>("Hash");
b.Property<int?>("MetadataID");
b.Property<int?>("OnlineBeatmapSetID");
b.Property<bool>("Protected");
b.HasKey("ID");
b.HasIndex("DeletePending");
b.HasIndex("Hash")
.IsUnique();
b.HasIndex("MetadataID");
b.HasIndex("OnlineBeatmapSetID")
.IsUnique();
b.ToTable("BeatmapSetInfo");
});
modelBuilder.Entity("osu.Game.Input.Bindings.DatabasedKeyBinding", b =>
{
b.Property<int>("ID")
.ValueGeneratedOnAdd();
b.Property<int>("IntAction")
.HasColumnName("Action");
b.Property<string>("KeysString")
.HasColumnName("Keys");
b.Property<int?>("RulesetID");
b.Property<int?>("Variant");
b.HasKey("ID");
b.HasIndex("IntAction");
b.HasIndex("Variant");
b.ToTable("KeyBinding");
});
modelBuilder.Entity("osu.Game.IO.FileInfo", b =>
{
b.Property<int>("ID")
.ValueGeneratedOnAdd();
b.Property<string>("Hash");
b.Property<int>("ReferenceCount");
b.HasKey("ID");
b.HasIndex("Hash")
.IsUnique();
b.HasIndex("ReferenceCount");
b.ToTable("FileInfo");
});
modelBuilder.Entity("osu.Game.Rulesets.RulesetInfo", b =>
{
b.Property<int?>("ID")
.ValueGeneratedOnAdd();
b.Property<bool>("Available");
b.Property<string>("InstantiationInfo");
b.Property<string>("Name");
b.Property<string>("ShortName");
b.HasKey("ID");
b.HasIndex("Available");
b.HasIndex("ShortName")
.IsUnique();
b.ToTable("RulesetInfo");
});
modelBuilder.Entity("osu.Game.Beatmaps.BeatmapInfo", b =>
{
b.HasOne("osu.Game.Beatmaps.BeatmapDifficulty", "BaseDifficulty")
.WithMany()
.HasForeignKey("BaseDifficultyID")
.OnDelete(DeleteBehavior.Cascade);
b.HasOne("osu.Game.Beatmaps.BeatmapSetInfo", "BeatmapSet")
.WithMany("Beatmaps")
.HasForeignKey("BeatmapSetInfoID")
.OnDelete(DeleteBehavior.Cascade);
b.HasOne("osu.Game.Beatmaps.BeatmapMetadata", "Metadata")
.WithMany("Beatmaps")
.HasForeignKey("MetadataID");
b.HasOne("osu.Game.Rulesets.RulesetInfo", "Ruleset")
.WithMany()
.HasForeignKey("RulesetID")
.OnDelete(DeleteBehavior.Cascade);
});
modelBuilder.Entity("osu.Game.Beatmaps.BeatmapSetFileInfo", b =>
{
b.HasOne("osu.Game.Beatmaps.BeatmapSetInfo")
.WithMany("Files")
.HasForeignKey("BeatmapSetInfoID")
.OnDelete(DeleteBehavior.Cascade);
b.HasOne("osu.Game.IO.FileInfo", "FileInfo")
.WithMany()
.HasForeignKey("FileInfoID")
.OnDelete(DeleteBehavior.Cascade);
});
modelBuilder.Entity("osu.Game.Beatmaps.BeatmapSetInfo", b =>
{
b.HasOne("osu.Game.Beatmaps.BeatmapMetadata", "Metadata")
.WithMany("BeatmapSets")
.HasForeignKey("MetadataID");
});
#pragma warning restore 612, 618
}
}
}

View File

@ -0,0 +1,35 @@
using Microsoft.EntityFrameworkCore.Migrations;
using System;
using System.Collections.Generic;
namespace osu.Game.Migrations
{
public partial class AddRulesetInfoShortName : Migration
{
protected override void Up(MigrationBuilder migrationBuilder)
{
migrationBuilder.AddColumn<string>(
name: "ShortName",
table: "RulesetInfo",
type: "TEXT",
nullable: true);
migrationBuilder.CreateIndex(
name: "IX_RulesetInfo_ShortName",
table: "RulesetInfo",
column: "ShortName",
unique: true);
}
protected override void Down(MigrationBuilder migrationBuilder)
{
migrationBuilder.DropIndex(
name: "IX_RulesetInfo_ShortName",
table: "RulesetInfo");
migrationBuilder.DropColumn(
name: "ShortName",
table: "RulesetInfo");
}
}
}

View File

@ -247,10 +247,15 @@ namespace osu.Game.Migrations
b.Property<string>("Name");
b.Property<string>("ShortName");
b.HasKey("ID");
b.HasIndex("Available");
b.HasIndex("ShortName")
.IsUnique();
b.ToTable("RulesetInfo");
});

View File

@ -10,7 +10,7 @@ using System;
namespace osu.Game.Online.API.Requests
{
public class GetBeatmapSetsResponse : BeatmapMetadata // todo: this is a bit wrong...
public class APIResponseBeatmapSet : BeatmapMetadata // todo: this is a bit wrong...
{
[JsonProperty(@"covers")]
private BeatmapSetOnlineCovers covers { get; set; }
@ -45,7 +45,7 @@ namespace osu.Game.Online.API.Requests
}
[JsonProperty(@"beatmaps")]
private IEnumerable<GetBeatmapSetsBeatmapResponse> beatmaps { get; set; }
private IEnumerable<APIResponseBeatmap> beatmaps { get; set; }
public BeatmapSetInfo ToBeatmapSet(RulesetStore rulesets)
{
@ -65,11 +65,11 @@ namespace osu.Game.Online.API.Requests
Ranked = ranked,
LastUpdated = lastUpdated,
},
Beatmaps = beatmaps.Select(b => b.ToBeatmap(rulesets)).ToList(),
Beatmaps = beatmaps?.Select(b => b.ToBeatmap(rulesets)).ToList(),
};
}
private class GetBeatmapSetsBeatmapResponse : BeatmapMetadata
private class APIResponseBeatmap : BeatmapMetadata
{
[JsonProperty(@"id")]
private int onlineBeatmapID { get; set; }

View File

@ -3,7 +3,7 @@
namespace osu.Game.Online.API.Requests
{
public class GetBeatmapSetRequest : APIRequest<GetBeatmapSetsResponse>
public class GetBeatmapSetRequest : APIRequest<APIResponseBeatmapSet>
{
private readonly int beatmapSetId;

View File

@ -6,7 +6,7 @@ using System.Collections.Generic;
namespace osu.Game.Online.API.Requests
{
public class GetUserBeatmapsRequest : APIRequest<List<GetBeatmapSetsResponse>>
public class GetUserBeatmapsRequest : APIRequest<List<APIResponseBeatmapSet>>
{
private readonly long userId;
private readonly int offset;
@ -24,7 +24,6 @@ namespace osu.Game.Online.API.Requests
public enum BeatmapSetType
{
MostPlayed,
Favourite,
RankedAndApproved,
Unranked,

View File

@ -0,0 +1,48 @@
// Copyright (c) 2007-2017 ppy Pty Ltd <contact@ppy.sh>.
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
using Newtonsoft.Json;
using osu.Game.Beatmaps;
using osu.Game.Rulesets;
using System.Collections.Generic;
namespace osu.Game.Online.API.Requests
{
public class GetUserMostPlayedBeatmapsRequest : APIRequest<List<MostPlayedBeatmap>>
{
private readonly long userId;
private readonly int offset;
public GetUserMostPlayedBeatmapsRequest(long userId, int offset = 0)
{
this.userId = userId;
this.offset = offset;
}
protected override string Target => $@"users/{userId}/beatmapsets/most_played?offset={offset}";
}
public class MostPlayedBeatmap
{
[JsonProperty("beatmap_id")]
public int BeatmapID;
[JsonProperty("count")]
public int PlayCount;
[JsonProperty]
private BeatmapInfo beatmap;
[JsonProperty]
private APIResponseBeatmapSet beatmapSet;
public BeatmapInfo GetBeatmapInfo(RulesetStore rulesets)
{
BeatmapSetInfo setInfo = beatmapSet.ToBeatmapSet(rulesets);
beatmap.BeatmapSet = setInfo;
beatmap.OnlineBeatmapSetID = setInfo.OnlineBeatmapSetID;
beatmap.Metadata = setInfo.Metadata;
return beatmap;
}
}
}

View File

@ -9,7 +9,7 @@ using osu.Game.Rulesets;
namespace osu.Game.Online.API.Requests
{
public class SearchBeatmapSetsRequest : APIRequest<IEnumerable<GetBeatmapSetsResponse>>
public class SearchBeatmapSetsRequest : APIRequest<IEnumerable<APIResponseBeatmapSet>>
{
private readonly string query;
private readonly RulesetInfo ruleset;

View File

@ -14,10 +14,10 @@ namespace osu.Game.Overlays.BeatmapSet
public DownloadButton(string title, string subtitle)
{
Width = 120;
RelativeSizeAxes = Axes.Y;
Child = new Container
Add(new Container
{
Depth = -1,
RelativeSizeAxes = Axes.Both,
Padding = new MarginPadding { Horizontal = 10 },
Children = new Drawable[]
@ -53,7 +53,7 @@ namespace osu.Game.Overlays.BeatmapSet
Margin = new MarginPadding { Right = 5 },
},
},
};
});
}
}
}

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 osu.Framework.Allocation;
using osu.Framework.Configuration;
using osu.Framework.Graphics;
using osu.Framework.Graphics.Containers;
@ -15,13 +16,12 @@ namespace osu.Game.Overlays.BeatmapSet
{
public readonly Bindable<bool> Favourited = new Bindable<bool>();
public FavouriteButton()
[BackgroundDependencyLoader]
private void load()
{
RelativeSizeAxes = Axes.Y;
Container pink;
SpriteIcon icon;
Children = new Drawable[]
AddRange(new Drawable[]
{
pink = new Container
{
@ -51,7 +51,7 @@ namespace osu.Game.Overlays.BeatmapSet
Size = new Vector2(18),
Shadow = false,
},
};
});
Favourited.ValueChanged += value =>
{

View File

@ -2,44 +2,27 @@
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
using osu.Framework.Graphics;
using osu.Framework.Graphics.Containers;
using osu.Framework.Graphics.Shapes;
using osu.Game.Graphics;
using osu.Game.Graphics.Backgrounds;
using osu.Game.Graphics.Containers;
using osu.Game.Graphics.UserInterface;
using osu.Framework.Allocation;
namespace osu.Game.Overlays.BeatmapSet
{
public class HeaderButton : OsuClickableContainer
public class HeaderButton : TriangleButton
{
private readonly Container content;
protected override Container<Drawable> Content => content;
public HeaderButton()
{
CornerRadius = 3;
Masking = true;
Height = 0;
RelativeSizeAxes = Axes.Y;
}
InternalChildren = new Drawable[]
[BackgroundDependencyLoader]
private void load()
{
new Box
{
RelativeSizeAxes = Axes.Both,
Colour = OsuColour.FromHex(@"094c5f"),
},
new Triangles
{
RelativeSizeAxes = Axes.Both,
ColourLight = OsuColour.FromHex(@"0f7c9b"),
ColourDark = OsuColour.FromHex(@"094c5f"),
TriangleScale = 1.5f,
},
content = new Container
{
RelativeSizeAxes = Axes.Both,
},
};
BackgroundColour = OsuColour.FromHex(@"094c5f");
Triangles.ColourLight = OsuColour.FromHex(@"0f7c9b");
Triangles.ColourDark = OsuColour.FromHex(@"094c5f");
Triangles.TriangleScale = 1.5f;
}
}
}

View File

@ -117,7 +117,7 @@ namespace osu.Game.Overlays.Direct
{
base.Update();
if (PreviewPlaying && Preview != null)
if (PreviewPlaying && Preview != null && Preview.IsLoaded)
{
PreviewBar.Width = (float)(Preview.CurrentTime / Preview.Length);
}

View File

@ -105,6 +105,7 @@ namespace osu.Game.Overlays.Direct
public enum DirectSortCriteria
{
Relevance,
Title,
Artist,
Creator,

View File

@ -43,6 +43,7 @@ namespace osu.Game.Overlays
protected override SearchableListFilterControl<DirectSortCriteria, RankStatus> CreateFilterControl() => new FilterControl();
private IEnumerable<BeatmapSetInfo> beatmapSets;
public IEnumerable<BeatmapSetInfo> BeatmapSets
{
get { return beatmapSets; }
@ -69,6 +70,7 @@ namespace osu.Game.Overlays
}
private ResultCounts resultAmounts;
public ResultCounts ResultAmounts
{
get { return resultAmounts; }
@ -115,7 +117,23 @@ namespace osu.Game.Overlays
},
};
Filter.Search.Current.ValueChanged += text => { if (text != string.Empty) Header.Tabs.Current.Value = DirectTab.Search; };
Filter.Search.Current.ValueChanged += text =>
{
if (text != string.Empty)
{
Header.Tabs.Current.Value = DirectTab.Search;
if (Filter.Tabs.Current.Value == DirectSortCriteria.Ranked)
Filter.Tabs.Current.Value = DirectSortCriteria.Relevance;
}
else
{
Header.Tabs.Current.Value = DirectTab.NewestMaps;
if (Filter.Tabs.Current.Value == DirectSortCriteria.Relevance)
Filter.Tabs.Current.Value = DirectSortCriteria.Ranked;
}
};
((FilterControl)Filter).Ruleset.ValueChanged += ruleset => Scheduler.AddOnce(updateSearch);
Filter.DisplayStyleControl.DisplayStyle.ValueChanged += recreatePanels;
Filter.DisplayStyleControl.Dropdown.Current.ValueChanged += rankStatus => Scheduler.AddOnce(updateSearch);

View File

@ -251,7 +251,7 @@ namespace osu.Game.Overlays
playButton.Icon = track.IsRunning ? FontAwesome.fa_pause_circle_o : FontAwesome.fa_play_circle_o;
if (track.HasCompleted && !beatmapBacking.Disabled && playlist.BeatmapSets.Any())
if (track.HasCompleted && !track.Looping && !beatmapBacking.Disabled && playlist.BeatmapSets.Any())
next();
}
else

View File

@ -382,7 +382,7 @@ namespace osu.Game.Overlays.Profile
}
tryAddInfoRightLine(FontAwesome.fa_map_marker, user.Location);
tryAddInfoRightLine(FontAwesome.fa_heart_o, user.Intrerests);
tryAddInfoRightLine(FontAwesome.fa_heart_o, user.Interests);
tryAddInfoRightLine(FontAwesome.fa_suitcase, user.Occupation);
infoTextRight.NewParagraph();
if (!string.IsNullOrEmpty(user.Twitter))

View File

@ -81,12 +81,12 @@ namespace osu.Game.Overlays.Profile
{
rankText.Text = user.Statistics.Rank > 0 ? $"#{user.Statistics.Rank:#,0}" : "no rank";
performanceText.Text = user.Statistics.PP != null ? $"{user.Statistics.PP:#,0}pp" : string.Empty;
relativeText.Text = $"{user.Country?.FullName} #{user.CountryRank:#,0}";
relativeText.Text = user.CountryRank > 0 ? $"{user.Country?.FullName} #{user.CountryRank:#,0}" : $"{user.Country?.FullName}";
}
private void showHistoryRankTexts(int dayIndex)
{
rankText.Text = $"#{ranks[dayIndex]:#,0}";
rankText.Text = ranks[dayIndex] > 0 ? $"#{ranks[dayIndex]:#,0}" : "no rank";
dayIndex++;
relativeText.Text = dayIndex == ranks.Length ? "Now" : $"{ranks.Length - dayIndex} days ago";
//plural should be handled in a general way
@ -99,7 +99,7 @@ namespace osu.Game.Overlays.Profile
{
graph.Colour = colours.Yellow;
// use logarithmic coordinates
graph.Values = ranks.Select(x => -(float)Math.Log(x));
graph.Values = ranks.Select(x => x == 0 ? float.MinValue : -(float)Math.Log(x));
graph.SetStaticBallPosition();
}

View File

@ -0,0 +1,63 @@
// 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;
using osu.Framework.Graphics.Cursor;
using osu.Framework.Localisation;
using osu.Game.Beatmaps;
using osu.Game.Graphics.Containers;
using osu.Game.Graphics.Sprites;
namespace osu.Game.Overlays.Profile.Sections
{
/// <summary>
/// Display artist/title/mapper information, commonly used as the left portion of a profile or score display row (see <see cref="DrawableProfileRow"/>).
/// </summary>
public class BeatmapMetadataContainer : OsuHoverContainer, IHasTooltip
{
private readonly BeatmapInfo beatmap;
public BeatmapMetadataContainer(BeatmapInfo beatmap)
{
this.beatmap = beatmap;
AutoSizeAxes = Axes.Both;
TooltipText = $"{beatmap.Metadata.Artist} - {beatmap.Metadata.Title}";
}
public string TooltipText { get; }
[BackgroundDependencyLoader(true)]
private void load(LocalisationEngine locale, BeatmapSetOverlay beatmapSetOverlay)
{
Action = () =>
{
if (beatmap.OnlineBeatmapSetID.HasValue) beatmapSetOverlay?.ShowBeatmapSet(beatmap.OnlineBeatmapSetID.Value);
};
Child = new FillFlowContainer
{
AutoSizeAxes = Axes.Both,
Children = new Drawable[]
{
new OsuSpriteText
{
Current = locale.GetUnicodePreference(
$"{beatmap.Metadata.TitleUnicode ?? beatmap.Metadata.Title} [{beatmap.Version}] ",
$"{beatmap.Metadata.Title ?? beatmap.Metadata.TitleUnicode} [{beatmap.Version}] "
),
TextSize = 15,
Font = "Exo2.0-SemiBoldItalic",
},
new OsuSpriteText
{
Current = locale.GetUnicodePreference(beatmap.Metadata.ArtistUnicode, beatmap.Metadata.Artist),
TextSize = 12,
Padding = new MarginPadding { Top = 3 },
Font = "Exo2.0-RegularItalic",
},
},
};
}
}
}

View File

@ -0,0 +1,124 @@
// 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.Extensions.Color4Extensions;
using osu.Framework.Graphics;
using osu.Framework.Graphics.Containers;
using osu.Framework.Graphics.Shapes;
using osu.Framework.Input;
using osu.Game.Graphics;
using OpenTK;
using OpenTK.Graphics;
namespace osu.Game.Overlays.Profile.Sections
{
public abstract class DrawableProfileRow : Container
{
private const int fade_duration = 200;
private Box underscoreLine;
private readonly Box coloredBackground;
private readonly Container background;
/// <summary>
/// A visual element displayed to the left of <see cref="LeftFlowContainer"/> content.
/// </summary>
protected abstract Drawable CreateLeftVisual();
protected FillFlowContainer LeftFlowContainer { get; private set; }
protected FillFlowContainer RightFlowContainer { get; private set; }
protected override Container<Drawable> Content { get; }
protected DrawableProfileRow()
{
RelativeSizeAxes = Axes.X;
Height = 60;
InternalChildren = new Drawable[]
{
background = new Container
{
RelativeSizeAxes = Axes.Both,
Masking = true,
CornerRadius = 3,
Alpha = 0,
EdgeEffect = new EdgeEffectParameters
{
Type = EdgeEffectType.Shadow,
Offset = new Vector2(0f, 1f),
Radius = 1f,
Colour = Color4.Black.Opacity(0.2f),
},
Child = coloredBackground = new Box { RelativeSizeAxes = Axes.Both }
},
Content = new Container
{
RelativeSizeAxes = Axes.Both,
Anchor = Anchor.TopCentre,
Origin = Anchor.TopCentre,
Width = 0.97f,
},
};
}
[BackgroundDependencyLoader(true)]
private void load(OsuColour colour)
{
AddRange(new Drawable[]
{
underscoreLine = new Box
{
Anchor = Anchor.BottomCentre,
Origin = Anchor.BottomCentre,
RelativeSizeAxes = Axes.X,
Height = 1,
},
new FillFlowContainer
{
RelativeSizeAxes = Axes.Both,
Direction = FillDirection.Horizontal,
Children = new[]
{
CreateLeftVisual(),
LeftFlowContainer = new FillFlowContainer
{
RelativeSizeAxes = Axes.X,
AutoSizeAxes = Axes.Y,
Anchor = Anchor.CentreLeft,
Origin = Anchor.CentreLeft,
Margin = new MarginPadding { Left = 10 },
Direction = FillDirection.Vertical,
},
}
},
RightFlowContainer = new FillFlowContainer
{
RelativeSizeAxes = Axes.X,
AutoSizeAxes = Axes.Y,
Anchor = Anchor.CentreRight,
Origin = Anchor.CentreRight,
Direction = FillDirection.Vertical,
},
});
coloredBackground.Colour = underscoreLine.Colour = colour.Gray4;
}
protected override bool OnClick(InputState state) => true;
protected override bool OnHover(InputState state)
{
background.FadeIn(fade_duration, Easing.OutQuint);
underscoreLine.FadeOut(fade_duration, Easing.OutQuint);
return true;
}
protected override void OnHoverLost(InputState state)
{
background.FadeOut(fade_duration, Easing.OutQuint);
underscoreLine.FadeIn(fade_duration, Easing.OutQuint);
base.OnHoverLost(state);
}
}
}

View File

@ -0,0 +1,105 @@
// 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;
using osu.Game.Beatmaps;
using osu.Game.Beatmaps.Drawables;
using osu.Game.Graphics.Containers;
using osu.Game.Graphics.Sprites;
using OpenTK;
namespace osu.Game.Overlays.Profile.Sections.Historical
{
public class DrawableMostPlayedRow : DrawableProfileRow
{
private readonly BeatmapInfo beatmap;
private readonly int playCount;
private OsuHoverContainer mapperContainer;
public DrawableMostPlayedRow(BeatmapInfo beatmap, int playCount)
{
this.beatmap = beatmap;
this.playCount = playCount;
}
protected override Drawable CreateLeftVisual() => new DelayedLoadWrapper(new BeatmapSetCover(beatmap.BeatmapSet, BeatmapSetCoverType.List)
{
Anchor = Anchor.Centre,
Origin = Anchor.Centre,
FillMode = FillMode.Fit,
RelativeSizeAxes = Axes.Both,
OnLoadComplete = d => d.FadeInFromZero(500, Easing.OutQuint)
})
{
Origin = Anchor.CentreLeft,
Anchor = Anchor.CentreLeft,
RelativeSizeAxes = Axes.None,
Size = new Vector2(80, 50),
};
[BackgroundDependencyLoader(true)]
private void load(UserProfileOverlay profileOverlay)
{
LeftFlowContainer.Add(new BeatmapMetadataContainer(beatmap));
LeftFlowContainer.Add(new FillFlowContainer
{
RelativeSizeAxes = Axes.X,
AutoSizeAxes = Axes.Y,
Direction = FillDirection.Horizontal,
Children = new Drawable[]
{
new OsuSpriteText
{
Text = @"mapped by ",
TextSize = 12,
},
mapperContainer = new OsuHoverContainer
{
AutoSizeAxes = Axes.Both,
Children = new Drawable[]
{
new OsuSpriteText
{
Text = beatmap.Metadata.AuthorString,
TextSize = 12,
Font = @"Exo2.0-MediumItalic"
}
}
},
}
});
RightFlowContainer.Add(new FillFlowContainer
{
Anchor = Anchor.TopRight,
Origin = Anchor.TopRight,
AutoSizeAxes = Axes.Both,
Direction = FillDirection.Horizontal,
Children = new[]
{
new OsuSpriteText
{
Anchor = Anchor.BottomRight,
Origin = Anchor.BottomRight,
Text = playCount.ToString(),
TextSize = 18,
Font = @"Exo2.0-SemiBoldItalic"
},
new OsuSpriteText
{
Anchor = Anchor.BottomRight,
Origin = Anchor.BottomRight,
Text = @"times played ",
TextSize = 12,
Font = @"Exo2.0-RegularItalic"
},
}
});
if (profileOverlay != null)
mapperContainer.Action = () => profileOverlay.ShowUser(beatmap.BeatmapSet.Metadata.Author);
}
}
}

View File

@ -0,0 +1,51 @@
// 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.Linq;
using osu.Framework.Configuration;
using osu.Framework.Graphics;
using osu.Framework.Graphics.Containers;
using osu.Game.Online.API.Requests;
using osu.Game.Users;
namespace osu.Game.Overlays.Profile.Sections.Historical
{
public class PaginatedMostPlayedBeatmapContainer : PaginatedContainer
{
public PaginatedMostPlayedBeatmapContainer(Bindable<User> user)
:base(user, "Most Played Beatmaps", "No records. :(")
{
ItemsPerPage = 5;
ItemsContainer.Direction = FillDirection.Vertical;
}
protected override void ShowMore()
{
base.ShowMore();
var req = new GetUserMostPlayedBeatmapsRequest(User.Value.Id, VisiblePages++ * ItemsPerPage);
req.Success += beatmaps =>
{
ShowMoreButton.FadeTo(beatmaps.Count == ItemsPerPage ? 1 : 0);
ShowMoreLoading.Hide();
if (!beatmaps.Any() && VisiblePages == 1)
{
MissingText.Show();
return;
}
MissingText.Hide();
foreach (var beatmap in beatmaps)
{
ItemsContainer.Add(new DrawableMostPlayedRow(beatmap.GetBeatmapInfo(Rulesets), beatmap.PlayCount));
}
};
Api.Queue(req);
}
}
}

View File

@ -1,7 +1,9 @@
// 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.Game.Online.API.Requests;
using osu.Game.Overlays.Profile.Sections.Historical;
using osu.Game.Overlays.Profile.Sections.Ranks;
namespace osu.Game.Overlays.Profile.Sections
@ -14,7 +16,11 @@ namespace osu.Game.Overlays.Profile.Sections
public HistoricalSection()
{
Child = new PaginatedScoreContainer(ScoreType.Recent, User, "Recent Plays (24h)", "No performance records. :(");
Children = new Drawable[]
{
new PaginatedMostPlayedBeatmapContainer(User),
new PaginatedScoreContainer(ScoreType.Recent, User, "Recent Plays (24h)", "No performance records. :("),
};
}
}
}

View File

@ -9,7 +9,7 @@ using osu.Game.Rulesets.Scoring;
namespace osu.Game.Overlays.Profile.Sections.Ranks
{
public class DrawablePerformanceScore : DrawableScore
public class DrawablePerformanceScore : DrawableProfileScore
{
private readonly double? weight;
@ -23,7 +23,7 @@ namespace osu.Game.Overlays.Profile.Sections.Ranks
private void load(OsuColour colour)
{
double pp = Score.PP ?? 0;
Stats.Add(new OsuSpriteText
RightFlowContainer.Add(new OsuSpriteText
{
Text = $"{pp:0}pp",
Anchor = Anchor.TopRight,
@ -34,7 +34,7 @@ namespace osu.Game.Overlays.Profile.Sections.Ranks
if (weight.HasValue)
{
Stats.Add(new OsuSpriteText
RightFlowContainer.Add(new OsuSpriteText
{
Text = $"weighted: {pp * weight:0}pp ({weight:P0})",
Anchor = Anchor.TopRight,

View File

@ -0,0 +1,75 @@
// 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.Game.Graphics;
using osu.Game.Graphics.Sprites;
using osu.Game.Rulesets.Mods;
using osu.Game.Screens.Select.Leaderboards;
using osu.Game.Rulesets.Scoring;
using osu.Game.Rulesets.UI;
namespace osu.Game.Overlays.Profile.Sections.Ranks
{
public abstract class DrawableProfileScore : DrawableProfileRow
{
private readonly FillFlowContainer metadata;
private readonly ScoreModsContainer modsContainer;
protected readonly Score Score;
protected DrawableProfileScore(Score score)
{
Score = score;
RelativeSizeAxes = Axes.X;
Height = 60;
Children = new Drawable[]
{
modsContainer = new ScoreModsContainer
{
AutoSizeAxes = Axes.Y,
Anchor = Anchor.CentreRight,
Origin = Anchor.CentreRight,
Width = 60,
Margin = new MarginPadding { Right = 160 }
}
};
}
[BackgroundDependencyLoader(true)]
private void load(OsuColour colour)
{
RightFlowContainer.Add(new OsuSpriteText
{
Text = $"accuracy: {Score.Accuracy:P2}",
Anchor = Anchor.TopRight,
Origin = Anchor.TopRight,
Colour = colour.GrayA,
TextSize = 11,
Font = "Exo2.0-RegularItalic",
Depth = -1,
});
LeftFlowContainer.Add(new BeatmapMetadataContainer(Score.Beatmap));
LeftFlowContainer.Add(new OsuSpriteText
{
Text = Score.Date.LocalDateTime.ToShortDateString(),
TextSize = 11,
Colour = OsuColour.Gray(0xAA),
});
foreach (Mod mod in Score.Mods)
modsContainer.Add(new ModIcon(mod) { Scale = new Vector2(0.5f) });
}
protected override Drawable CreateLeftVisual() => new DrawableRank(Score.Rank)
{
RelativeSizeAxes = Axes.Y,
Width = 60,
FillMode = FillMode.Fit,
};
}
}

View File

@ -1,195 +0,0 @@
// 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.Game.Graphics;
using osu.Game.Graphics.Sprites;
using osu.Game.Rulesets.Mods;
using osu.Game.Screens.Select.Leaderboards;
using osu.Framework.Localisation;
using osu.Game.Rulesets.Scoring;
using osu.Game.Rulesets.UI;
using OpenTK.Graphics;
using osu.Framework.Graphics.Shapes;
using osu.Framework.Graphics.Cursor;
using osu.Framework.Input;
using osu.Framework.Extensions.Color4Extensions;
using osu.Game.Graphics.Containers;
namespace osu.Game.Overlays.Profile.Sections.Ranks
{
public abstract class DrawableScore : Container
{
private const int fade_duration = 200;
protected readonly FillFlowContainer<OsuSpriteText> Stats;
private readonly FillFlowContainer metadata;
private readonly ScoreModsContainer modsContainer;
protected readonly Score Score;
private readonly Box underscoreLine;
private readonly Box coloredBackground;
private readonly Container background;
protected DrawableScore(Score score)
{
Score = score;
RelativeSizeAxes = Axes.X;
Height = 60;
Children = new Drawable[]
{
background = new Container
{
RelativeSizeAxes = Axes.Both,
Masking = true,
CornerRadius = 3,
Alpha = 0,
EdgeEffect = new EdgeEffectParameters
{
Type = EdgeEffectType.Shadow,
Offset = new Vector2(0f, 1f),
Radius = 1f,
Colour = Color4.Black.Opacity(0.2f),
},
Child = coloredBackground = new Box { RelativeSizeAxes = Axes.Both }
},
new Container
{
RelativeSizeAxes = Axes.Both,
Anchor = Anchor.TopCentre,
Origin = Anchor.TopCentre,
Width = 0.97f,
Children = new Drawable[]
{
underscoreLine = new Box
{
Anchor = Anchor.BottomCentre,
Origin = Anchor.BottomCentre,
RelativeSizeAxes = Axes.X,
Height = 1,
},
new DrawableRank(score.Rank)
{
RelativeSizeAxes = Axes.Y,
Width = 60,
FillMode = FillMode.Fit,
},
Stats = new FillFlowContainer<OsuSpriteText>
{
RelativeSizeAxes = Axes.X,
AutoSizeAxes = Axes.Y,
Anchor = Anchor.CentreRight,
Origin = Anchor.CentreRight,
Direction = FillDirection.Vertical,
},
metadata = new FillFlowContainer
{
RelativeSizeAxes = Axes.X,
AutoSizeAxes = Axes.Y,
Anchor = Anchor.CentreLeft,
Origin = Anchor.CentreLeft,
Margin = new MarginPadding { Left = 70 },
Direction = FillDirection.Vertical,
Child = new OsuSpriteText
{
Text = score.Date.LocalDateTime.ToShortDateString(),
TextSize = 11,
Colour = OsuColour.Gray(0xAA),
Depth = -1,
},
},
modsContainer = new ScoreModsContainer
{
AutoSizeAxes = Axes.Y,
Anchor = Anchor.CentreRight,
Origin = Anchor.CentreRight,
Width = 60,
Margin = new MarginPadding { Right = 160 }
}
}
},
};
}
[BackgroundDependencyLoader(true)]
private void load(OsuColour colour, LocalisationEngine locale, BeatmapSetOverlay beatmapSetOverlay)
{
coloredBackground.Colour = underscoreLine.Colour = colour.Gray4;
Stats.Add(new OsuSpriteText
{
Text = $"accuracy: {Score.Accuracy:P2}",
Anchor = Anchor.TopRight,
Origin = Anchor.TopRight,
Colour = colour.GrayA,
TextSize = 11,
Font = "Exo2.0-RegularItalic",
Depth = -1,
});
metadata.Add(new MetadataContainer(Score.Beatmap.Metadata.Title, Score.Beatmap.Metadata.Artist)
{
AutoSizeAxes = Axes.Both,
Action = () =>
{
if (Score.Beatmap.OnlineBeatmapSetID.HasValue) beatmapSetOverlay?.ShowBeatmapSet(Score.Beatmap.OnlineBeatmapSetID.Value);
},
Child = new FillFlowContainer
{
AutoSizeAxes = Axes.Both,
Children = new Drawable[]
{
new OsuSpriteText
{
Current = locale.GetUnicodePreference(
$"{Score.Beatmap.Metadata.TitleUnicode ?? Score.Beatmap.Metadata.Title} [{Score.Beatmap.Version}] ",
$"{Score.Beatmap.Metadata.Title ?? Score.Beatmap.Metadata.TitleUnicode} [{Score.Beatmap.Version}] "
),
TextSize = 15,
Font = "Exo2.0-SemiBoldItalic",
},
new OsuSpriteText
{
Current = locale.GetUnicodePreference(Score.Beatmap.Metadata.ArtistUnicode, Score.Beatmap.Metadata.Artist),
TextSize = 12,
Padding = new MarginPadding { Top = 3 },
Font = "Exo2.0-RegularItalic",
},
},
},
});
foreach (Mod mod in Score.Mods)
modsContainer.Add(new ModIcon(mod) { Scale = new Vector2(0.5f) });
}
protected override bool OnClick(InputState state) => true;
protected override bool OnHover(InputState state)
{
background.FadeIn(fade_duration, Easing.OutQuint);
underscoreLine.FadeOut(fade_duration, Easing.OutQuint);
return true;
}
protected override void OnHoverLost(InputState state)
{
background.FadeOut(fade_duration, Easing.OutQuint);
underscoreLine.FadeIn(fade_duration, Easing.OutQuint);
base.OnHoverLost(state);
}
private class MetadataContainer : OsuHoverContainer, IHasTooltip
{
public string TooltipText { get; set; }
public MetadataContainer(string title, string artist)
{
TooltipText = $"{artist} - {title}";
}
}
}
}

View File

@ -8,7 +8,7 @@ using osu.Game.Rulesets.Scoring;
namespace osu.Game.Overlays.Profile.Sections.Ranks
{
public class DrawableTotalScore : DrawableScore
public class DrawableTotalScore : DrawableProfileScore
{
public DrawableTotalScore(Score score)
: base(score)
@ -18,7 +18,7 @@ namespace osu.Game.Overlays.Profile.Sections.Ranks
[BackgroundDependencyLoader]
private void load()
{
Stats.Add(new OsuSpriteText
RightFlowContainer.Add(new OsuSpriteText
{
Text = Score.TotalScore.ToString("#,###"),
Anchor = Anchor.TopRight,

View File

@ -51,7 +51,7 @@ namespace osu.Game.Overlays.Profile.Sections.Ranks
foreach (OnlineScore score in scores)
{
DrawableScore drawableScore;
DrawableProfileScore drawableScore;
switch (type)
{

View File

@ -97,6 +97,11 @@ namespace osu.Game.Overlays.Settings.Sections.Input
doubleValue.ValueChanged += newValue => base.Bindable.Value = newValue;
}
}
public SensitivitySetting()
{
KeyboardStep = 0.01f;
}
}
private class SensitivitySlider : OsuSliderBar<double>
@ -105,8 +110,6 @@ namespace osu.Game.Overlays.Settings.Sections.Input
public SensitivitySlider()
{
KeyboardStep = 0.01f;
Current.ValueChanged += newValue =>
{
if (!isDragging && Sensitivity != null)

View File

@ -159,8 +159,6 @@ namespace osu.Game.Overlays.Settings
public string TooltipText => "Revert to default";
public override bool HandleInput => true;
protected override bool OnMouseDown(InputState state, MouseDownEventArgs args) => true;
protected override bool OnMouseUp(InputState state, MouseUpEventArgs args) => true;

View File

@ -23,13 +23,12 @@ namespace osu.Game.Rulesets
public virtual IEnumerable<BeatmapStatistic> GetBeatmapStatistics(WorkingBeatmap beatmap) => new BeatmapStatistic[] { };
public IEnumerable<Mod> GetAllMods() => Enum.GetValues(typeof(ModType)).Cast<ModType>()
// Get all mod types as an IEnumerable<ModType>
.SelectMany(GetModsFor)
// Confine all mods of each mod type into a single IEnumerable<Mod>
.Where(mod => mod != null)
.SelectMany(GetModsFor)
// Filter out all null mods
.SelectMany(mod => (mod as MultiMod)?.Mods ?? new[] { mod });
.Where(mod => mod != null)
// Resolve MultiMods as their .Mods property
.SelectMany(mod => (mod as MultiMod)?.Mods ?? new[] { mod });
public abstract IEnumerable<Mod> GetModsFor(ModType type);
@ -66,6 +65,11 @@ namespace osu.Game.Rulesets
/// </summary>
public virtual int LegacyID => -1;
/// <summary>
/// A unique short name to reference this ruleset in online requests.
/// </summary>
public abstract string ShortName { get; }
/// <summary>
/// A list of available variant ids.
/// </summary>

View File

@ -13,6 +13,8 @@ namespace osu.Game.Rulesets
public string Name { get; set; }
public string ShortName { get; set; }
public string InstantiationInfo { get; set; }
public bool Available { get; set; }

View File

@ -83,7 +83,11 @@ namespace osu.Game.Rulesets
{
try
{
r.CreateInstance();
var instance = r.CreateInstance();
r.Name = instance.Description;
r.ShortName = instance.ShortName;
r.Available = true;
}
catch
@ -117,6 +121,7 @@ namespace osu.Game.Rulesets
private RulesetInfo createRulesetInfo(Ruleset ruleset) => new RulesetInfo
{
Name = ruleset.Description,
ShortName = ruleset.ShortName,
InstantiationInfo = ruleset.GetType().AssemblyQualifiedName,
ID = ruleset.LegacyID
};

View File

@ -16,8 +16,6 @@ namespace osu.Game.Screens.Play.HUD
public bool ReplayLoaded;
public override bool HandleInput => true;
public readonly PlaybackSettings PlaybackSettings;
//public readonly CollectionSettings CollectionSettings;
//public readonly DiscussionSettings DiscussionSettings;
@ -35,7 +33,7 @@ namespace osu.Game.Screens.Play.HUD
Direction = FillDirection.Vertical,
Spacing = new Vector2(0, 20),
Margin = new MarginPadding { Top = 100, Right = 10 },
Children = new []
Children = new[]
{
//CollectionSettings = new CollectionSettings(),
//DiscussionSettings = new DiscussionSettings(),

View File

@ -141,8 +141,6 @@ namespace osu.Game.Screens.Play
public override bool ReceiveMouseInputAt(Vector2 screenSpacePos) => true;
public override bool HandleInput => true;
protected override bool OnKeyDown(InputState state, KeyDownEventArgs args) => Target.Children.Any(c => c.TriggerOnKeyDown(state, args));
protected override bool OnKeyUp(InputState state, KeyUpEventArgs args) => Target.Children.Any(c => c.TriggerOnKeyUp(state, args));

View File

@ -34,7 +34,6 @@ namespace osu.Game.Screens.Select
public IEnumerable<BeatmapSetInfo> Beatmaps
{
get { return groups.Select(g => g.BeatmapSet); }
set
{
scrollableContent.Clear(false);
@ -52,7 +51,7 @@ namespace osu.Game.Screens.Select
Schedule(() =>
{
foreach (var g in newGroups)
if (g != null) addGroup(g);
addGroup(g);
computeYPositions();
BeatmapsChanged?.Invoke();
@ -95,50 +94,31 @@ namespace osu.Game.Screens.Select
});
}
public void AddBeatmap(BeatmapSetInfo beatmapSet)
{
Schedule(() =>
{
var group = createGroup(beatmapSet);
if (group == null)
return;
addGroup(group);
computeYPositions();
if (selectedGroup == null)
selectGroup(group);
});
}
public void RemoveBeatmap(BeatmapSetInfo beatmapSet)
{
Schedule(() => removeGroup(groups.Find(b => b.BeatmapSet.ID == beatmapSet.ID)));
}
public void UpdateBeatmap(BeatmapInfo beatmap)
public void UpdateBeatmapSet(BeatmapSetInfo beatmapSet)
{
// todo: this method should not run more than once for the same BeatmapSetInfo.
var set = manager.QueryBeatmapSet(s => s.ID == beatmap.BeatmapSetInfoID);
// todo: this method should be smarter as to not recreate panels that haven't changed, etc.
var group = groups.Find(b => b.BeatmapSet.ID == set.ID);
var oldGroup = groups.Find(b => b.BeatmapSet.ID == beatmapSet.ID);
int i = groups.IndexOf(group);
if (i >= 0)
groups.RemoveAt(i);
var newGroup = createGroup(beatmapSet);
var newGroup = createGroup(set);
int index = groups.IndexOf(oldGroup);
if (index >= 0)
groups.RemoveAt(index);
if (newGroup != null)
{
if (i >= 0)
groups.Insert(i, newGroup);
if (index >= 0)
groups.Insert(index, newGroup);
else
groups.Add(newGroup);
addGroup(newGroup);
}
bool hadSelection = selectedGroup == group;
bool hadSelection = selectedGroup == oldGroup;
if (hadSelection && newGroup == null)
selectedGroup = null;
@ -149,8 +129,10 @@ namespace osu.Game.Screens.Select
if (hadSelection && newGroup != null)
{
var newSelection =
newGroup.BeatmapPanels.Find(p => p.Beatmap.ID == selectedPanel?.Beatmap.ID) ??
newGroup.BeatmapPanels[Math.Min(newGroup.BeatmapPanels.Count - 1, group.BeatmapPanels.IndexOf(selectedPanel))];
newGroup.BeatmapPanels.Find(p => p.Beatmap.ID == selectedPanel?.Beatmap.ID);
if(newSelection == null && oldGroup != null && selectedPanel != null)
newSelection = newGroup.BeatmapPanels[Math.Min(newGroup.BeatmapPanels.Count - 1, oldGroup.BeatmapPanels.IndexOf(selectedPanel))];
selectGroup(newGroup, newSelection);
}
@ -308,8 +290,6 @@ namespace osu.Game.Screens.Select
if (newCriteria != null)
criteria = newCriteria;
if (!IsLoaded) return;
Action perform = delegate
{
filterTask = null;
@ -381,6 +361,10 @@ namespace osu.Game.Screens.Select
private void addGroup(BeatmapGroup group)
{
// prevent duplicates by concurrent independent actions trying to add a group
if (groups.Any(g => g.BeatmapSet.ID == group.BeatmapSet.ID))
return;
groups.Add(group);
panels.Add(group.Header);
panels.AddRange(group.BeatmapPanels);

View File

@ -2,6 +2,7 @@
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
using System;
using System.Linq;
using System.Threading;
using OpenTK;
using OpenTK.Input;
@ -203,8 +204,23 @@ namespace osu.Game.Screens.Select
Push(new Editor());
}
private void onBeatmapRestored(BeatmapInfo b) => Schedule(() => carousel.UpdateBeatmap(b));
private void onBeatmapHidden(BeatmapInfo b) => Schedule(() => carousel.UpdateBeatmap(b));
private void onBeatmapRestored(BeatmapInfo beatmap)
{
Schedule(() =>
{
var beatmapSet = beatmaps.QueryBeatmapSet(s => s.ID == beatmap.BeatmapSetInfoID);
carousel.UpdateBeatmapSet(beatmapSet);
});
}
private void onBeatmapHidden(BeatmapInfo beatmap)
{
Schedule(() =>
{
var beatmapSet = beatmaps.QueryBeatmapSet(s => s.ID == beatmap.BeatmapSetInfoID);
carousel.UpdateBeatmapSet(beatmapSet);
});
}
private void carouselBeatmapsLoaded()
{
@ -255,11 +271,11 @@ namespace osu.Game.Screens.Select
UpdateBeatmap(Beatmap.Value);
};
selectionChangedDebounce?.Cancel();
if (beatmap?.Equals(beatmapNoDebounce) == true)
return;
selectionChangedDebounce?.Cancel();
beatmapNoDebounce = beatmap;
if (beatmap == null)
@ -293,7 +309,14 @@ namespace osu.Game.Screens.Select
carousel.Filter(criteria, debounce);
}
private void onBeatmapSetAdded(BeatmapSetInfo s) => Schedule(() => addBeatmapSet(s));
private void onBeatmapSetAdded(BeatmapSetInfo s)
{
Schedule(() =>
{
carousel.UpdateBeatmapSet(s);
carousel.SelectBeatmap(s.Beatmaps.First());
});
}
private void onBeatmapSetRemoved(BeatmapSetInfo s) => Schedule(() => removeBeatmapSet(s));
@ -436,8 +459,6 @@ namespace osu.Game.Screens.Select
}
}
private void addBeatmapSet(BeatmapSetInfo beatmapSet) => carousel.AddBeatmap(beatmapSet);
private void removeBeatmapSet(BeatmapSetInfo beatmapSet)
{
carousel.RemoveBeatmap(beatmapSet);

View File

@ -75,7 +75,7 @@ namespace osu.Game.Users
public bool Active;
[JsonProperty(@"interests")]
public string Intrerests;
public string Interests;
[JsonProperty(@"occupation")]
public string Occupation;

View File

@ -285,15 +285,24 @@
<Compile Include="Migrations\20171119065731_AddBeatmapOnlineIDUniqueConstraint.Designer.cs">
<DependentUpon>20171119065731_AddBeatmapOnlineIDUniqueConstraint.cs</DependentUpon>
</Compile>
<Compile Include="Migrations\20171209034410_AddRulesetInfoShortName.cs" />
<Compile Include="Migrations\20171209034410_AddRulesetInfoShortName.Designer.cs">
<DependentUpon>20171209034410_AddRulesetInfoShortName.cs</DependentUpon>
</Compile>
<Compile Include="Migrations\OsuDbContextModelSnapshot.cs" />
<Compile Include="Online\API\Requests\GetBeatmapSetRequest.cs" />
<Compile Include="Online\API\Requests\GetBeatmapSetsResponse.cs" />
<Compile Include="Online\API\Requests\APIResponseBeatmapSet.cs" />
<Compile Include="Online\API\Requests\GetUserMostPlayedBeatmapsRequest.cs" />
<Compile Include="Overlays\BeatmapSet\Scores\ClickableUsername.cs" />
<Compile Include="Overlays\BeatmapSet\Scores\DrawableScore.cs" />
<Compile Include="Overlays\BeatmapSet\Scores\DrawableTopScore.cs" />
<Compile Include="Overlays\BeatmapSet\Scores\ScoresContainer.cs" />
<Compile Include="Online\API\Requests\GetUserBeatmapsRequest.cs" />
<Compile Include="Overlays\Profile\Sections\BeatmapMetadataContainer.cs" />
<Compile Include="Overlays\Profile\Sections\Beatmaps\PaginatedBeatmapContainer.cs" />
<Compile Include="Overlays\Profile\Sections\DrawableProfileRow.cs" />
<Compile Include="Overlays\Profile\Sections\Historical\DrawableMostPlayedRow.cs" />
<Compile Include="Overlays\Profile\Sections\Historical\PaginatedMostPlayedBeatmapContainer.cs" />
<Compile Include="Overlays\Profile\Sections\Kudosu\KudosuInfo.cs" />
<Compile Include="Overlays\Profile\Sections\PaginatedContainer.cs" />
<Compile Include="Overlays\Profile\Sections\Ranks\DrawablePerformanceScore.cs" />
@ -483,7 +492,7 @@
<Compile Include="Overlays\Notifications\ProgressNotification.cs" />
<Compile Include="Overlays\Notifications\SimpleNotification.cs" />
<Compile Include="Overlays\OnScreenDisplay.cs" />
<Compile Include="Overlays\Profile\Sections\Ranks\DrawableScore.cs" />
<Compile Include="Overlays\Profile\Sections\Ranks\DrawableProfileScore.cs" />
<Compile Include="Overlays\Profile\ProfileHeader.cs" />
<Compile Include="Overlays\Profile\ProfileSection.cs" />
<Compile Include="Overlays\Profile\RankChart.cs" />
@ -820,6 +829,9 @@
<Compile Include="Overlays\BeatmapSet\SuccessRate.cs" />
<Compile Include="Overlays\BeatmapSet\PreviewButton.cs" />
</ItemGroup>
<ItemGroup>
<Service Include="{82A7F48D-3B50-4B1E-B82E-3ADA8210C358}" />
</ItemGroup>
<Import Project="$(MSBuildBinPath)\Microsoft.CSharp.targets" />
<!-- To modify your build process, add your task inside one of the targets below and uncomment it.
Other similar extension points exist, see Microsoft.Common.targets.