Middleware
A Quil middleware is a function which takes a map containing options passed to defsketch
or sketch
and returns updated map. The simplest middleware (which does nothing) is the identity
function: it takes a map and returns the map unmodified. The idea is similar to Ring middleware. Middleware support was added in Quil 2.1.0.
You can find all built-in middleware in the quil.middleware
namespace. All middleware available both in clj and cljs versions, if not stated otherwise. Here is the list:
-
fun-mode
- introduces functional mode. -
navigation-3d
- enables shooter-like navigation in 3D space. Check wiki article for more details. -
pause-on-error
- pauses sketch, if some handler throws an exception. Prints info about error on screen and waits for key press. Allows user to fix the error and reload broken handler on-fly. Not available in cljs.
To enable middleware you can use :middleware
option for defsketch
or sketch
. For example, suppose that we have a my-middleware
function - our custom middleware which does something. Here is how we use it:
(q/defsketch my-sketch
:size [500 500]
:draw draw
:middleware [my-middleware])
You can see that the :middleware
option takes a vector of middlewares so you can use multiple middleware functions at the same time. The functions in a middleware vector [f g h]
are applied in following order: (f (g (h options)))
, just like in the comp function.
Our middleware will draw the current frame rate in the top left corner of the screen. Here is the middleware:
(ns middleware-example
(:require [quil.core :as q]))
(defn show-frame-rate [options]
(let [; retrieve existing draw function or use empty one if not present
draw (:draw options (fn []))
; updated-draw will replace draw
updated-draw (fn []
(draw) ; call user-provided draw function
(q/fill 0)
(q/text-num (q/current-frame-rate) 10 10))]
; set updated-draw as :draw function
(assoc options :draw updated-draw)))
(defn setup []
(q/frame-rate 30)
(q/color-mode :hsb))
; draw ellipse of random size and random color
(defn draw []
(q/background 240)
(let [period 100
cur (mod (q/frame-count) period)
angle (q/map-range cur
0 period
0 q/PI)]
(q/fill (q/map-range cur 0 period 0 255) 255 255)
(q/ellipse 100 100
(* 150 (q/sin angle))
(* 150 (q/cos angle)))))
(q/defsketch my-sketch
:size [200 200]
:setup setup
:draw draw
:middleware [show-frame-rate])
And the result:
Note: This middleware is not ideal and it can be improved. For example, it overrides fill
value when it would be better if we store current fill and restore it back after we drew frame rate.
- middleware for creating gifs from sketch;
- middleware for drag and zoom-in/zoom-out support: similar to how it is done in maps or mobiles;