1
0
mirror of https://github.com/ppy/osu.git synced 2024-12-14 09:32:55 +08:00

Add the ability to create settings UI components from a class w… (#7081)

Add the ability to create settings UI components from a class with exposed drawables
This commit is contained in:
Dean Herbert 2019-12-10 19:12:58 +09:00 committed by GitHub
commit f3ec98d85f
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 175 additions and 0 deletions

View File

@ -0,0 +1,65 @@
// 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.Configuration;
using osuTK;
namespace osu.Game.Tests.Visual.Settings
{
[TestFixture]
public class TestSceneSettingsSource : OsuTestScene
{
public TestSceneSettingsSource()
{
Children = new Drawable[]
{
new FillFlowContainer
{
RelativeSizeAxes = Axes.Both,
Direction = FillDirection.Vertical,
Spacing = new Vector2(20),
Width = 0.5f,
Anchor = Anchor.Centre,
Origin = Anchor.Centre,
Padding = new MarginPadding(50),
ChildrenEnumerable = new TestTargetClass().CreateSettingsControls()
},
};
}
private class TestTargetClass
{
[SettingSource("Sample bool", "Clicking this changes a setting")]
public BindableBool TickBindable { get; } = new BindableBool();
[SettingSource("Sample float", "Change something for a mod")]
public BindableFloat SliderBindable { get; } = new BindableFloat
{
MinValue = 0,
MaxValue = 10,
Default = 5,
Value = 7
};
[SettingSource("Sample enum", "Change something for a mod")]
public Bindable<TestEnum> EnumBindable { get; } = new Bindable<TestEnum>
{
Default = TestEnum.Value1,
Value = TestEnum.Value2
};
[SettingSource("Sample string", "Change something for a mod")]
public Bindable<string> StringBindable { get; } = new Bindable<string>();
}
private enum TestEnum
{
Value1,
Value2
}
}
}

View File

@ -0,0 +1,110 @@
// 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.Reflection;
using JetBrains.Annotations;
using osu.Framework.Bindables;
using osu.Framework.Graphics;
using osu.Framework.Graphics.UserInterface;
using osu.Game.Overlays.Settings;
namespace osu.Game.Configuration
{
/// <summary>
/// An attribute to mark a bindable as being exposed to the user via settings controls.
/// Can be used in conjunction with <see cref="SettingSourceExtensions.CreateSettingsControls"/> to automatically create UI controls.
/// </summary>
[MeansImplicitUse]
[AttributeUsage(AttributeTargets.Property)]
public class SettingSourceAttribute : Attribute
{
public string Label { get; }
public string Description { get; }
public SettingSourceAttribute(string label, string description = null)
{
Label = label ?? string.Empty;
Description = description ?? string.Empty;
}
}
public static class SettingSourceExtensions
{
public static IEnumerable<Drawable> CreateSettingsControls(this object obj)
{
foreach (var property in obj.GetType().GetProperties(BindingFlags.GetProperty | BindingFlags.Public | BindingFlags.Instance))
{
var attr = property.GetCustomAttribute<SettingSourceAttribute>(true);
if (attr == null)
continue;
var prop = property.GetValue(obj);
switch (prop)
{
case BindableNumber<float> bNumber:
yield return new SettingsSlider<float>
{
LabelText = attr.Label,
Bindable = bNumber
};
break;
case BindableNumber<double> bNumber:
yield return new SettingsSlider<double>
{
LabelText = attr.Label,
Bindable = bNumber
};
break;
case BindableNumber<int> bNumber:
yield return new SettingsSlider<int>
{
LabelText = attr.Label,
Bindable = bNumber
};
break;
case Bindable<bool> bBool:
yield return new SettingsCheckbox
{
LabelText = attr.Label,
Bindable = bBool
};
break;
case Bindable<string> bString:
yield return new SettingsTextBox
{
LabelText = attr.Label,
Bindable = bString
};
break;
case IBindable bindable:
var dropdownType = typeof(SettingsEnumDropdown<>).MakeGenericType(bindable.GetType().GetGenericArguments()[0]);
var dropdown = (Drawable)Activator.CreateInstance(dropdownType);
dropdown.GetType().GetProperty(nameof(IHasCurrentValue<object>.Current))?.SetValue(dropdown, obj);
yield return dropdown;
break;
default:
throw new InvalidOperationException($"{nameof(SettingSourceAttribute)} was attached to an unsupported type ({prop})");
}
}
}
}
}