state_machine_resource.cpp 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533
  1. /*
  2. * Copyright (c) 2012-2018 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/vector.h"
  8. #include "core/error/error.h"
  9. #include "core/filesystem/file.h"
  10. #include "core/guid.h"
  11. #include "core/json/json_object.h"
  12. #include "core/json/sjson.h"
  13. #include "core/math/math.h"
  14. #include "core/memory/temp_allocator.h"
  15. #include "core/strings/dynamic_string.h"
  16. #include "resource/compile_options.h"
  17. #include "resource/expression_language.h"
  18. #include "resource/state_machine_resource.h"
  19. #include "resource/types.h"
  20. namespace crown
  21. {
  22. template <>
  23. struct hash<Guid>
  24. {
  25. u32 operator()(const Guid& id) const
  26. {
  27. return id.data1;
  28. }
  29. };
  30. namespace state_machine_internal
  31. {
  32. struct TransitionModeInfo
  33. {
  34. const char* name;
  35. TransitionMode::Enum mode;
  36. };
  37. static TransitionModeInfo _transition_mode_map[] =
  38. {
  39. { "immediate", TransitionMode::IMMEDIATE },
  40. { "wait_until_end", TransitionMode::WAIT_UNTIL_END },
  41. };
  42. CE_STATIC_ASSERT(countof(_transition_mode_map) == TransitionMode::COUNT);
  43. static TransitionMode::Enum name_to_transition_mode(const char* name)
  44. {
  45. for (u32 i = 0; i < countof(_transition_mode_map); ++i)
  46. {
  47. if (strcmp(name, _transition_mode_map[i].name) == 0)
  48. return _transition_mode_map[i].mode;
  49. }
  50. return TransitionMode::COUNT;
  51. }
  52. struct OffsetAccumulator
  53. {
  54. u32 _offset;
  55. OffsetAccumulator()
  56. {
  57. _offset = sizeof(StateMachineResource);
  58. }
  59. // Returns the offset of
  60. u32 offset(u32 num_animations, u32 num_transitions)
  61. {
  62. const u32 offt = _offset;
  63. _offset += sizeof(State);
  64. _offset += sizeof(Transition) * num_transitions;
  65. _offset += sizeof(AnimationArray);
  66. _offset += sizeof(Animation) * num_animations;
  67. return offt;
  68. }
  69. };
  70. struct AnimationInfo
  71. {
  72. ALLOCATOR_AWARE;
  73. StringId64 name;
  74. DynamicString weight;
  75. u32 bytecode_entry;
  76. AnimationInfo(Allocator& a)
  77. : weight(a)
  78. {
  79. }
  80. };
  81. struct TransitionInfo
  82. {
  83. Transition transition;
  84. Guid state;
  85. };
  86. struct StateInfo
  87. {
  88. ALLOCATOR_AWARE;
  89. Vector<AnimationInfo> animations;
  90. Vector<TransitionInfo> transitions;
  91. DynamicString speed;
  92. u32 speed_bytecode;
  93. u32 loop;
  94. StateInfo()
  95. : animations(default_allocator())
  96. , transitions(default_allocator())
  97. , speed(default_allocator())
  98. , speed_bytecode(UINT32_MAX)
  99. , loop(0)
  100. {
  101. }
  102. StateInfo(Allocator& a)
  103. : animations(a)
  104. , transitions(a)
  105. , speed(a)
  106. , speed_bytecode(UINT32_MAX)
  107. , loop(0)
  108. {
  109. }
  110. };
  111. struct VariableInfo
  112. {
  113. ALLOCATOR_AWARE;
  114. DynamicString name_string;
  115. StringId32 name;
  116. float value;
  117. VariableInfo()
  118. : name_string(default_allocator())
  119. , value(0.0f)
  120. {
  121. }
  122. VariableInfo(Allocator& a)
  123. : name_string(a)
  124. , value(0.0f)
  125. {
  126. }
  127. };
  128. struct StateMachineCompiler
  129. {
  130. CompileOptions& _opts;
  131. Guid _initial_state;
  132. HashMap<Guid, StateInfo> _states;
  133. OffsetAccumulator _offset_accumulator;
  134. HashMap<Guid, u32> _offsets;
  135. Vector<VariableInfo> _variables;
  136. Array<u32> _byte_code;
  137. StateMachineCompiler(CompileOptions& opts)
  138. : _opts(opts)
  139. , _states(default_allocator())
  140. , _offsets(default_allocator())
  141. , _variables(default_allocator())
  142. , _byte_code(default_allocator())
  143. {
  144. }
  145. s32 parse(Buffer& buf)
  146. {
  147. TempAllocator4096 ta;
  148. JsonObject object(ta);
  149. JsonArray states(ta);
  150. JsonArray variables(ta);
  151. sjson::parse(buf, object);
  152. sjson::parse_array(object["states"], states);
  153. sjson::parse_array(object["variables"], variables);
  154. // Parse states
  155. for (u32 i = 0; i < array::size(states); ++i)
  156. {
  157. TempAllocator4096 ta;
  158. JsonObject state(ta);
  159. JsonArray animations(ta);
  160. JsonArray transitions(ta);
  161. sjson::parse_object(states[i], state);
  162. sjson::parse_array(state["animations"], animations);
  163. sjson::parse_array(state["transitions"], transitions);
  164. StateInfo si;
  165. sjson::parse_string(state["speed"], si.speed);
  166. si.loop = sjson::parse_bool(state["loop"]);
  167. // Parse transitions
  168. {
  169. for (u32 i = 0; i < array::size(transitions); ++i)
  170. {
  171. JsonObject transition(ta);
  172. sjson::parse_object(transitions[i], transition);
  173. DynamicString mode_str(ta);
  174. sjson::parse_string(transition["mode"], mode_str);
  175. const u32 mode = name_to_transition_mode(mode_str.c_str());
  176. DATA_COMPILER_ASSERT(mode != TransitionMode::COUNT
  177. , _opts
  178. , "Unknown transition mode: '%s'"
  179. , mode_str.c_str()
  180. );
  181. TransitionInfo ti;
  182. ti.transition.event = sjson::parse_string_id(transition["event"]);
  183. ti.transition.state_offset = UINT32_MAX;
  184. ti.transition.mode = mode;
  185. ti.state = sjson::parse_guid(transition["to"]);
  186. vector::push_back(si.transitions, ti);
  187. }
  188. }
  189. // Parse animations
  190. {
  191. for (u32 i = 0; i < array::size(animations); ++i)
  192. {
  193. JsonObject animation(ta);
  194. sjson::parse_object(animations[i], animation);
  195. DynamicString animation_resource(ta);
  196. sjson::parse_string(animation["name"], animation_resource);
  197. DATA_COMPILER_ASSERT_RESOURCE_EXISTS("sprite_animation"
  198. , animation_resource.c_str()
  199. , _opts
  200. );
  201. AnimationInfo ai(ta);
  202. ai.name = sjson::parse_resource_id(animation["name"]);
  203. sjson::parse_string(animation["weight"], ai.weight);
  204. vector::push_back(si.animations, ai);
  205. }
  206. DATA_COMPILER_ASSERT(vector::size(si.animations) > 0
  207. , _opts
  208. , "State must contain one animation at least"
  209. );
  210. }
  211. Guid guid = sjson::parse_guid(state["id"]);
  212. DATA_COMPILER_ASSERT(!hash_map::has(_states, guid)
  213. , _opts
  214. , "State GUID duplicated"
  215. );
  216. hash_map::set(_states, guid, si);
  217. }
  218. DATA_COMPILER_ASSERT(hash_map::size(_states) > 0
  219. , _opts
  220. , "State machine must contain one state at least"
  221. );
  222. _initial_state = sjson::parse_guid(object["initial_state"]);
  223. DATA_COMPILER_ASSERT(hash_map::has(_states, _initial_state)
  224. , _opts
  225. , "Initial state references non-existing state"
  226. );
  227. // Parse variables
  228. {
  229. for (u32 i = 0; i < array::size(variables); ++i)
  230. {
  231. JsonObject variable(ta);
  232. sjson::parse_object(variables[i], variable);
  233. VariableInfo vi;
  234. vi.name = sjson::parse_string_id(variable["name"]);
  235. vi.value = sjson::parse_float(variable["value"]);
  236. sjson::parse_string(variable["name"], vi.name_string);
  237. vector::push_back(_variables, vi);
  238. }
  239. }
  240. // Compute state offsets
  241. {
  242. // Limit byte code to 4K
  243. array::resize(_byte_code, 1024);
  244. u32 written = 0;
  245. const u32 num_variables = vector::size(_variables);
  246. const char** variables = (const char**)default_allocator().allocate(num_variables*sizeof(char*));
  247. for (u32 i = 0; i < num_variables; ++i)
  248. variables[i] = _variables[i].name_string.c_str();
  249. const u32 num_constants = 1;
  250. const char* constants[] =
  251. {
  252. "PI"
  253. };
  254. const f32 constant_values[] =
  255. {
  256. PI
  257. };
  258. auto cur = hash_map::begin(_states);
  259. auto end = hash_map::end(_states);
  260. for (; cur != end; ++cur)
  261. {
  262. HASH_MAP_SKIP_HOLE(_states, cur);
  263. const Guid& guid = cur->first;
  264. const StateInfo& si = cur->second;
  265. const u32 offset = _offset_accumulator.offset(vector::size(si.animations), vector::size(si.transitions));
  266. hash_map::set(_offsets, guid, offset);
  267. for (u32 i = 0; i < vector::size(si.animations); ++i)
  268. {
  269. const u32 num = skinny::expression_language::compile(si.animations[i].weight.c_str()
  270. , num_variables
  271. , variables
  272. , num_constants
  273. , constants
  274. , constant_values
  275. , array::begin(_byte_code) + written
  276. , array::size(_byte_code)
  277. );
  278. const_cast<AnimationInfo&>(si.animations[i]).bytecode_entry = num > 0 ? written : UINT32_MAX;
  279. written += num;
  280. }
  281. const u32 num = skinny::expression_language::compile(si.speed.c_str()
  282. , num_variables
  283. , variables
  284. , num_constants
  285. , constants
  286. , constant_values
  287. , array::begin(_byte_code) + written
  288. , array::size(_byte_code)
  289. );
  290. const_cast<StateInfo&>(si).speed_bytecode = num > 0 ? written : UINT32_MAX;
  291. written += num;
  292. }
  293. // Resize to total amount of written bytecode
  294. array::resize(_byte_code, written);
  295. default_allocator().deallocate(variables);
  296. }
  297. return 0;
  298. }
  299. s32 write()
  300. {
  301. StateMachineResource smr;
  302. smr.version = RESOURCE_HEADER(RESOURCE_VERSION_STATE_MACHINE);
  303. smr.initial_state_offset = hash_map::get(_offsets, _initial_state, UINT32_MAX);
  304. smr.num_variables = vector::size(_variables);
  305. smr.variables_offset = _offset_accumulator._offset; // Offset of last state + 1
  306. smr.bytecode_size = array::size(_byte_code)*4;
  307. smr.bytecode_offset = smr.variables_offset + smr.num_variables*4*2;
  308. _opts.write(smr.version);
  309. _opts.write(smr.initial_state_offset);
  310. _opts.write(smr.num_variables);
  311. _opts.write(smr.variables_offset);
  312. _opts.write(smr.bytecode_size);
  313. _opts.write(smr.bytecode_offset);
  314. // Write states
  315. auto cur = hash_map::begin(_states);
  316. auto end = hash_map::end(_states);
  317. for (; cur != end; ++cur)
  318. {
  319. HASH_MAP_SKIP_HOLE(_states, cur);
  320. const StateInfo& si = cur->second;
  321. const u32 num_animations = vector::size(si.animations);
  322. const u32 num_transitions = vector::size(si.transitions);
  323. // Write speed
  324. _opts.write(si.speed_bytecode);
  325. // Write loop
  326. _opts.write(si.loop);
  327. // Write transitions
  328. TransitionArray ta;
  329. ta.num = num_transitions;
  330. _opts.write(ta.num);
  331. for (u32 i = 0; i < num_transitions; ++i)
  332. {
  333. Transition t = si.transitions[i].transition;
  334. t.state_offset = hash_map::get(_offsets, si.transitions[i].state, UINT32_MAX);
  335. _opts.write(t.event);
  336. _opts.write(t.state_offset);
  337. _opts.write(t.mode);
  338. }
  339. // Write animations
  340. AnimationArray aa;
  341. aa.num = num_animations;
  342. _opts.write(aa.num);
  343. for (u32 i = 0; i < num_animations; ++i)
  344. {
  345. Animation a;
  346. a.name = si.animations[i].name;
  347. a.bytecode_entry = si.animations[i].bytecode_entry;
  348. a.pad = 0;
  349. _opts.write(a.name);
  350. _opts.write(a.bytecode_entry);
  351. _opts.write(a.pad);
  352. }
  353. }
  354. // Write variables
  355. for (u32 i = 0; i < vector::size(_variables); ++i)
  356. _opts.write(_variables[i].name);
  357. for (u32 i = 0; i < vector::size(_variables); ++i)
  358. _opts.write(_variables[i].value);
  359. // Write bytecode
  360. for (u32 i = 0; i < array::size(_byte_code); ++i)
  361. _opts.write(_byte_code[i]);
  362. return 0;
  363. }
  364. };
  365. s32 compile(CompileOptions& opts)
  366. {
  367. Buffer buf = opts.read();
  368. StateMachineCompiler smc(opts);
  369. if (smc.parse(buf) != 0)
  370. return -1;
  371. return smc.write();
  372. }
  373. } // namespace state_machine_internal
  374. namespace state_machine
  375. {
  376. const State* initial_state(const StateMachineResource* smr)
  377. {
  378. return (State*)((char*)smr + smr->initial_state_offset);
  379. }
  380. const State* state(const StateMachineResource* smr, const Transition* t)
  381. {
  382. return (State*)((char*)smr + t->state_offset);
  383. }
  384. const State* trigger(const StateMachineResource* smr, const State* s, StringId32 event, const Transition** transition_out)
  385. {
  386. const TransitionArray* ta = state_transitions(s);
  387. for (u32 i = 0; i < ta->num; ++i)
  388. {
  389. const Transition* transition_i = transition(ta, i);
  390. if (transition_i->event == event)
  391. {
  392. *transition_out = transition_i;
  393. return state(smr, transition_i);
  394. }
  395. }
  396. *transition_out = NULL;
  397. return s;
  398. }
  399. const TransitionArray* state_transitions(const State* s)
  400. {
  401. return &s->ta;
  402. }
  403. const Transition* transition(const TransitionArray* ta, u32 index)
  404. {
  405. CE_ASSERT(index < ta->num, "Index out of bounds");
  406. const Transition* first = (Transition*)(&ta[1]);
  407. return &first[index];
  408. }
  409. const AnimationArray* state_animations(const State* s)
  410. {
  411. const TransitionArray* ta = state_transitions(s);
  412. const Transition* first = (Transition*)(&ta[1]);
  413. return (AnimationArray*)(first + ta->num);
  414. }
  415. const Animation* animation(const AnimationArray* aa, u32 index)
  416. {
  417. CE_ASSERT(index < aa->num, "Index out of bounds");
  418. Animation* first = (Animation*)(&aa[1]);
  419. return &first[index];
  420. }
  421. static inline const StringId32* variables_names(const StateMachineResource* smr)
  422. {
  423. return (StringId32*)((char*)smr + smr->variables_offset);
  424. }
  425. const f32* variables(const StateMachineResource* smr)
  426. {
  427. const StringId32* names = variables_names(smr);
  428. return (f32*)(names + smr->num_variables);
  429. }
  430. u32 variable_index(const StateMachineResource* smr, StringId32 name)
  431. {
  432. const StringId32* names = variables_names(smr);
  433. for (u32 i = 0; i < smr->num_variables; ++i)
  434. {
  435. if (names[i] == name)
  436. return i;
  437. }
  438. return UINT32_MAX;
  439. }
  440. const u32* byte_code(const StateMachineResource* smr)
  441. {
  442. return (u32*)((char*)smr + smr->bytecode_offset);
  443. }
  444. } // namespace state_machine
  445. } // namespace crown