diff --git a/Content.Tests/DMProject/Tests/Builtins/rgb.dm b/Content.Tests/DMProject/Tests/Builtins/rgb.dm new file mode 100644 index 0000000000..f0eb2f206d --- /dev/null +++ b/Content.Tests/DMProject/Tests/Builtins/rgb.dm @@ -0,0 +1,12 @@ +/proc/RunTest() + ASSERT(rgb(255, 255, 255) =="#ffffff") + ASSERT(rgb(255, 0, 0) == "#ff0000" ) + ASSERT(rgb(0, 0, 255) == "#0000ff") + ASSERT(rgb(18, 245, 230) == "#12f5e6") + ASSERT(rgb(18, 245, 230, 128) == "#12f5e680") + ASSERT(rgb(202, 96, 219, space=COLORSPACE_RGB) == "#ca60db") + ASSERT(rgb(291.70734, 56.164383, 85.882355, space=COLORSPACE_HSV) == "#ca60db") + ASSERT(rgb(291.70734, 63.07692, 61.764706, space=COLORSPACE_HSL) == "#ca60db" ) + + ASSERT(rgb(291.70734, 63.07692, 61.764706, 128, COLORSPACE_HSL) == "#ca60db80" ) + //ASSERT(rgb(291.70734, 68.2215, 55.423534, space=COLORSPACE_HCY) == "#ca60db") // TODO Support HCY \ No newline at end of file diff --git a/OpenDream.sln.DotSettings b/OpenDream.sln.DotSettings index d7ed950d3a..68a026431e 100644 --- a/OpenDream.sln.DotSettings +++ b/OpenDream.sln.DotSettings @@ -16,6 +16,9 @@ LHS RHS UI + RGB + HSV + HSL True True True diff --git a/OpenDreamRuntime/Procs/DMOpcodeHandlers.cs b/OpenDreamRuntime/Procs/DMOpcodeHandlers.cs index 542ac796cf..8e15ccf7bd 100644 --- a/OpenDreamRuntime/Procs/DMOpcodeHandlers.cs +++ b/OpenDreamRuntime/Procs/DMOpcodeHandlers.cs @@ -1929,7 +1929,7 @@ public static ProcStatus Rgb(DMProcState state) { DreamValue color1 = default; DreamValue color2 = default; DreamValue color3 = default; - DreamValue a = default; + DreamValue a = DreamValue.Null; ColorHelpers.ColorSpace space = ColorHelpers.ColorSpace.RGB; if (arguments.Item1 != null) { @@ -1974,6 +1974,9 @@ public static ProcStatus Rgb(DMProcState state) { } else if (name.StartsWith("v", StringComparison.InvariantCultureIgnoreCase) && color3 == default) { color3 = arg.Value; space = ColorHelpers.ColorSpace.HSV; + } else if (name.StartsWith("l", StringComparison.InvariantCultureIgnoreCase) && color3 == default) { + color3 = arg.Value; + space = ColorHelpers.ColorSpace.HSL; } else if (name.StartsWith("a", StringComparison.InvariantCultureIgnoreCase) && a == default) a = arg.Value; else if (name == "space" && space == default) @@ -1994,10 +1997,10 @@ public static ProcStatus Rgb(DMProcState state) { return ProcStatus.Continue; } - int color1Value = (int)color1.UnsafeGetValueAsFloat(); - int color2Value = (int)color2.UnsafeGetValueAsFloat(); - int color3Value = (int)color3.UnsafeGetValueAsFloat(); - byte aValue = (byte)Math.Clamp((int)a.UnsafeGetValueAsFloat(), 0, 255); + float color1Value = color1.UnsafeGetValueAsFloat(); + float color2Value = color2.UnsafeGetValueAsFloat(); + float color3Value = color3.UnsafeGetValueAsFloat(); + byte aValue = a.IsNull ? (byte)255 : (byte)Math.Clamp((int)a.UnsafeGetValueAsFloat(), 0, 255); Color color; switch (space) { @@ -2018,15 +2021,23 @@ public static ProcStatus Rgb(DMProcState state) { color = Color.FromHsv((h, s, v, aValue / 255f)); break; } + case ColorHelpers.ColorSpace.HSL: { + float h = Math.Clamp(color1Value, 0, 360) / 360f; + float s = Math.Clamp(color2Value, 0, 100) / 100f; + float l = Math.Clamp(color3Value, 0, 100) / 100f; + + color = Color.FromHsl((h, s, l, aValue / 255f)); + break; + } default: throw new Exception($"Unimplemented color space {space}"); } // TODO: There is a difference between passing null and not passing a fourth arg at all if (a.IsNull) { - state.Push(new DreamValue($"#{color.RByte:X2}{color.GByte:X2}{color.BByte:X2}")); + state.Push(new DreamValue($"#{color.RByte:X2}{color.GByte:X2}{color.BByte:X2}".ToLower())); } else { - state.Push(new DreamValue($"#{color.RByte:X2}{color.GByte:X2}{color.BByte:X2}{color.AByte:X2}")); + state.Push(new DreamValue($"#{color.RByte:X2}{color.GByte:X2}{color.BByte:X2}{color.AByte:X2}".ToLower())); } return ProcStatus.Continue; diff --git a/OpenDreamShared/Dream/ColorHelpers.cs b/OpenDreamShared/Dream/ColorHelpers.cs index 45f5a2794b..98f5e413eb 100644 --- a/OpenDreamShared/Dream/ColorHelpers.cs +++ b/OpenDreamShared/Dream/ColorHelpers.cs @@ -29,7 +29,8 @@ public static class ColorHelpers { public enum ColorSpace { RGB = 0, - HSV = 1 + HSV = 1, + HSL = 2 } public static bool TryParseColor(string color, out Color colorOut, string defaultAlpha = "ff") {