using System.Collections.Generic; using UnityEngine; // Sci-Fi Ship Controller. Copyright (c) 2018-2023 SCSM Pty Ltd. All rights reserved. namespace SciFiShipController { /// <summary> /// stores Unity colour data in multiple formats. /// RGBA (Color32 and Color), HSV /// </summary> public struct SSCColour { #region Public Variables - RGBA colours in 32 bit format /// <summary> /// Red value 0-255. Set(r,g,b,a) is the same as calling Refresh() after changing the value. /// </summary> public byte r; /// <summary> /// Green value 0-255. Set(r,g,b,a) is the same as calling Refresh() after changing the value. /// </summary> public byte g; /// <summary> /// Blue value 0-255. Set(r,g,b,a) is the same as calling Refresh() after changing the value. /// </summary> public byte b; /// <summary> /// Alpha value 0-255. Set(r,g,b,a) is the same as calling Refresh() after changing the value. /// </summary> public byte a; #endregion #region Public Variables - RGBA (float) colour format /// <summary> /// Red value 0.0-1.0. See also Set(r,g,b,a) /// </summary> public float rF { get; private set; } /// <summary> /// Green value 0.0-1.0. See also Set(r,g,b,a) /// </summary> public float gF { get; private set; } /// <summary> /// Blue value 0.0-1.0. See also Set(r,g,b,a) /// </summary> public float bF { get; private set; } /// <summary> /// Alpha value 0.0-1.0. See also Set(r,g,b,a) /// </summary> public float aF { get; private set; } #endregion #region Public Varaibles - HSV colour format /// <summary> /// Hue /// </summary> public float h { get; private set; } /// <summary> /// Satuation /// </summary> public float s { get; private set; } /// <summary> /// Lightness value /// </summary> public float v { get; private set; } #endregion #region Constructors public SSCColour(byte red, byte green, byte blue, byte alpha) { r = red; g = green; b = blue; a = alpha; rF = r / 255f; gF = g / 255f; bF = b / 255f; aF = a / 255f; float _h, _s, _v; Color.RGBToHSV(new Color(rF, gF, bF, aF), out _h, out _s, out _v); h = _h; s = _s; v = _v; } public SSCColour(float red, float green, float blue, float alpha) { rF = red < 0f ? 0f : red > 1f ? 1f : red; gF = green < 0f ? 0f : green > 1f ? 1f : green; bF = blue < 0f ? 0f : blue > 1f ? 1f : blue; aF = alpha < 0f ? 0f : alpha > 1f ? 1f : alpha; r = (byte)(rF * 255f); g = (byte)(gF * 255f); b = (byte)(bF * 255f); a = (byte)(aF * 255f); float _h, _s, _v; Color.RGBToHSV(new Color(rF, gF, bF, aF), out _h, out _s, out _v); h = _h; s = _s; v = _v; } public SSCColour(Color color) { r = (byte)(color.r * 255f); g = (byte)(color.g * 255f); b = (byte)(color.b * 255f); a = (byte)(color.a * 255f); rF = color.r; gF = color.g; bF = color.b; aF = color.a; float _h, _s, _v; Color.RGBToHSV(new Color(rF, gF, bF, aF), out _h, out _s, out _v); h = _h; s = _s; v = _v; } public SSCColour(Color32 color) { r = color.r; g = color.g; b = color.b; a = color.a; rF = r / 255f; gF = g / 255f; bF = b / 255f; aF = a / 255f; float _h, _s, _v; Color.RGBToHSV(new Color(rF, gF, bF, aF), out _h, out _s, out _v); h = _h; s = _s; v = _v; } #endregion #region Private Methods private void RefreshHSV() { float _h, _s, _v; Color.RGBToHSV(new Color(rF, gF, bF, aF), out _h, out _s, out _v); h = _h; s = _s; v = _v; } /// <summary> /// Refresh only the Color float data. /// Does not include HSV data. /// </summary> private void RefreshFloatData() { rF = r / 255f; gF = g / 255f; bF = b / 255f; aF = a / 255f; } #endregion #region Public Methods /// <summary> /// Call this after updating the (byte) r, g, b or a values /// OR call Set(red, green, blue, alpha). /// NOTE: Updating the HSV values will create a temporary Color object. /// </summary> public void Refresh() { RefreshFloatData(); RefreshHSV(); } /// <summary> /// Set the byte colour values (0-255) and then refresh all other colour values. /// NOTE: Updating the HSV values will create a temporary Color object. /// Optionally do not refresh the HSV data /// </summary> /// <param name="red"></param> /// <param name="green"></param> /// <param name="blue"></param> /// <param name="alpha"></param> public void Set(byte red, byte green, byte blue, byte alpha, bool refreshHSV = true) { r = red; g = green; b = blue; a = alpha; if (refreshHSV) { Refresh(); } else { RefreshFloatData(); } } /// <summary> /// Set the float colour values (0.0-1.0) and then refresh all other colour values. /// NOTE: Updating the HSV values will create a temporary Color object. /// Optionally do not refresh the HSV data. /// </summary> /// <param name="red"></param> /// <param name="green"></param> /// <param name="blue"></param> /// <param name="alpha"></param> public void Set(float red, float green, float blue, float alpha, bool refreshHSV = true) { rF = red < 0f ? 0f : red > 1f ? 1f : red; gF = green < 0f ? 0f : green > 1f ? 1f : green; bF = blue < 0f ? 0f : blue > 1f ? 1f : blue; aF = alpha < 0f ? 0f : alpha > 1f ? 1f : alpha; // We should always update the core byte rgba data r = (byte)(rF * 255f); g = (byte)(gF * 255f); b = (byte)(bF * 255f); a = (byte)(aF * 255f); if (refreshHSV) { RefreshHSV(); } } /// <summary> /// Get a new Color struct by applying a brightness factor (0.0-1.0) to the existing colour. /// </summary> /// <param name="brightness"></param> /// <returns></returns> public Color GetColorWithBrightness(float brightness) { // Modify the HSV lightness Value by the brightness level. float newV = v * (brightness < 0f ? 0f : brightness > 1f ? 1f : brightness); return Color.HSVToRGB(h, s, newV); } /// <summary> /// Get a new Color struct by applying a brightness factor (0.0-1.0) to the existing colour. /// Then apply the fade to the alpha channel. /// </summary> /// <param name="brightness"></param> /// <param name="fadeValue"></param> /// <returns></returns> public Color GetColorWithFadedBrightness(float brightness, float fadeValue) { // Modify the HSV lightness Value by the brightness level. float newV = v * (brightness < 0f ? 0f : brightness > 1f ? 1f : brightness); Color _colour = Color.HSVToRGB(h, s, newV); _colour.a = fadeValue * aF; return _colour; } #endregion #region Implicit Operators public static implicit operator SSCColour(Color c) { return new SSCColour(c); } public static implicit operator SSCColour(Color32 c) { return new SSCColour(c); } #endregion } }