Loading...
Searching...
No Matches
Plugin.h
Go to the documentation of this file.
1// Plugin.h
2#pragma once
3
4#ifdef _WIN32
5 #define PLUGIN_EXPORT __declspec(dllexport)
6#else
7 #define PLUGIN_EXPORT
8#endif
9
11#include <Malena/Core/Core.h>
12#include <Malena/Core/Export.h>
22#include <type_traits>
23
24namespace ml
25{
27
28 template<typename M, typename = void>
29 struct HasPluginName : std::false_type {};
30 template<typename M>
31 struct HasPluginName<M, std::void_t<decltype(M::name)>>
32 : std::is_convertible<decltype(M::name), const char*> {};
33
34 template<typename M, typename = void>
35 struct HasPluginVersion : std::false_type {};
36 template<typename M>
37 struct HasPluginVersion<M, std::void_t<decltype(M::version)>>
38 : std::is_convertible<decltype(M::version), const char*> {};
39
40 template<typename M, typename = void>
41 struct HasThumbnail : std::false_type {};
42 template<typename M>
43 struct HasThumbnail<M, std::void_t<decltype(M::Images::THUMBNAIL)>>
44 : std::true_type {};
45
47
76 class Plugin : public Messenger
77 {
78 public:
79 virtual ~Plugin() = default;
80
85 virtual const char* getName() const { return "Unnamed Plugin"; }
86
91 virtual const char* getVersion() const { return "1.0.0"; }
92
102 virtual const sf::Texture* getThumbnail() const { return nullptr; }
103
110 virtual void onLoad() {}
111
119 virtual void onUnload() {}
120
126 template<typename T>
127 bool is() const { return dynamic_cast<const T*>(this) != nullptr; }
128
135 template<typename T>
136 T* getIf() { return dynamic_cast<T*>(this); }
137
143 template<typename T>
144 const T* getIf() const { return dynamic_cast<const T*>(this); }
145
147 virtual Plugin* asPlugin() { return this; }
149 };
150
152
153 template<typename... Traits>
154 struct TraitsHaveCore : std::disjunction<
155 std::is_base_of<Core, Traits>...
156 > {};
157
158 template<typename Manifest, typename... Traits>
159 struct PluginBase : public Plugin,
160 public Customizable<Manifest>,
161 public Traits...,
162 public GatherFlags <Manifest, Traits...>::type,
163 public GatherStates<Manifest, Traits...>::type
164 {
165 static_assert(HasPluginName<Manifest>::value,
166 "[Malena] Manifest is missing: static constexpr const char* name = \"Your Plugin Name\";");
167 static_assert(HasPluginVersion<Manifest>::value,
168 "[Malena] Manifest is missing: static constexpr const char* version = \"1.0.0\";");
169
170 using manifest_type = Manifest;
171
172 const char* getName() const override { return Manifest::name; }
173 const char* getVersion() const override { return Manifest::version; }
174 ml::Plugin* asPlugin() override { return this; }
175
176 const sf::Texture* getThumbnail() const override
177 {
178 if constexpr (HasThumbnail<Manifest>::value)
179 return &ml::TextureManager<Manifest>::get(Manifest::Images::THUMBNAIL);
180 else
181 return nullptr;
182 }
183
184 using GatherFlags<Manifest, Traits...>::type::enableFlag;
185 using GatherFlags<Manifest, Traits...>::type::disableFlag;
186 using GatherFlags<Manifest, Traits...>::type::checkFlag;
187 using GatherFlags<Manifest, Traits...>::type::setFlag;
188 using GatherFlags<Manifest, Traits...>::type::toggleFlag;
189
190 using GatherStates<Manifest, Traits...>::type::setState;
191 using GatherStates<Manifest, Traits...>::type::getState;
192 using GatherStates<Manifest, Traits...>::type::isState;
193 using GatherStates<Manifest, Traits...>::type::onStateEnter;
194 using GatherStates<Manifest, Traits...>::type::onStateExit;
195 };
196
197 template<typename Manifest, typename... Traits>
198 struct PluginBaseWithCore : public Plugin,
199 public Customizable<Manifest>,
200 public Traits...,
201 public GatherFlags <Manifest, Traits...>::type,
202 public GatherStates<Manifest, Traits...>::type
203 {
204 static_assert(HasPluginName<Manifest>::value,
205 "[Malena] Manifest is missing: static constexpr const char* name = \"Your Plugin Name\";");
206 static_assert(HasPluginVersion<Manifest>::value,
207 "[Malena] Manifest is missing: static constexpr const char* version = \"1.0.0\";");
208
209 using manifest_type = Manifest;
210
211 const char* getName() const override { return Manifest::name; }
212 const char* getVersion() const override { return Manifest::version; }
213 ml::Plugin* asPlugin() override { return this; }
214
215 const sf::Texture* getThumbnail() const override
216 {
217 if constexpr (HasThumbnail<Manifest>::value)
218 return &ml::TextureManager<Manifest>::get(Manifest::Images::THUMBNAIL);
219 else
220 return nullptr;
221 }
222
223 using FlagManager<ml::Flag>::enableFlag;
224 using FlagManager<ml::Flag>::disableFlag;
225 using FlagManager<ml::Flag>::checkFlag;
226 using FlagManager<ml::Flag>::setFlag;
227 using FlagManager<ml::Flag>::toggleFlag;
228
229 using GatherFlags<Manifest, Traits...>::type::enableFlag;
230 using GatherFlags<Manifest, Traits...>::type::disableFlag;
231 using GatherFlags<Manifest, Traits...>::type::checkFlag;
232 using GatherFlags<Manifest, Traits...>::type::setFlag;
233 using GatherFlags<Manifest, Traits...>::type::toggleFlag;
234
235 using GatherStates<Manifest, Traits...>::type::setState;
236 using GatherStates<Manifest, Traits...>::type::getState;
237 using GatherStates<Manifest, Traits...>::type::isState;
238 using GatherStates<Manifest, Traits...>::type::onStateEnter;
239 using GatherStates<Manifest, Traits...>::type::onStateExit;
240 };
241
243
267 template<typename Manifest, typename... Traits>
268 using PluginWith = std::conditional_t<
269 TraitsHaveCore<Traits...>::value,
270 PluginBaseWithCore<Manifest, Traits...>,
271 PluginBase<Manifest, Traits...>
272 >;
273
274} // namespace ml
275
276// =============================================================================
277// PluginHelper
278// =============================================================================
279
280namespace ml::exports
281{
283
284 template<typename T, typename = void>
285 struct PluginHelper
286 {
287 static ml::Plugin* create() { return nullptr; }
288 static void destroy(ml::Plugin*) {}
289 };
290
291 template<typename T>
292 struct PluginHelper<T, std::enable_if_t<std::is_base_of_v<ml::Plugin, T>>>
293 {
294 static ml::Plugin* create() { return (new T())->asPlugin(); }
295 static void destroy(ml::Plugin* p) { delete p; }
296 };
297
299}
300
301// =============================================================================
302// ML_EXPORT — full version (Plugin + Fireable both complete)
303// =============================================================================
304
305#undef ML_EXPORT
306
329#define ML_EXPORT(ClassName) \
330 \
331 extern "C" { \
332 PLUGIN_EXPORT ml::Plugin* createPlugin() \
333 { \
334 return ml::exports::PluginHelper<ClassName>::create(); \
335 } \
336 PLUGIN_EXPORT void destroyPlugin(ml::Plugin* p) \
337 { \
338 ml::exports::PluginHelper<ClassName>::destroy(p); \
339 } \
340 } \
341 \
342 namespace ml::exports { \
343 \
344 inline struct _Register_##ClassName \
345 { \
346 _Register_##ClassName() \
347 { \
348 ml::exports::FireableHelper<ClassName>::doRegister(); \
349 \
350 static_assert( \
351 std::is_base_of_v<ml::Plugin, ClassName> || \
352 std::is_base_of_v<ml::Fireable, ClassName>, \
353 "[Malena] ML_EXPORT: '" #ClassName "' is not a " \
354 "recognised exportable Malena type. " \
355 "Must derive from ml::Plugin or ml::Fireable."); \
356 } \
357 } _instance_##ClassName; \
358 \
359 }
Provides ML_EXPORT for registering Malena types at startup.
Tags a class with a manifest type and wires in its State manager.
Base class for all Malena manifests.
Definition Manifest.h:81
Messenger()=default
Abstract base class for all Malena plugins.
Definition Plugin.h:77
virtual const sf::Texture * getThumbnail() const
Return a pointer to this plugin's thumbnail texture, or nullptr.
Definition Plugin.h:102
virtual void onUnload()
Called just before the plugin is destroyed and unloaded.
Definition Plugin.h:119
bool is() const
Return true if this plugin is an instance of T.
Definition Plugin.h:127
const T * getIf() const
Const overload of getIf.
Definition Plugin.h:144
virtual const char * getVersion() const
Return the plugin's version string.
Definition Plugin.h:91
virtual const char * getName() const
Return the plugin's display name.
Definition Plugin.h:85
T * getIf()
Return a T* if this plugin is an instance of T, or nullptr otherwise.
Definition Plugin.h:136
virtual ~Plugin()=default
virtual void onLoad()
Called immediately after the plugin is loaded and constructed.
Definition Plugin.h:110
static const sf::Texture & get(const Asset &asset)
std::conditional_t< TraitsHaveCore< Traits... >::value, PluginBaseWithCore< Manifest, Traits... >, PluginBase< Manifest, Traits... > > PluginWith
Primary base class for manifest-driven plugins.
Definition Plugin.h:268
Flag
System-level boolean flags available on every ml::Core object.
Definition Flag.h:60
Definition Component.h:18
Collects all Flag enums from a component manifest and its traits.
Collects all State enums from a component manifest and its traits.