public WRange DistanceToEdge(WPos pos, WVec dir) { var tl = CenterOfCell(Cells.TopLeft) - new WVec(512, 512, 0); var br = CenterOfCell(Cells.BottomRight) + new WVec(511, 511, 0); var x = dir.X == 0 ? int.MaxValue : ((dir.X < 0 ? tl.X : br.X) - pos.X) / dir.X; var y = dir.Y == 0 ? int.MaxValue : ((dir.Y < 0 ? tl.Y : br.Y) - pos.Y) / dir.Y; return new WRange(Math.Min(x, y) * dir.Length); }
public static WVec Lerp(WVec a, WVec b, int mul, int div) { return a + (b - a) * mul / div; }
public static WVec LerpQuadratic(WVec a, WVec b, WAngle pitch, int mul, int div) { // Start with a linear lerp between the points var ret = Lerp(a, b, mul, div); if (pitch.Angle == 0) return ret; // Add an additional quadratic variation to height // Uses fp to avoid integer overflow var offset = (int)((float)((float)(b - a).Length*pitch.Tan()*mul*(div - mul)) / (float)(1024*div*div)); return new WVec(ret.X, ret.Y, ret.Z + offset); }
public WDist DistanceToEdge(WPos pos, WVec dir) { var projectedPos = pos - new WVec(0, pos.Z, pos.Z); var x = dir.X == 0 ? int.MaxValue : ((dir.X < 0 ? ProjectedTopLeft.X : ProjectedBottomRight.X) - projectedPos.X) / dir.X; var y = dir.Y == 0 ? int.MaxValue : ((dir.Y < 0 ? ProjectedTopLeft.Y : ProjectedBottomRight.Y) - projectedPos.Y) / dir.Y; return new WDist(Math.Min(x, y) * dir.Length); }
public static int Dot(WVec a, WVec b) { return a.X * b.X + a.Y * b.Y + a.Z * b.Z; }
public static CVec ToCVec(this WVec a) { return(new CVec(a.X / 1024, a.Y / 1024)); }
public static object GetValue(string fieldName, Type fieldType, MiniYaml yaml, MemberInfo field) { var value = yaml.Value; if (value != null) { value = value.Trim(); } if (fieldType == typeof(int)) { int res; if (Exts.TryParseIntegerInvariant(value, out res)) { return(res); } return(InvalidValueAction(value, fieldType, fieldName)); } else if (fieldType == typeof(ushort)) { ushort res; if (ushort.TryParse(value, NumberStyles.Integer, NumberFormatInfo.InvariantInfo, out res)) { return(res); } return(InvalidValueAction(value, fieldType, fieldName)); } if (fieldType == typeof(long)) { long res; if (long.TryParse(value, NumberStyles.Integer, NumberFormatInfo.InvariantInfo, out res)) { return(res); } return(InvalidValueAction(value, fieldType, fieldName)); } else if (fieldType == typeof(float)) { float res; if (value != null && float.TryParse(value.Replace("%", ""), NumberStyles.Float, NumberFormatInfo.InvariantInfo, out res)) { return(res * (value.Contains('%') ? 0.01f : 1f)); } return(InvalidValueAction(value, fieldType, fieldName)); } else if (fieldType == typeof(decimal)) { decimal res; if (value != null && decimal.TryParse(value.Replace("%", ""), NumberStyles.Float, NumberFormatInfo.InvariantInfo, out res)) { return(res * (value.Contains('%') ? 0.01m : 1m)); } return(InvalidValueAction(value, fieldType, fieldName)); } else if (fieldType == typeof(string)) { if (field != null && MemberHasTranslateAttribute[field] && value != null) { return(Regex.Replace(value, "@[^@]+@", m => Translate(m.Value.Substring(1, m.Value.Length - 2)), RegexOptions.Compiled)); } return(value); } else if (fieldType == typeof(Color)) { Color color; if (value != null && HSLColor.TryParseRGB(value, out color)) { return(color); } return(InvalidValueAction(value, fieldType, fieldName)); } else if (fieldType == typeof(Color[])) { if (value != null) { var parts = value.Split(','); var colors = new Color[parts.Length]; for (var i = 0; i < colors.Length; i++) { if (!HSLColor.TryParseRGB(parts[i], out colors[i])) { return(InvalidValueAction(value, fieldType, fieldName)); } } return(colors); } return(InvalidValueAction(value, fieldType, fieldName)); } else if (fieldType == typeof(HSLColor)) { if (value != null) { Color rgb; if (HSLColor.TryParseRGB(value, out rgb)) { return(new HSLColor(rgb)); } // Allow old HSLColor/ColorRamp formats to be parsed as HSLColor var parts = value.Split(','); if (parts.Length == 3 || parts.Length == 4) { return(new HSLColor( (byte)Exts.ParseIntegerInvariant(parts[0]).Clamp(0, 255), (byte)Exts.ParseIntegerInvariant(parts[1]).Clamp(0, 255), (byte)Exts.ParseIntegerInvariant(parts[2]).Clamp(0, 255))); } } return(InvalidValueAction(value, fieldType, fieldName)); } else if (fieldType == typeof(Hotkey)) { Hotkey res; if (Hotkey.TryParse(value, out res)) { return(res); } return(InvalidValueAction(value, fieldType, fieldName)); } else if (fieldType == typeof(WDist)) { WDist res; if (WDist.TryParse(value, out res)) { return(res); } return(InvalidValueAction(value, fieldType, fieldName)); } else if (fieldType == typeof(WVec)) { if (value != null) { var parts = value.Split(','); if (parts.Length == 3) { WDist rx, ry, rz; if (WDist.TryParse(parts[0], out rx) && WDist.TryParse(parts[1], out ry) && WDist.TryParse(parts[2], out rz)) { return(new WVec(rx, ry, rz)); } } } return(InvalidValueAction(value, fieldType, fieldName)); } else if (fieldType == typeof(WVec[])) { if (value != null) { var parts = value.Split(','); if (parts.Length % 3 != 0) { return(InvalidValueAction(value, fieldType, fieldName)); } var vecs = new WVec[parts.Length / 3]; for (var i = 0; i < vecs.Length; ++i) { WDist rx, ry, rz; if (WDist.TryParse(parts[3 * i], out rx) && WDist.TryParse(parts[3 * i + 1], out ry) && WDist.TryParse(parts[3 * i + 2], out rz)) { vecs[i] = new WVec(rx, ry, rz); } } return(vecs); } return(InvalidValueAction(value, fieldType, fieldName)); } else if (fieldType == typeof(WPos)) { if (value != null) { var parts = value.Split(','); if (parts.Length == 3) { WDist rx, ry, rz; if (WDist.TryParse(parts[0], out rx) && WDist.TryParse(parts[1], out ry) && WDist.TryParse(parts[2], out rz)) { return(new WPos(rx, ry, rz)); } } } return(InvalidValueAction(value, fieldType, fieldName)); } else if (fieldType == typeof(WAngle)) { int res; if (Exts.TryParseIntegerInvariant(value, out res)) { return(new WAngle(res)); } return(InvalidValueAction(value, fieldType, fieldName)); } else if (fieldType == typeof(WRot)) { if (value != null) { var parts = value.Split(','); if (parts.Length == 3) { int rr, rp, ry; if (Exts.TryParseIntegerInvariant(value, out rr) && Exts.TryParseIntegerInvariant(value, out rp) && Exts.TryParseIntegerInvariant(value, out ry)) { return(new WRot(new WAngle(rr), new WAngle(rp), new WAngle(ry))); } } } return(InvalidValueAction(value, fieldType, fieldName)); } else if (fieldType == typeof(CPos)) { if (value != null) { var parts = value.Split(new char[] { ',' }, StringSplitOptions.RemoveEmptyEntries); return(new CPos(Exts.ParseIntegerInvariant(parts[0]), Exts.ParseIntegerInvariant(parts[1]))); } return(InvalidValueAction(value, fieldType, fieldName)); } else if (fieldType == typeof(CVec)) { if (value != null) { var parts = value.Split(new char[] { ',' }, StringSplitOptions.RemoveEmptyEntries); return(new CVec(Exts.ParseIntegerInvariant(parts[0]), Exts.ParseIntegerInvariant(parts[1]))); } return(InvalidValueAction(value, fieldType, fieldName)); } else if (fieldType == typeof(CVec[])) { if (value != null) { var parts = value.Split(','); if (parts.Length % 2 != 0) { return(InvalidValueAction(value, fieldType, fieldName)); } var vecs = new CVec[parts.Length / 2]; for (var i = 0; i < vecs.Length; i++) { int rx, ry; if (int.TryParse(parts[2 * i], out rx) && int.TryParse(parts[2 * i + 1], out ry)) { vecs[i] = new CVec(rx, ry); } } return(vecs); } return(InvalidValueAction(value, fieldType, fieldName)); } else if (fieldType.IsEnum) { try { return(Enum.Parse(fieldType, value, true)); } catch (ArgumentException) { return(InvalidValueAction(value, fieldType, fieldName)); } } else if (fieldType == typeof(ImageFormat)) { if (value != null) { switch (value.ToLowerInvariant()) { case "bmp": return(ImageFormat.Bmp); case "gif": return(ImageFormat.Gif); case "jpg": case "jpeg": return(ImageFormat.Jpeg); case "tif": case "tiff": return(ImageFormat.Tiff); default: return(ImageFormat.Png); } } return(InvalidValueAction(value, fieldType, fieldName)); } else if (fieldType == typeof(bool)) { return(ParseYesNo(value, fieldType, fieldName)); } else if (fieldType.IsArray && fieldType.GetArrayRank() == 1) { if (value == null) { return(Array.CreateInstance(fieldType.GetElementType(), 0)); } var parts = value.Split(new char[] { ',' }, StringSplitOptions.RemoveEmptyEntries); var ret = Array.CreateInstance(fieldType.GetElementType(), parts.Length); for (var i = 0; i < parts.Length; i++) { ret.SetValue(GetValue(fieldName, fieldType.GetElementType(), parts[i].Trim(), field), i); } return(ret); } else if (fieldType.IsGenericType && fieldType.GetGenericTypeDefinition() == typeof(HashSet <>)) { var set = Activator.CreateInstance(fieldType); if (value == null) { return(set); } var parts = value.Split(new char[] { ',' }, StringSplitOptions.RemoveEmptyEntries); var addMethod = fieldType.GetMethod("Add", fieldType.GetGenericArguments()); for (var i = 0; i < parts.Length; i++) { addMethod.Invoke(set, new[] { GetValue(fieldName, fieldType.GetGenericArguments()[0], parts[i].Trim(), field) }); } return(set); } else if (fieldType.IsGenericType && fieldType.GetGenericTypeDefinition() == typeof(Dictionary <,>)) { var dict = Activator.CreateInstance(fieldType); var arguments = fieldType.GetGenericArguments(); var addMethod = fieldType.GetMethod("Add", arguments); foreach (var node in yaml.Nodes) { var key = GetValue(fieldName, arguments[0], node.Key, field); var val = GetValue(fieldName, arguments[1], node.Value, field); addMethod.Invoke(dict, new[] { key, val }); } return(dict); } else if (fieldType == typeof(Size)) { if (value != null) { var parts = value.Split(new char[] { ',' }, StringSplitOptions.RemoveEmptyEntries); return(new Size(Exts.ParseIntegerInvariant(parts[0]), Exts.ParseIntegerInvariant(parts[1]))); } return(InvalidValueAction(value, fieldType, fieldName)); } else if (fieldType == typeof(int2)) { if (value != null) { var parts = value.Split(new char[] { ',' }, StringSplitOptions.RemoveEmptyEntries); return(new int2(Exts.ParseIntegerInvariant(parts[0]), Exts.ParseIntegerInvariant(parts[1]))); } return(InvalidValueAction(value, fieldType, fieldName)); } else if (fieldType == typeof(float2)) { if (value != null) { var parts = value.Split(new char[] { ',' }, StringSplitOptions.RemoveEmptyEntries); float xx = 0; float yy = 0; float res; if (float.TryParse(parts[0].Replace("%", ""), NumberStyles.Float, NumberFormatInfo.InvariantInfo, out res)) { xx = res * (parts[0].Contains('%') ? 0.01f : 1f); } if (float.TryParse(parts[1].Replace("%", ""), NumberStyles.Float, NumberFormatInfo.InvariantInfo, out res)) { yy = res * (parts[1].Contains('%') ? 0.01f : 1f); } return(new float2(xx, yy)); } return(InvalidValueAction(value, fieldType, fieldName)); } else if (fieldType == typeof(float3)) { if (value != null) { var parts = value.Split(new char[] { ',' }, StringSplitOptions.RemoveEmptyEntries); float x = 0; float y = 0; float z = 0; float.TryParse(parts[0], NumberStyles.Float, NumberFormatInfo.InvariantInfo, out x); float.TryParse(parts[1], NumberStyles.Float, NumberFormatInfo.InvariantInfo, out y); // z component is optional for compatibility with older float2 definitions if (parts.Length > 2) { float.TryParse(parts[2], NumberStyles.Float, NumberFormatInfo.InvariantInfo, out z); } return(new float3(x, y, z)); } return(InvalidValueAction(value, fieldType, fieldName)); } else if (fieldType == typeof(Rectangle)) { if (value != null) { var parts = value.Split(new char[] { ',' }, StringSplitOptions.RemoveEmptyEntries); return(new Rectangle( Exts.ParseIntegerInvariant(parts[0]), Exts.ParseIntegerInvariant(parts[1]), Exts.ParseIntegerInvariant(parts[2]), Exts.ParseIntegerInvariant(parts[3]))); } return(InvalidValueAction(value, fieldType, fieldName)); } else if (fieldType.IsGenericType && fieldType.GetGenericTypeDefinition() == typeof(Bits <>)) { if (value != null) { var parts = value.Split(new char[] { ',' }, StringSplitOptions.RemoveEmptyEntries); var argTypes = new Type[] { typeof(string[]) }; var argValues = new object[] { parts }; return(fieldType.GetConstructor(argTypes).Invoke(argValues)); } return(InvalidValueAction(value, fieldType, fieldName)); } else if (fieldType.IsGenericType && fieldType.GetGenericTypeDefinition() == typeof(Nullable <>)) { var innerType = fieldType.GetGenericArguments().First(); var innerValue = GetValue("Nullable<T>", innerType, value, field); return(fieldType.GetConstructor(new[] { innerType }).Invoke(new[] { innerValue })); } else if (fieldType == typeof(DateTime)) { DateTime dt; if (DateTime.TryParseExact(value, "yyyy-MM-dd HH-mm-ss", CultureInfo.InvariantCulture, DateTimeStyles.AssumeUniversal, out dt)) { return(dt); } return(InvalidValueAction(value, fieldType, fieldName)); } else { var conv = TypeDescriptor.GetConverter(fieldType); if (conv.CanConvertFrom(typeof(string))) { try { return(conv.ConvertFromInvariantString(value)); } catch { return(InvalidValueAction(value, fieldType, fieldName)); } } } UnknownFieldAction("[Type] {0}".F(value), fieldType); return(null); }
public MapGrid(MiniYaml yaml) { FieldLoader.Load(this, yaml); // The default subcell index defaults to the middle entry var defaultSubCellIndex = (byte)DefaultSubCell; if (defaultSubCellIndex == byte.MaxValue) { DefaultSubCell = (SubCell)(SubCellOffsets.Length / 2); } else { var minSubCellOffset = SubCellOffsets.Length > 1 ? 1 : 0; if (defaultSubCellIndex < minSubCellOffset || defaultSubCellIndex >= SubCellOffsets.Length) { throw new InvalidDataException("Subcell default index must be a valid index into the offset triples and must be greater than 0 for mods with subcells"); } } // Rotation axes and amounts for the different slope types var southEast = new WVec(724, 724, 0); var southWest = new WVec(-724, 724, 0); var south = new WVec(0, 1024, 0); var east = new WVec(1024, 0, 0); var forward = new WAngle(64); var backward = -forward; var halfForward = new WAngle(48); var halfBackward = -halfForward; // Slope types are hardcoded following the convention from the TS and RA2 map format Ramps = new[] { // Flat new CellRamp(Type, WRot.None), // Two adjacent corners raised by half a cell new CellRamp(Type, new WRot(southEast, backward), tr: RampCornerHeight.Half, br: RampCornerHeight.Half), new CellRamp(Type, new WRot(southWest, backward), br: RampCornerHeight.Half, bl: RampCornerHeight.Half), new CellRamp(Type, new WRot(southEast, forward), tl: RampCornerHeight.Half, bl: RampCornerHeight.Half), new CellRamp(Type, new WRot(southWest, forward), tl: RampCornerHeight.Half, tr: RampCornerHeight.Half), // One corner raised by half a cell new CellRamp(Type, new WRot(south, halfBackward), br: RampCornerHeight.Half, split: RampSplit.X), new CellRamp(Type, new WRot(east, halfForward), bl: RampCornerHeight.Half, split: RampSplit.Y), new CellRamp(Type, new WRot(south, halfForward), tl: RampCornerHeight.Half, split: RampSplit.X), new CellRamp(Type, new WRot(east, halfBackward), tr: RampCornerHeight.Half, split: RampSplit.Y), // Three corners raised by half a cell new CellRamp(Type, new WRot(south, halfBackward), tr: RampCornerHeight.Half, br: RampCornerHeight.Half, bl: RampCornerHeight.Half, split: RampSplit.X), new CellRamp(Type, new WRot(east, halfForward), tl: RampCornerHeight.Half, br: RampCornerHeight.Half, bl: RampCornerHeight.Half, split: RampSplit.Y), new CellRamp(Type, new WRot(south, halfForward), tl: RampCornerHeight.Half, tr: RampCornerHeight.Half, bl: RampCornerHeight.Half, split: RampSplit.X), new CellRamp(Type, new WRot(east, halfBackward), tl: RampCornerHeight.Half, tr: RampCornerHeight.Half, br: RampCornerHeight.Half, split: RampSplit.Y), // Full tile sloped (mid corners raised by half cell, far corner by full cell) new CellRamp(Type, new WRot(south, backward), tr: RampCornerHeight.Half, br: RampCornerHeight.Full, bl: RampCornerHeight.Half), new CellRamp(Type, new WRot(east, forward), tl: RampCornerHeight.Half, br: RampCornerHeight.Half, bl: RampCornerHeight.Full), new CellRamp(Type, new WRot(south, forward), tl: RampCornerHeight.Full, tr: RampCornerHeight.Half, bl: RampCornerHeight.Half), new CellRamp(Type, new WRot(east, backward), tl: RampCornerHeight.Half, tr: RampCornerHeight.Full, br: RampCornerHeight.Half), // Two opposite corners raised by half a cell new CellRamp(Type, WRot.None, tr: RampCornerHeight.Half, bl: RampCornerHeight.Half, split: RampSplit.Y), new CellRamp(Type, WRot.None, tl: RampCornerHeight.Half, br: RampCornerHeight.Half, split: RampSplit.Y), new CellRamp(Type, WRot.None, tr: RampCornerHeight.Half, bl: RampCornerHeight.Half, split: RampSplit.X), new CellRamp(Type, WRot.None, tl: RampCornerHeight.Half, br: RampCornerHeight.Half, split: RampSplit.X), }; TilesByDistance = CreateTilesByDistance(); }
public static object GetValue(string fieldName, Type fieldType, string value, MemberInfo field) { if (value != null) { value = value.Trim(); } if (fieldType == typeof(int)) { int res; if (Exts.TryParseIntegerInvariant(value, out res)) { return(res); } return(InvalidValueAction(value, fieldType, fieldName)); } else if (fieldType == typeof(ushort)) { ushort res; if (ushort.TryParse(value, NumberStyles.Integer, NumberFormatInfo.InvariantInfo, out res)) { return(res); } return(InvalidValueAction(value, fieldType, fieldName)); } if (fieldType == typeof(long)) { long res; if (long.TryParse(value, NumberStyles.Integer, NumberFormatInfo.InvariantInfo, out res)) { return(res); } return(InvalidValueAction(value, fieldType, fieldName)); } else if (fieldType == typeof(float)) { float res; if (float.TryParse(value.Replace("%", ""), NumberStyles.Float, NumberFormatInfo.InvariantInfo, out res)) { return(res * (value.Contains('%') ? 0.01f : 1f)); } return(InvalidValueAction(value, fieldType, fieldName)); } else if (fieldType == typeof(decimal)) { decimal res; if (decimal.TryParse(value.Replace("%", ""), NumberStyles.Float, NumberFormatInfo.InvariantInfo, out res)) { return(res * (value.Contains('%') ? 0.01m : 1m)); } return(InvalidValueAction(value, fieldType, fieldName)); } else if (fieldType == typeof(string)) { if (field != null && field.HasAttribute <TranslateAttribute>()) { return(Regex.Replace(value, "@[^@]+@", m => Translate(m.Value.Substring(1, m.Value.Length - 2)), RegexOptions.Compiled)); } return(value); } else if (fieldType == typeof(Color)) { var parts = value.Split(','); if (parts.Length == 3) { return(Color.FromArgb( Exts.ParseIntegerInvariant(parts[0]).Clamp(0, 255), Exts.ParseIntegerInvariant(parts[1]).Clamp(0, 255), Exts.ParseIntegerInvariant(parts[2]).Clamp(0, 255))); } if (parts.Length == 4) { return(Color.FromArgb( Exts.ParseIntegerInvariant(parts[0]).Clamp(0, 255), Exts.ParseIntegerInvariant(parts[1]).Clamp(0, 255), Exts.ParseIntegerInvariant(parts[2]).Clamp(0, 255), Exts.ParseIntegerInvariant(parts[3]).Clamp(0, 255))); } return(InvalidValueAction(value, fieldType, fieldName)); } else if (fieldType == typeof(HSLColor)) { var parts = value.Split(','); // Allow old ColorRamp format to be parsed as HSLColor if (parts.Length == 3 || parts.Length == 4) { return(new HSLColor( (byte)Exts.ParseIntegerInvariant(parts[0]).Clamp(0, 255), (byte)Exts.ParseIntegerInvariant(parts[1]).Clamp(0, 255), (byte)Exts.ParseIntegerInvariant(parts[2]).Clamp(0, 255))); } return(InvalidValueAction(value, fieldType, fieldName)); } else if (fieldType == typeof(Hotkey)) { Hotkey res; if (Hotkey.TryParse(value, out res)) { return(res); } return(InvalidValueAction(value, fieldType, fieldName)); } else if (fieldType == typeof(WRange)) { WRange res; if (WRange.TryParse(value, out res)) { return(res); } return(InvalidValueAction(value, fieldType, fieldName)); } else if (fieldType == typeof(WVec)) { var parts = value.Split(','); if (parts.Length == 3) { WRange rx, ry, rz; if (WRange.TryParse(parts[0], out rx) && WRange.TryParse(parts[1], out ry) && WRange.TryParse(parts[2], out rz)) { return(new WVec(rx, ry, rz)); } } return(InvalidValueAction(value, fieldType, fieldName)); } else if (fieldType == typeof(WVec[])) { var parts = value.Split(','); if (parts.Length % 3 != 0) { return(InvalidValueAction(value, fieldType, fieldName)); } var vecs = new WVec[parts.Length / 3]; for (var i = 0; i < vecs.Length; ++i) { WRange rx, ry, rz; if (WRange.TryParse(parts[3 * i], out rx) && WRange.TryParse(parts[3 * i + 1], out ry) && WRange.TryParse(parts[3 * i + 2], out rz)) { vecs[i] = new WVec(rx, ry, rz); } } return(vecs); } else if (fieldType == typeof(WPos)) { var parts = value.Split(','); if (parts.Length == 3) { WRange rx, ry, rz; if (WRange.TryParse(parts[0], out rx) && WRange.TryParse(parts[1], out ry) && WRange.TryParse(parts[2], out rz)) { return(new WPos(rx, ry, rz)); } } return(InvalidValueAction(value, fieldType, fieldName)); } else if (fieldType == typeof(WAngle)) { int res; if (Exts.TryParseIntegerInvariant(value, out res)) { return(new WAngle(res)); } return(InvalidValueAction(value, fieldType, fieldName)); } else if (fieldType == typeof(WRot)) { var parts = value.Split(','); if (parts.Length == 3) { int rr, rp, ry; if (Exts.TryParseIntegerInvariant(value, out rr) && Exts.TryParseIntegerInvariant(value, out rp) && Exts.TryParseIntegerInvariant(value, out ry)) { return(new WRot(new WAngle(rr), new WAngle(rp), new WAngle(ry))); } } return(InvalidValueAction(value, fieldType, fieldName)); } else if (fieldType == typeof(CPos)) { var parts = value.Split(new char[] { ',' }, StringSplitOptions.RemoveEmptyEntries); return(new CPos( Exts.ParseIntegerInvariant(parts[0]), Exts.ParseIntegerInvariant(parts[1]))); } else if (fieldType == typeof(CVec)) { var parts = value.Split(new char[] { ',' }, StringSplitOptions.RemoveEmptyEntries); return(new CVec( Exts.ParseIntegerInvariant(parts[0]), Exts.ParseIntegerInvariant(parts[1]))); } else if (fieldType.IsEnum) { try { return(Enum.Parse(fieldType, value, true)); } catch (ArgumentException) { return(InvalidValueAction(value, fieldType, fieldName)); } } else if (fieldType == typeof(bool)) { return(ParseYesNo(value, fieldType, fieldName)); } else if (fieldType.IsArray) { if (value == null) { return(Array.CreateInstance(fieldType.GetElementType(), 0)); } var parts = value.Split(new char[] { ',' }, StringSplitOptions.RemoveEmptyEntries); var ret = Array.CreateInstance(fieldType.GetElementType(), parts.Length); for (var i = 0; i < parts.Length; i++) { ret.SetValue(GetValue(fieldName, fieldType.GetElementType(), parts[i].Trim(), field), i); } return(ret); } else if (fieldType == typeof(Size)) { var parts = value.Split(new char[] { ',' }, StringSplitOptions.RemoveEmptyEntries); return(new Size( Exts.ParseIntegerInvariant(parts[0]), Exts.ParseIntegerInvariant(parts[1]))); } else if (fieldType == typeof(int2)) { var parts = value.Split(new char[] { ',' }, StringSplitOptions.RemoveEmptyEntries); return(new int2( Exts.ParseIntegerInvariant(parts[0]), Exts.ParseIntegerInvariant(parts[1]))); } else if (fieldType == typeof(float2)) { var parts = value.Split(new char[] { ',' }, StringSplitOptions.RemoveEmptyEntries); float xx = 0; float yy = 0; float res; if (float.TryParse(parts[0].Replace("%", ""), NumberStyles.Float, NumberFormatInfo.InvariantInfo, out res)) { xx = res * (parts[0].Contains('%') ? 0.01f : 1f); } if (float.TryParse(parts[1].Replace("%", ""), NumberStyles.Float, NumberFormatInfo.InvariantInfo, out res)) { yy = res * (parts[1].Contains('%') ? 0.01f : 1f); } return(new float2(xx, yy)); } else if (fieldType == typeof(Rectangle)) { var parts = value.Split(new char[] { ',' }, StringSplitOptions.RemoveEmptyEntries); return(new Rectangle( Exts.ParseIntegerInvariant(parts[0]), Exts.ParseIntegerInvariant(parts[1]), Exts.ParseIntegerInvariant(parts[2]), Exts.ParseIntegerInvariant(parts[3]))); } else if (fieldType.IsGenericType && fieldType.GetGenericTypeDefinition() == typeof(Bits <>)) { var parts = value.Split(new char[] { ',' }, StringSplitOptions.RemoveEmptyEntries); var argTypes = new Type[] { typeof(string[]) }; var argValues = new object[] { parts }; return(fieldType.GetConstructor(argTypes).Invoke(argValues)); } else if (fieldType.IsGenericType && fieldType.GetGenericTypeDefinition() == typeof(Nullable <>)) { var innerType = fieldType.GetGenericArguments().First(); var innerValue = GetValue("Nullable<T>", innerType, value, field); return(fieldType.GetConstructor(new[] { innerType }).Invoke(new[] { innerValue })); } else if (fieldType == typeof(DateTime)) { DateTime dt; if (DateTime.TryParseExact(value, "yyyy-MM-dd HH-mm-ss", CultureInfo.InvariantCulture, DateTimeStyles.AssumeUniversal, out dt)) { return(dt); } return(InvalidValueAction(value, fieldType, fieldName)); } else { var conv = TypeDescriptor.GetConverter(fieldType); if (conv.CanConvertFrom(typeof(string))) { try { return(conv.ConvertFromInvariantString(value)); } catch { return(InvalidValueAction(value, fieldType, fieldName)); } } } UnknownFieldAction("[Type] {0}".F(value), fieldType); return(null); }
public static object GetValue(string fieldName, Type fieldType, MiniYaml yaml, MemberInfo field) { var value = yaml.Value; if (value != null) { value = value.Trim(); } if (fieldType == typeof(int)) { int res; if (Exts.TryParseIntegerInvariant(value, out res)) { return(res); } return(InvalidValueAction(value, fieldType, fieldName)); } else if (fieldType == typeof(ushort)) { ushort res; if (ushort.TryParse(value, NumberStyles.Integer, NumberFormatInfo.InvariantInfo, out res)) { return(res); } return(InvalidValueAction(value, fieldType, fieldName)); } if (fieldType == typeof(long)) { long res; if (long.TryParse(value, NumberStyles.Integer, NumberFormatInfo.InvariantInfo, out res)) { return(res); } return(InvalidValueAction(value, fieldType, fieldName)); } else if (fieldType == typeof(float)) { float res; if (value != null && float.TryParse(value.Replace("%", ""), NumberStyles.Float, NumberFormatInfo.InvariantInfo, out res)) { return(res * (value.Contains('%') ? 0.01f : 1f)); } return(InvalidValueAction(value, fieldType, fieldName)); } else if (fieldType == typeof(decimal)) { decimal res; if (value != null && decimal.TryParse(value.Replace("%", ""), NumberStyles.Float, NumberFormatInfo.InvariantInfo, out res)) { return(res * (value.Contains('%') ? 0.01m : 1m)); } return(InvalidValueAction(value, fieldType, fieldName)); } else if (fieldType == typeof(string)) { if (field != null && MemberHasTranslateAttribute[field] && value != null) { return(Regex.Replace(value, "@[^@]+@", m => Translate(m.Value.Substring(1, m.Value.Length - 2)), RegexOptions.Compiled)); } return(value); } else if (fieldType == typeof(Color)) { Color color; if (value != null && Color.TryParse(value, out color)) { return(color); } return(InvalidValueAction(value, fieldType, fieldName)); } else if (fieldType == typeof(Hotkey)) { Hotkey res; if (Hotkey.TryParse(value, out res)) { return(res); } return(InvalidValueAction(value, fieldType, fieldName)); } else if (fieldType == typeof(HotkeyReference)) { return(Game.ModData.Hotkeys[value]); } else if (fieldType == typeof(WDist)) { WDist res; if (WDist.TryParse(value, out res)) { return(res); } return(InvalidValueAction(value, fieldType, fieldName)); } else if (fieldType == typeof(WVec)) { if (value != null) { var parts = value.Split(','); if (parts.Length == 3) { WDist rx, ry, rz; if (WDist.TryParse(parts[0], out rx) && WDist.TryParse(parts[1], out ry) && WDist.TryParse(parts[2], out rz)) { return(new WVec(rx, ry, rz)); } } } return(InvalidValueAction(value, fieldType, fieldName)); } else if (fieldType == typeof(WVec[])) { if (value != null) { var parts = value.Split(','); if (parts.Length % 3 != 0) { return(InvalidValueAction(value, fieldType, fieldName)); } var vecs = new WVec[parts.Length / 3]; for (var i = 0; i < vecs.Length; ++i) { WDist rx, ry, rz; if (WDist.TryParse(parts[3 * i], out rx) && WDist.TryParse(parts[3 * i + 1], out ry) && WDist.TryParse(parts[3 * i + 2], out rz)) { vecs[i] = new WVec(rx, ry, rz); } } return(vecs); } return(InvalidValueAction(value, fieldType, fieldName)); } else if (fieldType == typeof(WPos)) { if (value != null) { var parts = value.Split(','); if (parts.Length == 3) { WDist rx, ry, rz; if (WDist.TryParse(parts[0], out rx) && WDist.TryParse(parts[1], out ry) && WDist.TryParse(parts[2], out rz)) { return(new WPos(rx, ry, rz)); } } } return(InvalidValueAction(value, fieldType, fieldName)); } else if (fieldType == typeof(WAngle)) { int res; if (Exts.TryParseIntegerInvariant(value, out res)) { return(new WAngle(res)); } return(InvalidValueAction(value, fieldType, fieldName)); } else if (fieldType == typeof(WRot)) { if (value != null) { var parts = value.Split(','); if (parts.Length == 3) { int rr, rp, ry; if (Exts.TryParseIntegerInvariant(parts[0], out rr) && Exts.TryParseIntegerInvariant(parts[1], out rp) && Exts.TryParseIntegerInvariant(parts[2], out ry)) { return(new WRot(new WAngle(rr), new WAngle(rp), new WAngle(ry))); } } } return(InvalidValueAction(value, fieldType, fieldName)); } else if (fieldType == typeof(CPos)) { if (value != null) { var parts = value.Split(new char[] { ',' }, StringSplitOptions.RemoveEmptyEntries); return(new CPos(Exts.ParseIntegerInvariant(parts[0]), Exts.ParseIntegerInvariant(parts[1]))); } return(InvalidValueAction(value, fieldType, fieldName)); } else if (fieldType == typeof(CVec)) { if (value != null) { var parts = value.Split(new char[] { ',' }, StringSplitOptions.RemoveEmptyEntries); return(new CVec(Exts.ParseIntegerInvariant(parts[0]), Exts.ParseIntegerInvariant(parts[1]))); } return(InvalidValueAction(value, fieldType, fieldName)); } else if (fieldType == typeof(CVec[])) { if (value != null) { var parts = value.Split(','); if (parts.Length % 2 != 0) { return(InvalidValueAction(value, fieldType, fieldName)); } var vecs = new CVec[parts.Length / 2]; for (var i = 0; i < vecs.Length; i++) { int rx, ry; if (int.TryParse(parts[2 * i], out rx) && int.TryParse(parts[2 * i + 1], out ry)) { vecs[i] = new CVec(rx, ry); } } return(vecs); } return(InvalidValueAction(value, fieldType, fieldName)); } else if (fieldType == typeof(BooleanExpression)) { if (value != null) { try { return(BooleanExpressionCache[value]); } catch (InvalidDataException e) { throw new YamlException(e.Message); } } return(InvalidValueAction(value, fieldType, fieldName)); } else if (fieldType == typeof(IntegerExpression)) { if (value != null) { try { return(IntegerExpressionCache[value]); } catch (InvalidDataException e) { throw new YamlException(e.Message); } } return(InvalidValueAction(value, fieldType, fieldName)); } else if (fieldType.IsEnum) { try { return(Enum.Parse(fieldType, value, true)); } catch (ArgumentException) { return(InvalidValueAction(value, fieldType, fieldName)); } } else if (fieldType == typeof(bool)) { bool result; if (bool.TryParse(value.ToLowerInvariant(), out result)) { return(result); } return(InvalidValueAction(value, fieldType, fieldName)); } else if (fieldType == typeof(int2[])) { if (value != null) { var parts = value.Split(new char[] { ',' }, StringSplitOptions.RemoveEmptyEntries); if (parts.Length % 2 != 0) { return(InvalidValueAction(value, fieldType, fieldName)); } var ints = new int2[parts.Length / 2]; for (var i = 0; i < ints.Length; i++) { ints[i] = new int2(Exts.ParseIntegerInvariant(parts[2 * i]), Exts.ParseIntegerInvariant(parts[2 * i + 1])); } return(ints); } return(InvalidValueAction(value, fieldType, fieldName)); } else if (fieldType.IsArray && fieldType.GetArrayRank() == 1) { if (value == null) { return(Array.CreateInstance(fieldType.GetElementType(), 0)); } var options = field != null && field.HasAttribute <AllowEmptyEntriesAttribute>() ? StringSplitOptions.None : StringSplitOptions.RemoveEmptyEntries; var parts = value.Split(new char[] { ',' }, options); var ret = Array.CreateInstance(fieldType.GetElementType(), parts.Length); for (var i = 0; i < parts.Length; i++) { ret.SetValue(GetValue(fieldName, fieldType.GetElementType(), parts[i].Trim(), field), i); } return(ret); } else if (fieldType.IsGenericType && fieldType.GetGenericTypeDefinition() == typeof(HashSet <>)) { var set = Activator.CreateInstance(fieldType); if (value == null) { return(set); } var parts = value.Split(new char[] { ',' }, StringSplitOptions.RemoveEmptyEntries); var addMethod = fieldType.GetMethod("Add", fieldType.GetGenericArguments()); for (var i = 0; i < parts.Length; i++) { addMethod.Invoke(set, new[] { GetValue(fieldName, fieldType.GetGenericArguments()[0], parts[i].Trim(), field) }); } return(set); } else if (fieldType.IsGenericType && fieldType.GetGenericTypeDefinition() == typeof(Dictionary <,>)) { var dict = Activator.CreateInstance(fieldType); var arguments = fieldType.GetGenericArguments(); var addMethod = fieldType.GetMethod("Add", arguments); foreach (var node in yaml.Nodes) { var key = GetValue(fieldName, arguments[0], node.Key, field); var val = GetValue(fieldName, arguments[1], node.Value, field); addMethod.Invoke(dict, new[] { key, val }); } return(dict); } else if (fieldType == typeof(Size)) { if (value != null) { var parts = value.Split(new char[] { ',' }, StringSplitOptions.RemoveEmptyEntries); return(new Size(Exts.ParseIntegerInvariant(parts[0]), Exts.ParseIntegerInvariant(parts[1]))); } return(InvalidValueAction(value, fieldType, fieldName)); } else if (fieldType == typeof(int2)) { if (value != null) { var parts = value.Split(new char[] { ',' }, StringSplitOptions.RemoveEmptyEntries); if (parts.Length != 2) { return(InvalidValueAction(value, fieldType, fieldName)); } return(new int2(Exts.ParseIntegerInvariant(parts[0]), Exts.ParseIntegerInvariant(parts[1]))); } return(InvalidValueAction(value, fieldType, fieldName)); } else if (fieldType == typeof(float2)) { if (value != null) { var parts = value.Split(new char[] { ',' }, StringSplitOptions.RemoveEmptyEntries); float xx = 0; float yy = 0; float res; if (float.TryParse(parts[0].Replace("%", ""), NumberStyles.Float, NumberFormatInfo.InvariantInfo, out res)) { xx = res * (parts[0].Contains('%') ? 0.01f : 1f); } if (float.TryParse(parts[1].Replace("%", ""), NumberStyles.Float, NumberFormatInfo.InvariantInfo, out res)) { yy = res * (parts[1].Contains('%') ? 0.01f : 1f); } return(new float2(xx, yy)); } return(InvalidValueAction(value, fieldType, fieldName)); } else if (fieldType == typeof(float3)) { if (value != null) { var parts = value.Split(new char[] { ',' }, StringSplitOptions.RemoveEmptyEntries); float x = 0; float y = 0; float z = 0; float.TryParse(parts[0], NumberStyles.Float, NumberFormatInfo.InvariantInfo, out x); float.TryParse(parts[1], NumberStyles.Float, NumberFormatInfo.InvariantInfo, out y); // z component is optional for compatibility with older float2 definitions if (parts.Length > 2) { float.TryParse(parts[2], NumberStyles.Float, NumberFormatInfo.InvariantInfo, out z); } return(new float3(x, y, z)); } return(InvalidValueAction(value, fieldType, fieldName)); } else if (fieldType == typeof(Rectangle)) { if (value != null) { var parts = value.Split(new char[] { ',' }, StringSplitOptions.RemoveEmptyEntries); return(new Rectangle( Exts.ParseIntegerInvariant(parts[0]), Exts.ParseIntegerInvariant(parts[1]), Exts.ParseIntegerInvariant(parts[2]), Exts.ParseIntegerInvariant(parts[3]))); } return(InvalidValueAction(value, fieldType, fieldName)); } else if (fieldType.IsGenericType && fieldType.GetGenericTypeDefinition() == typeof(BitSet <>)) { if (value != null) { var parts = value.Split(new char[] { ',' }, StringSplitOptions.RemoveEmptyEntries); var ctor = fieldType.GetConstructor(new[] { typeof(string[]) }); return(ctor.Invoke(new object[] { parts.Select(p => p.Trim()).ToArray() })); } return(InvalidValueAction(value, fieldType, fieldName)); } else if (fieldType.IsGenericType && fieldType.GetGenericTypeDefinition() == typeof(Nullable <>)) { if (string.IsNullOrEmpty(value)) { return(null); } var innerType = fieldType.GetGenericArguments().First(); var innerValue = GetValue("Nullable<T>", innerType, value, field); return(fieldType.GetConstructor(new[] { innerType }).Invoke(new[] { innerValue })); } else if (fieldType == typeof(DateTime)) { DateTime dt; if (DateTime.TryParseExact(value, "yyyy-MM-dd HH-mm-ss", CultureInfo.InvariantCulture, DateTimeStyles.AssumeUniversal, out dt)) { return(dt); } return(InvalidValueAction(value, fieldType, fieldName)); } else { var conv = TypeDescriptor.GetConverter(fieldType); if (conv.CanConvertFrom(typeof(string))) { try { return(conv.ConvertFromInvariantString(value)); } catch { return(InvalidValueAction(value, fieldType, fieldName)); } } } UnknownFieldAction("[Type] {0}".F(value), fieldType); return(null); }