animation_state_machine.cpp 6.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234
  1. /*
  2. * Copyright (c) 2012-2017 Daniele Bartolini and individual contributors.
  3. * License: https://github.com/dbartolini/crown/blob/master/LICENSE
  4. */
  5. #include "core/containers/array.h"
  6. #include "core/containers/hash_map.h"
  7. #include "core/containers/types.h"
  8. #include "resource/expression_language.h"
  9. #include "resource/resource_manager.h"
  10. #include "resource/sprite_resource.h"
  11. #include "resource/state_machine_resource.h"
  12. #include "world/animation_state_machine.h"
  13. #include "world/types.h"
  14. #include "world/unit_manager.h"
  15. namespace crown
  16. {
  17. static void unit_destroyed_callback_bridge(UnitId id, void* user_ptr)
  18. {
  19. ((AnimationStateMachine*)user_ptr)->unit_destroyed_callback(id);
  20. }
  21. AnimationStateMachine::AnimationStateMachine(Allocator& a, ResourceManager& rm, UnitManager& um)
  22. : _marker(ANIMATION_STATE_MACHINE_MARKER)
  23. , _resource_manager(&rm)
  24. , _unit_manager(&um)
  25. , _map(a)
  26. , _animations(a)
  27. , _events(a)
  28. {
  29. um.register_destroy_function(unit_destroyed_callback_bridge, this);
  30. }
  31. AnimationStateMachine::~AnimationStateMachine()
  32. {
  33. _unit_manager->unregister_destroy_function(this);
  34. _marker = 0;
  35. }
  36. u32 AnimationStateMachine::create(UnitId unit, const AnimationStateMachineDesc& desc)
  37. {
  38. CE_ASSERT(!hash_map::has(_map, unit), "Unit already has this component");
  39. const StateMachineResource* smr = (StateMachineResource*)_resource_manager->get(RESOURCE_TYPE_STATE_MACHINE, desc.state_machine_resource);
  40. Animation anim;
  41. anim.unit = unit;
  42. anim.time = 0.0f;
  43. anim.time_total = 0.0f;
  44. anim.num_frames = 0;
  45. anim.frames = NULL;
  46. anim.resource = NULL;
  47. anim.state = state_machine::initial_state(smr);
  48. anim.state_next = NULL;
  49. anim.state_machine = smr;
  50. anim.variables = (f32*)default_allocator().allocate(sizeof(*anim.variables)*smr->num_variables);
  51. memcpy(anim.variables, state_machine::variables(smr), sizeof(*anim.variables)*smr->num_variables);
  52. u32 last = array::size(_animations);
  53. array::push_back(_animations, anim);
  54. hash_map::set(_map, unit, last);
  55. return 0;
  56. }
  57. void AnimationStateMachine::destroy(UnitId unit)
  58. {
  59. const u32 i = hash_map::get(_map, unit, UINT32_MAX);
  60. const u32 last_i = array::size(_animations) - 1;
  61. const UnitId last_u = _animations[last_i].unit;
  62. default_allocator().deallocate(_animations[i].variables);
  63. _animations[i] = _animations[last_i];
  64. array::pop_back(_animations);
  65. hash_map::set(_map, last_u, i);
  66. hash_map::remove(_map, unit);
  67. }
  68. u32 AnimationStateMachine::instances(UnitId unit)
  69. {
  70. return hash_map::get(_map, unit, UINT32_MAX);
  71. }
  72. bool AnimationStateMachine::has(UnitId unit)
  73. {
  74. return hash_map::has(_map, unit);
  75. }
  76. u32 AnimationStateMachine::variable_id(UnitId unit, StringId32 name)
  77. {
  78. const u32 i = hash_map::get(_map, unit, UINT32_MAX);
  79. const u32 index = state_machine::variable_index(_animations[i].state_machine, name);
  80. return index;
  81. }
  82. f32 AnimationStateMachine::variable(UnitId unit, u32 variable_id)
  83. {
  84. const u32 i = hash_map::get(_map, unit, UINT32_MAX);
  85. CE_ENSURE(variable_id != UINT32_MAX);
  86. return _animations[i].variables[variable_id];
  87. }
  88. void AnimationStateMachine::set_variable(UnitId unit, u32 variable_id, f32 value)
  89. {
  90. const u32 i = hash_map::get(_map, unit, UINT32_MAX);
  91. CE_ENSURE(variable_id != UINT32_MAX);
  92. _animations[i].variables[variable_id] = value;
  93. }
  94. void AnimationStateMachine::trigger(UnitId unit, StringId32 event)
  95. {
  96. const u32 i = hash_map::get(_map, unit, UINT32_MAX);
  97. const Transition* transition;
  98. const State* s = state_machine::trigger(_animations[i].state_machine
  99. , _animations[i].state
  100. , event
  101. , &transition
  102. );
  103. if (!transition)
  104. return;
  105. if (transition->mode == TransitionMode::IMMEDIATE)
  106. _animations[i].state = s;
  107. else if (transition->mode == TransitionMode::WAIT_UNTIL_END)
  108. _animations[i].state_next = s;
  109. else
  110. CE_FATAL("Unknown transition mode");
  111. }
  112. void AnimationStateMachine::update(float dt)
  113. {
  114. f32 stack_data[32];
  115. skinny::expression_language::Stack stack(stack_data, countof(stack_data));
  116. for (u32 i = 0; i < array::size(_animations); ++i)
  117. {
  118. Animation& anim_i = _animations[i];
  119. const f32* variables = anim_i.variables;
  120. const u32* byte_code = state_machine::byte_code(anim_i.state_machine);
  121. // Evaluate animation weights
  122. f32 max_v = 0.0f;
  123. u32 max_i = UINT32_MAX;
  124. StringId64 name;
  125. const AnimationArray* aa = state_machine::state_animations(anim_i.state);
  126. for (u32 i = 0; i < aa->num; ++i)
  127. {
  128. const crown::Animation* animation = state_machine::animation(aa, i);
  129. stack.size = 0;
  130. skinny::expression_language::run(&byte_code[animation->bytecode_entry], variables, stack);
  131. const f32 cur = stack.size > 0 ? stack_data[stack.size-1] : 0.0f;
  132. if (cur > max_v || max_i == UINT32_MAX)
  133. {
  134. max_v = cur;
  135. max_i = i;
  136. name = animation->name;
  137. }
  138. }
  139. // Evaluate animation speed
  140. stack.size = 0;
  141. skinny::expression_language::run(&byte_code[anim_i.state->speed_bytecode], variables, stack);
  142. const f32 speed = stack.size > 0 ? stack_data[stack.size-1] : 1.0f;
  143. // Play animation
  144. const SpriteAnimationResource* sar = (SpriteAnimationResource*)_resource_manager->get(RESOURCE_TYPE_SPRITE_ANIMATION, name);
  145. if (anim_i.resource != sar)
  146. {
  147. anim_i.time = 0.0f;
  148. anim_i.time_total = sar->total_time;
  149. anim_i.num_frames = sar->num_frames;
  150. anim_i.frames = sprite_animation_resource::frames(sar);
  151. anim_i.resource = sar;
  152. }
  153. if (!anim_i.resource)
  154. continue;
  155. const f32 frame_time = f32(anim_i.num_frames) * (anim_i.time/anim_i.time_total);
  156. const u32 frame_index = u32(frame_time) % anim_i.num_frames;
  157. anim_i.time += dt*speed;
  158. // If animation finished playing
  159. if (anim_i.time > anim_i.time_total)
  160. {
  161. if (anim_i.state_next)
  162. {
  163. anim_i.state = anim_i.state_next;
  164. anim_i.state_next = NULL;
  165. anim_i.time = 0.0f;
  166. }
  167. else
  168. {
  169. if (!!anim_i.state->loop)
  170. {
  171. anim_i.time = anim_i.time - anim_i.time_total;
  172. }
  173. else
  174. {
  175. const Transition* dummy;
  176. const State* s = state_machine::trigger(anim_i.state_machine
  177. , anim_i.state
  178. , StringId32("animation_end")
  179. , &dummy
  180. );
  181. anim_i.time = anim_i.state != s ? 0.0f : anim_i.time_total;
  182. anim_i.state = s;
  183. }
  184. }
  185. }
  186. // Emit events
  187. SpriteFrameChangeEvent ev;
  188. ev.unit = anim_i.unit;
  189. ev.frame_num = anim_i.frames[frame_index];
  190. event_stream::write(_events, 0, ev);
  191. }
  192. }
  193. void AnimationStateMachine::unit_destroyed_callback(UnitId unit)
  194. {
  195. if (has(unit))
  196. destroy(unit);
  197. }
  198. } // namespace crown