1 module Engine.math; 2 3 public import gl3n.linalg; 4 import std.traits; 5 6 struct dirty(T) { 7 bool dirty = true; 8 T val; 9 10 alias val this; 11 12 this(T v) { 13 val = v; 14 } 15 16 @property opDispatch(string s, Args...)(Args args) { 17 static if (mixin("isSomeFunction!(T."~s~")")) { 18 static if(mixin("isFuncMutable!(T."~s~")") && !mixin("functionAttributes!(T."~s~") & FunctionAttribute.property")) { 19 dirty = true; 20 } 21 static if (mixin("is(ReturnType!(T."~s~") == void)")) { 22 mixin("val." ~ s ~ "(args);"); 23 } else { 24 static if (args.length > 0 && mixin("functionAttributes!(T."~s~") & FunctionAttribute.property")) { 25 dirty = true; 26 mixin("val." ~ s ~ " = cast(typeof(val." ~ s ~"))args[0];"); 27 } else { 28 return mixin("val." ~ s ~ "(args)"); 29 } 30 } 31 } else { 32 static if(args.length > 0) { 33 dirty = true; 34 mixin("val." ~ s ~ " = cast(typeof(val." ~ s ~ "))args[0];"); 35 } else { 36 return mixin("val." ~ s); 37 } 38 } 39 } 40 41 void opOpAssign(string op, R)(R r) { 42 dirty = true; 43 mixin("val" ~ op ~ "= r;"); 44 } 45 46 void opAssign(R)(auto ref const R r) { 47 static if (__traits(compiles, val.opAssign!R(r))) { 48 val.opAssign!R(r); 49 } else { 50 val = r; 51 } 52 dirty = true; 53 } 54 55 T opUnary(string s)() { 56 dirty = true; 57 return mixin(s ~ "val"); 58 } 59 } 60 61 template isFuncMutable(T...) if (T.length == 1) 62 { 63 enum bool isFuncMutable = !(is(typeof(T[0]) == const) || is(typeof(T[0]) == immutable)); 64 } 65 66 67 alias Rect!(int) recti; 68 alias Rect!(float) rect; 69 70 struct Rect(T) { 71 alias Vector!(T, 2) vectp; 72 vectp min = vectp(0,0); 73 vectp max = vectp(0,0); 74 75 static Rect Zero = Rect(); 76 77 78 this(T width, T height) { 79 max = vectp(width,height); 80 } 81 82 void add(vectp v) { 83 min += v; 84 max += v; 85 } 86 87 nothrow this(vectp min, vectp max) { 88 this.min = min; 89 this.max = max; 90 } 91 92 // Empty returns whether the rectangle contains no points. 93 nothrow pure bool Empty()() const { 94 return min.x >= max.x || min.y >= max.y; 95 } 96 97 nothrow pure T Dx()() const { 98 return max.x - min.x; 99 } 100 101 nothrow pure T Dy()() const { 102 return max.y - min.y; 103 } 104 105 nothrow pure bool In()(Rect s) const { 106 if (Empty()) { 107 return true; 108 } 109 // Note that r.Max is an exclusive bound for r, so that this.In(s) 110 // does not require that this.max.In(s). 111 return s.min.x <= min.x && max.x <= s.max.x && 112 s.min.y <= min.y && max.y <= s.max.y; 113 } 114 115 //returns an AABB that holds both a and b. 116 public static nothrow Rect!T Merge()(auto ref const Rect!T a,auto ref const Rect!T b ) { 117 return Rect!T( 118 minv(a.min, b.min), 119 maxv(a.max, b.max), 120 ); 121 } 122 123 T Area()() { 124 return (max.x - min.x) * (max.y - min.y); 125 } 126 127 static T MergedArea()(auto ref const Rect!T a,auto ref const Rect!T b ) { 128 return (maxv(a.max.x, b.max.x) - minv(a.min.x, b.min.x)) * (maxv(a.max.y, b.max.y) - minv(a.min.y, b.min.y)); 129 } 130 131 static T Proximity()(auto ref const Rect!T a,auto ref const Rect!T b ) { 132 return abs(a.min.x+a.max.x-b.min.x-b.max.x) + abs(a.min.y+a.max.y-b.min.y-b.max.y); 133 } 134 135 static bool Intersects()(auto ref const Rect!T a,auto ref const Rect!T b ) { 136 return (a.min.x <= b.max.x && b.min.x <= a.max.x && a.min.y <= b.max.y && b.min.y <= a.max.y); 137 } 138 139 static bool Contains()(auto ref const Rect!T aabb,auto ref const Rect!T other ) { 140 return aabb.min.x <= other.min.x && 141 aabb.max.x >= other.max.x && 142 aabb.min.y <= other.min.y && 143 aabb.max.y >= other.max.y; 144 } 145 146 147 nothrow static T abs()(T v) { 148 if (v > 0) 149 return v; 150 return -v; 151 } 152 153 nothrow static T minv()(T v1,T v2) { 154 if (v1 > v2) 155 return v2; 156 return v1; 157 } 158 159 nothrow static T maxv()(T v1,T v2) { 160 if (v1 > v2) 161 return v1; 162 return v2; 163 } 164 165 166 nothrow static vectp minv()(vectp v1,vectp v2) { 167 vectp o; 168 if (v1.x < v2.x) { 169 o.x = v1.x; 170 } else { 171 o.x = v2.x; 172 } 173 174 if (v1.y < v2.y) { 175 o.y = v1.y; 176 } else { 177 o.y = v2.y; 178 } 179 return o; 180 } 181 182 nothrow static vectp maxv()(vectp v1,vectp v2) { 183 vectp o; 184 if (v1.x > v2.x) { 185 o.x = v1.x; 186 } else { 187 o.x = v2.x; 188 } 189 190 if (v1.y > v2.y) { 191 o.y = v1.y; 192 } else { 193 o.y = v2.y; 194 } 195 return o; 196 } 197 }