karlib_raylib.odin 5.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259
  1. package karlib
  2. import rl "raylib"
  3. import "raylib/rlgl"
  4. import "core:log"
  5. import "base:runtime"
  6. _init :: proc(width: int, height: int, title: string,
  7. allocator := context.allocator, loc := #caller_location) -> ^State {
  8. s = new(State, allocator, loc)
  9. s.textures = make([dynamic]rl.Texture, allocator, loc)
  10. s.allocator = allocator
  11. rl.SetConfigFlags({.WINDOW_RESIZABLE, .VSYNC_HINT})
  12. rl.InitWindow(i32(width), i32(height), temp_cstring(title))
  13. return s
  14. }
  15. _shutdown :: proc() {
  16. rl.CloseWindow()
  17. if s != nil {
  18. delete(s.textures)
  19. a := s.allocator
  20. free(s, a)
  21. s = nil
  22. }
  23. }
  24. _set_internal_state :: proc(new_state: ^State) {
  25. s = new_state
  26. }
  27. _clear :: proc(color: Color) {
  28. rl.ClearBackground(rl.Color(color))
  29. }
  30. s: ^State
  31. State :: struct {
  32. textures: [dynamic]rl.Texture,
  33. allocator: runtime.Allocator,
  34. implicitly_created: bool,
  35. }
  36. _load_texture :: proc(filename: string) -> Texture {
  37. tex := rl.LoadTexture(temp_cstring(filename))
  38. if tex.id == 0 {
  39. return {}
  40. }
  41. if len(s.textures) == 0 {
  42. append(&s.textures, rl.Texture{})
  43. }
  44. tex_id := Texture_Handle(len(s.textures))
  45. append(&s.textures, tex)
  46. return {
  47. id = tex_id,
  48. width = int(tex.width),
  49. height = int(tex.height),
  50. }
  51. }
  52. _destroy_texture :: proc(tex: Texture) {
  53. if tex.id < 1 || int(tex.id) >= len(s.textures) {
  54. return
  55. }
  56. rl.UnloadTexture(s.textures[tex.id])
  57. s.textures[tex.id] = {}
  58. }
  59. _draw_texture :: proc(tex: Texture, pos: Vec2, tint := WHITE) {
  60. _draw_texture_ex(
  61. tex,
  62. {0, 0, f32(tex.width), f32(tex.height)},
  63. {pos.x, pos.y, f32(tex.width), f32(tex.height)},
  64. {},
  65. 0,
  66. tint,
  67. )
  68. }
  69. _draw_texture_rect :: proc(tex: Texture, rect: Rect, pos: Vec2, tint := WHITE) {
  70. _draw_texture_ex(
  71. tex,
  72. rect,
  73. {pos.x, pos.y, rect.w, rect.h},
  74. {},
  75. 0,
  76. tint,
  77. )
  78. }
  79. _draw_texture_ex :: proc(tex: Texture, src: Rect, dst: Rect, origin: Vec2, rot: f32, tint := WHITE) {
  80. if tex.id == 0 {
  81. log.error("Invalid texture.")
  82. return
  83. }
  84. rl.DrawTexturePro(
  85. s.textures[tex.id],
  86. transmute(rl.Rectangle)(src),
  87. transmute(rl.Rectangle)(dst),
  88. origin,
  89. rot,
  90. rl.Color(tint),
  91. )
  92. }
  93. _draw_rectangle :: proc(rect: Rect, color: Color) {
  94. rl.DrawRectangleRec(rl_rect(rect), rl_color(color))
  95. }
  96. _draw_rectangle_outline :: proc(rect: Rect, thickness: f32, color: Color) {
  97. rl.DrawRectangleLinesEx(rl_rect(rect), thickness, rl_color(color))
  98. }
  99. _draw_circle :: proc(center: Vec2, radius: f32, color: Color) {
  100. rl.DrawCircleV(center, radius, rl_color(color))
  101. }
  102. _draw_line :: proc(start: Vec2, end: Vec2, thickness: f32, color: Color) {
  103. rl.DrawLineEx(start, end, thickness, rl_color(color))
  104. }
  105. _get_screen_width :: proc() -> int {
  106. return int(rl.GetScreenWidth())
  107. }
  108. _get_screen_height :: proc() -> int {
  109. return int(rl.GetScreenHeight())
  110. }
  111. _key_pressed :: proc(key: Keyboard_Key) -> bool {
  112. return rl.IsKeyPressed(rl.KeyboardKey(key))
  113. }
  114. _key_released :: proc(key: Keyboard_Key) -> bool {
  115. return rl.IsKeyReleased(rl.KeyboardKey(key))
  116. }
  117. _key_held :: proc(key: Keyboard_Key) -> bool {
  118. return rl.IsKeyDown(rl.KeyboardKey(key))
  119. }
  120. _window_should_close :: proc() -> bool {
  121. return rl.WindowShouldClose()
  122. }
  123. rl_texture :: proc(tex: Texture) -> rl.Texture {
  124. if tex.id < 1 || int(tex.id) >= len(s.textures) {
  125. return {}
  126. }
  127. return s.textures[tex.id]
  128. }
  129. rl_rect :: proc(r: Rect) -> rl.Rectangle {
  130. return transmute(rl.Rectangle)(r)
  131. }
  132. rl_color :: proc(c: Color) -> rl.Color {
  133. return (rl.Color)(c)
  134. }
  135. _draw_text :: proc(text: string, pos: Vec2, font_size: f32, color: Color) {
  136. rl.DrawTextEx(rl.GetFontDefault(), temp_cstring(text), pos, font_size, 1, rl_color(color))
  137. }
  138. _mouse_button_pressed :: proc(button: Mouse_Button) -> bool {
  139. return rl.IsMouseButtonPressed(rl.MouseButton(button))
  140. }
  141. _mouse_button_released :: proc(button: Mouse_Button) -> bool {
  142. return rl.IsMouseButtonReleased(rl.MouseButton(button))
  143. }
  144. _mouse_button_held :: proc(button: Mouse_Button) -> bool {
  145. return rl.IsMouseButtonDown(rl.MouseButton(button))
  146. }
  147. _mouse_wheel_delta :: proc() -> f32 {
  148. return rl.GetMouseWheelMove()
  149. }
  150. _mouse_position :: proc() -> Vec2 {
  151. return rl.GetMousePosition()
  152. }
  153. _enable_scissor :: proc(x, y, w, h: int) {
  154. rl.BeginScissorMode(i32(x), i32(y), i32(w), i32(h))
  155. }
  156. _disable_scissor :: proc() {
  157. rl.EndScissorMode()
  158. }
  159. _set_window_size :: proc(width: int, height: int) {
  160. rl.SetWindowSize(i32(width), i32(height))
  161. }
  162. _set_window_position :: proc(x: int, y: int) {
  163. rl.SetWindowPosition(i32(x), i32(y))
  164. }
  165. _screen_to_world :: proc(pos: Vec2, camera: Camera) -> Vec2 {
  166. return rl.GetScreenToWorld2D(pos, rl_camera(camera))
  167. }
  168. rl_camera :: proc(camera: Camera) -> rl.Camera2D {
  169. return {
  170. offset = camera.origin,
  171. target = camera.target,
  172. rotation = camera.rotation,
  173. zoom = camera.zoom,
  174. }
  175. }
  176. _set_camera :: proc(camera: Maybe(Camera)) {
  177. // TODO: Only do something if the camera is actually different.
  178. rlgl.DrawRenderBatchActive()
  179. rlgl.LoadIdentity()
  180. if c, c_ok := camera.?; c_ok {
  181. camera_mat := rl.MatrixToFloatV(rl.GetCameraMatrix2D(rl_camera(c)))
  182. rlgl.MultMatrixf(&camera_mat[0])
  183. }
  184. }
  185. _set_scissor_rect :: proc(scissor_rect: Maybe(Rect)) {
  186. // TODO: Only do something if the scissor rect is actually different
  187. rlgl.DrawRenderBatchActive()
  188. if s, s_ok := scissor_rect.?; s_ok {
  189. rl.BeginScissorMode(i32(s.x), i32(s.y), i32(s.w), i32(s.h))
  190. } else {
  191. rlgl.DisableScissorTest()
  192. }
  193. }
  194. _process_events :: proc() {
  195. rl.PollInputEvents()
  196. }
  197. _flush_batch :: proc() {
  198. rlgl.DrawRenderBatchActive()
  199. }
  200. _present :: proc(do_flush := true) {
  201. if do_flush {
  202. rlgl.DrawRenderBatchActive()
  203. }
  204. rl.SwapScreenBuffer()
  205. }