Three shapes, two text, three textures, one models and one core, picked for binding surface rather than for how they look. shapes-basic-shapes brings in six draw families nothing had called — the circle and rectangle gradients, the triangles, all three poly draws — and is the first call in the corpus to pass two Colors or three Vector2s at once. shapes-collision-area is get-collision-rec, the only binding that takes two Rectangles and answers a third, on a frame path. shapes-following-eyes is the raymath gap measured rather than worked around: every line of it is vector arithmetic written without a vector library, the way the C writes it. text-input-box drains get-char-pressed's queue, which no example had read, and needed a MouseCursor defenum for set-mouse-cursor. text-writing-anim replaces TextSubtext — unbindable, it answers a pointer into a rotating static buffer — with (string (slice b 0 n)), which is the same operation without the shared state. textures-image-generation runs nine Gen* calls and the gen/upload/unload-image path, all procedural, no file on disk. textures-fog-of-war needed a TextureFilter defenum: the smooth fog edge is entirely :bilinear on a 25x15 render texture, and it is also the first draw-texture-pro with a negative source height. textures-mouse-painting is the same render texture used as a document rather than as scratch, plus the round trip back off the GPU — load-image-from-texture, image-flip-vertical, export-image — which nothing had run. models-box-collisions is the counterexample to "a models example is a binding exercise": nothing in it is a Model, and one BoundingBox defstruct un-refuses four functions. core-3d-picking is the only caller anywhere for Ray and RayCollision, and picking is the inverse of the get-world-to-screen the corpus already had. Added to vendor/raylib: defstructs BoundingBox, Ray and RayCollision; defenums MouseCursor and TextureFilter with their mapping lines in bindings; hand-written declare-c for SetMouseCursor, SetTextureFilter, DrawCubeV, DrawSphere, DrawSphereWires, DrawRay and GetScreenToWorldRay, each excluded from the generated half on the rule bindings already states. generated.flan regenerated against raylib 5.5: 272 declarations, 117 refused, every defstruct, hand-written declare-c and mapped constant agreeing with the header.
141 lines
6.0 KiB
Plaintext
141 lines
6.0 KiB
Plaintext
;;;; raylib [text] example - input box
|
|
;;;;
|
|
;;;; examples/text/text_input_box.c. Two things in this file exist nowhere
|
|
;;;; else in the corpus.
|
|
;;;;
|
|
;;;; The first is get-char-pressed. Everything ported so far reads input as
|
|
;;;; state — key-down?, key-pressed?, the mouse position — and this is the
|
|
;;;; only example that drains a *queue*: raylib buffers the characters the
|
|
;;;; platform produced since the last frame, already through the keyboard
|
|
;;;; layout and the dead keys, and hands them back one at a time until it
|
|
;;;; answers 0. The loop that empties it is the point of the example, and a
|
|
;;;; program that read the queue once per frame instead would silently drop
|
|
;;;; the second character of a fast pair. It is a plain i32 out of the
|
|
;;;; generated bindings; nothing needed adding for it.
|
|
;;;;
|
|
;;;; The second is set-mouse-cursor, which needed a new defenum. raylib's
|
|
;;;; header says `int cursor` and means one of eleven MOUSE_CURSOR_ values, so
|
|
;;;; the Flan face is `MouseCursor` — hand-written in raylib.flan beside the
|
|
;;;; other cursor calls, excluded from the generated half, and mapped in
|
|
;;;; `bindings` so the eleven members are checked against the header. See the
|
|
;;;; comment there: this call is made on every frame off a hover test, and the
|
|
;;;; failure an i32 would allow is not a crash but a pointer in the wrong
|
|
;;;; shape, which nothing reports.
|
|
;;;;
|
|
;;;; The text buffer, and what it says about strings. The C keeps a
|
|
;;;; `char name[MAX_INPUT_CHARS + 1]` and maintains the NUL itself; here it is
|
|
;;;; a `[9 u8]` with no terminator, and every use is `(string (slice name 0
|
|
;;;; letter-count))`. A Flan string is a pointer and a length, and the shim
|
|
;;;; that calls DrawText copies it and NUL-terminates the copy
|
|
;;;; (lib/shim.ml) — so the extra byte the C needs has no counterpart here and
|
|
;;;; the buffer is exactly as long as the characters it can hold. The two
|
|
;;;; draws and the measure all take the same slice, so they cannot disagree
|
|
;;;; about where the text ends.
|
|
;;;;
|
|
;;;; Dropped from the C: its IsAnyKeyPressed helper, which is defined at the
|
|
;;;; bottom of the file and called from nowhere.
|
|
|
|
(import rl "vendor:raylib")
|
|
(import d "digits.flan")
|
|
|
|
(defconst screen-width 800)
|
|
(defconst screen-height 450)
|
|
|
|
(defconst max-input-chars 9)
|
|
|
|
;; No +1: see the header comment. There is no NUL to leave room for.
|
|
(defvar name [9 u8])
|
|
(defvar letter-count i32)
|
|
|
|
(defvar text-box rl/Rectangle)
|
|
(defvar mouse-on-text bool)
|
|
(defvar frames-counter i32)
|
|
|
|
(defn main [] ()
|
|
(rl/init-window screen-width screen-height
|
|
"raylib [text] example - input box")
|
|
(defer (rl/close-window))
|
|
|
|
(set name (array max-input-chars u8))
|
|
(set letter-count 0)
|
|
|
|
(set text-box (rl/Rectangle {.x (- (/ (f32 screen-width) 2.0) 100.0)
|
|
.y 180.0 .width 225.0 .height 50.0}))
|
|
(set mouse-on-text false)
|
|
(set frames-counter 0)
|
|
|
|
(rl/set-target-fps 60)
|
|
|
|
(until (rl/window-should-close?)
|
|
;; Update
|
|
(set mouse-on-text
|
|
(rl/collision-point-rec? (rl/get-mouse-position) text-box))
|
|
|
|
(if mouse-on-text
|
|
(do
|
|
(rl/set-mouse-cursor :ibeam)
|
|
|
|
;; Drain the character queue. raylib answers 0 when it is empty, and
|
|
;; more than one character can arrive in a single frame — holding a
|
|
;; key with the platform's repeat on is the ordinary way that happens.
|
|
(let [key (rl/get-char-pressed)]
|
|
(while (> key 0)
|
|
;; 32..125 is the printable ASCII range the C accepts. Anything
|
|
;; outside it — an accented letter, a control character — is
|
|
;; dropped rather than stored, because the buffer is bytes and a
|
|
;; codepoint above 127 would need more than one of them.
|
|
(when (and (>= key 32) (<= key 125) (< letter-count max-input-chars))
|
|
(set (at name letter-count) (u8 key))
|
|
(set letter-count (+ letter-count 1)))
|
|
(set key (rl/get-char-pressed))))
|
|
|
|
(when (rl/key-pressed? :backspace)
|
|
(set letter-count (- letter-count 1))
|
|
(when (< letter-count 0) (set letter-count 0))))
|
|
(rl/set-mouse-cursor :default))
|
|
|
|
;; The blink phase only runs while the box has focus, so the underscore is
|
|
;; always visible on the frame the pointer arrives.
|
|
(if mouse-on-text
|
|
(set frames-counter (+ frames-counter 1))
|
|
(set frames-counter 0))
|
|
|
|
;; Draw
|
|
(rl/begin-drawing)
|
|
(rl/clear-background rl/raywhite)
|
|
|
|
(rl/draw-text "PLACE MOUSE OVER INPUT BOX!" 240 140 20 rl/gray)
|
|
|
|
(rl/draw-rectangle-rec text-box rl/lightgray)
|
|
(rl/draw-rectangle-lines (i32 (.x text-box)) (i32 (.y text-box))
|
|
(i32 (.width text-box)) (i32 (.height text-box))
|
|
(if mouse-on-text rl/red rl/darkgray))
|
|
|
|
(let [typed (string (slice name 0 letter-count))]
|
|
(rl/draw-text typed (+ (i32 (.x text-box)) 5) (+ (i32 (.y text-box)) 8)
|
|
40 rl/maroon)
|
|
|
|
;; The C's TextFormat("INPUT CHARS: %i/%i", ...), reassembled out of
|
|
;; examples/digits.flan the way the other ports do it. `typed` is a view
|
|
;; of `name` and not of the runtime's shared format buffer, so it
|
|
;; survives the two numbers being formatted — which a value from
|
|
;; i64->bytes would not.
|
|
(let [x 315]
|
|
(set x (+ x (d/draw-piece "INPUT CHARS: " x 250 20 rl/darkgray)))
|
|
(set x (+ x (d/draw-int letter-count x 250 20 rl/darkgray)))
|
|
(set x (+ x (d/draw-piece "/" x 250 20 rl/darkgray)))
|
|
(d/draw-int max-input-chars x 250 20 rl/darkgray))
|
|
|
|
(when mouse-on-text
|
|
(if (< letter-count max-input-chars)
|
|
;; Twenty frames on, twenty frames off, at the pen position after
|
|
;; whatever has been typed.
|
|
(when (= (% (/ frames-counter 20) 2) 0)
|
|
(rl/draw-text "_"
|
|
(+ (i32 (.x text-box)) 8 (rl/measure-text typed 40))
|
|
(+ (i32 (.y text-box)) 12) 40 rl/maroon))
|
|
(rl/draw-text "Press BACKSPACE to delete chars..." 230 300 20
|
|
rl/gray))))
|
|
|
|
(rl/end-drawing)))
|