/Utilities/Datatypes/Color.cs
C# | 988 lines | 560 code | 89 blank | 339 comment | 13 complexity | 3ca85ffd6206a7af1216ab0c8d41b1c8 MD5 | raw file
Possible License(s): Apache-2.0
- using System;
- using System.ComponentModel;
- using System.Diagnostics;
- using System.IO;
- using System.Runtime.InteropServices;
- using Delta.Utilities.Helpers;
- using NUnit.Framework;
-
-
- namespace Delta.Utilities.Datatypes
- {
- /// <summary>
- /// Color datatype, originally contained 4 floats for all the color
- /// components. Now we still got those, but as properties because the
- /// internal format is a packed uint RGBA value (4 bytes instead of 16):
- /// R for red, G for green, B for blue and A for alpha, all between 0 and 1.
- /// </summary>
- /// <remarks>
- /// The change to uint (and thanks to unions to the 4 byte values RedByte,
- /// GreenByte, BlueByte, and AlphaByte) was done to increase rendering
- /// performance. Especially on mobile platforms bandwidth is key and
- /// reducing the amount of data send to the vertex and fragment shaders
- /// can speed up rendering a lot (e.g. 36 bytes per vertex lead to max. 33
- /// fps on the iPad, while 16 bytes (2 floats for position, 2 ushorts for UV
- /// and 4 bytes for color) is almost 3 times faster!
- /// Here can find a lot of "color codes": System.Drawing.Color
- /// Use Reflector or the MSDN documentation to learn more.
- /// http://www.htmlhelp.com/cgi-bin/color.cgi
- /// http://www.pamramsey.com/colors.htm
- /// </remarks>
- [Serializable]
- [StructLayout(LayoutKind.Explicit)]
- [DebuggerDisplay("Color(R={R}, G={G}, B={B}, A={A})")]
- [Description("Expand to edit this Color")]
- [TypeConverter(typeof(ExpandableObjectConverter))]
- public struct Color : ISaveLoadBinary, IEquatable<Color>
- {
- #region Constants
- /// <summary>
- /// Represents the size in bytes of that R,G,B,A Color (just 4 bytes).
- /// </summary>
- public const int DataSize = 4;
-
- /// <summary>
- /// Strings of the known color names that can be passed into FromColor!
- /// Note: These names are not used in ToString, but they may be used for
- /// UI, ComboBoxes, DropDown lists, etc.
- /// </summary>
- public static readonly string[] KnownColorNames = new string[]
- {
- "Black",
- "BlackHalfTransparent",
- "Grey",
- "White",
- "WhiteHalfTransparent",
- "Transparent",
- "Red",
- "Green",
- "Blue",
- "Yellow",
- "CornflowerBlue",
- "DarkBlue",
- "Purple",
- "Cyan",
- "Teal",
- "Orange",
- "Brown",
- "Gold",
- "LightGrey",
- "LightRed",
- "LightGreen",
- "LightPurple",
- "LightBlue",
- "LightTeal",
- "LightOrange",
- "DarkGrey"
- };
-
- /// <summary>
- /// Unused color, all values including alpha are set to 0. Usually used to
- /// indicate that a color is unused, e.g. if Graphic.Instances.ClearColor
- /// is set to Unused, we won't clear the backbuffer with the ClearColor
- /// (which is a bit faster for games that do not need to have the
- /// backbuffer cleared). Note that we usually have premultiplied alpha
- /// so it is faster to check if Alpha == 0 to see if a color is unused!
- /// </summary>
- public static readonly Color Unused =
- new Color(0.0f, 0.0f, 0.0f, 0.0f);
-
- /// <summary>
- /// Transparent color (0, 0, 0, 0), same as Unused.
- /// </summary>
- public static readonly Color Transparent = Unused;
-
- /// <summary>
- /// Black color (0, 0, 0), but has alpha (1), use Unused for (0, 0, 0, 0)
- /// </summary>
- public static readonly Color Black =
- new Color(0.0f, 0.0f, 0.0f);
-
- /// <summary>
- /// Black color (0, 0, 0) but with an alpha value of 0.5
- /// </summary>
- public static readonly Color BlackHalfTransparent =
- new Color(Black, 0.5f);
-
- /// <summary>
- /// Grey color (0.5, 0.5, 0.5) = (127, 127, 127)
- /// http://en.wikipedia.org/wiki/Grey
- /// </summary>
- public static readonly Color Grey =
- new Color(0.5f, 0.5f, 0.5f);
-
- /// <summary>
- /// White color (1, 1, 1)
- /// </summary>
- public static readonly Color White =
- new Color(1.0f, 1.0f, 1.0f);
-
- /// <summary>
- /// White color (1, 1, 1) but with an alpha value of 0.5
- /// </summary>
- public static readonly Color WhiteHalfTransparent =
- new Color(White, 0.5f);
-
- /// <summary>
- /// Red color (1, 0, 0)
- /// </summary>
- public static readonly Color Red =
- new Color(1.0f, 0.0f, 0.0f);
-
- /// <summary>
- /// Green color (0, 1, 0)
- /// </summary>
- public static readonly Color Green =
- new Color(0.0f, 1.0f, 0.0f);
-
- /// <summary>
- /// Blue color (0, 0, 1)
- /// </summary>
- public static readonly Color Blue =
- new Color(0.0f, 0.0f, 1.0f);
-
- /// <summary>
- /// Yellow color (1, 1, 0)
- /// </summary>
- public static readonly Color Yellow =
- new Color(1.0f, 1.0f, 0.0f);
-
- /// <summary>
- /// CornflowerBlue color (0.39, 0.58, 0.93)
- /// </summary>
- public static readonly Color CornflowerBlue =
- new Color(0.392f, 0.584f, 0.93f);
-
- /// <summary>
- /// Dark blue color (0.19, 0.28, 0.43)
- /// </summary>
- public static readonly Color DarkBlue =
- new Color(0.192f, 0.284f, 0.43f);
-
- /// <summary>
- /// Purple color (0.5, 0, 0.5)
- /// </summary>
- public static readonly Color Purple =
- new Color(0.5f, 0, 0.5f);
-
- /// <summary>
- /// Cyan color (0.0, 1.0, 1.0)
- /// </summary>
- public static readonly Color Cyan =
- new Color(0.0f, 1.0f, 1.0f);
-
- /// <summary>
- /// Teal color (0, 0.5, 0.5)
- /// </summary>
- public static readonly Color Teal =
- new Color(0, 0.5f, 0.5f);
-
- /// <summary>
- /// Orange color (1, 0.65, 0)
- /// </summary>
- public static readonly Color Orange =
- new Color(1, 0.65f, 0);
-
- /// <summary>
- /// Brown color (0.65, 0.16, 0.16)
- /// </summary>
- public static readonly Color Brown =
- new Color(0.65f, 0.165f, 0.165f);
-
- /// <summary>
- /// Gold color (1.0, 0.84, 0.0)
- /// </summary>
- public static readonly Color Gold =
- new Color(1.0f, 0.843f, 0.0f);
-
- /// <summary>
- /// Light grey color (0.65, 0.65, 0.65) = (165, 165, 165)
- /// http://en.wikipedia.org/wiki/Grey
- /// </summary>
- public static readonly Color LightGrey =
- new Color(0.65f, 0.65f, 0.65f);
-
- /// <summary>
- /// LightRed color (1, 0.25, 0.25)
- /// </summary>
- public static readonly Color LightRed =
- new Color(1.0f, 0.25f, 0.25f);
-
- /// <summary>
- /// LightGreen color (0.25, 1, 0.25)
- /// </summary>
- public static readonly Color LightGreen =
- new Color(0.25f, 1.0f, 0.25f);
-
- /// <summary>
- /// LightPurple color (0.576, 0.44, 0.86)
- /// </summary>
- public static readonly Color LightPurple =
- new Color(0.576f, 0.44f, 0.86f);
-
- /// <summary>
- /// LightBlue color (0.65f, 0.795f, 1.0f)
- /// </summary>
- public static readonly Color LightBlue =
- new Color(0.65f, 0.795f, 1.0f);
-
- /// <summary>
- /// LightTeal color (0.25, 0.8, 0.8)
- /// </summary>
- public static readonly Color LightTeal =
- new Color(0.25f, 0.8f, 0.8f);
-
- /// <summary>
- /// LightOrange color (1, 0.8, 0.25)
- /// </summary>
- public static readonly Color LightOrange =
- new Color(1, 0.8f, 0.25f);
-
- /// <summary>
- /// Dark grey color (0.35, 0.35, 0.35) = (89, 89, 89)
- /// http://en.wikipedia.org/wiki/Grey
- /// </summary>
- public static readonly Color DarkGrey =
- new Color(0.35f, 0.35f, 0.35f);
- #endregion
-
- #region FromString (Static)
- /// <summary>
- /// Convert a string to a Color. The expected format is
- /// (r.r, g.g, b.b, a.a), e.g. (0.2, 0.3, 0.4, 1.0). Alpha is optional.
- /// </summary>
- /// <param name="colorString">String containing the color values</param>
- /// <returns>
- /// Color from the colorString or White if no valid string was used.
- /// </returns>
- public static Color FromString(string colorString)
- {
- // First remove the brackets and split the string up into seperate values
- colorString = colorString.Replace("(", "");
- colorString = colorString.Replace(")", "");
- string[] colorStrings = colorString.Split(
- new[]
- {
- ',', ' '
- },
- StringSplitOptions.RemoveEmptyEntries);
-
- // Then check if the length is 4 for 4 values and return the new vector.
- // If the length is not 4 than return Vector.Zero.
- if (colorStrings.Length == 4)
- {
- return new Color(
- colorStrings[0].FromInvariantString(1.0f),
- colorStrings[1].FromInvariantString(1.0f),
- colorStrings[2].FromInvariantString(1.0f),
- colorStrings[3].FromInvariantString(1.0f));
- }
- if (colorStrings.Length == 3)
- {
- return new Color(
- colorStrings[0].FromInvariantString(1.0f),
- colorStrings[1].FromInvariantString(1.0f),
- colorStrings[2].FromInvariantString(1.0f));
- }
-
- // Check if it is one of the supported color names
- switch (colorString)
- {
- case "Black":
- return Black;
- case "BlackHalfTransparent":
- return BlackHalfTransparent;
- case "Grey":
- return Grey;
- case "White":
- return White;
- case "WhiteHalfTransparent":
- return WhiteHalfTransparent;
- case "Transparent":
- return Transparent;
- case "Red":
- return Red;
- case "Green":
- return Green;
- case "Blue":
- return Blue;
- case "Yellow":
- return Yellow;
- case "CornflowerBlue":
- return CornflowerBlue;
- case "DarkBlue":
- return DarkBlue;
- case "Purple":
- return Purple;
- case "Cyan":
- return Cyan;
- case "Teal":
- return Teal;
- case "Orange":
- return Orange;
- case "Brown":
- return Brown;
- case "Gold":
- return Gold;
- case "LightGrey":
- return LightGrey;
- case "LightRed":
- return LightRed;
- case "LightGreen":
- return LightGreen;
- case "LightPurple":
- return LightPurple;
- case "LightBlue":
- return LightBlue;
- case "LightTeal":
- return LightTeal;
- case "LightOrange":
- return LightOrange;
- case "DarkGrey":
- return DarkGrey;
- }
-
- // Not found? Then just return White, the default for loading colors.
- return White;
- }
- #endregion
-
- #region Lerp (Static)
- /// <summary>
- /// Lerp (interpolate) between to colors based on the given amount between
- /// 0.0 and 1.0. If the amount value is closer to 0, the output color will
- /// be more like c1, otherwise it will be closer to c2.
- /// </summary>
- /// <param name="c1">Color 1</param>
- /// <param name="c2">Color 2</param>
- /// <param name="amount">Amount for interpolation</param>
- /// <returns>Color in between c1 and c2</returns>
- public static Color Lerp(Color c1, Color c2, float amount)
- {
- return new Color(
- MathHelper.Lerp(c1.R, c2.R, amount),
- MathHelper.Lerp(c1.G, c2.G, amount),
- MathHelper.Lerp(c1.B, c2.B, amount),
- MathHelper.Lerp(c1.A, c2.A, amount));
- }
- #endregion
-
- #region Random (Static)
- /// <summary>
- /// Returns a random color (0-1, 0-1, 0-1)
- /// </summary>
- public static Color Random
- {
- get
- {
- return new Color(
- RandomHelper.RandomFloat(0, 1),
- RandomHelper.RandomFloat(0, 1),
- RandomHelper.RandomFloat(0, 1));
- }
- }
- #endregion
-
- #region SolidColors (Static)
- /// <summary>
- /// List of 15 predefined solid colors, which look better than random
- /// colors if used for profiling or effects (Red, Blue,
- /// Green, Yellow, Purple, Teal, Orange, White, Brown, Gray,
- /// CornflowerBlue, Gold, LightGreen, LightRed, LightPurple).
- /// </summary>
- public static Color[] SolidColors = new[]
- {
- Red,
- Blue,
- Green,
- Yellow,
- Purple,
- Teal,
- Orange,
- White,
- LightGreen,
- LightRed,
- LightPurple,
- LightTeal,
- LightBlue,
- LightOrange,
- Brown,
- LightGrey,
- CornflowerBlue,
- Gold,
- };
- #endregion
-
- #region LightColors (Static)
- /// <summary>
- /// List of 15 predefined solid colors, which look better than random
- /// colors if used for profiling or effects (Red, Blue,
- /// Green, Yellow, Purple, Teal, Orange, White, Brown, Gray,
- /// CornflowerBlue, Gold, LightGreen, LightRed, LightPurple).
- /// </summary>
- public static Color[] LightColors = new[]
- {
- White,
- LightRed,
- CornflowerBlue,
- LightBlue,
- LightGreen,
- LightOrange,
- };
- #endregion
-
- #region NextSolidColor (Static)
- /// <summary>
- /// Returns the next solid color from a predefined array (Red, Blue,
- /// Green, Yellow, Purple, Teal, Orange, White, Brown, Gray,
- /// CornflowerBlue, Gold, LightGreen, LightRed, LightPurple).
- /// </summary>
- public static Color NextSolidColor
- {
- get
- {
- return SolidColors[(SolidColorNumber++) % SolidColors.Length];
- }
- }
- #endregion
-
- #region NextLightColor (Static)
- /// <summary>
- /// Returns the next light color from a predefined array (White,
- /// LightRed, CornflowerBlue, LightBlue, LightGreen, LightOrange).
- /// </summary>
- public static Color NextLightColor
- {
- get
- {
- return LightColors[(LightColorNumber++) % LightColors.Length];
- }
- }
- #endregion
-
- #region Framework Union Defines (Public)
- #endregion
-
- #region PackedRGBA (Public)
- /// <summary>
- /// This color as 4 packed bytes in an uint value. This is the same format
- /// used for OpenGL colors, xna colors and RGBA values in general :)
- /// </summary>
- [FieldOffset(0)]
- public uint PackedRGBA;
- #endregion
-
- #region RedByte (Public)
- /// <summary>
- /// Red byte in a range of [0,255]. Use the property R for a float [0,1].
- /// </summary>
- [FieldOffset(0)]
- public byte RedByte;
- #endregion
-
- #region GreenByte (Public)
- /// <summary>
- /// Green byte in a range of [0,255]. Use the property G for a float [0,1].
- /// </summary>
- [FieldOffset(1)]
- public byte GreenByte;
- #endregion
-
- #region BlueByte (Public)
- /// <summary>
- /// Blue byte in a range of [0,255]. Use the property B for a float [0,1].
- /// </summary>
- [FieldOffset(2)]
- public byte BlueByte;
- #endregion
-
- #region AlphaByte (Public)
- /// <summary>
- /// Alpha channel byte in a range of [0,255]. Use the property B for a
- /// float [0,1]. 0=transparent, 255 (or A=1)=fully visible. Note: Like
- /// xna 4.0 we use premultiplied alpha by default, which makes
- /// multiplying colors a little easier (just newAlpha*Color).
- /// </summary>
- [FieldOffset(3)]
- public byte AlphaByte;
- #endregion
-
- #region R (Public)
- /// <summary>
- /// Red channel (in a range of [0,1], caller has to make sure not to set
- /// this to any crazy value). Set to the RedByte value of this color.
- /// </summary>
- [Browsable(true)]
- [DisplayName("Red")]
- public float R
- {
- get
- {
- return RedByte / 255.0f;
- }
- set
- {
- RedByte = (byte)(value * 255.0f);
- }
- }
- #endregion
-
- #region G (Public)
- /// <summary>
- /// Green channel (in a range of [0,1]). Set to the GreenByte value of
- /// this color.
- /// </summary>
- [Browsable(true)]
- [DisplayName("Green")]
- public float G
- {
- get
- {
- return GreenByte / 255.0f;
- }
- set
- {
- GreenByte = (byte)(value * 255.0f);
- }
- }
- #endregion
-
- #region B (Public)
- /// <summary>
- /// Blue channel (in a range of [0,1]). Set to the BlueByte value of this
- /// color.
- /// </summary>
- [Browsable(true)]
- [DisplayName("Blue")]
- public float B
- {
- get
- {
- return BlueByte / 255.0f;
- }
- set
- {
- BlueByte = (byte)(value * 255.0f);
- }
- }
- #endregion
-
- #region A (Public)
- /// <summary>
- /// Alpha channel (in a range of [0,1]). 0=transparent, 1=fully visible.
- /// Note: Like XNA 4.0 we use premultiplied alpha by default, which makes
- /// multiplying colors a little easier (just newAlpha*Color). Set to the
- /// AlphaByte value of this color.
- /// </summary>
- [Browsable(true)]
- [DisplayName("Alpha")]
- public float A
- {
- get
- {
- return AlphaByte / 255.0f;
- }
- set
- {
- AlphaByte = (byte)(value * 255.0f);
- }
- }
- #endregion
-
- #region Private
-
- #region SolidColorNumber (Private)
- /// <summary>
- /// Current index for NextSolidColor, will increase each call.
- /// </summary>
- private static int SolidColorNumber;
- #endregion
-
- #region LightColorNumber (Private)
- /// <summary>
- /// Current index for NextLightColor, will increase each call.
- /// </summary>
- private static int LightColorNumber;
- #endregion
-
- #endregion
-
- #region Constructors
- /// <summary>
- /// Creates a color with an alpha of 1.0
- /// </summary>
- /// <param name="setBaseColor">Sets the "base color" RGB</param>
- /// <param name="setA">Set alpha channel in a range of [0,1]</param>
- public Color(Color setBaseColor, float setA)
- : this(setBaseColor.R, setBaseColor.G, setBaseColor.B, setA)
- {
- }
-
- /// <summary>
- /// Creates a color with an alpha of 1.0
- /// </summary>
- /// <param name="setR">Set red channel in a range of [0,1]</param>
- /// <param name="setG">Set green channel in a range of [0,1]</param>
- /// <param name="setB">Set blue channel in a range of [0,1]</param>
- public Color(float setR, float setG, float setB)
- : this(setR, setG, setB, 1.0f)
- {
- }
-
- /// <summary>
- /// Creates a color with values for R, G, B, A.
- /// </summary>
- /// <param name="setR">Set red channel in a range of [0,1]</param>
- /// <param name="setG">Set green channel in a range of [0,1]</param>
- /// <param name="setB">Set blue channel in a range of [0,1]</param>
- /// <param name="setA">Set alpha channel in a range of [0,1]</param>
- public Color(float setR, float setG, float setB, float setA)
- // Needed now because of PackedRGBA, XNA and SlimDx unions
- : this()
- {
- // If any value is above 10 interpret it as a byte value, not a float!
- // This is basically not allowed in the Delta Engine, but if any byte
- // values come into this method (e.g. via FromString), fix the issue.
- if (setR > 10)
- {
- setR = setR / 255.0f;
- }
- if (setG > 10)
- {
- setG = setG / 255.0f;
- }
- if (setB > 10)
- {
- setB = setB / 255.0f;
- }
- if (setA > 10)
- {
- setA = setA / 255.0f;
- }
-
- // Note: Nothing is clamped here, make sure the input does not go out of
- // range at the caller level.
- RedByte = (byte)(setR * 255.0f);
- GreenByte = (byte)(setG * 255.0f);
- BlueByte = (byte)(setB * 255.0f);
- AlphaByte = (byte)(setA * 255.0f);
- }
-
- /// <summary>
- /// Creates a color from the byte RGB values in the range [0-255] for each
- /// channel.
- /// </summary>
- /// <param name="setR">The red value in the range [0-255].</param>
- /// <param name="setG">The green value in the range [0-255].</param>
- /// <param name="setB">The blue value in the range [0-255].</param>
- public Color(byte setR, byte setG, byte setB)
- // Needed now because of PackedRGBA, XNA and SlimDx unions
- : this()
- {
- RedByte = setR;
- GreenByte = setG;
- BlueByte = setB;
- AlphaByte = 255;
- }
-
- /// <summary>
- /// Creates a color from the byte RGBA values in the range [0-255] for each
- /// channel.
- /// </summary>
- /// <param name="setR">The red value in the range [0-255].</param>
- /// <param name="setG">The green value in the range [0-255].</param>
- /// <param name="setB">The blue value in the range [0-255].</param>
- /// <param name="setA">The alpha value in the range [0-255].</param>
- public Color(byte setR, byte setG, byte setB, byte setA)
- // Needed now because of PackedRGBA, XNA and SlimDx unions
- : this()
- {
- RedByte = setR;
- GreenByte = setG;
- BlueByte = setB;
- AlphaByte = setA;
- }
-
- /// <summary>
- /// Create color from binary data stream (e.g. to load vertices or
- /// material data).
- /// </summary>
- /// <param name="setReader">setReader</param>
- public Color(BinaryReader setReader)
- : this()
- {
- Load(setReader);
- }
- #endregion
-
- #region IEquatable<Color> Members
- /// <summary>
- /// Equals
- /// </summary>
- /// <param name="other">Other</param>
- /// <returns>Value indicating the equality of two colors</returns>
- public bool Equals(Color other)
- {
- return PackedRGBA == other.PackedRGBA;
- }
- #endregion
-
- #region ISaveLoadBinary Members
- /// <summary>
- /// Load the color values from a stream (4 bytes).
- /// </summary>
- /// <param name="reader">The stream that will be used.</param>
- public void Load(BinaryReader reader)
- {
- PackedRGBA = reader.ReadUInt32();
- }
-
- /// <summary>
- /// Saves the color out to a stream (4 bytes).
- /// </summary>
- /// <param name="writer">The stream that will be used.</param>
- public void Save(BinaryWriter writer)
- {
- writer.Write(PackedRGBA);
- }
- #endregion
-
- #region op_Multiply (Operator)
- /// <summary>
- /// Multiply operator to multiply all color values with a number.
- /// </summary>
- /// <param name="c1">Color to multiply</param>
- /// <param name="brightScale">Bright scale</param>
- /// <returns>Color</returns>
- public static Color operator *(Color c1, float brightScale)
- {
- return new Color(
- c1.R * brightScale,
- c1.G * brightScale,
- c1.B * brightScale,
- c1.A * brightScale);
- }
-
- /// <summary>
- /// Multiply operator to multiply two colors (each value will be multiplied)
- /// </summary>
- /// <param name="c1">Color 1</param>
- /// <param name="c2">Color 2</param>
- /// <returns>Color</returns>
- public static Color operator *(Color c1, Color c2)
- {
- return new Color(c1.R * c2.R, c1.G * c2.G, c1.B * c2.B, c1.A * c2.A);
- }
- #endregion
-
- #region op_Equality (Operator)
- /// <summary>
- /// Check for equality
- /// </summary>
- /// <param name="value1">Value 1</param>
- /// <param name="value2">Value 2</param>
- /// <returns>True if the values are equal, false otherwise</returns>
- public static bool operator ==(Color value1, Color value2)
- {
- return value1.PackedRGBA == value2.PackedRGBA;
- }
- #endregion
-
- #region op_Inequality (Operator)
- /// <summary>
- /// Check for inequality
- /// </summary>
- /// <param name="value1">Value 1</param>
- /// <param name="value2">Value 2</param>
- /// <returns>True if the values are not equal</returns>
- public static bool operator !=(Color value1, Color value2)
- {
- return value1.PackedRGBA != value2.PackedRGBA;
- }
- #endregion
-
- #region GetHashCode (Public)
- /// <summary>
- /// Get hash code
- /// </summary>
- /// <returns>hash code</returns>
- public override int GetHashCode()
- {
- return PackedRGBA.GetHashCode();
- }
- #endregion
-
- #region Equals (Public)
- /// <summary>
- /// Equals
- /// </summary>
- /// <param name="obj">Object to compare to</param>
- /// <returns>True if the values are equal, false otherwise</returns>
- public override bool Equals(object obj)
- {
- if (obj is Color)
- {
- return Equals((Color)obj);
- }
- return base.Equals(obj);
- }
- #endregion
-
- #region ToString (Public)
- /// <summary>
- /// To string
- /// </summary>
- /// <returns>string</returns>
- public override string ToString()
- {
- //return String.Format("({0}, {1}, {2}, {3})", R, G, B, A);
- return ToString("(", ")");
- }
-
- /// <summary>
- /// To string
- /// </summary>
- /// <param name="closeBrace">closeBrace</param>
- /// <param name="openBrace">openBrace</param>
- /// <returns>string</returns>
- public string ToString(string openBrace, string closeBrace)
- {
- return openBrace + R.ToInvariantString("0.00") +
- ", " + G.ToInvariantString("0.00") +
- ", " + B.ToInvariantString("0.00") +
- ", " + A.ToInvariantString("0.00") + closeBrace;
- }
- #endregion
-
- /// <summary>
- /// Tests
- /// </summary>
- internal class ColorTests
- {
- #region Constructor (Static)
- /// <summary>
- /// FromIntRGB
- /// </summary>
- [Test]
- public static void Constructor()
- {
- Color testColor = new Color(255, 0, 127, 255);
- Assert.NearlyEqual(testColor.R, 1f);
- Assert.NearlyEqual(testColor.G, 0f);
- Assert.NearlyEqual(testColor.B, 0.498f);
- Assert.NearlyEqual(testColor.A, 1f);
- }
- #endregion
-
- #region SizeOf (Static)
- /// <summary>
- /// Checks if the size of Point is exactly 8 bytes (2 floats: X and Y)
- /// </summary>
- [Test]
- public static void SizeOf()
- {
- // Color consists of 4 bytes: R, G, B, and A
- Assert.Equal(4, Marshal.SizeOf(typeof(Color)));
- }
- #endregion
-
- #region ColorCompare (Static)
- /// <summary>
- /// Color compare
- /// </summary>
- [Test]
- public static void ColorCompare()
- {
- Color testColor = Black;
-
- Assert.NotEqual(White, testColor);
- Assert.NotEqual(new Color(0, 1, 0), testColor);
-
- Assert.Equal(new Color(0, 0, 0), testColor);
- Assert.Equal(Black, testColor);
- Assert.Equal(testColor, testColor);
- }
- #endregion
-
- #region SaveAndLoad (Static)
- /// <summary>
- /// Save
- /// </summary>
- [Test]
- public static void SaveAndLoad()
- {
- Color color = Yellow;
-
- #region Saving
- MemoryStream memHandle = new MemoryStream();
- Assert.Equal(0, memHandle.Position);
-
- BinaryWriter writer = new BinaryWriter(memHandle);
- // save all the current data
- color.Save(writer);
-
- // and finally check (for saving) if the file was written correctly
- Assert.NotEqual(0, memHandle.Length);
- #endregion
-
- #region Loading
- // then we create an "empty" material
- Color loadColor = Unused;
- memHandle.Position = 0;
-
- // which we use to load the material values from the the file
- // Note: The using closes the file access too
- BinaryReader reader = new BinaryReader(memHandle);
- loadColor.Load(reader);
-
- // before we finally check if everything is loaded correctly
- Assert.Equal(color, loadColor);
- #endregion
-
- writer.Close();
- reader.Close();
- memHandle.Close();
- }
- #endregion
-
- #region Multiplication (Static)
- /// <summary>
- /// Multiplication
- /// </summary>
- [Test]
- public static void Multiplication()
- {
- Assert.Equal(Yellow, Yellow * White);
- Assert.Equal(new Color(1, 1, 0, 0.5f),
- Yellow * new Color(1, 1, 1, 0.5f));
-
- Assert.Equal(Black, Red * Green);
- }
- #endregion
-
- #region FromString (Static)
- /// <summary>
- /// FromString
- /// </summary>
- [Test]
- public static void FromString()
- {
- Color testColor = Color.FromString("(0.0, 1.0, 0.0, 0.5)");
- Assert.Equal(testColor, new Color(0f, 1f, 0f, 0.5f));
- }
- #endregion
-
- #region Equality
- /// <summary>
- /// Equality
- /// </summary>
- [Test]
- public void Equality()
- {
- Assert.Equal(new Color(1f, 1f, 0f, 1f), Yellow);
- Assert.NotEqual(White, Yellow);
- }
- #endregion
- }
- }
- }