sys.ts 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474
  1. type sys_callback_t = {
  2. f?: () => void;
  3. };
  4. type sys_string_callback_t = {
  5. f?: (s: string) => void;
  6. };
  7. type callback_t = {
  8. f?: (data?: any) => void;
  9. data?: any;
  10. };
  11. let _sys_foreground_listeners: sys_callback_t[] = [];
  12. let _sys_resume_listeners: sys_callback_t[] = [];
  13. let _sys_pause_listeners: sys_callback_t[] = [];
  14. let _sys_background_listeners: sys_callback_t[] = [];
  15. let _sys_shutdown_listeners: sys_callback_t[] = [];
  16. let _sys_drop_files_listeners: sys_string_callback_t[] = [];
  17. let _sys_start_time: f32;
  18. let _sys_window_title: string;
  19. let _sys_shaders: map_t<string, gpu_shader_t> = map_create();
  20. declare type iron_window_options_t = {
  21. title?: string;
  22. x?: i32;
  23. y?: i32;
  24. width?: i32;
  25. height?: i32;
  26. features?: window_features_t;
  27. mode?: iron_window_mode_t;
  28. frequency?: i32;
  29. vsync?: bool;
  30. display_index?: i32;
  31. visible?: bool;
  32. color_bits?: i32;
  33. depth_bits?: i32;
  34. };
  35. function sys_start(ops: iron_window_options_t) {
  36. _iron_init(ops);
  37. _sys_start_time = iron_time();
  38. draw_init(iron_load_blob(data_path() + "draw_image.vert" + sys_shader_ext()), iron_load_blob(data_path() + "draw_image.frag" + sys_shader_ext()),
  39. iron_load_blob(data_path() + "draw_image_transform.vert" + sys_shader_ext()),
  40. iron_load_blob(data_path() + "draw_image_transform.frag" + sys_shader_ext()), iron_load_blob(data_path() + "draw_rect.vert" + sys_shader_ext()),
  41. iron_load_blob(data_path() + "draw_rect.frag" + sys_shader_ext()), iron_load_blob(data_path() + "draw_tris.vert" + sys_shader_ext()),
  42. iron_load_blob(data_path() + "draw_tris.frag" + sys_shader_ext()), iron_load_blob(data_path() + "draw_text.vert" + sys_shader_ext()),
  43. iron_load_blob(data_path() + "draw_text.frag" + sys_shader_ext()));
  44. _iron_set_update_callback(sys_render);
  45. _iron_set_drop_files_callback(sys_drop_files_callback);
  46. iron_set_application_state_callback(sys_foreground_callback, sys_resume_callback, sys_pause_callback, sys_background_callback, sys_shutdown_callback);
  47. iron_set_keyboard_down_callback(sys_keyboard_down_callback);
  48. iron_set_keyboard_up_callback(sys_keyboard_up_callback);
  49. iron_set_mouse_down_callback(sys_mouse_down_callback);
  50. iron_set_mouse_up_callback(sys_mouse_up_callback);
  51. iron_set_mouse_move_callback(sys_mouse_move_callback);
  52. iron_set_mouse_wheel_callback(sys_mouse_wheel_callback);
  53. iron_set_touch_down_callback(sys_touch_down_callback);
  54. iron_set_touch_up_callback(sys_touch_up_callback);
  55. iron_set_touch_move_callback(sys_touch_move_callback);
  56. iron_set_pen_down_callback(sys_pen_down_callback);
  57. iron_set_pen_up_callback(sys_pen_up_callback);
  58. iron_set_pen_move_callback(sys_pen_move_callback);
  59. /// if WITH_GAMEPAD
  60. iron_set_gamepad_axis_callback(sys_gamepad_axis_callback);
  61. iron_set_gamepad_button_callback(sys_gamepad_button_callback);
  62. /// end
  63. input_register();
  64. }
  65. function _sys_callback_create(f: () => void): sys_callback_t {
  66. let cb: sys_callback_t = {};
  67. cb.f = f;
  68. return cb;
  69. }
  70. function sys_notify_on_app_state(on_foreground: () => void, on_resume: () => void, on_pause: () => void, on_background: () => void, on_shutdown: () => void) {
  71. if (on_foreground != null) {
  72. array_push(_sys_foreground_listeners, _sys_callback_create(on_foreground));
  73. }
  74. if (on_resume != null) {
  75. array_push(_sys_resume_listeners, _sys_callback_create(on_resume));
  76. }
  77. if (on_pause != null) {
  78. array_push(_sys_pause_listeners, _sys_callback_create(on_pause));
  79. }
  80. if (on_background != null) {
  81. array_push(_sys_background_listeners, _sys_callback_create(on_background));
  82. }
  83. if (on_shutdown != null) {
  84. array_push(_sys_shutdown_listeners, _sys_callback_create(on_shutdown));
  85. }
  86. }
  87. function sys_notify_on_drop_files(drop_files_listener: (s: string) => void) {
  88. let cb: sys_string_callback_t = {};
  89. cb.f = drop_files_listener;
  90. array_push(_sys_drop_files_listeners, cb);
  91. }
  92. function sys_foreground() {
  93. for (let i: i32 = 0; i < _sys_foreground_listeners.length; ++i) {
  94. _sys_foreground_listeners[i].f();
  95. }
  96. input_on_foreground();
  97. }
  98. function sys_resume() {
  99. for (let i: i32 = 0; i < _sys_resume_listeners.length; ++i) {
  100. _sys_resume_listeners[i].f();
  101. }
  102. }
  103. function sys_pause() {
  104. for (let i: i32 = 0; i < _sys_pause_listeners.length; ++i) {
  105. _sys_pause_listeners[i].f();
  106. }
  107. }
  108. function sys_background() {
  109. for (let i: i32 = 0; i < _sys_background_listeners.length; ++i) {
  110. _sys_background_listeners[i].f();
  111. }
  112. }
  113. function sys_shutdown() {
  114. for (let i: i32 = 0; i < _sys_shutdown_listeners.length; ++i) {
  115. _sys_shutdown_listeners[i].f();
  116. }
  117. }
  118. function sys_drop_files(file_path: string) {
  119. for (let i: i32 = 0; i < _sys_drop_files_listeners.length; ++i) {
  120. _sys_drop_files_listeners[i].f(file_path);
  121. }
  122. }
  123. function sys_time(): f32 {
  124. return iron_time() - _sys_start_time;
  125. }
  126. function sys_drop_files_callback(file_path: string) {
  127. sys_drop_files(file_path);
  128. }
  129. function sys_foreground_callback() {
  130. sys_foreground();
  131. }
  132. function sys_resume_callback() {
  133. sys_resume();
  134. }
  135. function sys_pause_callback() {
  136. sys_pause();
  137. }
  138. function sys_background_callback() {
  139. sys_background();
  140. }
  141. function sys_shutdown_callback() {
  142. sys_shutdown();
  143. }
  144. function sys_keyboard_down_callback(code: i32) {
  145. keyboard_down_listener(code);
  146. }
  147. function sys_keyboard_up_callback(code: i32) {
  148. keyboard_up_listener(code);
  149. }
  150. function sys_mouse_down_callback(button: i32, x: i32, y: i32) {
  151. mouse_down_listener(button, x, y);
  152. }
  153. function sys_mouse_up_callback(button: i32, x: i32, y: i32) {
  154. mouse_up_listener(button, x, y);
  155. }
  156. function sys_mouse_move_callback(x: i32, y: i32, mx: i32, my: i32) {
  157. mouse_move_listener(x, y, mx, my);
  158. }
  159. function sys_mouse_wheel_callback(delta: f32) {
  160. mouse_wheel_listener(delta);
  161. }
  162. function sys_touch_down_callback(index: i32, x: i32, y: i32) {
  163. /// if (arm_android || arm_ios)
  164. mouse_on_touch_down(index, x, y);
  165. /// end
  166. }
  167. function sys_touch_up_callback(index: i32, x: i32, y: i32) {
  168. /// if (arm_android || arm_ios)
  169. mouse_on_touch_up(index, x, y);
  170. /// end
  171. }
  172. function sys_touch_move_callback(index: i32, x: i32, y: i32) {
  173. /// if (arm_android || arm_ios)
  174. mouse_on_touch_move(index, x, y);
  175. /// end
  176. }
  177. function sys_pen_down_callback(x: i32, y: i32, pressure: f32) {
  178. pen_down_listener(x, y, pressure);
  179. }
  180. function sys_pen_up_callback(x: i32, y: i32, pressure: f32) {
  181. pen_up_listener(x, y, pressure);
  182. }
  183. function sys_pen_move_callback(x: i32, y: i32, pressure: f32) {
  184. pen_move_listener(x, y, pressure);
  185. }
  186. /// if WITH_GAMEPAD
  187. function sys_gamepad_axis_callback(gamepad: i32, axis: i32, value: f32) {
  188. gamepad_axis_listener(gamepad, axis, value);
  189. }
  190. function sys_gamepad_button_callback(gamepad: i32, button: i32, value: f32) {
  191. gamepad_button_listener(gamepad, button, value);
  192. }
  193. /// end
  194. function sys_title(): string {
  195. return _sys_window_title;
  196. }
  197. function sys_title_set(value: string) {
  198. iron_window_set_title(value);
  199. _sys_window_title = value;
  200. }
  201. function sys_display_primary_id(): i32 {
  202. for (let i: i32 = 0; i < iron_count_displays(); ++i) {
  203. if (iron_display_is_primary(i)) {
  204. return i;
  205. }
  206. }
  207. return 0;
  208. }
  209. function sys_display_width(): i32 {
  210. return iron_display_width(sys_display_primary_id());
  211. }
  212. function sys_display_height(): i32 {
  213. return iron_display_height(sys_display_primary_id());
  214. }
  215. function sys_display_frequency(): i32 {
  216. return iron_display_frequency(sys_display_primary_id());
  217. }
  218. function sys_buffer_to_string(b: buffer_t): string {
  219. let str: string = string_alloc(b.length + 1);
  220. memcpy(str, b.buffer, b.length);
  221. return str;
  222. }
  223. function sys_string_to_buffer(str: string): buffer_t {
  224. let b: u8_array_t = u8_array_create(str.length);
  225. memcpy(b.buffer, str, str.length);
  226. return b;
  227. }
  228. function sys_shader_ext(): string {
  229. /// if arm_vulkan
  230. return ".spirv";
  231. /// elseif arm_metal
  232. return ".metal";
  233. /// elseif arm_webgpu
  234. return ".wgsl";
  235. /// else
  236. return ".d3d11";
  237. /// end
  238. }
  239. function sys_get_shader(name: string): gpu_shader_t {
  240. let shader: gpu_shader_t = map_get(_sys_shaders, name);
  241. if (shader == null) {
  242. shader =
  243. gpu_create_shader(iron_load_blob(data_path() + name + sys_shader_ext()), ends_with(name, ".frag") ? gpu_shader_type_t.FRAGMENT : gpu_shader_type_t.VERTEX);
  244. map_set(_sys_shaders, name, shader);
  245. }
  246. return shader;
  247. }
  248. function video_unload(self: video_t) {}
  249. /// if arm_audio
  250. function sound_create(sound_: any): sound_t {
  251. let raw: sound_t = {};
  252. raw.sound_ = sound_;
  253. return raw;
  254. }
  255. function sound_unload(raw: sound_t) {
  256. iron_a1_sound_destroy(raw.sound_);
  257. }
  258. /// end
  259. type color_t = i32;
  260. type video_t = {
  261. video_?: any;
  262. };
  263. type sound_t = {
  264. sound_?: any;
  265. };
  266. enum window_features_t {
  267. NONE = 0,
  268. RESIZABLE = 1,
  269. MINIMIZABLE = 2,
  270. MAXIMIZABLE = 4,
  271. }
  272. declare enum iron_window_mode_t {
  273. WINDOW,
  274. FULLSCREEN,
  275. }
  276. let _sys_on_next_frames: callback_t[] = [];
  277. let _sys_on_end_frames: callback_t[] = [];
  278. let _sys_on_updates: callback_t[] = [];
  279. let _sys_on_renders: callback_t[] = [];
  280. let _sys_lastw: i32 = -1;
  281. let _sys_lasth: i32 = -1;
  282. let sys_on_resize: () => void = null;
  283. let sys_on_w: () => i32 = null;
  284. let sys_on_h: () => i32 = null;
  285. let sys_on_x: () => i32 = null;
  286. let sys_on_y: () => i32 = null;
  287. function sys_w(): i32 {
  288. if (sys_on_w != null) {
  289. return sys_on_w();
  290. }
  291. return iron_window_width();
  292. }
  293. function sys_h(): i32 {
  294. if (sys_on_h != null) {
  295. return sys_on_h();
  296. }
  297. return iron_window_height();
  298. }
  299. function sys_x(): i32 {
  300. if (sys_on_x != null) {
  301. return sys_on_x();
  302. }
  303. return 0;
  304. }
  305. function sys_y(): i32 {
  306. if (sys_on_y != null) {
  307. return sys_on_y();
  308. }
  309. return 0;
  310. }
  311. function _sys_run_callbacks(cbs: callback_t[]) {
  312. for (let i: i32 = 0; i < cbs.length; ++i) {
  313. let cb: callback_t = cbs[i];
  314. cb.f(cb.data);
  315. }
  316. }
  317. let _sys_time_last: f32 = 0.0;
  318. let _sys_time_real_delta: f32 = 0.0;
  319. let _sys_time_frequency: i32 = -1;
  320. function sys_delta(): f32 {
  321. if (_sys_time_frequency < 0) {
  322. _sys_time_frequency = sys_display_frequency();
  323. }
  324. return (1 / _sys_time_frequency);
  325. }
  326. function sys_real_delta(): f32 {
  327. return _sys_time_real_delta;
  328. }
  329. function sys_render() {
  330. if (_sys_on_next_frames.length > 0) {
  331. _sys_run_callbacks(_sys_on_next_frames);
  332. array_splice(_sys_on_next_frames, 0, _sys_on_next_frames.length);
  333. }
  334. _sys_run_callbacks(_sys_on_updates);
  335. if (iron_window_width() > 0 && iron_window_height() > 0) {
  336. scene_render_frame();
  337. _sys_run_callbacks(_sys_on_renders);
  338. }
  339. if (_sys_on_end_frames.length > 0) {
  340. _sys_run_callbacks(_sys_on_end_frames);
  341. array_splice(_sys_on_end_frames, 0, _sys_on_end_frames.length);
  342. }
  343. input_end_frame();
  344. // Rebuild projection on window resize
  345. if (_sys_lastw == -1) {
  346. _sys_lastw = sys_w();
  347. _sys_lasth = sys_h();
  348. }
  349. if (_sys_lastw != sys_w() || _sys_lasth != sys_h()) {
  350. if (sys_on_resize != null) {
  351. sys_on_resize();
  352. }
  353. }
  354. _sys_lastw = sys_w();
  355. _sys_lasth = sys_h();
  356. _sys_time_real_delta = sys_time() - _sys_time_last;
  357. _sys_time_last = sys_time();
  358. }
  359. function _callback_create(f: (data?: any) => void, data: any): callback_t {
  360. let cb: callback_t = {};
  361. cb.f = f;
  362. cb.data = data;
  363. return cb;
  364. }
  365. // Hooks
  366. function sys_notify_on_update(f: (data?: any) => void, data: any = null) {
  367. array_push(_sys_on_updates, _callback_create(f, data));
  368. }
  369. function sys_notify_on_render(f: (data?: any) => void, data: any = null) {
  370. array_push(_sys_on_renders, _callback_create(f, data));
  371. }
  372. function sys_notify_on_next_frame(f: (data?: any) => void, data: any = null) {
  373. array_push(_sys_on_next_frames, _callback_create(f, data));
  374. }
  375. function sys_notify_on_end_frame(f: (data?: any) => void, data: any = null) {
  376. array_push(_sys_on_end_frames, _callback_create(f, data));
  377. }
  378. function _sys_remove_callback(ar: callback_t[], f: (data?: any) => void) {
  379. for (let i: i32 = 0; i < ar.length; ++i) {
  380. if (ar[i].f == f) {
  381. array_splice(ar, i, 1);
  382. break;
  383. }
  384. }
  385. }
  386. function sys_remove_update(f: (data?: any) => void) {
  387. _sys_remove_callback(_sys_on_updates, f);
  388. }
  389. function sys_remove_render(f: (data?: any) => void) {
  390. _sys_remove_callback(_sys_on_renders, f);
  391. }
  392. function sys_remove_end_frame(f: (data?: any) => void) {
  393. _sys_remove_callback(_sys_on_end_frames, f);
  394. }