karl2d.odin 18 KB

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