1
0
mirror of https://github.com/ppy/osu.git synced 2024-11-06 06:17:23 +08:00

Merge pull request #6940 from aspriddell/cinema-mod

Add "Cinema" mod
This commit is contained in:
Dean Herbert 2019-12-17 14:33:12 +09:00 committed by GitHub
commit 735b7a8455
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
16 changed files with 193 additions and 26 deletions

View File

@ -51,7 +51,9 @@ namespace osu.Game.Rulesets.Catch
else if (mods.HasFlag(LegacyMods.SuddenDeath))
yield return new CatchModSuddenDeath();
if (mods.HasFlag(LegacyMods.Autoplay))
if (mods.HasFlag(LegacyMods.Cinema))
yield return new CatchModCinema();
else if (mods.HasFlag(LegacyMods.Autoplay))
yield return new CatchModAutoplay();
if (mods.HasFlag(LegacyMods.Easy))
@ -101,7 +103,7 @@ namespace osu.Game.Rulesets.Catch
case ModType.Automation:
return new Mod[]
{
new MultiMod(new CatchModAutoplay(), new ModCinema()),
new MultiMod(new CatchModAutoplay(), new CatchModCinema()),
new CatchModRelax(),
};

View File

@ -0,0 +1,21 @@
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
// See the LICENCE file in the repository root for full licence text.
using osu.Game.Beatmaps;
using osu.Game.Rulesets.Catch.Objects;
using osu.Game.Rulesets.Catch.Replays;
using osu.Game.Rulesets.Mods;
using osu.Game.Scoring;
using osu.Game.Users;
namespace osu.Game.Rulesets.Catch.Mods
{
public class CatchModCinema : ModCinema<CatchHitObject>
{
public override Score CreateReplayScore(IBeatmap beatmap) => new Score
{
ScoreInfo = new ScoreInfo { User = new User { Username = "osu!salad!" } },
Replay = new CatchAutoGenerator(beatmap).Generate(),
};
}
}

View File

@ -51,7 +51,9 @@ namespace osu.Game.Rulesets.Mania
else if (mods.HasFlag(LegacyMods.SuddenDeath))
yield return new ManiaModSuddenDeath();
if (mods.HasFlag(LegacyMods.Autoplay))
if (mods.HasFlag(LegacyMods.Cinema))
yield return new ManiaModCinema();
else if (mods.HasFlag(LegacyMods.Autoplay))
yield return new ManiaModAutoplay();
if (mods.HasFlag(LegacyMods.Easy))
@ -148,7 +150,7 @@ namespace osu.Game.Rulesets.Mania
case ModType.Automation:
return new Mod[]
{
new MultiMod(new ManiaModAutoplay(), new ModCinema()),
new MultiMod(new ManiaModAutoplay(), new ManiaModCinema()),
};
case ModType.Fun:

View File

@ -0,0 +1,22 @@
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
// See the LICENCE file in the repository root for full licence text.
using osu.Game.Beatmaps;
using osu.Game.Rulesets.Mania.Beatmaps;
using osu.Game.Rulesets.Mania.Objects;
using osu.Game.Rulesets.Mania.Replays;
using osu.Game.Rulesets.Mods;
using osu.Game.Scoring;
using osu.Game.Users;
namespace osu.Game.Rulesets.Mania.Mods
{
public class ManiaModCinema : ModCinema<ManiaHitObject>
{
public override Score CreateReplayScore(IBeatmap beatmap) => new Score
{
ScoreInfo = new ScoreInfo { User = new User { Username = "osu!topus!" } },
Replay = new ManiaAutoGenerator((ManiaBeatmap)beatmap).Generate(),
};
}
}

View File

@ -0,0 +1,25 @@
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
// See the LICENCE file in the repository root for full licence text.
using System;
using System.Linq;
using osu.Game.Beatmaps;
using osu.Game.Rulesets.Mods;
using osu.Game.Rulesets.Osu.Objects;
using osu.Game.Rulesets.Osu.Replays;
using osu.Game.Scoring;
using osu.Game.Users;
namespace osu.Game.Rulesets.Osu.Mods
{
public class OsuModCinema : ModCinema<OsuHitObject>
{
public override Type[] IncompatibleMods => base.IncompatibleMods.Append(typeof(OsuModAutopilot)).Append(typeof(OsuModSpunOut)).ToArray();
public override Score CreateReplayScore(IBeatmap beatmap) => new Score
{
ScoreInfo = new ScoreInfo { User = new User { Username = "Autoplay" } },
Replay = new OsuAutoGenerator(beatmap).Generate()
};
}
}

View File

@ -60,7 +60,9 @@ namespace osu.Game.Rulesets.Osu
if (mods.HasFlag(LegacyMods.Autopilot))
yield return new OsuModAutopilot();
if (mods.HasFlag(LegacyMods.Autoplay))
if (mods.HasFlag(LegacyMods.Cinema))
yield return new OsuModCinema();
else if (mods.HasFlag(LegacyMods.Autoplay))
yield return new OsuModAutoplay();
if (mods.HasFlag(LegacyMods.Easy))
@ -126,7 +128,7 @@ namespace osu.Game.Rulesets.Osu
case ModType.Automation:
return new Mod[]
{
new MultiMod(new OsuModAutoplay(), new ModCinema()),
new MultiMod(new OsuModAutoplay(), new OsuModCinema()),
new OsuModRelax(),
new OsuModAutopilot(),
};

View File

@ -0,0 +1,21 @@
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
// See the LICENCE file in the repository root for full licence text.
using osu.Game.Beatmaps;
using osu.Game.Rulesets.Mods;
using osu.Game.Rulesets.Taiko.Objects;
using osu.Game.Rulesets.Taiko.Replays;
using osu.Game.Scoring;
using osu.Game.Users;
namespace osu.Game.Rulesets.Taiko.Mods
{
public class TaikoModCinema : ModCinema<TaikoHitObject>
{
public override Score CreateReplayScore(IBeatmap beatmap) => new Score
{
ScoreInfo = new ScoreInfo { User = new User { Username = "mekkadosu!" } },
Replay = new TaikoAutoGenerator(beatmap).Generate(),
};
}
}

View File

@ -50,7 +50,9 @@ namespace osu.Game.Rulesets.Taiko
else if (mods.HasFlag(LegacyMods.SuddenDeath))
yield return new TaikoModSuddenDeath();
if (mods.HasFlag(LegacyMods.Autoplay))
if (mods.HasFlag(LegacyMods.Cinema))
yield return new TaikoModCinema();
else if (mods.HasFlag(LegacyMods.Autoplay))
yield return new TaikoModAutoplay();
if (mods.HasFlag(LegacyMods.Easy))
@ -100,7 +102,7 @@ namespace osu.Game.Rulesets.Taiko
case ModType.Automation:
return new Mod[]
{
new MultiMod(new TaikoModAutoplay(), new ModCinema()),
new MultiMod(new TaikoModAutoplay(), new TaikoModCinema()),
new TaikoModRelax(),
};

View File

@ -88,6 +88,20 @@ namespace osu.Game.Tests.Visual.Background
AddUntilStep("not lightened", () => userDimContainer.DimEqual(test_user_dim));
}
[Test]
public void TestIgnoreUserSettings()
{
AddStep("set dim level 0.6", () => userDimContainer.UserDimLevel.Value = test_user_dim);
AddUntilStep("dim reached", () => userDimContainer.DimEqual(test_user_dim));
AddStep("ignore settings", () => userDimContainer.IgnoreUserSettings.Value = true);
AddUntilStep("no dim", () => userDimContainer.DimEqual(0));
AddStep("set break", () => isBreakTime.Value = true);
AddAssert("no dim", () => userDimContainer.DimEqual(0));
AddStep("clear break", () => isBreakTime.Value = false);
AddAssert("no dim", () => userDimContainer.DimEqual(0));
}
private class TestUserDimContainer : UserDimContainer
{
public bool DimEqual(float expectedDimLevel) => Content.Colour == OsuColour.Gray(1f - expectedDimLevel);

View File

@ -28,6 +28,11 @@ namespace osu.Game.Graphics.Containers
/// </summary>
public readonly Bindable<bool> EnableUserDim = new Bindable<bool>(true);
/// <summary>
/// Whether or not user-configured settings relating to brightness of elements should be ignored
/// </summary>
public readonly Bindable<bool> IgnoreUserSettings = new Bindable<bool>();
/// <summary>
/// Whether or not the storyboard loaded should completely hide the background behind it.
/// </summary>
@ -53,7 +58,8 @@ namespace osu.Game.Graphics.Containers
protected Bindable<bool> ShowVideo { get; private set; }
private float breakLightening => LightenDuringBreaks.Value && IsBreakTime.Value ? BREAK_LIGHTEN_AMOUNT : 0;
protected float DimLevel => Math.Max(EnableUserDim.Value ? (float)UserDimLevel.Value - breakLightening : 0, 0);
protected float DimLevel => Math.Max(EnableUserDim.Value && !IgnoreUserSettings.Value ? (float)UserDimLevel.Value - breakLightening : 0, 0);
protected override Container<Drawable> Content => dimContent;
@ -82,6 +88,7 @@ namespace osu.Game.Graphics.Containers
ShowStoryboard.ValueChanged += _ => UpdateVisuals();
ShowVideo.ValueChanged += _ => UpdateVisuals();
StoryboardReplacesBackground.ValueChanged += _ => UpdateVisuals();
IgnoreUserSettings.ValueChanged += _ => UpdateVisuals();
}
protected override void LoadComplete()

View File

@ -0,0 +1,15 @@
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
// See the LICENCE file in the repository root for full licence text.
using osu.Game.Screens.Play;
namespace osu.Game.Rulesets.Mods
{
/// <summary>
/// An interface for a mod which can temporarily override the <see cref="Player"/> settings.
/// </summary>
public interface IApplicableToPlayer : IApplicableMod
{
void ApplyToPlayer(Player player);
}
}

View File

@ -3,15 +3,46 @@
using osu.Framework.Graphics.Sprites;
using osu.Game.Graphics;
using osu.Game.Rulesets.Objects;
using osu.Game.Rulesets.UI;
using osu.Game.Screens.Play;
namespace osu.Game.Rulesets.Mods
{
public class ModCinema : ModAutoplay
public abstract class ModCinema<T> : ModCinema, IApplicableToDrawableRuleset<T>
where T : HitObject
{
public virtual void ApplyToDrawableRuleset(DrawableRuleset<T> drawableRuleset)
{
drawableRuleset.SetReplayScore(CreateReplayScore(drawableRuleset.Beatmap));
// AlwaysPresent required for hitsounds
drawableRuleset.Playfield.AlwaysPresent = true;
drawableRuleset.Playfield.Hide();
}
}
public class ModCinema : ModAutoplay, IApplicableToHUD, IApplicableToPlayer
{
public override string Name => "Cinema";
public override string Acronym => "CN";
public override bool HasImplementation => false;
public override IconUsage Icon => OsuIcon.ModCinema;
public override string Description => "Watch the video without visual distractions.";
public void ApplyToHUD(HUDOverlay overlay)
{
overlay.ShowHud.Value = false;
overlay.ShowHud.Disabled = true;
}
public void ApplyToPlayer(Player player)
{
player.Background.EnableUserDim.Value = false;
player.DimmableVideo.IgnoreUserSettings.Value = true;
player.DimmableStoryboard.IgnoreUserSettings.Value = true;
player.BreakOverlay.Hide();
}
}
}

View File

@ -33,14 +33,14 @@ namespace osu.Game.Screens.Play
base.LoadComplete();
}
protected override bool ShowDimContent => ShowStoryboard.Value && DimLevel < 1;
protected override bool ShowDimContent => IgnoreUserSettings.Value || (ShowStoryboard.Value && DimLevel < 1);
private void initializeStoryboard(bool async)
{
if (drawableStoryboard != null)
return;
if (!ShowStoryboard.Value)
if (!ShowStoryboard.Value && !IgnoreUserSettings.Value)
return;
drawableStoryboard = storyboard.CreateDrawable();

View File

@ -33,7 +33,7 @@ namespace osu.Game.Screens.Play
base.LoadComplete();
}
protected override bool ShowDimContent => ShowVideo.Value && DimLevel < 1;
protected override bool ShowDimContent => IgnoreUserSettings.Value || (ShowVideo.Value && DimLevel < 1);
private void initializeVideo(bool async)
{
@ -43,7 +43,7 @@ namespace osu.Game.Screens.Play
if (drawableVideo != null)
return;
if (!ShowVideo.Value)
if (!ShowVideo.Value && !IgnoreUserSettings.Value)
return;
drawableVideo = new DrawableVideo(video);

View File

@ -69,7 +69,7 @@ namespace osu.Game.Screens.Play
private SampleChannel sampleRestart;
private BreakOverlay breakOverlay;
public BreakOverlay BreakOverlay;
protected ScoreProcessor ScoreProcessor { get; private set; }
protected DrawableRuleset DrawableRuleset { get; private set; }
@ -80,8 +80,8 @@ namespace osu.Game.Screens.Play
protected GameplayClockContainer GameplayClockContainer { get; private set; }
protected DimmableStoryboard DimmableStoryboard { get; private set; }
protected DimmableVideo DimmableVideo { get; private set; }
public DimmableStoryboard DimmableStoryboard { get; private set; }
public DimmableVideo DimmableVideo { get; private set; }
[Cached]
[Cached(Type = typeof(IBindable<IReadOnlyList<Mod>>))]
@ -154,7 +154,7 @@ namespace osu.Game.Screens.Play
foreach (var mod in Mods.Value.OfType<IApplicableToScoreProcessor>())
mod.ApplyToScoreProcessor(ScoreProcessor);
breakOverlay.IsBreakTime.ValueChanged += _ => updatePauseOnFocusLostState();
BreakOverlay.IsBreakTime.ValueChanged += _ => updatePauseOnFocusLostState();
}
private void addUnderlayComponents(Container target)
@ -188,7 +188,7 @@ namespace osu.Game.Screens.Play
{
target.AddRange(new[]
{
breakOverlay = new BreakOverlay(working.Beatmap.BeatmapInfo.LetterboxInBreaks, DrawableRuleset.GameplayStartTime, ScoreProcessor)
BreakOverlay = new BreakOverlay(working.Beatmap.BeatmapInfo.LetterboxInBreaks, DrawableRuleset.GameplayStartTime, ScoreProcessor)
{
Anchor = Anchor.Centre,
Origin = Anchor.Centre,
@ -253,7 +253,7 @@ namespace osu.Game.Screens.Play
private void updatePauseOnFocusLostState() =>
HUDOverlay.HoldToQuit.PauseOnFocusLost = PauseOnFocusLost
&& !DrawableRuleset.HasReplayLoaded.Value
&& !breakOverlay.IsBreakTime.Value;
&& !BreakOverlay.IsBreakTime.Value;
private IBeatmap loadPlayableBeatmap()
{
@ -478,7 +478,7 @@ namespace osu.Game.Screens.Play
PauseOverlay.Hide();
// breaks and time-based conditions may allow instant resume.
if (breakOverlay.IsBreakTime.Value)
if (BreakOverlay.IsBreakTime.Value)
completeResume();
else
DrawableRuleset.RequestResume(completeResume);
@ -512,9 +512,9 @@ namespace osu.Game.Screens.Play
Background.BlurAmount.Value = 0;
// bind component bindables.
Background.IsBreakTime.BindTo(breakOverlay.IsBreakTime);
DimmableStoryboard.IsBreakTime.BindTo(breakOverlay.IsBreakTime);
DimmableVideo.IsBreakTime.BindTo(breakOverlay.IsBreakTime);
Background.IsBreakTime.BindTo(BreakOverlay.IsBreakTime);
DimmableStoryboard.IsBreakTime.BindTo(BreakOverlay.IsBreakTime);
DimmableVideo.IsBreakTime.BindTo(BreakOverlay.IsBreakTime);
Background.StoryboardReplacesBackground.BindTo(storyboardReplacesBackground);
DimmableStoryboard.StoryboardReplacesBackground.BindTo(storyboardReplacesBackground);
@ -524,6 +524,9 @@ namespace osu.Game.Screens.Play
GameplayClockContainer.Restart();
GameplayClockContainer.FadeInFromZero(750, Easing.OutQuint);
foreach (var mod in Mods.Value.OfType<IApplicableToPlayer>())
mod.ApplyToPlayer(this);
foreach (var mod in Mods.Value.OfType<IApplicableToHUD>())
mod.ApplyToHUD(HUDOverlay);
}

View File

@ -9,6 +9,6 @@ namespace osu.Game.Screens.Play
{
protected override BackgroundScreen CreateBackground() => new BackgroundScreenBeatmap(Beatmap.Value);
protected new BackgroundScreenBeatmap Background => (BackgroundScreenBeatmap)base.Background;
public new BackgroundScreenBeatmap Background => (BackgroundScreenBeatmap)base.Background;
}
}