Two gaps in what was claimed. The first is prose: "the typedef follows the defstruct" answers field order and field types but says nothing about padding, which reads like the remaining hazard. It is not one. Every field type the generator admits has the same layout under LLVM as under C, and emit.ml writes no datalayout, so clang applies the target's own rules to both halves; everything where they could diverge — an array, a slice, an Option, a map, a union — is already refused at the field. The second is real. The flattened declaration's name is invented by appending -c, so a hand-written foo-c beside (declare-c foo ...) came out as the checker complaining that a name not in the file was declared twice. Refused now where it happens, naming both and saying to rename one.
486 lines
22 KiB
Plaintext
486 lines
22 KiB
Plaintext
;;;; raylib, declared for Flan. The directory is the package (plan.org,
|
|
;;;; Modules), and (import rl "vendor:raylib") qualifies all of it as rl/…
|
|
;;;;
|
|
;;;; Every binding here is one `declare-c` line naming raylib's own function
|
|
;;;; in raylib's own signature — Color by value, Vector2 returned by value —
|
|
;;;; and the compiler writes the C that flattens it. There is no shim.c in
|
|
;;;; this directory any more, and no hand-written wrapper at all.
|
|
;;;;
|
|
;;;; The shim itself did not go away, only the typing of it. A small
|
|
;;;; aggregate's calling convention is a per-target classification rather than
|
|
;;;; part of its layout: x86-64 hands Vector2 over as <2 x float> and returns
|
|
;;;; Rectangle as {i64,i64}, and arm64 and wasm32 each do something else.
|
|
;;;; Written in C, clang classifies every one of them correctly for whichever
|
|
;;;; target the build is for; written in emit.ml it would be three calling
|
|
;;;; conventions to reimplement and then keep correct forever, and a mistake
|
|
;;;; would read as a field full of garbage rather than as a link error. This
|
|
;;;; is "one narrow host ABI, implemented twice" (plan.org, Targets). See
|
|
;;;; lib/shim.ml.
|
|
;;;;
|
|
;;;; What that means for reading this file: the `defstruct`s below are the
|
|
;;;; only statement anywhere about raylib's layouts, and the generated C
|
|
;;;; typedefs are made from them. No raylib header is consulted — a build
|
|
;;;; needs libraylib linkable, not raylib-devel — so a wrong field order here
|
|
;;;; is wrong everywhere and nothing but a test can catch it. The acceptance
|
|
;;;; cases pin the layouts by making raylib *compute* with the fields, and
|
|
;;;; they go red when a struct below is permuted. Likewise a scalar's width:
|
|
;;;; f64 where raylib says float now emits `double` in the generated
|
|
;;;; prototype, and raylib reads garbage.
|
|
;;;;
|
|
;;;; Two bindings keep a hand-written Flan wrapper, both because their Flan
|
|
;;;; face is deliberately not raylib's: collision-point-poly? takes a slice,
|
|
;;;; and collision-lines answers with an Option. Both wrappers are Flan.
|
|
|
|
;; Layouts are C's — no object headers anywhere — so these are exactly
|
|
;; raylib's structs and nothing marshals.
|
|
(defstruct Vector2 [x f32 y 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
|
|
;; to be silently wrong: permute two of them and every field still reads as a
|
|
;; plausible number. Rectangle is four floats in x/y/width/height order.
|
|
(defstruct Texture2D [id u32 width i32 height i32 mipmaps i32 format i32])
|
|
(defstruct Rectangle [x f32 y f32 width f32 height f32])
|
|
|
|
;; KeyboardKey, the subset sand.flan uses. A keyword at a call site resolves
|
|
;; against these members at compile time and a typo is an error there.
|
|
(defenum Key
|
|
[space 32 apostrophe 39 comma 44 minus 45 period 46 slash 47
|
|
zero 48 one 49 two 50 three 51 four 52
|
|
five 53 six 54 seven 55 eight 56 nine 57
|
|
a 65 b 66 c 67 d 68 e 69 f 70 g 71 h 72 i 73
|
|
j 74 k 75 l 76 m 77 n 78 o 79 p 80 q 81 r 82
|
|
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])
|
|
|
|
(defenum MouseButton
|
|
[left 0 right 1 middle 2 side 3 extra 4 forward 5 back 6])
|
|
|
|
(defenum TraceLogLevel
|
|
[all 0 trace 1 debug 2 info 3 warning 4 error 5 fatal 6 none 7])
|
|
|
|
;; ── Window ──────────────────────────────────────────────────────────
|
|
|
|
(declare-c init-window [width i32 height i32 title string] "InitWindow")
|
|
(declare-c close-window [] "CloseWindow")
|
|
(declare-c window-should-close? [] bool "WindowShouldClose")
|
|
(declare-c set-target-fps [fps i32] "SetTargetFPS")
|
|
(declare-c set-trace-log-level [level TraceLogLevel] "SetTraceLogLevel")
|
|
|
|
;; ── Input ───────────────────────────────────────────────────────────
|
|
|
|
(declare-c key-pressed? [key Key] bool "IsKeyPressed")
|
|
(declare-c key-down? [key Key] bool "IsKeyDown")
|
|
(declare-c key-released? [key Key] bool "IsKeyReleased")
|
|
|
|
(declare-c mouse-button-pressed?
|
|
[button MouseButton] bool
|
|
"IsMouseButtonPressed")
|
|
(declare-c mouse-button-down? [button MouseButton] bool "IsMouseButtonDown")
|
|
(declare-c mouse-button-released?
|
|
[button MouseButton] bool
|
|
"IsMouseButtonReleased")
|
|
|
|
(declare-c get-mouse-position [] Vector2 "GetMousePosition")
|
|
|
|
;; ── Colours ─────────────────────────────────────────────────────────
|
|
;;
|
|
;; A Color is four bytes in RGBA order, so it is *not* the little-endian
|
|
;; reading of the packed 0xRRGGBBAA integer — that is why get-color is a real
|
|
;; call and not a reinterpretation.
|
|
|
|
(declare-c get-color [hex u32] Color "GetColor")
|
|
|
|
(defconst black (Color {:r 0 :g 0 :b 0 :a 255}))
|
|
(defconst white (Color {:r 255 :g 255 :b 255 :a 255}))
|
|
|
|
;; ── Drawing ─────────────────────────────────────────────────────────
|
|
|
|
(declare-c begin-drawing [] "BeginDrawing")
|
|
(declare-c end-drawing [] "EndDrawing")
|
|
(declare-c draw-fps [x i32 y i32] "DrawFPS")
|
|
|
|
(declare-c clear-background [color Color] "ClearBackground")
|
|
|
|
(declare-c draw-rectangle
|
|
[x i32 y i32 width i32 height i32 color Color]
|
|
"DrawRectangle")
|
|
|
|
;; ── Shapes texture ──────────────────────────────────────────────────
|
|
;;
|
|
;; raylib draws every shape from one atlas texture, and this pair sets and
|
|
;; reads it. It is bound here for a second reason: it is the only part of the
|
|
;; API that stores a Texture2D and a Rectangle and hands them back without
|
|
;; touching the GPU, so it is how the acceptance table checks both layouts
|
|
;; headlessly. Everything else that takes a texture needs a GL context.
|
|
;;
|
|
;; raylib substitutes a default ({1,1,1,1,7} / {0,0,1,1}) when the id or the
|
|
;; source's width or height is not positive, so a caller — and the test —
|
|
;; should keep clear of those values if it wants its own back.
|
|
|
|
(declare-c set-shapes-texture
|
|
[texture Texture2D source Rectangle]
|
|
"SetShapesTexture")
|
|
|
|
(declare-c get-shapes-texture [] Texture2D "GetShapesTexture")
|
|
|
|
(declare-c get-shapes-texture-rectangle
|
|
[] Rectangle
|
|
"GetShapesTextureRectangle")
|
|
|
|
;; ── Camera2D ────────────────────────────────────────────────────────
|
|
;;
|
|
;; The 2D camera: everything drawn between begin-mode-2d and end-mode-2d is
|
|
;; transformed by it. `offset` is where the camera's target lands on screen —
|
|
;; half the window size is what centres it — `target` is the world point that
|
|
;; goes there, and rotation is in degrees.
|
|
;;
|
|
;; `zoom` of 0 makes the transform singular and both conversions below hand
|
|
;; back NaN rather than failing. raylib does not guard it and neither does
|
|
;; this; 1.0 is the identity and a fresh (Camera2D {}) is therefore NOT usable
|
|
;; as one — it has to be given a zoom.
|
|
|
|
(defstruct Camera2D [offset Vector2 target Vector2 rotation f32 zoom f32])
|
|
|
|
(declare-c begin-mode-2d [camera Camera2D] "BeginMode2D")
|
|
|
|
(declare-c end-mode-2d [] "EndMode2D")
|
|
|
|
;; The two conversions are pure arithmetic over every field of the camera, so
|
|
;; unlike the rest of the camera they run with no window and no GL context.
|
|
;; That is what the acceptance table uses to pin Camera2D's layout, and — via
|
|
;; a rotated camera, which is the only call here that mixes x into y — it is
|
|
;; also the only thing that pins Vector2's two fields against each other.
|
|
|
|
(declare-c get-screen-to-world-2d
|
|
[position Vector2 camera Camera2D] Vector2
|
|
"GetScreenToWorld2D")
|
|
|
|
(declare-c get-world-to-screen-2d
|
|
[position Vector2 camera Camera2D] Vector2
|
|
"GetWorldToScreen2D")
|
|
|
|
;; ── Shapes ──────────────────────────────────────────────────────────
|
|
;;
|
|
;; Rectangle intersection, which raylib computes from all four fields in
|
|
;; different ways. It is the one Rectangle call that needs no GPU, so it is
|
|
;; also how the acceptance table pins the layout: a store-and-return check is
|
|
;; symmetric and a permuted layout survives it untouched.
|
|
|
|
(declare-c get-collision-rec
|
|
[a Rectangle b Rectangle] Rectangle
|
|
"GetCollisionRec")
|
|
|
|
;; ── Collision ───────────────────────────────────────────────────────
|
|
;;
|
|
;; All of these are pure geometry: no window, no GL context, no state. That
|
|
;; makes them the other half of what the acceptance table can assert, and the
|
|
;; only part of the 2D surface that is tested as thoroughly as it is bound.
|
|
;;
|
|
;; Each is declared exactly as raylib declares it. The pointers and the copies
|
|
;; the crossing needs — a parameter is not an assignable place
|
|
;; (spec-memory.md), so a struct argument has no address to take without one —
|
|
;; are in the generated halves and not here.
|
|
|
|
(declare-c collision-recs?
|
|
[a Rectangle b Rectangle] bool
|
|
"CheckCollisionRecs")
|
|
|
|
(declare-c collision-circles?
|
|
[c1 Vector2 r1 f32 c2 Vector2 r2 f32] bool
|
|
"CheckCollisionCircles")
|
|
|
|
(declare-c collision-circle-rec?
|
|
[center Vector2 radius f32 rec Rectangle] bool
|
|
"CheckCollisionCircleRec")
|
|
|
|
(declare-c collision-circle-line? [center Vector2 radius f32
|
|
p1 Vector2 p2 Vector2] bool "CheckCollisionCircleLine")
|
|
|
|
(declare-c collision-point-rec?
|
|
[point Vector2 rec Rectangle] bool
|
|
"CheckCollisionPointRec")
|
|
|
|
(declare-c collision-point-circle?
|
|
[point Vector2 center Vector2 radius f32] bool
|
|
"CheckCollisionPointCircle")
|
|
|
|
(declare-c collision-point-triangle? [point Vector2 a Vector2 b Vector2
|
|
c Vector2] bool "CheckCollisionPointTriangle")
|
|
|
|
;; `threshold` is in pixels, and it is not optional in practice: raylib's test
|
|
;; is a distance comparison in floats, so a point exactly on the line fails at
|
|
;; a threshold of 0. 1 is the useful smallest value.
|
|
(declare-c collision-point-line? [point Vector2 p1 Vector2 p2 Vector2
|
|
threshold i32] bool "CheckCollisionPointLine")
|
|
|
|
;; The one binding whose Flan face is not raylib's, and one of only two in
|
|
;; this file with a hand-written wrapper on top. A Flan slice crosses as
|
|
;; ptr+len with an i64 length; raylib wants a pointer and an `int` count, and
|
|
;; the generator refuses to guess what integer type a C count parameter is —
|
|
;; so the declaration says (Ptr Vector2) and a count, and the wrapper takes
|
|
;; the slice apart. The polygon is not closed explicitly; raylib joins the
|
|
;; last point to the first.
|
|
;;
|
|
;; Empty is answered here rather than passed on: (at points 0) would be an
|
|
;; out-of-bounds read, and raylib answers false for a polygon with no points
|
|
;; anyway.
|
|
(declare-c collision-point-poly?-raw
|
|
[point Vector2 points (Ptr Vector2) count i32] bool
|
|
"CheckCollisionPointPoly")
|
|
|
|
(defn collision-point-poly? [point Vector2 points [Vector2]] bool
|
|
(if (= (len points) 0)
|
|
false
|
|
(collision-point-poly?-raw point (addr (at points 0)) (len points))))
|
|
|
|
;; The one that answers with more than yes or no: where the two segments meet.
|
|
;; None is "they do not", so the point cannot be read when there isn't one —
|
|
;; raylib's own signature leaves the out-parameter untouched in that case and
|
|
;; a caller that forgets reads whatever was there.
|
|
(declare-c collision-lines-raw
|
|
[a1 Vector2 a2 Vector2 b1 Vector2 b2 Vector2 out (Ptr Vector2)] bool
|
|
"CheckCollisionLines")
|
|
|
|
(defn collision-lines [a1 Vector2 a2 Vector2 b1 Vector2 b2 Vector2]
|
|
(Option Vector2)
|
|
(let [out (Vector2 {})]
|
|
(if (collision-lines-raw a1 a2 b1 b2 (addr out))
|
|
(Some out)
|
|
None)))
|
|
|
|
;; ── Textures ────────────────────────────────────────────────────────
|
|
;;
|
|
;; Everything here needs a GL context, so a window has to be open first —
|
|
;; load-texture before init-window returns an id of 0 and raylib says so on
|
|
;; the log. texture-valid? is how that is noticed in the program rather than
|
|
;; only in the log; raylib 5.5 spells it IsTextureValid, and IsTextureReady,
|
|
;; which older code calls, does not exist in this version.
|
|
|
|
(declare-c load-texture [path string] Texture2D "LoadTexture")
|
|
|
|
(declare-c texture-valid? [texture Texture2D] bool "IsTextureValid")
|
|
|
|
(declare-c unload-texture [texture Texture2D] "UnloadTexture")
|
|
|
|
(declare-c draw-texture
|
|
[texture Texture2D x i32 y i32 tint Color]
|
|
"DrawTexture")
|
|
|
|
(declare-c draw-texture-v
|
|
[texture Texture2D position Vector2 tint Color]
|
|
"DrawTextureV")
|
|
|
|
(declare-c draw-texture-ex [texture Texture2D position Vector2 rotation f32
|
|
scale f32 tint Color] "DrawTextureEx")
|
|
|
|
;; A negative source width or height flips the sprite, which is how a sheet is
|
|
;; drawn facing the other way without a second image.
|
|
(declare-c draw-texture-rec [texture Texture2D source Rectangle position Vector2
|
|
tint Color] "DrawTextureRec")
|
|
|
|
;; ── Images ──────────────────────────────────────────────────────────
|
|
;;
|
|
;; An Image is pixels in RAM. Nothing here touches the GPU, which makes it the
|
|
;; one corner of the 2D surface a headless test can assert properly — raylib
|
|
;; *computes* with these, and a wrong answer is a wrong number rather than the
|
|
;; struct handed back unchanged.
|
|
;;
|
|
;; `data` is raylib's buffer and Flan never reads through it; it is here so
|
|
;; the struct is the right size and the four ints that follow are at the right
|
|
;; offsets. `format` is a PixelFormat code — GenImageColor makes 7, which is
|
|
;; uncompressed R8G8B8A8, one byte per channel.
|
|
;;
|
|
;; The split between by-value and by-pointer here is raylib's own and worth
|
|
;; keeping: a call that *mutates* the image takes (Ptr Image) at the Flan
|
|
;; level too, so a caller can see which ones change what they are given.
|
|
(defstruct Image [data (Ptr u8) width i32 height i32 mipmaps i32 format i32])
|
|
|
|
(declare-c load-image [path string] Image "LoadImage")
|
|
|
|
;; raylib 5.5 spells this IsImageValid. IsImageReady, which older code calls,
|
|
;; does not exist here — the same rename that took IsTextureReady.
|
|
(declare-c image-valid? [image Image] bool "IsImageValid")
|
|
|
|
;; By value, as raylib has it. The caller's copy is dangling afterwards —
|
|
;; `data` pointed at the buffer this just freed — so an Image is used or
|
|
;; unloaded, never both.
|
|
(declare-c unload-image [image Image] "UnloadImage")
|
|
|
|
;; The format is taken from the path's extension, so ".png" writes a PNG.
|
|
;; False means it could not be written.
|
|
(declare-c export-image [image Image path string] bool "ExportImage")
|
|
|
|
(declare-c gen-image-color
|
|
[width i32 height i32 color Color] Image
|
|
"GenImageColor")
|
|
|
|
;; Bicubic, so the pixels that come out are interpolated and only the new
|
|
;; width and height are exactly predictable. image-resize-nn is the
|
|
;; nearest-neighbour one, and it is the one to reach for when the colours
|
|
;; have to survive.
|
|
(declare-c image-resize
|
|
[image (Ptr Image) width i32 height i32]
|
|
"ImageResize")
|
|
(declare-c image-resize-nn
|
|
[image (Ptr Image) width i32 height i32]
|
|
"ImageResizeNN")
|
|
|
|
(declare-c image-crop [image (Ptr Image) crop Rectangle] "ImageCrop")
|
|
|
|
(declare-c image-flip-horizontal [image (Ptr Image)] "ImageFlipHorizontal")
|
|
(declare-c image-flip-vertical [image (Ptr Image)] "ImageFlipVertical")
|
|
|
|
(declare-c image-draw-pixel
|
|
[image (Ptr Image) x i32 y i32 color Color]
|
|
"ImageDrawPixel")
|
|
|
|
;; Out of bounds is not an error: raylib logs a warning and hands back a
|
|
;; transparent black, so a caller that is off by one gets zeroes rather than
|
|
;; somebody else's memory.
|
|
(declare-c get-image-color [image Image x i32 y i32] Color "GetImageColor")
|
|
|
|
;; The one call in this section that does need a GL context — it uploads. An
|
|
;; image loaded and edited on the CPU becomes something draw-texture can use.
|
|
(declare-c load-texture-from-image
|
|
[image Image] Texture2D
|
|
"LoadTextureFromImage")
|
|
|
|
;; ── Shapes ──────────────────────────────────────────────────────────
|
|
;;
|
|
;; Immediate-mode drawing: each of these needs a GL context, so a window has
|
|
;; to be open and none of them can be in the acceptance table. They are
|
|
;; exercised by running sand.flan and looking at it, which is the honest
|
|
;; description — "it links" is not "it draws the right thing".
|
|
;;
|
|
;; raylib's own naming is kept: a plain name fills, `-lines` outlines, and a
|
|
;; `-v` suffix takes Vector2s where the plain form takes integers.
|
|
;;
|
|
;; The one signature worth calling out is draw-rectangle-rounded-lines, which
|
|
;; in raylib 5.5 has NO thickness — it moved to the `-ex` form. The 5.1 header
|
|
;; still shows the five-argument version, and getting it wrong links cleanly
|
|
;; and draws nonsense, so this was read off the library with nm rather than
|
|
;; remembered.
|
|
|
|
(declare-c draw-pixel [x i32 y i32 color Color] "DrawPixel")
|
|
|
|
(declare-c draw-pixel-v [position Vector2 color Color] "DrawPixelV")
|
|
|
|
(declare-c draw-line [x1 i32 y1 i32 x2 i32 y2 i32 color Color] "DrawLine")
|
|
|
|
(declare-c draw-line-v [start Vector2 end Vector2 color Color] "DrawLineV")
|
|
|
|
;; The thick one is built from triangles rather than GL lines, which is why it
|
|
;; is a separate call and not a parameter on the one above.
|
|
(declare-c draw-line-ex
|
|
[start Vector2 end Vector2 thick f32 color Color]
|
|
"DrawLineEx")
|
|
|
|
(declare-c draw-circle [x i32 y i32 radius f32 color Color] "DrawCircle")
|
|
|
|
(declare-c draw-circle-v
|
|
[center Vector2 radius f32 color Color]
|
|
"DrawCircleV")
|
|
|
|
(declare-c draw-circle-lines
|
|
[x i32 y i32 radius f32 color Color]
|
|
"DrawCircleLines")
|
|
|
|
(declare-c draw-circle-lines-v
|
|
[center Vector2 radius f32 color Color]
|
|
"DrawCircleLinesV")
|
|
|
|
;; Two radii, horizontal then vertical. Equal radii is a circle, so a binding
|
|
;; that exchanged them would be invisible unless they differ — which is why
|
|
;; sand.flan's ellipse is deliberately wider than it is tall.
|
|
(declare-c draw-ellipse
|
|
[x i32 y i32 radius-h f32 radius-v f32 color Color]
|
|
"DrawEllipse")
|
|
|
|
(declare-c draw-ellipse-lines
|
|
[x i32 y i32 radius-h f32 radius-v f32 color Color]
|
|
"DrawEllipseLines")
|
|
|
|
;; Angles are degrees, clockwise from the +x axis, and `segments` is how many
|
|
;; straight pieces the arc is made of — 0 lets raylib pick from the radius.
|
|
(declare-c draw-ring [center Vector2 inner f32 outer f32 start f32 end f32
|
|
segments i32 color Color] "DrawRing")
|
|
|
|
(declare-c draw-ring-lines [center Vector2 inner f32 outer f32 start f32 end f32
|
|
segments i32 color Color] "DrawRingLines")
|
|
|
|
;; Counter-clockwise, and raylib means it: the clockwise winding is culled and
|
|
;; draws nothing at all, which looks exactly like a broken binding.
|
|
(declare-c draw-triangle
|
|
[v1 Vector2 v2 Vector2 v3 Vector2 color Color]
|
|
"DrawTriangle")
|
|
|
|
(declare-c draw-triangle-lines
|
|
[v1 Vector2 v2 Vector2 v3 Vector2 color Color]
|
|
"DrawTriangleLines")
|
|
|
|
(declare-c draw-rectangle-v
|
|
[position Vector2 size Vector2 color Color]
|
|
"DrawRectangleV")
|
|
|
|
(declare-c draw-rectangle-rec [rec Rectangle color Color] "DrawRectangleRec")
|
|
|
|
(declare-c draw-rectangle-lines
|
|
[x i32 y i32 width i32 height i32 color Color]
|
|
"DrawRectangleLines")
|
|
|
|
;; The one-pixel outline above is drawn with GL lines and sits *on* the
|
|
;; rectangle's edge; this one is drawn with quads and sits inside it, so the
|
|
;; two do not agree at thickness 1 and that is raylib's doing, not a bug here.
|
|
(declare-c draw-rectangle-lines-ex
|
|
[rec Rectangle thick f32 color Color]
|
|
"DrawRectangleLinesEx")
|
|
|
|
;; `roundness` is 0 to 1 as a fraction of the shorter side, so 0 is a plain
|
|
;; rectangle and 1 is a stadium.
|
|
(declare-c draw-rectangle-rounded [rec Rectangle roundness f32 segments i32
|
|
color Color] "DrawRectangleRounded")
|
|
|
|
;; No thickness here — see the section note. The `-ex` form below is the one
|
|
;; that takes it.
|
|
(declare-c draw-rectangle-rounded-lines [rec Rectangle roundness f32 segments i32
|
|
color Color] "DrawRectangleRoundedLines")
|
|
|
|
(declare-c draw-rectangle-rounded-lines-ex [rec Rectangle roundness f32
|
|
segments i32 thick f32 color Color] "DrawRectangleRoundedLinesEx")
|
|
|
|
;; ── Text ────────────────────────────────────────────────────────────
|
|
;;
|
|
;; Both of these use raylib's built-in font, and both therefore need
|
|
;; init-window — not for the GPU in measure-text's case, but because the
|
|
;; default font is only loaded as part of opening a window. Called headless,
|
|
;; measure-text answers 0 for every string, which was measured against
|
|
;; libraylib.so.550 and is why it is NOT in the acceptance table despite
|
|
;; looking like exactly the kind of call that could be.
|
|
;;
|
|
;; Font loading is not bound, deliberately. A Font is baseSize, glyphCount and
|
|
;; glyphPadding beside a Texture2D, a Rectangle* and a GlyphInfo* — and a
|
|
;; GlyphInfo embeds an Image. Binding it means binding two more aggregates and
|
|
;; two owned arrays for something with no headless test at the end of it, so
|
|
;; load-font, load-font-ex, unload-font, get-font-default, draw-text-ex and
|
|
;; measure-text-ex are all absent rather than half-done.
|
|
|
|
(declare-c draw-text
|
|
[text string x i32 y i32 font-size i32 color Color]
|
|
"DrawText")
|
|
|
|
(declare-c measure-text [text string font-size i32] i32 "MeasureText")
|
|
|
|
;; ── Timing and window state ─────────────────────────────────────────
|
|
;;
|
|
;; All four read state that init-window creates, so all four answer 0 before
|
|
;; there is a window — again measured, not assumed. get-frame-time is the
|
|
;; delta the last frame took, in seconds, which is what a simulation should
|
|
;; scale by instead of assuming the target fps was met.
|
|
|
|
(declare-c get-frame-time [] f32 "GetFrameTime")
|
|
(declare-c get-time [] f64 "GetTime")
|
|
(declare-c get-screen-width [] i32 "GetScreenWidth")
|
|
(declare-c get-screen-height [] i32 "GetScreenHeight")
|