Epilepsy warning for SV maps#4576
Conversation
|
SELF DESTRUCT MENTIONED 🗣🗣 |
this was actually not skinnable at the moment, as I don't know which folder I should put this in lmao but yea prob could make this animatable |
There was a problem hiding this comment.
Pull request overview
Adds an in-game epilepsy warning that fades in before maps with significant scroll-velocity (SV) usage start, plus a user-facing toggle and a skinnable texture. The warning is wired into the keys playfield stage, exposed through the options menu, and persisted via ConfigManager.
Changes:
- New
EpilepsyWarningsprite that decides visibility based on map tags / SV magnitude and fades in/out around track start. - New
DisplayEpilepsyWarningconfig bindable + options checkbox to toggle the warning. - New skin/UI texture entries (
SkinStore.EpilepsyWarning,UserInterface.EpilepsyWarning) and instantiation fromGameplayPlayfieldKeysStage.
Reviewed changes
Copilot reviewed 9 out of 9 changed files in this pull request and generated 5 comments.
Show a summary per file
| File | Description |
|---|---|
| Quaver.Shared/Screens/Gameplay/UI/EpilepsyWarning.cs | New sprite implementing the warning logic and fade animation. |
| Quaver.Shared/Screens/Gameplay/Rulesets/Keys/Playfield/GameplayPlayfieldKeysStage.cs | Instantiates the warning as part of the keys playfield. |
| Quaver.Shared/Skinning/SkinStore.cs | Loads the epilepsy-warning texture from skin or default resources. |
| Quaver.Shared/Assets/UserInterface.cs | Exposes the default warning texture asset. |
| Quaver.Shared/Config/ConfigManager.cs | Adds DisplayEpilepsyWarning bindable persisted in user config. |
| Quaver.Shared/Screens/Options/OptionsMenu.cs | Adds the toggle for the new bindable to the options menu. |
| Quaver.Shared/QuaverGame.cs | Unrelated change to FPS counter font (Lato Black via FontManager). |
Comments suppressed due to low confidence (3)
Quaver.Shared/Screens/Gameplay/UI/EpilepsyWarning.cs:37
- When
mapis null,ShouldDisplayWarningreturnstrue, which will display the epilepsy warning unconditionally. Since the warning is intended to fire only on maps that actually use SVs (per the PR's "Only show on SV maps" requirement), the safe default when the map cannot be inspected should befalse. As written, any code path that ends up constructing the warning beforeScreen.Mapis populated will show the warning on a non-SV map.
if (map == null)
return true;
Quaver.Shared/Screens/Gameplay/UI/EpilepsyWarning.cs:40
map.Tagsis a free-form string, andContains("sv", IgnoreCase)is a substring match on the entire tag blob. This will match any tag (or word in artist/source/etc. embedded in tags) that happens to contain the letters "sv" — e.g. tags like "psv", "tsv", "service", "lsvg" — producing false positives. Consider splitting the tags on the project's standard delimiter (space/comma) and comparing each token with case-insensitive equality to "sv".
var hasSvTag = map.Tags?.Contains("sv", StringComparison.InvariantCultureIgnoreCase) ??
false;
Quaver.Shared/Screens/Gameplay/UI/EpilepsyWarning.cs:70
ShouldDisplayWarning()is evaluated only once in the constructor and stored inVisible. However,Updatecontinues to run the lerp logic on every frame for the entire gameplay session even after the warning has fully faded out (and on every frame, regardless of whether the warning was ever displayed). Consider early-returning whenVisibleis false, and/or destroying/disabling the sprite onceScreen.Timing.Time >= -500andAlphais effectively zero, to avoid pointless per-frame work and an always-rendered fully-transparent fullscreen sprite.
public override void Update(GameTime gameTime)
{
base.Update(gameTime);
var dt = gameTime.ElapsedGameTime.TotalMilliseconds;
// Fade in on map start
if (Screen.Timing.Time < -500)
{
var alpha = MathHelper.Lerp(Alpha, 1, (float)Math.Min(dt / AnimationScale, 1));
Alpha = alpha;
}
else
{
var alpha = MathHelper.Lerp(Alpha, 0, (float)Math.Min(dt / AnimationScale, 1));
Alpha = alpha;
}
}
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| BattleRoyaleWarning = LoadSingleTexture($"{multiplayerFolder}/{battleRoyaleWarning}" | ||
| , $"Quaver.Resources/Textures/Skins/Shared/Multiplayer/{battleRoyaleWarning}.png"); | ||
|
|
||
| var warningFolder = $"{Dir}/Warnings/"; |
There was a problem hiding this comment.
why is folder even in a second variable
| /// </summary> | ||
| internal static Bindable<bool> DisplayFailWarning { get; private set; } | ||
|
|
||
| /// <summary> |
| private void CreateEpilepsyWarning() | ||
| { | ||
| var epilepsyWarning = new EpilepsyWarning(Screen) | ||
| { | ||
| Parent = Playfield.Container, | ||
| Size = new ScalableVector2(0, 0, 1, 1) | ||
| }; | ||
| } |
There was a problem hiding this comment.
EpilepsyWarning should be a class member like everything else no?
| /// <summary> | ||
| /// The scale used for fade animations. | ||
| /// </summary> | ||
| private static float AnimationScale => 120f / AudioEngine.Track.Rate; |
Resolves #4287
Requires a 1920x1080 texture
2026-01-18.21-58-45.mp4
TODO: