It would be nice if we can get color by its name (string).
A good example would be scripting. You get the color from a file as a string and you have to convert it to Color. Right now the only way to achieve this is to use Reflection which is both slow and error-prone (you risk getting a non-color property for instance, so you have to check) or make a library class (basically a dictionary) and enter all of them on your own. The second solution is fine if you want to support only a handful of colors, but it will become a real chore to input if you want to have all 140 of them.
I have a few ideas of how to implement this:
Example:
```c#
///
/// Colors library
///
private static Dictionary
. . . .
/// <summary>
/// Transparent color (R:0,G:0,B:0,A:0).
/// </summary>
public static Color Transparent
{
get { return Colors["transparent"]; }
}
. . . .
/// <summary>
/// Get color by name.
/// </summary>
public static Color Parse(string name)
{
name = name.ToLower();
if (Colors.Contains(name))
{
return Colors[name];
}
else
{
new ArgumentException("Color not found.");
}
}
2. The same as option 1 but the color properties have setters which populate the dictionary beside setting the property's field. This way it still have the original performance when getting color by its property, but the code is uglier: a lot of copy/paste and the setter have hidden behavior (adding a value to a dictionary). But I think it is still the better solution since the setter is private.
Example:
```c#
/// <summary>
/// Colors library
/// </summary>
private static Dictionary<string, Color> Colors = new Dictionary<string, Color>();
. . . .
private static Color transparent;
/// <summary>
/// Transparent color (R:0,G:0,B:0,A:0).
/// </summary>
public static Color Transparent
{
get { return transparent; }
private set
{
transparent = value;
Colors["transparent"] = value;
}
}
. . . .
/// <summary>
/// Get color by name.
/// </summary>
public static Color Parse(string name)
{
name = name.ToLower();
if (Colors.Contains(name))
{
return Colors[name];
}
else
{
new ArgumentException("Color not found.");
}
}
If the admins give it a go, I can implement one of the options (preferably the second) and make a pull request.
The performance costs eliminate option 1. Transforming the property getters to access a dictionary will negatively affect every call that uses a Color property.
The Color properties are currently the most performant they can be in .NET. We don't want to see them changed. The library already has all the Color type information in reflection metadata, so we don't want to use the extra memory to duplicate that information. MonoGame is also used on some memory-constrained systems, so this is not something that we would be adding to MonoGame itself.
I think the best option for you will be to make a helper library that creates a Dictionary<string, Color> and at initialization it uses reflection to grab all public static properties in Color that return a Color type and add them to the dictionary. Reflection is not error-prone if you validate the results, i.e. get static public properties that return a Color type.
make a helper library that creates a Dictionary
and at initialization it uses reflection to grab all public static properties in Color that return a Color type
If you don't want to use reflection you can do this once and print out the result nicely for adding them to a dictionary and copy-paste that into your code i.e.
List<String> colors = ... // this is a list of all color names, gotten through reflection
foreach (var cname in colors)
{
Console.WriteLine($"ColorDict.Add({cname.ToLower()}, Color.{cname})");
}
Hmm, is this what C++ template programming is like? :p
Hmm, is this what C++ template programming is like? :p
It's worse. Much, much worse.
It would be nice if we can get color by its name (string).
@dellis1972 @KonajuGames @Jjagg - First off... do we agree we want this feature?
I think it could be fine and useful for some people, but ideally we would avoid sticking this huge dictionary into the main Color.cs.
Maybe we should make Color partial and moving all the named colors to a separate .cs file. Thoughts?
I don't think we need it in MonoGame. It's an extended feature that hasn't really been called for before (this is the first time I've seen it asked for), and would belong in a separate helper library that people could use if they wanted this.
I also don't think MonoGame needs this feature.
On a side note I did need to translate string to color in one of my games, I did it using reflection:
```c#
private Color GetColor(string color)
{
var props = typeof(Color).GetProperties();
foreach (var p in props)
if (p.Name.ToLower() == color.ToLower())
return (Color)p.GetValue(null, null);
// Default color if the color was not found
return Color.Transparent;
}
```
In xna if i remember right they were Enums so you could just do something like this.
string m = Enum.GetName(typeof(MyEnumClass), value);
I mean i guess you can reflect it and check for hastags for those r g b properties or string compare on known properties you don't want to use and disregaurd them.
Im not sure how this will help much though all that getting the color names will do, is allow you to save them to file. I mean if anyone wants to add in there own scripted colors to read from that file they need to write them to file anyways so you have to make new colors from the file data anyways.
Id probably just copy paste them right to a text file and start working on parsing them into a dictionary as is and probably leave that as the save load format itself.
This is something that could be done via reflection by the app that wants it. It is not something that we should add into the base MonoGame library.
Most helpful comment
I don't think we need it in MonoGame. It's an extended feature that hasn't really been called for before (this is the first time I've seen it asked for), and would belong in a separate helper library that people could use if they wanted this.