1
0
mirror of https://github.com/ppy/osu.git synced 2025-01-12 17:43:05 +08:00

Merge branch 'master' into confine-during-gameplay

# Conflicts:
#	osu.Game/Overlays/Settings/Sections/Input/MouseSettings.cs
This commit is contained in:
Shane Woolcock 2020-10-07 11:07:00 +10:30
commit ec12a21088
46 changed files with 686 additions and 417 deletions

View File

@ -29,12 +29,12 @@ namespace osu.Game.Rulesets.Mania
new SettingsEnumDropdown<ManiaScrollingDirection>
{
LabelText = "Scrolling direction",
Bindable = config.GetBindable<ManiaScrollingDirection>(ManiaRulesetSetting.ScrollDirection)
Current = config.GetBindable<ManiaScrollingDirection>(ManiaRulesetSetting.ScrollDirection)
},
new SettingsSlider<double, TimeSlider>
{
LabelText = "Scroll speed",
Bindable = config.GetBindable<double>(ManiaRulesetSetting.ScrollTime),
Current = config.GetBindable<double>(ManiaRulesetSetting.ScrollTime),
KeyboardStep = 5
},
};

View File

@ -19,7 +19,7 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables.Pieces
Origin = Anchor.Centre;
Masking = true;
BorderThickness = 10;
BorderThickness = 9; // roughly matches slider borders and makes stacked circles distinctly visible from each other.
BorderColour = Color4.White;
Child = new Box

View File

@ -49,6 +49,23 @@ namespace osu.Game.Rulesets.Osu.Skinning
{
OsuHitObject osuObject = (OsuHitObject)drawableObject.HitObject;
bool allowFallback = false;
// attempt lookup using priority specification
Texture baseTexture = getTextureWithFallback(string.Empty);
// if the base texture was not found without a fallback, switch on fallback mode and re-perform the lookup.
if (baseTexture == null)
{
allowFallback = true;
baseTexture = getTextureWithFallback(string.Empty);
}
// at this point, any further texture fetches should be correctly using the priority source if the base texture was retrieved using it.
// the flow above handles the case where a sliderendcircle.png is retrieved from the skin, but sliderendcircleoverlay.png doesn't exist.
// expected behaviour in this scenario is not showing the overlay, rather than using hitcircleoverlay.png (potentially from the default/fall-through skin).
Texture overlayTexture = getTextureWithFallback("overlay");
InternalChildren = new Drawable[]
{
circleSprites = new Container<Sprite>
@ -60,13 +77,13 @@ namespace osu.Game.Rulesets.Osu.Skinning
{
hitCircleSprite = new Sprite
{
Texture = getTextureWithFallback(string.Empty),
Texture = baseTexture,
Anchor = Anchor.Centre,
Origin = Anchor.Centre,
},
hitCircleOverlay = new Sprite
{
Texture = getTextureWithFallback("overlay"),
Texture = overlayTexture,
Anchor = Anchor.Centre,
Origin = Anchor.Centre,
}
@ -101,8 +118,13 @@ namespace osu.Game.Rulesets.Osu.Skinning
Texture tex = null;
if (!string.IsNullOrEmpty(priorityLookup))
{
tex = skin.GetTexture($"{priorityLookup}{name}");
if (!allowFallback)
return tex;
}
return tex ?? skin.GetTexture($"hitcircle{name}");
}
}

View File

@ -27,17 +27,17 @@ namespace osu.Game.Rulesets.Osu.UI
new SettingsCheckbox
{
LabelText = "Snaking in sliders",
Bindable = config.GetBindable<bool>(OsuRulesetSetting.SnakingInSliders)
Current = config.GetBindable<bool>(OsuRulesetSetting.SnakingInSliders)
},
new SettingsCheckbox
{
LabelText = "Snaking out sliders",
Bindable = config.GetBindable<bool>(OsuRulesetSetting.SnakingOutSliders)
Current = config.GetBindable<bool>(OsuRulesetSetting.SnakingOutSliders)
},
new SettingsCheckbox
{
LabelText = "Cursor trail",
Bindable = config.GetBindable<bool>(OsuRulesetSetting.ShowCursorTrail)
Current = config.GetBindable<bool>(OsuRulesetSetting.ShowCursorTrail)
},
};
}

View File

@ -69,7 +69,7 @@ namespace osu.Game.Tests.Visual.Editing
using (var zip = ZipArchive.Open(temp))
zip.WriteToDirectory(extractedFolder);
bool success = setup.ChangeAudioTrack(Path.Combine(extractedFolder, "03. Renatus - Soleily 192kbps.mp3"));
bool success = setup.ChildrenOfType<ResourcesSection>().First().ChangeAudioTrack(Path.Combine(extractedFolder, "03. Renatus - Soleily 192kbps.mp3"));
File.Delete(temp);
Directory.Delete(extractedFolder, true);

View File

@ -0,0 +1,46 @@
// 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 NUnit.Framework;
using osu.Framework.Bindables;
using osu.Framework.Graphics;
using osu.Framework.Graphics.Containers;
using osu.Game.Graphics.UserInterfaceV2;
namespace osu.Game.Tests.Visual.UserInterface
{
public class TestSceneLabelledSliderBar : OsuTestScene
{
[TestCase(false)]
[TestCase(true)]
public void TestSliderBar(bool hasDescription) => createSliderBar(hasDescription);
private void createSliderBar(bool hasDescription = false)
{
AddStep("create component", () =>
{
LabelledSliderBar<double> component;
Child = new Container
{
Anchor = Anchor.Centre,
Origin = Anchor.Centre,
Width = 500,
AutoSizeAxes = Axes.Y,
Child = component = new LabelledSliderBar<double>
{
Current = new BindableDouble(5)
{
MinValue = 0,
MaxValue = 10,
Precision = 1,
}
}
};
component.Label = "a sample component";
component.Description = hasDescription ? "this text describes the component" : string.Empty;
});
}
}
}

View File

@ -10,34 +10,34 @@ namespace osu.Game.Tournament.Components
{
public class DateTextBox : SettingsTextBox
{
public new Bindable<DateTimeOffset> Bindable
public new Bindable<DateTimeOffset> Current
{
get => bindable;
get => current;
set
{
bindable = value.GetBoundCopy();
bindable.BindValueChanged(dto =>
base.Bindable.Value = dto.NewValue.ToUniversalTime().ToString("yyyy-MM-ddTHH:mm:ssZ"), true);
current = value.GetBoundCopy();
current.BindValueChanged(dto =>
base.Current.Value = dto.NewValue.ToUniversalTime().ToString("yyyy-MM-ddTHH:mm:ssZ"), true);
}
}
// hold a reference to the provided bindable so we don't have to in every settings section.
private Bindable<DateTimeOffset> bindable = new Bindable<DateTimeOffset>();
private Bindable<DateTimeOffset> current = new Bindable<DateTimeOffset>();
public DateTextBox()
{
base.Bindable = new Bindable<string>();
base.Current = new Bindable<string>();
((OsuTextBox)Control).OnCommit += (sender, newText) =>
{
try
{
bindable.Value = DateTimeOffset.Parse(sender.Text);
current.Value = DateTimeOffset.Parse(sender.Text);
}
catch
{
// reset textbox content to its last valid state on a parse failure.
bindable.TriggerChange();
current.TriggerChange();
}
};
}

View File

@ -63,25 +63,25 @@ namespace osu.Game.Tournament.Screens.Editors
{
LabelText = "Name",
Width = 0.33f,
Bindable = Model.Name
Current = Model.Name
},
new SettingsTextBox
{
LabelText = "Description",
Width = 0.33f,
Bindable = Model.Description
Current = Model.Description
},
new DateTextBox
{
LabelText = "Start Time",
Width = 0.33f,
Bindable = Model.StartDate
Current = Model.StartDate
},
new SettingsSlider<int>
{
LabelText = "Best of",
Width = 0.33f,
Bindable = Model.BestOf
Current = Model.BestOf
},
new SettingsButton
{
@ -186,14 +186,14 @@ namespace osu.Game.Tournament.Screens.Editors
LabelText = "Beatmap ID",
RelativeSizeAxes = Axes.None,
Width = 200,
Bindable = beatmapId,
Current = beatmapId,
},
new SettingsTextBox
{
LabelText = "Mods",
RelativeSizeAxes = Axes.None,
Width = 200,
Bindable = mods,
Current = mods,
},
drawableContainer = new Container
{

View File

@ -74,13 +74,13 @@ namespace osu.Game.Tournament.Screens.Editors
{
LabelText = "Mod",
Width = 0.33f,
Bindable = Model.Mod
Current = Model.Mod
},
new SettingsSlider<int>
{
LabelText = "Seed",
Width = 0.33f,
Bindable = Model.Seed
Current = Model.Seed
},
new SettingsButton
{
@ -187,21 +187,21 @@ namespace osu.Game.Tournament.Screens.Editors
LabelText = "Beatmap ID",
RelativeSizeAxes = Axes.None,
Width = 200,
Bindable = beatmapId,
Current = beatmapId,
},
new SettingsSlider<int>
{
LabelText = "Seed",
RelativeSizeAxes = Axes.None,
Width = 200,
Bindable = beatmap.Seed
Current = beatmap.Seed
},
new SettingsTextBox
{
LabelText = "Score",
RelativeSizeAxes = Axes.None,
Width = 200,
Bindable = score,
Current = score,
},
drawableContainer = new Container
{

View File

@ -102,31 +102,31 @@ namespace osu.Game.Tournament.Screens.Editors
{
LabelText = "Name",
Width = 0.2f,
Bindable = Model.FullName
Current = Model.FullName
},
new SettingsTextBox
{
LabelText = "Acronym",
Width = 0.2f,
Bindable = Model.Acronym
Current = Model.Acronym
},
new SettingsTextBox
{
LabelText = "Flag",
Width = 0.2f,
Bindable = Model.FlagName
Current = Model.FlagName
},
new SettingsTextBox
{
LabelText = "Seed",
Width = 0.2f,
Bindable = Model.Seed
Current = Model.Seed
},
new SettingsSlider<int>
{
LabelText = "Last Year Placement",
Width = 0.33f,
Bindable = Model.LastYearPlacing
Current = Model.LastYearPlacing
},
new SettingsButton
{
@ -247,7 +247,7 @@ namespace osu.Game.Tournament.Screens.Editors
LabelText = "User ID",
RelativeSizeAxes = Axes.None,
Width = 200,
Bindable = userId,
Current = userId,
},
drawableContainer = new Container
{

View File

@ -113,13 +113,13 @@ namespace osu.Game.Tournament.Screens.Gameplay
new SettingsSlider<int>
{
LabelText = "Chroma width",
Bindable = LadderInfo.ChromaKeyWidth,
Current = LadderInfo.ChromaKeyWidth,
KeyboardStep = 1,
},
new SettingsSlider<int>
{
LabelText = "Players per team",
Bindable = LadderInfo.PlayersPerTeam,
Current = LadderInfo.PlayersPerTeam,
KeyboardStep = 1,
}
}

View File

@ -51,15 +51,15 @@ namespace osu.Game.Tournament.Screens.Ladder.Components
editorInfo.Selected.ValueChanged += selection =>
{
roundDropdown.Bindable = selection.NewValue?.Round;
roundDropdown.Current = selection.NewValue?.Round;
losersCheckbox.Current = selection.NewValue?.Losers;
dateTimeBox.Bindable = selection.NewValue?.Date;
dateTimeBox.Current = selection.NewValue?.Date;
team1Dropdown.Bindable = selection.NewValue?.Team1;
team2Dropdown.Bindable = selection.NewValue?.Team2;
team1Dropdown.Current = selection.NewValue?.Team1;
team2Dropdown.Current = selection.NewValue?.Team2;
};
roundDropdown.Bindable.ValueChanged += round =>
roundDropdown.Current.ValueChanged += round =>
{
if (editorInfo.Selected.Value?.Date.Value < round.NewValue?.StartDate.Value)
{
@ -88,7 +88,7 @@ namespace osu.Game.Tournament.Screens.Ladder.Components
{
public SettingsRoundDropdown(BindableList<TournamentRound> rounds)
{
Bindable = new Bindable<TournamentRound>();
Current = new Bindable<TournamentRound>();
foreach (var r in rounds.Prepend(new TournamentRound()))
add(r);

View File

@ -61,7 +61,7 @@ namespace osu.Game.Tournament.Screens.TeamIntro
new SettingsTeamDropdown(LadderInfo.Teams)
{
LabelText = "Show specific team",
Bindable = currentTeam,
Current = currentTeam,
}
}
}

View File

@ -57,7 +57,7 @@ namespace osu.Game.Configuration
yield return new SettingsSlider<float>
{
LabelText = attr.Label,
Bindable = bNumber,
Current = bNumber,
KeyboardStep = 0.1f,
};
@ -67,7 +67,7 @@ namespace osu.Game.Configuration
yield return new SettingsSlider<double>
{
LabelText = attr.Label,
Bindable = bNumber,
Current = bNumber,
KeyboardStep = 0.1f,
};
@ -77,7 +77,7 @@ namespace osu.Game.Configuration
yield return new SettingsSlider<int>
{
LabelText = attr.Label,
Bindable = bNumber
Current = bNumber
};
break;
@ -86,7 +86,7 @@ namespace osu.Game.Configuration
yield return new SettingsCheckbox
{
LabelText = attr.Label,
Bindable = bBool
Current = bBool
};
break;
@ -95,7 +95,7 @@ namespace osu.Game.Configuration
yield return new SettingsTextBox
{
LabelText = attr.Label,
Bindable = bString
Current = bString
};
break;
@ -105,7 +105,7 @@ namespace osu.Game.Configuration
var dropdown = (Drawable)Activator.CreateInstance(dropdownType);
dropdownType.GetProperty(nameof(SettingsDropdown<object>.LabelText))?.SetValue(dropdown, attr.Label);
dropdownType.GetProperty(nameof(SettingsDropdown<object>.Bindable))?.SetValue(dropdown, bindable);
dropdownType.GetProperty(nameof(SettingsDropdown<object>.Current))?.SetValue(dropdown, bindable);
yield return dropdown;

View File

@ -0,0 +1,24 @@
// 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 osu.Framework.Graphics;
using osu.Game.Overlays.Settings;
namespace osu.Game.Graphics.UserInterfaceV2
{
public class LabelledSliderBar<TNumber> : LabelledComponent<SettingsSlider<TNumber>, TNumber>
where TNumber : struct, IEquatable<TNumber>, IComparable<TNumber>, IConvertible
{
public LabelledSliderBar()
: base(true)
{
}
protected override SettingsSlider<TNumber> CreateComponent() => new SettingsSlider<TNumber>
{
TransferValueOnCommit = true,
RelativeSizeAxes = Axes.X,
};
}
}

View File

@ -64,7 +64,7 @@ namespace osu.Game.Overlays.Settings.Sections.Audio
updateItems();
dropdown.Bindable = audio.AudioDevice;
dropdown.Current = audio.AudioDevice;
audio.OnNewDevice += onDeviceChanged;
audio.OnLostDevice += onDeviceChanged;

View File

@ -21,23 +21,23 @@ namespace osu.Game.Overlays.Settings.Sections.Audio
new SettingsCheckbox
{
LabelText = "Interface voices",
Bindable = config.GetBindable<bool>(OsuSetting.MenuVoice)
Current = config.GetBindable<bool>(OsuSetting.MenuVoice)
},
new SettingsCheckbox
{
LabelText = "osu! music theme",
Bindable = config.GetBindable<bool>(OsuSetting.MenuMusic)
Current = config.GetBindable<bool>(OsuSetting.MenuMusic)
},
new SettingsDropdown<IntroSequence>
{
LabelText = "Intro sequence",
Bindable = config.GetBindable<IntroSequence>(OsuSetting.IntroSequence),
Current = config.GetBindable<IntroSequence>(OsuSetting.IntroSequence),
Items = Enum.GetValues(typeof(IntroSequence)).Cast<IntroSequence>()
},
new SettingsDropdown<BackgroundSource>
{
LabelText = "Background source",
Bindable = config.GetBindable<BackgroundSource>(OsuSetting.MenuBackgroundSource),
Current = config.GetBindable<BackgroundSource>(OsuSetting.MenuBackgroundSource),
Items = Enum.GetValues(typeof(BackgroundSource)).Cast<BackgroundSource>()
}
};

View File

@ -20,7 +20,7 @@ namespace osu.Game.Overlays.Settings.Sections.Audio
new SettingsSlider<double, OffsetSlider>
{
LabelText = "Audio offset",
Bindable = config.GetBindable<double>(OsuSetting.AudioOffset),
Current = config.GetBindable<double>(OsuSetting.AudioOffset),
KeyboardStep = 1f
},
new SettingsButton

View File

@ -20,28 +20,28 @@ namespace osu.Game.Overlays.Settings.Sections.Audio
new SettingsSlider<double>
{
LabelText = "Master",
Bindable = audio.Volume,
Current = audio.Volume,
KeyboardStep = 0.01f,
DisplayAsPercentage = true
},
new SettingsSlider<double>
{
LabelText = "Master (window inactive)",
Bindable = config.GetBindable<double>(OsuSetting.VolumeInactive),
Current = config.GetBindable<double>(OsuSetting.VolumeInactive),
KeyboardStep = 0.01f,
DisplayAsPercentage = true
},
new SettingsSlider<double>
{
LabelText = "Effect",
Bindable = audio.VolumeSample,
Current = audio.VolumeSample,
KeyboardStep = 0.01f,
DisplayAsPercentage = true
},
new SettingsSlider<double>
{
LabelText = "Music",
Bindable = audio.VolumeTrack,
Current = audio.VolumeTrack,
KeyboardStep = 0.01f,
DisplayAsPercentage = true
},

View File

@ -19,12 +19,12 @@ namespace osu.Game.Overlays.Settings.Sections.Debug
new SettingsCheckbox
{
LabelText = "Show log overlay",
Bindable = frameworkConfig.GetBindable<bool>(FrameworkSetting.ShowLogOverlay)
Current = frameworkConfig.GetBindable<bool>(FrameworkSetting.ShowLogOverlay)
},
new SettingsCheckbox
{
LabelText = "Bypass front-to-back render pass",
Bindable = config.GetBindable<bool>(DebugSetting.BypassFrontToBackPass)
Current = config.GetBindable<bool>(DebugSetting.BypassFrontToBackPass)
}
};
}

View File

@ -21,62 +21,62 @@ namespace osu.Game.Overlays.Settings.Sections.Gameplay
new SettingsSlider<double>
{
LabelText = "Background dim",
Bindable = config.GetBindable<double>(OsuSetting.DimLevel),
Current = config.GetBindable<double>(OsuSetting.DimLevel),
KeyboardStep = 0.01f,
DisplayAsPercentage = true
},
new SettingsSlider<double>
{
LabelText = "Background blur",
Bindable = config.GetBindable<double>(OsuSetting.BlurLevel),
Current = config.GetBindable<double>(OsuSetting.BlurLevel),
KeyboardStep = 0.01f,
DisplayAsPercentage = true
},
new SettingsCheckbox
{
LabelText = "Lighten playfield during breaks",
Bindable = config.GetBindable<bool>(OsuSetting.LightenDuringBreaks)
Current = config.GetBindable<bool>(OsuSetting.LightenDuringBreaks)
},
new SettingsCheckbox
{
LabelText = "Show score overlay",
Bindable = config.GetBindable<bool>(OsuSetting.ShowInterface)
Current = config.GetBindable<bool>(OsuSetting.ShowInterface)
},
new SettingsCheckbox
{
LabelText = "Show difficulty graph on progress bar",
Bindable = config.GetBindable<bool>(OsuSetting.ShowProgressGraph)
Current = config.GetBindable<bool>(OsuSetting.ShowProgressGraph)
},
new SettingsCheckbox
{
LabelText = "Show health display even when you can't fail",
Bindable = config.GetBindable<bool>(OsuSetting.ShowHealthDisplayWhenCantFail),
Current = config.GetBindable<bool>(OsuSetting.ShowHealthDisplayWhenCantFail),
Keywords = new[] { "hp", "bar" }
},
new SettingsCheckbox
{
LabelText = "Fade playfield to red when health is low",
Bindable = config.GetBindable<bool>(OsuSetting.FadePlayfieldWhenHealthLow),
Current = config.GetBindable<bool>(OsuSetting.FadePlayfieldWhenHealthLow),
},
new SettingsCheckbox
{
LabelText = "Always show key overlay",
Bindable = config.GetBindable<bool>(OsuSetting.KeyOverlay)
Current = config.GetBindable<bool>(OsuSetting.KeyOverlay)
},
new SettingsCheckbox
{
LabelText = "Positional hitsounds",
Bindable = config.GetBindable<bool>(OsuSetting.PositionalHitSounds)
Current = config.GetBindable<bool>(OsuSetting.PositionalHitSounds)
},
new SettingsEnumDropdown<ScoreMeterType>
{
LabelText = "Score meter type",
Bindable = config.GetBindable<ScoreMeterType>(OsuSetting.ScoreMeter)
Current = config.GetBindable<ScoreMeterType>(OsuSetting.ScoreMeter)
},
new SettingsEnumDropdown<ScoringMode>
{
LabelText = "Score display mode",
Bindable = config.GetBindable<ScoringMode>(OsuSetting.ScoreDisplayMode)
Current = config.GetBindable<ScoringMode>(OsuSetting.ScoreDisplayMode)
}
};
@ -85,7 +85,7 @@ namespace osu.Game.Overlays.Settings.Sections.Gameplay
Add(new SettingsCheckbox
{
LabelText = "Disable Windows key during gameplay",
Bindable = config.GetBindable<bool>(OsuSetting.GameplayDisableWinKey)
Current = config.GetBindable<bool>(OsuSetting.GameplayDisableWinKey)
});
}
}

View File

@ -22,7 +22,7 @@ namespace osu.Game.Overlays.Settings.Sections.Gameplay
new SettingsCheckbox
{
LabelText = "Increase visibility of first object when visual impairment mods are enabled",
Bindable = config.GetBindable<bool>(OsuSetting.IncreaseFirstObjectVisibility),
Current = config.GetBindable<bool>(OsuSetting.IncreaseFirstObjectVisibility),
},
};
}

View File

@ -31,31 +31,31 @@ namespace osu.Game.Overlays.Settings.Sections.Gameplay
new SettingsCheckbox
{
LabelText = "Right mouse drag to absolute scroll",
Bindable = config.GetBindable<bool>(OsuSetting.SongSelectRightMouseScroll),
Current = config.GetBindable<bool>(OsuSetting.SongSelectRightMouseScroll),
},
new SettingsCheckbox
{
LabelText = "Show converted beatmaps",
Bindable = config.GetBindable<bool>(OsuSetting.ShowConvertedBeatmaps),
Current = config.GetBindable<bool>(OsuSetting.ShowConvertedBeatmaps),
},
new SettingsSlider<double, StarsSlider>
{
LabelText = "Display beatmaps from",
Bindable = config.GetBindable<double>(OsuSetting.DisplayStarsMinimum),
Current = config.GetBindable<double>(OsuSetting.DisplayStarsMinimum),
KeyboardStep = 0.1f,
Keywords = new[] { "minimum", "maximum", "star", "difficulty" }
},
new SettingsSlider<double, MaximumStarsSlider>
{
LabelText = "up to",
Bindable = config.GetBindable<double>(OsuSetting.DisplayStarsMaximum),
Current = config.GetBindable<double>(OsuSetting.DisplayStarsMaximum),
KeyboardStep = 0.1f,
Keywords = new[] { "minimum", "maximum", "star", "difficulty" }
},
new SettingsEnumDropdown<RandomSelectAlgorithm>
{
LabelText = "Random selection algorithm",
Bindable = config.GetBindable<RandomSelectAlgorithm>(OsuSetting.RandomSelectAlgorithm),
Current = config.GetBindable<RandomSelectAlgorithm>(OsuSetting.RandomSelectAlgorithm),
}
};
}

View File

@ -19,7 +19,7 @@ namespace osu.Game.Overlays.Settings.Sections.General
new SettingsCheckbox
{
LabelText = "Prefer metadata in original language",
Bindable = frameworkConfig.GetBindable<bool>(FrameworkSetting.ShowUnicode)
Current = frameworkConfig.GetBindable<bool>(FrameworkSetting.ShowUnicode)
},
};
}

View File

@ -240,12 +240,12 @@ namespace osu.Game.Overlays.Settings.Sections.General
new SettingsCheckbox
{
LabelText = "Remember username",
Bindable = config.GetBindable<bool>(OsuSetting.SaveUsername),
Current = config.GetBindable<bool>(OsuSetting.SaveUsername),
},
new SettingsCheckbox
{
LabelText = "Stay signed in",
Bindable = config.GetBindable<bool>(OsuSetting.SavePassword),
Current = config.GetBindable<bool>(OsuSetting.SavePassword),
},
new Container
{

View File

@ -27,7 +27,7 @@ namespace osu.Game.Overlays.Settings.Sections.General
Add(new SettingsEnumDropdown<ReleaseStream>
{
LabelText = "Release stream",
Bindable = config.GetBindable<ReleaseStream>(OsuSetting.ReleaseStream),
Current = config.GetBindable<ReleaseStream>(OsuSetting.ReleaseStream),
});
if (updateManager?.CanCheckForUpdate == true)

View File

@ -19,22 +19,22 @@ namespace osu.Game.Overlays.Settings.Sections.Graphics
new SettingsCheckbox
{
LabelText = "Storyboard / Video",
Bindable = config.GetBindable<bool>(OsuSetting.ShowStoryboard)
Current = config.GetBindable<bool>(OsuSetting.ShowStoryboard)
},
new SettingsCheckbox
{
LabelText = "Hit Lighting",
Bindable = config.GetBindable<bool>(OsuSetting.HitLighting)
Current = config.GetBindable<bool>(OsuSetting.HitLighting)
},
new SettingsEnumDropdown<ScreenshotFormat>
{
LabelText = "Screenshot format",
Bindable = config.GetBindable<ScreenshotFormat>(OsuSetting.ScreenshotFormat)
Current = config.GetBindable<ScreenshotFormat>(OsuSetting.ScreenshotFormat)
},
new SettingsCheckbox
{
LabelText = "Show menu cursor in screenshots",
Bindable = config.GetBindable<bool>(OsuSetting.ScreenshotCaptureMenuCursor)
Current = config.GetBindable<bool>(OsuSetting.ScreenshotCaptureMenuCursor)
}
};
}

View File

@ -62,7 +62,7 @@ namespace osu.Game.Overlays.Settings.Sections.Graphics
windowModeDropdown = new SettingsDropdown<WindowMode>
{
LabelText = "Screen mode",
Bindable = config.GetBindable<WindowMode>(FrameworkSetting.WindowMode),
Current = config.GetBindable<WindowMode>(FrameworkSetting.WindowMode),
ItemSource = windowModes,
},
resolutionSettingsContainer = new Container
@ -74,14 +74,14 @@ namespace osu.Game.Overlays.Settings.Sections.Graphics
{
LabelText = "UI Scaling",
TransferValueOnCommit = true,
Bindable = osuConfig.GetBindable<float>(OsuSetting.UIScale),
Current = osuConfig.GetBindable<float>(OsuSetting.UIScale),
KeyboardStep = 0.01f,
Keywords = new[] { "scale", "letterbox" },
},
new SettingsEnumDropdown<ScalingMode>
{
LabelText = "Screen Scaling",
Bindable = osuConfig.GetBindable<ScalingMode>(OsuSetting.Scaling),
Current = osuConfig.GetBindable<ScalingMode>(OsuSetting.Scaling),
Keywords = new[] { "scale", "letterbox" },
},
scalingSettings = new FillFlowContainer<SettingsSlider<float>>
@ -97,28 +97,28 @@ namespace osu.Game.Overlays.Settings.Sections.Graphics
new SettingsSlider<float>
{
LabelText = "Horizontal position",
Bindable = scalingPositionX,
Current = scalingPositionX,
KeyboardStep = 0.01f,
DisplayAsPercentage = true
},
new SettingsSlider<float>
{
LabelText = "Vertical position",
Bindable = scalingPositionY,
Current = scalingPositionY,
KeyboardStep = 0.01f,
DisplayAsPercentage = true
},
new SettingsSlider<float>
{
LabelText = "Horizontal scale",
Bindable = scalingSizeX,
Current = scalingSizeX,
KeyboardStep = 0.01f,
DisplayAsPercentage = true
},
new SettingsSlider<float>
{
LabelText = "Vertical scale",
Bindable = scalingSizeY,
Current = scalingSizeY,
KeyboardStep = 0.01f,
DisplayAsPercentage = true
},
@ -126,7 +126,7 @@ namespace osu.Game.Overlays.Settings.Sections.Graphics
},
};
scalingSettings.ForEach(s => bindPreviewEvent(s.Bindable));
scalingSettings.ForEach(s => bindPreviewEvent(s.Current));
var resolutions = getResolutions();
@ -137,10 +137,10 @@ namespace osu.Game.Overlays.Settings.Sections.Graphics
LabelText = "Resolution",
ShowsDefaultIndicator = false,
Items = resolutions,
Bindable = sizeFullscreen
Current = sizeFullscreen
};
windowModeDropdown.Bindable.BindValueChanged(mode =>
windowModeDropdown.Current.BindValueChanged(mode =>
{
if (mode.NewValue == WindowMode.Fullscreen)
{

View File

@ -23,17 +23,17 @@ namespace osu.Game.Overlays.Settings.Sections.Graphics
new SettingsEnumDropdown<FrameSync>
{
LabelText = "Frame limiter",
Bindable = config.GetBindable<FrameSync>(FrameworkSetting.FrameSync)
Current = config.GetBindable<FrameSync>(FrameworkSetting.FrameSync)
},
new SettingsEnumDropdown<ExecutionMode>
{
LabelText = "Threading mode",
Bindable = config.GetBindable<ExecutionMode>(FrameworkSetting.ExecutionMode)
Current = config.GetBindable<ExecutionMode>(FrameworkSetting.ExecutionMode)
},
new SettingsCheckbox
{
LabelText = "Show FPS",
Bindable = osuConfig.GetBindable<bool>(OsuSetting.ShowFpsDisplay)
Current = osuConfig.GetBindable<bool>(OsuSetting.ShowFpsDisplay)
},
};
}

View File

@ -20,17 +20,17 @@ namespace osu.Game.Overlays.Settings.Sections.Graphics
new SettingsCheckbox
{
LabelText = "Rotate cursor when dragging",
Bindable = config.GetBindable<bool>(OsuSetting.CursorRotation)
Current = config.GetBindable<bool>(OsuSetting.CursorRotation)
},
new SettingsCheckbox
{
LabelText = "Parallax",
Bindable = config.GetBindable<bool>(OsuSetting.MenuParallax)
Current = config.GetBindable<bool>(OsuSetting.MenuParallax)
},
new SettingsSlider<float, TimeSlider>
{
LabelText = "Hold-to-confirm activation time",
Bindable = config.GetBindable<float>(OsuSetting.UIHoldActivationDelay),
Current = config.GetBindable<float>(OsuSetting.UIHoldActivationDelay),
KeyboardStep = 50
},
};

View File

@ -35,32 +35,32 @@ namespace osu.Game.Overlays.Settings.Sections.Input
new SettingsCheckbox
{
LabelText = "Raw input",
Bindable = rawInputToggle
Current = rawInputToggle
},
new SensitivitySetting
{
LabelText = "Cursor sensitivity",
Bindable = sensitivityBindable
Current = sensitivityBindable
},
new SettingsCheckbox
{
LabelText = "Map absolute input to window",
Bindable = config.GetBindable<bool>(FrameworkSetting.MapAbsoluteInputToWindow)
Current = config.GetBindable<bool>(FrameworkSetting.MapAbsoluteInputToWindow)
},
new SettingsEnumDropdown<OsuConfineMouseMode>
{
LabelText = "Confine mouse cursor to window",
Bindable = osuConfig.GetBindable<OsuConfineMouseMode>(OsuSetting.ConfineMouseMode)
Current = osuConfig.GetBindable<OsuConfineMouseMode>(OsuSetting.ConfineMouseMode)
},
new SettingsCheckbox
{
LabelText = "Disable mouse wheel during gameplay",
Bindable = osuConfig.GetBindable<bool>(OsuSetting.MouseDisableWheel)
Current = osuConfig.GetBindable<bool>(OsuSetting.MouseDisableWheel)
},
new SettingsCheckbox
{
LabelText = "Disable mouse buttons during gameplay",
Bindable = osuConfig.GetBindable<bool>(OsuSetting.MouseDisableButtons)
Current = osuConfig.GetBindable<bool>(OsuSetting.MouseDisableButtons)
},
};

View File

@ -19,13 +19,13 @@ namespace osu.Game.Overlays.Settings.Sections.Online
new SettingsCheckbox
{
LabelText = "Warn about opening external links",
Bindable = config.GetBindable<bool>(OsuSetting.ExternalLinkWarning)
Current = config.GetBindable<bool>(OsuSetting.ExternalLinkWarning)
},
new SettingsCheckbox
{
LabelText = "Prefer downloads without video",
Keywords = new[] { "no-video" },
Bindable = config.GetBindable<bool>(OsuSetting.PreferNoVideo)
Current = config.GetBindable<bool>(OsuSetting.PreferNoVideo)
},
};
}

View File

@ -47,29 +47,29 @@ namespace osu.Game.Overlays.Settings.Sections
new SettingsSlider<float, SizeSlider>
{
LabelText = "Menu cursor size",
Bindable = config.GetBindable<float>(OsuSetting.MenuCursorSize),
Current = config.GetBindable<float>(OsuSetting.MenuCursorSize),
KeyboardStep = 0.01f
},
new SettingsSlider<float, SizeSlider>
{
LabelText = "Gameplay cursor size",
Bindable = config.GetBindable<float>(OsuSetting.GameplayCursorSize),
Current = config.GetBindable<float>(OsuSetting.GameplayCursorSize),
KeyboardStep = 0.01f
},
new SettingsCheckbox
{
LabelText = "Adjust gameplay cursor size based on current beatmap",
Bindable = config.GetBindable<bool>(OsuSetting.AutoCursorSize)
Current = config.GetBindable<bool>(OsuSetting.AutoCursorSize)
},
new SettingsCheckbox
{
LabelText = "Beatmap skins",
Bindable = config.GetBindable<bool>(OsuSetting.BeatmapSkins)
Current = config.GetBindable<bool>(OsuSetting.BeatmapSkins)
},
new SettingsCheckbox
{
LabelText = "Beatmap hitsounds",
Bindable = config.GetBindable<bool>(OsuSetting.BeatmapHitsounds)
Current = config.GetBindable<bool>(OsuSetting.BeatmapHitsounds)
},
};
@ -81,7 +81,7 @@ namespace osu.Game.Overlays.Settings.Sections
config.BindWith(OsuSetting.Skin, configBindable);
skinDropdown.Bindable = dropdownBindable;
skinDropdown.Current = dropdownBindable;
skinDropdown.Items = skins.GetAllUsableSkins().ToArray();
// Todo: This should not be necessary when OsuConfigManager is databased

View File

@ -21,7 +21,7 @@ using osuTK;
namespace osu.Game.Overlays.Settings
{
public abstract class SettingsItem<T> : Container, IFilterable, ISettingsItem
public abstract class SettingsItem<T> : Container, IFilterable, ISettingsItem, IHasCurrentValue<T>
{
protected abstract Drawable CreateControl();
@ -54,7 +54,14 @@ namespace osu.Game.Overlays.Settings
}
}
public virtual Bindable<T> Bindable
[Obsolete("Use Current instead")] // Can be removed 20210406
public Bindable<T> Bindable
{
get => Current;
set => Current = value;
}
public virtual Bindable<T> Current
{
get => controlWithCurrent.Current;
set => controlWithCurrent.Current = value;

View File

@ -199,7 +199,40 @@ namespace osu.Game.Screens.Edit.Compose.Components.Timeline
base.Update();
// no bindable so we perform this every update
Width = (float)(HitObject.GetEndTime() - HitObject.StartTime);
float duration = (float)(HitObject.GetEndTime() - HitObject.StartTime);
if (Width != duration)
{
Width = duration;
// kind of haphazard but yeah, no bindables.
if (HitObject is IHasRepeats repeats)
updateRepeats(repeats);
}
}
private Container repeatsContainer;
private void updateRepeats(IHasRepeats repeats)
{
repeatsContainer?.Expire();
mainComponents.Add(repeatsContainer = new Container
{
RelativeSizeAxes = Axes.Both,
});
for (int i = 0; i < repeats.RepeatCount; i++)
{
repeatsContainer.Add(new Circle
{
Size = new Vector2(circle_size / 2),
Anchor = Anchor.CentreLeft,
Origin = Anchor.Centre,
RelativePositionAxes = Axes.X,
X = (float)(i + 1) / (repeats.RepeatCount + 1),
});
}
}
protected override bool ShouldBeConsideredForInput(Drawable child) => true;

View File

@ -589,7 +589,7 @@ namespace osu.Game.Screens.Edit
private void seek(UIEvent e, int direction)
{
double amount = e.ShiftPressed ? 2 : 1;
double amount = e.ShiftPressed ? 4 : 1;
if (direction < 1)
clock.SeekBackward(!clock.IsRunning, amount);

View File

@ -86,7 +86,7 @@ namespace osu.Game.Screens.Edit
/// </summary>
/// <param name="snapped">Whether to snap to the closest beat after seeking.</param>
/// <param name="amount">The relative amount (magnitude) which should be seeked.</param>
public void SeekBackward(bool snapped = false, double amount = 1) => seek(-1, snapped, amount);
public void SeekBackward(bool snapped = false, double amount = 1) => seek(-1, snapped, amount + (IsRunning ? 1.5 : 0));
/// <summary>
/// Seeks forwards by one beat length.

View File

@ -0,0 +1,73 @@
// 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.IO;
using osu.Framework.Bindables;
using osu.Framework.Graphics;
using osu.Framework.Graphics.Containers;
using osu.Framework.Input.Events;
using osu.Game.Graphics.UserInterface;
using osu.Game.Graphics.UserInterfaceV2;
namespace osu.Game.Screens.Edit.Setup
{
/// <summary>
/// A labelled textbox which reveals an inline file chooser when clicked.
/// </summary>
internal class FileChooserLabelledTextBox : LabelledTextBox
{
public Container Target;
private readonly IBindable<FileInfo> currentFile = new Bindable<FileInfo>();
public FileChooserLabelledTextBox()
{
currentFile.BindValueChanged(onFileSelected);
}
private void onFileSelected(ValueChangedEvent<FileInfo> file)
{
if (file.NewValue == null)
return;
Target.Clear();
Current.Value = file.NewValue.FullName;
}
protected override OsuTextBox CreateTextBox() =>
new FileChooserOsuTextBox
{
Anchor = Anchor.Centre,
Origin = Anchor.Centre,
RelativeSizeAxes = Axes.X,
CornerRadius = CORNER_RADIUS,
OnFocused = DisplayFileChooser
};
public void DisplayFileChooser()
{
Target.Child = new FileSelector(validFileExtensions: ResourcesSection.AudioExtensions)
{
RelativeSizeAxes = Axes.X,
Height = 400,
Anchor = Anchor.Centre,
Origin = Anchor.Centre,
CurrentFile = { BindTarget = currentFile }
};
}
internal class FileChooserOsuTextBox : OsuTextBox
{
public Action OnFocused;
protected override void OnFocus(FocusEvent e)
{
OnFocused?.Invoke();
base.OnFocus(e);
GetContainingInputManager().TriggerFocusContention(this);
}
}
}
}

View File

@ -0,0 +1,71 @@
// 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.Linq;
using osu.Framework.Allocation;
using osu.Framework.Graphics;
using osu.Framework.Graphics.UserInterface;
using osu.Game.Graphics.Sprites;
using osu.Game.Graphics.UserInterfaceV2;
namespace osu.Game.Screens.Edit.Setup
{
internal class MetadataSection : SetupSection
{
private LabelledTextBox artistTextBox;
private LabelledTextBox titleTextBox;
private LabelledTextBox creatorTextBox;
private LabelledTextBox difficultyTextBox;
[BackgroundDependencyLoader]
private void load()
{
Children = new Drawable[]
{
new OsuSpriteText
{
Text = "Beatmap metadata"
},
artistTextBox = new LabelledTextBox
{
Label = "Artist",
Current = { Value = Beatmap.Value.Metadata.Artist },
TabbableContentContainer = this
},
titleTextBox = new LabelledTextBox
{
Label = "Title",
Current = { Value = Beatmap.Value.Metadata.Title },
TabbableContentContainer = this
},
creatorTextBox = new LabelledTextBox
{
Label = "Creator",
Current = { Value = Beatmap.Value.Metadata.AuthorString },
TabbableContentContainer = this
},
difficultyTextBox = new LabelledTextBox
{
Label = "Difficulty Name",
Current = { Value = Beatmap.Value.BeatmapInfo.Version },
TabbableContentContainer = this
},
};
foreach (var item in Children.OfType<LabelledTextBox>())
item.OnCommit += onCommit;
}
private void onCommit(TextBox sender, bool newText)
{
if (!newText) return;
// for now, update these on commit rather than making BeatmapMetadata bindables.
// after switching database engines we can reconsider if switching to bindables is a good direction.
Beatmap.Value.Metadata.Artist = artistTextBox.Current.Value;
Beatmap.Value.Metadata.Title = titleTextBox.Current.Value;
Beatmap.Value.Metadata.AuthorString = creatorTextBox.Current.Value;
Beatmap.Value.BeatmapInfo.Version = difficultyTextBox.Current.Value;
}
}
}

View File

@ -0,0 +1,211 @@
// 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.Collections.Generic;
using System.IO;
using System.Linq;
using System.Threading.Tasks;
using osu.Framework.Allocation;
using osu.Framework.Bindables;
using osu.Framework.Graphics;
using osu.Framework.Graphics.Containers;
using osu.Framework.Graphics.Shapes;
using osu.Game.Beatmaps;
using osu.Game.Beatmaps.Drawables;
using osu.Game.Database;
using osu.Game.Graphics;
using osu.Game.Graphics.Containers;
using osu.Game.Graphics.Sprites;
using osu.Game.Graphics.UserInterfaceV2;
using osu.Game.Overlays;
namespace osu.Game.Screens.Edit.Setup
{
internal class ResourcesSection : SetupSection, ICanAcceptFiles
{
private LabelledTextBox audioTrackTextBox;
private Container backgroundSpriteContainer;
public IEnumerable<string> HandledExtensions => ImageExtensions.Concat(AudioExtensions);
public static string[] ImageExtensions { get; } = { ".jpg", ".jpeg", ".png" };
public static string[] AudioExtensions { get; } = { ".mp3", ".ogg" };
[Resolved]
private OsuGameBase game { get; set; }
[Resolved]
private MusicController music { get; set; }
[Resolved]
private BeatmapManager beatmaps { get; set; }
[Resolved(canBeNull: true)]
private Editor editor { get; set; }
[BackgroundDependencyLoader]
private void load()
{
Container audioTrackFileChooserContainer = new Container
{
RelativeSizeAxes = Axes.X,
AutoSizeAxes = Axes.Y,
};
Children = new Drawable[]
{
backgroundSpriteContainer = new Container
{
RelativeSizeAxes = Axes.X,
Height = 250,
Masking = true,
CornerRadius = 10,
},
new OsuSpriteText
{
Text = "Resources"
},
audioTrackTextBox = new FileChooserLabelledTextBox
{
Label = "Audio Track",
Current = { Value = Beatmap.Value.Metadata.AudioFile ?? "Click to select a track" },
Target = audioTrackFileChooserContainer,
TabbableContentContainer = this
},
audioTrackFileChooserContainer,
};
updateBackgroundSprite();
audioTrackTextBox.Current.BindValueChanged(audioTrackChanged);
}
Task ICanAcceptFiles.Import(params string[] paths)
{
Schedule(() =>
{
var firstFile = new FileInfo(paths.First());
if (ImageExtensions.Contains(firstFile.Extension))
{
ChangeBackgroundImage(firstFile.FullName);
}
else if (AudioExtensions.Contains(firstFile.Extension))
{
audioTrackTextBox.Text = firstFile.FullName;
}
});
return Task.CompletedTask;
}
protected override void LoadComplete()
{
base.LoadComplete();
game.RegisterImportHandler(this);
}
public bool ChangeBackgroundImage(string path)
{
var info = new FileInfo(path);
if (!info.Exists)
return false;
var set = Beatmap.Value.BeatmapSetInfo;
// remove the previous background for now.
// in the future we probably want to check if this is being used elsewhere (other difficulties?)
var oldFile = set.Files.FirstOrDefault(f => f.Filename == Beatmap.Value.Metadata.BackgroundFile);
using (var stream = info.OpenRead())
{
if (oldFile != null)
beatmaps.ReplaceFile(set, oldFile, stream, info.Name);
else
beatmaps.AddFile(set, stream, info.Name);
}
Beatmap.Value.Metadata.BackgroundFile = info.Name;
updateBackgroundSprite();
return true;
}
protected override void Dispose(bool isDisposing)
{
base.Dispose(isDisposing);
game?.UnregisterImportHandler(this);
}
public bool ChangeAudioTrack(string path)
{
var info = new FileInfo(path);
if (!info.Exists)
return false;
var set = Beatmap.Value.BeatmapSetInfo;
// remove the previous audio track for now.
// in the future we probably want to check if this is being used elsewhere (other difficulties?)
var oldFile = set.Files.FirstOrDefault(f => f.Filename == Beatmap.Value.Metadata.AudioFile);
using (var stream = info.OpenRead())
{
if (oldFile != null)
beatmaps.ReplaceFile(set, oldFile, stream, info.Name);
else
beatmaps.AddFile(set, stream, info.Name);
}
Beatmap.Value.Metadata.AudioFile = info.Name;
music.ReloadCurrentTrack();
editor?.UpdateClockSource();
return true;
}
private void audioTrackChanged(ValueChangedEvent<string> filePath)
{
if (!ChangeAudioTrack(filePath.NewValue))
audioTrackTextBox.Current.Value = filePath.OldValue;
}
private void updateBackgroundSprite()
{
LoadComponentAsync(new BeatmapBackgroundSprite(Beatmap.Value)
{
RelativeSizeAxes = Axes.Both,
Anchor = Anchor.Centre,
Origin = Anchor.Centre,
FillMode = FillMode.Fill,
}, background =>
{
if (background.Texture != null)
backgroundSpriteContainer.Child = background;
else
{
backgroundSpriteContainer.Children = new Drawable[]
{
new Box
{
Colour = Colours.GreySeafoamDarker,
RelativeSizeAxes = Axes.Both,
},
new OsuTextFlowContainer(t => t.Font = OsuFont.Default.With(size: 24))
{
Text = "Drag image here to set beatmap background!",
Anchor = Anchor.Centre,
Origin = Anchor.Centre,
AutoSizeAxes = Axes.X,
}
};
}
background.FadeInFromZero(500);
});
}
}
}

View File

@ -1,73 +1,33 @@
// 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.Collections.Generic;
using System.IO;
using System.Linq;
using System.Threading.Tasks;
using osu.Framework.Allocation;
using osu.Framework.Bindables;
using osu.Framework.Graphics;
using osu.Framework.Graphics.Containers;
using osu.Framework.Graphics.Shapes;
using osu.Framework.Graphics.UserInterface;
using osu.Framework.Input.Events;
using osu.Game.Beatmaps;
using osu.Game.Beatmaps.Drawables;
using osu.Game.Database;
using osu.Game.Graphics;
using osu.Game.Graphics.Containers;
using osu.Game.Graphics.Sprites;
using osu.Game.Graphics.UserInterface;
using osu.Game.Graphics.UserInterfaceV2;
using osu.Game.Overlays;
using osuTK;
namespace osu.Game.Screens.Edit.Setup
{
public class SetupScreen : EditorScreen, ICanAcceptFiles
public class SetupScreen : EditorScreen
{
public IEnumerable<string> HandledExtensions => ImageExtensions.Concat(AudioExtensions);
public static string[] ImageExtensions { get; } = { ".jpg", ".jpeg", ".png" };
public static string[] AudioExtensions { get; } = { ".mp3", ".ogg" };
private FillFlowContainer flow;
private LabelledTextBox artistTextBox;
private LabelledTextBox titleTextBox;
private LabelledTextBox creatorTextBox;
private LabelledTextBox difficultyTextBox;
private LabelledTextBox audioTrackTextBox;
private Container backgroundSpriteContainer;
[Resolved]
private OsuGameBase game { get; set; }
private OsuColour colours { get; set; }
[Resolved]
private MusicController music { get; set; }
[Resolved]
private BeatmapManager beatmaps { get; set; }
[Resolved(canBeNull: true)]
private Editor editor { get; set; }
[Cached]
protected readonly OverlayColourProvider ColourProvider;
public SetupScreen()
: base(EditorScreenMode.SongSetup)
{
ColourProvider = new OverlayColourProvider(OverlayColourScheme.Green);
}
[BackgroundDependencyLoader]
private void load(OsuColour colours)
private void load()
{
Container audioTrackFileChooserContainer = new Container
{
RelativeSizeAxes = Axes.X,
AutoSizeAxes = Axes.Y,
};
Child = new Container
{
RelativeSizeAxes = Axes.Both,
@ -84,253 +44,33 @@ namespace osu.Game.Screens.Edit.Setup
Colour = colours.GreySeafoamDark,
RelativeSizeAxes = Axes.Both,
},
new OsuScrollContainer
new SectionsContainer<SetupSection>
{
FixedHeader = new SetupScreenHeader(),
RelativeSizeAxes = Axes.Both,
Padding = new MarginPadding(10),
Child = flow = new FillFlowContainer
Children = new SetupSection[]
{
RelativeSizeAxes = Axes.X,
AutoSizeAxes = Axes.Y,
Spacing = new Vector2(20),
Direction = FillDirection.Vertical,
Children = new Drawable[]
{
backgroundSpriteContainer = new Container
{
RelativeSizeAxes = Axes.X,
Height = 250,
Masking = true,
CornerRadius = 10,
},
new OsuSpriteText
{
Text = "Resources"
},
audioTrackTextBox = new FileChooserLabelledTextBox
{
Label = "Audio Track",
Current = { Value = Beatmap.Value.Metadata.AudioFile ?? "Click to select a track" },
Target = audioTrackFileChooserContainer,
TabbableContentContainer = this
},
audioTrackFileChooserContainer,
new OsuSpriteText
{
Text = "Beatmap metadata"
},
artistTextBox = new LabelledTextBox
{
Label = "Artist",
Current = { Value = Beatmap.Value.Metadata.Artist },
TabbableContentContainer = this
},
titleTextBox = new LabelledTextBox
{
Label = "Title",
Current = { Value = Beatmap.Value.Metadata.Title },
TabbableContentContainer = this
},
creatorTextBox = new LabelledTextBox
{
Label = "Creator",
Current = { Value = Beatmap.Value.Metadata.AuthorString },
TabbableContentContainer = this
},
difficultyTextBox = new LabelledTextBox
{
Label = "Difficulty Name",
Current = { Value = Beatmap.Value.BeatmapInfo.Version },
TabbableContentContainer = this
},
}
},
new ResourcesSection(),
new MetadataSection(),
}
},
}
}
};
updateBackgroundSprite();
audioTrackTextBox.Current.BindValueChanged(audioTrackChanged);
foreach (var item in flow.OfType<LabelledTextBox>())
item.OnCommit += onCommit;
}
Task ICanAcceptFiles.Import(params string[] paths)
{
Schedule(() =>
{
var firstFile = new FileInfo(paths.First());
if (ImageExtensions.Contains(firstFile.Extension))
{
ChangeBackgroundImage(firstFile.FullName);
}
else if (AudioExtensions.Contains(firstFile.Extension))
{
audioTrackTextBox.Text = firstFile.FullName;
}
});
return Task.CompletedTask;
}
private void updateBackgroundSprite()
{
LoadComponentAsync(new BeatmapBackgroundSprite(Beatmap.Value)
{
RelativeSizeAxes = Axes.Both,
Anchor = Anchor.Centre,
Origin = Anchor.Centre,
FillMode = FillMode.Fill,
}, background =>
{
backgroundSpriteContainer.Child = background;
background.FadeInFromZero(500);
});
}
protected override void LoadComplete()
{
base.LoadComplete();
game.RegisterImportHandler(this);
}
public bool ChangeBackgroundImage(string path)
{
var info = new FileInfo(path);
if (!info.Exists)
return false;
var set = Beatmap.Value.BeatmapSetInfo;
// remove the previous background for now.
// in the future we probably want to check if this is being used elsewhere (other difficulties?)
var oldFile = set.Files.FirstOrDefault(f => f.Filename == Beatmap.Value.Metadata.BackgroundFile);
using (var stream = info.OpenRead())
{
if (oldFile != null)
beatmaps.ReplaceFile(set, oldFile, stream, info.Name);
else
beatmaps.AddFile(set, stream, info.Name);
}
Beatmap.Value.Metadata.BackgroundFile = info.Name;
updateBackgroundSprite();
return true;
}
public bool ChangeAudioTrack(string path)
{
var info = new FileInfo(path);
if (!info.Exists)
return false;
var set = Beatmap.Value.BeatmapSetInfo;
// remove the previous audio track for now.
// in the future we probably want to check if this is being used elsewhere (other difficulties?)
var oldFile = set.Files.FirstOrDefault(f => f.Filename == Beatmap.Value.Metadata.AudioFile);
using (var stream = info.OpenRead())
{
if (oldFile != null)
beatmaps.ReplaceFile(set, oldFile, stream, info.Name);
else
beatmaps.AddFile(set, stream, info.Name);
}
Beatmap.Value.Metadata.AudioFile = info.Name;
music.ReloadCurrentTrack();
editor?.UpdateClockSource();
return true;
}
private void audioTrackChanged(ValueChangedEvent<string> filePath)
{
if (!ChangeAudioTrack(filePath.NewValue))
audioTrackTextBox.Current.Value = filePath.OldValue;
}
private void onCommit(TextBox sender, bool newText)
{
if (!newText) return;
// for now, update these on commit rather than making BeatmapMetadata bindables.
// after switching database engines we can reconsider if switching to bindables is a good direction.
Beatmap.Value.Metadata.Artist = artistTextBox.Current.Value;
Beatmap.Value.Metadata.Title = titleTextBox.Current.Value;
Beatmap.Value.Metadata.AuthorString = creatorTextBox.Current.Value;
Beatmap.Value.BeatmapInfo.Version = difficultyTextBox.Current.Value;
}
protected override void Dispose(bool isDisposing)
{
base.Dispose(isDisposing);
game?.UnregisterImportHandler(this);
}
}
internal class FileChooserLabelledTextBox : LabelledTextBox
internal class SetupScreenHeader : OverlayHeader
{
public Container Target;
protected override OverlayTitle CreateTitle() => new SetupScreenTitle();
private readonly IBindable<FileInfo> currentFile = new Bindable<FileInfo>();
public FileChooserLabelledTextBox()
private class SetupScreenTitle : OverlayTitle
{
currentFile.BindValueChanged(onFileSelected);
}
private void onFileSelected(ValueChangedEvent<FileInfo> file)
{
if (file.NewValue == null)
return;
Target.Clear();
Current.Value = file.NewValue.FullName;
}
protected override OsuTextBox CreateTextBox() =>
new FileChooserOsuTextBox
public SetupScreenTitle()
{
Anchor = Anchor.Centre,
Origin = Anchor.Centre,
RelativeSizeAxes = Axes.X,
CornerRadius = CORNER_RADIUS,
OnFocused = DisplayFileChooser
};
public void DisplayFileChooser()
{
Target.Child = new FileSelector(validFileExtensions: SetupScreen.AudioExtensions)
{
RelativeSizeAxes = Axes.X,
Height = 400,
Anchor = Anchor.Centre,
Origin = Anchor.Centre,
CurrentFile = { BindTarget = currentFile }
};
}
internal class FileChooserOsuTextBox : OsuTextBox
{
public Action OnFocused;
protected override void OnFocus(FocusEvent e)
{
OnFocused?.Invoke();
base.OnFocus(e);
GetContainingInputManager().TriggerFocusContention(this);
Title = "beatmap setup";
Description = "change general settings of your beatmap";
IconTexture = "Icons/Hexacons/social";
}
}
}

View File

@ -0,0 +1,42 @@
// 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.Framework.Allocation;
using osu.Framework.Bindables;
using osu.Framework.Graphics;
using osu.Framework.Graphics.Containers;
using osu.Game.Beatmaps;
using osu.Game.Graphics;
using osuTK;
namespace osu.Game.Screens.Edit.Setup
{
internal class SetupSection : Container
{
private readonly FillFlowContainer flow;
[Resolved]
protected OsuColour Colours { get; private set; }
[Resolved]
protected IBindable<WorkingBeatmap> Beatmap { get; private set; }
protected override Container<Drawable> Content => flow;
public SetupSection()
{
RelativeSizeAxes = Axes.X;
AutoSizeAxes = Axes.Y;
Padding = new MarginPadding(10);
InternalChild = flow = new FillFlowContainer
{
RelativeSizeAxes = Axes.X,
AutoSizeAxes = Axes.Y,
Spacing = new Vector2(20),
Direction = FillDirection.Vertical,
};
}
}
}

View File

@ -11,7 +11,7 @@ using osu.Game.Overlays.Settings;
namespace osu.Game.Screens.Edit.Timing
{
internal class SliderWithTextBoxInput<T> : CompositeDrawable, IHasCurrentValue<T>
public class SliderWithTextBoxInput<T> : CompositeDrawable, IHasCurrentValue<T>
where T : struct, IEquatable<T>, IComparable<T>, IConvertible
{
private readonly SettingsSlider<T> slider;
@ -51,7 +51,7 @@ namespace osu.Game.Screens.Edit.Timing
try
{
slider.Bindable.Parse(t.Text);
slider.Current.Parse(t.Text);
}
catch
{
@ -71,8 +71,8 @@ namespace osu.Game.Screens.Edit.Timing
public Bindable<T> Current
{
get => slider.Bindable;
set => slider.Bindable = value;
get => slider.Current;
set => slider.Current = value;
}
}
}

View File

@ -36,14 +36,14 @@ namespace osu.Game.Screens.Edit.Timing
{
if (point.NewValue != null)
{
bpmSlider.Bindable = point.NewValue.BeatLengthBindable;
bpmSlider.Bindable.BindValueChanged(_ => ChangeHandler?.SaveState());
bpmSlider.Current = point.NewValue.BeatLengthBindable;
bpmSlider.Current.BindValueChanged(_ => ChangeHandler?.SaveState());
bpmTextEntry.Bindable = point.NewValue.BeatLengthBindable;
// no need to hook change handler here as it's the same bindable as above
timeSignature.Bindable = point.NewValue.TimeSignatureBindable;
timeSignature.Bindable.BindValueChanged(_ => ChangeHandler?.SaveState());
timeSignature.Current = point.NewValue.TimeSignatureBindable;
timeSignature.Current.BindValueChanged(_ => ChangeHandler?.SaveState());
}
}
@ -121,14 +121,14 @@ namespace osu.Game.Screens.Edit.Timing
beatLengthBindable.BindValueChanged(beatLength => updateCurrent(beatLengthToBpm(beatLength.NewValue)), true);
bpmBindable.BindValueChanged(bpm => beatLengthBindable.Value = beatLengthToBpm(bpm.NewValue));
base.Bindable = bpmBindable;
base.Current = bpmBindable;
TransferValueOnCommit = true;
}
public override Bindable<double> Bindable
public override Bindable<double> Current
{
get => base.Bindable;
get => base.Current;
set
{
// incoming will be beat length, not bpm

View File

@ -51,14 +51,14 @@ namespace osu.Game.Screens.Play.PlayerSettings
}
},
},
rateSlider = new PlayerSliderBar<double> { Bindable = UserPlaybackRate }
rateSlider = new PlayerSliderBar<double> { Current = UserPlaybackRate }
};
}
protected override void LoadComplete()
{
base.LoadComplete();
rateSlider.Bindable.BindValueChanged(multiplier => multiplierText.Text = $"{multiplier.NewValue:0.0}x", true);
rateSlider.Current.BindValueChanged(multiplier => multiplierText.Text = $"{multiplier.NewValue:0.0}x", true);
}
}
}

View File

@ -50,8 +50,8 @@ namespace osu.Game.Screens.Play.PlayerSettings
[BackgroundDependencyLoader]
private void load(OsuConfigManager config)
{
dimSliderBar.Bindable = config.GetBindable<double>(OsuSetting.DimLevel);
blurSliderBar.Bindable = config.GetBindable<double>(OsuSetting.BlurLevel);
dimSliderBar.Current = config.GetBindable<double>(OsuSetting.DimLevel);
blurSliderBar.Current = config.GetBindable<double>(OsuSetting.BlurLevel);
showStoryboardToggle.Current = config.GetBindable<bool>(OsuSetting.ShowStoryboard);
beatmapSkinsToggle.Current = config.GetBindable<bool>(OsuSetting.BeatmapSkins);
beatmapHitsoundsToggle.Current = config.GetBindable<bool>(OsuSetting.BeatmapHitsounds);