diff --git a/Engine/source/core/util/journal/process.h b/Engine/source/core/util/journal/process.h index 19040e747..4d21898d9 100644 --- a/Engine/source/core/util/journal/process.h +++ b/Engine/source/core/util/journal/process.h @@ -96,6 +96,11 @@ public: get()._signalProcess.notify(del,order); } + static void notify(SignalSlot &slot, F32 order = PROCESS_DEFAULT_ORDER) + { + get()._signalProcess.notify(slot,order); + } + template static void notify(T func, F32 order = PROCESS_DEFAULT_ORDER) { diff --git a/Engine/source/core/util/tSignal.h b/Engine/source/core/util/tSignal.h index 08e2f6646..d13fb534e 100644 --- a/Engine/source/core/util/tSignal.h +++ b/Engine/source/core/util/tSignal.h @@ -77,6 +77,8 @@ protected: void insert(DelegateLink* node, F32 order); void unlink(); + + virtual ~DelegateLink() {} }; DelegateLink mList; @@ -92,6 +94,78 @@ protected: Vector mTriggerNext; }; +template 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 + void setDelegate( const X &fn ) { setDelegate( DelegateSig( fn ) ); } + + template + 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 class SignalBaseT : public SignalBase { public: @@ -163,6 +237,18 @@ public: notify(dlg, order); } + void notify( SignalSlot &slot, F32 order = 0.5f) + { + if( !slot.getDelegate() ) + return; + + if( slot.isConnected() ) + slot.disconnect(); + + slot._setSignal( this ); + mList.insert( new SlotLinkImpl(slot), order ); + } + template void remove(T obj,U func) { @@ -198,6 +284,23 @@ protected: DelegateLinkImpl(DelegateSig dlg) : mDelegate(dlg) {} }; + struct SlotLinkImpl : public DelegateLinkImpl + { + SlotLinkImpl(SignalSlot& slot) : mSlot( &slot ), DelegateLinkImpl( slot.getDelegate() ) + { + + } + + ~SlotLinkImpl() + { + if( mSlot ) + mSlot->_setSignal( NULL ); + } + + protected: + SignalSlot *mSlot; + }; + DelegateSig & getDelegate(SignalBase::DelegateLink * link) { return ((DelegateLinkImpl*)link)->mDelegate; diff --git a/Engine/source/windowManager/win32/win32WindowMgr.cpp b/Engine/source/windowManager/win32/win32WindowMgr.cpp index f92d40027..3777a01f6 100644 --- a/Engine/source/windowManager/win32/win32WindowMgr.cpp +++ b/Engine/source/windowManager/win32/win32WindowMgr.cpp @@ -41,7 +41,8 @@ PlatformWindowManager * CreatePlatformWindowManager() Win32WindowManager::Win32WindowManager() { // Register in the process list. - Process::notify(this, &Win32WindowManager::_process, PROCESS_INPUT_ORDER); + mOnProcessSignalSlot.setDelegate( this, &Win32WindowManager::_process ); + Process::notify( mOnProcessSignalSlot, PROCESS_INPUT_ORDER ); // Init our list of allocated windows. mWindowListHead = NULL; @@ -58,9 +59,6 @@ Win32WindowManager::Win32WindowManager() Win32WindowManager::~Win32WindowManager() { - // Get ourselves off the process list. - Process::remove(this, &Win32WindowManager::_process); - // Kill all our windows first. while(mWindowListHead) // The destructors update the list, so this works just fine. diff --git a/Engine/source/windowManager/win32/win32WindowMgr.h b/Engine/source/windowManager/win32/win32WindowMgr.h index a5c747501..be9cdaa42 100644 --- a/Engine/source/windowManager/win32/win32WindowMgr.h +++ b/Engine/source/windowManager/win32/win32WindowMgr.h @@ -85,6 +85,8 @@ class Win32WindowManager : public PlatformWindowManager /// If a curtain window is present, then its HWND will be stored here. HWND mCurtainWindow; + SignalSlot mOnProcessSignalSlot; + public: Win32WindowManager(); ~Win32WindowManager();