unity/Assets/Scripts/Utils/Flags.cs (145 lines of code) (raw):

using System.Collections; using System.Collections.Generic; using UnityEngine; using System; using System.IO; using System.Reflection; // This utility allows properties (class member variables) to be configured from commandline and // property files. Use the Flag attribute to mark configurable variables. This utility depends // on runtime reflexive introspection. [AttributeUsage(AttributeTargets.Field)] public class Flag : Attribute { } public class Flags { static private Dictionary<string, object> object_flags_ = new Dictionary<string, object>(); static private Dictionary<string, string> string_flags_ = new Dictionary<string, string>(); static Flags() { string[] args = System.Environment.GetCommandLineArgs(); foreach (string arg in args) { string[] split = arg.Split(new char[] { '=' }, 2, StringSplitOptions.RemoveEmptyEntries); if (split.Length == 1) { string bool_flag = split[0]; if (!bool_flag.StartsWith("--", StringComparison.Ordinal)) { continue; } bool_flag = bool_flag.Substring(2); AddBoolFlag(bool_flag, true); } else if (split.Length == 2) { string key = split[0]; string value = split[1]; if (!key.StartsWith("--", StringComparison.Ordinal)) { continue; } key = key.Substring(2); if ("flags.file".Equals(key)) { LoadFlagsFromFile(value); } else { string_flags_[key] = value; } } } } private static void LoadFlagsFromFile(string file_name) { Logger.Info("Flags::LoadFlagsFromFile::Reading flag file: {0}", file_name); StreamReader reader = new StreamReader(file_name); string line = ""; while ((line = reader.ReadLine()) != null) { string[] split = line.Split(new char[] { ' ' }, 3, StringSplitOptions.RemoveEmptyEntries); if (split.Length == 2) { string flag_type = split[0]; string key = split[1]; if (typeof(bool).Name.Equals(flag_type)) { AddBoolFlag(key, true); } else if (typeof(string).Name.Equals(flag_type)) { string_flags_[key] = ""; } } else if (split.Length == 3) { string flag_type = split[0]; string key = split[1]; string value = split[2]; if (typeof(bool).Name.Equals(flag_type)) { AddBoolFlag(key, bool.Parse(value)); } else if (typeof(int).Name.Equals(flag_type)) { object_flags_[key] = int.Parse(value); } else if (typeof(float).Name.Equals(flag_type)) { object_flags_[key] = float.Parse(value); } else if (typeof(string).Name.Equals(flag_type)) { object_flags_[key] = value; string_flags_[key] = value; } else { string_flags_[key] = value; } } } reader.Close(); } static private void AddBoolFlag(string key, bool value) { if (key.StartsWith("no", System.StringComparison.Ordinal)) { object_flags_[key.Substring(2)] = !value; } else { object_flags_[key] = value; } } static public object Get<T>(string name, T default_value) { if (string_flags_.ContainsKey(name)) { string value = string_flags_[name]; if (typeof(T).IsEnum) { T retval = (T)Enum.Parse(typeof(T), value, true); object_flags_[name] = retval; return retval; } else if (typeof(T).Equals(typeof(Vector3))) { Vector3 retval = ParseVector3(value); object_flags_[name] = retval; return retval; } else { T retval = (T)Convert.ChangeType(value, typeof(T)); object_flags_[name] = retval; return retval; } } else if (object_flags_.ContainsKey(name)) { return (T)object_flags_[name]; } else { object_flags_.Add(name, default_value); return default_value; } } static private Vector3 ParseVector3(string string_vec) { if (string_vec.StartsWith("(") && string_vec.EndsWith(")")) { string_vec = string_vec.Substring(1, string_vec.Length - 2); } string[] splits = string_vec.Split(new char[] { ',' }); if (splits.Length != 3) { Logger.Error("Flags::ParseVector3::Invalid Vector3: {0}", string_vec); return Vector3.zero; } return new Vector3(float.Parse(splits[0].Trim()), float.Parse(splits[1].Trim()), float.Parse(splits[2].Trim())); } static public void DumpFlags() { SortedDictionary<string, string> flag_strings = new SortedDictionary<string, string>(); foreach (KeyValuePair<string, object> pair in object_flags_) { if (pair.Value.GetType().IsEnum) { flag_strings.Add(pair.Key, string.Format("String {0} {1}", pair.Key, pair.Value)); } else { flag_strings.Add(pair.Key, string.Format("{0} {1} {2}", pair.Value.GetType().Name, pair.Key, pair.Value)); } } foreach (KeyValuePair<string, string> pair in flag_strings) { System.Console.WriteLine(pair.Value); } } static public void InitFlags(object subject, string prefix) { MethodInfo flag_getter = typeof(Flags).GetMethod("Get"); foreach (FieldInfo field_info in subject.GetType().GetFields()) { if (field_info.IsDefined(typeof(Flag), true)) { MethodInfo typed_flag_getter = flag_getter.MakeGenericMethod(field_info.FieldType); field_info.SetValue(subject, typed_flag_getter.Invoke(null, new object[] { GetFlagName (prefix, field_info.Name), field_info.GetValue (subject) })); } } } static private string GetFlagName(string prefix, string flag_name) { if (flag_name.EndsWith("_")) { flag_name = flag_name.Substring(0, flag_name.Length - 1); } return string.Format("{0}.{1}", prefix, flag_name); } }