103 lines
4.0 KiB
Plaintext
103 lines
4.0 KiB
Plaintext
;;;; raylib [core] example - 2d camera mouse zoom
|
|
;;;;
|
|
;;;; examples/core/core_2d_camera_mouse_zoom.c at the raylib 5.5 tag. It
|
|
;;;; needed rlgl's matrix stack: the grid is a 3D grid on the XZ plane, and the
|
|
;;;; C stands it up in the XY plane by pushing a matrix, translating, rotating
|
|
;;;; ninety degrees about X and drawing. vendor/rlgl binds that stack.
|
|
;;;;
|
|
;;;; One difference from the C. The mouse read-out is `TextFormat("[%i, %i]",
|
|
;;;; ...)` through DrawTextEx with a spacing of 2. TextFormat is variadic and
|
|
;;;; unbound, so the read-out is drawn in pieces with draw-text and
|
|
;;;; digits.fln's draw-int, which space the glyphs raylib's default way.
|
|
|
|
import rl "vendor:raylib"
|
|
|
|
import rlgl "vendor:rlgl"
|
|
|
|
import d "digits.fln"
|
|
|
|
const screen-width = 800
|
|
const screen-height = 450
|
|
|
|
;; 0 zooms with the mouse wheel, 1 with a right-button drag.
|
|
once zoom-mode: i32
|
|
once camera: rl/Camera2D
|
|
|
|
;; Put the world point under the mouse at the camera's origin, and the origin
|
|
;; under the mouse, so a zoom that follows keeps that point still.
|
|
fn anchor-at-mouse() -> ()
|
|
let mouse-world = rl/get-screen-to-world-2d(rl/get-mouse-position(), camera)
|
|
camera.offset = rl/get-mouse-position()
|
|
camera.target = mouse-world
|
|
|
|
;; One zoom step: `amount` is how far the input moved, and the direction is its
|
|
;; sign. The zoom stays between 1/8 and 64.
|
|
fn zoom-by(amount: f32, rate: f32) -> ()
|
|
let factor = 1.0 + rate * abs-f32(amount)
|
|
let factor = if amount < 0.0 then 1.0 / factor else factor
|
|
camera.zoom = clamp(camera.zoom * factor, 0.125, 64.0)
|
|
|
|
fn main() -> ()
|
|
rl/init-window(screen-width, screen-height,
|
|
"raylib [core] example - 2d camera mouse zoom")
|
|
defer rl/close-window()
|
|
;; A zero zoom makes the camera's transform singular.
|
|
camera = rl/Camera2D{.zoom 1.0}
|
|
zoom-mode = 0
|
|
rl/set-target-fps(60)
|
|
until rl/window-should-close()
|
|
;; Update
|
|
if rl/is-key-pressed(:key-one)
|
|
zoom-mode = 0
|
|
elif rl/is-key-pressed(:key-two)
|
|
zoom-mode = 1
|
|
;; Drag to move: the mouse's screen delta, scaled back into world units.
|
|
if rl/is-mouse-button-down(:mouse-left)
|
|
let delta = rl/v2-scale(rl/get-mouse-delta(), -1.0 / camera.zoom)
|
|
camera.target = rl/v2-add(camera.target, delta)
|
|
if zoom-mode == 0
|
|
let wheel = rl/get-mouse-wheel-move()
|
|
if wheel != 0.0
|
|
anchor-at-mouse()
|
|
zoom-by(wheel, 0.25)
|
|
else
|
|
if rl/is-mouse-button-pressed(:mouse-right)
|
|
anchor-at-mouse()
|
|
if rl/is-mouse-button-down(:mouse-right)
|
|
zoom-by(rl/get-mouse-delta().x, 0.01)
|
|
;; Draw
|
|
rl/with-drawing:
|
|
rl/clear-background(rl/raywhite)
|
|
rl/begin-mode-2d(camera)
|
|
;; The 3D grid, rotated ninety degrees and centred on the origin, so it
|
|
;; lies in the XY plane the 2D camera looks at.
|
|
rlgl/push-matrix()
|
|
rlgl/translate(0.0, 25.0 * 50.0, 0.0)
|
|
rlgl/rotate(90.0, 1.0, 0.0, 0.0)
|
|
rl/draw-grid(100, 50.0)
|
|
rlgl/pop-matrix()
|
|
;; A reference circle.
|
|
rl/draw-circle(rl/get-screen-width() / 2, rl/get-screen-height() / 2,
|
|
50.0, rl/maroon)
|
|
rl/end-mode-2d()
|
|
;; The mouse, and where it is in screen pixels.
|
|
let mouse = rl/get-mouse-position()
|
|
x = i32(mouse.x) - 44
|
|
y = i32(mouse.y) - 24
|
|
rl/draw-circle-v(mouse, 4.0, rl/darkgray)
|
|
rl/draw-text("[", x, y, 20, rl/black)
|
|
let x = x + rl/measure-text("[", 20)
|
|
let x = x + d/draw-int(rl/get-mouse-x(), x, y, 20, rl/black)
|
|
rl/draw-text(", ", x, y, 20, rl/black)
|
|
let x = x + rl/measure-text(", ", 20)
|
|
let x = x + d/draw-int(rl/get-mouse-y(), x, y, 20, rl/black)
|
|
rl/draw-text("]", x, y, 20, rl/black)
|
|
rl/draw-text("[1][2] Select mouse zoom mode (Wheel or Move)", 20, 20, 20,
|
|
rl/darkgray)
|
|
if zoom-mode == 0
|
|
rl/draw-text("Mouse left button drag to move, mouse wheel to zoom", 20,
|
|
50, 20, rl/darkgray)
|
|
else
|
|
rl/draw-text("Mouse left button drag to move, mouse press and move to zoom",
|
|
20, 50, 20, rl/darkgray)
|