;;;; raylib [core] example - window flags ;;;; ;;;; examples/core/core_window_flags.c. The reason to port this one is the ;;;; flags themselves: raylib.flan carried four of ConfigFlags' sixteen ;;;; members — the four sand.flan sets before the window exists — and this ;;;; example reads and writes eleven of them after it exists. All sixteen are ;;;; in raylib.flan now, read off raylib.h 5.5, in the header's order and not ;;;; in bit order (FLAG_VSYNC_HINT is 0x40 and FLAG_FULLSCREEN_MODE is 0x02, ;;;; which is the kind of thing nobody remembers correctly). ;;;; ;;;; They are `defconst u32`s and not a `defenum` for the reason the file ;;;; already gives about gestures: raylib wants the OR of several and a ;;;; keyword can only ever name one member. ;;;; ;;;; window-state?, set-window-state, clear-window-state, toggle-fullscreen, ;;;; minimize-window, maximize-window and restore-window all come from the ;;;; generated half. That is the line drawn in vendor/raylib/bindings and it ;;;; is worth saying why it falls here: the rule in docs/PORTING.md §1 exists so ;;;; that a build with no header set can still draw, and generated.flan is ;;;; committed, so it can. What a hand-written line adds on top of that is a ;;;; Flan face the C signature does not have — a Key instead of an int, a ;;;; (Ptr Camera3D) instead of a raw pointer — and these seven have no such ;;;; face to add. They are u32 in and bool out in both languages. ;;;; ;;;; Not faithful in one place, deliberately: the C draws twelve lines of ;;;; on/off state through TextFormat and a two-branch if each time. Flan has ;;;; no TextFormat, so the pair is one helper here — which also removes the ;;;; C's own copy-paste bug, where the UNFOCUSED line says "[G]" when it is on ;;;; and "[U]" when it is off. (import rl "vendor:raylib") (import d "digits.flan") (defconst screen-width 800) (defconst screen-height 450) ;; Frames the window has been hidden or minimized for. H and N both put the ;; window somewhere it cannot be typed at, so the only way back is a count. (defconst restore-after 240) (defvar ball-pos rl/Vector2) (defvar ball-speed rl/Vector2) (defvar frames i32) (defconst ball-radius f32 20.0) ;; One line of the state list: the label, then "on" or "off" in lime or ;; maroon, at the x the label ended. The C writes two whole DrawText calls per ;; flag with the text repeated; this says it once. (defn draw-flag [label string flag u32 y i32] () (rl/draw-text label 10 y 10 rl/gray) (let [x (+ 10 (rl/measure-text label 10))] (if (rl/window-state? flag) (rl/draw-text " on" x y 10 rl/lime) (rl/draw-text " off" x y 10 rl/maroon)))) ;; A flag the program owns: pressing the key turns it off if it is on and on ;; if it is off. Nine of the C's eleven key handlers are exactly this. (defn toggle-flag [flag u32] () (if (rl/window-state? flag) (rl/clear-window-state flag) (rl/set-window-state flag))) (defn main [] () ;; The C leaves its SetConfigFlags call commented out, so that every flag ;; the list shows starts off. Kept that way: the point of the example is ;; which of them can be changed afterwards. (rl/init-window screen-width screen-height "raylib [core] example - window flags") (defer (rl/close-window)) (set ball-pos (rl/Vector2 {.x (/ (f32 (rl/get-screen-width)) 2.0) .y (/ (f32 (rl/get-screen-height)) 2.0)})) (set ball-speed (rl/Vector2 {.x 5.0 .y 4.0})) ;; No set-target-fps, as in the C: with FLAG_VSYNC_HINT among the flags the ;; example toggles, a frame limiter on top of it would hide what V-Sync ;; does to the number draw-fps reports. (until (rl/window-should-close?) ;; Update (when (rl/key-pressed? :f) (rl/toggle-fullscreen)) (when (rl/key-pressed? :r) (toggle-flag rl/flag-window-resizable)) (when (rl/key-pressed? :d) (toggle-flag rl/flag-window-undecorated)) (when (rl/key-pressed? :u) (toggle-flag rl/flag-window-unfocused)) (when (rl/key-pressed? :t) (toggle-flag rl/flag-window-topmost)) (when (rl/key-pressed? :a) (toggle-flag rl/flag-window-always-run)) (when (rl/key-pressed? :v) (toggle-flag rl/flag-vsync-hint)) ;; Hidden and minimized are not toggles: the window they hide is also the ;; window the key would have to be pressed in, so each comes back on a ;; timer instead. (when (rl/key-pressed? :h) (unless (rl/window-state? rl/flag-window-hidden) (rl/set-window-state rl/flag-window-hidden)) (set frames 0)) (when (rl/window-state? rl/flag-window-hidden) (set frames (+ frames 1)) (when (>= frames restore-after) (rl/clear-window-state rl/flag-window-hidden))) (when (rl/key-pressed? :n) (unless (rl/window-state? rl/flag-window-minimized) (rl/minimize-window)) (set frames 0)) (when (rl/window-state? rl/flag-window-minimized) (set frames (+ frames 1)) (when (>= frames restore-after) (rl/restore-window))) ;; Maximize needs FLAG_WINDOW_RESIZABLE first, which is what R is for. (when (rl/key-pressed? :m) (if (rl/window-state? rl/flag-window-maximized) (rl/restore-window) (rl/maximize-window))) ;; The ball bounces off whatever the window is right now, so resizing, ;; maximizing and going fullscreen all show up in its path. (set (.x ball-pos) (+ (.x ball-pos) (.x ball-speed))) (set (.y ball-pos) (+ (.y ball-pos) (.y ball-speed))) (when (or (>= (.x ball-pos) (- (f32 (rl/get-screen-width)) ball-radius)) (<= (.x ball-pos) ball-radius)) (set (.x ball-speed) (* (.x ball-speed) -1.0))) (when (or (>= (.y ball-pos) (- (f32 (rl/get-screen-height)) ball-radius)) (<= (.y ball-pos) ball-radius)) (set (.y ball-speed) (* (.y ball-speed) -1.0))) ;; Draw (rl/with-drawing ;; A transparent framebuffer wants a transparent clear; anything else ;; paints over the desktop the flag exists to show. (if (rl/window-state? rl/flag-window-transparent) (rl/clear-background rl/blank) (rl/clear-background rl/raywhite)) (rl/draw-circle-v ball-pos ball-radius rl/maroon) (rl/draw-rectangle-lines-ex (rl/Rectangle {.x 0.0 .y 0.0 .width (f32 (rl/get-screen-width)) .height (f32 (rl/get-screen-height))}) 4.0 rl/raywhite) (rl/draw-circle-v (rl/get-mouse-position) 10.0 rl/darkblue) (rl/draw-fps 10 10) ;; The C's TextFormat("Screen Size: [%i, %i]", ...), reassembled out of ;; literals and examples/digits.flan the way the other ports do it: `x` ;; walks along the line, and draw-int hands back the width it drew. (let [x 10] (rl/draw-text "Screen Size: [" x 40 10 rl/green) (set x (+ x (rl/measure-text "Screen Size: [" 10))) (set x (+ x (d/draw-int (rl/get-screen-width) x 40 10 rl/green))) (rl/draw-text ", " x 40 10 rl/green) (set x (+ x (rl/measure-text ", " 10))) (set x (+ x (d/draw-int (rl/get-screen-height) x 40 10 rl/green))) (rl/draw-text "]" x 40 10 rl/green)) (rl/draw-text "Following flags can be set after window creation:" 10 60 10 rl/gray) (draw-flag "[F] FLAG_FULLSCREEN_MODE:" rl/flag-fullscreen-mode 80) (draw-flag "[R] FLAG_WINDOW_RESIZABLE:" rl/flag-window-resizable 100) (draw-flag "[D] FLAG_WINDOW_UNDECORATED:" rl/flag-window-undecorated 120) (draw-flag "[H] FLAG_WINDOW_HIDDEN:" rl/flag-window-hidden 140) (draw-flag "[N] FLAG_WINDOW_MINIMIZED:" rl/flag-window-minimized 160) (draw-flag "[M] FLAG_WINDOW_MAXIMIZED:" rl/flag-window-maximized 180) (draw-flag "[U] FLAG_WINDOW_UNFOCUSED:" rl/flag-window-unfocused 200) (draw-flag "[T] FLAG_WINDOW_TOPMOST:" rl/flag-window-topmost 220) (draw-flag "[A] FLAG_WINDOW_ALWAYS_RUN:" rl/flag-window-always-run 240) (draw-flag "[V] FLAG_VSYNC_HINT:" rl/flag-vsync-hint 260) (rl/draw-text "Following flags can only be set before window creation:" 10 300 10 rl/gray) (draw-flag "FLAG_WINDOW_HIGHDPI:" rl/flag-window-highdpi 320) (draw-flag "FLAG_WINDOW_TRANSPARENT:" rl/flag-window-transparent 340) (draw-flag "FLAG_MSAA_4X_HINT:" rl/flag-msaa-4x-hint 360))))