Five more core examples, and the 3D half of the bindings they wanted
core-2d-camera, core-scissor-test, core-window-flags, core-world-screen
and core-window-should-close, ported from raylib 5.5's examples/core.
What each one asked of vendor/raylib:
2d-camera nothing. A whole Camera2D by value, per frame, into the
call that actually draws with it — the layout the
acceptance table pins through arithmetic, now going
through the path it was bound for.
scissor-test begin-scissor-mode / end-scissor-mode, hand-written.
window-flags twelve more ConfigFlags constants; raylib.flan carried
the four sand.flan sets and this reads eleven.
world-screen the 3D surface did not exist: no Vector3, no Camera3D,
and the importer refused every 3D function in raylib.h
by name for want of them. Two defstructs, two defenums,
begin/end-mode-3d, update-camera, get-world-to-screen,
draw-cube, draw-cube-wires, draw-grid — and 24 more 3D
lines the importer can generate now that the types are
described.
window-should-close set-exit-key, and Key/null to pass it.
The hand-written/generated line, written down in vendor/raylib/bindings:
a drawing pair inside a frame is hand-written, and so is anything whose
Flan face is not the C signature — set-exit-key takes a Key, update-camera
takes a (Ptr Camera3D) and a CameraMode. The window-state family and
get-mouse-x/y stay generated: plain scalars in and bool out, with nothing
for a hand-written line to add.
Camera3D's projection field stays i32, because the header says int and the
layout check holds this file to that; rl/camera-projection is the
conversion, and still takes a keyword.
This commit is contained in:
parent
a016c3f226
commit
1df6f7a642
142
examples/core-2d-camera.flan
Normal file
142
examples/core-2d-camera.flan
Normal file
@ -0,0 +1,142 @@
|
||||
;;;; raylib [core] example - 2d camera
|
||||
;;;;
|
||||
;;;; examples/core/core_2d_camera.c. Needed no new binding at all, which is
|
||||
;;;; the reason to port it: Camera2D, begin-mode-2d and end-mode-2d have been
|
||||
;;;; in vendor/raylib/raylib.flan since the beginning and nothing in the
|
||||
;;;; corpus had ever passed a whole Camera2D across the FFI on a frame's path.
|
||||
;;;; Two Vector2s, a float and a float, by value, sixty times a second — the
|
||||
;;;; acceptance table pins that layout with get-screen-to-world-2d, and this
|
||||
;;;; is the same struct going into the call that actually draws with it.
|
||||
;;;;
|
||||
;;;; The hundred buildings are a `defvar` of fixed arrays rather than a Vec:
|
||||
;;;; a global cannot hold a Vec (PORTING.md §3) and does not need to here,
|
||||
;;;; because the count is a constant in the C too. `(array n T)` is the zeroed
|
||||
;;;; fixed array, and the C's `= { 0 }` is exactly that.
|
||||
;;;;
|
||||
;;;; get-random-value comes from the generated half of the bindings. It is on
|
||||
;;;; no frame's path — it runs once, before the loop — and its Flan face is
|
||||
;;;; the C one, so PORTING.md §1's rule does not reach it.
|
||||
;;;;
|
||||
;;;; One deliberate difference from the C: `(- camera.rotation 1.0)` and the
|
||||
;;;; clamp after it are written with the prelude's `clamp` macro rather than
|
||||
;;;; two ifs. It is the same arithmetic; the C spells it out because C has no
|
||||
;;;; clamp.
|
||||
|
||||
(import rl "vendor:raylib")
|
||||
|
||||
(defconst screen-width 800)
|
||||
(defconst screen-height 450)
|
||||
|
||||
(defconst max-buildings 100)
|
||||
|
||||
(defvar buildings [100 rl/Rectangle])
|
||||
(defvar build-colors [100 rl/Color])
|
||||
(defvar player rl/Rectangle)
|
||||
(defvar camera rl/Camera2D)
|
||||
|
||||
(defn main [] ()
|
||||
(rl/init-window screen-width screen-height
|
||||
"raylib [core] example - 2d camera")
|
||||
(defer (rl/close-window))
|
||||
|
||||
(set player (rl/Rectangle {.x 400.0 .y 280.0 .width 40.0 .height 40.0}))
|
||||
(set buildings (array max-buildings rl/Rectangle))
|
||||
(set build-colors (array max-buildings rl/Color))
|
||||
|
||||
;; The skyline: each building is as wide as the last one left room for, so
|
||||
;; the spacing accumulates and the row starts 6000 units to the left.
|
||||
(let [spacing 0]
|
||||
(dotimes [i max-buildings]
|
||||
(let [w (f32 (rl/get-random-value 50 200))
|
||||
h (f32 (rl/get-random-value 100 800))]
|
||||
(set (at buildings i)
|
||||
(rl/Rectangle {.x (+ -6000.0 (f32 spacing))
|
||||
.y (- (- (f32 screen-height) 130.0) h)
|
||||
.width w
|
||||
.height h}))
|
||||
(set spacing (+ spacing (i32 w)))
|
||||
(set (at build-colors i)
|
||||
(rl/Color {.r (u8 (rl/get-random-value 200 240))
|
||||
.g (u8 (rl/get-random-value 200 240))
|
||||
.b (u8 (rl/get-random-value 200 250))
|
||||
.a 255})))))
|
||||
|
||||
;; A fresh Camera2D is all zeroes and a zoom of 0 makes the transform
|
||||
;; singular, so the zoom is the one field that must be set — raylib.flan's
|
||||
;; own comment on the struct says so.
|
||||
(set camera (rl/Camera2D {.offset (rl/Vector2 {.x (/ (f32 screen-width) 2.0)
|
||||
.y (/ (f32 screen-height) 2.0)})
|
||||
.target (rl/Vector2 {.x (+ (.x player) 20.0)
|
||||
.y (+ (.y player) 20.0)})
|
||||
.rotation 0.0
|
||||
.zoom 1.0}))
|
||||
|
||||
(rl/set-target-fps 60)
|
||||
|
||||
(until (rl/window-should-close?)
|
||||
;; Update
|
||||
;; The C's `if (RIGHT) ... else if (LEFT) ...`: both held cancels to the
|
||||
;; right, which is the else-if and not an accident.
|
||||
(if (rl/key-down? :right)
|
||||
(set (.x player) (+ (.x player) 2.0))
|
||||
(when (rl/key-down? :left) (set (.x player) (- (.x player) 2.0))))
|
||||
|
||||
;; The camera follows the player's centre.
|
||||
(set (.target camera) (rl/Vector2 {.x (+ (.x player) 20.0)
|
||||
.y (+ (.y player) 20.0)}))
|
||||
|
||||
(if (rl/key-down? :a)
|
||||
(set (.rotation camera) (- (.rotation camera) 1.0))
|
||||
(when (rl/key-down? :s)
|
||||
(set (.rotation camera) (+ (.rotation camera) 1.0))))
|
||||
(set (.rotation camera) (clamp (.rotation camera) -40.0 40.0))
|
||||
|
||||
(set (.zoom camera) (+ (.zoom camera) (* (rl/get-mouse-wheel-move) 0.05)))
|
||||
(set (.zoom camera) (clamp (.zoom camera) 0.1 3.0))
|
||||
|
||||
(when (rl/key-pressed? :r)
|
||||
(set (.zoom camera) 1.0)
|
||||
(set (.rotation camera) 0.0))
|
||||
|
||||
;; Draw
|
||||
(rl/begin-drawing)
|
||||
(rl/clear-background rl/raywhite)
|
||||
|
||||
;; Everything between these two is in world space and goes through the
|
||||
;; camera. The ground and the crosshair lines are drawn far outside the
|
||||
;; window on purpose: at zoom 0.1 they still have to reach the edges.
|
||||
(rl/begin-mode-2d camera)
|
||||
|
||||
(rl/draw-rectangle -6000 320 13000 8000 rl/darkgray)
|
||||
|
||||
(dotimes [i max-buildings]
|
||||
(rl/draw-rectangle-rec (at buildings i) (at build-colors i)))
|
||||
|
||||
(rl/draw-rectangle-rec player rl/red)
|
||||
|
||||
(rl/draw-line (i32 (.x (.target camera))) (* screen-height -10)
|
||||
(i32 (.x (.target camera))) (* screen-height 10) rl/green)
|
||||
(rl/draw-line (* screen-width -10) (i32 (.y (.target camera)))
|
||||
(* screen-width 10) (i32 (.y (.target camera))) rl/green)
|
||||
|
||||
(rl/end-mode-2d)
|
||||
|
||||
;; And everything after it is in screen space again — the frame drawn
|
||||
;; around the window is how the example shows the difference.
|
||||
(rl/draw-text "SCREEN AREA" 640 10 20 rl/red)
|
||||
|
||||
(rl/draw-rectangle 0 0 screen-width 5 rl/red)
|
||||
(rl/draw-rectangle 0 5 5 (- screen-height 10) rl/red)
|
||||
(rl/draw-rectangle (- screen-width 5) 5 5 (- screen-height 10) rl/red)
|
||||
(rl/draw-rectangle 0 (- screen-height 5) screen-width 5 rl/red)
|
||||
|
||||
(rl/draw-rectangle 10 10 250 113 (rl/fade rl/skyblue 0.5))
|
||||
(rl/draw-rectangle-lines 10 10 250 113 rl/blue)
|
||||
|
||||
(rl/draw-text "Free 2d camera controls:" 20 20 10 rl/black)
|
||||
(rl/draw-text "- Right/Left to move Offset" 40 40 10 rl/darkgray)
|
||||
(rl/draw-text "- Mouse Wheel to Zoom in-out" 40 60 10 rl/darkgray)
|
||||
(rl/draw-text "- A / S to Rotate" 40 80 10 rl/darkgray)
|
||||
(rl/draw-text "- R to reset Zoom and Rotation" 40 100 10 rl/darkgray)
|
||||
|
||||
(rl/end-drawing)))
|
||||
72
examples/core-scissor-test.flan
Normal file
72
examples/core-scissor-test.flan
Normal file
@ -0,0 +1,72 @@
|
||||
;;;; raylib [core] example - scissor test
|
||||
;;;;
|
||||
;;;; examples/core/core_scissor_test.c. Needed begin-scissor-mode and
|
||||
;;;; end-scissor-mode, now hand-written in vendor/raylib/raylib.flan: they are
|
||||
;;;; a begin/end pair inside a frame, which is the class PORTING.md §1 says
|
||||
;;;; belongs in the hand-written half and not in the importer's. get-mouse-x
|
||||
;;;; and get-mouse-y come from the generated half — their Flan face is the C
|
||||
;;;; one, two plain i32s, and there is nothing for a hand-written line to say
|
||||
;;;; about them that the header does not already say.
|
||||
;;;;
|
||||
;;;; The scissor rectangle is a Rectangle of floats in the C and stays one
|
||||
;;;; here, even though every use of it casts back to i32, because the one call
|
||||
;;;; that takes it whole — draw-rectangle-lines-ex — wants a Rectangle. That
|
||||
;;;; is also why the mouse is read through get-mouse-x/get-mouse-y rather than
|
||||
;;;; get-mouse-position: the C does the arithmetic in floats from integer
|
||||
;;;; readings, and doing it the other way round would round differently on the
|
||||
;;;; odd pixel.
|
||||
;;;;
|
||||
;;;; What this example is really a test of, and what no headless case could
|
||||
;;;; be: raylib's scissor rectangle is in screen pixels with y growing DOWN,
|
||||
;;;; and the GL call underneath measures from the bottom. raylib flips it. If
|
||||
;;;; the binding or the flip were wrong the clip would appear mirrored about
|
||||
;;;; the middle of the window — a perfectly plausible picture, in the wrong
|
||||
;;;; place — so the only check is the outline drawn around it afterwards
|
||||
;;;; landing on the revealed patch.
|
||||
|
||||
(import rl "vendor:raylib")
|
||||
|
||||
(defconst screen-width 800)
|
||||
(defconst screen-height 450)
|
||||
|
||||
(defvar scissor rl/Rectangle)
|
||||
(defvar scissor-mode bool)
|
||||
|
||||
(defn main [] ()
|
||||
(rl/init-window screen-width screen-height
|
||||
"raylib [core] example - scissor test")
|
||||
(defer (rl/close-window))
|
||||
|
||||
(set scissor (rl/Rectangle {.x 0.0 .y 0.0 .width 300.0 .height 300.0}))
|
||||
(set scissor-mode true)
|
||||
|
||||
(rl/set-target-fps 60)
|
||||
|
||||
(until (rl/window-should-close?)
|
||||
;; Update
|
||||
(when (rl/key-pressed? :s) (set scissor-mode (not scissor-mode)))
|
||||
|
||||
;; Centre the scissor area on the mouse.
|
||||
(set (.x scissor) (- (f32 (rl/get-mouse-x)) (/ (.width scissor) 2.0)))
|
||||
(set (.y scissor) (- (f32 (rl/get-mouse-y)) (/ (.height scissor) 2.0)))
|
||||
|
||||
;; Draw
|
||||
(rl/begin-drawing)
|
||||
(rl/clear-background rl/raywhite)
|
||||
|
||||
(when scissor-mode
|
||||
(rl/begin-scissor-mode (i32 (.x scissor)) (i32 (.y scissor))
|
||||
(i32 (.width scissor)) (i32 (.height scissor))))
|
||||
|
||||
;; A full-screen rectangle and a line of text. Only the part inside the
|
||||
;; scissor rectangle reaches the framebuffer, which is the whole example.
|
||||
(rl/draw-rectangle 0 0 (rl/get-screen-width) (rl/get-screen-height) rl/red)
|
||||
(rl/draw-text "Move the mouse around to reveal this text!" 190 200 20
|
||||
rl/lightgray)
|
||||
|
||||
(when scissor-mode (rl/end-scissor-mode))
|
||||
|
||||
(rl/draw-rectangle-lines-ex scissor 1.0 rl/black)
|
||||
(rl/draw-text "Press S to toggle scissor test" 10 10 20 rl/black)
|
||||
|
||||
(rl/end-drawing)))
|
||||
179
examples/core-window-flags.flan
Normal file
179
examples/core-window-flags.flan
Normal file
@ -0,0 +1,179 @@
|
||||
;;;; 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 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/begin-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)
|
||||
|
||||
(rl/end-drawing)))
|
||||
68
examples/core-window-should-close.flan
Normal file
68
examples/core-window-should-close.flan
Normal file
@ -0,0 +1,68 @@
|
||||
;;;; raylib [core] example - window should close
|
||||
;;;;
|
||||
;;;; examples/core/core_window_should_close.c. Needed set-exit-key, and one
|
||||
;;;; enum member to go with it: raylib.flan's `Key` now has `null 0`, read off
|
||||
;;;; KEY_NULL in raylib.h. The binding is hand-written rather than taken from
|
||||
;;;; the generated half because the Flan face differs — raylib declares
|
||||
;;;; `void SetExitKey(int key)` and the generated line therefore takes an i32,
|
||||
;;;; where this one takes a Key, so `(rl/set-exit-key :null)` is checked
|
||||
;;;; against the enum and `:nul` is a compile error instead of a 0.
|
||||
;;;;
|
||||
;;;; The whole example is about what window-should-close? means. It is not a
|
||||
;;;; flag raylib latches: it is "the close button was clicked, or the exit key
|
||||
;;;; is down", recomputed each frame, and it goes back to false on its own.
|
||||
;;;; That is what lets this program ask for confirmation and then carry on —
|
||||
;;;; and it is also why the loop is driven by a `defvar` of its own rather
|
||||
;;;; than by the predicate, which is the one structural difference from every
|
||||
;;;; other example in this directory.
|
||||
;;;;
|
||||
;;;; `(set-exit-key :null)` takes ESC away from raylib so the program can read
|
||||
;;;; it itself. The window's X button still works and is still what
|
||||
;;;; window-should-close? reports.
|
||||
|
||||
(import rl "vendor:raylib")
|
||||
|
||||
(defconst screen-width 800)
|
||||
(defconst screen-height 450)
|
||||
|
||||
(defvar exit-requested bool)
|
||||
(defvar exiting bool)
|
||||
|
||||
(defn main [] ()
|
||||
(rl/init-window screen-width screen-height
|
||||
"raylib [core] example - window should close")
|
||||
(defer (rl/close-window))
|
||||
|
||||
;; No key closes the window any more. ESC is an ordinary key from here on.
|
||||
(rl/set-exit-key :null)
|
||||
|
||||
(rl/set-target-fps 60)
|
||||
|
||||
(until exiting
|
||||
;; Update. Either way of asking to leave raises the question; only Y and N
|
||||
;; answer it. window-should-close? is false again on the next frame, so
|
||||
;; the request has to be remembered in a variable.
|
||||
(when (or (rl/window-should-close?) (rl/key-pressed? :escape))
|
||||
(set exit-requested true))
|
||||
|
||||
;; The C's `if (Y) ... else if (N) ...`, which is an `if` with a `when`
|
||||
;; in its else and not a `cond`: a `cond` needs an `:else` arm and there
|
||||
;; is nothing to do when neither key was pressed.
|
||||
(when exit-requested
|
||||
(if (rl/key-pressed? :y)
|
||||
(set exiting true)
|
||||
(when (rl/key-pressed? :n) (set exit-requested false))))
|
||||
|
||||
;; Draw
|
||||
(rl/begin-drawing)
|
||||
(rl/clear-background rl/raywhite)
|
||||
|
||||
(if exit-requested
|
||||
(do
|
||||
(rl/draw-rectangle 0 100 screen-width 200 rl/black)
|
||||
(rl/draw-text "Are you sure you want to exit program? [Y/N]" 40 180 30
|
||||
rl/white))
|
||||
(rl/draw-text "Try to close the window to get confirmation message!"
|
||||
120 200 20 rl/lightgray))
|
||||
|
||||
(rl/end-drawing)))
|
||||
114
examples/core-world-screen.flan
Normal file
114
examples/core-world-screen.flan
Normal file
@ -0,0 +1,114 @@
|
||||
;;;; raylib [core] example - world to screen
|
||||
;;;;
|
||||
;;;; examples/core/core_world_screen.c, and the first thing in this directory
|
||||
;;;; to draw in 3D at all. That is why it is here: before it, vendor/raylib
|
||||
;;;; described no Vector3, no Camera3D and not one call that takes either, so
|
||||
;;;; the importer refused every 3D function in raylib.h by name — "Vector3 is
|
||||
;;;; a struct the package does not describe". Two defstructs later it refuses
|
||||
;;;; none of them, and the generated half grew the cubes, spheres, cylinders
|
||||
;;;; and billboards along with the eight lines this example needs.
|
||||
;;;;
|
||||
;;;; Hand-written in raylib.flan rather than generated, and why each:
|
||||
;;;;
|
||||
;;;; begin-mode-3d / end-mode-3d a begin/end pair inside a frame, the
|
||||
;;;; class PORTING.md §1 names, and taken
|
||||
;;;; together the way begin-mode-2d is
|
||||
;;;; draw-cube / draw-cube-wires / draw-grid drawn every frame
|
||||
;;;; update-camera the Flan face differs: (Ptr Camera3D),
|
||||
;;;; because it mutates, and a CameraMode
|
||||
;;;; rather than the header's int
|
||||
;;;; get-world-to-screen it reads the same camera as the mode
|
||||
;;;;
|
||||
;;;; What is NOT pinned by anything, and cannot be: Camera3D's first three
|
||||
;;;; fields are all Vector3, so every permutation of position, target and up
|
||||
;;;; has the identical layout and no computed test can tell them apart. A
|
||||
;;;; camera looking from the wrong place is a picture, not a number. The same
|
||||
;;;; is true of Vector3's own x, y and z. Only the screen catches those.
|
||||
;;;;
|
||||
;;;; update-camera in :third-person mode also takes the mouse, which is why
|
||||
;;;; the C calls DisableCursor: the cursor is locked to the window and its
|
||||
;;;; movement becomes camera rotation rather than a pointer. disable-cursor
|
||||
;;;; comes from the generated half — it is called once, before the loop.
|
||||
;;;;
|
||||
;;;; The C's two TextFormats go through examples/digits.flan, as in the other
|
||||
;;;; ports, because Flan has no TextFormat and i64->bytes has no field width.
|
||||
|
||||
(import rl "vendor:raylib")
|
||||
(import d "digits.flan")
|
||||
|
||||
(defconst screen-width 800)
|
||||
(defconst screen-height 450)
|
||||
|
||||
(defvar camera rl/Camera3D)
|
||||
(defvar cube rl/Vector3)
|
||||
|
||||
(defn main [] ()
|
||||
(rl/init-window screen-width screen-height
|
||||
"raylib [core] example - core world screen")
|
||||
(defer (rl/close-window))
|
||||
|
||||
;; `projection` is an i32 and not a CameraProjection, because the header
|
||||
;; says the field is `int` and the layout check holds this file to that.
|
||||
;; rl/camera-projection is the conversion, and it still takes a keyword, so
|
||||
;; a misspelt projection is a compile error rather than a 0.
|
||||
(set camera
|
||||
(rl/Camera3D {.position (rl/Vector3 {.x 10.0 .y 10.0 .z 10.0})
|
||||
.target (rl/Vector3 {.x 0.0 .y 0.0 .z 0.0})
|
||||
.up (rl/Vector3 {.x 0.0 .y 1.0 .z 0.0})
|
||||
.fovy 45.0
|
||||
.projection (rl/camera-projection :perspective)}))
|
||||
|
||||
(set cube (rl/Vector3 {.x 0.0 .y 0.0 .z 0.0}))
|
||||
|
||||
;; The mouse becomes the camera's, not a pointer's.
|
||||
(rl/disable-cursor)
|
||||
|
||||
(rl/set-target-fps 60)
|
||||
|
||||
(until (rl/window-should-close?)
|
||||
;; Update. The camera is passed by address because update-camera writes
|
||||
;; to it — a global is an assignable place, so it has an address to take.
|
||||
(rl/update-camera (addr camera) :third-person)
|
||||
|
||||
;; Where the point 2.5 units above the cube lands on the screen. This is
|
||||
;; the whole example: the same transform raylib is about to draw with,
|
||||
;; asked in advance, so a label can be put on a thing in the world.
|
||||
(let [label-pos (rl/get-world-to-screen
|
||||
(rl/Vector3 {.x (.x cube)
|
||||
.y (+ (.y cube) 2.5)
|
||||
.z (.z cube)})
|
||||
camera)]
|
||||
|
||||
;; Draw
|
||||
(rl/begin-drawing)
|
||||
(rl/clear-background rl/raywhite)
|
||||
|
||||
(rl/begin-mode-3d camera)
|
||||
(rl/draw-cube cube 2.0 2.0 2.0 rl/red)
|
||||
(rl/draw-cube-wires cube 2.0 2.0 2.0 rl/maroon)
|
||||
(rl/draw-grid 10 1.0)
|
||||
(rl/end-mode-3d)
|
||||
|
||||
;; And the 2D half, drawn after end-mode-3d and therefore on top of the
|
||||
;; cube whatever the depth buffer says — which is the second half of
|
||||
;; what the example demonstrates.
|
||||
(rl/draw-text "Enemy: 100 / 100"
|
||||
(- (i32 (.x label-pos))
|
||||
(/ (rl/measure-text "Enemy: 100/100" 20) 2))
|
||||
(i32 (.y label-pos)) 20 rl/black)
|
||||
|
||||
(let [x 10]
|
||||
(rl/draw-text "Cube position in screen space coordinates: [" x 10 20
|
||||
rl/lime)
|
||||
(set x (+ x (rl/measure-text
|
||||
"Cube position in screen space coordinates: [" 20)))
|
||||
(set x (+ x (d/draw-int (i32 (.x label-pos)) x 10 20 rl/lime)))
|
||||
(rl/draw-text ", " x 10 20 rl/lime)
|
||||
(set x (+ x (rl/measure-text ", " 20)))
|
||||
(set x (+ x (d/draw-int (i32 (.y label-pos)) x 10 20 rl/lime)))
|
||||
(rl/draw-text "]" x 10 20 rl/lime))
|
||||
|
||||
(rl/draw-text "Text 2d should be always on top of the cube" 10 40 20
|
||||
rl/gray)
|
||||
|
||||
(rl/end-drawing))))
|
||||
38
vendor/raylib/bindings
vendored
38
vendor/raylib/bindings
vendored
@ -76,3 +76,41 @@ name IsAudioStreamProcessed audio-stream-processed?
|
||||
exclude DrawTexturePro
|
||||
exclude ImageFromImage
|
||||
exclude IsWindowReady
|
||||
|
||||
# The scissor pair and the 3D surface the ported examples in examples/ draw
|
||||
# through, excluded here for the same two reasons in different proportions.
|
||||
#
|
||||
# - BeginScissorMode/EndScissorMode, BeginMode3D/EndMode3D, DrawCube,
|
||||
# DrawCubeWires, DrawGrid are inside a frame. The rule above is about the
|
||||
# per-frame path, and a begin/end pair is taken together: hand-writing one
|
||||
# half and generating the other is the asymmetry that reads as a mistake.
|
||||
# - SetExitKey, UpdateCamera and GetWorldToScreen are excluded because their
|
||||
# Flan face is not the C signature. SetExitKey takes a Key and not an int,
|
||||
# UpdateCamera takes a CameraMode, and both of those refuse a typo the
|
||||
# generated i32 would take. GetWorldToScreen goes with BeginMode3D
|
||||
# because they read the same camera.
|
||||
#
|
||||
# What this line splits, and deliberately: draw-cube is here and draw-cube-v
|
||||
# is generated, get-world-to-screen is here and get-world-to-screen-ex is
|
||||
# generated, update-camera is here and update-camera-pro is generated. Every
|
||||
# other family in raylib.flan — the texture draws, the circle draws — sits
|
||||
# together, so the split is worth naming: what is hand-written is what the
|
||||
# ported examples call, and hand-writing the variants as well would widen the
|
||||
# half that has to be maintained by hand for nothing the examples ask for.
|
||||
#
|
||||
# What is deliberately NOT here: the window-state family (IsWindowState,
|
||||
# SetWindowState, ClearWindowState, ToggleFullscreen, Minimize/Maximize/
|
||||
# RestoreWindow), GetMouseX/GetMouseY and GetRandomValue. Those are called
|
||||
# per frame by the examples too, but their Flan face IS the C one — plain
|
||||
# scalars, nothing an enum or a pointer improves — and generated.flan is
|
||||
# committed, so the default build has them with no header set either way.
|
||||
exclude BeginScissorMode
|
||||
exclude EndScissorMode
|
||||
exclude BeginMode3D
|
||||
exclude EndMode3D
|
||||
exclude DrawCube
|
||||
exclude DrawCubeWires
|
||||
exclude DrawGrid
|
||||
exclude SetExitKey
|
||||
exclude UpdateCamera
|
||||
exclude GetWorldToScreen
|
||||
|
||||
29
vendor/raylib/generated.flan
vendored
29
vendor/raylib/generated.flan
vendored
@ -56,13 +56,11 @@
|
||||
(declare-c enable-cursor [] "EnableCursor")
|
||||
(declare-c disable-cursor [] "DisableCursor")
|
||||
(declare-c cursor-on-screen? [] bool "IsCursorOnScreen")
|
||||
(declare-c end-mode-3d [] "EndMode3D")
|
||||
(declare-c end-shader-mode [] "EndShaderMode")
|
||||
(declare-c begin-blend-mode [mode i32] "BeginBlendMode")
|
||||
(declare-c end-blend-mode [] "EndBlendMode")
|
||||
(declare-c begin-scissor-mode [x i32 y i32 width i32 height i32] "BeginScissorMode")
|
||||
(declare-c end-scissor-mode [] "EndScissorMode")
|
||||
(declare-c end-vr-stereo-mode [] "EndVrStereoMode")
|
||||
(declare-c get-world-to-screen-ex [position Vector3 camera Camera3D width i32 height i32] Vector2 "GetWorldToScreenEx")
|
||||
(declare-c swap-screen-buffer [] "SwapScreenBuffer")
|
||||
(declare-c poll-input-events [] "PollInputEvents")
|
||||
(declare-c wait-time [seconds f64] "WaitTime")
|
||||
@ -98,7 +96,6 @@
|
||||
(declare-c key-up? [key i32] bool "IsKeyUp")
|
||||
(declare-c get-key-pressed [] i32 "GetKeyPressed")
|
||||
(declare-c get-char-pressed [] i32 "GetCharPressed")
|
||||
(declare-c set-exit-key [key i32] "SetExitKey")
|
||||
(declare-c set-gamepad-mappings [mappings string] i32 "SetGamepadMappings")
|
||||
(declare-c set-gamepad-vibration [gamepad i32 left-motor f32 right-motor f32 duration f32] "SetGamepadVibration")
|
||||
(declare-c mouse-button-up? [button i32] bool "IsMouseButtonUp")
|
||||
@ -110,6 +107,7 @@
|
||||
(declare-c set-mouse-scale [scale-x f32 scale-y f32] "SetMouseScale")
|
||||
(declare-c get-mouse-wheel-move-v [] Vector2 "GetMouseWheelMoveV")
|
||||
(declare-c set-mouse-cursor [cursor i32] "SetMouseCursor")
|
||||
(declare-c update-camera-pro [camera (Ptr Camera3D) movement Vector3 rotation Vector3 zoom f32] "UpdateCameraPro")
|
||||
(declare-c draw-line-strip [points (Ptr Vector2) point-count i32 color Color] "DrawLineStrip")
|
||||
(declare-c draw-line-bezier [start-pos Vector2 end-pos Vector2 thick f32 color Color] "DrawLineBezier")
|
||||
(declare-c draw-circle-sector [center Vector2 radius f32 start-angle f32 end-angle f32 segments i32 color Color] "DrawCircleSector")
|
||||
@ -212,6 +210,7 @@
|
||||
(declare-c set-texture-wrap [texture Texture2D wrap i32] "SetTextureWrap")
|
||||
(declare-c color-is-equal [col-1 Color col-2 Color] bool "ColorIsEqual")
|
||||
(declare-c color-to-int [color Color] i32 "ColorToInt")
|
||||
(declare-c color-to-hsv [color Color] Vector3 "ColorToHSV")
|
||||
(declare-c color-from-hsv [hue f32 saturation f32 value f32] Color "ColorFromHSV")
|
||||
(declare-c color-tint [color Color tint Color] Color "ColorTint")
|
||||
(declare-c color-brightness [color Color factor f32] Color "ColorBrightness")
|
||||
@ -243,7 +242,27 @@
|
||||
(declare-c text-find-index [text string find string] i32 "TextFindIndex")
|
||||
(declare-c text-to-integer [text string] i32 "TextToInteger")
|
||||
(declare-c text-to-float [text string] f32 "TextToFloat")
|
||||
(declare-c draw-grid [slices i32 spacing f32] "DrawGrid")
|
||||
(declare-c draw-line-3d [start-pos Vector3 end-pos Vector3 color Color] "DrawLine3D")
|
||||
(declare-c draw-point-3d [position Vector3 color Color] "DrawPoint3D")
|
||||
(declare-c draw-circle-3d [center Vector3 radius f32 rotation-axis Vector3 rotation-angle f32 color Color] "DrawCircle3D")
|
||||
(declare-c draw-triangle-3d [v-1 Vector3 v-2 Vector3 v-3 Vector3 color Color] "DrawTriangle3D")
|
||||
(declare-c draw-triangle-strip-3d [points (Ptr Vector3) point-count i32 color Color] "DrawTriangleStrip3D")
|
||||
(declare-c draw-cube-v [position Vector3 size Vector3 color Color] "DrawCubeV")
|
||||
(declare-c draw-cube-wires-v [position Vector3 size Vector3 color Color] "DrawCubeWiresV")
|
||||
(declare-c draw-sphere [center-pos Vector3 radius f32 color Color] "DrawSphere")
|
||||
(declare-c draw-sphere-ex [center-pos Vector3 radius f32 rings i32 slices i32 color Color] "DrawSphereEx")
|
||||
(declare-c draw-sphere-wires [center-pos Vector3 radius f32 rings i32 slices i32 color Color] "DrawSphereWires")
|
||||
(declare-c draw-cylinder [position Vector3 radius-top f32 radius-bottom f32 height f32 slices i32 color Color] "DrawCylinder")
|
||||
(declare-c draw-cylinder-ex [start-pos Vector3 end-pos Vector3 start-radius f32 end-radius f32 sides i32 color Color] "DrawCylinderEx")
|
||||
(declare-c draw-cylinder-wires [position Vector3 radius-top f32 radius-bottom f32 height f32 slices i32 color Color] "DrawCylinderWires")
|
||||
(declare-c draw-cylinder-wires-ex [start-pos Vector3 end-pos Vector3 start-radius f32 end-radius f32 sides i32 color Color] "DrawCylinderWiresEx")
|
||||
(declare-c draw-capsule [start-pos Vector3 end-pos Vector3 radius f32 slices i32 rings i32 color Color] "DrawCapsule")
|
||||
(declare-c draw-capsule-wires [start-pos Vector3 end-pos Vector3 radius f32 slices i32 rings i32 color Color] "DrawCapsuleWires")
|
||||
(declare-c draw-plane [center-pos Vector3 size Vector2 color Color] "DrawPlane")
|
||||
(declare-c draw-billboard [camera Camera3D texture Texture2D position Vector3 scale f32 tint Color] "DrawBillboard")
|
||||
(declare-c draw-billboard-rec [camera Camera3D texture Texture2D source Rectangle position Vector3 size Vector2 tint Color] "DrawBillboardRec")
|
||||
(declare-c draw-billboard-pro [camera Camera3D texture Texture2D source Rectangle position Vector3 up Vector3 size Vector2 origin Vector2 rotation f32 tint Color] "DrawBillboardPro")
|
||||
(declare-c check-collision-spheres [center-1 Vector3 radius-1 f32 center-2 Vector3 radius-2 f32] bool "CheckCollisionSpheres")
|
||||
(declare-c load-wave-from-memory [file-type string file-data (Ptr u8) data-size i32] Wave "LoadWaveFromMemory")
|
||||
(declare-c update-sound [sound Sound data (Ptr u8) sample-count i32] "UpdateSound")
|
||||
(declare-c export-wave-as-code [wave Wave file-name string] bool "ExportWaveAsCode")
|
||||
|
||||
140
vendor/raylib/raylib.flan
vendored
140
vendor/raylib/raylib.flan
vendored
@ -33,7 +33,13 @@
|
||||
|
||||
;; Layouts are C's — no object headers anywhere — so these are exactly
|
||||
;; raylib's structs and nothing marshals.
|
||||
;; Vector3 sits here rather than in the 3D section below because it is a
|
||||
;; vector before it is a camera's business: nothing about it is 3D-only. Three
|
||||
;; floats in x/y/z order, and — like the three Vector3 fields of Camera3D —
|
||||
;; nothing in the acceptance table can tell a permutation of them apart,
|
||||
;; because every permutation has the same layout.
|
||||
(defstruct Vector2 [x f32 y f32])
|
||||
(defstruct Vector3 [x f32 y f32 z f32])
|
||||
(defstruct Color [r u8 g u8 b u8 a u8])
|
||||
|
||||
;; Texture2D is five 4-byte fields in a row, which is the layout most likely
|
||||
@ -53,7 +59,10 @@
|
||||
s 83 t 84 u 85 v 86 w 87 x 88 y 89 z 90
|
||||
escape 256 enter 257 tab 258 backspace 259
|
||||
right 262 left 263 down 264 up 265
|
||||
left-shift 340])
|
||||
left-shift 340
|
||||
;; KEY_NULL is not a key. It is the value set-exit-key takes to mean "no
|
||||
;; key closes the window", which is the only thing that ever passes it.
|
||||
null 0])
|
||||
|
||||
(defenum MouseButton
|
||||
[left 0 right 1 middle 2 side 3 extra 4 forward 5 back 6])
|
||||
@ -79,21 +88,47 @@
|
||||
;; the OR of several and a keyword can only ever name one member, so the
|
||||
;; parameter is a u32 and the members are defconsts rather than a defenum.
|
||||
;;
|
||||
;; The part that is NOT obvious from the signature: this has to be called
|
||||
;; BEFORE init-window. raylib stores the flags and reads them while creating
|
||||
;; the context, so setting them afterwards is accepted, logged at INFO, and
|
||||
;; does nothing to the window that already exists — which looks exactly like
|
||||
;; a binding that did not work. Only the four the examples ask for are here;
|
||||
;; the rest are one line each when something calls them.
|
||||
(defconst flag-fullscreen-mode u32 2)
|
||||
(defconst flag-window-resizable u32 4)
|
||||
(defconst flag-msaa-4x-hint u32 32)
|
||||
(defconst flag-vsync-hint u32 64)
|
||||
;; The part that is NOT obvious from the signature: set-config-flags has to
|
||||
;; be called BEFORE init-window. raylib stores the flags and reads them while
|
||||
;; creating the context, so setting them afterwards is accepted, logged at
|
||||
;; INFO, and does nothing to the window that already exists — which looks
|
||||
;; exactly like a binding that did not work. Afterwards is what the generated
|
||||
;; set-window-state, clear-window-state and window-state? are for, and they
|
||||
;; take these same bits, which is why the four sand.flan sets grew into the
|
||||
;; whole of ConfigFlags: a subset has its hole exactly where the next caller
|
||||
;; looks. Every value below was read off raylib.h 5.5.
|
||||
;;
|
||||
;; The values are NOT in bit order in the header and are not reordered here:
|
||||
;; FLAG_VSYNC_HINT is 0x40 and FLAG_FULLSCREEN_MODE is 0x02.
|
||||
(defconst flag-vsync-hint u32 64)
|
||||
(defconst flag-fullscreen-mode u32 2)
|
||||
(defconst flag-window-resizable u32 4)
|
||||
(defconst flag-window-undecorated u32 8)
|
||||
(defconst flag-window-hidden u32 128)
|
||||
(defconst flag-window-minimized u32 512)
|
||||
(defconst flag-window-maximized u32 1024)
|
||||
(defconst flag-window-unfocused u32 2048)
|
||||
(defconst flag-window-topmost u32 4096)
|
||||
(defconst flag-window-always-run u32 256)
|
||||
(defconst flag-window-transparent u32 16)
|
||||
(defconst flag-window-highdpi u32 8192)
|
||||
(defconst flag-window-mouse-passthrough u32 16384)
|
||||
(defconst flag-borderless-windowed-mode u32 32768)
|
||||
(defconst flag-msaa-4x-hint u32 32)
|
||||
(defconst flag-interlaced-hint u32 65536)
|
||||
|
||||
(declare-c set-config-flags [flags u32] "SetConfigFlags")
|
||||
|
||||
;; ── Input ───────────────────────────────────────────────────────────
|
||||
|
||||
;; Which key closes the window, ESCAPE by default. Hand-written rather than
|
||||
;; left to the generated half because the Flan face is the difference: raylib
|
||||
;; declares it `void SetExitKey(int key)` and the generated line therefore
|
||||
;; takes an i32, where this one takes a Key and so accepts :escape and refuses
|
||||
;; a typo. `:null` is how a program says "no key does that" and takes the
|
||||
;; close over itself.
|
||||
(declare-c set-exit-key [key Key] "SetExitKey")
|
||||
|
||||
(declare-c key-pressed? [key Key] bool "IsKeyPressed")
|
||||
(declare-c key-down? [key Key] bool "IsKeyDown")
|
||||
(declare-c key-released? [key Key] bool "IsKeyReleased")
|
||||
@ -189,6 +224,20 @@
|
||||
[x i32 y i32 width i32 height i32 color Color]
|
||||
"DrawRectangle")
|
||||
|
||||
;; Scissor: everything drawn between these two is clipped to the rectangle,
|
||||
;; in screen pixels with y down from the top — which is NOT the GL convention
|
||||
;; underneath, and raylib flips it for you. It is drawing state like
|
||||
;; begin-mode-2d is, so the pair is hand-written for the same reason: both
|
||||
;; halves of a begin/end pair sit together, and both are on a frame's path.
|
||||
;;
|
||||
;; Nothing headless can assert this. A clip that is off by the window height
|
||||
;; — the flip not applied — draws a perfectly plausible picture in the wrong
|
||||
;; half of the screen, and only looking catches it.
|
||||
(declare-c begin-scissor-mode
|
||||
[x i32 y i32 width i32 height i32]
|
||||
"BeginScissorMode")
|
||||
(declare-c end-scissor-mode [] "EndScissorMode")
|
||||
|
||||
;; ── Shapes texture ──────────────────────────────────────────────────
|
||||
;;
|
||||
;; raylib draws every shape from one atlas texture, and this pair sets and
|
||||
@ -243,6 +292,75 @@
|
||||
[position Vector2 camera Camera2D] Vector2
|
||||
"GetWorldToScreen2D")
|
||||
|
||||
;; ── Camera3D ────────────────────────────────────────────────────────
|
||||
;;
|
||||
;; raylib's `Camera` is a typedef for this, and every 3D call takes it by
|
||||
;; value: position, the point it looks at, an up vector, a vertical
|
||||
;; field-of-view in degrees, and which projection to build. Field order is
|
||||
;; read off raylib.h 5.5 and is position/target/up/fovy/projection.
|
||||
;;
|
||||
;; What nothing here can pin, said the way the Texture2D note above says it:
|
||||
;; the first three fields are the same type and the same size, so a permuted
|
||||
;; Camera3D has the identical layout and every acceptance case that could
|
||||
;; exist would pass. A camera that looks from the wrong place is a picture,
|
||||
;; not a number. `projection` is `int` in the header and i32 here rather than
|
||||
;; CameraProjection, because the layout is what a defstruct states and no
|
||||
;; other field in this file is enum-typed; the enum below is for the value a
|
||||
;; caller writes into it.
|
||||
(defenum CameraProjection [perspective 0 orthographic 1])
|
||||
|
||||
;; A member's value, as the i32 the field above is. Writing the field's type
|
||||
;; as CameraProjection instead was tried first and is refused by the check
|
||||
;; that compares this file against raylib.h — "field projection is
|
||||
;; CameraProjection in the defstruct and i32 (int)" — which is the right
|
||||
;; answer even though the two have the same representation: a defstruct is a
|
||||
;; statement about a C layout and the C says `int`. And a bare `:perspective`
|
||||
;; cannot be written into an i32 field either, because a keyword only resolves
|
||||
;; where an enum type is expected. So the conversion is said out loud, once,
|
||||
;; here: (camera-projection :perspective) is 0 and a typo is still an error.
|
||||
(defn camera-projection [p CameraProjection] i32 (i32 p))
|
||||
|
||||
;; UpdateCamera's mode. :custom means it does nothing and the program moves
|
||||
;; the camera itself.
|
||||
(defenum CameraMode
|
||||
[custom 0 free 1 orbital 2 first-person 3 third-person 4])
|
||||
|
||||
(defstruct Camera3D
|
||||
[position Vector3 target Vector3 up Vector3 fovy f32 projection i32])
|
||||
|
||||
;; The mode's built-in controls, applied to the camera in place — hence
|
||||
;; (Ptr Camera3D), on the rule the Images section states: a call that mutates
|
||||
;; takes a pointer at the Flan face. It reads the mouse and the keyboard
|
||||
;; itself, which is what makes it a per-frame call and not a setup one.
|
||||
(declare-c update-camera
|
||||
[camera (Ptr Camera3D) mode CameraMode]
|
||||
"UpdateCamera")
|
||||
|
||||
(declare-c begin-mode-3d [camera Camera3D] "BeginMode3D")
|
||||
(declare-c end-mode-3d [] "EndMode3D")
|
||||
|
||||
;; Where a world point lands on the screen, for the current camera and the
|
||||
;; current window size. Unlike get-world-to-screen-2d this one is not pure
|
||||
;; arithmetic over its arguments — it reads the window's dimensions — so it
|
||||
;; needs a window, and headless it answers about a 0x0 screen.
|
||||
(declare-c get-world-to-screen
|
||||
[position Vector3 camera Camera3D] Vector2
|
||||
"GetWorldToScreen")
|
||||
|
||||
;; The three 3D draws the examples use. All of them are immediate-mode
|
||||
;; geometry and all of them need a GL context, so like the shapes above they
|
||||
;; are link-checked and nothing more.
|
||||
(declare-c draw-cube
|
||||
[position Vector3 width f32 height f32 length f32 color Color]
|
||||
"DrawCube")
|
||||
(declare-c draw-cube-wires
|
||||
[position Vector3 width f32 height f32 length f32 color Color]
|
||||
"DrawCubeWires")
|
||||
|
||||
;; `slices` squares each way from the origin, `spacing` world units apart, on
|
||||
;; the XZ plane.
|
||||
(declare-c draw-grid [slices i32 spacing f32] "DrawGrid")
|
||||
|
||||
;; ── Shapes ──────────────────────────────────────────────────────────
|
||||
;;
|
||||
;; Rectangle intersection, which raylib computes from all four fields in
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user