package rect Rect :: struct($T: typeid) { l, r, t, b: T, } RECTF_INF :: RectF { max(f32), -max(f32), max(f32), -max(f32) } RectF :: Rect(f32) RectI :: Rect(int) i2f :: proc(rect: RectI) -> RectF { return { f32(rect.l), f32(rect.r), f32(rect.t), f32(rect.b) } } wh :: proc(x, y, w, h: $T) -> (res: Rect(T)) { res.l = x res.r = x + w res.t = y res.b = y + h return } sized :: proc(rect: ^Rect($T), pos: [2]T, size: [2]T) { rect.l = pos.x rect.r = pos.x + size.x rect.t = pos.y rect.b = pos.y + size.y } overlap :: proc(a, b: Rect($T)) -> bool { return b.r >= a.l && b.l <= a.r && b.b >= a.t && b.t <= a.b } inf_push :: proc(rect: ^Rect($T), pos: [2]T) { rect.l = min(rect.l, pos.x) rect.r = max(rect.r, pos.x) rect.t = min(rect.t, pos.y) rect.b = max(rect.b, pos.y) } // center :: proc(rect: Rect($T)) -> [2]T { // return { f32(rect.l) + f32(rect.r - rect.l) / 2, f32(rect.t) + f32(rect.b - rect.t) / 2 } // } valid :: proc(rect: Rect($T)) -> bool { return (rect.r - rect.l) > 0 && (rect.b - rect.t) > 0 } invalid :: #force_inline proc(rect: Rect($T)) -> bool { return !valid(rect) } intersection :: proc(a, b: Rect($T)) -> (res: Rect(T)) { res = a if a.l < b.l do res.l = b.l if a.t < b.t do res.t = b.t if a.r > b.r do res.r = b.r if a.b > b.b do res.b = b.b return } margin :: proc(a: Rect($T), value: T) -> Rect(T) { a := a a.l += value a.t += value a.r -= value a.b -= value return a } offset :: proc(rect: Rect($T), x, y: T) -> (res: Rect(T)) { res = rect res.l += x res.r += x res.t += y res.b += y return } contains :: proc(a: Rect($T), x, y: T) -> bool { return a.l <= x && a.r > x && a.t <= y && a.b > y } widthf :: proc(a: RectI) -> f32 { return f32(a.r - a.l) } heightf :: proc(a: RectI) -> f32 { return f32(a.b - a.t) } widthi :: proc(a: RectI) -> int { return int(a.r - a.l) } heighti :: proc(a: RectI) -> int { return int(a.b - a.t) } splitv :: proc(rect: RectF) -> (left, right: RectF) { left = rect right = rect left.r = rect.l + (rect.r - rect.l) / 2 right.l = left.r return } cut_left :: proc(rect: ^Rect($T), a: T) -> (res: Rect(T)) { res = rect^ res.r = rect.l + a rect.l = res.r return } cut_right :: proc(rect: ^Rect($T), a: T) -> (res: Rect(T)) { res = rect^ res.l = rect.r - a rect.r = res.l return } cut_top :: proc(rect: ^Rect($T), a: T) -> (res: Rect(T)) { res = rect^ res.b = rect.t + a rect.t = res.b return } cut_bottom :: proc(rect: ^Rect($T), a: T) -> (res: Rect(T)) { res = rect^ res.t = rect.b - a rect.b = res.t return }