109 lines
4.8 KiB
Plaintext
109 lines
4.8 KiB
Plaintext
;;;; raylib [core] example - input gestures
|
|
;;;;
|
|
;;;; examples/core/core_input_gestures.c. Needed `fade`, now bound.
|
|
;;;;
|
|
;;;; The C keeps `char gestureStrings[20][32]` and TextCopy's a name into the
|
|
;;;; next slot. Flan has no mutable character buffer and no way to copy into
|
|
;;;; one, but it does not need either: the names are compile-time literals, so
|
|
;;;; the log is a `[20 string]` and a slot holds the literal itself. That is
|
|
;;;; strictly better than the C — no truncation at 32 bytes, no copy — and it
|
|
;;;; is only possible because every string that ever goes into the log is
|
|
;;;; known at compile time. A log of strings the program had BUILT could not be
|
|
;;;; written at all.
|
|
;;;;
|
|
;;;; The C's `switch (currentGesture)` over the ten gesture values is a `cond`
|
|
;;;; of keyword equalities. `get-gesture-detected` answers an `rl/Gesture` and
|
|
;;;; `(= g :gesture-tap)` compares against a member by name, checked at
|
|
;;;; compile time — so a typo here is an error and the C's `default: break`
|
|
;;;; has nothing to catch.
|
|
;;;;
|
|
;;;; A slot that has not been written yet holds a zero-length string, because a
|
|
;;;; `defonce` with no initialiser is all-bytes-zero and a string is ptr+len —
|
|
;;;; a null pointer with a length of 0. draw-text draws nothing for it. That is
|
|
;;;; the C's `{ "" }` initialiser arriving by a different route, and it is why
|
|
;;;; resetting the log below only has to reset the counter.
|
|
|
|
(import rl "vendor:raylib")
|
|
|
|
(defconst screen-width 800)
|
|
(defconst screen-height 450)
|
|
|
|
(defconst max-gesture-strings 20)
|
|
|
|
(defonce gesture-log [max-gesture-strings str])
|
|
(defonce gestures-count i32)
|
|
(defonce current-gesture rl/Gesture)
|
|
(defonce last-gesture rl/Gesture)
|
|
|
|
;; The C's switch, as a function. `:else` is its `default:` — an unnamed
|
|
;; gesture logs the empty string, which draws nothing, which is what falling
|
|
;; through the C's switch without a TextCopy leaves in the slot.
|
|
(defn gesture-name [g rl/Gesture] str
|
|
(cond
|
|
(= g :gesture-tap) "GESTURE TAP"
|
|
(= g :gesture-double-tap) "GESTURE DOUBLETAP"
|
|
(= g :gesture-hold) "GESTURE HOLD"
|
|
(= g :gesture-drag) "GESTURE DRAG"
|
|
(= g :gesture-swipe-right) "GESTURE SWIPE RIGHT"
|
|
(= g :gesture-swipe-left) "GESTURE SWIPE LEFT"
|
|
(= g :gesture-swipe-up) "GESTURE SWIPE UP"
|
|
(= g :gesture-swipe-down) "GESTURE SWIPE DOWN"
|
|
(= g :gesture-pinch-in) "GESTURE PINCH IN"
|
|
(= g :gesture-pinch-out) "GESTURE PINCH OUT"
|
|
:else ""))
|
|
|
|
(defn main [] ()
|
|
(rl/init-window screen-width screen-height
|
|
"raylib [core] example - input gestures")
|
|
(defer (rl/close-window))
|
|
|
|
(rl/set-target-fps 60)
|
|
|
|
(let [touch-area (rl/Rectangle {.x 220.0 .y 10.0
|
|
.width (- (f32 screen-width) 230.0)
|
|
.height (- (f32 screen-height) 20.0)})]
|
|
(until (rl/window-should-close)
|
|
;; Update
|
|
(set last-gesture current-gesture)
|
|
(set current-gesture (rl/get-gesture-detected))
|
|
(let [touch (rl/get-touch-position 0)]
|
|
|
|
(when (and (rl/check-collision-point-rec touch touch-area)
|
|
(not (= current-gesture :gesture-none))
|
|
(not (= current-gesture last-gesture)))
|
|
(set (at gesture-log gestures-count) (gesture-name current-gesture))
|
|
(set gestures-count (+ gestures-count 1))
|
|
;; Full: start over. The stale slots below the counter are never
|
|
;; drawn, so they do not have to be cleared the way the C clears
|
|
;; them — the loop below is bounded by gestures-count.
|
|
(when (>= gestures-count max-gesture-strings)
|
|
(set gestures-count 0)))
|
|
|
|
;; Draw
|
|
(rl/with-drawing
|
|
(rl/clear-background rl/raywhite)
|
|
|
|
(rl/draw-rectangle-rec touch-area rl/gray)
|
|
(rl/draw-rectangle 225 15 (- screen-width 240) (- screen-height 30)
|
|
rl/raywhite)
|
|
|
|
(rl/draw-text "GESTURES TEST AREA" (- screen-width 270)
|
|
(- screen-height 40) 20 (rl/fade rl/gray 0.5))
|
|
|
|
(dotimes [i gestures-count]
|
|
(if (= 0 (% i 2))
|
|
(rl/draw-rectangle 10 (+ 30 (* 20 i)) 200 20
|
|
(rl/fade rl/lightgray 0.5))
|
|
(rl/draw-rectangle 10 (+ 30 (* 20 i)) 200 20
|
|
(rl/fade rl/lightgray 0.3)))
|
|
;; The newest entry in maroon and the rest in dark grey, as the C
|
|
;; has it.
|
|
(rl/draw-text (at gesture-log i) 35 (+ 36 (* 20 i)) 10
|
|
(if (< i (- gestures-count 1)) rl/darkgray rl/maroon)))
|
|
|
|
(rl/draw-rectangle-lines 10 29 200 (- screen-height 50) rl/gray)
|
|
(rl/draw-text "DETECTED GESTURES" 50 15 10 rl/gray)
|
|
|
|
(unless (= current-gesture :gesture-none)
|
|
(rl/draw-circle-v touch 30.0 rl/maroon)))))))
|