CommonLibSSE (powerof3)
RegistrationMapUnique.h
Go to the documentation of this file.
1 #pragma once
2 
3 #include "RE/A/ActiveEffect.h"
4 #include "RE/B/BGSRefAlias.h"
5 #include "RE/B/BSFixedString.h"
8 #include "RE/T/TESForm.h"
9 #include "RE/T/TESObjectREFR.h"
10 #include "RE/T/TypeTraits.h"
11 #include "RE/V/VirtualMachine.h"
12 
13 #include "SKSE/API.h"
15 #include "SKSE/Interfaces.h"
16 #include "SKSE/Logger.h"
17 
18 namespace SKSE
19 {
20  namespace Impl
21  {
22  template <class Filter>
24  {
25  public:
26  using EventFilter = std::pair<Filter, bool>;
27  using EventFilterHandleMap = std::map<EventFilter, std::set<RE::VMHandle>>;
28 
29  using PassFilterFunc = std::function<bool(const Filter&, bool)>;
30 
32  {
33  public:
35  RegistrationMapUniqueBase(const std::string_view& a_eventName);
39 
42 
43  bool Register(RE::TESForm* a_form, const Filter& a_filter, bool a_matchFilter);
44  bool Register(RE::ActiveEffect* a_activeEffect, const Filter& a_filter, bool a_matchFilter);
45  bool Register(RE::BGSRefAlias* a_alias, const Filter& a_filter, bool a_matchFilter);
46  bool Unregister(RE::TESForm* a_form, const Filter& a_filter, bool a_matchFilter);
47  bool Unregister(RE::ActiveEffect* a_activeEffect, const Filter& a_filter, bool a_matchFilter);
48  bool Unregister(RE::BGSRefAlias* a_alias, const Filter& a_filter, bool a_matchFilter);
49  void UnregisterAll(const RE::TESForm* a_form);
50  void UnregisterAll(RE::ActiveEffect* a_activeEffect);
51  void UnregisterAll(RE::BGSRefAlias* a_alias);
52  void UnregisterAll(RE::VMHandle a_handle);
53  void UnregisterAll(RE::FormID a_uniqueID);
54  void Clear();
55  bool Save(SerializationInterface* a_intfc, std::uint32_t a_type, std::uint32_t a_version);
56  bool Save(SerializationInterface* a_intfc);
57  bool Load(SerializationInterface* a_intfc);
59 
60  protected:
61  using Lock = std::recursive_mutex;
62  using Locker = std::lock_guard<Lock>;
63 
64  bool Register(const void* a_object, RE::FormID a_formID, EventFilter a_filter, RE::VMTypeID a_typeID);
65  bool Unregister(const void* a_object, RE::FormID a_formID, EventFilter a_filter, RE::VMTypeID a_typeID);
66  void UnregisterAll(const void* a_object, RE::FormID a_formID, RE::VMTypeID a_typeID);
67 
68  std::map<RE::FormID, EventFilterHandleMap> _regs;
70  mutable Lock _lock;
71  };
72 
73  template <class Enable, class... Args>
75 
76  template <class... Args>
78  std::enable_if_t<
79  std::conjunction_v<
80  RE::BSScript::is_return_convertible<Args>...>>,
81  Args...> :
83  {
84  private:
86 
87  public:
91 
92  inline RegistrationMapUnique(const std::string_view& a_eventName) :
93  super(a_eventName)
94  {}
95 
97 
100 
101  inline void SendEvent(const RE::TESObjectREFR* a_target, PassFilterFunc a_callback, Args... a_args)
102  {
103  RE::BSFixedString eventName(this->_eventName);
104 
106  const auto targetFormID = a_target->GetFormID();
107  if (auto it = this->_regs.find(targetFormID); it != this->_regs.end()) {
108  for (auto& [eventFilter, handles] : it->second) {
109  if (a_callback(eventFilter.first, eventFilter.second)) {
110  for (auto& handle : handles) {
111  auto copy = std::make_tuple(a_args...);
112  std::apply([&](auto&&... a_copy) {
113  auto args = RE::MakeFunctionArguments(std::forward<Args>(a_copy)...);
114  vm->SendEvent(handle, eventName, args);
115  },
116  copy);
117  }
118  }
119  }
120  }
121  }
122  }
123 
124  inline void QueueEvent(RE::TESObjectREFR* a_target, PassFilterFunc a_callback, Args... a_args)
125  {
126  std::tuple args(VMArg(std::forward<Args>(a_args))...);
127  auto task = GetTaskInterface();
128  assert(task);
129  if (task) {
130  task->AddTask([a_target, a_callback, args, this]() mutable {
131  SendEvent_Tuple(a_target, a_callback, std::move(args), index_sequence_for_tuple<decltype(args)>{});
132  });
133  }
134  }
135 
136  private:
137  template <class Tuple, std::size_t... I>
138  inline void SendEvent_Tuple(RE::TESObjectREFR* a_target, PassFilterFunc a_callback, Tuple&& a_tuple, std::index_sequence<I...>)
139  {
140  SendEvent(a_target, a_callback, std::get<I>(std::forward<Tuple>(a_tuple)).Unpack()...);
141  }
142  };
143 
144  template <>
146  {
147  private:
149 
150  public:
154 
155  inline RegistrationMapUnique(const std::string_view& a_eventName) :
156  super(a_eventName)
157  {}
158 
160 
163 
164  inline void SendEvent(const RE::TESObjectREFR* a_target, PassFilterFunc a_callback)
165  {
166  RE::BSFixedString eventName(this->_eventName);
167 
169  const auto targetFormID = a_target->GetFormID();
170  if (auto it = this->_regs.find(targetFormID); it != this->_regs.end()) {
171  for (auto& [eventFilter, handles] : it->second) {
172  if (a_callback(eventFilter.first, eventFilter.second)) {
173  for (auto& handle : handles) {
174  auto args = RE::MakeFunctionArguments();
175  vm->SendEvent(handle, eventName, args);
176  }
177  }
178  }
179  }
180  }
181  }
182 
183  inline void QueueEvent(RE::TESObjectREFR* a_target, PassFilterFunc a_callback)
184  {
185  auto task = GetTaskInterface();
186  assert(task);
187  task->AddTask([a_target, a_callback, this]() {
188  SendEvent(a_target, std::move(a_callback));
189  });
190  }
191  };
192  };
193 
194  template <class Filter>
196  _regs(),
197  _eventName(a_eventName),
198  _lock()
199  {}
200 
201  template <class Filter>
203  _regs(),
204  _eventName(a_rhs._eventName),
205  _lock()
206  {
207  a_rhs._lock.lock();
208  _regs = a_rhs._regs;
209  a_rhs._lock.unlock();
210 
212  if (auto policy = vm ? vm->GetObjectHandlePolicy() : nullptr) {
213  for (auto& reg : _regs) {
214  for (auto& keyHandles : reg.second) {
215  for (auto& handle : keyHandles.second) {
216  policy->PersistHandle(handle);
217  }
218  }
219  }
220  }
221  }
222 
223  template <class Filter>
225  _regs(),
226  _eventName(a_rhs._eventName),
227  _lock()
228  {
229  Locker locker(a_rhs._lock);
230  _regs = std::move(a_rhs._regs);
231  a_rhs._regs.clear();
232  }
233 
234  template <class Filter>
236  {
238  if (auto policy = vm ? vm->GetObjectHandlePolicy() : nullptr) {
239  for (auto& reg : _regs) {
240  for (auto& keyHandles : reg.second) {
241  for (auto& handle : keyHandles.second) {
242  policy->ReleaseHandle(handle);
243  }
244  }
245  }
246  }
247  }
248 
249  template <class Filter>
251  {
252  if (this == &a_rhs) {
253  return *this;
254  }
255 
256  Locker lhsLocker(_lock);
257  Clear();
258 
259  {
260  Locker rhsLocker(a_rhs._lock);
261  _regs = a_rhs._regs;
262  _eventName = a_rhs._eventName;
263  }
264 
266  if (auto policy = vm ? vm->GetObjectHandlePolicy() : nullptr) {
267  for (auto& reg : _regs) {
268  for (auto& keyHandles : reg.second) {
269  for (auto& handle : keyHandles.second) {
270  policy->PersistHandle(handle);
271  }
272  }
273  }
274  }
275 
276  return *this;
277  }
278 
279  template <class Filter>
281  {
282  if (this == &a_rhs) {
283  return *this;
284  }
285 
286  Locker lhsLocker(_lock);
287  Locker rhsLocker(a_rhs._lock);
288 
289  Clear();
290 
291  _eventName = a_rhs._eventName;
292 
293  _regs = std::move(a_rhs._regs);
294  a_rhs._regs.clear();
295 
296  return *this;
297  }
298 
299  template <class Filter>
300  bool EventFilterUnique<Filter>::RegistrationMapUniqueBase::Register(RE::TESForm* a_form, const Filter& a_filter, bool a_matchFilter)
301  {
302  assert(a_form);
303 
304  const auto reference = a_form->AsReference();
305  const auto formID = reference ? reference->GetFormID() : 0;
306 
307  if (formID != 0) {
308  return Register(a_form, formID, { a_filter, a_matchFilter }, static_cast<RE::VMTypeID>(a_form->GetFormType()));
309  }
310 
311  return false;
312  }
313 
314  template <class Filter>
315  bool EventFilterUnique<Filter>::RegistrationMapUniqueBase::Register(RE::ActiveEffect* a_activeEffect, const Filter& a_filter, bool a_matchFilter)
316  {
317  assert(a_activeEffect);
318 
319  const auto target = a_activeEffect->GetTargetActor();
320  const auto formID = target ? target->GetFormID() : 0;
321 
322  if (formID != 0) {
323  return Register(a_activeEffect, formID, { a_filter, a_matchFilter }, RE::ActiveEffect::VMTYPEID);
324  }
325 
326  return false;
327  }
328 
329  template <class Filter>
330  bool EventFilterUnique<Filter>::RegistrationMapUniqueBase::Register(RE::BGSRefAlias* a_alias, const Filter& a_filter, bool a_matchFilter)
331  {
332  assert(a_alias);
333 
334  const auto target = a_alias->GetActorReference();
335  const auto formID = target ? target->GetFormID() : 0;
336 
337  if (formID != 0) {
338  return Register(a_alias, formID, { a_filter, a_matchFilter }, RE::BGSRefAlias::VMTYPEID);
339  }
340 
341  return false;
342  }
343 
344  template <class Filter>
345  bool EventFilterUnique<Filter>::RegistrationMapUniqueBase::Unregister(RE::TESForm* a_form, const Filter& a_filter, bool a_matchFilter)
346  {
347  assert(a_form);
348 
349  const auto reference = a_form->AsReference();
350  const auto formID = reference ? reference->GetFormID() : 0;
351 
352  if (formID != 0) {
353  return Unregister(a_form, formID, { a_filter, a_matchFilter }, static_cast<RE::VMTypeID>(a_form->GetFormType()));
354  }
355 
356  return false;
357  }
358 
359  template <class Filter>
360  bool EventFilterUnique<Filter>::RegistrationMapUniqueBase::Unregister(RE::ActiveEffect* a_activeEffect, const Filter& a_filter, bool a_matchFilter)
361  {
362  assert(a_activeEffect);
363 
364  const auto target = a_activeEffect->GetTargetActor();
365  const auto formID = target ? target->GetFormID() : 0;
366 
367  if (formID != 0) {
368  return Unregister(a_activeEffect, formID, { a_filter, a_matchFilter }, RE::ActiveEffect::VMTYPEID);
369  }
370 
371  return false;
372  }
373 
374  template <class Filter>
375  bool EventFilterUnique<Filter>::RegistrationMapUniqueBase::Unregister(RE::BGSRefAlias* a_alias, const Filter& a_filter, bool a_matchFilter)
376  {
377  assert(a_alias);
378 
379  const auto target = a_alias->GetActorReference();
380  const auto formID = target ? target->GetFormID() : 0;
381 
382  if (formID != 0) {
383  return Unregister(a_alias, formID, { a_filter, a_matchFilter }, RE::BGSRefAlias::VMTYPEID);
384  }
385 
386  return false;
387  }
388 
389  template <class Filter>
391  {
392  assert(a_form);
393 
394  const auto reference = a_form->AsReference();
395  const auto formID = reference ? reference->GetFormID() : 0;
396 
397  if (formID != 0) {
398  UnregisterAll(a_form, formID, static_cast<RE::VMTypeID>(a_form->GetFormType()));
399  }
400  }
401 
402  template <class Filter>
404  {
405  assert(a_activeEffect);
406 
407  const auto target = a_activeEffect->GetTargetActor();
408  const auto formID = target ? target->GetFormID() : 0;
409 
410  if (formID != 0) {
411  UnregisterAll(a_activeEffect, formID, RE::ActiveEffect::VMTYPEID);
412  }
413  }
414 
415  template <class Filter>
417  {
418  assert(a_alias);
419 
420  const auto target = a_alias->GetActorReference();
421  const auto formID = target ? target->GetFormID() : 0;
422 
423  if (formID != 0) {
424  UnregisterAll(a_alias, formID, RE::BGSRefAlias::VMTYPEID);
425  }
426  }
427 
428  template <class Filter>
430  {
432  auto policy = vm ? vm->GetObjectHandlePolicy() : nullptr;
433  if (!policy) {
434  log::error("Failed to get handle policy!");
435  return;
436  }
437 
438  Locker locker(_lock);
439  for (auto& reg : _regs) {
440  for (auto& keyHandle : reg.second) {
441  if (auto result = keyHandle.second.erase(a_handle); result != 0) {
442  policy->ReleaseHandle(a_handle);
443  }
444  }
445  }
446  }
447 
448  template <class Filter>
450  {
452  auto policy = vm ? vm->GetObjectHandlePolicy() : nullptr;
453  if (!policy) {
454  log::error("Failed to get handle policy!");
455  return;
456  }
457 
458  Locker locker(_lock);
459  auto it = _regs.find(a_uniqueID);
460  if (it != _regs.end()) {
461  for (auto& keyHandles : it->second) {
462  for (auto& handle : keyHandles.second) {
463  policy->ReleaseHandle(handle);
464  }
465  }
466  _regs.erase(it);
467  }
468  }
469 
470  template <class Filter>
472  {
474  auto policy = vm ? vm->GetObjectHandlePolicy() : nullptr;
475  Locker locker(_lock);
476  if (policy) {
477  for (auto& reg : _regs) {
478  for (auto& keyHandle : reg.second) {
479  for (auto& handle : keyHandle.second) {
480  policy->ReleaseHandle(handle);
481  }
482  }
483  }
484  }
485  _regs.clear();
486  }
487 
488  template <class Filter>
489  bool EventFilterUnique<Filter>::RegistrationMapUniqueBase::Save(SerializationInterface* a_intfc, std::uint32_t a_type, std::uint32_t a_version)
490  {
491  assert(a_intfc);
492  if (!a_intfc->OpenRecord(a_type, a_version)) {
493  log::error("Failed to open record!");
494  return false;
495  }
496 
497  return Save(a_intfc);
498  }
499 
500  template <class Filter>
502  {
503  assert(a_intfc);
504  Locker locker(_lock);
505 
506  // Reg count
507  const std::size_t numRegs = _regs.size();
508  if (!a_intfc->WriteRecordData(numRegs)) {
509  log::error("Failed to save reg count ({})!", numRegs);
510  return false;
511  }
512  for (auto& reg : _regs) {
513  //FormID
514  if (!a_intfc->WriteRecordData(reg.first)) {
515  log::error("Failed to save handle formID ({:X})", reg.first);
516  return false;
517  }
518  std::size_t numUniqueHandle = reg.second.size();
519  if (!a_intfc->WriteRecordData(numUniqueHandle)) {
520  log::error("Failed to save handle count ({})!", numUniqueHandle);
521  return false;
522  }
523  // UniqueHandle
524  for (auto& [key, handles] : reg.second) {
525  // EventFilter
526  auto [eventFilter, match] = key;
527  if (!eventFilter.Save(a_intfc)) {
528  log::error("Failed to save event filters!");
529  return false;
530  }
531  if (!a_intfc->WriteRecordData(match)) {
532  log::error("Failed to save reg key as bool ({})!", match);
533  return false;
534  }
535  //handle set
536  std::size_t numHandles = handles.size();
537  if (!a_intfc->WriteRecordData(numHandles)) {
538  log::error("Failed to save handle count ({})!", numHandles);
539  return false;
540  }
541  for (auto& handle : handles) {
542  if (!a_intfc->WriteRecordData(handle)) {
543  log::error("Failed to save handle ({})", handle);
544  return false;
545  }
546  }
547  }
548  }
549 
550  return true;
551  }
552 
553  template <class Filter>
555  {
556  assert(a_intfc);
557  std::size_t numRegs;
558  a_intfc->ReadRecordData(numRegs);
559 
560  Locker locker(_lock);
561  _regs.clear();
562 
563  //FormID
564  RE::FormID formID;
565  // KeyHandle
566  std::size_t numKeyHandle;
567  // Handle
568  std::size_t numHandles;
569  RE::VMHandle vmHandle;
570 
571  for (std::size_t i = 0; i < numRegs; ++i) {
572  a_intfc->ReadRecordData(formID);
573  if (!a_intfc->ResolveFormID(formID, formID)) {
574  log::warn("Failed to resolve target formID ({:X})", formID);
575  continue;
576  }
577  a_intfc->ReadRecordData(numKeyHandle);
578  for (std::size_t j = 0; j < numKeyHandle; ++j) {
579  // filter
580  Filter eventFilter{};
581  if (!eventFilter.Load(a_intfc)) {
582  log::error("Failed to save event filters!");
583  continue;
584  }
585  bool match;
586  a_intfc->ReadRecordData(match);
587  EventFilter curKey = { eventFilter, match };
588  // handles
589  a_intfc->ReadRecordData(numHandles);
590  for (std::size_t k = 0; k < numHandles; ++k) {
591  a_intfc->ReadRecordData(vmHandle);
592  if (a_intfc->ResolveHandle(vmHandle, vmHandle)) {
593  _regs[formID][curKey].insert(vmHandle);
594  }
595  }
596  }
597  }
598 
599  return true;
600  }
601 
602  template <class Filter>
604  {
605  Clear();
606  }
607 
608  template <class Filter>
610  {
611  assert(a_object);
613  auto policy = vm ? vm->GetObjectHandlePolicy() : nullptr;
614  if (!policy) {
615  log::error("Failed to get handle policy!");
616  return false;
617  }
618 
619  const auto invalidHandle = policy->EmptyHandle();
620  auto handle = policy->GetHandleForObject(a_typeID, a_object);
621  if (handle == invalidHandle) {
622  log::error("Failed to create handle!");
623  return false;
624  }
625 
626  _lock.lock();
627  auto result = _regs[a_formID][a_filter].insert(handle);
628  _lock.unlock();
629 
630  if (result.second) {
631  policy->PersistHandle(handle);
632  }
633 
634  return result.second;
635  }
636 
637  template <class Filter>
639  {
640  assert(a_object);
642  auto policy = vm ? vm->GetObjectHandlePolicy() : nullptr;
643  if (!policy) {
644  log::error("Failed to get handle policy!");
645  return false;
646  }
647 
648  const auto invalidHandle = policy->EmptyHandle();
649  const auto handle = policy->GetHandleForObject(a_typeID, a_object);
650  if (handle == invalidHandle) {
651  log::error("Failed to create handle!");
652  return false;
653  }
654 
655  Locker locker(_lock);
656  if (auto formIt = _regs.find(a_formID); formIt != _regs.end()) {
657  if (auto keyIt = formIt->second.find(a_filter); keyIt != formIt->second.end()) {
658  if (auto result = keyIt->second.erase(handle); result != 0) {
659  policy->ReleaseHandle(handle);
660  return true;
661  }
662  }
663  }
664 
665  return false;
666  }
667 
668  template <class Filter>
670  {
671  assert(a_object);
673  auto policy = vm ? vm->GetObjectHandlePolicy() : nullptr;
674  if (!policy) {
675  log::error("Failed to get handle policy!");
676  return;
677  }
678 
679  const auto invalidHandle = policy->EmptyHandle();
680  const auto handle = policy->GetHandleForObject(a_typeID, a_object);
681  if (handle == invalidHandle) {
682  log::error("Failed to create handle!");
683  return;
684  }
685 
686  Locker locker(_lock);
687  if (auto it = _regs.find(a_formID); it != _regs.end()) {
688  for (auto& keyHandles : it->second) {
689  if (auto result = keyHandles.second.erase(handle); result != 0) {
690  policy->ReleaseHandle(handle);
691  }
692  }
693  }
694  }
695  }
696 
697  template <class Filter, class... Args>
699 }
Definition: ActiveEffect.h:27
static constexpr auto VMTYPEID
Definition: ActiveEffect.h:31
Actor * GetTargetActor()
Definition: BGSRefAlias.h:15
static constexpr auto VMTYPEID
Definition: BGSRefAlias.h:19
Actor * GetActorReference() const
static VirtualMachine * GetSingleton()
Definition: TESForm.h:36
TESObjectREFR * AsReference()
Definition: TESForm.h:271
FormType GetFormType() const noexcept
Definition: TESForm.h:290
FormID GetFormID() const noexcept
Definition: TESForm.h:289
Definition: TESObjectREFR.h:114
Definition: RegistrationMapUnique.h:32
std::recursive_mutex Lock
Definition: RegistrationMapUnique.h:61
bool Load(SerializationInterface *a_intfc)
Definition: RegistrationMapUnique.h:554
void Clear()
Definition: RegistrationMapUnique.h:471
~RegistrationMapUniqueBase()
Definition: RegistrationMapUnique.h:235
void Revert(SerializationInterface *)
Definition: RegistrationMapUnique.h:603
Lock _lock
Definition: RegistrationMapUnique.h:70
std::map< RE::FormID, EventFilterHandleMap > _regs
Definition: RegistrationMapUnique.h:68
bool Register(RE::TESForm *a_form, const Filter &a_filter, bool a_matchFilter)
Definition: RegistrationMapUnique.h:300
bool Save(SerializationInterface *a_intfc, std::uint32_t a_type, std::uint32_t a_version)
Definition: RegistrationMapUnique.h:489
RegistrationMapUniqueBase & operator=(const RegistrationMapUniqueBase &a_rhs)
Definition: RegistrationMapUnique.h:250
bool Unregister(RE::TESForm *a_form, const Filter &a_filter, bool a_matchFilter)
Definition: RegistrationMapUnique.h:345
void UnregisterAll(const RE::TESForm *a_form)
Definition: RegistrationMapUnique.h:390
std::string _eventName
Definition: RegistrationMapUnique.h:69
std::lock_guard< Lock > Locker
Definition: RegistrationMapUnique.h:62
void SendEvent(const RE::TESObjectREFR *a_target, PassFilterFunc a_callback, Args... a_args)
Definition: RegistrationMapUnique.h:101
void QueueEvent(RE::TESObjectREFR *a_target, PassFilterFunc a_callback, Args... a_args)
Definition: RegistrationMapUnique.h:124
RegistrationMapUnique & operator=(const RegistrationMapUnique &)=default
RegistrationMapUnique & operator=(RegistrationMapUnique &&)=default
RegistrationMapUnique(const RegistrationMapUnique &)=default
void SendEvent(const RE::TESObjectREFR *a_target, PassFilterFunc a_callback)
Definition: RegistrationMapUnique.h:164
RegistrationMapUnique(const std::string_view &a_eventName)
Definition: RegistrationMapUnique.h:155
void QueueEvent(RE::TESObjectREFR *a_target, PassFilterFunc a_callback)
Definition: RegistrationMapUnique.h:183
Definition: RegistrationMapUnique.h:74
Definition: RegistrationMapUnique.h:24
std::function< bool(const Filter &, bool)> PassFilterFunc
Definition: RegistrationMapUnique.h:29
std::map< EventFilter, std::set< RE::VMHandle > > EventFilterHandleMap
Definition: RegistrationMapUnique.h:27
std::pair< Filter, bool > EventFilter
Definition: RegistrationMapUnique.h:26
Definition: Interfaces.h:82
bool ResolveHandle(RE::VMHandle a_oldHandle, RE::VMHandle &a_newHandle) const
std::uint32_t ReadRecordData(void *a_buf, std::uint32_t a_length) const
bool WriteRecordData(const void *a_buf, std::uint32_t a_length) const
bool ResolveFormID(RE::FormID a_oldFormID, RE::FormID &a_newFormID) const
bool OpenRecord(std::uint32_t a_type, std::uint32_t a_version) const
constexpr REL::ID Save(static_cast< std::uint64_t >(34818))
std::uint32_t FormID
Definition: BSCoreTypes.h:5
auto make_tuple(T1 &&a_first, T2 &&a_second)
Definition: BSTTuple.h:187
std::uint32_t VMTypeID
Definition: BSCoreTypes.h:9
std::uint64_t VMHandle
Definition: BSCoreTypes.h:7
BSScript::IFunctionArguments * MakeFunctionArguments(Args &&... a_args)
Definition: FunctionArguments.h:80
VMArg(T &&) -> VMArg< T >
string(const CharT(&)[N]) -> string< CharT, N - 1 >
Definition: API.h:14
typename Impl::EventFilterUnique< Filter >::template RegistrationMapUnique< void, Args... > RegistrationMapUnique
Definition: RegistrationMapUnique.h:698
const TaskInterface * GetTaskInterface() noexcept
Definition: EffectArchetypes.h:65
Definition: RegistrationTraits.h:40