;;;; 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. ;;;; ;;;; is-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.fln" const screen-width = 800 const 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. const restore-after = 240 once ball-pos: rl/Vector2 once ball-speed: rl/Vector2 once frames: i32 const 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. fn draw-flag(label: str, flag: u32, y: i32) -> () rl/draw-text(label, 10, y, 10, rl/gray) let x = 10 + rl/measure-text(label, 10) if rl/is-window-state(flag) rl/draw-text(" on", x, y, 10, rl/lime) else 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. fn toggle-flag(flag: u32) -> () if rl/is-window-state(flag) rl/clear-window-state(flag) else rl/set-window-state(flag) fn 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() ball-pos = rl/Vector2({.x f32(rl/get-screen-width()) / 2.0, .y f32(rl/get-screen-height()) / 2.0}) 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 if rl/is-key-pressed(:key-f) rl/toggle-fullscreen() if rl/is-key-pressed(:key-r) toggle-flag(rl/flag-window-resizable) if rl/is-key-pressed(:key-d) toggle-flag(rl/flag-window-undecorated) if rl/is-key-pressed(:key-u) toggle-flag(rl/flag-window-unfocused) if rl/is-key-pressed(:key-t) toggle-flag(rl/flag-window-topmost) if rl/is-key-pressed(:key-a) toggle-flag(rl/flag-window-always-run) if rl/is-key-pressed(:key-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. if rl/is-key-pressed(:key-h) unless(rl/is-window-state(rl/flag-window-hidden)): rl/set-window-state(rl/flag-window-hidden) frames = 0 if rl/is-window-state(rl/flag-window-hidden) frames += 1 if frames >= restore-after rl/clear-window-state(rl/flag-window-hidden) if rl/is-key-pressed(:key-n) unless(rl/is-window-state(rl/flag-window-minimized)): rl/minimize-window() frames = 0 if rl/is-window-state(rl/flag-window-minimized) frames += 1 if frames >= restore-after rl/restore-window() ;; Maximize needs FLAG_WINDOW_RESIZABLE first, which is what R is for. if rl/is-key-pressed(:key-m) if rl/is-window-state(rl/flag-window-maximized) rl/restore-window() else 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. ball-pos.x += ball-speed.x ball-pos.y += ball-speed.y if ball-pos.x >= f32(rl/get-screen-width()) - ball-radius or ball-pos.x <= ball-radius ball-speed.x *= -1.0 if ball-pos.y >= f32(rl/get-screen-height()) - ball-radius or ball-pos.y <= ball-radius ball-speed.y *= -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/is-window-state(rl/flag-window-transparent) rl/clear-background(rl/blank) else 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.fln 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) x += rl/measure-text("Screen Size: [", 10) x += d/draw-int(rl/get-screen-width(), x, 40, 10, rl/green) rl/draw-text(", ", x, 40, 10, rl/green) x += rl/measure-text(", ", 10) 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)