// Copyright (C) 2015 Jérôme Leclercq // This file is part of the "Nazara Engine - Core module" // For conditions of distribution and use, see copyright notice in Config.hpp #include #include #include template NzSignal::NzSignal(NzSignal&& signal) { operator=(std::move(signal)); } template void NzSignal::Clear() { m_slots.clear(); } template typename NzSignal::Connection NzSignal::Connect(const Callback& func) { return Connect(Callback(func)); } template typename NzSignal::Connection NzSignal::Connect(Callback&& func) { NazaraAssert(func, "Invalid function"); auto tempPtr = std::make_shared(this); tempPtr->callback = std::move(func); tempPtr->index = m_slots.size(); m_slots.emplace_back(std::move(tempPtr)); return Connection(m_slots.back()); } template template typename NzSignal::Connection NzSignal::Connect(O& object, void (O::*method) (Args...)) { return Connect([&object, method] (Args&&... args) { return (object .* method) (std::forward(args)...); }); } template template typename NzSignal::Connection NzSignal::Connect(O* object, void (O::*method)(Args...)) { return Connect([object, method] (Args&&... args) { return (object ->* method) (std::forward(args)...); }); } template void NzSignal::operator()(Args... args) const { for (const SlotPtr& slot : m_slots) slot->callback(args...); } template NzSignal& NzSignal::operator=(NzSignal&& signal) { m_slots = std::move(signal.m_slots); // We need to update the signal pointer inside of each slot for (SlotPtr& slot : m_slots) slot->signal = this; return *this; } template void NzSignal::Disconnect(const SlotPtr& slot) { NazaraAssert(slot, "Invalid slot pointer"); NazaraAssert(slot->index < m_slots.size(), "Invalid slot index"); // "Swap this slot with the last one and pop" idiom // This will preserve slot indexes SlotPtr& current = m_slots[slot->index]; std::swap(current, m_slots.back()); m_slots.pop_back(); current->index = slot->index; //< Update the moved slot index } template NzSignal::Connection::Connection(const SlotPtr& slot) : m_ptr(slot) { } template void NzSignal::Connection::Disconnect() { if (SlotPtr ptr = m_ptr.lock()) ptr->signal->Disconnect(ptr); } template bool NzSignal::Connection::IsConnected() const { return !m_ptr.expired(); } template NzSignal::ConnectionGuard::ConnectionGuard(const Connection& connection) : m_connection(connection) { } template NzSignal::ConnectionGuard::ConnectionGuard(Connection&& connection) : m_connection(std::move(connection)) { } template NzSignal::ConnectionGuard::~ConnectionGuard() { m_connection.Disconnect(); } template typename NzSignal::Connection& NzSignal::ConnectionGuard::GetConnection() { return m_connection; } template typename NzSignal::ConnectionGuard& NzSignal::ConnectionGuard::operator=(const Connection& connection) { m_connection.Disconnect(); m_connection = connection; return *this; } template typename NzSignal::ConnectionGuard& NzSignal::ConnectionGuard::operator=(Connection&& connection) { m_connection.Disconnect(); m_connection = std::move(connection); return *this; } template typename NzSignal::ConnectionGuard& NzSignal::ConnectionGuard::operator=(ConnectionGuard&& connection) { m_connection.Disconnect(); m_connection = std::move(connection.m_connection); return *this; } #include