Merge pull request #13714 from bdach/colour-picker

Add osu!-styled colour picker control
This commit is contained in:
Dean Herbert 2021-07-02 18:05:19 +09:00 committed by GitHub
commit 1bbf578dfe
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 297 additions and 0 deletions

View File

@ -0,0 +1,91 @@
// 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.Framework.Testing;
using osu.Game.Graphics;
using osu.Game.Graphics.Sprites;
using osu.Game.Graphics.UserInterfaceV2;
using osu.Game.Overlays;
namespace osu.Game.Tests.Visual.UserInterface
{
public class TestSceneColourPicker : OsuTestScene
{
private readonly Bindable<Colour4> colour = new Bindable<Colour4>(Colour4.Aquamarine);
[SetUpSteps]
public void SetUpSteps()
{
AddStep("create pickers", () => Child = new GridContainer
{
RelativeSizeAxes = Axes.Both,
ColumnDimensions = new[]
{
new Dimension(),
new Dimension()
},
Content = new[]
{
new Drawable[]
{
new Container
{
RelativeSizeAxes = Axes.Both,
Children = new Drawable[]
{
new OsuSpriteText
{
Text = @"No OverlayColourProvider",
Font = OsuFont.Default.With(size: 40)
},
new OsuColourPicker
{
Anchor = Anchor.Centre,
Origin = Anchor.Centre,
Current = { BindTarget = colour },
}
}
},
new ColourProvidingContainer(OverlayColourScheme.Blue)
{
RelativeSizeAxes = Axes.Both,
Children = new Drawable[]
{
new OsuSpriteText
{
Text = @"With blue OverlayColourProvider",
Font = OsuFont.Default.With(size: 40)
},
new OsuColourPicker
{
Anchor = Anchor.Centre,
Origin = Anchor.Centre,
Current = { BindTarget = colour },
}
}
}
}
}
});
AddStep("set green", () => colour.Value = Colour4.LimeGreen);
AddStep("set white", () => colour.Value = Colour4.White);
AddStep("set red", () => colour.Value = Colour4.Red);
}
private class ColourProvidingContainer : Container
{
[Cached]
private OverlayColourProvider provider { get; }
public ColourProvidingContainer(OverlayColourScheme colourScheme)
{
provider = new OverlayColourProvider(colourScheme);
}
}
}
}

View File

@ -0,0 +1,19 @@
// 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.Graphics.UserInterface;
namespace osu.Game.Graphics.UserInterfaceV2
{
public class OsuColourPicker : ColourPicker
{
public OsuColourPicker()
{
CornerRadius = 10;
Masking = true;
}
protected override HSVColourPicker CreateHSVColourPicker() => new OsuHSVColourPicker();
protected override HexColourPicker CreateHexColourPicker() => new OsuHexColourPicker();
}
}

View File

@ -0,0 +1,129 @@
// 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 JetBrains.Annotations;
using osu.Framework.Allocation;
using osu.Framework.Bindables;
using osu.Framework.Graphics;
using osu.Framework.Graphics.Containers;
using osu.Framework.Graphics.Effects;
using osu.Framework.Graphics.Shapes;
using osu.Framework.Graphics.UserInterface;
using osu.Game.Overlays;
using osuTK;
namespace osu.Game.Graphics.UserInterfaceV2
{
public class OsuHSVColourPicker : HSVColourPicker
{
private const float spacing = 10;
private const float corner_radius = 10;
private const float control_border_thickness = 3;
protected override HueSelector CreateHueSelector() => new OsuHueSelector();
protected override SaturationValueSelector CreateSaturationValueSelector() => new OsuSaturationValueSelector();
[BackgroundDependencyLoader(true)]
private void load([CanBeNull] OverlayColourProvider colourProvider, OsuColour osuColour)
{
Background.Colour = colourProvider?.Dark5 ?? osuColour.GreySeafoamDark;
Content.Padding = new MarginPadding(spacing);
Content.Spacing = new Vector2(0, spacing);
}
private static EdgeEffectParameters createShadowParameters() => new EdgeEffectParameters
{
Type = EdgeEffectType.Shadow,
Offset = new Vector2(0, 1),
Radius = 3,
Colour = Colour4.Black.Opacity(0.3f)
};
private class OsuHueSelector : HueSelector
{
public OsuHueSelector()
{
SliderBar.CornerRadius = corner_radius;
SliderBar.Masking = true;
}
protected override Drawable CreateSliderNub() => new SliderNub(this);
private class SliderNub : CompositeDrawable
{
private readonly Bindable<float> hue;
private readonly Box fill;
public SliderNub(OsuHueSelector osuHueSelector)
{
hue = osuHueSelector.Hue.GetBoundCopy();
InternalChild = new CircularContainer
{
Height = 35,
Width = 10,
Origin = Anchor.Centre,
Anchor = Anchor.Centre,
Masking = true,
BorderColour = Colour4.White,
BorderThickness = control_border_thickness,
EdgeEffect = createShadowParameters(),
Child = fill = new Box
{
RelativeSizeAxes = Axes.Both
}
};
}
protected override void LoadComplete()
{
hue.BindValueChanged(h => fill.Colour = Colour4.FromHSV(h.NewValue, 1, 1), true);
}
}
}
private class OsuSaturationValueSelector : SaturationValueSelector
{
public OsuSaturationValueSelector()
{
SelectionArea.CornerRadius = corner_radius;
SelectionArea.Masking = true;
// purposefully use hard non-AA'd masking to avoid edge artifacts.
SelectionArea.MaskingSmoothness = 0;
}
protected override Marker CreateMarker() => new OsuMarker();
private class OsuMarker : Marker
{
private readonly Box previewBox;
public OsuMarker()
{
AutoSizeAxes = Axes.Both;
InternalChild = new CircularContainer
{
Size = new Vector2(20),
Masking = true,
BorderColour = Colour4.White,
BorderThickness = control_border_thickness,
EdgeEffect = createShadowParameters(),
Child = previewBox = new Box
{
RelativeSizeAxes = Axes.Both
}
};
}
protected override void LoadComplete()
{
base.LoadComplete();
Current.BindValueChanged(colour => previewBox.Colour = colour.NewValue, true);
}
}
}
}
}

View File

@ -0,0 +1,57 @@
// 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 JetBrains.Annotations;
using osu.Framework.Allocation;
using osu.Framework.Graphics;
using osu.Framework.Graphics.Containers;
using osu.Framework.Graphics.Shapes;
using osu.Framework.Graphics.UserInterface;
using osu.Game.Graphics.UserInterface;
using osu.Game.Overlays;
namespace osu.Game.Graphics.UserInterfaceV2
{
public class OsuHexColourPicker : HexColourPicker
{
public OsuHexColourPicker()
{
Padding = new MarginPadding(20);
Spacing = 20;
}
[BackgroundDependencyLoader(true)]
private void load([CanBeNull] OverlayColourProvider overlayColourProvider, OsuColour osuColour)
{
Background.Colour = overlayColourProvider?.Dark6 ?? osuColour.GreySeafoamDarker;
}
protected override TextBox CreateHexCodeTextBox() => new OsuTextBox();
protected override ColourPreview CreateColourPreview() => new OsuColourPreview();
private class OsuColourPreview : ColourPreview
{
private readonly Box preview;
public OsuColourPreview()
{
InternalChild = new CircularContainer
{
RelativeSizeAxes = Axes.Both,
Masking = true,
Child = preview = new Box
{
RelativeSizeAxes = Axes.Both
}
};
}
protected override void LoadComplete()
{
base.LoadComplete();
Current.BindValueChanged(colour => preview.Colour = colour.NewValue, true);
}
}
}
}

View File

@ -308,6 +308,7 @@
<s:String x:Key="/Default/CodeStyle/Naming/CSharpNaming/Abbreviations/=GL/@EntryIndexedValue">GL</s:String>
<s:String x:Key="/Default/CodeStyle/Naming/CSharpNaming/Abbreviations/=GLSL/@EntryIndexedValue">GLSL</s:String>
<s:String x:Key="/Default/CodeStyle/Naming/CSharpNaming/Abbreviations/=HID/@EntryIndexedValue">HID</s:String>
<s:String x:Key="/Default/CodeStyle/Naming/CSharpNaming/Abbreviations/=HSV/@EntryIndexedValue">HSV</s:String>
<s:String x:Key="/Default/CodeStyle/Naming/CSharpNaming/Abbreviations/=HTML/@EntryIndexedValue">HTML</s:String>
<s:String x:Key="/Default/CodeStyle/Naming/CSharpNaming/Abbreviations/=HUD/@EntryIndexedValue">HUD</s:String>
<s:String x:Key="/Default/CodeStyle/Naming/CSharpNaming/Abbreviations/=ID/@EntryIndexedValue">ID</s:String>