diff --git a/Assets/PerfectWorld/Scripts/Managers/ARect.cs b/Assets/PerfectWorld/Scripts/Managers/ARect.cs index 48dff7a51f..cd9a7d2cc8 100644 --- a/Assets/PerfectWorld/Scripts/Managers/ARect.cs +++ b/Assets/PerfectWorld/Scripts/Managers/ARect.cs @@ -29,6 +29,41 @@ namespace BrewMonster.Scripts this.bottom = bottom; } + // helpers for int/float only + static int Cmp(T a, T b) => Comparer.Default.Compare(a, b); + static T Min(T a, T b) => Cmp(a, b) <= 0 ? a : b; + static T Max(T a, T b) => Cmp(a, b) >= 0 ? a : b; + static T Add(T a, T b) + { + if (typeof(T) == typeof(int)) return (T)(object)((int)(object)a + (int)(object)b); + if (typeof(T) == typeof(float)) return (T)(object)((float)(object)a + (float)(object)b); + throw new NotSupportedException("ARect supports only int and float"); + } + static T Sub(T a, T b) + { + if (typeof(T) == typeof(int)) return (T)(object)((int)(object)a - (int)(object)b); + if (typeof(T) == typeof(float)) return (T)(object)((float)(object)a - (float)(object)b); + throw new NotSupportedException("ARect supports only int and float"); + } + static T Neg(T a) + { + if (typeof(T) == typeof(int)) return (T)(object)(-(int)(object)a); + if (typeof(T) == typeof(float)) return (T)(object)(-(float)(object)a); + throw new NotSupportedException("ARect supports only int and float"); + } + static bool IsZero(T v) + { + if (typeof(T) == typeof(int)) return (int)(object)v == 0; + if (typeof(T) == typeof(float)) return (float)(object)v == 0f; + throw new NotSupportedException("ARect supports only int and float"); + } + static T FromInt(int v) + { + if (typeof(T) == typeof(int)) return (T)(object)v; + if (typeof(T) == typeof(float)) return (T)(object)(float)v; + throw new NotSupportedException("ARect supports only int and float"); + } + // == and != operator public static bool operator !=(ARect rc1, ARect rc2) { @@ -45,17 +80,21 @@ namespace BrewMonster.Scripts // + and - operator public static ARect operator +(ARect rc1, ARect rc2) { - dynamic l = rc1.left, t = rc1.top, r = rc1.right, b = rc1.bottom; - dynamic l2 = rc2.left, t2 = rc2.top, r2 = rc2.right, b2 = rc2.bottom; - ARect result = new ARect(l + l2, t + t2, r + r2, b + b2); - return result; + return new ARect( + Add(rc1.left, rc2.left), + Add(rc1.top, rc2.top), + Add(rc1.right, rc2.right), + Add(rc1.bottom, rc2.bottom) + ); } public static ARect operator -(ARect rc1, ARect rc2) { - return new ARect((dynamic)rc1.left - (dynamic)rc2.left, - (dynamic)rc1.top - (dynamic)rc2.top, - (dynamic)rc1.right - (dynamic)rc2.right, - (dynamic)rc1.bottom - (dynamic)rc2.bottom); + return new ARect( + Sub(rc1.left, rc2.left), + Sub(rc1.top, rc2.top), + Sub(rc1.right, rc2.right), + Sub(rc1.bottom, rc2.bottom) + ); } //public static ARect operator +(ARect rc1, APoint pt) //{ @@ -81,17 +120,19 @@ namespace BrewMonster.Scripts if (rc1.IsEmpty() || rc2.IsEmpty()) return new ARect(default, default, default, default); - dynamic l1 = rc1.left, r1 = rc1.right, t1 = rc1.top, b1 = rc1.bottom; - dynamic l2 = rc2.left, r2 = rc2.right, t2 = rc2.top, b2 = rc2.bottom; + var l1 = rc1.left; var r1 = rc1.right; var t1 = rc1.top; var b1 = rc1.bottom; + var l2 = rc2.left; var r2 = rc2.right; var t2 = rc2.top; var b2 = rc2.bottom; - if (l1 >= r2 || l2 >= r1 || - t1 >= b2 || t2 >= b1) + if (Cmp(l1, r2) >= 0 || Cmp(l2, r1) >= 0 || + Cmp(t1, b2) >= 0 || Cmp(t2, b1) >= 0) return new ARect(default, default, default, default); - return new ARect(l1 > l2 ? l1 : l2, - t1 > t2 ? t1 : t2, - r1 < r2 ? r1 : r2, - b1 < b2 ? b1 : b2); + return new ARect( + Max(l1, l2), + Max(t1, t2), + Min(r1, r2), + Min(b1, b2) + ); } public static ARect operator |(ARect rc1, ARect rc2) @@ -102,19 +143,26 @@ namespace BrewMonster.Scripts if (rc2.IsEmpty()) return rc1; - dynamic l1 = rc1.left, r1 = rc1.right, t1 = rc1.top, b1 = rc1.bottom; - dynamic l2 = rc2.left, r2 = rc2.right, t2 = rc2.top, b2 = rc2.bottom; + var l1 = rc1.left; var r1 = rc1.right; var t1 = rc1.top; var b1 = rc1.bottom; + var l2 = rc2.left; var r2 = rc2.right; var t2 = rc2.top; var b2 = rc2.bottom; - return new ARect(l1 < l2 ? l1 : l2, - t1 < t2 ? t1 : t2, - r1 > r2 ? r1 : r2, - b1 > b2 ? b1 : b2); + return new ARect( + Min(l1, l2), + Min(t1, t2), + Max(r1, r2), + Max(b1, b2) + ); } public static ARect operator +(ARect rc) { return rc; } public static ARect operator -(ARect rc) { - return new ARect(-(dynamic)rc.left, -(dynamic)rc.top, -(dynamic)rc.right, -(dynamic)rc.bottom); + return new ARect( + Neg(rc.left), + Neg(rc.top), + Neg(rc.right), + Neg(rc.bottom) + ); } // = operator @@ -123,18 +171,18 @@ namespace BrewMonster.Scripts // += and -= operator public ARect AdditionAssign(ARect rc) { - left += (dynamic)rc.left; - top += (dynamic)rc.top; - right += (dynamic)rc.right; - bottom += (dynamic)rc.bottom; + left = Add(left, rc.left); + top = Add(top, rc.top); + right = Add(right, rc.right); + bottom = Add(bottom, rc.bottom); return this; } public ARect SubtractionAssign(ARect rc) { - left -= (dynamic)rc.left; - top -= (dynamic)rc.top; - right -= (dynamic)rc.right; - bottom -= (dynamic)rc.bottom; + left = Sub(left, rc.left); + top = Sub(top, rc.top); + right = Sub(right, rc.right); + bottom = Sub(bottom, rc.bottom); return this; } //public ARect AdditionAssign(APoint pt) { left += pt.x; top += pt.y; right += pt.x; bottom += pt.y; return this; } @@ -143,12 +191,12 @@ namespace BrewMonster.Scripts // Get width of rectangle public T Width() { - return (dynamic)right - (dynamic)left; + return Sub(right, left); } // Get height of rectangle public T Height() { - return (dynamic)bottom - (dynamic)top; + return Sub(bottom, top); } // Get center point of rectangle //public APoint CenterPoint() { return new APoint((left + right) / 2, (top + bottom) / 2); } @@ -164,9 +212,7 @@ namespace BrewMonster.Scripts // Point in rectangle public bool PtInRect(T x, T y) { - dynamic valueX = x; - dynamic valueY = y; - return (valueX >= left && valueX < right && valueY >= top && valueY < bottom) ? true : false; + return Cmp(x, left) >= 0 && Cmp(x, right) < 0 && Cmp(y, top) >= 0 && Cmp(y, bottom) < 0; } //public bool PtInRect(APoint pt) { return PtInRect(pt.x, pt.y); } @@ -176,14 +222,14 @@ namespace BrewMonster.Scripts // operator |, operator |=, operator &, and operator &= void Normalize() { - if ((dynamic)left > right) - a_Swap(left, right); + if (Cmp(left, right) > 0) + a_Swap(ref left, ref right); - if ((dynamic)top > bottom) - a_Swap(top, bottom); + if (Cmp(top, bottom) > 0) + a_Swap(ref top, ref bottom); } - private void a_Swap(T lhs, T rhs) + private void a_Swap(ref T lhs, ref T rhs) { T tmp; tmp = lhs; @@ -194,12 +240,12 @@ namespace BrewMonster.Scripts // All members are 0 ? public bool IsRectNull() { - return ((dynamic)left == 0 && (dynamic)top == 0 && (dynamic)right == 0 && (dynamic)bottom == 0); + return IsZero(left) && IsZero(top) && IsZero(right) && IsZero(bottom); } // Rectangle is empty ? public bool IsEmpty() { - return ((dynamic)Width() == 0 || (dynamic)Height() == 0); + return IsZero(Width()) || IsZero(Height()); } // Set all members to 0 public void Clear() @@ -209,55 +255,58 @@ namespace BrewMonster.Scripts // Deflate rectangle public void Deflate(T x, T y) { - left += (dynamic)x; - top += (dynamic)y; - right -= (dynamic)x; - bottom -= (dynamic)y; + left = Add(left, x); + top = Add(top, y); + right = Sub(right, x); + bottom = Sub(bottom, y); } public void Deflate(ARect rc) { - left += (dynamic)rc.left; - top += (dynamic)rc.top; - right -= (dynamic)rc.right; - bottom -= (dynamic)rc.bottom; + left = Add(left, rc.left); + top = Add(top, rc.top); + right = Sub(right, rc.right); + bottom = Sub(bottom, rc.bottom); } public void Deflate(T l, T t, T r, T b) { - left += (dynamic)l; - top += (dynamic)t; - right -= (dynamic)r; - bottom -= (dynamic)b; + left = Add(left, l); + top = Add(top, t); + right = Sub(right, r); + bottom = Sub(bottom, b); } // Inflate rectangle public void Inflate(T x, T y) { - left -= (dynamic)x; - top -= (dynamic)y; - right += (dynamic)x; - bottom += (dynamic)y; + left = Sub(left, x); + top = Sub(top, y); + right = Add(right, x); + bottom = Add(bottom, y); } public void Inflate(ARect rc) { - left -= (dynamic)rc.left; - top -= (dynamic)rc.top; - right += (dynamic)rc.right; - bottom += (dynamic)rc.bottom; + left = Sub(left, rc.left); + top = Sub(top, rc.top); + right = Add(right, rc.right); + bottom = Add(bottom, rc.bottom); } public void Inflate(T l, T t, T r, T b) { - left -= (dynamic)l; - top -= (dynamic)t; - right += (dynamic)r; - bottom += (dynamic)b; + left = Sub(left, l); + top = Sub(top, t); + right = Add(right, r); + bottom = Add(bottom, b); } // Offset rectangle - public void Offset(T x, T y) + public void Offset(int x, int y) { - left += (dynamic)x; - top += (dynamic)y; - right += (dynamic)x; - bottom += (dynamic)y; + var dx = FromInt(x); + var dy = FromInt(y); + left = Add(left, dx); + top = Add(top, dy); + right = Add(right, dx); + bottom = Add(bottom, dy); } + //public void Offset(APoint pt) { this += pt; } // Set rectangle as union result public void SetUnion(ARect rc1, ARect rc2)