1#pragma once
2
3#include <prim/seadStorageFor.h>
4
5#include "Library/Base/Macros.h"
6#include "Library/Nerve/Nerve.h"
7#include "Library/Nerve/NerveAction.h"
8#include "Library/Nerve/NerveKeeper.h"
9
10/*
11
12Proper usage of these nerve macros:
13
14namespace {
15 NERVE_IMPL(ExampleUseCase, Wait);
16 NERVE_IMPL_(ExampleUseCase, WaitHack, Wait);
17 NERVE_IMPL(ExampleUseCase, HackEnd);
18 ...
19
20 NERVES_MAKE_STRUCT(ExampleUseCase, Wait, WaitHack, HackEnd, ...);
21 // or NERVES_MAKE_NOSTRUCT if they are not supposed to be in a struct
22
23}
24
25al::setNerve(this, &NrvExampleUseCase.Wait);
26
27
28Similar setup for NerveAction:
29
30namespace {
31 NERVE_ACTION_IMPL(ExampleUseCase, Wait);
32 NERVE_ACTION_IMPL_(ExampleUseCase, WaitHack, Wait);
33 NERVE_ACTION_IMPL(ExampleUseCase, HackEnd);
34 ...
35
36 NERVE_ACTIONS_MAKE_STRUCT(ExampleUseCase, Wait, WaitHack, HackEnd, ...);
37 // no NOSTRUCT variant, as the struct also contains a NerveActionCollector
38 // and no variants without it have been found so far
39}
40
41al::initNerveAction(this, "Hide", &NrvExampleUseCase.collector, 0);
42
43*/
44
45#define NERVE_IMPL_(Class, Action, ActionFunc) \
46 class Class##Nrv##Action : public al::Nerve { \
47 public: \
48 void execute(al::NerveKeeper* keeper) const override { \
49 (keeper->getParent<Class>())->exe##ActionFunc(); \
50 } \
51 };
52
53#define NERVE_IMPL(Class, Action) NERVE_IMPL_(Class, Action, Action)
54
55#define NERVE_END_IMPL_(Class, Action, ActionFunc) \
56 class Class##Nrv##Action : public al::Nerve { \
57 public: \
58 void execute(al::NerveKeeper* keeper) const override { \
59 (keeper->getParent<Class>())->exe##ActionFunc(); \
60 } \
61 void executeOnEnd(al::NerveKeeper* keeper) const override { \
62 (keeper->getParent<Class>())->end##ActionFunc(); \
63 } \
64 };
65
66#define NERVE_END_IMPL(Class, Action) NERVE_END_IMPL_(Class, Action, Action)
67
68#define NERVE_HOST_TYPE_IMPL_(Class, Action, ActionFunc) \
69 class HostType##Nrv##Action : public al::Nerve { \
70 public: \
71 void execute(al::NerveKeeper* keeper) const override { \
72 (keeper->getParent<Class>())->exe##ActionFunc(); \
73 } \
74 };
75
76#define NERVE_HOST_TYPE_IMPL(Class, Action) NERVE_HOST_TYPE_IMPL_(Class, Action, Action)
77
78#define NERVE_MAKE(Class, Action) Class##Nrv##Action Action;
79
80#define NERVES_MAKE_STRUCT(Class, ...) \
81 struct { \
82 FOR_EACH(NERVE_MAKE, Class, __VA_ARGS__) \
83 } Nrv##Class;
84
85#define NERVES_MAKE_NOSTRUCT(Class, ...) FOR_EACH(NERVE_MAKE, Class, __VA_ARGS__)
86
87#define NERVE_ACTION_IMPL_(Class, Action, ActionFunc) \
88 class Class##Nrv##Action : public al::NerveAction { \
89 public: \
90 void execute(al::NerveKeeper* keeper) const override { \
91 (keeper->getParent<Class>())->exe##ActionFunc(); \
92 } \
93 \
94 const char* getActionName() const override { \
95 return #Action; \
96 } \
97 };
98
99#define NERVE_ACTION_IMPL(Class, Action) NERVE_ACTION_IMPL_(Class, Action, Action)
100
101#define NERVE_ACTION_MAKE(Class, Action) sead::StorageFor<Class##Nrv##Action> Action;
102
103#define NERVE_ACTION_CONSTRUCT(Class, Action) Action.constructDefault();
104
105#define NERVE_ACTIONS_MAKE_STRUCT(Class, ...) \
106 struct NrvStruct##Class { \
107 FOR_EACH(NERVE_ACTION_MAKE, Class, __VA_ARGS__) \
108 \
109 alNerveFunction::NerveActionCollector collector; \
110 \
111 NrvStruct##Class() { \
112 FOR_EACH(NERVE_ACTION_CONSTRUCT, Class, __VA_ARGS__) \
113 } \
114 } Nrv##Class;
115