Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add colour customisation to layout editor #29936

Open
wants to merge 13 commits into
base: master
Choose a base branch
from
28 changes: 20 additions & 8 deletions osu.Game.Tests/Visual/Settings/TestSceneSettingsSource.cs
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
using osu.Framework.Bindables;
using osu.Framework.Graphics;
using osu.Framework.Graphics.Containers;
using osu.Framework.Graphics.Cursor;
using osu.Framework.Localisation;
using osu.Game.Configuration;
using osu.Game.Overlays.Settings;
Expand All @@ -19,16 +20,20 @@ public TestSceneSettingsSource()
{
Children = new Drawable[]
{
new FillFlowContainer
new PopoverContainer
{
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()
Child = 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()
},
},
};
}
Expand Down Expand Up @@ -66,6 +71,13 @@ private class TestTargetClass

[SettingSource("Sample number textbox", "Textbox number entry", SettingControlType = typeof(SettingsNumberBox))]
public Bindable<int?> IntTextBoxBindable { get; } = new Bindable<int?>();

[SettingSource("Sample colour", "Change the colour", SettingControlType = typeof(SettingsColour))]
public BindableColour4 ColourBindable { get; } = new BindableColour4
{
Default = Colour4.White,
Value = Colour4.Red
};
}

private enum TestEnum
Expand Down
75 changes: 75 additions & 0 deletions osu.Game.Tests/Visual/UserInterface/TestSceneSettingsColour.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
// Copyright (c) ppy Pty Ltd <[email protected]>. Licensed under the MIT Licence.
// See the LICENCE file in the repository root for full licence text.

using System.Linq;
using NUnit.Framework;
using osu.Framework.Graphics;
using osu.Framework.Graphics.Containers;
using osu.Framework.Graphics.Cursor;
using osu.Framework.Testing;
using osu.Framework.Utils;
using osu.Game.Graphics.UserInterfaceV2;
using osu.Game.Overlays.Settings;
using osuTK.Graphics;
using osuTK.Input;

namespace osu.Game.Tests.Visual.UserInterface
{
public partial class TestSceneSettingsColour : OsuManualInputManagerTestScene
{
private SettingsColour? component;

[Test]
public void TestColour()
{
createContent();

AddRepeatStep("set random colour", () => component!.Current.Value = randomColour(), 4);
}

[Test]
public void TestUserInteractions()
{
createContent();

AddStep("click colour", () =>
{
InputManager.MoveMouseTo(component!);
InputManager.Click(MouseButton.Left);
});

AddAssert("colour picker spawned", () => this.ChildrenOfType<OsuColourPicker>().Any());
}

private void createContent()
{
AddStep("create component", () =>
{
Child = new PopoverContainer
{
RelativeSizeAxes = Axes.Both,
Child = new FillFlowContainer
{
Anchor = Anchor.Centre,
Origin = Anchor.Centre,
Width = 500,
AutoSizeAxes = Axes.Y,
Children = new Drawable[]
{
component = new SettingsColour
{
LabelText = "a sample component",
},
},
},
};
});
}

private Colour4 randomColour() => new Color4(
RNG.NextSingle(),
RNG.NextSingle(),
RNG.NextSingle(),
1);
}
}
13 changes: 13 additions & 0 deletions osu.Game/Configuration/SettingSourceAttribute.cs
Original file line number Diff line number Diff line change
Expand Up @@ -186,6 +186,16 @@ public static IEnumerable<Drawable> CreateSettingsControls(this object obj)

break;

case BindableColour4 bColour:
yield return new SettingsColour
{
LabelText = attr.Label,
TooltipText = attr.Description,
Current = bColour
};

break;

case IBindable bindable:
var dropdownType = typeof(ModSettingsEnumDropdown<>).MakeGenericType(bindable.GetType().GetGenericArguments()[0]);
var dropdown = (Drawable)Activator.CreateInstance(dropdownType)!;
Expand Down Expand Up @@ -227,6 +237,9 @@ public static object GetUnderlyingSettingValue(this object setting)
case Bindable<bool> b:
return b.Value;

case BindableColour4 c:
return c.Value.ToHex();

case IBindable u:
// An unknown (e.g. enum) generic type.
var valueMethod = u.GetType().GetProperty(nameof(IBindable<int>.Value));
Expand Down
20 changes: 20 additions & 0 deletions osu.Game/Localisation/SkinComponents/SkinnableComponentStrings.cs
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,26 @@ public static class SkinnableComponentStrings
/// </summary>
public static LocalisableString ShowLabelDescription => new TranslatableString(getKey(@"show_label_description"), @"Whether the component's label should be shown.");

/// <summary>
/// "Colour"
/// </summary>
public static LocalisableString Colour => new TranslatableString(getKey(@"colour"), @"Colour");

/// <summary>
/// "The colour of the component."
/// </summary>
public static LocalisableString ColourDescription => new TranslatableString(getKey(@"colour_description"), @"The colour of the component.");

/// <summary>
/// "Text colour"
/// </summary>
public static LocalisableString TextColour => new TranslatableString(getKey(@"text_colour"), @"Text colour");

/// <summary>
/// "The colour of the text."
/// </summary>
public static LocalisableString TextColourDescription => new TranslatableString(getKey(@"text_colour_description"), @"The colour of the text.");

private static string getKey(string key) => $@"{prefix}:{key}";
}
}
80 changes: 80 additions & 0 deletions osu.Game/Overlays/Settings/SettingsColour.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
// Copyright (c) ppy Pty Ltd <[email protected]>. Licensed under the MIT Licence.
// See the LICENCE file in the repository root for full licence text.

using osu.Framework.Bindables;
using osu.Framework.Extensions;
using osu.Framework.Graphics;
using osu.Framework.Graphics.Cursor;
using osu.Framework.Graphics.Shapes;
using osu.Framework.Graphics.UserInterface;
using osu.Game.Graphics;
using osu.Game.Graphics.Containers;
using osu.Game.Graphics.Sprites;
using osu.Game.Graphics.UserInterfaceV2;

namespace osu.Game.Overlays.Settings
{
public partial class SettingsColour : SettingsItem<Colour4>
{
protected override Drawable CreateControl() => new ColourControl();

public partial class ColourControl : OsuClickableContainer, IHasPopover, IHasCurrentValue<Colour4>
{
private readonly BindableWithCurrent<Colour4> current = new BindableWithCurrent<Colour4>(Colour4.White);

public Bindable<Colour4> Current
{
get => current.Current;
set => current.Current = value;
}

private readonly Box fill;
private readonly OsuSpriteText colourHexCode;

public ColourControl()
{
RelativeSizeAxes = Axes.X;
Height = 40;
CornerRadius = 20;
Masking = true;
Action = this.ShowPopover;

Children = new Drawable[]
{
fill = new Box
{
RelativeSizeAxes = Axes.Both
},
colourHexCode = new OsuSpriteText
{
Anchor = Anchor.Centre,
Origin = Anchor.Centre,
Font = OsuFont.Default.With(size: 20)
}
};
}

protected override void LoadComplete()
{
base.LoadComplete();

Current.BindValueChanged(_ => updateColour(), true);
}

private void updateColour()
{
fill.Colour = Current.Value;
colourHexCode.Text = Current.Value.ToHex();
colourHexCode.Colour = OsuColour.ForegroundTextColourFor(Current.Value);
}

public Popover GetPopover() => new OsuPopover(false)
{
Child = new OsuColourPicker
{
Current = { BindTarget = Current }
}
};
}
}
}
Loading