private void load(OsuColour colours, BeatmapDifficultyCache difficultyCache) { Colour = colours.BlueLighter; if (gameplayState != null) { performanceCalculator = gameplayState.Ruleset.CreatePerformanceCalculator(); clonedMods = gameplayState.Mods.Select(m => m.DeepClone()).ToArray(); scoreInfo = new ScoreInfo(gameplayState.Score.ScoreInfo.BeatmapInfo, gameplayState.Score.ScoreInfo.Ruleset) { Mods = clonedMods }; var gameplayWorkingBeatmap = new GameplayWorkingBeatmap(gameplayState.Beatmap); difficultyCache.GetTimedDifficultyAttributesAsync(gameplayWorkingBeatmap, gameplayState.Ruleset, clonedMods, loadCancellationSource.Token) .ContinueWith(task => Schedule(() => { timedAttributes = task.GetResultSafely(); IsValid = true; if (lastJudgement != null) { onJudgementChanged(lastJudgement); } }), TaskContinuationOptions.OnlyOnRanToCompletion); } }
private void load() { InterpretedDifficulty.Default = BeatmapDifficultyCache.GetDifficultyRating(EditorBeatmap.BeatmapInfo.StarRating); InterpretedDifficulty.SetDefault(); Child = new Container { RelativeSizeAxes = Axes.Both, Child = new GridContainer { RelativeSizeAxes = Axes.Both, ColumnDimensions = new[] { new Dimension(), new Dimension(GridSizeMode.Absolute, 250), }, Content = new[] { new Drawable[] { IssueList = new IssueList(), new IssueSettings(), }, } } }; }
private void load(SkinManager skinManager, IBeatmap beatmap, BeatmapDifficultyCache difficultyCache) { RegisterPool <TouchHold, DrawableTouchHold>(2); // handle colouring of playfield elements beatmapDifficulty = difficultyCache.GetBindableDifficulty(beatmap.BeatmapInfo); skin = skinManager.CurrentSkin.GetBoundCopy(); sentakkiRulesetConfig?.BindWith(SentakkiRulesetSettings.RingColor, ringColor); }
private void load([CanBeNull] IBindable <WorkingBeatmap> workingBeatmap, [CanBeNull] BeatmapDifficultyCache difficultyCache) { if (workingBeatmap == null || difficultyCache == null) { return; } var beatmapDifficulty = difficultyCache.GetBindableDifficulty(beatmap.BeatmapInfo).Value; LoadComponentAsync(new BeatmapInfoWedge(workingBeatmap.Value, mods.Value, beatmapDifficulty ?? new StarDifficulty()), Add); }
private void load(BeatmapDifficultyCache beatmapDifficultyCache) { var beatmap = score.Beatmap; var metadata = beatmap.BeatmapSet?.Metadata ?? beatmap.Metadata; var creator = metadata.Author?.Username; var topStatistics = new List <StatisticDisplay> { new AccuracyStatistic(score.Accuracy), new ComboStatistic(score.MaxCombo, !score.Statistics.TryGetValue(HitResult.Miss, out var missCount) || missCount == 0), new PerformanceStatistic(score), }; var bottomStatistics = new List <HitResultStatistic>(); foreach (var result in score.GetStatisticsForDisplay()) { bottomStatistics.Add(new HitResultStatistic(result)); } statisticDisplays.AddRange(topStatistics); statisticDisplays.AddRange(bottomStatistics); var starDifficulty = beatmapDifficultyCache.GetDifficultyAsync(beatmap, score.Ruleset, score.Mods).Result; InternalChildren = new Drawable[] { new FillFlowContainer { RelativeSizeAxes = Axes.Both, Direction = FillDirection.Vertical, Spacing = new Vector2(20), Children = new Drawable[] { new FillFlowContainer { Anchor = Anchor.TopCentre, Origin = Anchor.TopCentre, RelativeSizeAxes = Axes.X, AutoSizeAxes = Axes.Y, Direction = FillDirection.Vertical, Children = new Drawable[] { new OsuSpriteText { Anchor = Anchor.TopCentre, Origin = Anchor.TopCentre, Text = new LocalisedString((metadata.TitleUnicode, metadata.Title)), Font = OsuFont.Torus.With(size: 20, weight: FontWeight.SemiBold), MaxWidth = ScorePanel.EXPANDED_WIDTH - padding * 2, Truncate = true, },
public ScoreManager(RulesetStore rulesets, Func <BeatmapManager> beatmaps, Storage storage, RealmAccess realm, Scheduler scheduler, BeatmapDifficultyCache difficultyCache = null, OsuConfigManager configManager = null) : base(storage, realm) { this.scheduler = scheduler; this.difficultyCache = difficultyCache; this.configManager = configManager; scoreImporter = new ScoreImporter(rulesets, beatmaps, storage, realm) { PostNotification = obj => PostNotification?.Invoke(obj) }; }
private void load(BeatmapDifficultyCache difficultyCache) { var metadata = beatmap.BeatmapInfo.Metadata; AutoSizeAxes = Axes.Both; Children = new Drawable[] { new FillFlowContainer { AutoSizeAxes = Axes.Both, Origin = Anchor.TopCentre, Anchor = Anchor.TopCentre, Direction = FillDirection.Vertical, Children = new[]
private void load(OsuColour colours, BeatmapDifficultyCache difficultyCache) { Colour = colours.BlueLighter; if (gameplayState != null) { clonedMods = gameplayState.Mods.Select(m => m.DeepClone()).ToArray(); var gameplayWorkingBeatmap = new GameplayWorkingBeatmap(gameplayState.Beatmap); difficultyCache.GetTimedDifficultyAttributesAsync(gameplayWorkingBeatmap, gameplayState.Ruleset, clonedMods, loadCancellationSource.Token) .ContinueWith(r => Schedule(() => { timedAttributes = r.Result; IsValid = true; if (lastJudgement != null) { onJudgementChanged(lastJudgement); } }), TaskContinuationOptions.OnlyOnRanToCompletion); } }
private void load() { try { using (var str = File.OpenRead(typeof(OsuGameBase).Assembly.Location)) VersionHash = str.ComputeMD5Hash(); } catch { // special case for android builds, which can't read DLLs from a packed apk. // should eventually be handled in a better way. VersionHash = $"{Version}-{RuntimeInfo.OS}".ComputeMD5Hash(); } Resources.AddStore(new DllResourceStore(OsuResources.ResourceAssembly)); dependencies.Cache(contextFactory = new DatabaseContextFactory(Storage)); dependencies.CacheAs(Storage); var largeStore = new LargeTextureStore(Host.CreateTextureLoaderStore(new NamespacedResourceStore <byte[]>(Resources, @"Textures"))); largeStore.AddStore(Host.CreateTextureLoaderStore(new OnlineStore())); dependencies.Cache(largeStore); dependencies.CacheAs(this); dependencies.CacheAs(LocalConfig); AddFont(Resources, @"Fonts/osuFont"); AddFont(Resources, @"Fonts/Torus-Regular"); AddFont(Resources, @"Fonts/Torus-Light"); AddFont(Resources, @"Fonts/Torus-SemiBold"); AddFont(Resources, @"Fonts/Torus-Bold"); AddFont(Resources, @"Fonts/Noto-Basic"); AddFont(Resources, @"Fonts/Noto-Hangul"); AddFont(Resources, @"Fonts/Noto-CJK-Basic"); AddFont(Resources, @"Fonts/Noto-CJK-Compatibility"); AddFont(Resources, @"Fonts/Noto-Thai"); AddFont(Resources, @"Fonts/Venera-Light"); AddFont(Resources, @"Fonts/Venera-Bold"); AddFont(Resources, @"Fonts/Venera-Black"); Audio.Samples.PlaybackConcurrency = SAMPLE_CONCURRENCY; runMigrations(); dependencies.Cache(SkinManager = new SkinManager(Storage, contextFactory, Host, Audio, new NamespacedResourceStore <byte[]>(Resources, "Skins/Legacy"))); dependencies.CacheAs <ISkinSource>(SkinManager); // needs to be done here rather than inside SkinManager to ensure thread safety of CurrentSkinInfo. SkinManager.ItemRemoved.BindValueChanged(weakRemovedInfo => { if (weakRemovedInfo.NewValue.TryGetTarget(out var removedInfo)) { Schedule(() => { // check the removed skin is not the current user choice. if it is, switch back to default. if (removedInfo.ID == SkinManager.CurrentSkinInfo.Value.ID) { SkinManager.CurrentSkinInfo.Value = SkinInfo.Default; } }); } }); EndpointConfiguration endpoints = UseDevelopmentServer ? (EndpointConfiguration) new DevelopmentEndpointConfiguration() : new ProductionEndpointConfiguration(); dependencies.CacheAs(API ??= new APIAccess(LocalConfig, endpoints)); dependencies.CacheAs(spectatorStreaming = new SpectatorStreamingClient(endpoints)); dependencies.CacheAs(multiplayerClient = new MultiplayerClient(endpoints)); var defaultBeatmap = new DummyWorkingBeatmap(Audio, Textures); dependencies.Cache(RulesetStore = new RulesetStore(contextFactory, Storage)); dependencies.Cache(FileStore = new FileStore(contextFactory, Storage)); // ordering is important here to ensure foreign keys rules are not broken in ModelStore.Cleanup() dependencies.Cache(ScoreManager = new ScoreManager(RulesetStore, () => BeatmapManager, Storage, API, contextFactory, Host, () => DifficultyCache, LocalConfig)); dependencies.Cache(BeatmapManager = new BeatmapManager(Storage, contextFactory, RulesetStore, API, Audio, Host, defaultBeatmap, true)); // this should likely be moved to ArchiveModelManager when another case appers where it is necessary // to have inter-dependent model managers. this could be obtained with an IHasForeign<T> interface to // allow lookups to be done on the child (ScoreManager in this case) to perform the cascading delete. List <ScoreInfo> getBeatmapScores(BeatmapSetInfo set) { var beatmapIds = BeatmapManager.QueryBeatmaps(b => b.BeatmapSetInfoID == set.ID).Select(b => b.ID).ToList(); return(ScoreManager.QueryScores(s => beatmapIds.Contains(s.Beatmap.ID)).ToList()); } BeatmapManager.ItemRemoved.BindValueChanged(i => { if (i.NewValue.TryGetTarget(out var item)) { ScoreManager.Delete(getBeatmapScores(item), true); } }); BeatmapManager.ItemUpdated.BindValueChanged(i => { if (i.NewValue.TryGetTarget(out var item)) { ScoreManager.Undelete(getBeatmapScores(item), true); } }); dependencies.Cache(DifficultyCache = new BeatmapDifficultyCache()); AddInternal(DifficultyCache); dependencies.Cache(UserCache = new UserLookupCache()); AddInternal(UserCache); var scorePerformanceManager = new ScorePerformanceCache(); dependencies.Cache(scorePerformanceManager); AddInternal(scorePerformanceManager); dependencies.Cache(KeyBindingStore = new KeyBindingStore(contextFactory, RulesetStore)); dependencies.Cache(SettingsStore = new SettingsStore(contextFactory)); dependencies.Cache(RulesetConfigCache = new RulesetConfigCache(SettingsStore)); dependencies.Cache(new SessionStatics()); dependencies.Cache(new OsuColour()); RegisterImportHandler(BeatmapManager); RegisterImportHandler(ScoreManager); RegisterImportHandler(SkinManager); // drop track volume game-wide to leave some head-room for UI effects / samples. // this means that for the time being, gameplay sample playback is louder relative to the audio track, compared to stable. // we may want to revisit this if users notice or complain about the difference (consider this a bit of a trial). Audio.Tracks.AddAdjustment(AdjustableProperty.Volume, globalTrackVolumeAdjust); Beatmap = new NonNullableBindable <WorkingBeatmap>(defaultBeatmap); dependencies.CacheAs <IBindable <WorkingBeatmap> >(Beatmap); dependencies.CacheAs(Beatmap); FileStore.Cleanup(); // add api components to hierarchy. if (API is APIAccess apiAccess) { AddInternal(apiAccess); } AddInternal(spectatorStreaming); AddInternal(multiplayerClient); AddInternal(RulesetConfigCache); MenuCursorContainer = new MenuCursorContainer { RelativeSizeAxes = Axes.Both }; GlobalActionContainer globalBindings; MenuCursorContainer.Child = globalBindings = new GlobalActionContainer(this) { RelativeSizeAxes = Axes.Both, Child = content = new OsuTooltipContainer(MenuCursorContainer.Cursor) { RelativeSizeAxes = Axes.Both } }; base.Content.Add(CreateScalingContainer().WithChild(MenuCursorContainer)); KeyBindingStore.Register(globalBindings); dependencies.Cache(globalBindings); PreviewTrackManager previewTrackManager; dependencies.Cache(previewTrackManager = new PreviewTrackManager()); Add(previewTrackManager); AddInternal(MusicController = new MusicController()); dependencies.CacheAs(MusicController); Ruleset.BindValueChanged(onRulesetChanged); }
private void load(ReadableKeyCombinationProvider keyCombinationProvider) { try { using (var str = File.OpenRead(typeof(OsuGameBase).Assembly.Location)) VersionHash = str.ComputeMD5Hash(); } catch { // special case for android builds, which can't read DLLs from a packed apk. // should eventually be handled in a better way. VersionHash = $"{Version}-{RuntimeInfo.OS}".ComputeMD5Hash(); } Resources.AddStore(new DllResourceStore(OsuResources.ResourceAssembly)); if (Storage.Exists(DatabaseContextFactory.DATABASE_NAME)) { dependencies.Cache(EFContextFactory = new DatabaseContextFactory(Storage)); } dependencies.Cache(realm = new RealmAccess(Storage, "client", EFContextFactory)); dependencies.CacheAs <RulesetStore>(RulesetStore = new RealmRulesetStore(realm, Storage)); dependencies.CacheAs <IRulesetStore>(RulesetStore); Decoder.RegisterDependencies(RulesetStore); // Backup is taken here rather than in EFToRealmMigrator to avoid recycling realm contexts // after initial usages below. It can be moved once a direction is established for handling re-subscription. // See https://github.com/ppy/osu/pull/16547 for more discussion. if (EFContextFactory != null) { const string backup_folder = "backups"; string migration = $"before_final_migration_{DateTimeOffset.UtcNow.ToUnixTimeSeconds()}"; EFContextFactory.CreateBackup(Path.Combine(backup_folder, $"client.{migration}.db")); realm.CreateBackup(Path.Combine(backup_folder, $"client.{migration}.realm")); using (var source = Storage.GetStream("collection.db")) { if (source != null) { using (var destination = Storage.GetStream(Path.Combine(backup_folder, $"collection.{migration}.db"), FileAccess.Write, FileMode.CreateNew)) source.CopyTo(destination); } } } dependencies.CacheAs(Storage); var largeStore = new LargeTextureStore(Host.CreateTextureLoaderStore(new NamespacedResourceStore <byte[]>(Resources, @"Textures"))); largeStore.AddStore(Host.CreateTextureLoaderStore(new OnlineStore())); dependencies.Cache(largeStore); dependencies.CacheAs(this); dependencies.CacheAs(LocalConfig); InitialiseFonts(); Audio.Samples.PlaybackConcurrency = SAMPLE_CONCURRENCY; dependencies.Cache(SkinManager = new SkinManager(Storage, realm, Host, Resources, Audio, Scheduler)); dependencies.CacheAs <ISkinSource>(SkinManager); EndpointConfiguration endpoints = UseDevelopmentServer ? (EndpointConfiguration) new DevelopmentEndpointConfiguration() : new ProductionEndpointConfiguration(); MessageFormatter.WebsiteRootUrl = endpoints.WebsiteRootUrl; dependencies.CacheAs(API ??= new APIAccess(LocalConfig, endpoints, VersionHash)); dependencies.CacheAs(spectatorClient = new OnlineSpectatorClient(endpoints)); dependencies.CacheAs(multiplayerClient = new OnlineMultiplayerClient(endpoints)); var defaultBeatmap = new DummyWorkingBeatmap(Audio, Textures); // ordering is important here to ensure foreign keys rules are not broken in ModelStore.Cleanup() dependencies.Cache(ScoreManager = new ScoreManager(RulesetStore, () => BeatmapManager, Storage, realm, Scheduler, () => difficultyCache, LocalConfig)); dependencies.Cache(BeatmapManager = new BeatmapManager(Storage, realm, RulesetStore, API, Audio, Resources, Host, defaultBeatmap, performOnlineLookups: true)); dependencies.Cache(BeatmapDownloader = new BeatmapModelDownloader(BeatmapManager, API)); dependencies.Cache(ScoreDownloader = new ScoreModelDownloader(ScoreManager, API)); dependencies.Cache(difficultyCache = new BeatmapDifficultyCache()); AddInternal(difficultyCache); dependencies.Cache(userCache = new UserLookupCache()); AddInternal(userCache); dependencies.Cache(beatmapCache = new BeatmapLookupCache()); AddInternal(beatmapCache); var scorePerformanceManager = new ScorePerformanceCache(); dependencies.Cache(scorePerformanceManager); AddInternal(scorePerformanceManager); dependencies.CacheAs <IRulesetConfigCache>(rulesetConfigCache = new RulesetConfigCache(realm, RulesetStore)); var powerStatus = CreateBatteryInfo(); if (powerStatus != null) { dependencies.CacheAs(powerStatus); } dependencies.Cache(SessionStatics = new SessionStatics()); dependencies.Cache(new OsuColour()); RegisterImportHandler(BeatmapManager); RegisterImportHandler(ScoreManager); RegisterImportHandler(SkinManager); // drop track volume game-wide to leave some head-room for UI effects / samples. // this means that for the time being, gameplay sample playback is louder relative to the audio track, compared to stable. // we may want to revisit this if users notice or complain about the difference (consider this a bit of a trial). Audio.Tracks.AddAdjustment(AdjustableProperty.Volume, globalTrackVolumeAdjust); Beatmap = new NonNullableBindable <WorkingBeatmap>(defaultBeatmap); dependencies.CacheAs <IBindable <WorkingBeatmap> >(Beatmap); dependencies.CacheAs(Beatmap); // add api components to hierarchy. if (API is APIAccess apiAccess) { AddInternal(apiAccess); } AddInternal(spectatorClient); AddInternal(multiplayerClient); AddInternal(rulesetConfigCache); GlobalActionContainer globalBindings; base.Content.Add(new SafeAreaContainer { SafeAreaOverrideEdges = SafeAreaOverrideEdges, RelativeSizeAxes = Axes.Both, Child = CreateScalingContainer().WithChildren(new Drawable[] { (MenuCursorContainer = new MenuCursorContainer { RelativeSizeAxes = Axes.Both }).WithChild(content = new OsuTooltipContainer(MenuCursorContainer.Cursor) { RelativeSizeAxes = Axes.Both }), // to avoid positional input being blocked by children, ensure the GlobalActionContainer is above everything. globalBindings = new GlobalActionContainer(this) }) }); KeyBindingStore = new RealmKeyBindingStore(realm, keyCombinationProvider); KeyBindingStore.Register(globalBindings, RulesetStore.AvailableRulesets); dependencies.Cache(globalBindings); PreviewTrackManager previewTrackManager; dependencies.Cache(previewTrackManager = new PreviewTrackManager(BeatmapManager.BeatmapTrackStore)); Add(previewTrackManager); AddInternal(MusicController = new MusicController()); dependencies.CacheAs(MusicController); Ruleset.BindValueChanged(onRulesetChanged); Beatmap.BindValueChanged(onBeatmapChanged); }
private void load(BeatmapDifficultyCache beatmapDifficultyCache) { var beatmap = score.BeatmapInfo; var metadata = beatmap.BeatmapSet?.Metadata ?? beatmap.Metadata; string creator = metadata.Author.Username; var topStatistics = new List <StatisticDisplay> { new AccuracyStatistic(score.Accuracy), new ComboStatistic(score.MaxCombo, !score.Statistics.TryGetValue(HitResult.Miss, out int missCount) || missCount == 0), new PerformanceStatistic(score), }; var bottomStatistics = new List <HitResultStatistic>(); foreach (var result in score.GetStatisticsForDisplay()) { bottomStatistics.Add(new HitResultStatistic(result)); } statisticDisplays.AddRange(topStatistics); statisticDisplays.AddRange(bottomStatistics); var starDifficulty = beatmapDifficultyCache.GetDifficultyAsync(beatmap, score.Ruleset, score.Mods).GetResultSafely(); AddInternal(new FillFlowContainer { RelativeSizeAxes = Axes.Both, Direction = FillDirection.Vertical, Spacing = new Vector2(20), Children = new Drawable[] { new FillFlowContainer { Anchor = Anchor.TopCentre, Origin = Anchor.TopCentre, RelativeSizeAxes = Axes.X, AutoSizeAxes = Axes.Y, Direction = FillDirection.Vertical, Children = new Drawable[] { new OsuSpriteText { Anchor = Anchor.TopCentre, Origin = Anchor.TopCentre, Text = new RomanisableString(metadata.TitleUnicode, metadata.Title), Font = OsuFont.Torus.With(size: 20, weight: FontWeight.SemiBold), MaxWidth = ScorePanel.EXPANDED_WIDTH - padding * 2, Truncate = true, }, new OsuSpriteText { Anchor = Anchor.TopCentre, Origin = Anchor.TopCentre, Text = new RomanisableString(metadata.ArtistUnicode, metadata.Artist), Font = OsuFont.Torus.With(size: 14, weight: FontWeight.SemiBold), MaxWidth = ScorePanel.EXPANDED_WIDTH - padding * 2, Truncate = true, }, new Container { Anchor = Anchor.TopCentre, Origin = Anchor.TopCentre, Margin = new MarginPadding { Top = 40 }, RelativeSizeAxes = Axes.X, Height = 230, Child = new AccuracyCircle(score, withFlair) { Anchor = Anchor.Centre, Origin = Anchor.Centre, RelativeSizeAxes = Axes.Both, FillMode = FillMode.Fit, } }, scoreCounter = new TotalScoreCounter { Margin = new MarginPadding { Top = 0, Bottom = 5 }, Current = { Value = 0 }, Alpha = 0, AlwaysPresent = true }, starAndModDisplay = new FillFlowContainer { Anchor = Anchor.TopCentre, Origin = Anchor.TopCentre, AutoSizeAxes = Axes.Both, Spacing = new Vector2(5, 0), }, new FillFlowContainer { Anchor = Anchor.TopCentre, Origin = Anchor.TopCentre, Direction = FillDirection.Vertical, AutoSizeAxes = Axes.Both, Children = new Drawable[] { new OsuSpriteText { Anchor = Anchor.TopCentre, Origin = Anchor.TopCentre, Text = beatmap.DifficultyName, Font = OsuFont.Torus.With(size: 16, weight: FontWeight.SemiBold), }, new OsuTextFlowContainer(s => s.Font = OsuFont.Torus.With(size: 12)) { Anchor = Anchor.TopCentre, Origin = Anchor.TopCentre, AutoSizeAxes = Axes.Both, Direction = FillDirection.Horizontal, }.With(t => { if (!string.IsNullOrEmpty(creator)) { t.AddText("mapped by "); t.AddText(creator, s => s.Font = s.Font.With(weight: FontWeight.SemiBold)); } }) } }, } }, new FillFlowContainer { RelativeSizeAxes = Axes.X, AutoSizeAxes = Axes.Y, Direction = FillDirection.Vertical, Spacing = new Vector2(0, 5), Children = new Drawable[] { new GridContainer { RelativeSizeAxes = Axes.X, AutoSizeAxes = Axes.Y, Content = new[] { topStatistics.Cast <Drawable>().ToArray() }, RowDimensions = new[] { new Dimension(GridSizeMode.AutoSize), } }, new GridContainer { RelativeSizeAxes = Axes.X, AutoSizeAxes = Axes.Y, Content = new[] { bottomStatistics.Where(s => s.Result <= HitResult.Perfect).ToArray() }, RowDimensions = new[] { new Dimension(GridSizeMode.AutoSize), } }, new GridContainer { RelativeSizeAxes = Axes.X, AutoSizeAxes = Axes.Y, Content = new[] { bottomStatistics.Where(s => s.Result > HitResult.Perfect).ToArray() }, RowDimensions = new[] { new Dimension(GridSizeMode.AutoSize), } } } } } }); if (score.Date != default) { AddInternal(new PlayedOnText(score.Date)); } if (starDifficulty != null) { starAndModDisplay.Add(new StarRatingDisplay(starDifficulty.Value) { Anchor = Anchor.CentreLeft, Origin = Anchor.CentreLeft }); } if (score.Mods.Any()) { starAndModDisplay.Add(new ModDisplay { Anchor = Anchor.CentreLeft, Origin = Anchor.CentreLeft, ExpansionMode = ExpansionMode.AlwaysExpanded, Scale = new Vector2(0.5f), Current = { Value = score.Mods } }); } }
public PerformanceBreakdownCalculator(IBeatmap playableBeatmap, BeatmapDifficultyCache difficultyCache, ScorePerformanceCache performanceCache) { this.playableBeatmap = playableBeatmap; this.difficultyCache = difficultyCache; this.performanceCache = performanceCache; }
private void load(ReadableKeyCombinationProvider keyCombinationProvider) { try { using (var str = File.OpenRead(typeof(OsuGameBase).Assembly.Location)) VersionHash = str.ComputeMD5Hash(); } catch { // special case for android builds, which can't read DLLs from a packed apk. // should eventually be handled in a better way. VersionHash = $"{Version}-{RuntimeInfo.OS}".ComputeMD5Hash(); } Resources.AddStore(new DllResourceStore(OsuResources.ResourceAssembly)); dependencies.Cache(contextFactory = new DatabaseContextFactory(Storage)); dependencies.Cache(realmFactory = new RealmContextFactory(Storage, "client")); dependencies.CacheAs(Storage); var largeStore = new LargeTextureStore(Host.CreateTextureLoaderStore(new NamespacedResourceStore <byte[]>(Resources, @"Textures"))); largeStore.AddStore(Host.CreateTextureLoaderStore(new OnlineStore())); dependencies.Cache(largeStore); dependencies.CacheAs(this); dependencies.CacheAs(LocalConfig); InitialiseFonts(); Audio.Samples.PlaybackConcurrency = SAMPLE_CONCURRENCY; runMigrations(); dependencies.Cache(SkinManager = new SkinManager(Storage, contextFactory, Host, Resources, Audio)); dependencies.CacheAs <ISkinSource>(SkinManager); // needs to be done here rather than inside SkinManager to ensure thread safety of CurrentSkinInfo. SkinManager.ItemRemoved += item => Schedule(() => { // check the removed skin is not the current user choice. if it is, switch back to default. if (item.ID == SkinManager.CurrentSkinInfo.Value.ID) { SkinManager.CurrentSkinInfo.Value = SkinInfo.Default; } }); EndpointConfiguration endpoints = UseDevelopmentServer ? (EndpointConfiguration) new DevelopmentEndpointConfiguration() : new ProductionEndpointConfiguration(); MessageFormatter.WebsiteRootUrl = endpoints.WebsiteRootUrl; dependencies.CacheAs(API ??= new APIAccess(LocalConfig, endpoints, VersionHash)); dependencies.CacheAs(spectatorClient = new OnlineSpectatorClient(endpoints)); dependencies.CacheAs(multiplayerClient = new OnlineMultiplayerClient(endpoints)); var defaultBeatmap = new DummyWorkingBeatmap(Audio, Textures); dependencies.Cache(RulesetStore = new RulesetStore(contextFactory, Storage)); dependencies.Cache(fileStore = new FileStore(contextFactory, Storage)); // ordering is important here to ensure foreign keys rules are not broken in ModelStore.Cleanup() dependencies.Cache(ScoreManager = new ScoreManager(RulesetStore, () => BeatmapManager, Storage, API, contextFactory, Scheduler, Host, () => difficultyCache, LocalConfig)); dependencies.Cache(BeatmapManager = new BeatmapManager(Storage, contextFactory, RulesetStore, API, Audio, Resources, Host, defaultBeatmap, performOnlineLookups: true)); // the following realm components are not actively used yet, but initialised and kept up to date for initial testing. realmRulesetStore = new RealmRulesetStore(realmFactory, Storage); dependencies.Cache(realmRulesetStore); // this should likely be moved to ArchiveModelManager when another case appears where it is necessary // to have inter-dependent model managers. this could be obtained with an IHasForeign<T> interface to // allow lookups to be done on the child (ScoreManager in this case) to perform the cascading delete. List <ScoreInfo> getBeatmapScores(BeatmapSetInfo set) { var beatmapIds = BeatmapManager.QueryBeatmaps(b => b.BeatmapSetInfoID == set.ID).Select(b => b.ID).ToList(); return(ScoreManager.QueryScores(s => beatmapIds.Contains(s.BeatmapInfo.ID)).ToList()); } BeatmapManager.ItemRemoved += item => ScoreManager.Delete(getBeatmapScores(item), true); BeatmapManager.ItemUpdated += item => ScoreManager.Undelete(getBeatmapScores(item), true); dependencies.Cache(difficultyCache = new BeatmapDifficultyCache()); AddInternal(difficultyCache); dependencies.Cache(userCache = new UserLookupCache()); AddInternal(userCache); var scorePerformanceManager = new ScorePerformanceCache(); dependencies.Cache(scorePerformanceManager); AddInternal(scorePerformanceManager); migrateDataToRealm(); dependencies.Cache(rulesetConfigCache = new RulesetConfigCache(realmFactory, RulesetStore)); var powerStatus = CreateBatteryInfo(); if (powerStatus != null) { dependencies.CacheAs(powerStatus); } dependencies.Cache(SessionStatics = new SessionStatics()); dependencies.Cache(new OsuColour()); RegisterImportHandler(BeatmapManager); RegisterImportHandler(ScoreManager); RegisterImportHandler(SkinManager); // drop track volume game-wide to leave some head-room for UI effects / samples. // this means that for the time being, gameplay sample playback is louder relative to the audio track, compared to stable. // we may want to revisit this if users notice or complain about the difference (consider this a bit of a trial). Audio.Tracks.AddAdjustment(AdjustableProperty.Volume, globalTrackVolumeAdjust); Beatmap = new NonNullableBindable <WorkingBeatmap>(defaultBeatmap); dependencies.CacheAs <IBindable <WorkingBeatmap> >(Beatmap); dependencies.CacheAs(Beatmap); fileStore.Cleanup(); // add api components to hierarchy. if (API is APIAccess apiAccess) { AddInternal(apiAccess); } AddInternal(spectatorClient); AddInternal(multiplayerClient); AddInternal(rulesetConfigCache); GlobalActionContainer globalBindings; var mainContent = new Drawable[] { MenuCursorContainer = new MenuCursorContainer { RelativeSizeAxes = Axes.Both }, // to avoid positional input being blocked by children, ensure the GlobalActionContainer is above everything. globalBindings = new GlobalActionContainer(this) }; MenuCursorContainer.Child = content = new OsuTooltipContainer(MenuCursorContainer.Cursor) { RelativeSizeAxes = Axes.Both }; base.Content.Add(CreateScalingContainer().WithChildren(mainContent)); KeyBindingStore = new RealmKeyBindingStore(realmFactory, keyCombinationProvider); KeyBindingStore.Register(globalBindings, RulesetStore.AvailableRulesets); dependencies.Cache(globalBindings); PreviewTrackManager previewTrackManager; dependencies.Cache(previewTrackManager = new PreviewTrackManager(BeatmapManager.BeatmapTrackStore)); Add(previewTrackManager); AddInternal(MusicController = new MusicController()); dependencies.CacheAs(MusicController); Ruleset.BindValueChanged(onRulesetChanged); }
private void load(OsuColour colours, BeatmapDifficultyCache difficultyCache) { AutoSizeAxes = Axes.Both; var starRatingParts = difficulty.Stars.ToString("0.00", CultureInfo.InvariantCulture).Split('.'); string wholePart = starRatingParts[0]; string fractionPart = starRatingParts[1]; string separator = CultureInfo.CurrentCulture.NumberFormat.NumberDecimalSeparator; ColourInfo backgroundColour = difficulty.DifficultyRating == DifficultyRating.ExpertPlus ? ColourInfo.GradientVertical(Color4Extensions.FromHex("#C1C1C1"), Color4Extensions.FromHex("#595959")) : (ColourInfo)colours.ForDifficultyRating(difficulty.DifficultyRating); InternalChildren = new Drawable[] { new CircularContainer { RelativeSizeAxes = Axes.Both, Masking = true, Children = new Drawable[] { new Box { RelativeSizeAxes = Axes.Both, Colour = backgroundColour }, } }, new FillFlowContainer { AutoSizeAxes = Axes.Both, Padding = new MarginPadding { Horizontal = 8, Vertical = 4 }, Direction = FillDirection.Horizontal, Spacing = new Vector2(2, 0), Children = new Drawable[] { new SpriteIcon { Anchor = Anchor.CentreLeft, Origin = Anchor.CentreLeft, Size = new Vector2(7), Icon = FontAwesome.Solid.Star, Colour = Color4.Black }, new OsuTextFlowContainer(s => s.Font = OsuFont.Numeric.With(weight: FontWeight.Black)) { Anchor = Anchor.CentreLeft, Origin = Anchor.CentreLeft, AutoSizeAxes = Axes.Both, Direction = FillDirection.Horizontal, TextAnchor = Anchor.BottomLeft, }.With(t => { t.AddText($"{wholePart}", s => { s.Colour = Color4.Black; s.Font = s.Font.With(size: 14); s.UseFullGlyphHeight = false; }); t.AddText($"{separator}{fractionPart}", s => { s.Colour = Color4.Black; s.Font = s.Font.With(size: 7); s.UseFullGlyphHeight = false; }); }) } } }; }
public void TestDifficultyRatingMapping(double starRating, DifficultyRating expectedBracket) { var actualBracket = BeatmapDifficultyCache.GetDifficultyRating(starRating); Assert.AreEqual(expectedBracket, actualBracket); }
private void load(OsuColour colours, BeatmapDifficultyCache difficultyCache) { Colour = colours.BlueLighter; valid.BindValueChanged(e => DrawableCount.FadeTo(e.NewValue ? 1 : alpha_when_invalid, 1000, Easing.OutQuint)); }