A reimplementation of Mario Kart Wii's physics engine in C++
Loading...
Searching...
No Matches
StateManager.hh
1#pragma once
2
3#include "game/field/obj/ObjectBase.hh"
4
5namespace Kinoko::Field {
6
8 u16 id;
9 void (*onEnter)(void *);
10 void (*onCalc)(void *);
11};
12
13template <typename T, void (T::*Enter)(), void (T::*Calc)()>
14constexpr StateManagerEntry StateEntry(u16 id) {
15 auto enter = [](void *obj) { (reinterpret_cast<T *>(obj)->*Enter)(); };
16 auto calc = [](void *obj) { (reinterpret_cast<T *>(obj)->*Calc)(); };
17 return {id, enter, calc};
18}
19
27class StateManager {
28protected:
29 StateManager(void *obj, const std::span<const StateManagerEntry> &entries)
30 : m_currentStateId(0), m_nextStateId(-1), m_currentFrame(0), m_entries(entries),
31 m_obj(obj) {
32 m_entryIds = std::span(static_cast<u16 *>(EGG::egg_alloc(m_entries.size() * sizeof(u16))),
33 m_entries.size());
34
35 // The base game initializes all entries to 0xffff, possibly to avoid an uninitialized value
36 memset(m_entryIds.data(), 0xff, m_entryIds.size());
37
38 for (size_t i = 0; i < m_entryIds.size(); ++i) {
39 m_entryIds[m_entries[i].id] = i;
40 }
41 }
42
43 virtual ~StateManager() {
44 EGG::egg_free(m_entryIds.data());
45 }
46
47 void calc() {
48 if (m_nextStateId >= 0) {
49 m_currentStateId = m_nextStateId;
50 m_nextStateId = -1;
51 m_currentFrame = 0;
52
53 auto enterFunc = m_entries[m_entryIds[m_currentStateId]].onEnter;
54 enterFunc(m_obj);
55 } else {
56 ++m_currentFrame;
57 }
58
59 auto calcFunc = m_entries[m_entryIds[m_currentStateId]].onCalc;
60 calcFunc(m_obj);
61 }
62
63 u16 m_currentStateId;
64 s32 m_nextStateId;
65 u32 m_currentFrame;
66 std::span<u16> m_entryIds;
67 std::span<const StateManagerEntry> m_entries;
68 void *m_obj;
69};
70
71} // namespace Kinoko::Field
Pertains to collision.