gs_engine.c 5.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199
  1. #include "base/gs_engine.h"
  2. #include "common/gs_util.h"
  3. #include "platform/gs_platform.h"
  4. #include "graphics/gs_graphics.h"
  5. #include "audio/gs_audio.h"
  6. #include "math/gs_math.h"
  7. // Global instance of gunslinger engine ( ...THERE CAN ONLY BE ONE )
  8. _global gs_engine* gs_engine_instance_g = { 0 };
  9. // Function forward declarations
  10. gs_result gs_engine_run();
  11. gs_result gs_engine_shutdown();
  12. gs_result gs_default_app_update();
  13. gs_result gs_default_app_shutdown();
  14. gs_resource_handle window;
  15. gs_engine* gs_engine_construct( gs_application_desc app_desc )
  16. {
  17. if ( gs_engine_instance_g == NULL )
  18. {
  19. // Construct instance
  20. gs_engine_instance_g = gs_malloc_init( gs_engine );
  21. // Initialize the meta class registry
  22. // Want a way to add user meta class information as well as the engine's (haven't considered how that looks yet)
  23. // gs_meta_class_registry_init( &gs_engine_instance_g->ctx.registry );
  24. // gs_assert( gs_engine_instance_g->ctx.registry.classes != NULL );
  25. // Set up function pointers
  26. gs_engine_instance_g->run = &gs_engine_run;
  27. gs_engine_instance_g->shutdown = &gs_engine_shutdown;
  28. // Need to have video settings passed down from user
  29. gs_engine_instance_g->ctx.platform = gs_platform_construct();
  30. // Default initialization for platform here
  31. __gs_default_init_platform( gs_engine_instance_g->ctx.platform );
  32. // Set frame rate for application
  33. if ( app_desc.frame_rate > 0.f ) {
  34. gs_engine_instance_g->ctx.platform->time.max_fps = app_desc.frame_rate;
  35. }
  36. // Set vsync for video
  37. gs_engine_instance_g->ctx.platform->enable_vsync( app_desc.enable_vsync );
  38. // Construct window
  39. gs_engine_instance()->ctx.platform->create_window( app_desc.window_title, app_desc.window_width, app_desc.window_height );
  40. // Construct graphics api
  41. gs_engine_instance_g->ctx.graphics = __gs_graphics_construct();
  42. // Initialize graphics here
  43. gs_engine_instance_g->ctx.graphics->init( gs_engine_instance_g->ctx.graphics );
  44. // Construct audio api
  45. gs_engine_instance_g->ctx.audio = __gs_audio_construct();
  46. // Initialize audio
  47. gs_engine_instance_g->ctx.audio->init( gs_engine_instance_g->ctx.audio );
  48. // Default application context
  49. gs_engine_instance_g->ctx.app.update = app_desc.update == NULL ? &gs_default_app_update : app_desc.update;
  50. gs_engine_instance_g->ctx.app.shutdown = app_desc.shutdown == NULL ? &gs_default_app_shutdown : app_desc.shutdown;
  51. if ( app_desc.init )
  52. {
  53. app_desc.init();
  54. }
  55. // gs_engine_instance_g->ctx.assets = gs_construct_heap( gs_asset_subsystem );
  56. // gs_asset_subsystem_init( gs_engine_instance_g->ctx.assets, "./assets/" );
  57. // Construct graphics
  58. // gs_engine_instance_g->ctx.graphics = gs_graphics_subsystem_construct();
  59. }
  60. return gs_engine_instance_g;
  61. }
  62. gs_result gs_engine_run()
  63. {
  64. // Main engine loop
  65. while ( true )
  66. {
  67. static u32 curr_ticks = 0;
  68. static u32 prev_ticks = 0;
  69. // Cache platform pointer
  70. gs_platform_i* platform = gs_engine_instance()->ctx.platform;
  71. gs_graphics_i* gfx = gs_engine_instance()->ctx.graphics;
  72. gs_audio_i* audio = gs_engine_instance()->ctx.audio;
  73. // Cache times at start of frame
  74. platform->time.current = platform->elapsed_time();
  75. platform->time.update = platform->time.current - platform->time.previous;
  76. platform->time.previous = platform->time.current;
  77. // Update platform input from previous frame
  78. platform->update_input( &platform->input );
  79. // Process input for this frame
  80. if ( platform->process_input() != gs_result_in_progress )
  81. {
  82. return ( gs_engine_instance()->shutdown() );
  83. }
  84. // Process application context
  85. if ( gs_engine_instance()->ctx.app.update() != gs_result_in_progress )
  86. {
  87. // Shutdown engine and return
  88. return ( gs_engine_instance()->shutdown() );
  89. }
  90. // Audio update and commit
  91. if ( audio )
  92. {
  93. if ( audio->update) {
  94. audio->update( audio );
  95. }
  96. if ( audio->commit ) {
  97. audio->commit( audio );
  98. }
  99. }
  100. // Graphics update and commit
  101. if ( gfx && gfx->update )
  102. {
  103. gfx->update( gfx );
  104. }
  105. // NOTE(John): This won't work forever. Must change eventually.
  106. // Swap all platform window buffers? Sure...
  107. gs_for_range_i( gs_dyn_array_size( platform->active_window_handles ) )
  108. {
  109. platform->window_swap_buffer( platform->active_window_handles[ i ] );
  110. }
  111. // Frame locking
  112. platform->time.current = platform->elapsed_time();
  113. platform->time.render = platform->time.current - platform->time.previous;
  114. platform->time.previous = platform->time.current;
  115. platform->time.frame = platform->time.update + platform->time.render; // Total frame time
  116. platform->time.delta = platform->time.frame / 1000.f;
  117. f32 target = ( 1000.f / platform->time.max_fps );
  118. if ( platform->time.frame < target )
  119. {
  120. platform->sleep( (f32)( target - platform->time.frame ) );
  121. platform->time.current = platform->elapsed_time();
  122. f64 wait_time = platform->time.current - platform->time.previous;
  123. platform->time.previous = platform->time.current;
  124. platform->time.frame += wait_time;
  125. platform->time.delta = platform->time.frame / 1000.f;
  126. }
  127. }
  128. // Shouldn't hit here
  129. gs_assert( false );
  130. return gs_result_failure;
  131. }
  132. gs_result gs_engine_shutdown()
  133. {
  134. // Shutdown application
  135. return ( gs_engine_instance()->ctx.app.shutdown() );
  136. }
  137. gs_engine* gs_engine_instance()
  138. {
  139. return gs_engine_instance_g;
  140. }
  141. gs_result gs_default_app_update()
  142. {
  143. return gs_result_in_progress;
  144. }
  145. gs_result gs_default_app_shutdown()
  146. {
  147. return gs_result_success;
  148. }