21 template<
typename... Args>
class Slot;
27 template <
typename... Args>
31 using Function = std::function<void(Args... args)>;
67 #ifdef NAP_ENABLE_PYTHON
71 void connect(
const pybind11::function pythonFunction);
72 #endif // NAP_ENABLE_PYTHON
77 template <
typename U,
typename F>
78 void connect(U*
object, F memberFunction) {
connect(std::bind(memberFunction,
object, std::placeholders::_1)); }
115 Slot<Args...>* mSlot;
119 enum class EType : uint8_t
129 std::vector<Data> mData;
130 std::unique_ptr<std::vector<Function>> mFunctionEffects;
138 template <
typename... Args>
142 using Function = std::function<void(Args... args)>;
153 mFunction(inFunction)
161 template <
typename U,
typename F>
162 Slot(U* parent, F memberFunction) :
163 mFunction(std::bind(memberFunction, parent, std::placeholders::_1))
172 template <
typename U,
typename F>
174 mFunction(std::bind(memberFunction, parent, std::placeholders::_1)) { signal.
connect(*
this); }
217 template<
typename... Args_>
friend class Signal;
218 typedef std::vector<
Signal<Args...>*> SignalList;
232 template <
typename... Args>
235 for (
auto& data : mData)
237 if (data.mType == Data::EType::SignalCause)
238 data.USignal.mSignal->disconnect(*
this);
239 else if (data.mType == Data::EType::SignalEffect)
240 data.USignal.mSignal->removeCause(*
this);
242 data.USlot.mSlot->removeCause(*
this);
246 template <
typename... Args>
250 data.mType = Data::EType::SignalCause;
251 data.USignal.mSignal = &signal;
252 mData.push_back(data);
255 template <
typename... Args>
256 void Signal<Args...>::removeCause(Signal<Args...>& event)
258 for (
int index = 0; index < mData.size(); ++index)
260 Data& value = mData[index];
261 if (value.mType == Data::EType::SignalCause && value.USignal.mSignal == &event)
263 mData.erase(mData.begin() + index);
269 template <
typename... Args>
273 data.mType = Data::EType::SignalEffect;
274 data.USignal.mSignal = &signal;
275 mData.push_back(data);
276 signal.addCause(*
this);
279 template <
typename... Args>
282 for (
int index = 0; index < mData.size(); ++index)
284 Data& value = mData[index];
285 if (value.mType == Data::EType::SignalEffect && value.USignal.mSignal == &signal)
287 value.USignal.mSignal->removeCause(*
this);
288 mData.erase(mData.begin() + index);
294 template <
typename... Args>
298 data.mType = Data::EType::SlotEffect;
299 data.USlot.mSlot = &slot;
300 mData.push_back(data);
301 slot.addCause(*
this);
304 template <
typename... Args>
307 for (
int index = 0; index < mData.size(); ++index)
309 Data& data = mData[index];
310 if (data.mType == Data::EType::SlotEffect && data.USlot.mSlot == &slot)
312 data.USlot.mSlot->removeCause(*
this);
313 mData.erase(mData.begin() + index);
320 template <
typename... Args>
323 if (!mFunctionEffects)
324 mFunctionEffects = std::make_unique<std::vector<Function>>();
326 mFunctionEffects->emplace_back(inFunction);
329 #ifdef NAP_ENABLE_PYTHON
330 template <
typename... Args>
333 Function func = [pythonFunction](Args... args)
337 pythonFunction(pybind11::cast(std::forward<Args>(args)..., std::is_lvalue_reference<Args>::value
338 ? pybind11::return_value_policy::reference : pybind11::return_value_policy::automatic_reference)...);
340 catch (
const pybind11::error_already_set& err)
342 auto message = std::string(
"Runtime python error while executing signal: ") + std::string(err.what());
346 std::cout << message << std::endl;
351 #endif // NAP_ENABLE_PYTHON
353 template <
typename... Args>
356 for (
auto& data : mData)
358 if (data.mType == Data::EType::SignalEffect)
359 data.USignal.mSignal->trigger(std::forward<Args>(args)...);
360 else if (data.mType == Data::EType::SlotEffect)
361 data.USlot.mSlot->trigger(std::forward<Args>(args)...);
364 if (mFunctionEffects)
365 for (
auto& effect : *mFunctionEffects)
366 effect(std::forward<Args>(args)...);
369 template <
typename... Args>
373 for (
auto cause : rhs.mCauses)
374 cause->connect(*
this);
377 template <
typename... Args>
381 mFunction = other.mFunction;
383 other.mFunction =
nullptr;
387 template <
typename... Args>
391 mFunction = other.mFunction;
395 template <
typename... Args>
399 mFunction(std::forward<Args>(args)...);
402 template <
typename... Args>
405 for (
int index = mCauses.size() - 1; index >= 0; --index)
409 template <
typename... Args>
412 mCauses.push_back(&event);
415 template <
typename... Args>
416 void Slot<Args...>::removeCause(Signal<Args...>& event)
418 for (
typename SignalList::iterator pos = mCauses.begin(); pos != mCauses.end(); ++pos)
420 if ((*pos) == &event)
437 #define NSLOT(NAME, TYPE, FUNCTION) nap::Slot<TYPE> NAME = {[&](TYPE inValue) -> void { FUNCTION(inValue); }};
440 #define CREATE_SLOT(NAME, TYPE) nap::Slot<TYPE> NAME;
443 #define BIND_SLOT(NAME, TYPE, FUNCTION) NAME([&](TYPE inValue) -> void { FUNCTION(inValue); })
446 #define NSIGNAL(NAME, TYPE) nap::Signal<TYPE> NAME;