Ejemplo n.º 1
0
        private void load()
        {
            dependencies.Cache(contextFactory = new DatabaseContextFactory(Host));

            dependencies.Cache(new LargeTextureStore(new RawTextureLoaderStore(new NamespacedResourceStore <byte[]>(Resources, @"Textures"))));

            dependencies.CacheAs(this);
            dependencies.Cache(LocalConfig);

            runMigrations();

            dependencies.Cache(SkinManager = new SkinManager(Host.Storage, contextFactory, Host, Audio));
            dependencies.CacheAs <ISkinSource>(SkinManager);

            var api = new APIAccess(LocalConfig);

            dependencies.Cache(api);
            dependencies.CacheAs <IAPIProvider>(api);

            dependencies.Cache(RulesetStore    = new RulesetStore(contextFactory));
            dependencies.Cache(FileStore       = new FileStore(contextFactory, Host.Storage));
            dependencies.Cache(BeatmapManager  = new BeatmapManager(Host.Storage, contextFactory, RulesetStore, api, Audio, Host));
            dependencies.Cache(ScoreStore      = new ScoreStore(Host.Storage, contextFactory, Host, BeatmapManager, RulesetStore));
            dependencies.Cache(KeyBindingStore = new KeyBindingStore(contextFactory, RulesetStore));
            dependencies.Cache(SettingsStore   = new SettingsStore(contextFactory));
            dependencies.Cache(new OsuColour());

            fileImporters.Add(BeatmapManager);
            fileImporters.Add(ScoreStore);
            fileImporters.Add(SkinManager);

            //this completely overrides the framework default. will need to change once we make a proper FontStore.
            dependencies.Cache(Fonts = new FontStore {
                ScaleAdjust = 100
            });

            Fonts.AddStore(new GlyphStore(Resources, @"Fonts/FontAwesome"));
            Fonts.AddStore(new GlyphStore(Resources, @"Fonts/osuFont"));
            Fonts.AddStore(new GlyphStore(Resources, @"Fonts/Exo2.0-Medium"));
            Fonts.AddStore(new GlyphStore(Resources, @"Fonts/Exo2.0-MediumItalic"));

            Fonts.AddStore(new GlyphStore(Resources, @"Fonts/Noto-Basic"));
            Fonts.AddStore(new GlyphStore(Resources, @"Fonts/Noto-Hangul"));
            Fonts.AddStore(new GlyphStore(Resources, @"Fonts/Noto-CJK-Basic"));
            Fonts.AddStore(new GlyphStore(Resources, @"Fonts/Noto-CJK-Compatibility"));

            Fonts.AddStore(new GlyphStore(Resources, @"Fonts/Exo2.0-Regular"));
            Fonts.AddStore(new GlyphStore(Resources, @"Fonts/Exo2.0-RegularItalic"));
            Fonts.AddStore(new GlyphStore(Resources, @"Fonts/Exo2.0-SemiBold"));
            Fonts.AddStore(new GlyphStore(Resources, @"Fonts/Exo2.0-SemiBoldItalic"));
            Fonts.AddStore(new GlyphStore(Resources, @"Fonts/Exo2.0-Bold"));
            Fonts.AddStore(new GlyphStore(Resources, @"Fonts/Exo2.0-BoldItalic"));
            Fonts.AddStore(new GlyphStore(Resources, @"Fonts/Exo2.0-Light"));
            Fonts.AddStore(new GlyphStore(Resources, @"Fonts/Exo2.0-LightItalic"));
            Fonts.AddStore(new GlyphStore(Resources, @"Fonts/Exo2.0-Black"));
            Fonts.AddStore(new GlyphStore(Resources, @"Fonts/Exo2.0-BlackItalic"));

            Fonts.AddStore(new GlyphStore(Resources, @"Fonts/Venera"));
            Fonts.AddStore(new GlyphStore(Resources, @"Fonts/Venera-Light"));

            var defaultBeatmap = new DummyWorkingBeatmap(this);

            Beatmap = new NonNullableBindable <WorkingBeatmap>(defaultBeatmap);
            BeatmapManager.DefaultBeatmap = defaultBeatmap;

            // tracks play so loud our samples can't keep up.
            // this adds a global reduction of track volume for the time being.
            Audio.Track.AddAdjustment(AdjustableProperty.Volume, new BindableDouble(0.8));

            Beatmap.ValueChanged += b =>
            {
                var trackLoaded = lastBeatmap?.TrackLoaded ?? false;

                // compare to last beatmap as sometimes the two may share a track representation (optimisation, see WorkingBeatmap.TransferTo)
                if (!trackLoaded || lastBeatmap?.Track != b.Track)
                {
                    if (trackLoaded)
                    {
                        Debug.Assert(lastBeatmap != null);
                        Debug.Assert(lastBeatmap.Track != null);

                        lastBeatmap.RecycleTrack();
                    }

                    Audio.Track.AddItem(b.Track);
                }

                lastBeatmap = b;
            };

            FileStore.Cleanup();

            AddInternal(api);
        }
Ejemplo n.º 2
0
        private void load(OsuColour colours, GameHost host)
        {
            this.host = host;

            // TODO: should probably be done at a RulesetContainer level to share logic with Player.
            var sourceClock = (IAdjustableClock)Beatmap.Value.Track ?? new StopwatchClock();

            clock = new EditorClock(Beatmap.Value, beatDivisor)
            {
                IsCoupled = false
            };
            clock.ChangeSource(sourceClock);

            dependencies.CacheAs <IFrameBasedClock>(clock);
            dependencies.CacheAs <IAdjustableClock>(clock);
            dependencies.Cache(beatDivisor);

            EditorMenuBar     menuBar;
            TimeInfoContainer timeInfo;
            SummaryTimeline   timeline;
            PlaybackControl   playback;

            InternalChildren = new[]
            {
                new Container
                {
                    Name             = "Screen container",
                    RelativeSizeAxes = Axes.Both,
                    Padding          = new MarginPadding {
                        Top = 40, Bottom = 60
                    },
                    Child = screenContainer = new Container
                    {
                        RelativeSizeAxes = Axes.Both,
                        Masking          = true
                    }
                },
                new Container
                {
                    Name             = "Top bar",
                    RelativeSizeAxes = Axes.X,
                    Height           = 40,
                    Child            = menuBar = new EditorMenuBar
                    {
                        Anchor           = Anchor.CentreLeft,
                        Origin           = Anchor.CentreLeft,
                        RelativeSizeAxes = Axes.Both,
                        Items            = new[]
                        {
                            new MenuItem("File")
                            {
                                Items = new[]
                                {
                                    new EditorMenuItem("Export", MenuItemType.Standard, exportBeatmap),
                                    new EditorMenuItemSpacer(),
                                    new EditorMenuItem("Exit", MenuItemType.Standard, this.Exit)
                                }
                            }
                        }
                    }
                },
                new Container
                {
                    Name             = "Bottom bar",
                    Anchor           = Anchor.BottomLeft,
                    Origin           = Anchor.BottomLeft,
                    RelativeSizeAxes = Axes.X,
                    Height           = 60,
                    Children         = new Drawable[]
                    {
                        bottomBackground = new Box {
                            RelativeSizeAxes = Axes.Both
                        },
                        new Container
                        {
                            RelativeSizeAxes = Axes.Both,
                            Padding          = new MarginPadding {
                                Vertical = 5, Horizontal = 10
                            },
                            Child = new GridContainer
                            {
                                RelativeSizeAxes = Axes.Both,
                                ColumnDimensions = new[]
                                {
                                    new Dimension(GridSizeMode.Absolute, 220),
                                    new Dimension(),
                                    new Dimension(GridSizeMode.Absolute, 220)
                                },
                                Content = new[]
                                {
                                    new Drawable[]
                                    {
                                        new Container
                                        {
                                            RelativeSizeAxes = Axes.Both,
                                            Padding          = new MarginPadding {
                                                Right = 10
                                            },
                                            Child = new TimeInfoContainer {
                                                RelativeSizeAxes = Axes.Both
                                            },
                                        },
                                        new SummaryTimeline
                                        {
                                            RelativeSizeAxes = Axes.Both,
                                        },
                                        new Container
                                        {
                                            RelativeSizeAxes = Axes.Both,
                                            Padding          = new MarginPadding {
                                                Left = 10
                                            },
                                            Child = new PlaybackControl {
                                                RelativeSizeAxes = Axes.Both
                                            },
                                        }
                                    },
                                }
                            },
                        }
                    }
                },
            };

            menuBar.Mode.ValueChanged += onModeChanged;

            bottomBackground.Colour = colours.Gray2;
        }
Ejemplo n.º 3
0
        private void load(FrameworkConfigManager config)
        {
            Resources = new ResourceStore <byte[]>();
            Resources.AddStore(new NamespacedResourceStore <byte[]>(new DllResourceStore(typeof(Game).Assembly), @"Resources"));

            Textures = new TextureStore(Host.CreateTextureLoaderStore(new NamespacedResourceStore <byte[]>(Resources, @"Textures")));
            Textures.AddStore(Host.CreateTextureLoaderStore(new OnlineStore()));
            dependencies.Cache(Textures);

            var tracks = new ResourceStore <byte[]>();

            tracks.AddStore(new NamespacedResourceStore <byte[]>(Resources, @"Tracks"));
            tracks.AddStore(new OnlineStore());

            var samples = new ResourceStore <byte[]>();

            samples.AddStore(new NamespacedResourceStore <byte[]>(Resources, @"Samples"));
            samples.AddStore(new OnlineStore());

            Audio = new AudioManager(Host.AudioThread, tracks, samples)
            {
                EventScheduler = Scheduler
            };
            dependencies.Cache(Audio);

            dependencies.CacheAs(Audio.Tracks);
            dependencies.CacheAs(Audio.Samples);

            // attach our bindables to the audio subsystem.
            config.BindWith(FrameworkSetting.AudioDevice, Audio.AudioDevice);
            config.BindWith(FrameworkSetting.VolumeUniversal, Audio.Volume);
            config.BindWith(FrameworkSetting.VolumeEffect, Audio.VolumeSample);
            config.BindWith(FrameworkSetting.VolumeMusic, Audio.VolumeTrack);

            Shaders = new ShaderManager(new NamespacedResourceStore <byte[]>(Resources, @"Shaders"));
            dependencies.Cache(Shaders);

            var cacheStorage = Host.Storage.GetStorageForDirectory(Path.Combine("cache", "fonts"));

            // base store is for user fonts
            Fonts = new FontStore(useAtlas: true, cacheStorage: cacheStorage);

            // nested store for framework provided fonts.
            // note that currently this means there could be two async font load operations.
            Fonts.AddStore(localFonts = new FontStore(useAtlas: false));

            addFont(localFonts, Resources, @"Fonts/OpenSans/OpenSans");
            addFont(localFonts, Resources, @"Fonts/OpenSans/OpenSans-Bold");
            addFont(localFonts, Resources, @"Fonts/OpenSans/OpenSans-Italic");
            addFont(localFonts, Resources, @"Fonts/OpenSans/OpenSans-BoldItalic");

            addFont(Fonts, Resources, @"Fonts/FontAwesome5/FontAwesome-Solid");
            addFont(Fonts, Resources, @"Fonts/FontAwesome5/FontAwesome-Regular");
            addFont(Fonts, Resources, @"Fonts/FontAwesome5/FontAwesome-Brands");

            dependencies.Cache(Fonts);

            Localisation = new LocalisationManager(config);
            dependencies.Cache(Localisation);

            logOverlayVisibility = config.GetBindable <bool>(FrameworkSetting.ShowLogOverlay);
            logOverlayVisibility.BindValueChanged(visibility =>
            {
                if (visibility.NewValue)
                {
                    if (logOverlay == null)
                    {
                        LoadComponentAsync(logOverlay = new LogOverlay
                        {
                            Depth = float.MinValue / 2,
                        }, AddInternal);
                    }

                    logOverlay.Show();
                }
                else
                {
                    logOverlay?.Hide();
                }
            }, true);
        }
Ejemplo n.º 4
0
        private void load(AudioManager audio, OsuConfigManager config, OsuGameBase game)
        {
            Mods.Value = base.Mods.Value.Select(m => m.DeepClone()).ToArray();

            if (Beatmap.Value is DummyWorkingBeatmap)
            {
                return;
            }

            IBeatmap playableBeatmap = loadPlayableBeatmap();

            if (playableBeatmap == null)
            {
                return;
            }

            sampleRestart = audio.Samples.Get(@"Gameplay/restart");

            mouseWheelDisabled = config.GetBindable <bool>(OsuSetting.MouseDisableWheel);

            if (game != null)
            {
                gameActive.BindTo(game.IsActive);
            }

            if (game is OsuGame osuGame)
            {
                LocalUserPlaying.BindTo(osuGame.LocalUserPlaying);
            }

            DrawableRuleset = GameplayRuleset.CreateDrawableRulesetWith(playableBeatmap, Mods.Value);
            dependencies.CacheAs(DrawableRuleset);

            ScoreProcessor = GameplayRuleset.CreateScoreProcessor();
            ScoreProcessor.ApplyBeatmap(playableBeatmap);
            ScoreProcessor.Mods.BindTo(Mods);

            dependencies.CacheAs(ScoreProcessor);

            HealthProcessor = GameplayRuleset.CreateHealthProcessor(playableBeatmap.HitObjects[0].StartTime);
            HealthProcessor.ApplyBeatmap(playableBeatmap);

            dependencies.CacheAs(HealthProcessor);

            if (!ScoreProcessor.Mode.Disabled)
            {
                config.BindWith(OsuSetting.ScoreDisplayMode, ScoreProcessor.Mode);
            }

            InternalChild = GameplayClockContainer = CreateGameplayClockContainer(Beatmap.Value, DrawableRuleset.GameplayStartTime);

            AddInternal(GameplayBeatmap  = new GameplayBeatmap(playableBeatmap));
            AddInternal(screenSuspension = new ScreenSuspensionHandler(GameplayClockContainer));

            dependencies.CacheAs(GameplayBeatmap);

            var rulesetSkinProvider = new RulesetSkinProvidingContainer(GameplayRuleset, playableBeatmap, Beatmap.Value.Skin);

            // load the skinning hierarchy first.
            // this is intentionally done in two stages to ensure things are in a loaded state before exposing the ruleset to skin sources.
            GameplayClockContainer.Add(rulesetSkinProvider);

            rulesetSkinProvider.AddRange(new[]
            {
                // underlay and gameplay should have access to the skinning sources.
                createUnderlayComponents(),
                createGameplayComponents(Beatmap.Value, playableBeatmap)
            });

            // add the overlay components as a separate step as they proxy some elements from the above underlay/gameplay components.
            // also give the overlays the ruleset skin provider to allow rulesets to potentially override HUD elements (used to disable combo counters etc.)
            // we may want to limit this in the future to disallow rulesets from outright replacing elements the user expects to be there.
            rulesetSkinProvider.Add(createOverlayComponents(Beatmap.Value));

            if (!DrawableRuleset.AllowGameplayOverlays)
            {
                HUDOverlay.ShowHud.Value    = false;
                HUDOverlay.ShowHud.Disabled = true;
                BreakOverlay.Hide();
            }

            DrawableRuleset.FrameStableClock.WaitingOnFrames.BindValueChanged(waiting =>
            {
                if (waiting.NewValue)
                {
                    GameplayClockContainer.Stop();
                }
                else
                {
                    GameplayClockContainer.Start();
                }
            });

            DrawableRuleset.IsPaused.BindValueChanged(paused =>
            {
                updateGameplayState();
                updateSampleDisabledState();
            });

            DrawableRuleset.FrameStableClock.IsCatchingUp.BindValueChanged(_ => updateSampleDisabledState());

            DrawableRuleset.HasReplayLoaded.BindValueChanged(_ => updateGameplayState());

            // bind clock into components that require it
            DrawableRuleset.IsPaused.BindTo(GameplayClockContainer.IsPaused);

            DrawableRuleset.NewResult += r =>
            {
                HealthProcessor.ApplyResult(r);
                ScoreProcessor.ApplyResult(r);
                GameplayBeatmap.ApplyResult(r);
            };

            DrawableRuleset.RevertResult += r =>
            {
                HealthProcessor.RevertResult(r);
                ScoreProcessor.RevertResult(r);
            };

            DimmableStoryboard.HasStoryboardEnded.ValueChanged += storyboardEnded =>
            {
                if (storyboardEnded.NewValue)
                {
                    progressToResults(true);
                }
            };

            // Bind the judgement processors to ourselves
            ScoreProcessor.HasCompleted.BindValueChanged(scoreCompletionChanged);
            HealthProcessor.Failed += onFail;

            // Provide judgement processors to mods after they're loaded so that they're on the gameplay clock,
            // this is required for mods that apply transforms to these processors.
            ScoreProcessor.OnLoadComplete += _ =>
            {
                foreach (var mod in Mods.Value.OfType <IApplicableToScoreProcessor>())
                {
                    mod.ApplyToScoreProcessor(ScoreProcessor);
                }
            };

            HealthProcessor.OnLoadComplete += _ =>
            {
                foreach (var mod in Mods.Value.OfType <IApplicableToHealthProcessor>())
                {
                    mod.ApplyToHealthProcessor(HealthProcessor);
                }
            };

            IsBreakTime.BindTo(breakTracker.IsBreakTime);
            IsBreakTime.BindValueChanged(onBreakTimeChanged, true);
        }
Ejemplo n.º 5
0
        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));

            runMigrations();

            dependencies.Cache(RulesetStore = new RulesetStore(contextFactory, Storage));
            dependencies.CacheAs <IRulesetStore>(RulesetStore);

            dependencies.Cache(realmFactory = new RealmContextFactory(Storage, "client", contextFactory));

            new EFToRealmMigrator(contextFactory, realmFactory, LocalConfig).Run();

            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, realmFactory, 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);

            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, contextFactory, Scheduler, Host, () => difficultyCache, LocalConfig));
            dependencies.Cache(BeatmapManager = new BeatmapManager(Storage, contextFactory, RulesetStore, API, Audio, Resources, Host, defaultBeatmap, performOnlineLookups: true));

            dependencies.Cache(BeatmapDownloader = new BeatmapModelDownloader(BeatmapManager, API));
            dependencies.Cache(ScoreDownloader   = new ScoreModelDownloader(ScoreManager, API));

            // 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);

            dependencies.Cache(beatmapCache = new BeatmapLookupCache());
            AddInternal(beatmapCache);

            var scorePerformanceManager = new ScorePerformanceCache();

            dependencies.Cache(scorePerformanceManager);
            AddInternal(scorePerformanceManager);

            dependencies.CacheAs <IRulesetConfigCache>(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);
        }
Ejemplo n.º 6
0
        private void load(OsuColour colours, GameHost host)
        {
            beatDivisor.Value = Beatmap.Value.BeatmapInfo.BeatDivisor;
            beatDivisor.BindValueChanged(divisor => Beatmap.Value.BeatmapInfo.BeatDivisor = divisor.NewValue);

            // Todo: should probably be done at a DrawableRuleset level to share logic with Player.
            var sourceClock = (IAdjustableClock)Beatmap.Value.Track ?? new StopwatchClock();

            clock = new EditorClock(Beatmap.Value, beatDivisor)
            {
                IsCoupled = false
            };
            clock.ChangeSource(sourceClock);

            dependencies.CacheAs <IFrameBasedClock>(clock);
            dependencies.CacheAs <IAdjustableClock>(clock);

            // todo: remove caching of this and consume via editorBeatmap?
            dependencies.Cache(beatDivisor);

            try
            {
                playableBeatmap = Beatmap.Value.GetPlayableBeatmap(Beatmap.Value.BeatmapInfo.Ruleset);
            }
            catch (Exception e)
            {
                Logger.Error(e, "Could not load beatmap successfully!");
                // couldn't load, hard abort!
                this.Exit();
                return;
            }

            AddInternal(editorBeatmap = new EditorBeatmap(playableBeatmap));
            dependencies.CacheAs(editorBeatmap);

            changeHandler = new EditorChangeHandler(editorBeatmap);
            dependencies.CacheAs <IEditorChangeHandler>(changeHandler);

            EditorMenuBar menuBar;

            var fileMenuItems = new List <MenuItem>
            {
                new EditorMenuItem("Save", MenuItemType.Standard, saveBeatmap)
            };

            if (RuntimeInfo.IsDesktop)
            {
                fileMenuItems.Add(new EditorMenuItem("Export package", MenuItemType.Standard, exportBeatmap));
            }

            fileMenuItems.Add(new EditorMenuItemSpacer());
            fileMenuItems.Add(new EditorMenuItem("Exit", MenuItemType.Standard, this.Exit));

            AddInternal(new OsuContextMenuContainer
            {
                RelativeSizeAxes = Axes.Both,
                Children         = new[]
                {
                    new Container
                    {
                        Name             = "Screen container",
                        RelativeSizeAxes = Axes.Both,
                        Padding          = new MarginPadding {
                            Top = 40, Bottom = 60
                        },
                        Child = screenContainer = new Container
                        {
                            RelativeSizeAxes = Axes.Both,
                            Masking          = true
                        }
                    },
                    new Container
                    {
                        Name             = "Top bar",
                        RelativeSizeAxes = Axes.X,
                        Height           = 40,
                        Child            = menuBar = new EditorMenuBar
                        {
                            Anchor           = Anchor.CentreLeft,
                            Origin           = Anchor.CentreLeft,
                            RelativeSizeAxes = Axes.Both,
                            Items            = new[]
                            {
                                new MenuItem("File")
                                {
                                    Items = fileMenuItems
                                },
                                new MenuItem("Edit")
                                {
                                    Items = new[]
                                    {
                                        new EditorMenuItem("Undo", MenuItemType.Standard, undo),
                                        new EditorMenuItem("Redo", MenuItemType.Standard, redo)
                                    }
                                }
                            }
                        }
                    },
                    new Container
                    {
                        Name             = "Bottom bar",
                        Anchor           = Anchor.BottomLeft,
                        Origin           = Anchor.BottomLeft,
                        RelativeSizeAxes = Axes.X,
                        Height           = 60,
                        Children         = new Drawable[]
                        {
                            bottomBackground = new Box {
                                RelativeSizeAxes = Axes.Both
                            },
                            new Container
                            {
                                RelativeSizeAxes = Axes.Both,
                                Padding          = new MarginPadding {
                                    Vertical = 5, Horizontal = 10
                                },
                                Child = new GridContainer
                                {
                                    RelativeSizeAxes = Axes.Both,
                                    ColumnDimensions = new[]
                                    {
                                        new Dimension(GridSizeMode.Absolute, 220),
                                        new Dimension(),
                                        new Dimension(GridSizeMode.Absolute, 220)
                                    },
                                    Content = new[]
                                    {
                                        new Drawable[]
                                        {
                                            new Container
                                            {
                                                RelativeSizeAxes = Axes.Both,
                                                Padding          = new MarginPadding {
                                                    Right = 10
                                                },
                                                Child = new TimeInfoContainer {
                                                    RelativeSizeAxes = Axes.Both
                                                },
                                            },
                                            new SummaryTimeline
                                            {
                                                RelativeSizeAxes = Axes.Both,
                                            },
                                            new Container
                                            {
                                                RelativeSizeAxes = Axes.Both,
                                                Padding          = new MarginPadding {
                                                    Left = 10
                                                },
                                                Child = new PlaybackControl {
                                                    RelativeSizeAxes = Axes.Both
                                                },
                                            }
                                        },
                                    }
                                },
                            }
                        }
                    },
                }
            });

            menuBar.Mode.ValueChanged += onModeChanged;

            bottomBackground.Colour = colours.Gray2;
        }
Ejemplo n.º 7
0
 private void Load()
 {
     _dependencies.CacheAs(this);
 }
Ejemplo n.º 8
0
Archivo: Player.cs Proyecto: ghanie/osu
        private void load(AudioManager audio, OsuConfigManager config, OsuGame game)
        {
            Mods.Value = base.Mods.Value.Select(m => m.CreateCopy()).ToArray();

            if (Beatmap.Value is DummyWorkingBeatmap)
            {
                return;
            }

            IBeatmap playableBeatmap = loadPlayableBeatmap();

            if (playableBeatmap == null)
            {
                return;
            }

            sampleRestart = audio.Samples.Get(@"Gameplay/restart");

            mouseWheelDisabled = config.GetBindable <bool>(OsuSetting.MouseDisableWheel);

            if (game != null)
            {
                LocalUserPlaying.BindTo(game.LocalUserPlaying);
            }

            DrawableRuleset = ruleset.CreateDrawableRulesetWith(playableBeatmap, Mods.Value);

            ScoreProcessor = ruleset.CreateScoreProcessor();
            ScoreProcessor.ApplyBeatmap(playableBeatmap);
            ScoreProcessor.Mods.BindTo(Mods);

            HealthProcessor = ruleset.CreateHealthProcessor(playableBeatmap.HitObjects[0].StartTime);
            HealthProcessor.ApplyBeatmap(playableBeatmap);

            if (!ScoreProcessor.Mode.Disabled)
            {
                config.BindWith(OsuSetting.ScoreDisplayMode, ScoreProcessor.Mode);
            }

            InternalChild = GameplayClockContainer = new GameplayClockContainer(Beatmap.Value, DrawableRuleset.GameplayStartTime);

            AddInternal(gameplayBeatmap  = new GameplayBeatmap(playableBeatmap));
            AddInternal(screenSuspension = new ScreenSuspensionHandler(GameplayClockContainer));

            dependencies.CacheAs(gameplayBeatmap);

            var beatmapSkinProvider = new BeatmapSkinProvidingContainer(Beatmap.Value.Skin);

            // the beatmapSkinProvider is used as the fallback source here to allow the ruleset-specific skin implementation
            // full access to all skin sources.
            var rulesetSkinProvider = new SkinProvidingContainer(ruleset.CreateLegacySkinProvider(beatmapSkinProvider, playableBeatmap));

            // load the skinning hierarchy first.
            // this is intentionally done in two stages to ensure things are in a loaded state before exposing the ruleset to skin sources.
            GameplayClockContainer.Add(beatmapSkinProvider.WithChild(rulesetSkinProvider));

            rulesetSkinProvider.AddRange(new[]
            {
                // underlay and gameplay should have access the to skinning sources.
                createUnderlayComponents(),
                createGameplayComponents(Beatmap.Value, playableBeatmap)
            });

            // also give the HUD a ruleset container to allow rulesets to potentially override HUD elements (used to disable combo counters etc.)
            // we may want to limit this in the future to disallow rulesets from outright replacing elements the user expects to be there.
            var hudRulesetContainer = new SkinProvidingContainer(ruleset.CreateLegacySkinProvider(beatmapSkinProvider, playableBeatmap));

            // add the overlay components as a separate step as they proxy some elements from the above underlay/gameplay components.
            GameplayClockContainer.Add(hudRulesetContainer.WithChild(createOverlayComponents(Beatmap.Value)));

            if (!DrawableRuleset.AllowGameplayOverlays)
            {
                HUDOverlay.ShowHud.Value    = false;
                HUDOverlay.ShowHud.Disabled = true;
                BreakOverlay.Hide();
                skipOverlay.Hide();
            }

            DrawableRuleset.IsPaused.BindValueChanged(paused =>
            {
                updateGameplayState();
                samplePlaybackDisabled.Value = paused.NewValue;
            });
            DrawableRuleset.HasReplayLoaded.BindValueChanged(_ => updateGameplayState());

            DrawableRuleset.HasReplayLoaded.BindValueChanged(_ => updatePauseOnFocusLostState(), true);

            // bind clock into components that require it
            DrawableRuleset.IsPaused.BindTo(GameplayClockContainer.IsPaused);

            DrawableRuleset.OnNewResult += r =>
            {
                HealthProcessor.ApplyResult(r);
                ScoreProcessor.ApplyResult(r);
                gameplayBeatmap.ApplyResult(r);
            };

            DrawableRuleset.OnRevertResult += r =>
            {
                HealthProcessor.RevertResult(r);
                ScoreProcessor.RevertResult(r);
            };

            // Bind the judgement processors to ourselves
            ScoreProcessor.HasCompleted.ValueChanged += updateCompletionState;
            HealthProcessor.Failed += onFail;

            foreach (var mod in Mods.Value.OfType <IApplicableToScoreProcessor>())
            {
                mod.ApplyToScoreProcessor(ScoreProcessor);
            }

            foreach (var mod in Mods.Value.OfType <IApplicableToHealthProcessor>())
            {
                mod.ApplyToHealthProcessor(HealthProcessor);
            }

            IsBreakTime.BindTo(breakTracker.IsBreakTime);
            IsBreakTime.BindValueChanged(onBreakTimeChanged, true);
        }
Ejemplo n.º 9
0
        private void load(AudioManager audio, OsuConfigManager config)
        {
            Mods.Value = base.Mods.Value.Select(m => m.CreateCopy()).ToArray();

            if (Beatmap.Value is DummyWorkingBeatmap)
            {
                return;
            }

            IBeatmap playableBeatmap = loadPlayableBeatmap();

            if (playableBeatmap == null)
            {
                return;
            }

            sampleRestart = audio.Samples.Get(@"Gameplay/restart");

            mouseWheelDisabled = config.GetBindable <bool>(OsuSetting.MouseDisableWheel);

            DrawableRuleset = ruleset.CreateDrawableRulesetWith(playableBeatmap, Mods.Value);

            ScoreProcessor = ruleset.CreateScoreProcessor();
            ScoreProcessor.ApplyBeatmap(playableBeatmap);
            ScoreProcessor.Mods.BindTo(Mods);

            HealthProcessor = ruleset.CreateHealthProcessor(playableBeatmap.HitObjects[0].StartTime);
            HealthProcessor.ApplyBeatmap(playableBeatmap);

            if (!ScoreProcessor.Mode.Disabled)
            {
                config.BindWith(OsuSetting.ScoreDisplayMode, ScoreProcessor.Mode);
            }

            InternalChild = GameplayClockContainer = new GameplayClockContainer(Beatmap.Value, DrawableRuleset.GameplayStartTime);

            AddInternal(gameplayBeatmap  = new GameplayBeatmap(playableBeatmap));
            AddInternal(screenSuspension = new ScreenSuspensionHandler(GameplayClockContainer));

            dependencies.CacheAs(gameplayBeatmap);

            addUnderlayComponents(GameplayClockContainer);
            addGameplayComponents(GameplayClockContainer, Beatmap.Value, playableBeatmap);
            addOverlayComponents(GameplayClockContainer, Beatmap.Value);

            if (!DrawableRuleset.AllowGameplayOverlays)
            {
                HUDOverlay.ShowHud.Value    = false;
                HUDOverlay.ShowHud.Disabled = true;
                BreakOverlay.Hide();
                skipOverlay.Hide();
            }

            DrawableRuleset.IsPaused.BindValueChanged(_ => updateOverlayActivationMode());
            DrawableRuleset.HasReplayLoaded.BindValueChanged(_ => updateOverlayActivationMode());
            breakTracker.IsBreakTime.BindValueChanged(_ => updateOverlayActivationMode());

            DrawableRuleset.HasReplayLoaded.BindValueChanged(_ => updatePauseOnFocusLostState(), true);

            // bind clock into components that require it
            DrawableRuleset.IsPaused.BindTo(GameplayClockContainer.IsPaused);

            DrawableRuleset.OnNewResult += r =>
            {
                HealthProcessor.ApplyResult(r);
                ScoreProcessor.ApplyResult(r);
                gameplayBeatmap.ApplyResult(r);
            };

            DrawableRuleset.OnRevertResult += r =>
            {
                HealthProcessor.RevertResult(r);
                ScoreProcessor.RevertResult(r);
            };

            // Bind the judgement processors to ourselves
            ScoreProcessor.HasCompleted.ValueChanged += updateCompletionState;
            HealthProcessor.Failed += onFail;

            foreach (var mod in Mods.Value.OfType <IApplicableToScoreProcessor>())
            {
                mod.ApplyToScoreProcessor(ScoreProcessor);
            }

            foreach (var mod in Mods.Value.OfType <IApplicableToHealthProcessor>())
            {
                mod.ApplyToHealthProcessor(HealthProcessor);
            }

            breakTracker.IsBreakTime.BindValueChanged(onBreakTimeChanged, true);
        }
Ejemplo n.º 10
0
        private void load(OsuColour colours, GameHost host)
        {
            beatDivisor.Value = Beatmap.Value.BeatmapInfo.BeatDivisor;
            beatDivisor.BindValueChanged(divisor => Beatmap.Value.BeatmapInfo.BeatDivisor = divisor.NewValue);

            // Todo: should probably be done at a DrawableRuleset level to share logic with Player.
            var sourceClock = (IAdjustableClock)Beatmap.Value.Track ?? new StopwatchClock();

            clock = new EditorClock(Beatmap.Value, beatDivisor)
            {
                IsCoupled = false
            };
            clock.ChangeSource(sourceClock);

            dependencies.CacheAs(clock);
            AddInternal(clock);

            // todo: remove caching of this and consume via editorBeatmap?
            dependencies.Cache(beatDivisor);

            bool isNewBeatmap = false;

            if (Beatmap.Value is DummyWorkingBeatmap)
            {
                isNewBeatmap  = true;
                Beatmap.Value = beatmapManager.CreateNew(Ruleset.Value, api.LocalUser.Value);
            }

            try
            {
                playableBeatmap = Beatmap.Value.GetPlayableBeatmap(Beatmap.Value.BeatmapInfo.Ruleset);
            }
            catch (Exception e)
            {
                Logger.Error(e, "Could not load beatmap successfully!");
                // couldn't load, hard abort!
                this.Exit();
                return;
            }

            AddInternal(editorBeatmap = new EditorBeatmap(playableBeatmap, Beatmap.Value.Skin));
            dependencies.CacheAs(editorBeatmap);
            changeHandler = new EditorChangeHandler(editorBeatmap);
            dependencies.CacheAs <IEditorChangeHandler>(changeHandler);

            updateLastSavedHash();

            EditorMenuBar menuBar;

            OsuMenuItem undoMenuItem;
            OsuMenuItem redoMenuItem;

            EditorMenuItem cutMenuItem;
            EditorMenuItem copyMenuItem;
            EditorMenuItem pasteMenuItem;

            var fileMenuItems = new List <MenuItem>
            {
                new EditorMenuItem("Save", MenuItemType.Standard, Save)
            };

            if (RuntimeInfo.IsDesktop)
            {
                fileMenuItems.Add(new EditorMenuItem("Export package", MenuItemType.Standard, exportBeatmap));
            }

            fileMenuItems.Add(new EditorMenuItemSpacer());
            fileMenuItems.Add(new EditorMenuItem("Exit", MenuItemType.Standard, this.Exit));

            AddInternal(new OsuContextMenuContainer
            {
                RelativeSizeAxes = Axes.Both,
                Children         = new[]
                {
                    new Container
                    {
                        Name             = "Screen container",
                        RelativeSizeAxes = Axes.Both,
                        Padding          = new MarginPadding {
                            Top = 40, Bottom = 60
                        },
                        Child = screenContainer = new Container
                        {
                            RelativeSizeAxes = Axes.Both,
                            Masking          = true
                        }
                    },
                    new Container
                    {
                        Name             = "Top bar",
                        RelativeSizeAxes = Axes.X,
                        Height           = 40,
                        Child            = menuBar = new EditorMenuBar
                        {
                            Anchor           = Anchor.CentreLeft,
                            Origin           = Anchor.CentreLeft,
                            RelativeSizeAxes = Axes.Both,
                            Mode             = { Value = isNewBeatmap ? EditorScreenMode.SongSetup : EditorScreenMode.Compose },
                            Items            = new[]
                            {
                                new MenuItem("File")
                                {
                                    Items = fileMenuItems
                                },
                                new MenuItem("Edit")
                                {
                                    Items = new[]
                                    {
                                        undoMenuItem = new EditorMenuItem("Undo", MenuItemType.Standard, Undo),
                                        redoMenuItem = new EditorMenuItem("Redo", MenuItemType.Standard, Redo),
                                        new EditorMenuItemSpacer(),
                                        cutMenuItem   = new EditorMenuItem("Cut", MenuItemType.Standard, Cut),
                                        copyMenuItem  = new EditorMenuItem("Copy", MenuItemType.Standard, Copy),
                                        pasteMenuItem = new EditorMenuItem("Paste", MenuItemType.Standard, Paste),
                                    }
                                }
                            }
                        }
                    },
                    new Container
                    {
                        Name             = "Bottom bar",
                        Anchor           = Anchor.BottomLeft,
                        Origin           = Anchor.BottomLeft,
                        RelativeSizeAxes = Axes.X,
                        Height           = 60,
                        Children         = new Drawable[]
                        {
                            bottomBackground = new Box {
                                RelativeSizeAxes = Axes.Both
                            },
                            new Container
                            {
                                RelativeSizeAxes = Axes.Both,
                                Padding          = new MarginPadding {
                                    Vertical = 5, Horizontal = 10
                                },
                                Child = new GridContainer
                                {
                                    RelativeSizeAxes = Axes.Both,
                                    ColumnDimensions = new[]
                                    {
                                        new Dimension(GridSizeMode.Absolute, 220),
                                        new Dimension(),
                                        new Dimension(GridSizeMode.Absolute, 220)
                                    },
                                    Content = new[]
                                    {
                                        new Drawable[]
                                        {
                                            new Container
                                            {
                                                RelativeSizeAxes = Axes.Both,
                                                Padding          = new MarginPadding {
                                                    Right = 10
                                                },
                                                Child = new TimeInfoContainer {
                                                    RelativeSizeAxes = Axes.Both
                                                },
                                            },
                                            new SummaryTimeline
                                            {
                                                RelativeSizeAxes = Axes.Both,
                                            },
                                            new Container
                                            {
                                                RelativeSizeAxes = Axes.Both,
                                                Padding          = new MarginPadding {
                                                    Left = 10
                                                },
                                                Child = new PlaybackControl {
                                                    RelativeSizeAxes = Axes.Both
                                                },
                                            }
                                        },
                                    }
                                },
                            }
                        }
                    },
                }
            });

            changeHandler.CanUndo.BindValueChanged(v => undoMenuItem.Action.Disabled = !v.NewValue, true);
            changeHandler.CanRedo.BindValueChanged(v => redoMenuItem.Action.Disabled = !v.NewValue, true);

            editorBeatmap.SelectedHitObjects.BindCollectionChanged((_, __) =>
            {
                var hasObjects = editorBeatmap.SelectedHitObjects.Count > 0;

                cutMenuItem.Action.Disabled  = !hasObjects;
                copyMenuItem.Action.Disabled = !hasObjects;
            }, true);

            clipboard.BindValueChanged(content => pasteMenuItem.Action.Disabled = string.IsNullOrEmpty(content.NewValue));

            menuBar.Mode.ValueChanged += onModeChanged;

            bottomBackground.Colour = colours.Gray2;
        }
Ejemplo n.º 11
0
        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_DATABASE_FILENAME, Host.UpdateThread, EFContextFactory));

            dependencies.CacheAs <RulesetStore>(RulesetStore = new RealmRulesetStore(realm, Storage));
            dependencies.CacheAs <IRulesetStore>(RulesetStore);

            Decoder.RegisterDependencies(RulesetStore);

            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 = CreateEndpoints();

            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(difficultyCache = new BeatmapDifficultyCache());

            // 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));

            // Add after all the above cache operations as it depends on them.
            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);
        }
Ejemplo n.º 12
0
        private void load()
        {
            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.Cache(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/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);

            if (API == null)
            {
                API = new APIAccess(LocalConfig);
            }

            dependencies.CacheAs(API);

            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));
            dependencies.Cache(BeatmapManager = new BeatmapManager(Storage, contextFactory, RulesetStore, API, Audio, Host, defaultBeatmap));

            // 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 += i => ScoreManager.Delete(getBeatmapScores(i), true);
            BeatmapManager.ItemAdded   += i => ScoreManager.Undelete(getBeatmapScores(i), true);

            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());

            fileImporters.Add(BeatmapManager);
            fileImporters.Add(ScoreManager);
            fileImporters.Add(SkinManager);

            // tracks play so loud our samples can't keep up.
            // this adds a global reduction of track volume for the time being.
            Audio.Tracks.AddAdjustment(AdjustableProperty.Volume, new BindableDouble(0.8));

            Beatmap = new NonNullableBindable <WorkingBeatmap>(defaultBeatmap);

            // ScheduleAfterChildren is safety against something in the current frame accessing the previous beatmap's track
            // and potentially causing a reload of it after just unloading.
            // Note that the reason for this being added *has* been resolved, so it may be feasible to removed this if required.
            Beatmap.BindValueChanged(b => ScheduleAfterChildren(() =>
            {
                // compare to last beatmap as sometimes the two may share a track representation (optimisation, see WorkingBeatmap.TransferTo)
                if (b.OldValue?.TrackLoaded == true && b.OldValue?.Track != b.NewValue?.Track)
                {
                    b.OldValue.RecycleTrack();
                }
            }));

            dependencies.CacheAs <IBindable <WorkingBeatmap> >(Beatmap);
            dependencies.CacheAs(Beatmap);

            FileStore.Cleanup();

            if (API is APIAccess apiAcces)
            {
                AddInternal(apiAcces);
            }
            AddInternal(RulesetConfigCache);

            GlobalActionContainer globalBinding;

            MenuCursorContainer = new MenuCursorContainer {
                RelativeSizeAxes = Axes.Both
            };
            MenuCursorContainer.Child = globalBinding = new GlobalActionContainer(this)
            {
                RelativeSizeAxes = Axes.Both,
                Child            = content = new OsuTooltipContainer(MenuCursorContainer.Cursor)
                {
                    RelativeSizeAxes = Axes.Both
                }
            };

            base.Content.Add(CreateScalingContainer().WithChild(MenuCursorContainer));

            KeyBindingStore.Register(globalBinding);
            dependencies.Cache(globalBinding);

            PreviewTrackManager previewTrackManager;

            dependencies.Cache(previewTrackManager = new PreviewTrackManager());
            Add(previewTrackManager);

            Ruleset.BindValueChanged(onRulesetChanged);
        }
Ejemplo n.º 13
0
 protected override IReadOnlyDependencyContainer CreateLocalDependencies(IReadOnlyDependencyContainer parent)
 {
     dependencies = new DependencyContainer(base.CreateLocalDependencies(parent));
     dependencies.CacheAs <IScrollingInfo>(scrollingInfo = new ScrollingInfo());
     return(dependencies);
 }
Ejemplo n.º 14
0
        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.Cache(RulesetStore = new RulesetStore(realm, Storage));
            dependencies.CacheAs <IRulesetStore>(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);
        }
Ejemplo n.º 15
0
        private void load(OsuColour colours, OsuConfigManager config)
        {
            var loadableBeatmap = Beatmap.Value;

            if (loadableBeatmap is DummyWorkingBeatmap)
            {
                isNewBeatmap = true;

                loadableBeatmap = beatmapManager.CreateNew(Ruleset.Value, api.LocalUser.Value);

                // required so we can get the track length in EditorClock.
                // this is safe as nothing has yet got a reference to this new beatmap.
                loadableBeatmap.LoadTrack();

                // this is a bit haphazard, but guards against setting the lease Beatmap bindable if
                // the editor has already been exited.
                if (!ValidForPush)
                {
                    return;
                }
            }

            try
            {
                playableBeatmap = loadableBeatmap.GetPlayableBeatmap(loadableBeatmap.BeatmapInfo.Ruleset);

                // clone these locally for now to avoid incurring overhead on GetPlayableBeatmap usages.
                // eventually we will want to improve how/where this is done as there are issues with *not* cloning it in all cases.
                playableBeatmap.ControlPointInfo = playableBeatmap.ControlPointInfo.DeepClone();
            }
            catch (Exception e)
            {
                Logger.Error(e, "Could not load beatmap successfully!");
                // couldn't load, hard abort!
                this.Exit();
                return;
            }

            beatDivisor.Value = playableBeatmap.BeatmapInfo.BeatDivisor;
            beatDivisor.BindValueChanged(divisor => playableBeatmap.BeatmapInfo.BeatDivisor = divisor.NewValue);

            // Todo: should probably be done at a DrawableRuleset level to share logic with Player.
            clock = new EditorClock(playableBeatmap, beatDivisor)
            {
                IsCoupled = false
            };
            clock.ChangeSource(loadableBeatmap.Track);

            dependencies.CacheAs(clock);
            AddInternal(clock);

            clock.SeekingOrStopped.BindValueChanged(_ => updateSampleDisabledState());

            // todo: remove caching of this and consume via editorBeatmap?
            dependencies.Cache(beatDivisor);

            AddInternal(editorBeatmap = new EditorBeatmap(playableBeatmap, loadableBeatmap.GetSkin()));
            dependencies.CacheAs(editorBeatmap);
            changeHandler = new EditorChangeHandler(editorBeatmap);
            dependencies.CacheAs <IEditorChangeHandler>(changeHandler);

            updateLastSavedHash();

            Schedule(() =>
            {
                // we need to avoid changing the beatmap from an asynchronous load thread. it can potentially cause weirdness including crashes.
                // this assumes that nothing during the rest of this load() method is accessing Beatmap.Value (loadableBeatmap should be preferred).
                // generally this is quite safe, as the actual load of editor content comes after menuBar.Mode.ValueChanged is fired in its own LoadComplete.
                Beatmap.Value = loadableBeatmap;
            });

            OsuMenuItem undoMenuItem;
            OsuMenuItem redoMenuItem;

            EditorMenuItem cutMenuItem;
            EditorMenuItem copyMenuItem;
            EditorMenuItem pasteMenuItem;

            AddInternal(new OsuContextMenuContainer
            {
                RelativeSizeAxes = Axes.Both,
                Children         = new[]
                {
                    new Container
                    {
                        Name             = "Screen container",
                        RelativeSizeAxes = Axes.Both,
                        Padding          = new MarginPadding {
                            Top = 40, Bottom = 60
                        },
                        Child = screenContainer = new Container <EditorScreen>
                        {
                            RelativeSizeAxes = Axes.Both,
                            Masking          = true
                        }
                    },
                    new Container
                    {
                        Name             = "Top bar",
                        RelativeSizeAxes = Axes.X,
                        Height           = 40,
                        Child            = menuBar = new EditorMenuBar
                        {
                            Anchor           = Anchor.CentreLeft,
                            Origin           = Anchor.CentreLeft,
                            RelativeSizeAxes = Axes.Both,
                            Mode             = { Value = isNewBeatmap ? EditorScreenMode.SongSetup : EditorScreenMode.Compose },
                            Items            = new[]
                            {
                                new MenuItem("File")
                                {
                                    Items = createFileMenuItems()
                                },
                                new MenuItem("Edit")
                                {
                                    Items = new[]
                                    {
                                        undoMenuItem = new EditorMenuItem("Undo", MenuItemType.Standard, Undo),
                                        redoMenuItem = new EditorMenuItem("Redo", MenuItemType.Standard, Redo),
                                        new EditorMenuItemSpacer(),
                                        cutMenuItem   = new EditorMenuItem("Cut", MenuItemType.Standard, Cut),
                                        copyMenuItem  = new EditorMenuItem("Copy", MenuItemType.Standard, Copy),
                                        pasteMenuItem = new EditorMenuItem("Paste", MenuItemType.Standard, Paste),
                                    }
                                },
                                new MenuItem("View")
                                {
                                    Items = new MenuItem[]
                                    {
                                        new WaveformOpacityMenuItem(config.GetBindable <float>(OsuSetting.EditorWaveformOpacity)),
                                        new HitAnimationsMenuItem(config.GetBindable <bool>(OsuSetting.EditorHitAnimations))
                                    }
                                }
                            }
                        }
                    },
                    new Container
                    {
                        Name             = "Bottom bar",
                        Anchor           = Anchor.BottomLeft,
                        Origin           = Anchor.BottomLeft,
                        RelativeSizeAxes = Axes.X,
                        Height           = 60,
                        Children         = new Drawable[]
                        {
                            new Box
                            {
                                RelativeSizeAxes = Axes.Both,
                                Colour           = colours.Gray2
                            },
                            new Container
                            {
                                RelativeSizeAxes = Axes.Both,
                                Padding          = new MarginPadding {
                                    Vertical = 5, Horizontal = 10
                                },
                                Child = new GridContainer
                                {
                                    RelativeSizeAxes = Axes.Both,
                                    ColumnDimensions = new[]
                                    {
                                        new Dimension(GridSizeMode.Absolute, 220),
                                        new Dimension(),
                                        new Dimension(GridSizeMode.Absolute, 220)
                                    },
                                    Content = new[]
                                    {
                                        new Drawable[]
                                        {
                                            new Container
                                            {
                                                RelativeSizeAxes = Axes.Both,
                                                Padding          = new MarginPadding {
                                                    Right = 10
                                                },
                                                Child = new TimeInfoContainer {
                                                    RelativeSizeAxes = Axes.Both
                                                },
                                            },
                                            new SummaryTimeline
                                            {
                                                RelativeSizeAxes = Axes.Both,
                                            },
                                            new Container
                                            {
                                                RelativeSizeAxes = Axes.Both,
                                                Padding          = new MarginPadding {
                                                    Left = 10
                                                },
                                                Child = new PlaybackControl {
                                                    RelativeSizeAxes = Axes.Both
                                                },
                                            }
                                        },
                                    }
                                },
                            }
                        }
                    },
                }
            });

            changeHandler.CanUndo.BindValueChanged(v => undoMenuItem.Action.Disabled = !v.NewValue, true);
            changeHandler.CanRedo.BindValueChanged(v => redoMenuItem.Action.Disabled = !v.NewValue, true);

            editorBeatmap.SelectedHitObjects.BindCollectionChanged((_, __) =>
            {
                var hasObjects = editorBeatmap.SelectedHitObjects.Count > 0;

                cutMenuItem.Action.Disabled  = !hasObjects;
                copyMenuItem.Action.Disabled = !hasObjects;
            }, true);

            clipboard.BindValueChanged(content => pasteMenuItem.Action.Disabled = string.IsNullOrEmpty(content.NewValue));

            menuBar.Mode.ValueChanged += onModeChanged;
        }
Ejemplo n.º 16
0
        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.Cache(realmFactory = new RealmContextFactory(Storage));

            updateThreadState = Host.UpdateThread.State.GetBoundCopy();
            updateThreadState.BindValueChanged(updateThreadStateChanged);

            AddInternal(realmFactory);

            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/Torus-Regular");
            AddFont(Resources, @"Fonts/Torus/Torus-Light");
            AddFont(Resources, @"Fonts/Torus/Torus-SemiBold");
            AddFont(Resources, @"Fonts/Torus/Torus-Bold");

            AddFont(Resources, @"Fonts/Inter/Inter-Regular");
            AddFont(Resources, @"Fonts/Inter/Inter-RegularItalic");
            AddFont(Resources, @"Fonts/Inter/Inter-Light");
            AddFont(Resources, @"Fonts/Inter/Inter-LightItalic");
            AddFont(Resources, @"Fonts/Inter/Inter-SemiBold");
            AddFont(Resources, @"Fonts/Inter/Inter-SemiBoldItalic");
            AddFont(Resources, @"Fonts/Inter/Inter-Bold");
            AddFont(Resources, @"Fonts/Inter/Inter-BoldItalic");

            AddFont(Resources, @"Fonts/Noto/Noto-Basic");
            AddFont(Resources, @"Fonts/Noto/Noto-Hangul");
            AddFont(Resources, @"Fonts/Noto/Noto-CJK-Basic");
            AddFont(Resources, @"Fonts/Noto/Noto-CJK-Compatibility");
            AddFont(Resources, @"Fonts/Noto/Noto-Thai");

            AddFont(Resources, @"Fonts/Venera/Venera-Light");
            AddFont(Resources, @"Fonts/Venera/Venera-Bold");
            AddFont(Resources, @"Fonts/Venera/Venera-Black");

            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.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();

            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, Host, () => difficultyCache, LocalConfig));
            dependencies.Cache(BeatmapManager = new BeatmapManager(Storage, contextFactory, RulesetStore, API, Audio, Resources, Host, defaultBeatmap, true));

            // 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.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);

            migrateDataToRealm();

            dependencies.Cache(settingsStore      = new SettingsStore(contextFactory));
            dependencies.Cache(rulesetConfigCache = new RulesetConfigCache(settingsStore));

            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 = new PopoverContainer
            {
                RelativeSizeAxes = Axes.Both,
                Child            = content = new OsuTooltipContainer(MenuCursorContainer.Cursor)
                {
                    RelativeSizeAxes = Axes.Both
                }
            };

            base.Content.Add(CreateScalingContainer().WithChildren(mainContent));

            KeyBindingStore = new RealmKeyBindingStore(realmFactory);
            KeyBindingStore.Register(globalBindings);

            foreach (var r in RulesetStore.AvailableRulesets)
            {
                KeyBindingStore.Register(r);
            }

            dependencies.Cache(globalBindings);

            PreviewTrackManager previewTrackManager;

            dependencies.Cache(previewTrackManager = new PreviewTrackManager());
            Add(previewTrackManager);

            AddInternal(MusicController = new MusicController());
            dependencies.CacheAs(MusicController);

            Ruleset.BindValueChanged(onRulesetChanged);
        }
Ejemplo n.º 17
0
        private void load()
        {
            Config = Dependencies.Get <IRulesetConfigCache>().GetConfigFor(Ruleset);

            try
            {
                drawableRulesetWrapper = new DrawableEditorRulesetWrapper <TObject>(CreateDrawableRuleset(Ruleset, EditorBeatmap.PlayableBeatmap, new[] { Ruleset.GetAutoplayMod() }))
                {
                    Clock = EditorClock,
                    ProcessCustomClock = false
                };
            }
            catch (Exception e)
            {
                Logger.Error(e, "Could not load beatmap successfully!");
                return;
            }

            dependencies.CacheAs(Playfield);

            InternalChildren = new Drawable[]
            {
                new Container
                {
                    Name             = "Content",
                    RelativeSizeAxes = Axes.Both,
                    Children         = new Drawable[]
                    {
                        // layers below playfield
                        drawableRulesetWrapper.CreatePlayfieldAdjustmentContainer().WithChild(LayerBelowRuleset),
                        drawableRulesetWrapper,
                        // layers above playfield
                        drawableRulesetWrapper.CreatePlayfieldAdjustmentContainer()
                        .WithChild(BlueprintContainer = CreateBlueprintContainer())
                    }
                },
                new ExpandingToolboxContainer(90, 200)
                {
                    Padding  = new MarginPadding(10),
                    Children = new Drawable[]
                    {
                        new EditorToolboxGroup("toolbox (1-9)")
                        {
                            Child = toolboxCollection = new EditorRadioButtonCollection {
                                RelativeSizeAxes = Axes.X
                            }
                        },
                        new EditorToolboxGroup("toggles (Q~P)")
                        {
                            Child = togglesCollection = new FillFlowContainer
                            {
                                RelativeSizeAxes = Axes.X,
                                AutoSizeAxes     = Axes.Y,
                                Direction        = FillDirection.Vertical,
                                Spacing          = new Vector2(0, 5),
                            },
                        }
                    }
                },
            };

            toolboxCollection.Items = CompositionTools
                                      .Prepend(new SelectTool())
                                      .Select(t => new RadioButton(t.Name, () => toolSelected(t), t.CreateIcon))
                                      .ToList();

            TernaryStates = CreateTernaryButtons().ToArray();
            togglesCollection.AddRange(TernaryStates.Select(b => new DrawableTernaryButton(b)));

            setSelectTool();

            EditorBeatmap.SelectedHitObjects.CollectionChanged += selectionChanged;
        }
Ejemplo n.º 18
0
        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);

            // tracks play so loud our samples can't keep up.
            // this adds a global reduction of track volume for the time being.
            Audio.Tracks.AddAdjustment(AdjustableProperty.Volume, new BindableDouble(0.8));

            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);
        }
Ejemplo n.º 19
0
        private void load()
        {
            if (!Host.IsPrimaryInstance && !DebugUtils.IsDebugBuild)
            {
                Logger.Log(@"osu! does not support multiple running instances.", LoggingTarget.Runtime, LogLevel.Error);
                Environment.Exit(0);
            }

            if (args?.Length > 0)
            {
                var paths = args.Where(a => !a.StartsWith('-')).ToArray();
                if (paths.Length > 0)
                {
                    Task.Run(() => Import(paths));
                }
            }

            dependencies.CacheAs(this);

            dependencies.Cache(SentryLogger);

            dependencies.Cache(osuLogo = new OsuLogo {
                Alpha = 0
            });

            // bind config int to database RulesetInfo
            configRuleset         = LocalConfig.GetBindable <int>(OsuSetting.Ruleset);
            Ruleset.Value         = RulesetStore.GetRuleset(configRuleset.Value) ?? RulesetStore.AvailableRulesets.First();
            Ruleset.ValueChanged += r => configRuleset.Value = r.NewValue.ID ?? 0;

            // bind config int to database SkinInfo
            configSkin = LocalConfig.GetBindable <int>(OsuSetting.Skin);
            SkinManager.CurrentSkinInfo.ValueChanged += skin => configSkin.Value = skin.NewValue.ID;
            configSkin.ValueChanged += skinId =>
            {
                var skinInfo = SkinManager.Query(s => s.ID == skinId.NewValue);

                if (skinInfo == null)
                {
                    switch (skinId.NewValue)
                    {
                    case -1:
                        skinInfo = DefaultLegacySkin.Info;
                        break;

                    default:
                        skinInfo = SkinInfo.Default;
                        break;
                    }
                }

                SkinManager.CurrentSkinInfo.Value = skinInfo;
            };
            configSkin.TriggerChange();

            IsActive.BindValueChanged(active => updateActiveState(active.NewValue), true);

            Audio.AddAdjustment(AdjustableProperty.Volume, inactiveVolumeFade);

            SelectedMods.BindValueChanged(modsChanged);
            Beatmap.BindValueChanged(beatmapChanged, true);
        }
Ejemplo n.º 20
0
        private void load()
        {
            dependencies.CacheAs(this);

            dependencies.Cache(SentryLogger);

            dependencies.Cache(osuLogo = new OsuLogo {
                Alpha = 0
            });

            // bind config int to database RulesetInfo
            configRuleset = LocalConfig.GetBindable <string>(OsuSetting.Ruleset);
            uiScale       = LocalConfig.GetBindable <float>(OsuSetting.UIScale);

            var preferredRuleset = int.TryParse(configRuleset.Value, out int rulesetId)
                                   // int parsing can be removed 20220522
                ? RulesetStore.GetRuleset(rulesetId)
                : RulesetStore.GetRuleset(configRuleset.Value);

            try
            {
                Ruleset.Value = preferredRuleset ?? RulesetStore.AvailableRulesets.First();
            }
            catch (Exception e)
            {
                // on startup, a ruleset may be selected which has compatibility issues.
                Logger.Error(e, $@"Failed to switch to preferred ruleset {preferredRuleset}.");
                Ruleset.Value = RulesetStore.AvailableRulesets.First();
            }

            Ruleset.ValueChanged += r => configRuleset.Value = r.NewValue.ShortName;

            // bind config int to database SkinInfo
            configSkin = LocalConfig.GetBindable <string>(OsuSetting.Skin);
            SkinManager.CurrentSkinInfo.ValueChanged += skin => configSkin.Value = skin.NewValue.ID.ToString();
            configSkin.ValueChanged += skinId =>
            {
                ILive <SkinInfo> skinInfo = null;

                if (Guid.TryParse(skinId.NewValue, out var guid))
                {
                    skinInfo = SkinManager.Query(s => s.ID == guid);
                }

                if (skinInfo == null)
                {
                    if (guid == SkinInfo.CLASSIC_SKIN)
                    {
                        skinInfo = DefaultLegacySkin.CreateInfo().ToLiveUnmanaged();
                    }
                }

                SkinManager.CurrentSkinInfo.Value = skinInfo ?? DefaultSkin.CreateInfo().ToLiveUnmanaged();
            };
            configSkin.TriggerChange();

            IsActive.BindValueChanged(active => updateActiveState(active.NewValue), true);

            Audio.AddAdjustment(AdjustableProperty.Volume, inactiveVolumeFade);

            SelectedMods.BindValueChanged(modsChanged);
            Beatmap.BindValueChanged(beatmapChanged, true);
        }