iron_system.c 19 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621
  1. #include "iron_system.h"
  2. #include <stdio.h>
  3. #include <stdlib.h>
  4. #include <string.h>
  5. #ifdef IRON_WINDOWS
  6. #include <backends/windows_mini.h>
  7. #include <backends/windows_system.h>
  8. #endif
  9. #ifdef IRON_ANDROID
  10. #include <android/log.h>
  11. #endif
  12. #include <iron_file.h>
  13. #include <memory.h>
  14. #include <stddef.h>
  15. typedef enum {
  16. IRON_LOG_LEVEL_INFO,
  17. IRON_LOG_LEVEL_ERROR
  18. } iron_log_level_t;
  19. void iron_log_args(iron_log_level_t level, const char *format, va_list args) {
  20. #ifdef IRON_WASM
  21. printf(format);
  22. return;
  23. #endif
  24. #ifdef IRON_ANDROID
  25. va_list args_android_copy;
  26. va_copy(args_android_copy, args);
  27. switch (level) {
  28. case IRON_LOG_LEVEL_INFO:
  29. __android_log_vprint(ANDROID_LOG_INFO, "Iron", format, args_android_copy);
  30. break;
  31. case IRON_LOG_LEVEL_ERROR:
  32. __android_log_vprint(ANDROID_LOG_ERROR, "Iron", format, args_android_copy);
  33. break;
  34. }
  35. va_end(args_android_copy);
  36. #endif
  37. #ifdef IRON_WINDOWS
  38. wchar_t buffer[4096];
  39. iron_microsoft_format(format, args, buffer);
  40. wcscat(buffer, L"\r\n");
  41. OutputDebugStringW(buffer);
  42. DWORD written;
  43. WriteConsoleW(GetStdHandle(level == IRON_LOG_LEVEL_INFO ? STD_OUTPUT_HANDLE : STD_ERROR_HANDLE), buffer, (DWORD)wcslen(buffer), &written, NULL);
  44. #else
  45. char buffer[4096];
  46. vsnprintf(buffer, 4090, format, args);
  47. strcat(buffer, "\n");
  48. fprintf(level == IRON_LOG_LEVEL_INFO ? stdout : stderr, "%s", buffer);
  49. #endif
  50. }
  51. void iron_log(const char *format, ...) {
  52. va_list args;
  53. va_start(args, format);
  54. iron_log_args(IRON_LOG_LEVEL_INFO, format == NULL ? "null" : format, args);
  55. va_end(args);
  56. }
  57. void iron_error(const char *format, ...) {
  58. {
  59. va_list args;
  60. va_start(args, format);
  61. iron_log_args(IRON_LOG_LEVEL_ERROR, format, args);
  62. va_end(args);
  63. }
  64. #ifdef IRON_WINDOWS
  65. {
  66. va_list args;
  67. va_start(args, format);
  68. wchar_t buffer[4096];
  69. iron_microsoft_format(format, args, buffer);
  70. MessageBoxW(NULL, buffer, L"Error", 0);
  71. va_end(args);
  72. }
  73. #endif
  74. }
  75. #if !defined(IRON_WASM) && !defined(IRON_ANDROID) && !defined(IRON_WINDOWS)
  76. double iron_time(void) {
  77. return iron_timestamp() / iron_frequency();
  78. }
  79. #endif
  80. static void (*update_callback)(void) = NULL;
  81. static void (*foreground_callback)(void *) = NULL;
  82. static void *foreground_callback_data = NULL;
  83. static void (*background_callback)(void *) = NULL;
  84. static void *background_callback_data = NULL;
  85. static void (*pause_callback)(void *) = NULL;
  86. static void *pause_callback_data = NULL;
  87. static void (*resume_callback)(void *) = NULL;
  88. static void *resume_callback_data = NULL;
  89. static void (*shutdown_callback)(void *) = NULL;
  90. static void *shutdown_callback_data = NULL;
  91. static void (*drop_files_callback)(char *, void *) = NULL;
  92. static void *drop_files_callback_data = NULL;
  93. static char *(*cut_callback)(void *) = NULL;
  94. static void *cut_callback_data = NULL;
  95. static char *(*copy_callback)(void *) = NULL;
  96. static void *copy_callback_data = NULL;
  97. static void (*paste_callback)(char *, void *) = NULL;
  98. static void *paste_callback_data = NULL;
  99. #if defined(IRON_IOS) || defined(IRON_MACOS)
  100. bool with_autoreleasepool(bool (*f)(void));
  101. #endif
  102. void iron_set_update_callback(void (*callback)(void)) {
  103. update_callback = callback;
  104. }
  105. void iron_set_foreground_callback(void (*callback)(void *), void *data) {
  106. foreground_callback = callback;
  107. foreground_callback_data = data;
  108. }
  109. void iron_set_resume_callback(void (*callback)(void *), void *data) {
  110. resume_callback = callback;
  111. resume_callback_data = data;
  112. }
  113. void iron_set_pause_callback(void (*callback)(void *), void *data) {
  114. pause_callback = callback;
  115. pause_callback_data = data;
  116. }
  117. void iron_set_background_callback(void (*callback)(void *), void *data) {
  118. background_callback = callback;
  119. background_callback_data = data;
  120. }
  121. void iron_set_shutdown_callback(void (*callback)(void *), void *data) {
  122. shutdown_callback = callback;
  123. shutdown_callback_data = data;
  124. }
  125. void iron_set_drop_files_callback(void (*callback)(char *, void *), void *data) {
  126. drop_files_callback = callback;
  127. drop_files_callback_data = data;
  128. }
  129. void iron_set_cut_callback(char *(*callback)(void *), void *data) {
  130. cut_callback = callback;
  131. cut_callback_data = data;
  132. }
  133. void iron_set_copy_callback(char *(*callback)(void *), void *data) {
  134. copy_callback = callback;
  135. copy_callback_data = data;
  136. }
  137. void iron_set_paste_callback(void (*callback)(char *, void *), void *data) {
  138. paste_callback = callback;
  139. paste_callback_data = data;
  140. }
  141. void iron_internal_update_callback(void) {
  142. if (update_callback != NULL) {
  143. update_callback();
  144. }
  145. }
  146. void iron_internal_foreground_callback(void) {
  147. if (foreground_callback != NULL) {
  148. foreground_callback(foreground_callback_data);
  149. }
  150. }
  151. void iron_internal_resume_callback(void) {
  152. if (resume_callback != NULL) {
  153. resume_callback(resume_callback_data);
  154. }
  155. }
  156. void iron_internal_pause_callback(void) {
  157. if (pause_callback != NULL) {
  158. pause_callback(pause_callback_data);
  159. }
  160. }
  161. void iron_internal_background_callback(void) {
  162. if (background_callback != NULL) {
  163. background_callback(background_callback_data);
  164. }
  165. }
  166. void iron_internal_shutdown_callback(void) {
  167. if (shutdown_callback != NULL) {
  168. shutdown_callback(shutdown_callback_data);
  169. }
  170. }
  171. void iron_internal_drop_files_callback(char *filePath) {
  172. if (drop_files_callback != NULL) {
  173. drop_files_callback(filePath, drop_files_callback_data);
  174. }
  175. }
  176. char *iron_internal_cut_callback(void) {
  177. if (cut_callback != NULL) {
  178. return cut_callback(cut_callback_data);
  179. }
  180. return NULL;
  181. }
  182. char *iron_internal_copy_callback(void) {
  183. if (copy_callback != NULL) {
  184. return copy_callback(copy_callback_data);
  185. }
  186. return NULL;
  187. }
  188. void iron_internal_paste_callback(char *value) {
  189. if (paste_callback != NULL) {
  190. paste_callback(value, paste_callback_data);
  191. }
  192. }
  193. static bool running = false;
  194. static char application_name[1024] = {"Iron Application"};
  195. const char *iron_application_name(void) {
  196. return application_name;
  197. }
  198. void iron_set_app_name(const char *name) {
  199. strcpy(application_name, name);
  200. }
  201. void iron_stop(void) {
  202. running = false;
  203. }
  204. bool iron_internal_frame(void) {
  205. iron_internal_update_callback();
  206. iron_internal_handle_messages();
  207. return running;
  208. }
  209. void iron_start(void) {
  210. running = true;
  211. #if !defined(IRON_WASM)
  212. #if defined(IRON_IOS) || defined(IRON_MACOS)
  213. while (with_autoreleasepool(iron_internal_frame)) {
  214. }
  215. #else
  216. while (iron_internal_frame()) {
  217. }
  218. #endif
  219. iron_internal_shutdown();
  220. #endif
  221. }
  222. static uint8_t *current_file = NULL;
  223. static size_t current_file_size = 0;
  224. bool iron_save_file_loaded(void) {
  225. return true;
  226. }
  227. uint8_t *iron_get_save_file(void) {
  228. return current_file;
  229. }
  230. size_t iron_get_save_file_size(void) {
  231. return current_file_size;
  232. }
  233. void iron_load_save_file(const char *filename) {
  234. free(current_file);
  235. current_file = NULL;
  236. current_file_size = 0;
  237. iron_file_reader_t reader;
  238. if (iron_file_reader_open(&reader, filename, IRON_FILE_TYPE_SAVE)) {
  239. current_file_size = iron_file_reader_size(&reader);
  240. current_file = (uint8_t *)malloc(current_file_size);
  241. iron_file_reader_read(&reader, current_file, current_file_size);
  242. iron_file_reader_close(&reader);
  243. }
  244. }
  245. void iron_save_save_file(const char *filename, uint8_t *data, size_t size) {
  246. iron_file_writer_t writer;
  247. if (iron_file_writer_open(&writer, filename)) {
  248. iron_file_writer_write(&writer, data, (int)size);
  249. iron_file_writer_close(&writer);
  250. }
  251. }
  252. bool iron_save_is_saving(void) {
  253. return false;
  254. }
  255. #if !defined(IRON_WINDOWS) && !defined(IRON_LINUX) && !defined(IRON_MACOS)
  256. void iron_copy_to_clipboard(const char *text) {
  257. iron_log("Oh no, iron_copy_to_clipboard is not implemented for this system.");
  258. }
  259. #endif
  260. static void (*keyboard_key_down_callback)(int /*key_code*/, void * /*data*/) = NULL;
  261. static void *keyboard_key_down_callback_data = NULL;
  262. static void (*keyboard_key_up_callback)(int /*key_code*/, void * /*data*/) = NULL;
  263. static void *keyboard_key_up_callback_data = NULL;
  264. static void (*keyboard_key_press_callback)(unsigned /*character*/, void * /*data*/) = NULL;
  265. static void *keyboard_key_press_callback_data = NULL;
  266. void iron_keyboard_set_key_down_callback(void (*value)(int /*key_code*/, void * /*data*/), void *data) {
  267. keyboard_key_down_callback = value;
  268. keyboard_key_down_callback_data = data;
  269. }
  270. void iron_keyboard_set_key_up_callback(void (*value)(int /*key_code*/, void * /*data*/), void *data) {
  271. keyboard_key_up_callback = value;
  272. keyboard_key_up_callback_data = data;
  273. }
  274. void iron_keyboard_set_key_press_callback(void (*value)(unsigned /*character*/, void * /*data*/), void *data) {
  275. keyboard_key_press_callback = value;
  276. keyboard_key_press_callback_data = data;
  277. }
  278. void iron_internal_keyboard_trigger_key_down(int key_code) {
  279. if (keyboard_key_down_callback != NULL) {
  280. keyboard_key_down_callback(key_code, keyboard_key_down_callback_data);
  281. }
  282. }
  283. void iron_internal_keyboard_trigger_key_up(int key_code) {
  284. if (keyboard_key_up_callback != NULL) {
  285. keyboard_key_up_callback(key_code, keyboard_key_up_callback_data);
  286. }
  287. }
  288. void iron_internal_keyboard_trigger_key_press(unsigned character) {
  289. if (keyboard_key_press_callback != NULL) {
  290. keyboard_key_press_callback(character, keyboard_key_press_callback_data);
  291. }
  292. }
  293. static void (*mouse_press_callback)(int /*button*/, int /*x*/, int /*y*/, void * /*data*/) = NULL;
  294. static void *mouse_press_callback_data = NULL;
  295. static void (*mouse_release_callback)(int /*button*/, int /*x*/, int /*y*/, void * /*data*/) = NULL;
  296. static void *mouse_release_callback_data = NULL;
  297. static void (*mouse_move_callback)(int /*x*/, int /*y*/, int /*movementX*/, int /*movementY*/, void * /*data*/) = NULL;
  298. static void *mouse_move_callback_data = NULL;
  299. static void (*mouse_scroll_callback)(float /*delta*/, void * /*data*/) = NULL;
  300. static void *mouse_scroll_callback_data = NULL;
  301. void iron_mouse_set_press_callback(void (*value)(int /*button*/, int /*x*/, int /*y*/, void * /*data*/), void *data) {
  302. mouse_press_callback = value;
  303. mouse_press_callback_data = data;
  304. }
  305. void iron_mouse_set_release_callback(void (*value)(int /*button*/, int /*x*/, int /*y*/, void * /*data*/), void *data) {
  306. mouse_release_callback = value;
  307. mouse_release_callback_data = data;
  308. }
  309. void iron_mouse_set_move_callback(void (*value)(int /*x*/, int /*y*/, int /*movement_x*/, int /*movement_y*/, void * /*data*/), void *data) {
  310. mouse_move_callback = value;
  311. mouse_move_callback_data = data;
  312. }
  313. void iron_mouse_set_scroll_callback(void (*value)(float /*delta*/, void * /*data*/), void *data) {
  314. mouse_scroll_callback = value;
  315. mouse_scroll_callback_data = data;
  316. }
  317. void iron_internal_mouse_trigger_release(int button, int x, int y) {
  318. if (mouse_release_callback != NULL) {
  319. mouse_release_callback(button, x, y, mouse_release_callback_data);
  320. }
  321. }
  322. void iron_internal_mouse_trigger_scroll(float delta) {
  323. if (mouse_scroll_callback != NULL) {
  324. mouse_scroll_callback(delta, mouse_scroll_callback_data);
  325. }
  326. }
  327. void iron_internal_mouse_window_activated() {
  328. if (iron_mouse_is_locked()) {
  329. iron_mouse_hide();
  330. }
  331. }
  332. void iron_internal_mouse_window_deactivated() {
  333. if (iron_mouse_is_locked()) {
  334. iron_mouse_show();
  335. }
  336. }
  337. static bool moved = false;
  338. static bool locked = false;
  339. static int preLockX = 0;
  340. static int preLockY = 0;
  341. static int lastX = 0;
  342. static int lastY = 0;
  343. void iron_internal_mouse_trigger_press(int button, int x, int y) {
  344. lastX = x;
  345. lastY = y;
  346. if (mouse_press_callback != NULL) {
  347. mouse_press_callback(button, x, y, mouse_press_callback_data);
  348. }
  349. }
  350. void iron_internal_mouse_trigger_move(int x, int y) {
  351. int movementX = 0;
  352. int movementY = 0;
  353. if (iron_mouse_is_locked()) {
  354. movementX = x - preLockX;
  355. movementY = y - preLockY;
  356. if (movementX != 0 || movementY != 0) {
  357. iron_mouse_set_position(preLockX, preLockY);
  358. x = preLockX;
  359. y = preLockY;
  360. }
  361. }
  362. else if (moved) {
  363. movementX = x - lastX;
  364. movementY = y - lastY;
  365. }
  366. moved = true;
  367. lastX = x;
  368. lastY = y;
  369. if (mouse_move_callback != NULL && (movementX != 0 || movementY != 0)) {
  370. mouse_move_callback(x, y, movementX, movementY, mouse_move_callback_data);
  371. }
  372. }
  373. bool iron_mouse_is_locked(void) {
  374. return locked;
  375. }
  376. void iron_mouse_lock() {
  377. if (iron_mouse_is_locked() || !iron_mouse_can_lock()) {
  378. return;
  379. }
  380. locked = true;
  381. iron_mouse_get_position(&preLockX, &preLockY);
  382. iron_mouse_hide();
  383. }
  384. void iron_mouse_unlock(void) {
  385. if (!iron_mouse_is_locked() || !iron_mouse_can_lock()) {
  386. return;
  387. }
  388. moved = false;
  389. locked = false;
  390. iron_mouse_set_position(preLockX, preLockY);
  391. iron_mouse_show();
  392. }
  393. static void (*pen_press_callback)(int /*x*/, int /*y*/, float /*pressure*/) = NULL;
  394. static void (*pen_move_callback)(int /*x*/, int /*y*/, float /*pressure*/) = NULL;
  395. static void (*pen_release_callback)(int /*x*/, int /*y*/, float /*pressure*/) = NULL;
  396. static void (*eraser_press_callback)(int /*x*/, int /*y*/, float /*pressure*/) = NULL;
  397. static void (*eraser_move_callback)(int /*x*/, int /*y*/, float /*pressure*/) = NULL;
  398. static void (*eraser_release_callback)(int /*x*/, int /*y*/, float /*pressure*/) = NULL;
  399. void iron_pen_set_press_callback(void (*value)(int /*x*/, int /*y*/, float /*pressure*/)) {
  400. pen_press_callback = value;
  401. }
  402. void iron_pen_set_move_callback(void (*value)(int /*x*/, int /*y*/, float /*pressure*/)) {
  403. pen_move_callback = value;
  404. }
  405. void iron_pen_set_release_callback(void (*value)(int /*x*/, int /*y*/, float /*pressure*/)) {
  406. pen_release_callback = value;
  407. }
  408. void iron_eraser_set_press_callback(void (*value)(int /*x*/, int /*y*/, float /*pressure*/)) {
  409. eraser_press_callback = value;
  410. }
  411. void iron_eraser_set_move_callback(void (*value)(int /*x*/, int /*y*/, float /*pressure*/)) {
  412. eraser_move_callback = value;
  413. }
  414. void iron_eraser_set_release_callback(void (*value)(int /*x*/, int /*y*/, float /*pressure*/)) {
  415. eraser_release_callback = value;
  416. }
  417. void iron_internal_pen_trigger_press(int x, int y, float pressure) {
  418. if (pen_press_callback != NULL) {
  419. pen_press_callback(x, y, pressure);
  420. }
  421. }
  422. void iron_internal_pen_trigger_move(int x, int y, float pressure) {
  423. if (pen_move_callback != NULL) {
  424. pen_move_callback(x, y, pressure);
  425. }
  426. }
  427. void iron_internal_pen_trigger_release(int x, int y, float pressure) {
  428. if (pen_release_callback != NULL) {
  429. pen_release_callback(x, y, pressure);
  430. }
  431. }
  432. void iron_internal_eraser_trigger_press(int x, int y, float pressure) {
  433. if (eraser_press_callback != NULL) {
  434. eraser_press_callback(x, y, pressure);
  435. }
  436. }
  437. void iron_internal_eraser_trigger_move(int x, int y, float pressure) {
  438. if (eraser_move_callback != NULL) {
  439. eraser_move_callback(x, y, pressure);
  440. }
  441. }
  442. void iron_internal_eraser_trigger_release(int x, int y, float pressure) {
  443. if (eraser_release_callback != NULL) {
  444. eraser_release_callback(x, y, pressure);
  445. }
  446. }
  447. static void (*surface_touch_start_callback)(int /*index*/, int /*x*/, int /*y*/) = NULL;
  448. static void (*surface_move_callback)(int /*index*/, int /*x*/, int /*y*/) = NULL;
  449. static void (*surface_touch_end_callback)(int /*index*/, int /*x*/, int /*y*/) = NULL;
  450. void iron_surface_set_touch_start_callback(void (*value)(int /*index*/, int /*x*/, int /*y*/)) {
  451. surface_touch_start_callback = value;
  452. }
  453. void iron_surface_set_move_callback(void (*value)(int /*index*/, int /*x*/, int /*y*/)) {
  454. surface_move_callback = value;
  455. }
  456. void iron_surface_set_touch_end_callback(void (*value)(int /*index*/, int /*x*/, int /*y*/)) {
  457. surface_touch_end_callback = value;
  458. }
  459. void iron_internal_surface_trigger_touch_start(int index, int x, int y) {
  460. if (surface_touch_start_callback != NULL) {
  461. surface_touch_start_callback(index, x, y);
  462. }
  463. }
  464. void iron_internal_surface_trigger_move(int index, int x, int y) {
  465. if (surface_move_callback != NULL) {
  466. surface_move_callback(index, x, y);
  467. }
  468. }
  469. void iron_internal_surface_trigger_touch_end(int index, int x, int y) {
  470. if (surface_touch_end_callback != NULL) {
  471. surface_touch_end_callback(index, x, y);
  472. }
  473. }
  474. #ifdef WITH_GAMEPAD
  475. static void (*gamepad_connect_callback)(int /*gamepad*/, void * /*userdata*/) = NULL;
  476. static void *gamepad_connect_callback_userdata = NULL;
  477. static void (*gamepad_disconnect_callback)(int /*gamepad*/, void * /*userdata*/) = NULL;
  478. static void *gamepad_disconnect_callback_userdata = NULL;
  479. static void (*gamepad_axis_callback)(int /*gamepad*/, int /*axis*/, float /*value*/, void * /*userdata*/) = NULL;
  480. static void *gamepad_axis_callback_userdata = NULL;
  481. static void (*gamepad_button_callback)(int /*gamepad*/, int /*button*/, float /*value*/, void * /*userdata*/) = NULL;
  482. static void *gamepad_button_callback_userdata = NULL;
  483. void iron_gamepad_set_connect_callback(void (*value)(int /*gamepad*/, void * /*userdata*/), void *userdata) {
  484. gamepad_connect_callback = value;
  485. gamepad_connect_callback_userdata = userdata;
  486. }
  487. void iron_gamepad_set_disconnect_callback(void (*value)(int /*gamepad*/, void * /*userdata*/), void *userdata) {
  488. gamepad_disconnect_callback = value;
  489. gamepad_disconnect_callback_userdata = userdata;
  490. }
  491. void iron_gamepad_set_axis_callback(void (*value)(int /*gamepad*/, int /*axis*/, float /*value*/, void * /*userdata*/), void *userdata) {
  492. gamepad_axis_callback = value;
  493. gamepad_axis_callback_userdata = userdata;
  494. }
  495. void iron_gamepad_set_button_callback(void (*value)(int /*gamepad*/, int /*button*/, float /*value*/, void * /*userdata*/), void *userdata) {
  496. gamepad_button_callback = value;
  497. gamepad_button_callback_userdata = userdata;
  498. }
  499. void iron_internal_gamepad_trigger_connect(int gamepad) {
  500. if (gamepad_connect_callback != NULL) {
  501. gamepad_connect_callback(gamepad, gamepad_connect_callback_userdata);
  502. }
  503. }
  504. void iron_internal_gamepad_trigger_disconnect(int gamepad) {
  505. if (gamepad_disconnect_callback != NULL) {
  506. gamepad_disconnect_callback(gamepad, gamepad_disconnect_callback_userdata);
  507. }
  508. }
  509. void iron_internal_gamepad_trigger_axis(int gamepad, int axis, float value) {
  510. if (gamepad_axis_callback != NULL) {
  511. gamepad_axis_callback(gamepad, axis, value, gamepad_axis_callback_userdata);
  512. }
  513. }
  514. void iron_internal_gamepad_trigger_button(int gamepad, int button, float value) {
  515. if (gamepad_button_callback != NULL) {
  516. gamepad_button_callback(gamepad, button, value, gamepad_button_callback_userdata);
  517. }
  518. }
  519. #endif