add proper fnl modules to demo
This commit is contained in:
parent
9bb9fa5f5b
commit
47c4f2045c
14 changed files with 510 additions and 240 deletions
151
demo/cube3d.fnl
151
demo/cube3d.fnl
|
|
@ -1,151 +0,0 @@
|
|||
(local pxl8 (require :pxl8))
|
||||
|
||||
(var angle-x 0)
|
||||
(var angle-y 0)
|
||||
(var angle-z 0)
|
||||
(var auto-rotate true)
|
||||
(var orthographic true)
|
||||
(var wireframe true)
|
||||
(var time 0)
|
||||
(var zoom 5.0)
|
||||
(var texture-id nil)
|
||||
(var use-texture false)
|
||||
(var affine false)
|
||||
(var texture-initialized false)
|
||||
|
||||
(fn init-texture []
|
||||
(when (not texture-initialized)
|
||||
(pxl8.load_palette "sprites/pxl8_logo.ase")
|
||||
(set texture-id (pxl8.load_sprite "sprites/pxl8_logo.ase"))
|
||||
(pxl8.upload_atlas)
|
||||
(set texture-initialized true)))
|
||||
|
||||
(fn make-cube-vertices []
|
||||
[[-1 -1 -1] [1 -1 -1] [1 1 -1] [-1 1 -1]
|
||||
[-1 -1 1] [1 -1 1] [1 1 1] [-1 1 1]])
|
||||
|
||||
(fn make-cube-faces []
|
||||
[[0 1 2] [0 2 3]
|
||||
[1 5 6] [1 6 2]
|
||||
[5 4 7] [5 7 6]
|
||||
[4 0 3] [4 3 7]
|
||||
[3 2 6] [3 6 7]
|
||||
[4 5 1] [4 1 0]])
|
||||
|
||||
(fn make-cube-faces-with-uvs []
|
||||
[{:tri [0 1 2] :uvs [[0 0] [1 0] [1 1]]}
|
||||
{:tri [0 2 3] :uvs [[0 0] [1 1] [0 1]]}
|
||||
{:tri [1 5 6] :uvs [[0 0] [1 0] [1 1]]}
|
||||
{:tri [1 6 2] :uvs [[0 0] [1 1] [0 1]]}
|
||||
{:tri [5 4 7] :uvs [[0 0] [1 0] [1 1]]}
|
||||
{:tri [5 7 6] :uvs [[0 0] [1 1] [0 1]]}
|
||||
{:tri [4 0 3] :uvs [[0 0] [1 0] [1 1]]}
|
||||
{:tri [4 3 7] :uvs [[0 0] [1 1] [0 1]]}
|
||||
{:tri [3 2 6] :uvs [[0 0] [1 0] [1 1]]}
|
||||
{:tri [3 6 7] :uvs [[0 0] [1 1] [0 1]]}
|
||||
{:tri [4 5 1] :uvs [[0 0] [1 0] [1 1]]}
|
||||
{:tri [4 1 0] :uvs [[0 0] [1 1] [0 1]]}])
|
||||
|
||||
(fn get-face-color [face-idx]
|
||||
(let [colors [12 22 30 16 28 20]]
|
||||
(. colors (+ 1 (% face-idx 6)))))
|
||||
|
||||
(fn cube-update [dt]
|
||||
(set time (+ time dt))
|
||||
|
||||
(when (pxl8.key_down "w")
|
||||
(set angle-x (- angle-x (* dt 2.0))))
|
||||
(when (pxl8.key_down "s")
|
||||
(set angle-x (+ angle-x (* dt 2.0))))
|
||||
(when (pxl8.key_down "a")
|
||||
(set angle-y (- angle-y (* dt 2.0))))
|
||||
(when (pxl8.key_down "d")
|
||||
(set angle-y (+ angle-y (* dt 2.0))))
|
||||
(when (pxl8.key_down "q")
|
||||
(set angle-z (- angle-z (* dt 2.0))))
|
||||
(when (pxl8.key_down "e")
|
||||
(set angle-z (+ angle-z (* dt 2.0))))
|
||||
|
||||
(when (pxl8.key_pressed " ")
|
||||
(set wireframe (not wireframe)))
|
||||
(when (pxl8.key_pressed "f")
|
||||
(set affine (not affine)))
|
||||
(when (pxl8.key_pressed "p")
|
||||
(set orthographic (not orthographic)))
|
||||
(when (pxl8.key_pressed "r")
|
||||
(set auto-rotate (not auto-rotate)))
|
||||
(when (pxl8.key_pressed "t")
|
||||
(set use-texture (not use-texture))
|
||||
(when use-texture
|
||||
(init-texture)))
|
||||
|
||||
(when (pxl8.key_down "=")
|
||||
(set zoom (- zoom (* dt 2.0))))
|
||||
(when (pxl8.key_down "-")
|
||||
(set zoom (+ zoom (* dt 2.0))))
|
||||
(set zoom (math.max 1.0 (math.min zoom 20.0)))
|
||||
|
||||
(when auto-rotate
|
||||
(set angle-x (+ angle-x (* dt 0.7)))
|
||||
(set angle-y (+ angle-y (* dt 0.5)))
|
||||
(set angle-z (+ angle-z (* dt 0.3)))))
|
||||
|
||||
(fn cube-frame []
|
||||
(pxl8.clr 0)
|
||||
|
||||
(pxl8.clear_zbuffer)
|
||||
(pxl8.set_affine_textures affine)
|
||||
(pxl8.set_backface_culling true)
|
||||
(pxl8.set_wireframe wireframe)
|
||||
|
||||
(if orthographic
|
||||
(let [size (* 2.5 (/ zoom 5.0))
|
||||
aspect (/ (pxl8.get_width) (pxl8.get_height))
|
||||
w (* size aspect)
|
||||
h size]
|
||||
(pxl8.set_projection (pxl8.mat4_ortho (- w) w (- h) h 1.0 50.0)))
|
||||
(let [aspect (/ (pxl8.get_width) (pxl8.get_height))
|
||||
fov (/ 3.14159 (+ 2.0 (/ zoom 5.0)))]
|
||||
(pxl8.set_projection (pxl8.mat4_perspective fov aspect 1.0 50.0))))
|
||||
|
||||
(pxl8.set_view (pxl8.mat4_lookat [0 0 zoom] [0 0 0] [0 1 0]))
|
||||
|
||||
(let [model (-> (pxl8.mat4_identity)
|
||||
(pxl8.mat4_multiply (pxl8.mat4_rotate_x angle-x))
|
||||
(pxl8.mat4_multiply (pxl8.mat4_rotate_y angle-y))
|
||||
(pxl8.mat4_multiply (pxl8.mat4_rotate_z angle-z)))]
|
||||
(pxl8.set_model model))
|
||||
|
||||
(let [vertices (make-cube-vertices)]
|
||||
(if (and use-texture texture-id)
|
||||
(let [faces (make-cube-faces-with-uvs)]
|
||||
(each [i face-data (ipairs faces)]
|
||||
(let [tri-indices face-data.tri
|
||||
tri-uvs face-data.uvs
|
||||
v0 (. vertices (+ 1 (. tri-indices 1)))
|
||||
v1 (. vertices (+ 1 (. tri-indices 2)))
|
||||
v2 (. vertices (+ 1 (. tri-indices 3)))
|
||||
uv0 (. tri-uvs 1)
|
||||
uv1 (. tri-uvs 2)
|
||||
uv2 (. tri-uvs 3)]
|
||||
(pxl8.draw_triangle_3d_textured
|
||||
v0 v1 v2
|
||||
uv0 uv1 uv2
|
||||
texture-id))))
|
||||
(let [faces (make-cube-faces)]
|
||||
(each [i face (ipairs faces)]
|
||||
(let [[i0 i1 i2] face
|
||||
v0 (. vertices (+ 1 i0))
|
||||
v1 (. vertices (+ 1 i1))
|
||||
v2 (. vertices (+ 1 i2))
|
||||
color (get-face-color (math.floor (/ (- i 1) 2)))]
|
||||
(pxl8.draw_triangle_3d v0 v1 v2 color))))))
|
||||
|
||||
(pxl8.text "WASD/QE: Rotate | +/-: Zoom | Space: Wire | R: Auto | P: Proj" 5 5 15)
|
||||
(pxl8.text (.. "T: Texture | F: Affine | Mode: "
|
||||
(if wireframe "Wire" "Fill")
|
||||
" | Texture: " (if use-texture "On" "Off")
|
||||
" | Mapping: " (if affine "Affine" "Persp")) 5 15 15))
|
||||
|
||||
{:update cube-update
|
||||
:frame cube-frame}
|
||||
|
|
@ -1,5 +1,5 @@
|
|||
(local pxl8 (require :pxl8))
|
||||
(local cube3d (fennel.dofile "cube3d.fnl"))
|
||||
(local cube3d (require :mod.cube3d))
|
||||
|
||||
(var time 0)
|
||||
(var current-effect 1)
|
||||
|
|
|
|||
213
demo/mod/cube3d.fnl
Normal file
213
demo/mod/cube3d.fnl
Normal file
|
|
@ -0,0 +1,213 @@
|
|||
(local pxl8 (require :pxl8))
|
||||
(local debug-ui (require :mod.debug_ui))
|
||||
|
||||
(var angle-x 0)
|
||||
(var angle-y 0)
|
||||
(var angle-z 0)
|
||||
(var auto-rotate true)
|
||||
(var orthographic true)
|
||||
(var wireframe true)
|
||||
(var time 0)
|
||||
(var zoom 5.0)
|
||||
(var texture-id nil)
|
||||
(var use-texture false)
|
||||
(var affine false)
|
||||
(var texture-initialized false)
|
||||
(var cam-x 0)
|
||||
(var cam-y 2)
|
||||
(var cam-z 12)
|
||||
(var cam-yaw 0)
|
||||
(var cam-pitch -0.2)
|
||||
(var show-debug-ui false)
|
||||
(var fps 0)
|
||||
(var fps-timer 0)
|
||||
(var fps-accumulator 0)
|
||||
(var fps-frame-count 0)
|
||||
|
||||
(fn init-texture []
|
||||
(when (not texture-initialized)
|
||||
(pxl8.load_palette "sprites/pxl8_logo.ase")
|
||||
(set texture-id (pxl8.load_sprite "sprites/pxl8_logo.ase"))
|
||||
(pxl8.upload_atlas)
|
||||
(set texture-initialized true)))
|
||||
|
||||
(fn make-cube-vertices []
|
||||
[[-1 -1 -1] [1 -1 -1] [1 1 -1] [-1 1 -1]
|
||||
[-1 -1 1] [1 -1 1] [1 1 1] [-1 1 1]])
|
||||
|
||||
(fn make-cube-faces []
|
||||
[[0 1 2] [0 2 3]
|
||||
[1 5 6] [1 6 2]
|
||||
[5 4 7] [5 7 6]
|
||||
[4 0 3] [4 3 7]
|
||||
[3 2 6] [3 6 7]
|
||||
[4 5 1] [4 1 0]])
|
||||
|
||||
(fn make-cube-faces-with-uvs []
|
||||
[{:tri [0 1 2] :uvs [[0 0] [1 0] [1 1]]}
|
||||
{:tri [0 2 3] :uvs [[0 0] [1 1] [0 1]]}
|
||||
{:tri [1 5 6] :uvs [[0 0] [1 0] [1 1]]}
|
||||
{:tri [1 6 2] :uvs [[0 0] [1 1] [0 1]]}
|
||||
{:tri [5 4 7] :uvs [[0 0] [1 0] [1 1]]}
|
||||
{:tri [5 7 6] :uvs [[0 0] [1 1] [0 1]]}
|
||||
{:tri [4 0 3] :uvs [[0 0] [1 0] [1 1]]}
|
||||
{:tri [4 3 7] :uvs [[0 0] [1 1] [0 1]]}
|
||||
{:tri [3 2 6] :uvs [[0 0] [1 0] [1 1]]}
|
||||
{:tri [3 6 7] :uvs [[0 0] [1 1] [0 1]]}
|
||||
{:tri [4 5 1] :uvs [[0 0] [1 0] [1 1]]}
|
||||
{:tri [4 1 0] :uvs [[0 0] [1 1] [0 1]]}])
|
||||
|
||||
(fn get-face-color [face-idx]
|
||||
(let [colors [12 22 30 16 28 20]]
|
||||
(. colors (+ 1 (% face-idx 6)))))
|
||||
|
||||
(fn update [dt]
|
||||
(set time (+ time dt))
|
||||
(set fps-accumulator (+ fps-accumulator dt))
|
||||
(set fps-frame-count (+ fps-frame-count 1))
|
||||
|
||||
(when (>= fps-accumulator 0.25)
|
||||
(set fps (/ fps-frame-count fps-accumulator))
|
||||
(set fps-accumulator 0)
|
||||
(set fps-frame-count 0))
|
||||
|
||||
(let [wheel-y (pxl8.mouse_wheel_y)
|
||||
zoom-speed 0.5]
|
||||
(when (not= wheel-y 0)
|
||||
(let [forward-x (* (math.sin cam-yaw) wheel-y zoom-speed)
|
||||
forward-z (* (math.cos cam-yaw) wheel-y zoom-speed)]
|
||||
(set cam-x (+ cam-x forward-x))
|
||||
(set cam-z (- cam-z forward-z)))))
|
||||
|
||||
(let [move-speed 5.0
|
||||
rot-speed 2.0
|
||||
forward-x (* (math.sin cam-yaw) move-speed dt)
|
||||
forward-z (* (math.cos cam-yaw) move-speed dt)
|
||||
right-x (* (math.cos cam-yaw) move-speed dt)
|
||||
right-z (* (- (math.sin cam-yaw)) move-speed dt)]
|
||||
|
||||
(when (pxl8.key_down "w")
|
||||
(set cam-x (+ cam-x forward-x))
|
||||
(set cam-z (- cam-z forward-z)))
|
||||
(when (pxl8.key_down "s")
|
||||
(set cam-x (- cam-x forward-x))
|
||||
(set cam-z (+ cam-z forward-z)))
|
||||
(when (pxl8.key_down "a")
|
||||
(set cam-x (- cam-x right-x))
|
||||
(set cam-z (- cam-z right-z)))
|
||||
(when (pxl8.key_down "d")
|
||||
(set cam-x (+ cam-x right-x))
|
||||
(set cam-z (+ cam-z right-z)))
|
||||
(when (pxl8.key_down "q")
|
||||
(set cam-y (- cam-y (* move-speed dt))))
|
||||
(when (pxl8.key_down "e")
|
||||
(set cam-y (+ cam-y (* move-speed dt))))
|
||||
|
||||
(when (pxl8.key_down "left")
|
||||
(set cam-yaw (- cam-yaw (* rot-speed dt))))
|
||||
(when (pxl8.key_down "right")
|
||||
(set cam-yaw (+ cam-yaw (* rot-speed dt))))
|
||||
(when (pxl8.key_down "up")
|
||||
(set cam-pitch (+ cam-pitch (* rot-speed dt))))
|
||||
(when (pxl8.key_down "down")
|
||||
(set cam-pitch (- cam-pitch (* rot-speed dt))))
|
||||
|
||||
(set cam-pitch (math.max -1.5 (math.min cam-pitch 1.5))))
|
||||
|
||||
(when (pxl8.key_pressed " ")
|
||||
(set wireframe (not wireframe)))
|
||||
(when (pxl8.key_pressed "f")
|
||||
(set affine (not affine)))
|
||||
(when (pxl8.key_pressed "p")
|
||||
(set orthographic (not orthographic)))
|
||||
(when (pxl8.key_pressed "r")
|
||||
(set auto-rotate (not auto-rotate)))
|
||||
(when (pxl8.key_pressed "t")
|
||||
(set use-texture (not use-texture))
|
||||
(when use-texture
|
||||
(init-texture)))
|
||||
(when (pxl8.key_pressed "F8")
|
||||
(set show-debug-ui (not show-debug-ui))
|
||||
(pxl8.ui_window_set_open "Debug Menu (F8)" show-debug-ui))
|
||||
|
||||
(when auto-rotate
|
||||
(set angle-x (+ angle-x (* dt 0.7)))
|
||||
(set angle-y (+ angle-y (* dt 0.5)))
|
||||
(set angle-z (+ angle-z (* dt 0.3)))))
|
||||
|
||||
(fn frame []
|
||||
(pxl8.clr 0)
|
||||
|
||||
(pxl8.clear_zbuffer)
|
||||
(pxl8.set_affine_textures affine)
|
||||
(pxl8.set_backface_culling true)
|
||||
(pxl8.set_wireframe wireframe)
|
||||
|
||||
(if orthographic
|
||||
(let [size 2.5
|
||||
aspect (/ (pxl8.get_width) (pxl8.get_height))
|
||||
w (* size aspect)
|
||||
h size]
|
||||
(pxl8.set_projection (pxl8.mat4_ortho (- w) w (- h) h 1.0 100.0)))
|
||||
(let [aspect (/ (pxl8.get_width) (pxl8.get_height))
|
||||
fov (* (/ 60.0 180.0) 3.14159)]
|
||||
(pxl8.set_projection (pxl8.mat4_perspective fov aspect 0.1 100.0))))
|
||||
|
||||
(let [target-x (* (math.sin cam-yaw) (math.cos cam-pitch))
|
||||
target-y (* (math.sin cam-pitch))
|
||||
target-z (* (- (math.cos cam-yaw)) (math.cos cam-pitch))
|
||||
look-x (+ cam-x target-x)
|
||||
look-y (+ cam-y target-y)
|
||||
look-z (+ cam-z target-z)]
|
||||
(pxl8.set_view (pxl8.mat4_lookat [cam-x cam-y cam-z] [look-x look-y look-z] [0 1 0])))
|
||||
|
||||
(let [model (-> (pxl8.mat4_identity)
|
||||
(pxl8.mat4_multiply (pxl8.mat4_rotate_x angle-x))
|
||||
(pxl8.mat4_multiply (pxl8.mat4_rotate_y angle-y))
|
||||
(pxl8.mat4_multiply (pxl8.mat4_rotate_z angle-z)))]
|
||||
(pxl8.set_model model))
|
||||
|
||||
(let [vertices (make-cube-vertices)]
|
||||
(if (and use-texture texture-id)
|
||||
(let [faces (make-cube-faces-with-uvs)]
|
||||
(each [_i face-data (ipairs faces)]
|
||||
(let [tri-indices face-data.tri
|
||||
tri-uvs face-data.uvs
|
||||
v0 (. vertices (+ 1 (. tri-indices 1)))
|
||||
v1 (. vertices (+ 1 (. tri-indices 2)))
|
||||
v2 (. vertices (+ 1 (. tri-indices 3)))
|
||||
uv0 (. tri-uvs 1)
|
||||
uv1 (. tri-uvs 2)
|
||||
uv2 (. tri-uvs 3)]
|
||||
(pxl8.draw_triangle_3d_textured
|
||||
v0 v1 v2
|
||||
uv0 uv1 uv2
|
||||
texture-id))))
|
||||
(let [faces (make-cube-faces)]
|
||||
(each [i face (ipairs faces)]
|
||||
(let [[i0 i1 i2] face
|
||||
v0 (. vertices (+ 1 i0))
|
||||
v1 (. vertices (+ 1 i1))
|
||||
v2 (. vertices (+ 1 i2))
|
||||
color (get-face-color (math.floor (/ (- i 1) 2)))]
|
||||
(pxl8.draw_triangle_3d v0 v1 v2 color))))))
|
||||
|
||||
(let [new-state (debug-ui.render {:show-debug-ui show-debug-ui
|
||||
:fps fps
|
||||
:wireframe wireframe
|
||||
:auto-rotate auto-rotate
|
||||
:orthographic orthographic
|
||||
:use-texture use-texture
|
||||
:affine affine
|
||||
:init-texture init-texture})]
|
||||
(when (not= new-state.show-debug-ui nil) (set show-debug-ui new-state.show-debug-ui))
|
||||
(when (not= new-state.wireframe nil) (set wireframe new-state.wireframe))
|
||||
(when (not= new-state.auto-rotate nil) (set auto-rotate new-state.auto-rotate))
|
||||
(when (not= new-state.orthographic nil) (set orthographic new-state.orthographic))
|
||||
(when (not= new-state.use-texture nil)
|
||||
(set use-texture new-state.use-texture)
|
||||
(when use-texture (init-texture)))
|
||||
(when (not= new-state.affine nil) (set affine new-state.affine))))
|
||||
|
||||
{: update
|
||||
: frame}
|
||||
32
demo/mod/debug_ui.fnl
Normal file
32
demo/mod/debug_ui.fnl
Normal file
|
|
@ -0,0 +1,32 @@
|
|||
(local pxl8 (require :pxl8))
|
||||
|
||||
(fn render [state]
|
||||
(var new-state {})
|
||||
(when state.show-debug-ui
|
||||
(let [window-h (if state.use-texture 210 180)
|
||||
window-open (pxl8.ui_window_begin "Debug Menu (F8)" 10 10 250 window-h)]
|
||||
(when window-open
|
||||
(pxl8.ui_layout_row 1 0 0)
|
||||
(pxl8.ui_label (string.format "FPS: %.0f" (or state.fps 0)))
|
||||
(let [(changed new-val) (pxl8.ui_checkbox "Wireframe" state.wireframe)]
|
||||
(when changed (set new-state.wireframe new-val)))
|
||||
(let [(changed new-val) (pxl8.ui_checkbox "Auto-rotate" state.auto-rotate)]
|
||||
(when changed (set new-state.auto-rotate new-val)))
|
||||
(let [(changed new-val) (pxl8.ui_checkbox "Orthographic" state.orthographic)]
|
||||
(when changed (set new-state.orthographic new-val)))
|
||||
(let [(changed new-val) (pxl8.ui_checkbox "Texture" state.use-texture)]
|
||||
(when changed
|
||||
(set new-state.use-texture new-val)
|
||||
(when (and new-val state.init-texture)
|
||||
(state.init-texture))))
|
||||
(when state.use-texture
|
||||
(pxl8.ui_indent 20)
|
||||
(let [(changed new-val) (pxl8.ui_checkbox "Affine mapping" state.affine)]
|
||||
(when changed (set new-state.affine new-val)))
|
||||
(pxl8.ui_indent -20))
|
||||
(pxl8.ui_window_end))
|
||||
(when (not window-open)
|
||||
(set new-state.show-debug-ui false))))
|
||||
new-state)
|
||||
|
||||
{: render}
|
||||
|
|
@ -1,20 +0,0 @@
|
|||
(local pxl8 (require :pxl8))
|
||||
|
||||
(var button-clicks 0)
|
||||
|
||||
(global init (fn []
|
||||
(pxl8.load_palette "palettes/gruvbox.ase")))
|
||||
|
||||
(global update (fn [_dt]))
|
||||
|
||||
(global frame (fn []
|
||||
(pxl8.clr 1)
|
||||
|
||||
(when pxl8.ui
|
||||
(when (pxl8.ui_window_begin "UI Demo" 20 20 280 150)
|
||||
(pxl8.ui_layout_row 1 0 0)
|
||||
(pxl8.ui_label "Welcome to some window UI!")
|
||||
(pxl8.ui_label (.. "Clicks: " button-clicks))
|
||||
(when (pxl8.ui_button "Click me!")
|
||||
(set button-clicks (+ button-clicks 1)))
|
||||
(pxl8.ui_window_end)))))
|
||||
|
|
@ -107,19 +107,33 @@ function pxl8.trace(msg)
|
|||
end
|
||||
|
||||
function pxl8.key_down(key)
|
||||
if type(key) == "string" then
|
||||
key = string.byte(key)
|
||||
end
|
||||
return C.pxl8_key_down(input, key)
|
||||
end
|
||||
|
||||
function pxl8.key_pressed(key)
|
||||
if type(key) == "string" then
|
||||
key = string.byte(key)
|
||||
end
|
||||
return C.pxl8_key_pressed(input, key)
|
||||
end
|
||||
|
||||
function pxl8.key_released(key)
|
||||
return C.pxl8_key_released(input, key)
|
||||
end
|
||||
|
||||
function pxl8.mouse_wheel_x()
|
||||
return C.pxl8_mouse_wheel_x(input)
|
||||
end
|
||||
|
||||
function pxl8.mouse_wheel_y()
|
||||
return C.pxl8_mouse_wheel_y(input)
|
||||
end
|
||||
|
||||
function pxl8.mouse_x()
|
||||
return C.pxl8_mouse_x(input)
|
||||
end
|
||||
|
||||
function pxl8.mouse_y()
|
||||
return C.pxl8_mouse_y(input)
|
||||
end
|
||||
|
||||
function pxl8.vfx_raster_bars(bars, time)
|
||||
local c_bars = ffi.new("pxl8_raster_bar[?]", #bars)
|
||||
for i, bar in ipairs(bars) do
|
||||
|
|
@ -363,19 +377,20 @@ function pxl8.bounds(x, y, w, h)
|
|||
return ffi.new("pxl8_bounds", {x = x, y = y, w = w, h = h})
|
||||
end
|
||||
|
||||
function pxl8.ui_window_begin(title, x, y, w, h, options)
|
||||
local rect = ffi.new("pxl8_bounds", {x = x, y = y, w = w, h = h})
|
||||
return C.pxl8_ui_window_begin(_pxl8_ui, title, rect, options or 0)
|
||||
end
|
||||
|
||||
function pxl8.ui_window_end()
|
||||
C.pxl8_ui_window_end(_pxl8_ui)
|
||||
end
|
||||
|
||||
function pxl8.ui_button(label)
|
||||
return C.pxl8_ui_button(_pxl8_ui, label)
|
||||
end
|
||||
|
||||
function pxl8.ui_checkbox(label, state)
|
||||
local state_ptr = ffi.new("bool[1]", state)
|
||||
local changed = C.pxl8_ui_checkbox(_pxl8_ui, label, state_ptr)
|
||||
return changed, state_ptr[0]
|
||||
end
|
||||
|
||||
function pxl8.ui_indent(amount)
|
||||
C.pxl8_ui_indent(_pxl8_ui, amount)
|
||||
end
|
||||
|
||||
function pxl8.ui_label(text)
|
||||
C.pxl8_ui_label(_pxl8_ui, text)
|
||||
end
|
||||
|
|
@ -390,4 +405,17 @@ function pxl8.ui_layout_row(item_count, widths, height)
|
|||
C.pxl8_ui_layout_row(_pxl8_ui, item_count, widths_array, height)
|
||||
end
|
||||
|
||||
function pxl8.ui_window_begin(title, x, y, w, h, options)
|
||||
local rect = ffi.new("pxl8_bounds", {x = x, y = y, w = w, h = h})
|
||||
return C.pxl8_ui_window_begin(_pxl8_ui, title, rect, options or 0)
|
||||
end
|
||||
|
||||
function pxl8.ui_window_end()
|
||||
C.pxl8_ui_window_end(_pxl8_ui)
|
||||
end
|
||||
|
||||
function pxl8.ui_window_set_open(title, open)
|
||||
C.pxl8_ui_window_set_open(_pxl8_ui, title, open)
|
||||
end
|
||||
|
||||
return pxl8
|
||||
|
|
|
|||
61
src/pxl8.c
61
src/pxl8.c
|
|
@ -44,8 +44,6 @@ typedef struct pxl8_state {
|
|||
pxl8_script* script;
|
||||
pxl8_ui* ui;
|
||||
|
||||
f32 current_fps;
|
||||
f32 fps_timer;
|
||||
i32 frame_count;
|
||||
u64 last_time;
|
||||
f32 time;
|
||||
|
|
@ -53,7 +51,6 @@ typedef struct pxl8_state {
|
|||
bool repl_mode;
|
||||
bool running;
|
||||
bool script_loaded;
|
||||
bool show_fps;
|
||||
char script_path[256];
|
||||
|
||||
pxl8_input_state input;
|
||||
|
|
@ -319,17 +316,9 @@ SDL_AppResult SDL_AppIterate(void* appstate) {
|
|||
u64 current_time = SDL_GetTicksNS();
|
||||
f32 dt = (f32)(current_time - app->last_time) / 1000000000.0f;
|
||||
|
||||
app->frame_count++;
|
||||
app->fps_timer += dt;
|
||||
app->last_time = current_time;
|
||||
app->time += dt;
|
||||
|
||||
if (app->fps_timer >= 1.0f) {
|
||||
app->current_fps = app->frame_count / app->fps_timer;
|
||||
app->frame_count = 0;
|
||||
app->fps_timer = 0.0f;
|
||||
}
|
||||
|
||||
pxl8_script_check_reload(app->script);
|
||||
|
||||
if (app->repl_mode) {
|
||||
|
|
@ -344,23 +333,24 @@ SDL_AppResult SDL_AppIterate(void* appstate) {
|
|||
}
|
||||
|
||||
if (app->ui) {
|
||||
pxl8_ui_input_mousemove(app->ui, app->input.mouse_x, app->input.mouse_y);
|
||||
|
||||
pxl8_ui_frame_begin(app->ui);
|
||||
|
||||
for (i32 i = 0; i < 3; i++) {
|
||||
if (app->input.mouse_buttons[i] && app->input.mouse_buttons_pressed[i]) {
|
||||
if (app->input.mouse_buttons_pressed[i]) {
|
||||
pxl8_ui_input_mousedown(app->ui, app->input.mouse_x, app->input.mouse_y, i + 1);
|
||||
}
|
||||
if (!app->input.mouse_buttons[i]) {
|
||||
if (app->input.mouse_buttons_released[i]) {
|
||||
pxl8_ui_input_mouseup(app->ui, app->input.mouse_x, app->input.mouse_y, i + 1);
|
||||
}
|
||||
}
|
||||
pxl8_ui_input_mousemove(app->ui, app->input.mouse_x, app->input.mouse_y);
|
||||
|
||||
for (i32 key = 0; key < 256; key++) {
|
||||
if (app->input.keys_pressed[key]) {
|
||||
pxl8_ui_input_keydown(app->ui, key);
|
||||
}
|
||||
if (!app->input.keys[key] && app->input.keys_pressed[key]) {
|
||||
if (!app->input.keys_down[key] && app->input.keys_pressed[key]) {
|
||||
pxl8_ui_input_keyup(app->ui, key);
|
||||
}
|
||||
}
|
||||
|
|
@ -390,12 +380,6 @@ SDL_AppResult SDL_AppIterate(void* appstate) {
|
|||
i32 render_width, render_height;
|
||||
pxl8_gfx_get_resolution_dimensions(app->resolution, &render_width, &render_height);
|
||||
|
||||
if (app->show_fps && app->current_fps > 0.0f) {
|
||||
char fps_text[32];
|
||||
SDL_snprintf(fps_text, sizeof(fps_text), "FPS: %d", (i32)(app->current_fps + 0.5f));
|
||||
pxl8_text(app->gfx, fps_text, render_width - 80, 10, 15);
|
||||
}
|
||||
|
||||
if (app->ui) {
|
||||
pxl8_ui_frame_end(app->ui);
|
||||
}
|
||||
|
|
@ -406,7 +390,9 @@ SDL_AppResult SDL_AppIterate(void* appstate) {
|
|||
pxl8_gfx_present(app->gfx);
|
||||
|
||||
SDL_memset(app->input.keys_pressed, 0, sizeof(app->input.keys_pressed));
|
||||
SDL_memset(app->input.keys_released, 0, sizeof(app->input.keys_released));
|
||||
SDL_memset(app->input.mouse_buttons_pressed, 0, sizeof(app->input.mouse_buttons_pressed));
|
||||
SDL_memset(app->input.mouse_buttons_released, 0, sizeof(app->input.mouse_buttons_released));
|
||||
app->input.mouse_wheel_x = 0;
|
||||
app->input.mouse_wheel_y = 0;
|
||||
|
||||
|
|
@ -427,25 +413,23 @@ SDL_AppResult SDL_AppEvent(void* appstate, SDL_Event* event) {
|
|||
return SDL_APP_SUCCESS;
|
||||
}
|
||||
|
||||
if (event->key.key == SDLK_F3) {
|
||||
app->show_fps = !app->show_fps;
|
||||
SDL_Scancode scancode = event->key.scancode;
|
||||
if (scancode < 256) {
|
||||
if (!app->input.keys_down[scancode]) {
|
||||
app->input.keys_pressed[scancode] = true;
|
||||
}
|
||||
|
||||
SDL_Keycode key = event->key.key;
|
||||
if (key < 256) {
|
||||
if (!app->input.keys[key]) {
|
||||
app->input.keys_pressed[key] = true;
|
||||
}
|
||||
app->input.keys[key] = true;
|
||||
app->input.keys_down[scancode] = true;
|
||||
app->input.keys_released[scancode] = false;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case SDL_EVENT_KEY_UP: {
|
||||
SDL_Keycode key = event->key.key;
|
||||
if (key < 256) {
|
||||
app->input.keys[key] = false;
|
||||
app->input.keys_pressed[key] = false;
|
||||
SDL_Scancode scancode = event->key.scancode;
|
||||
if (scancode < 256) {
|
||||
app->input.keys_down[scancode] = false;
|
||||
app->input.keys_pressed[scancode] = false;
|
||||
app->input.keys_released[scancode] = true;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
|
@ -453,10 +437,11 @@ SDL_AppResult SDL_AppEvent(void* appstate, SDL_Event* event) {
|
|||
case SDL_EVENT_MOUSE_BUTTON_DOWN: {
|
||||
u8 button = event->button.button - 1;
|
||||
if (button < 3) {
|
||||
if (!app->input.mouse_buttons[button]) {
|
||||
if (!app->input.mouse_buttons_down[button]) {
|
||||
app->input.mouse_buttons_pressed[button] = true;
|
||||
}
|
||||
app->input.mouse_buttons[button] = true;
|
||||
app->input.mouse_buttons_down[button] = true;
|
||||
app->input.mouse_buttons_released[button] = false;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
|
@ -464,7 +449,9 @@ SDL_AppResult SDL_AppEvent(void* appstate, SDL_Event* event) {
|
|||
case SDL_EVENT_MOUSE_BUTTON_UP: {
|
||||
u8 button = event->button.button - 1;
|
||||
if (button < 3) {
|
||||
app->input.mouse_buttons[button] = false;
|
||||
app->input.mouse_buttons_down[button] = false;
|
||||
app->input.mouse_buttons_pressed[button] = false;
|
||||
app->input.mouse_buttons_released[button] = true;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,3 +1,4 @@
|
|||
#include <ctype.h>
|
||||
#include <SDL3/SDL.h>
|
||||
|
||||
#include "pxl8_io.h"
|
||||
|
|
@ -97,12 +98,50 @@ void pxl8_io_free_binary_data(u8* data) {
|
|||
}
|
||||
}
|
||||
|
||||
bool pxl8_key_down(const pxl8_input_state* input, i32 key) {
|
||||
if (!input || key < 0 || key >= 256) return false;
|
||||
return input->keys[key];
|
||||
static i32 pxl8_key_code(const char* key_name) {
|
||||
if (!key_name || !key_name[0]) return 0;
|
||||
|
||||
SDL_Scancode scancode = SDL_GetScancodeFromName(key_name);
|
||||
return (i32)scancode;
|
||||
}
|
||||
|
||||
bool pxl8_key_pressed(const pxl8_input_state* input, i32 key) {
|
||||
if (!input || key < 0 || key >= 256) return false;
|
||||
bool pxl8_key_down(const pxl8_input_state* input, const char* key_name) {
|
||||
if (!input) return false;
|
||||
i32 key = pxl8_key_code(key_name);
|
||||
if (key < 0 || key >= 256) return false;
|
||||
return input->keys_down[key];
|
||||
}
|
||||
|
||||
bool pxl8_key_pressed(const pxl8_input_state* input, const char* key_name) {
|
||||
if (!input) return false;
|
||||
i32 key = pxl8_key_code(key_name);
|
||||
if (key < 0 || key >= 256) return false;
|
||||
return input->keys_pressed[key];
|
||||
}
|
||||
|
||||
bool pxl8_key_released(const pxl8_input_state* input, const char* key_name) {
|
||||
if (!input) return false;
|
||||
i32 key = pxl8_key_code(key_name);
|
||||
if (key < 0 || key >= 256) return false;
|
||||
return input->keys_released[key];
|
||||
}
|
||||
|
||||
i32 pxl8_mouse_wheel_x(const pxl8_input_state* input) {
|
||||
if (!input) return 0;
|
||||
return input->mouse_wheel_x;
|
||||
}
|
||||
|
||||
i32 pxl8_mouse_wheel_y(const pxl8_input_state* input) {
|
||||
if (!input) return 0;
|
||||
return input->mouse_wheel_y;
|
||||
}
|
||||
|
||||
i32 pxl8_mouse_x(const pxl8_input_state* input) {
|
||||
if (!input) return 0;
|
||||
return input->mouse_x;
|
||||
}
|
||||
|
||||
i32 pxl8_mouse_y(const pxl8_input_state* input) {
|
||||
if (!input) return 0;
|
||||
return input->mouse_y;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -19,8 +19,14 @@ pxl8_result pxl8_io_read_file(const char* path, char** content, size_t* size);
|
|||
pxl8_result pxl8_io_write_binary_file(const char* path, const u8* data, size_t size);
|
||||
pxl8_result pxl8_io_write_file(const char* path, const char* content, size_t size);
|
||||
|
||||
bool pxl8_key_down(const pxl8_input_state* input, i32 key);
|
||||
bool pxl8_key_pressed(const pxl8_input_state* input, i32 key);
|
||||
bool pxl8_key_down(const pxl8_input_state* input, const char* key_name);
|
||||
bool pxl8_key_pressed(const pxl8_input_state* input, const char* key_name);
|
||||
bool pxl8_key_released(const pxl8_input_state* input, const char* key_name);
|
||||
|
||||
i32 pxl8_mouse_wheel_x(const pxl8_input_state* input);
|
||||
i32 pxl8_mouse_wheel_y(const pxl8_input_state* input);
|
||||
i32 pxl8_mouse_x(const pxl8_input_state* input);
|
||||
i32 pxl8_mouse_y(const pxl8_input_state* input);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
|
|
|
|||
|
|
@ -59,8 +59,13 @@ static const char* pxl8_ffi_cdefs =
|
|||
"i32 pxl8_gfx_create_texture(pxl8_gfx* ctx, const u8* pixels, u32 width, u32 height);\n"
|
||||
"void pxl8_gfx_upload_atlas(pxl8_gfx* ctx);\n"
|
||||
"typedef struct pxl8_input_state pxl8_input_state;\n"
|
||||
"bool pxl8_key_down(const pxl8_input_state* input, i32 key);\n"
|
||||
"bool pxl8_key_pressed(const pxl8_input_state* input, i32 key);\n"
|
||||
"bool pxl8_key_down(const pxl8_input_state* input, const char* key_name);\n"
|
||||
"bool pxl8_key_pressed(const pxl8_input_state* input, const char* key_name);\n"
|
||||
"bool pxl8_key_released(const pxl8_input_state* input, const char* key_name);\n"
|
||||
"int pxl8_mouse_wheel_x(const pxl8_input_state* input);\n"
|
||||
"int pxl8_mouse_wheel_y(const pxl8_input_state* input);\n"
|
||||
"int pxl8_mouse_x(const pxl8_input_state* input);\n"
|
||||
"int pxl8_mouse_y(const pxl8_input_state* input);\n"
|
||||
"void pxl8_lua_debug(const char* msg);\n"
|
||||
"void pxl8_lua_error(const char* msg);\n"
|
||||
"void pxl8_lua_info(const char* msg);\n"
|
||||
|
|
@ -168,12 +173,15 @@ static const char* pxl8_ffi_cdefs =
|
|||
"void pxl8_ui_input_scroll(pxl8_ui* ui, int x, int y);\n"
|
||||
"void pxl8_ui_input_text(pxl8_ui* ui, const char* text);\n"
|
||||
"bool pxl8_ui_button(pxl8_ui* ui, const char* label);\n"
|
||||
"bool pxl8_ui_checkbox(pxl8_ui* ui, const char* label, bool* state);\n"
|
||||
"void pxl8_ui_indent(pxl8_ui* ui, int amount);\n"
|
||||
"void pxl8_ui_label(pxl8_ui* ui, const char* text);\n"
|
||||
"void pxl8_ui_layout_row(pxl8_ui* ui, int item_count, const int* widths, int height);\n"
|
||||
"int pxl8_ui_menu(pxl8_ui* ui, pxl8_menu_item* items, int item_count);\n"
|
||||
"void pxl8_ui_panel(pxl8_ui* ui, pxl8_bounds rect, pxl8_frame_theme* theme);\n"
|
||||
"bool pxl8_ui_window_begin(pxl8_ui* ui, const char* title, pxl8_bounds rect, int options);\n"
|
||||
"void pxl8_ui_window_end(pxl8_ui* ui);\n"
|
||||
"void pxl8_ui_window_set_open(pxl8_ui* ui, const char* title, bool open);\n"
|
||||
"pxl8_frame_theme pxl8_ui_theme_default(void);\n";
|
||||
|
||||
void pxl8_lua_info(const char* msg) {
|
||||
|
|
@ -246,6 +254,18 @@ pxl8_script* pxl8_script_create(void) {
|
|||
|
||||
if (luaL_dofile(script->L, "lib/fennel/fennel.lua") == 0) {
|
||||
lua_setglobal(script->L, "fennel");
|
||||
|
||||
lua_getglobal(script->L, "fennel");
|
||||
lua_getfield(script->L, -1, "install");
|
||||
if (lua_isfunction(script->L, -1)) {
|
||||
if (lua_pcall(script->L, 0, 0, 0) != 0) {
|
||||
pxl8_warn("Failed to install fennel searcher: %s", lua_tostring(script->L, -1));
|
||||
lua_pop(script->L, 1);
|
||||
}
|
||||
} else {
|
||||
lua_pop(script->L, 1);
|
||||
}
|
||||
lua_pop(script->L, 1);
|
||||
}
|
||||
|
||||
script->last_error[0] = '\0';
|
||||
|
|
|
|||
|
|
@ -64,11 +64,13 @@ typedef struct pxl8_bounds {
|
|||
} pxl8_bounds;
|
||||
|
||||
typedef struct pxl8_input_state {
|
||||
bool keys[256];
|
||||
bool keys_down[256];
|
||||
bool keys_pressed[256];
|
||||
bool keys_released[256];
|
||||
|
||||
bool mouse_buttons[3];
|
||||
bool mouse_buttons_down[3];
|
||||
bool mouse_buttons_pressed[3];
|
||||
bool mouse_buttons_released[3];
|
||||
i32 mouse_wheel_x;
|
||||
i32 mouse_wheel_y;
|
||||
i32 mouse_x;
|
||||
|
|
|
|||
|
|
@ -38,26 +38,47 @@ static int mu_text_height(mu_Font font) {
|
|||
return f->default_height;
|
||||
}
|
||||
|
||||
static void pxl8_ui_render_icon(pxl8_gfx* gfx, i32 id, i32 x, i32 y, i32 w, i32 h, u8 color) {
|
||||
switch (id) {
|
||||
case 2: {
|
||||
i32 cx = x + w / 2;
|
||||
i32 cy = y + h / 2;
|
||||
i32 size = (w < h ? w : h) / 3;
|
||||
pxl8_line(gfx, cx - size, cy, cx, cy + size, color);
|
||||
pxl8_line(gfx, cx, cy + size, cx + size, cy - size, color);
|
||||
break;
|
||||
}
|
||||
case 1: {
|
||||
i32 cx = x + w / 2;
|
||||
i32 cy = y + h / 2;
|
||||
i32 size = (w < h ? w : h) / 4;
|
||||
pxl8_line(gfx, cx - size, cy - size, cx + size, cy + size, color);
|
||||
pxl8_line(gfx, cx + size, cy - size, cx - size, cy + size, color);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void pxl8_ui_render_commands(pxl8_ui* ui) {
|
||||
mu_Command* cmd = NULL;
|
||||
while (mu_next_command(&ui->mu_ctx, &cmd)) {
|
||||
switch (cmd->type) {
|
||||
case MU_COMMAND_RECT: {
|
||||
mu_RectCommand* rc = (mu_RectCommand*)cmd;
|
||||
u8 color = rc->color.r;
|
||||
pxl8_rect_fill(ui->gfx, rc->rect.x, rc->rect.y, rc->rect.w, rc->rect.h, color);
|
||||
pxl8_rect_fill(ui->gfx, rc->rect.x, rc->rect.y, rc->rect.w, rc->rect.h, rc->color.r);
|
||||
break;
|
||||
}
|
||||
case MU_COMMAND_TEXT: {
|
||||
mu_TextCommand* tc = (mu_TextCommand*)cmd;
|
||||
u8 color = tc->color.r;
|
||||
pxl8_text(ui->gfx, tc->str, tc->pos.x, tc->pos.y, color);
|
||||
pxl8_text(ui->gfx, tc->str, tc->pos.x, tc->pos.y, tc->color.r);
|
||||
break;
|
||||
}
|
||||
case MU_COMMAND_CLIP: {
|
||||
break;
|
||||
}
|
||||
case MU_COMMAND_ICON: {
|
||||
mu_IconCommand* ic = (mu_IconCommand*)cmd;
|
||||
pxl8_ui_render_icon(ui->gfx, ic->id, ic->rect.x, ic->rect.y, ic->rect.w, ic->rect.h, ic->color.r);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
|
@ -104,6 +125,21 @@ pxl8_ui* pxl8_ui_create(pxl8_gfx* gfx) {
|
|||
ui->mu_ctx.text_height = mu_text_height;
|
||||
ui->mu_ctx.text_width = mu_text_width;
|
||||
|
||||
ui->mu_ctx.style->colors[0] = (mu_Color){15, 0, 0, 255};
|
||||
ui->mu_ctx.style->colors[1] = (mu_Color){8, 0, 0, 255};
|
||||
ui->mu_ctx.style->colors[2] = (mu_Color){1, 0, 0, 255};
|
||||
ui->mu_ctx.style->colors[3] = (mu_Color){2, 0, 0, 255};
|
||||
ui->mu_ctx.style->colors[4] = (mu_Color){15, 0, 0, 255};
|
||||
ui->mu_ctx.style->colors[5] = (mu_Color){0, 0, 0, 0};
|
||||
ui->mu_ctx.style->colors[6] = (mu_Color){7, 0, 0, 255};
|
||||
ui->mu_ctx.style->colors[7] = (mu_Color){8, 0, 0, 255};
|
||||
ui->mu_ctx.style->colors[8] = (mu_Color){10, 0, 0, 255};
|
||||
ui->mu_ctx.style->colors[9] = (mu_Color){2, 0, 0, 255};
|
||||
ui->mu_ctx.style->colors[10] = (mu_Color){3, 0, 0, 255};
|
||||
ui->mu_ctx.style->colors[11] = (mu_Color){10, 0, 0, 255};
|
||||
ui->mu_ctx.style->colors[12] = (mu_Color){7, 0, 0, 255};
|
||||
ui->mu_ctx.style->colors[13] = (mu_Color){8, 0, 0, 255};
|
||||
|
||||
return ui;
|
||||
}
|
||||
|
||||
|
|
@ -163,6 +199,48 @@ bool pxl8_ui_button(pxl8_ui* ui, const char* label) {
|
|||
return mu_button(&ui->mu_ctx, label) & MU_RES_SUBMIT;
|
||||
}
|
||||
|
||||
bool pxl8_ui_checkbox(pxl8_ui* ui, const char* label, bool* state) {
|
||||
if (!ui || !state || !label) return false;
|
||||
|
||||
mu_Context* ctx = &ui->mu_ctx;
|
||||
mu_push_id(ctx, label, (int)strlen(label));
|
||||
|
||||
mu_Id id = mu_get_id(ctx, label, (int)strlen(label));
|
||||
mu_Rect r = mu_layout_next(ctx);
|
||||
mu_Rect box = mu_rect(r.x, r.y, r.h, r.h);
|
||||
|
||||
int had_focus_before = (ctx->focus == id);
|
||||
mu_update_control(ctx, id, r, 0);
|
||||
int has_focus_after = (ctx->focus == id);
|
||||
int mouseover = mu_mouse_over(ctx, r);
|
||||
|
||||
int res = 0;
|
||||
int int_state = *state ? 1 : 0;
|
||||
|
||||
if (had_focus_before && !has_focus_after && !ctx->mouse_down && mouseover) {
|
||||
res |= MU_RES_CHANGE;
|
||||
int_state = !int_state;
|
||||
}
|
||||
|
||||
mu_draw_control_frame(ctx, id, box, MU_COLOR_BASE, 0);
|
||||
if (int_state) {
|
||||
mu_draw_icon(ctx, MU_ICON_CHECK, box, ctx->style->colors[MU_COLOR_TEXT]);
|
||||
}
|
||||
r = mu_rect(r.x + box.w, r.y, r.w - box.w, r.h);
|
||||
mu_draw_control_text(ctx, label, r, MU_COLOR_TEXT, 0);
|
||||
|
||||
mu_pop_id(ctx);
|
||||
|
||||
*state = int_state != 0;
|
||||
return res & MU_RES_CHANGE;
|
||||
}
|
||||
|
||||
void pxl8_ui_indent(pxl8_ui* ui, i32 amount) {
|
||||
if (!ui) return;
|
||||
mu_Layout* layout = &ui->mu_ctx.layout_stack.items[ui->mu_ctx.layout_stack.idx - 1];
|
||||
layout->indent += amount;
|
||||
}
|
||||
|
||||
void pxl8_ui_label(pxl8_ui* ui, const char* text) {
|
||||
if (!ui || !text) return;
|
||||
mu_label(&ui->mu_ctx, text);
|
||||
|
|
@ -205,6 +283,14 @@ void pxl8_ui_window_end(pxl8_ui* ui) {
|
|||
mu_end_window(&ui->mu_ctx);
|
||||
}
|
||||
|
||||
void pxl8_ui_window_set_open(pxl8_ui* ui, const char* title, bool open) {
|
||||
if (!ui || !title) return;
|
||||
mu_Container* win = mu_get_container(&ui->mu_ctx, title);
|
||||
if (win) {
|
||||
win->open = open ? 1 : 0;
|
||||
}
|
||||
}
|
||||
|
||||
pxl8_frame_theme pxl8_ui_theme_default(void) {
|
||||
pxl8_frame_theme theme = {0};
|
||||
theme.bg_color = 0;
|
||||
|
|
|
|||
|
|
@ -5,6 +5,23 @@
|
|||
|
||||
typedef struct pxl8_ui pxl8_ui;
|
||||
|
||||
typedef struct pxl8_ui_theme {
|
||||
u8 text;
|
||||
u8 border;
|
||||
u8 window_bg;
|
||||
u8 title_bg;
|
||||
u8 title_text;
|
||||
u8 panel_bg;
|
||||
u8 button;
|
||||
u8 button_hover;
|
||||
u8 button_focus;
|
||||
u8 base;
|
||||
u8 base_hover;
|
||||
u8 base_focus;
|
||||
u8 scroll_base;
|
||||
u8 scroll_thumb;
|
||||
} pxl8_ui_theme;
|
||||
|
||||
typedef struct pxl8_frame_theme {
|
||||
u8 bg_color;
|
||||
u32 sprite_id;
|
||||
|
|
@ -44,12 +61,15 @@ void pxl8_ui_input_scroll(pxl8_ui* ui, i32 x, i32 y);
|
|||
void pxl8_ui_input_text(pxl8_ui* ui, const char* text);
|
||||
|
||||
bool pxl8_ui_button(pxl8_ui* ui, const char* label);
|
||||
bool pxl8_ui_checkbox(pxl8_ui* ui, const char* label, bool* state);
|
||||
void pxl8_ui_indent(pxl8_ui* ui, i32 amount);
|
||||
void pxl8_ui_label(pxl8_ui* ui, const char* text);
|
||||
void pxl8_ui_layout_row(pxl8_ui* ui, i32 item_count, const i32* widths, i32 height);
|
||||
i32 pxl8_ui_menu(pxl8_ui* ui, pxl8_menu_item* items, i32 item_count);
|
||||
void pxl8_ui_panel(pxl8_ui* ui, pxl8_bounds rect, pxl8_frame_theme* theme);
|
||||
bool pxl8_ui_window_begin(pxl8_ui* ui, const char* title, pxl8_bounds rect, i32 options);
|
||||
void pxl8_ui_window_end(pxl8_ui* ui);
|
||||
void pxl8_ui_window_set_open(pxl8_ui* ui, const char* title, bool open);
|
||||
|
||||
pxl8_frame_theme pxl8_ui_theme_default(void);
|
||||
|
||||
|
|
|
|||
|
|
@ -30,6 +30,10 @@ typedef struct pxl8_raster_bar {
|
|||
f32 speed;
|
||||
} pxl8_raster_bar;
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
pxl8_particles* pxl8_particles_create(u32 max_count);
|
||||
void pxl8_particles_destroy(pxl8_particles* particles);
|
||||
|
||||
|
|
@ -51,3 +55,7 @@ void pxl8_vfx_raster_bars(pxl8_gfx* gfx, pxl8_raster_bar* bars, u32 bar_count, f
|
|||
void pxl8_vfx_rotozoom(pxl8_gfx* gfx, f32 angle, f32 zoom, i32 cx, i32 cy);
|
||||
void pxl8_vfx_tunnel(pxl8_gfx* gfx, f32 time, f32 speed, f32 twist);
|
||||
void pxl8_vfx_water_ripple(pxl8_gfx* gfx, f32* height_map, i32 drop_x, i32 drop_y, f32 damping);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue