karl2d.odin 19 KB

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