[ AmberSkyNet VR ]Я все-таки решил вынести функционал обработки событий из графического менеджера, несмотря на то, что в SDL эти понятия связаны (хотя бы тем, что без инициализации графического окна система событий работать не будет). Сейчас поясню зачем - есть ситуации, в которых графический менеджер не нужен, а менеджер событий - нужен всегда (например, в случае запуска приложения, написанного на движке, в качестве сервера, которому графику выводить совсем не обязательно). Написать отдельный класс, в котором функции графического менеджера будут представлены заглушками, конечно, можно.. Но проще разнести функционал обработки событий и вывода графики по разным классам, а точнее, выделить обработку событий из менеджера графики в отдельный класс. IEventManager
class IEventManager: public IManager {
public:
// читаем события из очереди
virtual int GetInput()=0;
virtual IEventListener* AddEventListener( const char *ListenerType )=0;
virtual bool AddCustomEventListener( IEventListener *listener )=0;
virtual int getLastKey()=0;
virtual UINT16 getUnicodeKey()=0;
virtual unsigned short getKeyModifier()=0;
};
GetInput - функция возвращет нам событие из очереди событий. Пока в виде int, потом, возможно,
напишу структуру, наподобие той, которая используется в SDL, чтобы иметь возможность
сохранять в файл последовательность событий и загружать из файла. Пригодится
для написания демок, да и в общем-то можно использовать в клиент-серверной архитектуре -
ловить текущие события, отбирать из них события, генерируемые действиями пользователя (перемещение,
заклинания, операции с вещами) и передавать на сервер. AddEventListener - при вызове этой функции менеджер событий обращается к менеджеру плагинов с запросом на создание экземпляра класса с именем ListenerType. AddCustomEventListerer - функция добавления своего прослушивателя событий. Можно во внешней программе создать свой класс слушателя событий, наследовав его от IEventListener, и добавить его в список слушателей событий менеджера событий. getLastKey - функция возвращает код последней нажатой клавиши (относительно текущего события, конечно). getUnicodeKey - функция возвращает код последней нажатой клавиши в unicode-кодировке. getKeyModifier - функция возвращает состояние нажатых клавиш-модификаторов (Shift, Alt.. итп) IEventListenerclass IEventListener: public virtual IBaseObject { public: virtual ~IEventListener(){}; virtual bool Listen(int Event)=0; }; Интерфейс к "слушателю" событий довольно прост. Интерес представляет только одна функция - Listen. Через эту функцию менеджер событий сообщает о текущем событии всем слушателям, которые находятся в его списке, когда у менеджера событий вызывается функция GetInput(). Таким образом вообще все события движка можно обратывать через слушатели событий, не анализируя в прикладной программе результат, возвращемый функцией GetInput. В дальнейшем, возможно, функционал менеджера событий будет расширен (скажем, добавлением функции генерации событий).. INodeModifierНад разными узлами сцены чаще всего требуется совершать однотипные операции - изменение углов поворота, движение в определенных границах. Мы можем написать классы различных модификаторв, скрывая их под одним интерфейсом - интерфейсом модификатора ноды INodeModifier.
class INodeModifier: public virtual IBaseObject {
public:
virtual int Modify(INode *node,float tms)=0;
// 0 - все ok
// 1 - модификатор удален
// 2... - ошибка
};
Я сделал так, чтобы при вызове Modify модификатору передавался указатель на узл сцены, которую следует обработать. Это сделано для того, чтобы оставить возможность обработки одним экземпляром класса модификатора нескольких узлов сцены. Далее напишем класс списка-"упаковки" модификаторов ноды. Это упростит задачу использования нескольких модификаторов в списке узла сцены. IModifierPackclass IModifierPack: public virtual IBaseObject { public: virtual UINT AddModifier(INodeModifier* modifier)=0; virtual UINT GetModifierCount()=0; virtual INodeModifier* GetModifier(UINT id)=0; virtual bool DelModifier(UINT id)=0; virtual bool Modify(INode *node, float tms)=0; }; AddModifier - функция добавляет модификатор ноды в список и возвращает номер модификатора в списке GetModifier - функция выдаёт число модификаторов в списке GetModifier - функция выдаёт указатель на модификатор ноды по его номеру DelModifier - функция удаляет модификатор из списка и вызывает его деструктор Modify - при вызове этой функции класса списка модификаторв у всех модификаторов в списке вызывается функция Modify(); Теперь при создании каждой ноды будет создаваться и экземпляр класса списка ее модификаторов. Получить указатель на него можно вызвав функцию GetPtrParam("ModifierPack"). Возможно, далее этот механизм будет доработан и вместо IModifierPack функции добавления и удаления модификаторов перейдут в интерфейс INode. Хорошей традицией становится отсуствие ссылок на версию движка.. =) |