Etterna 0.74.4
Loading...
Searching...
No Matches
OptionsBinding.h
1/* OptionsBinding - little helpers so that SongOptions and PlayerOptions can
2 * more easily have similar interfaces. */
3
4// No .cpp file because it's just some #defines, and not in a makefile because
5// it doesn't need to be. DefaultNilArgs would be in here, but then there would
6// need to be a .cpp file, and DefaultNilArgs is more widely useful.
7
8#ifndef OptionsBinding_H
9#define OptionsBinding_H
10// Functions are designed to combine Get and Set into one, to be less clumsy to
11// use. -Kyz If a valid arg is passed, the value is set. The previous value is
12// returned.
13// OPTIONAL_RETURN_SELF exists to provide optional chaining support.
14// Example: local a= player_options:Twirl(5, 1, true):Roll(5,
15// true):Dizzy(true):Twirl()
16#define OPTIONAL_RETURN_SELF(option_index) \
17 if (lua_isboolean(L, option_index) && lua_toboolean(L, option_index)) { \
18 p->PushSelf(L); \
19 return 1; \
20 }
21#define FLOAT_INTERFACE(func_name, member, valid) \
22 static int func_name(T* p, lua_State* L) \
23 { \
24 int original_top = lua_gettop(L); \
25 lua_pushnumber(L, p->m_f##member); \
26 lua_pushnumber(L, p->m_Speedf##member); \
27 if (lua_isnumber(L, 1) && original_top >= 1) { \
28 float v = FArg(1); \
29 if (!valid) { \
30 luaL_error(L, "Invalid value %f", v); \
31 } \
32 p->m_f##member = v; \
33 } \
34 if (original_top >= 2 && lua_isnumber(L, 2)) { \
35 p->m_Speedf##member = FArgGTEZero(L, 2); \
36 } \
37 OPTIONAL_RETURN_SELF(original_top); \
38 return 2; \
39 }
40#define SECFLOAT_INTERFACE(func_name, member, valid) \
41 static int func_name(T* p, lua_State* L) \
42 { \
43 int original_top = lua_gettop(L); \
44 lua_pushnumber(L, p->m_f##member); \
45 lua_pushnumber(L, p->m_Speedf##member); \
46 if (lua_isnumber(L, 1) && original_top >= 1) { \
47 if (DLMAN->InGameplay()) { \
48 Locator::getLogger()->warn( \
49 "Attempted to set mod illegally - {}", #member); \
50 OPTIONAL_RETURN_SELF(original_top); \
51 return 1; \
52 } \
53 float v = FArg(1); \
54 if (!valid) { \
55 luaL_error(L, "Invalid value %f", v); \
56 } \
57 p->m_f##member = v; \
58 } \
59 if (original_top >= 2 && lua_isnumber(L, 2)) { \
60 if (DLMAN->InGameplay()) { \
61 Locator::getLogger()->warn( \
62 "Attempted to set mod illegally - {}", #member); \
63 OPTIONAL_RETURN_SELF(original_top); \
64 return 1; \
65 } \
66 p->m_Speedf##member = FArgGTEZero(L, 2); \
67 } \
68 OPTIONAL_RETURN_SELF(original_top); \
69 return 2; \
70 }
71#define FLOAT_NO_SPEED_INTERFACE(func_name, member, valid) \
72 static int func_name(T* p, lua_State* L) \
73 { \
74 int original_top = lua_gettop(L); \
75 lua_pushnumber(L, p->m_f##member); \
76 if (lua_isnumber(L, 1) && original_top >= 1) { \
77 float v = FArg(1); \
78 if (!valid) { \
79 luaL_error(L, "Invalid value %f", v); \
80 } \
81 p->m_f##member = v; \
82 } \
83 OPTIONAL_RETURN_SELF(original_top); \
84 return 1; \
85 }
86#define INT_INTERFACE(func_name, member) \
87 static int func_name(T* p, lua_State* L) \
88 { \
89 int original_top = lua_gettop(L); \
90 lua_pushnumber(L, p->m_##member); \
91 if (lua_isnumber(L, 1) && original_top >= 1) { \
92 p->m_##member = IArg(1); \
93 } \
94 OPTIONAL_RETURN_SELF(original_top); \
95 return 1; \
96 }
97// BOOL_INTERFACE can't use OPTIONAL_RETURN_SELF because it pushes a bool.
98// If it did original_top, then "foo(true)" would chain when it shouldn't.
99#define BOOL_INTERFACE(func_name, member) \
100 static int func_name(T* p, lua_State* L) \
101 { \
102 int original_top = lua_gettop(L); \
103 lua_pushboolean(L, p->m_b##member); \
104 if (lua_isboolean(L, 1) && original_top >= 1) { \
105 p->m_b##member = BArg(1); \
106 } \
107 if (original_top >= 2 && lua_isboolean(L, 2)) { \
108 p->PushSelf(L); \
109 return 1; \
110 } \
111 return 1; \
112 }
113#define SECBOOL_INTERFACE(func_name, member) \
114 static int func_name(T* p, lua_State* L) \
115 { \
116 int original_top = lua_gettop(L); \
117 lua_pushboolean(L, p->m_b##member); \
118 if (lua_isboolean(L, 1) && original_top >= 1) { \
119 if (DLMAN->InGameplay()) { \
120 Locator::getLogger()->warn( \
121 "Attempted to set mod illegally - {}", #member); \
122 p->PushSelf(L); \
123 return 1; \
124 } \
125 p->m_b##member = BArg(1); \
126 } \
127 if (original_top >= 2 && lua_isboolean(L, 2)) { \
128 p->PushSelf(L); \
129 return 1; \
130 } \
131 return 1; \
132 }
133#define ENUM_INTERFACE(func_name, member, enum_name) \
134 static int func_name(T* p, lua_State* L) \
135 { \
136 int original_top = lua_gettop(L); \
137 Enum::Push(L, p->m_##member); \
138 if (!lua_isnil(L, 1) && original_top >= 1) { \
139 p->m_##member = Enum::Check<enum_name>(L, 1); \
140 } \
141 OPTIONAL_RETURN_SELF(original_top); \
142 return 1; \
143 }
144#define SECENUM_INTERFACE(func_name, member, enum_name) \
145 static int func_name(T* p, lua_State* L) \
146 { \
147 int original_top = lua_gettop(L); \
148 Enum::Push(L, p->m_##member); \
149 if (!lua_isnil(L, 1) && original_top >= 1) { \
150 if (DLMAN->InGameplay()) { \
151 Locator::getLogger()->warn( \
152 "Attempted to set mod illegally - {}", #enum_name); \
153 OPTIONAL_RETURN_SELF(original_top); \
154 return 1; \
155 } \
156 p->m_##member = Enum::Check<enum_name>(L, 1); \
157 } \
158 OPTIONAL_RETURN_SELF(original_top); \
159 return 1; \
160 }
161// Walk the table to make sure all entries are valid before setting.
162#define FLOAT_TABLE_INTERFACE(func_name, member, valid) \
163 static int func_name(T* p, lua_State* L) \
164 { \
165 int original_top = lua_gettop(L); \
166 lua_createtable(L, p->m_##member.size(), 0); \
167 for (size_t n = 0; n < p->m_##member.size(); ++n) { \
168 lua_pushnumber(L, p->m_##member[n]); \
169 lua_rawseti(L, -2, n + 1); \
170 } \
171 if (lua_istable(L, 1) && original_top >= 1) { \
172 size_t size = lua_objlen(L, 1); \
173 if (valid(L, 1)) { \
174 p->m_##member.clear(); \
175 p->m_##member.reserve(size); \
176 for (size_t n = 1; n <= size; ++n) { \
177 lua_pushnumber(L, n); \
178 lua_gettable(L, 1); \
179 float v = FArg(-1); \
180 p->m_##member.push_back(v); \
181 lua_pop(L, 1); \
182 } \
183 } \
184 } \
185 OPTIONAL_RETURN_SELF(original_top); \
186 return 1; \
187 }
188
189#endif