21 template<
typename... Args>
class Slot;
27 template <
typename... Args>
31 using Function = std::function<void(Args... args)>;
69 #ifdef NAP_ENABLE_PYTHON
73 void connect(
const pybind11::function pythonFunction);
74 #endif // NAP_ENABLE_PYTHON
79 template <
typename U,
typename F>
82 connect(std::bind(memberFunction,
object, std::placeholders::_1));
90 trigger(std::forward<Args>(args)...);
121 Slot<Args...>* mSlot;
125 enum class EType : uint8_t
135 std::vector<Data> mData;
136 std::unique_ptr<std::vector<Function>> mFunctionEffects;
146 template <
typename... Args>
150 using Function = std::function<void(Args... args)>;
157 mFunction(inFunction)
163 template <
typename U,
typename F>
164 Slot(U* parent, F memberFunction) :
165 mFunction(std::bind(memberFunction, parent, std::placeholders::_1))
171 template <
typename U,
typename F>
173 mFunction(std::bind(memberFunction, parent, std::placeholders::_1))
196 mFunction(std::forward<Args>(args)...);
201 for (
auto cause : rhs.mCauses)
202 cause->connect(*
this);
206 template<
typename... Args_>
friend class Signal;
212 typedef std::vector<
Signal<Args...>*> SignalList;
222 template <
typename... Args>
225 for (
auto& data : mData)
227 if (data.mType == Data::EType::SignalCause)
228 data.Signal.mSignal->disconnect(*
this);
229 else if (data.mType == Data::EType::SignalEffect)
230 data.Signal.mSignal->removeCause(*
this);
232 data.Slot.mSlot->removeCause(*
this);
236 template <
typename... Args>
240 data.mType = Data::EType::SignalCause;
241 data.Signal.mSignal = &signal;
242 mData.push_back(data);
245 template <
typename... Args>
246 void Signal<Args...>::removeCause(Signal<Args...>& event)
248 for (
int index = 0; index < mData.size(); ++index)
250 Data& value = mData[index];
251 if (value.mType == Data::EType::SignalCause && value.Signal.mSignal == &event)
253 mData.erase(mData.begin() + index);
259 template <
typename... Args>
263 data.mType = Data::EType::SignalEffect;
264 data.Signal.mSignal = &signal;
265 mData.push_back(data);
267 signal.addCause(*
this);
270 template <
typename... Args>
273 for (
int index = 0; index < mData.size(); ++index)
275 Data& value = mData[index];
276 if (value.mType == Data::EType::SignalEffect && value.Signal.mSignal == &signal)
278 value.Signal.mSignal->removeCause(*
this);
279 mData.erase(mData.begin() + index);
285 template <
typename... Args>
289 data.mType = Data::EType::SlotEffect;
290 data.Slot.mSlot = &slot;
291 mData.push_back(data);
293 slot.addCause(*
this);
296 template <
typename... Args>
299 for (
int index = 0; index < mData.size(); ++index)
301 Data& data = mData[index];
302 if (data.mType == Data::EType::SlotEffect && data.Slot.mSlot == &slot)
304 data.Slot.mSlot->removeCause(*
this);
305 mData.erase(mData.begin() + index);
312 template <
typename... Args>
315 if (!mFunctionEffects)
316 mFunctionEffects = std::make_unique<std::vector<Function>>();
318 mFunctionEffects->emplace_back(inFunction);
321 #ifdef NAP_ENABLE_PYTHON
322 template <
typename... Args>
325 Function func = [pythonFunction](Args... args)
329 pythonFunction(pybind11::cast(std::forward<Args>(args)..., std::is_lvalue_reference<Args>::value
330 ? pybind11::return_value_policy::reference : pybind11::return_value_policy::automatic_reference)...);
332 catch (
const pybind11::error_already_set& err)
334 auto message = std::string(
"Runtime python error while executing signal: ") + std::string(err.what());
338 std::cout << message << std::endl;
343 #endif // NAP_ENABLE_PYTHON
346 template <
typename... Args>
349 for (
auto& data : mData)
351 if (data.mType == Data::EType::SignalEffect)
352 data.Signal.mSignal->trigger(std::forward<Args>(args)...);
353 else if (data.mType == Data::EType::SlotEffect)
354 data.Slot.mSlot->trigger(std::forward<Args>(args)...);
357 if (mFunctionEffects)
358 for (
auto& effect : *mFunctionEffects)
359 effect(std::forward<Args>(args)...);
362 template <
typename... Args>
365 for (
int index = mCauses.size() - 1; index >= 0; --index)
369 template <
typename... Args>
372 mCauses.push_back(&event);
375 template <
typename... Args>
376 void Slot<Args...>::removeCause(Signal<Args...>& event)
378 for (
typename SignalList::iterator pos = mCauses.begin(); pos != mCauses.end(); ++pos)
380 if ((*pos) == &event)
397 #define NSLOT(NAME, TYPE, FUNCTION) nap::Slot<TYPE> NAME = {[&](TYPE inValue) -> void { FUNCTION(inValue); }};
400 #define CREATE_SLOT(NAME, TYPE) nap::Slot<TYPE> NAME;
403 #define BIND_SLOT(NAME, TYPE, FUNCTION) NAME([&](TYPE inValue) -> void { FUNCTION(inValue); })
406 #define NSIGNAL(NAME, TYPE) nap::Signal<TYPE> NAME;