2
0

gs_platform.c 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460
  1. #include "platform/gs_platform.h"
  2. #include "base/gs_engine.h"
  3. /*============================
  4. // Platform Window
  5. ============================*/
  6. gs_resource_handle __gs_platform_create_window( const char* title, u32 width, u32 height )
  7. {
  8. struct gs_platform_i* platform = gs_engine_instance()->ctx.platform;
  9. void* win = platform->create_window_internal( title, width, height );
  10. gs_assert( win );
  11. gs_resource_handle handle = gs_slot_array_insert( platform->windows, win );
  12. gs_dyn_array_push( platform->active_window_handles, handle );
  13. return handle;
  14. }
  15. gs_resource_handle __gs_platform_main_window()
  16. {
  17. // Should be the first element of the slot array...Great assumption to make.
  18. return 0;
  19. }
  20. /*============================
  21. // Platform Input
  22. ============================*/
  23. #define __input()\
  24. ( &gs_engine_instance()->ctx.platform->input )
  25. void __gs_platform_update_input()
  26. {
  27. gs_platform_input* input = __input();
  28. // Update all input and mouse keys from previous frame
  29. // Previous key presses
  30. gs_for_range_i( gs_keycode_count )
  31. {
  32. input->prev_key_map[ i ] = input->key_map[ i ];
  33. }
  34. // Previous mouse button presses
  35. gs_for_range_i( gs_mouse_button_code_count )
  36. {
  37. input->mouse.prev_button_map[ i ] = input->mouse.button_map[ i ];
  38. }
  39. input->mouse.prev_position = input->mouse.position;
  40. input->mouse.wheel = (gs_vec2){ 0.0f, 0.0f };
  41. input->mouse.moved_this_frame = false;
  42. }
  43. b32 __gs_platform_was_key_down( gs_platform_keycode code )
  44. {
  45. gs_platform_input* input = __input();
  46. return ( input->prev_key_map[ code ] );
  47. }
  48. b32 __gs_platform_key_down( gs_platform_keycode code )
  49. {
  50. gs_platform_input* input = __input();
  51. return ( input->key_map[ code ] );
  52. }
  53. b32 __gs_platform_key_pressed( gs_platform_keycode code )
  54. {
  55. gs_platform_input* input = __input();
  56. if ( __gs_platform_key_down( code ) && !__gs_platform_was_key_down( code ) )
  57. {
  58. return true;
  59. }
  60. return false;
  61. }
  62. b32 __gs_platform_key_released( gs_platform_keycode code )
  63. {
  64. gs_platform_input* input = __input();
  65. return ( __gs_platform_was_key_down( code ) && !__gs_platform_key_down( code ) );
  66. }
  67. b32 __gs_platform_was_mouse_down( gs_platform_mouse_button_code code )
  68. {
  69. gs_platform_input* input = __input();
  70. return ( input->mouse.prev_button_map[ code ] );
  71. }
  72. void __gs_platform_press_mouse_button( gs_platform_mouse_button_code code )
  73. {
  74. gs_platform_input* input = __input();
  75. if ( (u32)code < (u32)gs_mouse_button_code_count )
  76. {
  77. input->mouse.button_map[ code ] = true;
  78. }
  79. }
  80. void __gs_platform_release_mouse_button( gs_platform_mouse_button_code code )
  81. {
  82. gs_platform_input* input = __input();
  83. if ( (u32)code < (u32)gs_mouse_button_code_count )
  84. {
  85. input->mouse.button_map[ code ] = false;
  86. }
  87. }
  88. b32 __gs_platform_mouse_down( gs_platform_mouse_button_code code )
  89. {
  90. gs_platform_input* input = __input();
  91. return ( input->mouse.button_map[ code ] );
  92. }
  93. b32 __gs_platform_mouse_pressed( gs_platform_mouse_button_code code )
  94. {
  95. gs_platform_input* input = __input();
  96. if ( __gs_platform_mouse_down( code ) && !__gs_platform_was_mouse_down( code ) )
  97. {
  98. return true;
  99. }
  100. return false;
  101. }
  102. b32 __gs_platform_mouse_released( gs_platform_mouse_button_code code )
  103. {
  104. gs_platform_input* input = __input();
  105. return ( __gs_platform_was_mouse_down( code ) && !__gs_platform_mouse_down( code ) );
  106. }
  107. gs_vec2 __gs_platform_mouse_delta()
  108. {
  109. gs_platform_input* input = __input();
  110. if (input->mouse.prev_position.x < 0.0f ||
  111. input->mouse.prev_position.y < 0.0f ||
  112. input->mouse.position.x < 0.0f ||
  113. input->mouse.position.y < 0.0f )
  114. {
  115. return (gs_vec2){ 0.0f, 0.0f };
  116. }
  117. return (gs_vec2){ input->mouse.position.x - input->mouse.prev_position.x,
  118. input->mouse.position.y - input->mouse.prev_position.y };
  119. }
  120. gs_vec2 __gs_platform_mouse_position()
  121. {
  122. gs_platform_input* input = __input();
  123. return ( gs_vec2 )
  124. {
  125. input->mouse.position.x,
  126. input->mouse.position.y
  127. };
  128. }
  129. void __gs_platform_mouse_position_x_y( f32* x, f32* y )
  130. {
  131. gs_platform_input* input = __input();
  132. *x = input->mouse.position.x;
  133. *y = input->mouse.position.y;
  134. }
  135. void __gs_platform_mouse_wheel( f32* x, f32* y )
  136. {
  137. gs_platform_input* input = __input();
  138. *x = input->mouse.wheel.x;
  139. *y = input->mouse.wheel.y;
  140. }
  141. void __gs_platform_press_key( gs_platform_keycode code )
  142. {
  143. gs_platform_input* input = __input();
  144. if ( code < gs_keycode_count )
  145. {
  146. input->key_map[ code ] = true;
  147. }
  148. }
  149. void __gs_platform_release_key( gs_platform_keycode code )
  150. {
  151. gs_platform_input* input = __input();
  152. if ( code < gs_keycode_count )
  153. {
  154. input->key_map[ code ] = false;
  155. }
  156. }
  157. /*============================
  158. // Platform File I/O
  159. ============================*/
  160. b32 __gs_platform_file_exists( const char* file_path )
  161. {
  162. FILE* fp = fopen( file_path, "r" );
  163. if ( fp ) {
  164. fclose(fp);
  165. return true;
  166. }
  167. return false;
  168. }
  169. u32
  170. __gs_safe_truncate_u64( u64 value )
  171. {
  172. gs_assert(value <= 0xFFFFFFFF);
  173. u32 result = (u32)value;
  174. return result;
  175. }
  176. s32 __gs_platform_file_size_in_bytes( const char* file_path )
  177. {
  178. #ifdef GS_PLATFORM_WIN
  179. HANDLE hFile = CreateFile( file_path, GENERIC_READ,
  180. FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING,
  181. FILE_ATTRIBUTE_NORMAL, NULL );
  182. if (hFile==INVALID_HANDLE_VALUE)
  183. return -1; // error condition, could call GetLastError to find out more
  184. LARGE_INTEGER size;
  185. if (!GetFileSizeEx(hFile, &size))
  186. {
  187. CloseHandle(hFile);
  188. return -1; // error condition, could call GetLastError to find out more
  189. }
  190. CloseHandle(hFile);
  191. return __gs_safe_truncate_u64(size.QuadPart);
  192. #else
  193. #include <sys/stat.h>
  194. struct stat st;
  195. stat( file_path, &st );
  196. return (s32)st.st_size;
  197. #endif
  198. }
  199. gs_result __gs_write_file_contents( const char* file_path, const char* mode, void* data, usize data_type_size, usize data_size )
  200. {
  201. FILE* fp = fopen( file_path, "wb" );
  202. if ( fp )
  203. {
  204. s32 ret = fwrite( data, data_type_size, data_size, fp );
  205. fclose( fp );
  206. if ( ret == data_size ) {
  207. return gs_result_success;
  208. }
  209. }
  210. return gs_result_failure;
  211. }
  212. char* __gs_platform_read_file_contents_into_string_null_term( const char* file_path, const char* mode, s32* sz )
  213. {
  214. char* buffer = 0;
  215. FILE* fp = fopen( file_path, mode );
  216. s32 _sz = 0;
  217. if ( fp )
  218. {
  219. _sz = __gs_platform_file_size_in_bytes( file_path );
  220. buffer = ( char* )gs_malloc( _sz );
  221. if ( buffer )
  222. {
  223. fread( buffer, 1, _sz, fp );
  224. }
  225. fclose( fp );
  226. buffer[ _sz ] = '\0';
  227. }
  228. if ( sz )
  229. *sz = _sz;
  230. return buffer;
  231. }
  232. gs_result __gs_platform_write_str_to_file( const char* contents, const char* mode, usize sz, const char* output_path )
  233. {
  234. FILE* fp = fopen( output_path, mode );
  235. if ( fp )
  236. {
  237. s32 ret = fwrite( contents, sizeof( u8 ), sz, fp );
  238. if ( ret == sz )
  239. {
  240. return gs_result_success;
  241. }
  242. }
  243. return gs_result_failure;
  244. }
  245. void __gs_platform_file_extension( char* buffer, usize buffer_sz, const char* file_path )
  246. {
  247. gs_util_get_file_extension ( buffer, buffer_sz, file_path );
  248. }
  249. /*============================
  250. // Platform UUID
  251. ============================*/
  252. struct gs_uuid __gs_platform_generate_uuid()
  253. {
  254. struct gs_uuid uuid;
  255. srand( clock() );
  256. char guid[40];
  257. s32 t = 0;
  258. char* sz_temp = "xxxxxxxxxxxx4xxxyxxxxxxxxxxxxxxx";
  259. char* sz_hex = "0123456789abcdef-";
  260. s32 n_len = strlen( sz_temp );
  261. for ( t=0; t < n_len + 1; t++ )
  262. {
  263. s32 r = rand () % 16;
  264. char c = ' ';
  265. switch ( sz_temp[t] )
  266. {
  267. case 'x' : { c = sz_hex [r]; } break;
  268. case 'y' : { c = sz_hex [( r & 0x03 ) | 0x08]; } break;
  269. case '-' : { c = '-'; } break;
  270. case '4' : { c = '4'; } break;
  271. }
  272. guid[t] = ( t < n_len ) ? c : 0x00;
  273. }
  274. // Convert to uuid bytes from string
  275. const char* hex_string = sz_temp, *pos = hex_string;
  276. /* WARNING: no sanitization or error-checking whatsoever */
  277. for ( usize count = 0; count < 16; count++)
  278. {
  279. sscanf( pos, "%2hhx", &uuid.bytes[count] );
  280. pos += 2;
  281. }
  282. return uuid;
  283. }
  284. // Mutable temp buffer 'tmp_buffer'
  285. void __gs_platform_uuid_to_string( char* tmp_buffer, const struct gs_uuid* uuid )
  286. {
  287. gs_snprintf
  288. (
  289. tmp_buffer,
  290. 32,
  291. "%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x",
  292. uuid->bytes[ 0 ],
  293. uuid->bytes[ 1 ],
  294. uuid->bytes[ 2 ],
  295. uuid->bytes[ 3 ],
  296. uuid->bytes[ 4 ],
  297. uuid->bytes[ 5 ],
  298. uuid->bytes[ 6 ],
  299. uuid->bytes[ 7 ],
  300. uuid->bytes[ 8 ],
  301. uuid->bytes[ 9 ],
  302. uuid->bytes[ 10 ],
  303. uuid->bytes[ 11 ],
  304. uuid->bytes[ 12 ],
  305. uuid->bytes[ 13 ],
  306. uuid->bytes[ 14 ],
  307. uuid->bytes[ 15 ]
  308. );
  309. }
  310. u32 __gs_platform_hash_uuid( const struct gs_uuid* uuid )
  311. {
  312. char temp_buffer[] = gs_uuid_temp_str_buffer();
  313. __gs_platform_uuid_to_string( temp_buffer, uuid );
  314. return ( gs_hash_str( temp_buffer ) );
  315. }
  316. void __gs_default_init_platform( struct gs_platform_i* platform )
  317. {
  318. gs_assert( platform );
  319. // Just assert these for now
  320. __gs_verify_platform_correctness( platform );
  321. // Initialize random with time
  322. srand(time(0));
  323. /*============================
  324. // Platform Window
  325. ============================*/
  326. platform->windows = gs_slot_array_new( gs_platform_window_ptr );
  327. platform->active_window_handles = gs_dyn_array_new( gs_resource_handle );
  328. platform->create_window = &__gs_platform_create_window;
  329. platform->main_window = &__gs_platform_main_window;
  330. /*============================
  331. // Platform Input
  332. ============================*/
  333. platform->update_input = &__gs_platform_update_input;
  334. platform->press_key = &__gs_platform_press_key;
  335. platform->release_key = &__gs_platform_release_key;
  336. platform->was_key_down = &__gs_platform_was_key_down;
  337. platform->key_pressed = &__gs_platform_key_pressed;
  338. platform->key_down = &__gs_platform_key_down;
  339. platform->key_released = &__gs_platform_key_released;
  340. platform->press_mouse_button = &__gs_platform_press_mouse_button;
  341. platform->release_mouse_button = &__gs_platform_release_mouse_button;
  342. platform->was_mouse_down = &__gs_platform_was_mouse_down;
  343. platform->mouse_pressed = &__gs_platform_mouse_pressed;
  344. platform->mouse_down = &__gs_platform_mouse_down;
  345. platform->mouse_released = &__gs_platform_mouse_released;
  346. platform->mouse_delta = &__gs_platform_mouse_delta;
  347. platform->mouse_position = &__gs_platform_mouse_position;
  348. platform->mouse_position_x_y = &__gs_platform_mouse_position_x_y;
  349. platform->mouse_wheel = &__gs_platform_mouse_wheel;
  350. /*============================
  351. // Platform UUID
  352. ============================*/
  353. platform->generate_uuid = &__gs_platform_generate_uuid;
  354. platform->uuid_to_string = &__gs_platform_uuid_to_string;
  355. platform->hash_uuid = &__gs_platform_hash_uuid;
  356. /*============================
  357. // Platform File IO
  358. ============================*/
  359. platform->file_exists = &__gs_platform_file_exists;
  360. platform->read_file_contents = &__gs_platform_read_file_contents_into_string_null_term;
  361. platform->write_file_contents = &__gs_write_file_contents;
  362. platform->write_str_to_file = &__gs_platform_write_str_to_file;
  363. platform->file_size_in_bytes = &__gs_platform_file_size_in_bytes;
  364. platform->file_extension = &__gs_platform_file_extension;
  365. // Default world time initialization
  366. platform->time.max_fps = 60.0;
  367. platform->time.current = 0.0;
  368. platform->time.delta = 0.0;
  369. platform->time.update = 0.0;
  370. platform->time.render = 0.0;
  371. platform->time.previous = 0.0;
  372. platform->time.frame = 0.0;
  373. // Custom initialize plaform layer
  374. platform->init( platform );
  375. }
  376. void __gs_verify_platform_correctness( struct gs_platform_i* platform )
  377. {
  378. gs_assert( platform );
  379. gs_assert( platform->init );
  380. gs_assert( platform->shutdown );
  381. gs_assert( platform->sleep );
  382. gs_assert( platform->elapsed_time );
  383. gs_assert( platform->process_input );
  384. gs_assert( platform->create_window_internal );
  385. gs_assert( platform->window_swap_buffer );
  386. gs_assert( platform->set_window_size );
  387. gs_assert( platform->window_size );
  388. gs_assert( platform->window_size_w_h );
  389. gs_assert( platform->set_cursor );
  390. gs_assert( platform->enable_vsync );
  391. }