karl2d.odin 19 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877
  1. package karl2d
  2. import "base:runtime"
  3. import "core:mem"
  4. import "core:log"
  5. import "core:math"
  6. import "core:math/linalg"
  7. import "core:slice"
  8. import "core:image"
  9. import "core:image/bmp"
  10. import "core:image/png"
  11. import "core:image/tga"
  12. import hm "handle_map"
  13. _ :: bmp
  14. _ :: png
  15. _ :: tga
  16. Handle :: hm.Handle
  17. Texture_Handle :: distinct Handle
  18. // Opens a window and initializes some internal state. The internal state will use `allocator` for
  19. // all dynamically allocated memory. The return value can be ignored unless you need to later call
  20. // `set_state`.
  21. init :: proc(window_width: int, window_height: int, window_title: string,
  22. allocator := context.allocator, loc := #caller_location) -> ^State {
  23. s = new(State, allocator, loc)
  24. s.allocator = allocator
  25. s.custom_context = context
  26. s.width = window_width
  27. s.height = window_height
  28. s.win = WINDOW_INTERFACE_WIN32
  29. win = s.win
  30. window_state_alloc_error: runtime.Allocator_Error
  31. s.window_state, window_state_alloc_error = mem.alloc(win.state_size())
  32. log.assertf(window_state_alloc_error == nil, "Failed allocating memory for window state: %v", window_state_alloc_error)
  33. win.init(s.window_state, window_width, window_height, window_title, allocator)
  34. s.window = win.window_handle()
  35. s.rb = BACKEND_D3D11
  36. rb = s.rb
  37. rb_alloc_error: runtime.Allocator_Error
  38. s.rb_state, rb_alloc_error = mem.alloc(rb.state_size())
  39. log.assertf(rb_alloc_error == nil, "Failed allocating memory for rendering backend: %v", rb_alloc_error)
  40. s.proj_matrix = make_default_projection(window_width, window_height)
  41. s.view_matrix = 1
  42. rb.init(s.rb_state, s.window, window_width, window_height, allocator)
  43. s.vertex_buffer_cpu = make([]u8, VERTEX_BUFFER_MAX, allocator, loc)
  44. white_rect: [16*16*4]u8
  45. slice.fill(white_rect[:], 255)
  46. s.shape_drawing_texture = rb.load_texture(white_rect[:], 16, 16)
  47. s.default_shader = rb.load_shader(string(DEFAULT_SHADER_SOURCE), {
  48. .RG32_Float,
  49. .RG32_Float,
  50. .RGBA8_Norm,
  51. })
  52. return s
  53. }
  54. DEFAULT_SHADER_SOURCE :: #load("shader.hlsl")
  55. // Closes the window and cleans up the internal state.
  56. shutdown :: proc() {
  57. rb.destroy_texture(s.shape_drawing_texture)
  58. destroy_shader(s.default_shader)
  59. rb.shutdown()
  60. delete(s.vertex_buffer_cpu, s.allocator)
  61. win.shutdown()
  62. a := s.allocator
  63. free(s.window_state, a)
  64. free(s.rb_state, a)
  65. free(s, a)
  66. s = nil
  67. }
  68. // Clear the backbuffer with supplied color.
  69. clear :: proc(color: Color) {
  70. rb.clear(color)
  71. }
  72. // Present the backbuffer. Call at end of frame to make everything you've drawn appear on the screen.
  73. present :: proc() {
  74. draw_current_batch()
  75. rb.present()
  76. }
  77. // Call at start or end of frame to process all events that have arrived to the window.
  78. //
  79. // WARNING: Not calling this will make your program impossible to interact with.
  80. process_events :: proc() {
  81. s.keys_went_up = {}
  82. s.keys_went_down = {}
  83. s.mouse_delta = {}
  84. s.mouse_wheel_delta = 0
  85. win.process_events()
  86. events := win.get_events()
  87. for &event in events {
  88. switch &e in event {
  89. case Window_Event_Close_Wanted:
  90. s.shutdown_wanted = true
  91. case Window_Event_Key_Went_Down:
  92. s.keys_went_down[e.key] = true
  93. s.keys_is_held[e.key] = true
  94. case Window_Event_Key_Went_Up:
  95. s.keys_is_held[e.key] = false
  96. s.keys_went_up[e.key] = true
  97. case Window_Event_Mouse_Move:
  98. prev_pos := s.mouse_position
  99. s.mouse_position = e.position
  100. s.mouse_delta = prev_pos - s.mouse_position
  101. case Window_Event_Mouse_Wheel:
  102. s.mouse_wheel_delta = e.delta
  103. }
  104. }
  105. win.clear_events()
  106. }
  107. /* Flushes the current batch. This sends off everything to the GPU that has been queued in the
  108. current batch. Normally, you do not need to do this manually. It is done automatically when these
  109. procedures run:
  110. present
  111. set_camera
  112. set_shader
  113. TODO: complete this list and motivate why it needs to happen on those procs (or do that in the
  114. docs for those procs).
  115. */
  116. draw_current_batch :: proc() {
  117. shader := s.batch_shader.? or_else s.default_shader
  118. rb.draw(shader, s.batch_texture, s.proj_matrix * s.view_matrix, s.vertex_buffer_cpu[:s.vertex_buffer_cpu_used])
  119. s.vertex_buffer_cpu_used = 0
  120. }
  121. // Can be used to restore the internal state using the pointer returned by `init`. Useful after
  122. // reloading the library (for example, when doing code hot reload).
  123. set_internal_state :: proc(state: ^State) {
  124. s = state
  125. rb = s.rb
  126. win = s.win
  127. rb.set_internal_state(s.rb_state)
  128. win.set_internal_state(s.window_state)
  129. }
  130. get_screen_width :: proc() -> int {
  131. return rb.get_swapchain_width()
  132. }
  133. get_screen_height :: proc() -> int {
  134. return rb.get_swapchain_height()
  135. }
  136. key_went_down :: proc(key: Keyboard_Key) -> bool {
  137. return s.keys_went_down[key]
  138. }
  139. key_went_up :: proc(key: Keyboard_Key) -> bool {
  140. return s.keys_went_up[key]
  141. }
  142. key_is_held :: proc(key: Keyboard_Key) -> bool {
  143. return s.keys_is_held[key]
  144. }
  145. shutdown_wanted :: proc() -> bool {
  146. return s.shutdown_wanted
  147. }
  148. set_window_position :: proc(x: int, y: int) {
  149. win.set_position(x, y)
  150. }
  151. set_window_size :: proc(width: int, height: int) {
  152. panic("Not implemented")
  153. }
  154. set_camera :: proc(camera: Maybe(Camera)) {
  155. if camera == s.batch_camera {
  156. return
  157. }
  158. draw_current_batch()
  159. s.batch_camera = camera
  160. s.proj_matrix = make_default_projection(s.width, s.height)
  161. if c, c_ok := camera.?; c_ok {
  162. origin_trans := linalg.matrix4_translate(vec3_from_vec2(-c.origin))
  163. translate := linalg.matrix4_translate(vec3_from_vec2(c.target))
  164. scale := linalg.matrix4_scale(Vec3{1/c.zoom, 1/c.zoom, 1})
  165. rot := linalg.matrix4_rotate_f32(c.rotation * math.RAD_PER_DEG, {0, 0, 1})
  166. camera_matrix := translate * scale * rot * origin_trans
  167. s.view_matrix = linalg.inverse(camera_matrix)
  168. } else {
  169. s.view_matrix = 1
  170. }
  171. }
  172. load_texture_from_file :: proc(filename: string) -> Texture {
  173. img, img_err := image.load_from_file(filename, options = {.alpha_add_if_missing}, allocator = context.temp_allocator)
  174. if img_err != nil {
  175. log.errorf("Error loading texture %v: %v", filename, img_err)
  176. return {}
  177. }
  178. backend_tex := rb.load_texture(img.pixels.buf[:], img.width, img.height)
  179. return {
  180. handle = backend_tex,
  181. width = img.width,
  182. height = img.height,
  183. }
  184. }
  185. destroy_texture :: proc(tex: Texture) {
  186. rb.destroy_texture(tex.handle)
  187. }
  188. draw_rect :: proc(r: Rect, c: Color) {
  189. if s.batch_texture != TEXTURE_NONE && s.batch_texture != s.shape_drawing_texture {
  190. draw_current_batch()
  191. }
  192. s.batch_texture = s.shape_drawing_texture
  193. _batch_vertex({r.x, r.y}, {0, 0}, c)
  194. _batch_vertex({r.x + r.w, r.y}, {1, 0}, c)
  195. _batch_vertex({r.x + r.w, r.y + r.h}, {1, 1}, c)
  196. _batch_vertex({r.x, r.y}, {0, 0}, c)
  197. _batch_vertex({r.x + r.w, r.y + r.h}, {1, 1}, c)
  198. _batch_vertex({r.x, r.y + r.h}, {0, 1}, c)
  199. }
  200. draw_rect_ex :: proc(r: Rect, origin: Vec2, rot: f32, c: Color) {
  201. if s.batch_texture != TEXTURE_NONE && s.batch_texture != s.shape_drawing_texture {
  202. draw_current_batch()
  203. }
  204. s.batch_texture = s.shape_drawing_texture
  205. tl, tr, bl, br: Vec2
  206. // Rotation adapted from Raylib's "DrawTexturePro"
  207. if rot == 0 {
  208. x := r.x - origin.x
  209. y := r.y - origin.y
  210. tl = { x, y }
  211. tr = { x + r.w, y }
  212. bl = { x, y + r.h }
  213. br = { x + r.w, y + r.h }
  214. } else {
  215. sin_rot := math.sin(rot * math.RAD_PER_DEG)
  216. cos_rot := math.cos(rot * math.RAD_PER_DEG)
  217. x := r.x
  218. y := r.y
  219. dx := -origin.x
  220. dy := -origin.y
  221. tl = {
  222. x + dx * cos_rot - dy * sin_rot,
  223. y + dx * sin_rot + dy * cos_rot,
  224. }
  225. tr = {
  226. x + (dx + r.w) * cos_rot - dy * sin_rot,
  227. y + (dx + r.w) * sin_rot + dy * cos_rot,
  228. }
  229. bl = {
  230. x + dx * cos_rot - (dy + r.h) * sin_rot,
  231. y + dx * sin_rot + (dy + r.h) * cos_rot,
  232. }
  233. br = {
  234. x + (dx + r.w) * cos_rot - (dy + r.h) * sin_rot,
  235. y + (dx + r.w) * sin_rot + (dy + r.h) * cos_rot,
  236. }
  237. }
  238. _batch_vertex(tl, {0, 0}, c)
  239. _batch_vertex(tr, {1, 0}, c)
  240. _batch_vertex(br, {1, 1}, c)
  241. _batch_vertex(tl, {0, 0}, c)
  242. _batch_vertex(br, {1, 1}, c)
  243. _batch_vertex(bl, {0, 1}, c)
  244. }
  245. draw_rect_outline :: proc(r: Rect, thickness: f32, color: Color) {
  246. t := thickness
  247. // Based on DrawRectangleLinesEx from Raylib
  248. top := Rect {
  249. r.x,
  250. r.y,
  251. r.w,
  252. t,
  253. }
  254. bottom := Rect {
  255. r.x,
  256. r.y + r.h - t,
  257. r.w,
  258. t,
  259. }
  260. left := Rect {
  261. r.x,
  262. r.y + t,
  263. t,
  264. r.h - t * 2,
  265. }
  266. right := Rect {
  267. r.x + r.w - t,
  268. r.y + t,
  269. t,
  270. r.h - t * 2,
  271. }
  272. draw_rect(top, color)
  273. draw_rect(bottom, color)
  274. draw_rect(left, color)
  275. draw_rect(right, color)
  276. }
  277. draw_circle :: proc(center: Vec2, radius: f32, color: Color, segments := 16) {
  278. if s.batch_texture != TEXTURE_NONE && s.batch_texture != s.shape_drawing_texture {
  279. draw_current_batch()
  280. }
  281. s.batch_texture = s.shape_drawing_texture
  282. prev := center + {radius, 0}
  283. for s in 1..=segments {
  284. sr := (f32(s)/f32(segments)) * 2*math.PI
  285. rot := linalg.matrix2_rotate(sr)
  286. p := center + rot * Vec2{radius, 0}
  287. _batch_vertex(prev, {0, 0}, color)
  288. _batch_vertex(p, {1, 0}, color)
  289. _batch_vertex(center, {1, 1}, color)
  290. prev = p
  291. }
  292. }
  293. draw_line :: proc(start: Vec2, end: Vec2, thickness: f32, color: Color) {
  294. p := Vec2{start.x, start.y + thickness*0.5}
  295. s := Vec2{linalg.length(end - start), thickness}
  296. origin := Vec2 {0, thickness*0.5}
  297. r := Rect {p.x, p.y, s.x, s.y}
  298. rot := math.atan2(end.y - start.y, end.x - start.x)
  299. draw_rect_ex(r, origin, rot * math.DEG_PER_RAD, color)
  300. }
  301. draw_texture :: proc(tex: Texture, pos: Vec2, tint := WHITE) {
  302. draw_texture_ex(
  303. tex,
  304. {0, 0, f32(tex.width), f32(tex.height)},
  305. {pos.x, pos.y, f32(tex.width), f32(tex.height)},
  306. {},
  307. 0,
  308. tint,
  309. )
  310. }
  311. draw_texture_rect :: proc(tex: Texture, rect: Rect, pos: Vec2, tint := WHITE) {
  312. draw_texture_ex(
  313. tex,
  314. rect,
  315. {pos.x, pos.y, rect.w, rect.h},
  316. {},
  317. 0,
  318. tint,
  319. )
  320. }
  321. draw_texture_ex :: proc(tex: Texture, src: Rect, dst: Rect, origin: Vec2, rotation: f32, tint := WHITE) {
  322. if tex.width == 0 || tex.height == 0 {
  323. return
  324. }
  325. if s.batch_texture != TEXTURE_NONE && s.batch_texture != tex.handle {
  326. draw_current_batch()
  327. }
  328. flip_x, flip_y: bool
  329. src := src
  330. dst := dst
  331. if src.w < 0 {
  332. flip_x = true
  333. src.w = -src.w
  334. }
  335. if src.h < 0 {
  336. flip_y = true
  337. src.h = -src.h
  338. }
  339. if dst.w < 0 {
  340. dst.w *= -1
  341. }
  342. if dst.h < 0 {
  343. dst.h *= -1
  344. }
  345. s.batch_texture = tex.handle
  346. tl, tr, bl, br: Vec2
  347. // Rotation adapted from Raylib's "DrawTexturePro"
  348. if rotation == 0 {
  349. x := dst.x - origin.x
  350. y := dst.y - origin.y
  351. tl = { x, y }
  352. tr = { x + dst.w, y }
  353. bl = { x, y + dst.h }
  354. br = { x + dst.w, y + dst.h }
  355. } else {
  356. sin_rot := math.sin(rotation * math.RAD_PER_DEG)
  357. cos_rot := math.cos(rotation * math.RAD_PER_DEG)
  358. x := dst.x
  359. y := dst.y
  360. dx := -origin.x
  361. dy := -origin.y
  362. tl = {
  363. x + dx * cos_rot - dy * sin_rot,
  364. y + dx * sin_rot + dy * cos_rot,
  365. }
  366. tr = {
  367. x + (dx + dst.w) * cos_rot - dy * sin_rot,
  368. y + (dx + dst.w) * sin_rot + dy * cos_rot,
  369. }
  370. bl = {
  371. x + dx * cos_rot - (dy + dst.h) * sin_rot,
  372. y + dx * sin_rot + (dy + dst.h) * cos_rot,
  373. }
  374. br = {
  375. x + (dx + dst.w) * cos_rot - (dy + dst.h) * sin_rot,
  376. y + (dx + dst.w) * sin_rot + (dy + dst.h) * cos_rot,
  377. }
  378. }
  379. ts := Vec2{f32(tex.width), f32(tex.height)}
  380. up := Vec2{src.x, src.y} / ts
  381. us := Vec2{src.w, src.h} / ts
  382. c := tint
  383. uv0 := up
  384. uv1 := up + {us.x, 0}
  385. uv2 := up + us
  386. uv3 := up
  387. uv4 := up + us
  388. uv5 := up + {0, us.y}
  389. if flip_x {
  390. uv0.x += us.x
  391. uv1.x -= us.x
  392. uv2.x -= us.x
  393. uv3.x += us.x
  394. uv4.x -= us.x
  395. uv5.x += us.x
  396. }
  397. if flip_y {
  398. uv0.y += us.y
  399. uv1.y += us.y
  400. uv2.y -= us.y
  401. uv3.y += us.y
  402. uv4.y -= us.y
  403. uv5.y -= us.y
  404. }
  405. _batch_vertex(tl, uv0, c)
  406. _batch_vertex(tr, uv1, c)
  407. _batch_vertex(br, uv2, c)
  408. _batch_vertex(tl, uv3, c)
  409. _batch_vertex(br, uv4, c)
  410. _batch_vertex(bl, uv5, c)
  411. }
  412. load_shader :: proc(shader_source: string, layout_formats: []Shader_Input_Format = {}) -> Shader {
  413. return rb.load_shader(shader_source, layout_formats)
  414. }
  415. destroy_shader :: proc(shader: Shader) {
  416. rb.destroy_shader(shader)
  417. }
  418. set_shader :: proc(shader: Maybe(Shader)) {
  419. if maybe_handle_equal(shader, s.batch_shader) {
  420. return
  421. }
  422. draw_current_batch()
  423. s.batch_shader = shader
  424. }
  425. maybe_handle_equal :: proc(m1: Maybe($T), m2: Maybe(T)) -> bool {
  426. if m1 == nil && m2 == nil {
  427. return true
  428. }
  429. m1v, m1v_ok := m1.?
  430. m2v, m2v_ok := m2.?
  431. if !m1v_ok || !m2v_ok {
  432. return false
  433. }
  434. return m1v.handle == m2v.handle
  435. }
  436. set_shader_constant :: proc(shd: Shader, loc: Shader_Constant_Location, val: $T) {
  437. draw_current_batch()
  438. if int(loc.buffer_idx) >= len(shd.constant_buffers) {
  439. log.warnf("Constant buffer idx %v is out of bounds", loc.buffer_idx)
  440. return
  441. }
  442. b := &shd.constant_buffers[loc.buffer_idx]
  443. if int(loc.offset) + size_of(val) > len(b.cpu_data) {
  444. log.warnf("Constant buffer idx %v is trying to be written out of bounds by at offset %v with %v bytes", loc.buffer_idx, loc.offset, size_of(val))
  445. return
  446. }
  447. dst := (^T)(&b.cpu_data[loc.offset])
  448. dst^ = val
  449. }
  450. set_shader_constant_mat4 :: proc(shader: Shader, loc: Shader_Constant_Location, val: matrix[4,4]f32) {
  451. set_shader_constant(shader, loc, val)
  452. }
  453. set_shader_constant_f32 :: proc(shader: Shader, loc: Shader_Constant_Location, val: f32) {
  454. set_shader_constant(shader, loc, val)
  455. }
  456. set_shader_constant_vec2 :: proc(shader: Shader, loc: Shader_Constant_Location, val: Vec2) {
  457. set_shader_constant(shader, loc, val)
  458. }
  459. get_default_shader :: proc() -> Shader {
  460. return s.default_shader
  461. }
  462. set_scissor_rect :: proc(scissor_rect: Maybe(Rect)) {
  463. panic("not implemented")
  464. }
  465. screen_to_world :: proc(pos: Vec2, camera: Camera) -> Vec2 {
  466. panic("not implemented")
  467. }
  468. draw_text :: proc(text: string, pos: Vec2, font_size: f32, color: Color) {
  469. }
  470. mouse_button_went_down :: proc(button: Mouse_Button) -> bool {
  471. panic("not implemented")
  472. }
  473. mouse_button_went_up :: proc(button: Mouse_Button) -> bool {
  474. panic("not implemented")
  475. }
  476. mouse_button_is_held :: proc(button: Mouse_Button) -> bool {
  477. panic("not implemented")
  478. }
  479. get_mouse_wheel_delta :: proc() -> f32 {
  480. return s.mouse_wheel_delta
  481. }
  482. get_mouse_position :: proc() -> Vec2 {
  483. return s.mouse_position
  484. }
  485. _batch_vertex :: proc(v: Vec2, uv: Vec2, color: Color) {
  486. v := v
  487. if s.vertex_buffer_cpu_used == len(s.vertex_buffer_cpu) {
  488. panic("Must dispatch here")
  489. }
  490. shd := s.batch_shader.? or_else s.default_shader
  491. base_offset := s.vertex_buffer_cpu_used
  492. pos_offset := shd.default_input_offsets[.Position]
  493. uv_offset := shd.default_input_offsets[.UV]
  494. color_offset := shd.default_input_offsets[.Color]
  495. mem.set(&s.vertex_buffer_cpu[base_offset], 0, shd.vertex_size)
  496. if pos_offset != -1 {
  497. (^Vec2)(&s.vertex_buffer_cpu[base_offset + pos_offset])^ = v
  498. }
  499. if uv_offset != -1 {
  500. (^Vec2)(&s.vertex_buffer_cpu[base_offset + uv_offset])^ = uv
  501. }
  502. if color_offset != -1 {
  503. (^Color)(&s.vertex_buffer_cpu[base_offset + color_offset])^ = color
  504. }
  505. override_offset: int
  506. for &o, idx in shd.input_overrides {
  507. input := &shd.inputs[idx]
  508. sz := shader_input_format_size(input.format)
  509. if o.used != 0 {
  510. mem.copy(&s.vertex_buffer_cpu[base_offset + override_offset], raw_data(&o.val), o.used)
  511. }
  512. override_offset += sz
  513. }
  514. s.vertex_buffer_cpu_used += shd.vertex_size
  515. }
  516. State :: struct {
  517. allocator: runtime.Allocator,
  518. custom_context: runtime.Context,
  519. win: Window_Interface,
  520. window_state: rawptr,
  521. rb: Rendering_Backend_Interface,
  522. rb_state: rawptr,
  523. shutdown_wanted: bool,
  524. mouse_position: Vec2,
  525. mouse_delta: Vec2,
  526. mouse_wheel_delta: f32,
  527. keys_went_down: #sparse [Keyboard_Key]bool,
  528. keys_went_up: #sparse [Keyboard_Key]bool,
  529. keys_is_held: #sparse [Keyboard_Key]bool,
  530. window: Window_Handle,
  531. width: int,
  532. height: int,
  533. shape_drawing_texture: Texture_Handle,
  534. batch_camera: Maybe(Camera),
  535. batch_shader: Maybe(Shader),
  536. batch_texture: Texture_Handle,
  537. view_matrix: Mat4,
  538. proj_matrix: Mat4,
  539. vertex_buffer_cpu: []u8,
  540. vertex_buffer_cpu_used: int,
  541. default_shader: Shader,
  542. }
  543. @(private="file")
  544. s: ^State
  545. win: Window_Interface
  546. rb: Rendering_Backend_Interface
  547. Shader_Input_Format :: enum {
  548. Unknown,
  549. RGBA32_Float,
  550. RGBA8_Norm,
  551. RGBA8_Norm_SRGB,
  552. RG32_Float,
  553. R32_Float,
  554. }
  555. Color :: [4]u8
  556. Vec2 :: [2]f32
  557. Vec3 :: [3]f32
  558. Mat4 :: matrix[4,4]f32
  559. Vec2i :: [2]int
  560. Rect :: struct {
  561. x, y: f32,
  562. w, h: f32,
  563. }
  564. Texture :: struct {
  565. handle: Texture_Handle,
  566. width: int,
  567. height: int,
  568. }
  569. Shader :: struct {
  570. handle: Shader_Handle,
  571. constant_buffers: []Shader_Constant_Buffer,
  572. constant_lookup: map[string]Shader_Constant_Location,
  573. constant_builtin_locations: [Shader_Builtin_Constant]Maybe(Shader_Constant_Location),
  574. inputs: []Shader_Input,
  575. input_overrides: []Shader_Input_Value_Override,
  576. default_input_offsets: [Shader_Default_Inputs]int,
  577. vertex_size: int,
  578. }
  579. Camera :: struct {
  580. target: Vec2,
  581. origin: Vec2,
  582. rotation: f32,
  583. zoom: f32,
  584. }
  585. // Support for up to 255 mouse buttons. Cast an int to type `Mouse_Button` to use things outside the
  586. // options presented here.
  587. Mouse_Button :: enum {
  588. Left,
  589. Right,
  590. Middle,
  591. Max = 255,
  592. }
  593. // TODO: These are just copied from raylib, we probably want a list of our own "default colors"
  594. WHITE :: Color { 255, 255, 255, 255 }
  595. BLACK :: Color { 0, 0, 0, 255 }
  596. GRAY :: Color{ 130, 130, 130, 255 }
  597. RED :: Color { 230, 41, 55, 255 }
  598. YELLOW :: Color { 253, 249, 0, 255 }
  599. BLUE :: Color { 0, 121, 241, 255 }
  600. MAGENTA :: Color { 255, 0, 255, 255 }
  601. DARKGRAY :: Color{ 80, 80, 80, 255 }
  602. GREEN :: Color{ 0, 228, 48, 255 }
  603. Shader_Handle :: distinct Handle
  604. SHADER_NONE :: Shader_Handle {}
  605. // Based on Raylib / GLFW
  606. Keyboard_Key :: enum {
  607. None = 0,
  608. // Alphanumeric keys
  609. Apostrophe = 39,
  610. Comma = 44,
  611. Minus = 45,
  612. Period = 46,
  613. Slash = 47,
  614. Zero = 48,
  615. One = 49,
  616. Two = 50,
  617. Three = 51,
  618. Four = 52,
  619. Five = 53,
  620. Six = 54,
  621. Seven = 55,
  622. Eight = 56,
  623. Nine = 57,
  624. Semicolon = 59,
  625. Equal = 61,
  626. A = 65,
  627. B = 66,
  628. C = 67,
  629. D = 68,
  630. E = 69,
  631. F = 70,
  632. G = 71,
  633. H = 72,
  634. I = 73,
  635. J = 74,
  636. K = 75,
  637. L = 76,
  638. M = 77,
  639. N = 78,
  640. O = 79,
  641. P = 80,
  642. Q = 81,
  643. R = 82,
  644. S = 83,
  645. T = 84,
  646. U = 85,
  647. V = 86,
  648. W = 87,
  649. X = 88,
  650. Y = 89,
  651. Z = 90,
  652. Left_Bracket = 91,
  653. Backslash = 92,
  654. Right_Bracket = 93,
  655. Grave = 96,
  656. // Function keys
  657. Space = 32,
  658. Escape = 256,
  659. Enter = 257,
  660. Tab = 258,
  661. Backspace = 259,
  662. Insert = 260,
  663. Delete = 261,
  664. Right = 262,
  665. Left = 263,
  666. Down = 264,
  667. Up = 265,
  668. Page_Up = 266,
  669. Page_Down = 267,
  670. Home = 268,
  671. End = 269,
  672. Caps_Lock = 280,
  673. Scroll_Lock = 281,
  674. Num_Lock = 282,
  675. Print_Screen = 283,
  676. Pause = 284,
  677. F1 = 290,
  678. F2 = 291,
  679. F3 = 292,
  680. F4 = 293,
  681. F5 = 294,
  682. F6 = 295,
  683. F7 = 296,
  684. F8 = 297,
  685. F9 = 298,
  686. F10 = 299,
  687. F11 = 300,
  688. F12 = 301,
  689. Left_Shift = 340,
  690. Left_Control = 341,
  691. Left_Alt = 342,
  692. Left_Super = 343,
  693. Right_Shift = 344,
  694. Right_Control = 345,
  695. Right_Alt = 346,
  696. Right_Super = 347,
  697. Menu = 348,
  698. // Keypad keys
  699. KP_0 = 320,
  700. KP_1 = 321,
  701. KP_2 = 322,
  702. KP_3 = 323,
  703. KP_4 = 324,
  704. KP_5 = 325,
  705. KP_6 = 326,
  706. KP_7 = 327,
  707. KP_8 = 328,
  708. KP_9 = 329,
  709. KP_Decimal = 330,
  710. KP_Divide = 331,
  711. KP_Multiply = 332,
  712. KP_Subtract = 333,
  713. KP_Add = 334,
  714. KP_Enter = 335,
  715. KP_Equal = 336,
  716. }