Vianoce v ITnetwork sú tu! Dobí si teraz kredity a získaj až 80 % extra kreditov na e-learningové kurzy ZADARMO. Zisti viac.
Hľadáme nové posily do ITnetwork tímu. Pozri sa na voľné pozície a pridaj sa k najagilnejšej firme na trhu - Viac informácií.

13. diel - SDĽ - Vlastné udalosti a filtrovanie

V aplikácii často potrebujeme vlastné udalosti. Môže sa jednať o základné veci, ako vznik kolízie, spustenie určitého zvuku a ďalej. Všetky tieto veci možno (ale nie je nutné) riešiť cez udalosti. Preto si dnes ukážeme, ako môžeme vytvoriť vlastné udalosť a vložiť ju do fronty.

Vytvorenie vlastných udalostí

K vytvoreniu vlastnej udalosti budeme potrebovať vlastný typ. type je Uint32, to znamená, že môže nadobúdať celkovo 0xFFFF = 65535 hodnôt. Konštanta SDL_USEREVENT, od ktorej by mali druhy vlastných udalostí začínať, má hodnotu 0x8000 = 32768. Sami teda môžeme vytvoriť celkom 32767 udalostí - máme dostatok priestoru pre vlastné udalosti. Tým by som našu matematickú vložku ukončil a pozrieme sa na praktickú časť.

Najjednoduchšie je si pre každú udalosť vytvoriť konštantu v hlavičkovom súbore. Neskôr nebudeme musieť riešiť kolízie, až sa počet udalostí zväčší nad únosnú mieru. Druhou možnosťou je typy udalostí generovať za behu programu pomocou funkcie SDL_RegisterE­vents. Ak už nebudú k dispozícii ďalšie voľné udalosti, program vráti (Uint32)-1. Osobne sa prikláňam ku konštantám v hlavičkových súboroch. Bohužiaľ nie sú oba postupy navzájom kompatibilné.

Pre užívateľské udalosti máme k dispozícii SDL_UserEvent, ku ktorému pristupuje skrz user atribút. Štruktúra má dva ukazovatele typu void, to znamená, že môžeme preniesť prakticky ľubovoľné dáta, respektíve ukazovatele na ne. Nakoniec musíme udalosť vložiť do fronty funkcií SDL_PushEvent alebo SDL_PeepEvents.

Filtrovanie udalostí

Všetky filtrovacie funkcie pracujú s internou frontom - prebieha počas hovoru SDL_PumpEvents. Ako už bolo poznamenané na začiatku, v aplikácii sa nedozvieme o tom, že používateľ práve teraz niečo vykonáva. Vždy sa dozvieme len to, že niečo vykonal. Okamžitá spätná väzba nie je možná. To je dôvod, prečo filtrovanie prebieha až počas prenášania udalostí z externej frontu do internej.

Prvá možnosť je zablokovať všetky udalosti určitého typu. Použijeme na to funkciu SDL_EventState. V prvom parametri odovzdáme typ udalosti, ktorú nechceme v aplikácii získavať. Druhým parametrom je jedna z hodnôt SDL_QUERY pre opýtaní na aktuálny stav, SDL_IGNORE pre ignorovanie udalosti a SDL_ENABLE pre opätovné získavanie udalosti.

Ďalší v rade sú funkcie SDL_SetEventFil­ter a SDL_GetEventFil­ter. Nižšie uvádzam definícia každej funkcie.

int YourEventFilter(void* userdata, SDL_Event* event);
void SDL_SetEventFilter(SDL_EventFilter filter, void* userdata);
SDL_bool SDL_GetEventFilter(SDL_EventFilter* filter, void**  userdata);

Pri nastavení filtra môžeme druhým parametrom odovzdať ľubovoľný objekt, ktorý dostane filtrovacie funkcie pri jej zavolanie. Ak filtrovacie funkcie vráti hodnotu 0, udalosť nebude do internej fronty pridaná. Naopak pri hodnote 1 pridaná bude. Funkcia by mala byť skutočne použitá pre filtrovanie. Ak nás bude zaujímať iba vnútorný stav udalosti, použijeme Event Watch.

Event Watch pridáme funkcií SDL_AddEventWatch a zmažeme funkcií SDL_DelEventWat­ch.

int YourEventFilter(void* userdata, SDL_Event* event);
void SDL_AddEventWatch(SDL_EventFilter filter, void* userdata);
void SDL_DelEventWatch(SDL_EventFilter filter, void* userdata);

Vidíme, že callback je rovnaký ako pre filter. Na rozdiel od neho, vrátená hodnota callbacku je ignorovaná a ako je podľa pomenovania funkcií zrejmé, callback môže byť niekoľko. Môžeme mať samostatný callback pre každý typ udalosti, ale bude potreba na začiatku každého callbacku overiť, či ide o správny typ. Nie je možné nikde nastaviť, pre ktorý typ udalosti je callback určený - je volaný pre všetky typy.

Použitie filtra a Event Watch nie je tak jednoduché, ako by sa na prvý pohľad mohlo zdať. Obaja Callback môžu bežať v samostatnom vlákne. Problematika viacvláknových aplikácií je mimo rozsah tohto tutoriálu. Tu platí iba jednoduché pravidlo - dáta odovzdané pri vytváraní callbacku by sa nemala v žiadnej časti aplikácie meniť. Potom bude všetko fungovať, ako má. Callback sa volajú aj pre udalosti vložené do fronty funkcií SDL_PushEvent, ale už nie pre funkciu SDL_PeepEvents. Pri návrhu programu je s tým potrebné počítať.

Posledná funkcia je SDL_FilterEvents. V tomto prípade prebehne odovzdaný callback pre každú udalosť v internej fronte. Ide o jednorazovú záležitosť na aktuálne interné fronte.

Funkcie sú zoradené tak, ako prebiehajú za sebou. Ak funkcie spomínaná vyššie odfiltruje udalosť, funkcie alebo callback spomínaný pod ňou už neprebehne. Ak nastavíme SDL_KEYDOWN state na SDL_IGNORE, Event Watch sa nezavolá. Pre prehľadnosť uvádzam graf (prvý prebehne funkcia vľavo).

SDL_EventState -> SDL_ SetEventFilter -> SDL_AddEventWatch -> SDL_FilterEvents

Príklad

Priložený program obsahuje aj prvky z minulej lekcie a demonštruje vytvorenie vlastnej udalosti, filtrovanie a zmazanie udalosti po SDL_WarpMouseInWindow. V budúcom diele už opustíme udalosti a pozrieme sa na zvyšok veci, ktoré nám ešte chýba. Bude to napríklad abstrakcie súborov alebo viacvláknové programovanie.


 

Stiahnuť

Stiahnutím nasledujúceho súboru súhlasíš s licenčnými podmienkami

Stiahnuté 645x (11.77 MB)

 

Predchádzajúci článok
SDĽ - Všeobecná práca s udalosťami
Všetky články v sekcii
SDĽ
Preskočiť článok
(neodporúčame)
SDĽ - RWops, vlákna a ďalšie
Článok pre vás napísal Patrik Valkovič
Avatar
Užívateľské hodnotenie:
Ešte nikto nehodnotil, buď prvý!
Věnuji se programování v C++ a C#. Kromě toho také programuji v PHP (Nette) a JavaScriptu (NodeJS).
Aktivity