You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 

608 rivejä
21 KiB

  1. #pragma once
  2. #include "macros.hpp"
  3. #include "types.hpp"
  4. #include "print.hpp"
  5. #include "bucket_allocator.hpp"
  6. #include "arraylist.hpp"
  7. #include "stacktrace.hpp"
  8. namespace Scheduler {
  9. // NOTE(Felix): since we want to be able to interpolate any data in
  10. // principle, and the animation needs the start and end values, but the
  11. // size of the stuff we want to interpolate may vary, we just give it a
  12. // small chunk of memory to be stored
  13. typedef s64 Data_Block[22];
  14. typedef void (*Closure_F)(Data_Block);
  15. typedef void (*Lambda_F)();
  16. typedef f32 (*Shaper_F)(f32 t);
  17. typedef void (*Interpolator_F)(void* from, f32 t, void* to, void* interpolant);
  18. enum struct Interpolation_Type : u8 {
  19. Lerp = 1 << 7,
  20. Ease_In,
  21. Ease_Out,
  22. Ease_Middle,
  23. Ease_In_And_Out
  24. };
  25. enum struct Interpolant_Type : u8 {
  26. F32 = 1 << 7,
  27. };
  28. struct Scheduled_Animation_Create_Info {
  29. float seconds_to_start;
  30. float seconds_to_end;
  31. void* interpolant;
  32. Interpolant_Type interpolant_type;
  33. void* from;
  34. void* to;
  35. Interpolation_Type interpolation_type = Interpolation_Type::Lerp;
  36. const char* name = "";
  37. };
  38. enum struct Function_Type {
  39. Closure,
  40. Lambda
  41. };
  42. struct Action_Create_Info {
  43. Function_Type type;
  44. union {
  45. Lambda_F lambda;
  46. Closure_F closure;
  47. };
  48. void* param = nullptr;
  49. u32 param_size = 0;
  50. const char* name = "";
  51. };
  52. struct Scheduled_Action_Create_Info {
  53. float seconds_to_run;
  54. Action_Create_Info action;
  55. };
  56. struct Action {
  57. Function_Type type;
  58. union {
  59. Lambda_F lambda;
  60. Closure_F closure;
  61. };
  62. Data_Block param;
  63. Action* next;
  64. u64 creation_stamp;
  65. bool already_ran;
  66. #ifdef FTB_INTERNAL_DEBUG
  67. const char* name;
  68. #endif
  69. };
  70. struct Scheduled_Action {
  71. f32 seconds_to_run;
  72. Action action;
  73. };
  74. struct Scheduled_Animation {
  75. Interpolation_Type interpolation_type;
  76. Interpolant_Type interpolant_type;
  77. f32 seconds_to_start;
  78. f32 seconds_to_end;
  79. void* interpolant;
  80. Data_Block from;
  81. Data_Block to;
  82. Action* next;
  83. #ifdef FTB_INTERNAL_DEBUG
  84. const char* name;
  85. #endif
  86. };
  87. enum struct Schedulee_Type : u8 {
  88. None,
  89. Action,
  90. Animation,
  91. };
  92. struct Action_Or_Animation {
  93. Schedulee_Type type;
  94. union {
  95. Action* action;
  96. Scheduled_Animation* animation;
  97. };
  98. };
  99. // For user defined shapers t -> t
  100. Shaper_F _shapers[127];
  101. // Interpolators for user types
  102. Interpolator_F _interpolators[127];
  103. size_t _interpolatee_sizes[127];
  104. // Per reset cycle:
  105. // PING
  106. Bucket_Allocator<Scheduled_Animation> active_animations_1;
  107. Bucket_Allocator<Scheduled_Action> scheduled_actions_1;
  108. Bucket_Allocator<Action> chained_actions_1;
  109. // PONG
  110. Bucket_Allocator<Scheduled_Animation> active_animations_2;
  111. Bucket_Allocator<Scheduled_Action> scheduled_actions_2;
  112. Bucket_Allocator<Action> chained_actions_2;
  113. Bucket_Allocator<Scheduled_Animation>* active_animations;
  114. Bucket_Allocator<Scheduled_Action>* scheduled_actions;
  115. Bucket_Allocator<Action>* chained_actions;
  116. Bucket_Allocator<Scheduled_Animation>* future_active_animations;
  117. Bucket_Allocator<Scheduled_Action>* future_scheduled_actions;
  118. Bucket_Allocator<Action>* future_chained_actions;
  119. // Per Tick:
  120. // if something is deleted while iterating over them
  121. Array_List<Scheduled_Animation*> _animations_marked_for_deletion;
  122. Array_List<Scheduled_Action*> _actions_marked_for_deletion;
  123. Array_List<Action*> _chained_actions_to_be_run_after_iteration;
  124. bool _is_iterating = false;
  125. bool _should_reset = false;
  126. bool _should_stop_iterating = false;
  127. u64 _action_stamp_counter = 0;
  128. auto init() -> void {
  129. active_animations_1.alloc();
  130. scheduled_actions_1.alloc();
  131. chained_actions_1.alloc();
  132. active_animations_2.alloc();
  133. scheduled_actions_2.alloc();
  134. chained_actions_2.alloc();
  135. active_animations = &active_animations_1;
  136. scheduled_actions = &scheduled_actions_1;
  137. chained_actions = &chained_actions_1;
  138. future_active_animations = &active_animations_2;
  139. future_scheduled_actions = &scheduled_actions_2;
  140. future_chained_actions = &chained_actions_2;
  141. _animations_marked_for_deletion.alloc();
  142. _actions_marked_for_deletion.alloc();
  143. _chained_actions_to_be_run_after_iteration.alloc(20);
  144. }
  145. auto deinit() -> void {
  146. active_animations_1.dealloc();
  147. scheduled_actions_1.dealloc();
  148. chained_actions_1.dealloc();
  149. active_animations_2.dealloc();
  150. scheduled_actions_2.dealloc();
  151. chained_actions_2.dealloc();
  152. _animations_marked_for_deletion.dealloc();
  153. _actions_marked_for_deletion.dealloc();
  154. _chained_actions_to_be_run_after_iteration.dealloc();
  155. }
  156. auto register_shaper(Shaper_F f, Interpolation_Type t) {
  157. _shapers[(u8)t] = f;
  158. }
  159. auto register_interpolator(Interpolator_F f, Interpolant_Type t, size_t size_of_interpolant) {
  160. _interpolatee_sizes[(u8)t] = size_of_interpolant;
  161. _interpolators[(u8)t] = f;
  162. }
  163. auto schedule_animation(Scheduled_Animation_Create_Info aci) -> Scheduled_Animation* {
  164. Scheduled_Animation* anim;
  165. if (_should_reset) {
  166. anim = future_active_animations->allocate();
  167. } else {
  168. anim = active_animations->allocate();
  169. }
  170. anim->next = nullptr;
  171. #ifdef FTB_INTERNAL_DEBUG
  172. anim->name = aci.name;
  173. #endif
  174. anim->interpolation_type = aci.interpolation_type;
  175. anim->interpolant_type = aci.interpolant_type;
  176. anim->seconds_to_start = aci.seconds_to_start;
  177. anim->seconds_to_end = aci.seconds_to_end;
  178. anim->interpolant = aci.interpolant;
  179. u32 data_size;
  180. switch(anim->interpolant_type) {
  181. case Interpolant_Type::F32: data_size = sizeof(f32); break;
  182. default: {
  183. data_size = _interpolatee_sizes[(u8)(anim->interpolant_type)];
  184. panic_if(data_size == 0, "Interpolatee (%d) size was 0 (was it initialized correctly)?",
  185. anim->interpolant_type);
  186. }
  187. }
  188. memcpy(&anim->from, aci.from, data_size);
  189. memcpy(&anim->to, aci.to, data_size);
  190. return anim;
  191. }
  192. auto advance_single_animation(Scheduled_Animation* anim) -> void {
  193. // if not yet started, skip
  194. if (anim->seconds_to_start > 0)
  195. return;
  196. // otherwise run it:
  197. f32 perf_diff = anim->seconds_to_end - anim->seconds_to_start;
  198. f32 perf_inside = -anim->seconds_to_start;
  199. f64 t = 1.0 * perf_inside / perf_diff;
  200. switch (anim->interpolation_type) {
  201. case Interpolation_Type::Lerp: break;
  202. case Interpolation_Type::Ease_In: {
  203. t *= t;
  204. } break;
  205. case Interpolation_Type::Ease_Out: {
  206. t = -(t * (t - 2));
  207. } break;
  208. case Interpolation_Type::Ease_In_And_Out: {
  209. // NOTE(Felix): yes -- Mon Dec 7 11:47:34 2020
  210. t = (t < 0.5) ?
  211. +2 * t * t :
  212. -2 * (t * (t - 2)) - 1;
  213. } break;
  214. case Interpolation_Type::Ease_Middle: {
  215. // t = (t < 0.5) ?
  216. // -2 * t * (t - 1) :
  217. // +2 * t * (t - 1) + 1;
  218. t = 4.0f / 5.0f * t*t*t - 6.0f/5.0f *t*t + 7.0f/5.0f * t;
  219. } break;
  220. default: {
  221. // try user supported shaper
  222. Shaper_F shaper = _shapers[(u8)anim->interpolant_type];
  223. panic_if(shaper == nullptr,
  224. "Shaper function for type (%d) was nullptr (was it initialized correctly)?",
  225. anim->interpolation_type);
  226. t = shaper(t);
  227. }
  228. }
  229. switch(anim->interpolant_type) {
  230. case Interpolant_Type::F32: {
  231. f32 from = *((f32*)&anim->from);
  232. f32 to = *((f32*)&anim->to);
  233. *((f32*)anim->interpolant) = from + (to - from) * t;
  234. } break;
  235. default: {
  236. // try user supported interpolator
  237. Interpolator_F interpolator = _interpolators[(u8)anim->interpolant_type];
  238. panic_if(interpolator == nullptr,
  239. "Interpolator function for type (%d) was nullptr (was it initialized correctly)?",
  240. anim->interpolant_type);
  241. interpolator(&anim->from, t, &anim->to, anim->interpolant);
  242. }
  243. }
  244. }
  245. auto _init_action(Action* action, Action_Create_Info aci) -> void {
  246. action->next = nullptr;
  247. #ifdef FTB_INTERNAL_DEBUG
  248. action->name = aci.name;
  249. #endif
  250. action->creation_stamp = _action_stamp_counter;
  251. ++_action_stamp_counter;
  252. action->already_ran = false;
  253. if (aci.param) {
  254. if(aci.param_size > sizeof(Data_Block)) {
  255. panic("%llu (sizeof(Data_Block)) < %u (aci.param_size)",
  256. sizeof(Data_Block), aci.param_size);
  257. }
  258. action->type = Function_Type::Closure;
  259. action->closure = aci.closure;
  260. memcpy(&action->param, aci.param, aci.param_size);
  261. } else {
  262. action->type = Function_Type::Lambda;
  263. action->lambda = aci.lambda;
  264. memset(&action->param, 0, sizeof(Data_Block));
  265. }
  266. if (aci.type == Function_Type::Lambda) action->lambda = aci.lambda;
  267. else if (aci.type == Function_Type::Closure) action->closure = aci.closure;
  268. }
  269. auto schedule_action(Scheduled_Action_Create_Info aci) -> Scheduled_Action* {
  270. Scheduled_Action* scheduled_action;
  271. if (_should_reset) {
  272. scheduled_action = future_scheduled_actions->allocate();
  273. } else {
  274. scheduled_action = scheduled_actions->allocate();
  275. }
  276. scheduled_action->seconds_to_run = aci.seconds_to_run;
  277. _init_action(&scheduled_action->action, aci.action);
  278. debug_log("scheduling action %s %d", aci.action.name, scheduled_action->action.creation_stamp);
  279. return scheduled_action;
  280. }
  281. auto _actually_reset() {
  282. debug_log("HARD RESET SCHEDULER");
  283. _should_reset = false;
  284. active_animations->clear();
  285. scheduled_actions->clear();
  286. chained_actions->clear();
  287. _animations_marked_for_deletion.clear();
  288. _actions_marked_for_deletion.clear();
  289. // swap ping pong
  290. Bucket_Allocator<Scheduled_Animation>* t_active_animations = active_animations;
  291. Bucket_Allocator<Scheduled_Action>* t_scheduled_actions = scheduled_actions;
  292. Bucket_Allocator<Action>* t_chained_actions = chained_actions;
  293. active_animations = future_active_animations;
  294. scheduled_actions = future_scheduled_actions;
  295. chained_actions = future_chained_actions;
  296. future_active_animations = t_active_animations;
  297. future_scheduled_actions = t_scheduled_actions;
  298. future_chained_actions = t_chained_actions;
  299. }
  300. auto reset() -> void {
  301. if (_is_iterating) {
  302. debug_log("SOFT RESET Scheduler");
  303. _should_reset = true;
  304. future_active_animations->clear();
  305. future_scheduled_actions->clear();
  306. future_chained_actions->clear();
  307. }
  308. else
  309. _actually_reset();
  310. }
  311. auto chain_action(Scheduled_Animation* existing_animation, Action_Create_Info aci) -> Action* {
  312. Action* chain_action;
  313. if (_should_reset) {
  314. chain_action = future_chained_actions->allocate();
  315. } else {
  316. chain_action = chained_actions->allocate();
  317. }
  318. _init_action(chain_action, aci);
  319. existing_animation->next = chain_action;
  320. return chain_action;
  321. }
  322. auto chain_action(Action* existing_action, Action_Create_Info aci) -> Action* {
  323. Action* chain_action;
  324. if (_should_reset) {
  325. chain_action = future_chained_actions->allocate();
  326. } else {
  327. chain_action = chained_actions->allocate();
  328. }
  329. _init_action(chain_action, aci);
  330. existing_action->next = chain_action;
  331. return chain_action;
  332. }
  333. inline auto chain_action(Action_Or_Animation aoa, Action_Create_Info aci) -> Action* {
  334. if (aoa.type == Schedulee_Type::Action)
  335. return chain_action(aoa.action, aci);
  336. else if (aoa.type == Schedulee_Type::Animation)
  337. return chain_action(aoa.animation, aci);
  338. else if (aoa.type == Schedulee_Type::None) {
  339. Scheduled_Action* sa = schedule_action({
  340. .seconds_to_run = 0.0f,
  341. .action { aci }
  342. });
  343. return &sa->action;
  344. } else {
  345. panic("unknown Schedulee type");
  346. return nullptr;
  347. }
  348. }
  349. inline auto execute_action(Action* action) -> void {
  350. debug_log("running action %s %d", action->name, action->creation_stamp);
  351. action->already_ran = true;
  352. if (action->type == Function_Type::Closure) {
  353. action->closure(action->param);
  354. } else {
  355. action->lambda();
  356. }
  357. debug_log("finished running action %s %d", action->name, action->creation_stamp);
  358. }
  359. auto handle_chained_action(Action* action) -> void {
  360. debug_log("Handling chained actions");
  361. while (action) {
  362. debug_log("RUNNING CHAINED %s %d", action->name, action->creation_stamp);
  363. execute_action(action);
  364. debug_log("DELETING action %s %d", action->name, action->creation_stamp);
  365. chained_actions->free_object(action);
  366. action = action->next;
  367. if (_should_stop_iterating) break;
  368. }
  369. debug_log("Chained actions done");
  370. }
  371. auto run_pending_actions_and_reset() -> void {
  372. Auto_Array_List<Action*> pending_actions(16);
  373. debug_log("%{color<}Running pending actions:", console_cyan);
  374. scheduled_actions->for_each([&](Scheduled_Action* s_action) {
  375. if (!s_action->action.already_ran) {
  376. pending_actions.append(&s_action->action);
  377. }
  378. });
  379. active_animations->for_each([&](Scheduled_Animation* s_animation) {
  380. if (s_animation->next && !s_animation->next->already_ran) {
  381. pending_actions.append(s_animation->next);
  382. }
  383. });
  384. qsort(pending_actions.data,
  385. pending_actions.count,
  386. sizeof(pending_actions.data[0]),
  387. [] (const void* a1, const void* a2) -> int {
  388. return (*((Action**)(a1)))->creation_stamp - (*((Action**)(a2)))->creation_stamp;
  389. });
  390. for (auto action : pending_actions) {
  391. execute_action(action);
  392. }
  393. debug_log("pending_actions done%{>color}");
  394. _should_stop_iterating = true;
  395. reset();
  396. }
  397. auto update_all(f32 delta_time) -> void {
  398. // advance animations and collect due actions
  399. {
  400. active_animations->for_each([=](Scheduled_Animation* anim) {
  401. anim->seconds_to_start -= delta_time;
  402. anim->seconds_to_end -= delta_time;
  403. advance_single_animation(anim);
  404. if (anim->seconds_to_end <= 0) {
  405. // NOTE(Felix): if already finished snap the value to its target
  406. // and delete it
  407. switch (anim->interpolant_type) {
  408. case Interpolant_Type::F32: *(f32*)anim->interpolant = *(f32*)anim->to; break;
  409. default: {
  410. size_t interpolantee_size = _interpolatee_sizes[(u8)anim->interpolant_type];
  411. panic_if(interpolantee_size == 0,
  412. "Interpolatee (%d) size was 0 (was it initialized correctly)?",
  413. anim->interpolant_type);
  414. memcpy(anim->interpolant, anim->to, interpolantee_size);
  415. }
  416. }
  417. _animations_marked_for_deletion.append(anim);
  418. // NOTE(Felix): Don't actually run the next here, queue it
  419. // up for after the iteration, see note below.
  420. if (anim->next) {
  421. _chained_actions_to_be_run_after_iteration.append(anim->next);
  422. }
  423. }
  424. });
  425. scheduled_actions->for_each([=](Scheduled_Action* action) {
  426. action->seconds_to_run -= delta_time;
  427. if (action->seconds_to_run <= 0) {
  428. _chained_actions_to_be_run_after_iteration.append(&action->action);
  429. _actions_marked_for_deletion.append(action);
  430. }
  431. });
  432. }
  433. // NOTE(Felix): The reason why we iterate over the chained actions like
  434. // this: Imagine the following scenario: We schedule two animations
  435. // that take the same time to run should run in parallel. So what you
  436. // do for the first animation is put their parenting action (not the
  437. // unparenting action) as the last action in the current game state
  438. // and schedule their animation and then chain the unparenting action
  439. // to the animation. The gamestate however only knows about the
  440. // parenting action, so that the next thing that is scheduled runs
  441. // parallel to it. For the second animation, the parenting action is
  442. // scheduled onto the parenting action of the first animation, the
  443. // animation is scheduled, and then also the unparenting action is
  444. // chained to the animation. This time we set the Game_State
  445. // last_scheduled to the unparenting action, so that no further
  446. // animation will happen in parallel. Now imagine we chain some
  447. // animation to the game state, that involves the animation of the
  448. // first object. It can happen, when iterating through the animations,
  449. // that we iterate first over the second animation, would then run
  450. // their chained actions, in which we would animate the first object.
  451. // This is bad, as they are not finished yet, their unparenting action
  452. // did not run yet. Now we "solve" this by iterating breadth first
  453. // over the actions.
  454. if (_chained_actions_to_be_run_after_iteration.count > 1) {
  455. qsort(_chained_actions_to_be_run_after_iteration.data,
  456. _chained_actions_to_be_run_after_iteration.count,
  457. sizeof(_chained_actions_to_be_run_after_iteration.data[0]),
  458. [] (const void* a1, const void* a2) -> int {
  459. return (*((Action**)(a1)))->creation_stamp - (*((Action**)(a2)))->creation_stamp;
  460. });
  461. }
  462. // excute all due actions:
  463. {
  464. _is_iterating = true;
  465. _should_stop_iterating = false;
  466. for (Action* action : _chained_actions_to_be_run_after_iteration) {
  467. if (action->already_ran) continue;
  468. execute_action(action);
  469. if (_should_stop_iterating) break;
  470. handle_chained_action(action->next);
  471. if (_should_stop_iterating) break;
  472. }
  473. _is_iterating = false;
  474. _chained_actions_to_be_run_after_iteration.clear();
  475. }
  476. // NOTE(Felix): if Scheduler::reset was called in an action (happens
  477. // when scheduling a level switch), then don't actually reset
  478. // everyting, but only set _should_reset. Because if we would actually
  479. // clear all the bucket allocators, we would then anyway call
  480. // free_object on them down when we process the _marked_for_deletion
  481. // things, so we would have stuff in the free list that is not
  482. // actually allocated
  483. if (_should_reset) {
  484. _actually_reset();
  485. } else {
  486. // NOTE(Felix): Don't free stuff from the bucket_allocators while
  487. // iterating over them, as this appends the pointers to the free_list,
  488. // which then is no longer sorted, which destroys the mechanism to
  489. // check if a bucket is active or freed, so for_each will be called
  490. // for buckets that are no longer alive. -Felix Dec 18 2020
  491. for (auto anim : _animations_marked_for_deletion) {
  492. active_animations->free_object(anim);
  493. }
  494. for (auto action : _actions_marked_for_deletion) {
  495. scheduled_actions->free_object(action);
  496. }
  497. _animations_marked_for_deletion.clear();
  498. _actions_marked_for_deletion.clear();
  499. }
  500. }
  501. }