Появилось еще немного времени на игрушку. Недавно скачал юнити 5, поковырял новый гуй, и понял что хочу такой же. Действия кнопочек\слайдеров\радиокнопок выполняются через делегаты, но в цпп нет делегатов. Пришлось запилить.

class ruIContainer {
public:
virtual ~ruIContainer() {
};
virtual void Call() = 0;
};
template< class T, class M > class ruContainer : public ruIContainer {
private:
T * mClass;
M mMethod;
public:
explicit ruContainer( T * theClass, M theMethod ) : mClass( theClass ), mMethod( theMethod ) {
};
virtual void Call() {
(mClass->*mMethod)();
}
};
class ruDelegate {
private:
ruIContainer * mContainer;
public:
ruDelegate() : mContainer( nullptr ) {
};
~ruDelegate() {
if( mContainer ) {
delete mContainer;
}
}
ruDelegate( const ruDelegate & other ) {
mContainer = other.mContainer;
(const_cast<ruDelegate&>(other)).mContainer = nullptr;
}
template< class T, class M > static ruDelegate Bind( T * theClass, M theMethod ) {
ruDelegate delegat;
delegat.mContainer = new ruContainer< T, M >( theClass, theMethod );
return delegat;
}
void Call() {
if( mContainer ) {
mContainer->Call();
}
}
void operator = ( const ruDelegate & other ) {
mContainer = other.mContainer;
(const_cast<ruDelegate&>(other)).mContainer = nullptr;
}
};
class ruEvent {
private:
vector<ruDelegate> mListenerList;
public:
void AddListener( const ruDelegate & delegat ) {
mListenerList.push_back( delegat );
}
void RemoveAllListeners() {
mListenerList.clear();
}
void DoActions() {
for( auto iter = mListenerList.begin(); iter != mListenerList.end(); iter++ ) {
iter->Call();
}
}
};
Пользуюсь так
... где-то внутри класса Menu
button.AddListener( ruDelegate::Bind( this, &Menu::OnButtonClick ));
Плюсы делегатов для гуя можно перечислять долго, но от себя скажу, что с ними я запилил модальные окна для вопросов, анимацию элементов меню и много еще чего. И все очень удобно, не нужно городить неведомый спагетти-код.
Немного скриншотов, графон в гуй не завезли - и скрины заболели джпегом. Кстати последние скрины с исправленным хдр и без него.