// Copyright (c) 2007-2017 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using OpenTK; using OpenTK.Graphics; using OpenTK.Input; using osu.Framework.Allocation; using osu.Framework.Audio; using osu.Framework.Audio.Sample; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Sprites; using osu.Framework.Input; using osu.Game.Graphics.Sprites; using osu.Game.Rulesets.Mods; using osu.Game.Rulesets.UI; using System; using System.Linq; using osu.Framework.Graphics.Cursor; using osu.Game.Graphics.UserInterface; namespace osu.Game.Overlays.Mods { /// /// Represents a clickable button which can cycle through one of more mods. /// public class ModButton : ModButtonEmpty, IHasTooltip { private ModIcon foregroundIcon; private ModIcon backgroundIcon; private readonly SpriteText text; private readonly Container iconsContainer; private SampleChannel sampleOn, sampleOff; /// /// Fired when the selection changes. /// public Action SelectionChanged; public string TooltipText => (SelectedMod?.Description ?? Mods.FirstOrDefault()?.Description) ?? string.Empty; private const Easing mod_switch_easing = Easing.InOutSine; private const double mod_switch_duration = 120; // A selected index of -1 means not selected. private int selectedIndex = -1; /// /// Change the selected mod index of this button. /// /// /// Select the next available mod in a specified direction. /// /// 1 for forwards, -1 for backwards. public void SelectNext(int direction) { int start = selectedIndex + direction; // wrap around if we are at an extremity. if (start >= Mods.Length) start = -1; else if (start < -1) start = Mods.Length - 1; for (int i = start; i < Mods.Length && i >= 0; i += direction) { if (Mods[i].HasImplementation) { changeSelectedIndex(i); return; } } Deselect(); } public void Deselect() => changeSelectedIndex(-1); private void displayMod(Mod mod) { if (backgroundIcon != null) backgroundIcon.Icon = foregroundIcon.Icon; foregroundIcon.Icon = mod.Icon; text.Text = mod.Name; Colour = mod.HasImplementation ? Color4.White : Color4.Gray; } private void createIcons() { iconsContainer.Clear(); if (Mods.Length > 1) { iconsContainer.AddRange(new[] { backgroundIcon = new PassThroughTooltipModIcon(Mods[1]) { Origin = Anchor.BottomRight, Anchor = Anchor.BottomRight, Position = new Vector2(1.5f), }, foregroundIcon = new PassThroughTooltipModIcon(Mods[0]) { Origin = Anchor.BottomRight, Anchor = Anchor.BottomRight, Position = new Vector2(-1.5f), }, }); } else { iconsContainer.Add(foregroundIcon = new PassThroughTooltipModIcon(Mod) { Origin = Anchor.Centre, Anchor = Anchor.Centre, }); } } public ModButton(Mod mod) { Children = new Drawable[] { new Container { Size = new Vector2(77f, 80f), Origin = Anchor.TopCentre, Anchor = Anchor.TopCentre, Children = new Drawable[] { iconsContainer = new Container { RelativeSizeAxes = Axes.Both, Origin = Anchor.Centre, Anchor = Anchor.Centre, } } }, text = new OsuSpriteText { Y = 75, Origin = Anchor.TopCentre, Anchor = Anchor.TopCentre, TextSize = 18, }, new HoverClickSounds() }; Mod = mod; } private class PassThroughTooltipModIcon : ModIcon { public override string TooltipText => null; public PassThroughTooltipModIcon(Mod mod) : base(mod) { } } } }