"SQR
AlexJGriffith 2026
LGPL3+

A simple tool for placing rectangles relativly, and iterating over collections
of collections.

Place a rectangle at the top left of the screen:

(let [(w h) (values 64 64)
      (x y) (place 0 0 w h :tl :tl)]
  (love.graphics.rectangle :line x y w h))

Drawing a 3 x 4 grid:

(let [item-count 12
      padding 10
      grid-width 3
      ox 0
      oy 0
      w 64
      h 64
      iter (grid-iter item-count padding grid-width ox oy w h :c :c)] 
  (each [index x y iter]
    (love.graphics.rectangle :line x y w h)))
"

(local love (require :love))

(fn xy->position [x y w h position]
  (let [[ow oh]
        (. {:tl [0 0]
            :t [0.5 0]
            :tr [1 0]
            :r [1 0.5]
            :br [1 1]
            :b [0.5 1]
            :bl [0 1]
            :l [0 0.5]
            :c [0.5 0.5]
            :bottom-third [0.5 0.666]}
           position)]
    (values (+ x (* ow w))
            (+ y (* oh h)))))

(fn wh->alignment [w h alignment]
  (let [[ow oh]
         (. {:tl [0 0]
             :t [-0.5 0]
             :tr [-1 0]
             :r [-1 -0.5]
             :br [-1 -1]
             :b [-0.5 -1]
             :bl [0 -1]
             :l [0 -0.5]
             :c [-0.5 -0.5]}
            alignment)]
    (values (* ow w) (* oh h))))

(fn place [x y w h position alignment px? py? pw? ph?]
  (let [pw (or pw? (love.graphics.getWidth))
        ph (or ph? (love.graphics.getHeight))
        px (or px? 0)
        py (or py? 0)
        (x1 y1) (xy->position px py pw ph position)
        (x2 y2) (wh->alignment w h alignment)]
    (values (+ x x1 x2) (+ y y1 y2))))

(fn left-iter [count padding x y iw ih position alignment px? py? pw? ph?]
  (let [w (+ (* count iw) (* padding (math.max 0 (- count 1))))
        h ih
        (x y) (place x y w h position alignment px? py? pw? ph?)]
    (var index 0)
    (values
     (fn []
       (set index (+ index 1))      
       (when (<= index count)
         (values index  (+ x (* (+ padding iw) (- index 1))) y)))
     w h)))

(fn left-iter* [items padding x y position alignment px? py? pw? ph?]
  (let [count (# items)
        w (+ (accumulate [col 0 _ {: w} (ipairs items)] (+ col w))
             (* padding (- count 1)))
        h (accumulate [max 0 _ {: h} (ipairs items)] (math.max max h))
        (x y) (place x y w h position alignment px? py? pw? ph?)]
    (var index 0)
    (var ox x)
    (values
     (fn []
       (set index (+ index 1))      
       (when (<= index count)
         (local pox ox)
         (set ox (+ pox padding (. items index :w)))
         (values index  (. items index) pox y)))
     w h)))


(fn down-iter [count padding x y iw ih position alignment px? py? pw? ph?]
  (let [w iw
        h (+ (* count ih) (* padding (math.max 0 (- count 1))))
        (x y) (place x y w h position alignment px? py? pw? ph?)]    
    (var index 0)
    (values
     (fn []
       (set index (+ index 1))      
       (when (<= index count)
         (values index x (+ y (* (+ padding ih) (- index 1))))))
     w h)))

(fn down-iter* [items padding x y position alignment px? py? pw? ph?]
  (let [count (# items)
        w (accumulate [max 0 _ {: w} (ipairs items)] (math.max max w))
        h (+ (accumulate [col 0 _ {: h} (ipairs items)] (+ col h))
             (* padding (- count 1))) 
        (x y) (place x y w h position alignment px? py? pw? ph?)]
    (var index 0)
    (var oy y)
    (values
     (fn []
       (set index (+ index 1))      
       (when (<= index count)
         (local poy oy)
         (set oy (+ poy padding (. items index :h)))
         (values index  (. items index) x poy)))
     w h)))

(fn grid-iter [count padding grid-width
               x y iw ih position alignment px? py? pw? ph?]
  (let [w (+ (* grid-width iw) (* padding (- grid-width 1)))
        grid-height (math.ceil (/ count grid-width))
        h (+ (* grid-height ih) (* padding (- grid-height 1)))
        (x y) (place x y w h position alignment px? py? pw? ph?)]    
    (var index 0)
    (values
     (fn []
       (set index (+ index 1))      
       (when (<= index count)
         (local i (% (- index 1) grid-width))
         (local j (math.floor (/ (- index 1) grid-width)))
         (values index
                 (+ x (* (+ padding iw) i))
                 (+ y (* (+ padding ih) j)))))
     w h)))

(fn within [mx my x y w h]
  (and (> mx x) (<= mx (+ x w))
       (> my y) (<= my (+ y h))))

{: place : within : left-iter : left-iter* : down-iter : down-iter* : grid-iter}

Generated by alexjgriffith using scpaste at Sun Jun 28 23:26:29 2026. EDT. (original)