karl2d.odin 19 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823
  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_texture :: proc(tex: Texture, pos: Vec2, tint := WHITE) {
  258. draw_texture_ex(
  259. tex,
  260. {0, 0, f32(tex.width), f32(tex.height)},
  261. {pos.x, pos.y, f32(tex.width), f32(tex.height)},
  262. {},
  263. 0,
  264. tint,
  265. )
  266. }
  267. draw_texture_rect :: proc(tex: Texture, rect: Rect, pos: Vec2, tint := WHITE) {
  268. draw_texture_ex(
  269. tex,
  270. rect,
  271. {pos.x, pos.y, rect.w, rect.h},
  272. {},
  273. 0,
  274. tint,
  275. )
  276. }
  277. draw_texture_ex :: proc(tex: Texture, src: Rect, dst: Rect, origin: Vec2, rotation: f32, tint := WHITE) {
  278. if tex.width == 0 || tex.height == 0 {
  279. return
  280. }
  281. if s.batch_texture != TEXTURE_NONE && s.batch_texture != tex.handle {
  282. draw_current_batch()
  283. }
  284. r := dst
  285. r.x -= origin.x
  286. r.y -= origin.y
  287. s.batch_texture = tex.handle
  288. tl, tr, bl, br: Vec2
  289. // Rotation adapted from Raylib's "DrawTexturePro"
  290. if rotation == 0 {
  291. x := dst.x - origin.x
  292. y := dst.y - origin.y
  293. tl = { x, y }
  294. tr = { x + dst.w, y }
  295. bl = { x, y + dst.h }
  296. br = { x + dst.w, y + dst.h }
  297. } else {
  298. sin_rot := math.sin(rotation * math.RAD_PER_DEG)
  299. cos_rot := math.cos(rotation * math.RAD_PER_DEG)
  300. x := dst.x
  301. y := dst.y
  302. dx := -origin.x
  303. dy := -origin.y
  304. tl = {
  305. x + dx * cos_rot - dy * sin_rot,
  306. y + dx * sin_rot + dy * cos_rot,
  307. }
  308. tr = {
  309. x + (dx + dst.w) * cos_rot - dy * sin_rot,
  310. y + (dx + dst.w) * sin_rot + dy * cos_rot,
  311. }
  312. bl = {
  313. x + dx * cos_rot - (dy + dst.h) * sin_rot,
  314. y + dx * sin_rot + (dy + dst.h) * cos_rot,
  315. }
  316. br = {
  317. x + (dx + dst.w) * cos_rot - (dy + dst.h) * sin_rot,
  318. y + (dx + dst.w) * sin_rot + (dy + dst.h) * cos_rot,
  319. }
  320. }
  321. ts := Vec2{f32(tex.width), f32(tex.height)}
  322. up := Vec2{src.x, src.y} / ts
  323. us := Vec2{src.w, src.h} / ts
  324. c := tint
  325. _batch_vertex(tl, up, c)
  326. _batch_vertex(tr, up + {us.x, 0}, c)
  327. _batch_vertex(br, up + us, c)
  328. _batch_vertex(tl, up, c)
  329. _batch_vertex(br, up + us, c)
  330. _batch_vertex(bl, up + {0, us.y}, c)
  331. }
  332. load_shader :: proc(shader_source: string, layout_formats: []Shader_Input_Format = {}) -> Shader {
  333. return s.rb.load_shader(shader_source, layout_formats)
  334. }
  335. destroy_shader :: proc(shader: Shader) {
  336. s.rb.destroy_shader(shader)
  337. }
  338. set_shader :: proc(shader: Maybe(Shader)) {
  339. if maybe_handle_equal(shader, s.batch_shader) {
  340. return
  341. }
  342. draw_current_batch()
  343. s.batch_shader = shader
  344. }
  345. maybe_handle_equal :: proc(m1: Maybe($T), m2: Maybe(T)) -> bool {
  346. if m1 == nil && m2 == nil {
  347. return true
  348. }
  349. m1v, m1v_ok := m1.?
  350. m2v, m2v_ok := m2.?
  351. if !m1v_ok || !m2v_ok {
  352. return false
  353. }
  354. return m1v.handle == m2v.handle
  355. }
  356. set_shader_constant :: proc(shd: Shader, loc: Shader_Constant_Location, val: $T) {
  357. draw_current_batch()
  358. if int(loc.buffer_idx) >= len(shd.constant_buffers) {
  359. log.warnf("Constant buffer idx %v is out of bounds", loc.buffer_idx)
  360. return
  361. }
  362. b := &shd.constant_buffers[loc.buffer_idx]
  363. if int(loc.offset) + size_of(val) > len(b.cpu_data) {
  364. 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))
  365. return
  366. }
  367. dst := (^T)(&b.cpu_data[loc.offset])
  368. dst^ = val
  369. }
  370. set_shader_constant_mat4 :: proc(shader: Shader, loc: Shader_Constant_Location, val: matrix[4,4]f32) {
  371. set_shader_constant(shader, loc, val)
  372. }
  373. set_shader_constant_f32 :: proc(shader: Shader, loc: Shader_Constant_Location, val: f32) {
  374. set_shader_constant(shader, loc, val)
  375. }
  376. set_shader_constant_vec2 :: proc(shader: Shader, loc: Shader_Constant_Location, val: Vec2) {
  377. set_shader_constant(shader, loc, val)
  378. }
  379. _batch_vertex :: proc(v: Vec2, uv: Vec2, color: Color) {
  380. v := v
  381. if s.vertex_buffer_cpu_used == len(s.vertex_buffer_cpu) {
  382. panic("Must dispatch here")
  383. }
  384. shd := s.batch_shader.? or_else s.default_shader
  385. base_offset := s.vertex_buffer_cpu_used
  386. pos_offset := shd.default_input_offsets[.Position]
  387. uv_offset := shd.default_input_offsets[.UV]
  388. color_offset := shd.default_input_offsets[.Color]
  389. if pos_offset != -1 {
  390. (^Vec2)(&s.vertex_buffer_cpu[base_offset + pos_offset])^ = v
  391. }
  392. if uv_offset != -1 {
  393. (^Vec2)(&s.vertex_buffer_cpu[base_offset + uv_offset])^ = uv
  394. }
  395. if color_offset != -1 {
  396. (^Color)(&s.vertex_buffer_cpu[base_offset + color_offset])^ = color
  397. }
  398. override_offset: int
  399. for &o, idx in shd.input_overrides {
  400. input := &shd.inputs[idx]
  401. sz := shader_input_format_size(input.format)
  402. if o.used != 0 {
  403. mem.copy(&s.vertex_buffer_cpu[base_offset + override_offset], raw_data(&o.val), o.used)
  404. }
  405. override_offset += sz
  406. }
  407. s.vertex_buffer_cpu_used += shd.vertex_size
  408. }
  409. Rendering_Backend :: struct {
  410. state_size: proc() -> int,
  411. init: proc(state: rawptr, window_handle: uintptr, swapchain_width, swapchain_height: int,
  412. allocator := context.allocator, loc := #caller_location),
  413. shutdown: proc(),
  414. clear: proc(color: Color),
  415. present: proc(),
  416. draw: proc(shader: Shader, texture: Texture_Handle, vertex_buffer: []u8),
  417. set_internal_state: proc(state: rawptr),
  418. load_texture: proc(data: []u8, width: int, height: int) -> Texture_Handle,
  419. destroy_texture: proc(handle: Texture_Handle),
  420. load_shader: proc(shader: string, layout_formats: []Shader_Input_Format = {}) -> Shader,
  421. destroy_shader: proc(shader: Shader),
  422. get_swapchain_width: proc() -> int,
  423. get_swapchain_height: proc() -> int,
  424. set_view_projection_matrix: proc(m: Mat4),
  425. batch_vertex: proc(v: Vec2, uv: Vec2, color: Color),
  426. }
  427. State :: struct {
  428. allocator: runtime.Allocator,
  429. custom_context: runtime.Context,
  430. rb: Rendering_Backend,
  431. rb_state: rawptr,
  432. keys_went_down: #sparse [Keyboard_Key]bool,
  433. keys_went_up: #sparse [Keyboard_Key]bool,
  434. keys_is_held: #sparse [Keyboard_Key]bool,
  435. window: win32.HWND,
  436. width: int,
  437. height: int,
  438. run: bool,
  439. shape_drawing_texture: Texture_Handle,
  440. batch_camera: Maybe(Camera),
  441. batch_shader: Maybe(Shader),
  442. batch_texture: Texture_Handle,
  443. view_matrix: Mat4,
  444. proj_matrix: Mat4,
  445. vertex_buffer_cpu: []u8,
  446. vertex_buffer_cpu_used: int,
  447. default_shader: Shader,
  448. }
  449. VK_MAP := [255]Keyboard_Key {
  450. win32.VK_A = .A,
  451. win32.VK_B = .B,
  452. win32.VK_C = .C,
  453. win32.VK_D = .D,
  454. win32.VK_E = .E,
  455. win32.VK_F = .F,
  456. win32.VK_G = .G,
  457. win32.VK_H = .H,
  458. win32.VK_I = .I,
  459. win32.VK_J = .J,
  460. win32.VK_K = .K,
  461. win32.VK_L = .L,
  462. win32.VK_M = .M,
  463. win32.VK_N = .N,
  464. win32.VK_O = .O,
  465. win32.VK_P = .P,
  466. win32.VK_Q = .Q,
  467. win32.VK_R = .R,
  468. win32.VK_S = .S,
  469. win32.VK_T = .T,
  470. win32.VK_U = .U,
  471. win32.VK_V = .V,
  472. win32.VK_W = .W,
  473. win32.VK_X = .X,
  474. win32.VK_Y = .Y,
  475. win32.VK_Z = .Z,
  476. win32.VK_LEFT = .Left,
  477. win32.VK_RIGHT = .Right,
  478. win32.VK_UP = .Up,
  479. win32.VK_DOWN = .Down,
  480. }
  481. @(private="file")
  482. s: ^State
  483. // --------------------------------
  484. // old, non migrated API below
  485. get_default_shader: proc() -> Shader_Handle : _get_default_shader
  486. set_scissor_rect: proc(scissor_rect: Maybe(Rect)) : _set_scissor_rect
  487. //set_vertex_value :: _set_vertex_value
  488. draw_circle: proc(center: Vec2, radius: f32, color: Color) : _draw_circle
  489. draw_line: proc(start: Vec2, end: Vec2, thickness: f32, color: Color) : _draw_line
  490. Shader_Input_Format :: enum {
  491. Unknown,
  492. RGBA32_Float,
  493. RGBA8_Norm,
  494. RGBA8_Norm_SRGB,
  495. RG32_Float,
  496. R32_Float,
  497. }
  498. // WARNING: Not proper text rendering yet... No font support etc
  499. draw_text: proc(text: string, pos: Vec2, font_size: f32, color: Color) : _draw_text
  500. screen_to_world: proc(pos: Vec2, camera: Camera) -> Vec2 : _screen_to_world
  501. mouse_button_went_down: proc(button: Mouse_Button) -> bool : _mouse_button_pressed
  502. mouse_button_went_up: proc(button: Mouse_Button) -> bool : _mouse_button_released
  503. mouse_button_is_held: proc(button: Mouse_Button) -> bool : _mouse_button_held
  504. get_mouse_wheel_delta: proc() -> f32 : _mouse_wheel_delta
  505. get_mouse_position: proc() -> Vec2 : _mouse_position
  506. Color :: [4]u8
  507. Vec2 :: [2]f32
  508. Mat4 :: matrix[4,4]f32
  509. Vec2i :: [2]int
  510. Rect :: struct {
  511. x, y: f32,
  512. w, h: f32,
  513. }
  514. Texture :: struct {
  515. handle: Texture_Handle,
  516. width: int,
  517. height: int,
  518. }
  519. Shader :: struct {
  520. handle: Shader_Handle,
  521. constant_buffers: []Shader_Constant_Buffer,
  522. constant_lookup: map[string]Shader_Constant_Location,
  523. constant_builtin_locations: [Shader_Builtin_Constant]Maybe(Shader_Constant_Location),
  524. inputs: []Shader_Input,
  525. input_overrides: []Shader_Input_Value_Override,
  526. default_input_offsets: [Shader_Default_Inputs]int,
  527. vertex_size: int,
  528. }
  529. Camera :: struct {
  530. target: Vec2,
  531. origin: Vec2,
  532. rotation: f32,
  533. zoom: f32,
  534. }
  535. // Support for up to 255 mouse buttons. Cast an int to type `Mouse_Button` to use things outside the
  536. // options presented here.
  537. Mouse_Button :: enum {
  538. Left,
  539. Right,
  540. Middle,
  541. Max = 255,
  542. }
  543. // TODO: These are just copied from raylib, we probably want a list of our own "default colors"
  544. WHITE :: Color { 255, 255, 255, 255 }
  545. BLACK :: Color { 0, 0, 0, 255 }
  546. GRAY :: Color{ 130, 130, 130, 255 }
  547. RED :: Color { 230, 41, 55, 255 }
  548. YELLOW :: Color { 253, 249, 0, 255 }
  549. BLUE :: Color { 0, 121, 241, 255 }
  550. MAGENTA :: Color { 255, 0, 255, 255 }
  551. DARKGRAY :: Color{ 80, 80, 80, 255 }
  552. GREEN :: Color{ 0, 228, 48, 255 }
  553. Shader_Handle :: distinct Handle
  554. SHADER_NONE :: Shader_Handle {}
  555. // Based on Raylib / GLFW
  556. Keyboard_Key :: enum {
  557. None = 0,
  558. // Alphanumeric keys
  559. Apostrophe = 39,
  560. Comma = 44,
  561. Minus = 45,
  562. Period = 46,
  563. Slash = 47,
  564. Zero = 48,
  565. One = 49,
  566. Two = 50,
  567. Three = 51,
  568. Four = 52,
  569. Five = 53,
  570. Six = 54,
  571. Seven = 55,
  572. Eight = 56,
  573. Nine = 57,
  574. Semicolon = 59,
  575. Equal = 61,
  576. A = 65,
  577. B = 66,
  578. C = 67,
  579. D = 68,
  580. E = 69,
  581. F = 70,
  582. G = 71,
  583. H = 72,
  584. I = 73,
  585. J = 74,
  586. K = 75,
  587. L = 76,
  588. M = 77,
  589. N = 78,
  590. O = 79,
  591. P = 80,
  592. Q = 81,
  593. R = 82,
  594. S = 83,
  595. T = 84,
  596. U = 85,
  597. V = 86,
  598. W = 87,
  599. X = 88,
  600. Y = 89,
  601. Z = 90,
  602. Left_Bracket = 91,
  603. Backslash = 92,
  604. Right_Bracket = 93,
  605. Grave = 96,
  606. // Function keys
  607. Space = 32,
  608. Escape = 256,
  609. Enter = 257,
  610. Tab = 258,
  611. Backspace = 259,
  612. Insert = 260,
  613. Delete = 261,
  614. Right = 262,
  615. Left = 263,
  616. Down = 264,
  617. Up = 265,
  618. Page_Up = 266,
  619. Page_Down = 267,
  620. Home = 268,
  621. End = 269,
  622. Caps_Lock = 280,
  623. Scroll_Lock = 281,
  624. Num_Lock = 282,
  625. Print_Screen = 283,
  626. Pause = 284,
  627. F1 = 290,
  628. F2 = 291,
  629. F3 = 292,
  630. F4 = 293,
  631. F5 = 294,
  632. F6 = 295,
  633. F7 = 296,
  634. F8 = 297,
  635. F9 = 298,
  636. F10 = 299,
  637. F11 = 300,
  638. F12 = 301,
  639. Left_Shift = 340,
  640. Left_Control = 341,
  641. Left_Alt = 342,
  642. Left_Super = 343,
  643. Right_Shift = 344,
  644. Right_Control = 345,
  645. Right_Alt = 346,
  646. Right_Super = 347,
  647. Menu = 348,
  648. // Keypad keys
  649. KP_0 = 320,
  650. KP_1 = 321,
  651. KP_2 = 322,
  652. KP_3 = 323,
  653. KP_4 = 324,
  654. KP_5 = 325,
  655. KP_6 = 326,
  656. KP_7 = 327,
  657. KP_8 = 328,
  658. KP_9 = 329,
  659. KP_Decimal = 330,
  660. KP_Divide = 331,
  661. KP_Multiply = 332,
  662. KP_Subtract = 333,
  663. KP_Add = 334,
  664. KP_Enter = 335,
  665. KP_Equal = 336,
  666. }