1 module anchovy.utils.rect; 2 3 import std.conv; 4 import dlib.math.utils: clampValue = clamp; 5 import dlib.math.vector; 6 import anchovy.utils.rectoffset; 7 8 struct Rect 9 { 10 union 11 { 12 struct 13 { 14 int x, y, width, height; 15 } 16 int[4] arrayof; 17 } 18 19 this(int[4] array) @safe 20 { 21 arrayof = array; 22 } 23 24 this(int a, int b, int c, int d) @safe 25 { 26 x = a; 27 y = b; 28 width = c; 29 height = d; 30 } 31 32 this(ivec2 position, ivec2 size) 33 { 34 x = position.x; 35 y = position.y; 36 width = size.x; 37 height = size.y; 38 } 39 40 void move(ivec2 delta) 41 { 42 x += delta.x; 43 y += delta.y; 44 } 45 46 bool contains(ivec2 point) nothrow @trusted 47 { 48 return contains(point.x, point.y); 49 } 50 51 bool contains(int pointX, int pointY) nothrow @trusted 52 { 53 if(pointX < x) return false; 54 if(pointY < y) return false; 55 if(pointX > x + width) return false; 56 if(pointY > y + height) return false; 57 return true; 58 } 59 60 void cropOffset(RectOffset offset) nothrow 61 { 62 x += offset.left; 63 y += offset.top; 64 width -= offset.horizontal; 65 height -= offset.vertical; 66 } 67 68 Rect croppedByOffset(RectOffset offset) nothrow 69 { 70 Rect result; 71 result.x = x + offset.left; 72 result.y = y + offset.top; 73 result.width = width - offset.horizontal; 74 result.height = height - offset.vertical; 75 return result; 76 } 77 78 /// Increases size by deltaSize. 79 void grow(ivec2 deltaSize) 80 { 81 width += deltaSize.x; 82 height += deltaSize.y; 83 84 if (width < 0) width = 0; 85 if (height < 0) height = 0; 86 } 87 88 Rect growed(ivec2 deltaSize) 89 { 90 Rect newRect; 91 newRect.width = width + deltaSize.x; 92 newRect.height = height + deltaSize.y; 93 94 if (newRect.width < 0) newRect.width = 0; 95 if (newRect.height < 0) newRect.height = 0; 96 97 return newRect; 98 } 99 100 Rect relativeToParent(Rect parent) @safe 101 { 102 return Rect(x + parent.x, y + parent.y, width, height); 103 } 104 105 /// Returns true if size was changed 106 void clampSize(uvec2 minSize, uvec2 maxSize) nothrow 107 { 108 if (maxSize.x == 0) 109 { 110 width = clampValue!uint(width, minSize.x, width); 111 } 112 else 113 { 114 width = clampValue!uint(width, minSize.x, maxSize.x); 115 } 116 117 if (maxSize.y == 0) 118 { 119 height = clampValue!uint(height, minSize.y, height); 120 } 121 else 122 { 123 height = clampValue!uint(height, minSize.y, maxSize.y); 124 } 125 } 126 127 ivec2 position() @property 128 { 129 return ivec2(x, y); 130 } 131 132 ivec2 size() @property 133 { 134 return ivec2(width, height); 135 } 136 137 string toString() 138 { 139 return to!string(arrayof); 140 } 141 } 142 143 unittest 144 { 145 Rect rect = Rect(-5, -5, 10, 10); 146 147 assert(!rect.contains(-10, 0)); 148 assert(!rect.contains(6, 0)); 149 assert(!rect.contains(0, -6)); 150 assert(!rect.contains(9, 6)); 151 assert(rect.contains(0, 0)); 152 }