Loading...
Searching...
No Matches
Plugin.h
Go to the documentation of this file.
1// Copyright (c) 2025 Dave R. Smith. All rights reserved.
2// Malena Framework — Proprietary Software. See LICENSE for terms.
3
4// Plugin.h
5#pragma once
6
7#ifdef _WIN32
8 #define PLUGIN_EXPORT __declspec(dllexport)
9#else
10 #define PLUGIN_EXPORT
11#endif
12
15#include <Malena/Core/Core.h>
16#include <Malena/Core/Export.h>
26#include <type_traits>
27
28namespace ml
29{
31
32 template<typename M, typename = void>
33 struct HasPluginName : std::false_type {};
34 template<typename M>
35 struct HasPluginName<M, std::void_t<decltype(M::name)>>
36 : std::is_convertible<decltype(M::name), const char*> {};
37
38 template<typename M, typename = void>
39 struct HasPluginVersion : std::false_type {};
40 template<typename M>
41 struct HasPluginVersion<M, std::void_t<decltype(M::version)>>
42 : std::is_convertible<decltype(M::version), const char*> {};
43
44 template<typename M, typename = void>
45 struct HasThumbnail : std::false_type {};
46 template<typename M>
47 struct HasThumbnail<M, std::void_t<decltype(M::Images::THUMBNAIL)>>
48 : std::true_type {};
49
51
81 {
82 public:
83 virtual ~Plugin() = default;
84
89 virtual const char* getName() const { return "Unnamed Plugin"; }
90
95 virtual const char* getVersion() const { return "1.0.0"; }
96
106 virtual const sf::Texture* getThumbnail() const { return nullptr; }
107
114 virtual void onLoad() {}
115
123 virtual void onUnload() {}
124
130 template<typename T>
131 bool is() const { return dynamic_cast<const T*>(this) != nullptr; }
132
139 template<typename T>
140 T* getIf() { return dynamic_cast<T*>(this); }
141
147 template<typename T>
148 const T* getIf() const { return dynamic_cast<const T*>(this); }
149
151 virtual Plugin* asPlugin() { return this; }
153 };
154
156
157 template<typename... Traits>
158 struct TraitsHaveCore : std::disjunction<
159 std::is_base_of<Core, Traits>...
160 > {};
161
162 template<typename Manifest, typename... Traits>
163 struct PluginBase : public Plugin,
164 public Customizable<Manifest>,
165 public Traits...,
166 public GatherFlags <Manifest, Traits...>::type,
167 public GatherStates<Manifest, Traits...>::type
168 {
169 static_assert(HasPluginName<Manifest>::value,
170 "[Malena] Manifest is missing: static constexpr const char* name = \"Your Plugin Name\";");
171 static_assert(HasPluginVersion<Manifest>::value,
172 "[Malena] Manifest is missing: static constexpr const char* version = \"1.0.0\";");
173
174 using manifest_type = Manifest;
175
176 const char* getName() const override { return Manifest::name; }
177 const char* getVersion() const override { return Manifest::version; }
178 ml::Plugin* asPlugin() override { return this; }
179
180 const sf::Texture* getThumbnail() const override
181 {
182 if constexpr (HasThumbnail<Manifest>::value)
183 return &ml::TextureManager<Manifest>::get(Manifest::Images::THUMBNAIL);
184 else
185 return nullptr;
186 }
187
188 using GatherFlags<Manifest, Traits...>::type::enableFlag;
189 using GatherFlags<Manifest, Traits...>::type::disableFlag;
190 using GatherFlags<Manifest, Traits...>::type::checkFlag;
191 using GatherFlags<Manifest, Traits...>::type::setFlag;
192 using GatherFlags<Manifest, Traits...>::type::toggleFlag;
193
194 using GatherStates<Manifest, Traits...>::type::setState;
195 using GatherStates<Manifest, Traits...>::type::getState;
196 using GatherStates<Manifest, Traits...>::type::isState;
197 using GatherStates<Manifest, Traits...>::type::onStateEnter;
198 using GatherStates<Manifest, Traits...>::type::onStateExit;
199 };
200
201 template<typename Manifest, typename... Traits>
202 struct PluginBaseWithCore : public Plugin,
203 public Customizable<Manifest>,
204 public Traits...,
205 public GatherFlags <Manifest, Traits...>::type,
206 public GatherStates<Manifest, Traits...>::type
207 {
208 static_assert(HasPluginName<Manifest>::value,
209 "[Malena] Manifest is missing: static constexpr const char* name = \"Your Plugin Name\";");
210 static_assert(HasPluginVersion<Manifest>::value,
211 "[Malena] Manifest is missing: static constexpr const char* version = \"1.0.0\";");
212
213 using manifest_type = Manifest;
214
215 const char* getName() const override { return Manifest::name; }
216 const char* getVersion() const override { return Manifest::version; }
217 ml::Plugin* asPlugin() override { return this; }
218
219 const sf::Texture* getThumbnail() const override
220 {
221 if constexpr (HasThumbnail<Manifest>::value)
222 return &ml::TextureManager<Manifest>::get(Manifest::Images::THUMBNAIL);
223 else
224 return nullptr;
225 }
226
227 using FlagManager<ml::Flag>::enableFlag;
228 using FlagManager<ml::Flag>::disableFlag;
229 using FlagManager<ml::Flag>::checkFlag;
230 using FlagManager<ml::Flag>::setFlag;
231 using FlagManager<ml::Flag>::toggleFlag;
232
233 using GatherFlags<Manifest, Traits...>::type::enableFlag;
234 using GatherFlags<Manifest, Traits...>::type::disableFlag;
235 using GatherFlags<Manifest, Traits...>::type::checkFlag;
236 using GatherFlags<Manifest, Traits...>::type::setFlag;
237 using GatherFlags<Manifest, Traits...>::type::toggleFlag;
238
239 using GatherStates<Manifest, Traits...>::type::setState;
240 using GatherStates<Manifest, Traits...>::type::getState;
241 using GatherStates<Manifest, Traits...>::type::isState;
242 using GatherStates<Manifest, Traits...>::type::onStateEnter;
243 using GatherStates<Manifest, Traits...>::type::onStateExit;
244 };
245
247
271 template<typename Manifest, typename... Traits>
272 using PluginWith = std::conditional_t<
273 TraitsHaveCore<Traits...>::value,
274 PluginBaseWithCore<Manifest, Traits...>,
275 PluginBase<Manifest, Traits...>
276 >;
277
278} // namespace ml
279
280// =============================================================================
281// PluginHelper
282// =============================================================================
283
284namespace ml::exports
285{
287
288 template<typename T, typename = void>
289 struct PluginHelper
290 {
291 static ml::Plugin* create() { return nullptr; }
292 static void destroy(ml::Plugin*) {}
293 };
294
295 template<typename T>
296 struct PluginHelper<T, std::enable_if_t<std::is_base_of_v<ml::Plugin, T>>>
297 {
298 static ml::Plugin* create() { return (new T())->asPlugin(); }
299 static void destroy(ml::Plugin* p) { delete p; }
300 };
301
303}
304
305// =============================================================================
306// ML_EXPORT — full version (Plugin + Fireable both complete)
307// =============================================================================
308
309#undef ML_EXPORT
310
333#define ML_EXPORT(ClassName) \
334 \
335 extern "C" { \
336 PLUGIN_EXPORT ml::Plugin* createPlugin() \
337 { \
338 return ml::exports::PluginHelper<ClassName>::create(); \
339 } \
340 PLUGIN_EXPORT void destroyPlugin(ml::Plugin* p) \
341 { \
342 ml::exports::PluginHelper<ClassName>::destroy(p); \
343 } \
344 } \
345 \
346 namespace ml::exports { \
347 \
348 inline struct _Register_##ClassName \
349 { \
350 _Register_##ClassName() \
351 { \
352 ml::exports::FireableHelper<ClassName>::doRegister(); \
353 \
354 static_assert( \
355 std::is_base_of_v<ml::Plugin, ClassName> || \
356 std::is_base_of_v<ml::Fireable, ClassName>, \
357 "[Malena] ML_EXPORT: '" #ClassName "' is not a " \
358 "recognised exportable Malena type. " \
359 "Must derive from ml::Plugin or ml::Fireable."); \
360 } \
361 } _instance_##ClassName; \
362 \
363 }
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:51
Messenger()=default
Abstract base class for all Malena plugins.
Definition Plugin.h:81
virtual const sf::Texture * getThumbnail() const
Return a pointer to this plugin's thumbnail texture, or nullptr.
Definition Plugin.h:106
virtual void onUnload()
Called just before the plugin is destroyed and unloaded.
Definition Plugin.h:123
bool is() const
Return true if this plugin is an instance of T.
Definition Plugin.h:131
const T * getIf() const
Const overload of getIf.
Definition Plugin.h:148
virtual const char * getVersion() const
Return the plugin's version string.
Definition Plugin.h:95
virtual const char * getName() const
Return the plugin's display name.
Definition Plugin.h:89
T * getIf()
Return a T* if this plugin is an instance of T, or nullptr otherwise.
Definition Plugin.h:140
virtual ~Plugin()=default
virtual void onLoad()
Called immediately after the plugin is loaded and constructed.
Definition Plugin.h:114
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:272
Flag
System-level boolean flags available on every ml::Core object.
Definition Flag.h:65
#define MALENA_API
Definition Component.h:22
Collects all Flag enums from a component manifest and its traits.
Collects all State enums from a component manifest and its traits.