karl2d_raylib.odin 6.5 KB

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