diff --git a/CHANGELOG.md b/CHANGELOG.md index 1c82d06..30a2257 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -16,7 +16,9 @@ Jump to version: ## 7.0.1 (In Development) -No code changes +### MLEM +Additions +- Added ColorExtensions.ToHsl and ColorHelper.FromHsl ## 7.0.0 diff --git a/MLEM/Graphics/ColorExtensions.cs b/MLEM/Graphics/ColorExtensions.cs index 7c4faca..897fbb8 100644 --- a/MLEM/Graphics/ColorExtensions.cs +++ b/MLEM/Graphics/ColorExtensions.cs @@ -58,6 +58,39 @@ namespace MLEM.Graphics { return $"{(hash ? "#" : string.Empty)}{color.R:X2}{color.G:X2}{color.B:X2}"; } + /// + /// Converts the given into HSL representation and returns the result as a value tuple with values between 0 and 1. + /// + /// This code is adapted from https://gist.github.com/mjackson/5311256. + /// The color to convert. + /// The resulting HSL color as a value tuple containing H, S and L, each between 0 and 1. + public static (float H, float S, float L) ToHsl(this Color color) { + var r = color.R / 255F; + var g = color.G / 255F; + var b = color.B / 255F; + + var max = Math.Max(Math.Max(r, g), b); + var min = Math.Min(Math.Min(r, g), b); + float h, s, l = (max + min) / 2; + + if (max == min) { + h = s = 0; // achromatic + } else { + var d = max - min; + s = l > 0.5F ? d / (2 - max - min) : d / (max + min); + if (r == max) { + h = (g - b) / d + (g < b ? 6 : 0); + } else if (g == max) { + h = (b - r) / d + 2; + } else { + h = (r - g) / d + 4; + } + h /= 6; + } + + return (h, s, l); + } + } /// @@ -116,5 +149,54 @@ namespace MLEM.Graphics { return false; } + /// + ///Converts the given HSL color to an RGB and returns the result. + /// + /// This code is adapted from https://gist.github.com/mjackson/5311256. + /// The HSL color to convert, as a value tuple that contains H, S and L values, each between 0 and 1. + /// The resulting RGB color. + public static Color FromHsl((float H, float S, float L) color) { + return ColorHelper.FromHsl(color.H, color.S, color.L); + } + + /// + ///Converts the given HSL values to an RGB and returns the result. + /// + /// This code is adapted from https://gist.github.com/mjackson/5311256. + /// The H component of the HSL color, between 0 and 1. + /// The S component of the HSL color, between 0 and 1. + /// The L component of the HSL color, between 0 and 1. + /// The resulting RGB color. + public static Color FromHsl(float h, float s, float l) { + float r, g, b; + + if (s == 0) { + r = g = b = l; // achromatic + } else { + var q = l < 0.5F ? l * (1 + s) : l + s - l * s; + var p = 2 * l - q; + + r = ColorHelper.HueToRgb(p, q, h + 1 / 3F); + g = ColorHelper.HueToRgb(p, q, h); + b = ColorHelper.HueToRgb(p, q, h - 1 / 3F); + } + + return new Color(r, g, b); + } + + private static float HueToRgb(float p, float q, float t) { + if (t < 0) + t += 1; + if (t > 1) + t -= 1; + if (t < 1 / 6F) + return p + (q - p) * 6 * t; + if (t < 1 / 2F) + return q; + if (t < 2 / 3F) + return p + (q - p) * (2 / 3F - t) * 6; + return p; + } + } } diff --git a/Sandbox/GameImpl.cs b/Sandbox/GameImpl.cs index dff401b..3a2711f 100644 --- a/Sandbox/GameImpl.cs +++ b/Sandbox/GameImpl.cs @@ -19,6 +19,7 @@ using MLEM.Textures; using MLEM.Ui; using MLEM.Ui.Elements; using MLEM.Ui.Style; +using Group = MLEM.Ui.Elements.Group; namespace Sandbox; @@ -87,6 +88,7 @@ public class GameImpl : MlemGame { this.SpriteBatch.End(); };*/ + /* var panel = new Panel(Anchor.Center, new Vector2(0, 100), Vector2.Zero) {SetWidthBasedOnChildren = true}; panel.AddChild(new Button(Anchor.AutoLeft, new Vector2(100, 10))); panel.AddChild(new Button(Anchor.AutoCenter, new Vector2(80, 10))); @@ -112,17 +114,21 @@ public class GameImpl : MlemGame { var dir = vec.ToDirection(); Console.WriteLine(vec + " -> " + dir); } + */ + /* var writer = new StringWriter(); - this.Content.GetJsonSerializer().Serialize(writer, obj); + this.Content.GetJsonSerializer().Serialize(writer, obj);*/ //Console.WriteLine(writer.ToString()); // {"Vec":"10 20","Point":"20 30","Rectangle":"1 2 3 4","RectangleF":"4 5 6 7"} // Also: //this.Content.AddJsonConverter(new CustomConverter()); + /* var res = this.Content.LoadJson("Test"); Console.WriteLine("The res is " + res); + */ //var gradient = this.SpriteBatch.GenerateGradientTexture(Color.Green, Color.Red, Color.Blue, Color.Yellow); /*this.OnDraw += (game, time) => { @@ -139,6 +145,7 @@ public class GameImpl : MlemGame { this.SpriteBatch.End(); };*/ + /* var sc = 2; var formatter = new TextFormatter(); formatter.AddImage("Test", new TextureRegion(tex, 0, 8, 24, 24)); @@ -185,6 +192,7 @@ public class GameImpl : MlemGame { } this.tokenized.Update(time); }; + */ /*var testPanel = new Panel(Anchor.Center, new Vector2(0.5F, 100), Vector2.Zero); testPanel.AddChild(new Button(Anchor.AutoLeft, new Vector2(0.25F, -1))); @@ -225,6 +233,7 @@ public class GameImpl : MlemGame { par.OnDrawn = (e, time, batch, a) => batch.DrawRectangle(e.DisplayArea.ToExtended(), Color.Red); this.UiSystem.Add("Load", loadGroup);*/ + /* var spillPanel = new Panel(Anchor.Center, new Vector2(100), Vector2.Zero); var squishingGroup = spillPanel.AddChild(new SquishingGroup(Anchor.TopLeft, Vector2.One)); squishingGroup.AddChild(new Button(Anchor.TopLeft, new Vector2(30), "TL") { @@ -293,6 +302,7 @@ public class GameImpl : MlemGame { } this.SpriteBatch.End(); }; + */ /*var viewport = new BoxingViewportAdapter(this.Window, this.GraphicsDevice, 1280, 720); var newPanel = new Panel(Anchor.TopLeft, new Vector2(200, 100), new Vector2(10, 10)); @@ -387,6 +397,28 @@ public class GameImpl : MlemGame { Console.WriteLine("MouseButtons: " + string.Join(", ", GenericInput.AllMouseButtons)); Console.WriteLine("Buttons: " + string.Join(", ", GenericInput.AllButtons)); Console.WriteLine("Inputs: " + string.Join(", ", GenericInput.AllInputs));*/ + + var hsl = new Panel(Anchor.Center, new Vector2(100), true); + var color = Color.Pink.ToHsl(); + hsl.AddChild(new Paragraph(Anchor.AutoLeft, 1, "H")); + hsl.AddChild(new Slider(Anchor.AutoLeft, new Vector2(1, 10), 5, 1) { + CurrentValue = color.H, + OnValueChanged = (_, v) => color.H = v + }); + hsl.AddChild(new Paragraph(Anchor.AutoLeft, 1, "S")); + hsl.AddChild(new Slider(Anchor.AutoLeft, new Vector2(1, 10), 5, 1) { + CurrentValue = color.S, + OnValueChanged = (_, v) => color.S = v + }); + hsl.AddChild(new Paragraph(Anchor.AutoLeft, 1, "L")); + hsl.AddChild(new Slider(Anchor.AutoLeft, new Vector2(1, 10), 5, 1) { + CurrentValue = color.L, + OnValueChanged = (_, v) => color.L = v + }); + hsl.AddChild(new Group(Anchor.AutoLeft, new Vector2(1, 40), false) { + OnDrawn = (e, _, batch, _, _) => batch.Draw(batch.GetBlankTexture(), e.DisplayArea, ColorHelper.FromHsl(color)) + }); + this.UiSystem.Add("HSL", hsl); } protected override void DoUpdate(GameTime gameTime) {