mirror of
https://github.com/TorqueGameEngines/Torque3D.git
synced 2026-03-04 13:00:33 +00:00
Add SlotSignal for handle automatic disconnect on Signal or SignalSlot destruction.
Example:
```
Win32WindowManager::Win32WindowManager()
{
// Register in the process list.
mOnProcessSignalSlot.setDelegate( this, &Win32WindowManager::_process );
Process::notify( mOnProcessSignalSlot, PROCESS_INPUT_ORDER );
// When Signal it's destroyed, all slots are disconected.
// When a SignalSlot it's destroyed, it's disconected from Signal.
}
```
This commit is contained in:
parent
aca58356ee
commit
0137c86765
1 changed files with 103 additions and 0 deletions
|
|
@ -77,6 +77,8 @@ protected:
|
|||
|
||||
void insert(DelegateLink* node, F32 order);
|
||||
void unlink();
|
||||
|
||||
virtual ~DelegateLink() {}
|
||||
};
|
||||
|
||||
DelegateLink mList;
|
||||
|
|
@ -92,6 +94,78 @@ protected:
|
|||
Vector<DelegateLink*> mTriggerNext;
|
||||
};
|
||||
|
||||
template<typename Signature> class SignalBaseT;
|
||||
|
||||
/// Class for handle automatic diconnect form Signal when destroyed
|
||||
template< typename Signature >
|
||||
class SignalSlot
|
||||
{
|
||||
public:
|
||||
typedef Delegate< Signature > DelegateSig;
|
||||
typedef SignalBaseT< Signature > SignalSig;
|
||||
|
||||
SignalSlot() : mSignal(NULL)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
~SignalSlot()
|
||||
{
|
||||
disconnect();
|
||||
}
|
||||
|
||||
const DelegateSig& getDelegate() { return mDlg; }
|
||||
|
||||
/// setDelegate disconect form Signal old delegate and connect new delegate
|
||||
template<typename X>
|
||||
void setDelegate( const X &fn ) { setDelegate( DelegateSig( fn ) ); }
|
||||
|
||||
template<typename X, typename Y>
|
||||
void setDelegate( const X &ptr, const Y &fn ) { setDelegate( DelegateSig( ptr, fn ) ); }
|
||||
|
||||
void setDelegate( const DelegateSig &dlg)
|
||||
{
|
||||
SignalSig* signal = mSignal;
|
||||
if( isConnected() )
|
||||
disconnect();
|
||||
|
||||
mDlg = dlg;
|
||||
if( signal && mDlg )
|
||||
signal->notify( mDlg );
|
||||
}
|
||||
|
||||
/// is connected to Signal
|
||||
bool isConnected() const { return mSignal; }
|
||||
|
||||
/// disconnect from Signal
|
||||
void disconnect()
|
||||
{
|
||||
if( mSignal )
|
||||
{
|
||||
SignalSig *oldSignal = mSignal;
|
||||
mSignal = NULL;
|
||||
oldSignal->remove( mDlg );
|
||||
}
|
||||
}
|
||||
|
||||
protected:
|
||||
friend class SignalSig;
|
||||
|
||||
void _setSignal(SignalSig *sig)
|
||||
{
|
||||
mSignal = sig;
|
||||
}
|
||||
|
||||
SignalSig* _getSignal() const { return mSignal; }
|
||||
|
||||
DelegateSig mDlg;
|
||||
SignalSig *mSignal;
|
||||
|
||||
private:
|
||||
SignalSlot( const SignalSlot&) {}
|
||||
SignalSlot& operator=( const SignalSlot&) {}
|
||||
};
|
||||
|
||||
template<typename Signature> class SignalBaseT : public SignalBase
|
||||
{
|
||||
public:
|
||||
|
|
@ -163,6 +237,18 @@ public:
|
|||
notify(dlg, order);
|
||||
}
|
||||
|
||||
void notify( SignalSlot<Signature> &slot, F32 order = 0.5f)
|
||||
{
|
||||
if( !slot.getDelegate() )
|
||||
return;
|
||||
|
||||
if( slot.isConnected() )
|
||||
slot.disconnect();
|
||||
|
||||
slot._setSignal( this );
|
||||
mList.insert( new SlotLinkImpl(slot), order );
|
||||
}
|
||||
|
||||
template <class T,class U>
|
||||
void remove(T obj,U func)
|
||||
{
|
||||
|
|
@ -198,6 +284,23 @@ protected:
|
|||
DelegateLinkImpl(DelegateSig dlg) : mDelegate(dlg) {}
|
||||
};
|
||||
|
||||
struct SlotLinkImpl : public DelegateLinkImpl
|
||||
{
|
||||
SlotLinkImpl(SignalSlot<Signature>& slot) : mSlot( &slot ), DelegateLinkImpl( slot.getDelegate() )
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
~SlotLinkImpl()
|
||||
{
|
||||
if( mSlot )
|
||||
mSlot->_setSignal( NULL );
|
||||
}
|
||||
|
||||
protected:
|
||||
SignalSlot<Signature> *mSlot;
|
||||
};
|
||||
|
||||
DelegateSig & getDelegate(SignalBase::DelegateLink * link)
|
||||
{
|
||||
return ((DelegateLinkImpl*)link)->mDelegate;
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue