flan/examples/core-input-gestures.fln

107 lines
4.4 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
;;;; `once` 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"
const screen-width = 800
const screen-height = 450
const max-gesture-strings = 20
once gesture-log: [max-gesture-strings str]
once gestures-count: i32
once current-gesture: rl/Gesture
once 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.
fn gesture-name(g: rl/Gesture) -> str
if g == :gesture-tap
"GESTURE TAP"
elif g == :gesture-double-tap
"GESTURE DOUBLETAP"
elif g == :gesture-hold
"GESTURE HOLD"
elif g == :gesture-drag
"GESTURE DRAG"
elif g == :gesture-swipe-right
"GESTURE SWIPE RIGHT"
elif g == :gesture-swipe-left
"GESTURE SWIPE LEFT"
elif g == :gesture-swipe-up
"GESTURE SWIPE UP"
elif g == :gesture-swipe-down
"GESTURE SWIPE DOWN"
elif g == :gesture-pinch-in
"GESTURE PINCH IN"
elif g == :gesture-pinch-out
"GESTURE PINCH OUT"
else
""
fn 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
last-gesture = current-gesture
current-gesture = rl/get-gesture-detected()
let touch = rl/get-touch-position(0)
if rl/check-collision-point-rec(touch, touch-area) and not current-gesture == :gesture-none and not current-gesture == last-gesture
gesture-log[gestures-count] = gesture-name(current-gesture)
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.
if gestures-count >= max-gesture-strings
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))
for i in range(gestures-count)
if 0 == i % 2
rl/draw-rectangle(10, 30 + 20 * i, 200, 20,
rl/fade(rl/lightgray, 0.5))
else
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(gesture-log[i], 35, 36 + 20 * i, 10,
if i < gestures-count - 1 then rl/darkgray else 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)