11. diel - SDĽ - Udalosti myši
Dnes sa bližšie pozrieme na udalosti, ktoré môže vyvolať myš. Myš má dva typy udalostí - posun a stlačenie tlačidla. Najskôr sa pozrieme na stlačenie tlačidla myši, potom na posun a nakoniec aj na koliesko myši. V závere tiež uvediem funkcie, ktoré SDL poskytuje pre editáciu ukazovateľa myši.
SDL_MouseButtonEvent
SDL_MouseButtonEvent nám poskytuje informáciu o stlačení tlačidla myši. Opäť uvediem definíciu.
typedef struct SDL_MouseButtonEvent { Uint32 type; Uint32 timestamp; Uint32 windowID; Uint32 which; Uint8 button; Uint8 state; Uint8 clicks; Sint32 x; Sint32 y; } SDL_MouseButtonEvent;
- type je rovnako ako u klávesnice rozdielny pre stlačenie alebo
uvoľnenie tlačidla. Môže nadobúdať hodnoty
SDL_MOUSEBUTTONDOWN
aleboSDL_MOUSEBUTTONUP
. - which môže obsahovať
SDL_TOUCH_MOUSEID
alebo ID myši. ID myši nám v aplikácii moc platné nie je, aleSDL_TOUCH_MOUSEID
sa generuje vo chvíli, keď je udalosť pôvodne dotyková. Ak zachytávame SDL_TouchFingerEvent môžeme udalosť s týmto príznakom ignorovať. V opačnom prípade vidíme, že môžeme s dotykovou obrazovkou pracovať rovnako, ako by užívateľ používal klasickú myš. - state je rovnako ako u klávesnice duplicitné informácie.
Nadobúda hodnôt
SDL_PRESSED
aSDL_RELEADED
. - clicks nám povie, či sa jednalo o jedno kliknutie alebo dvojité (double click), prípadne či používateľ klikol viackrát. Tento atribút je zaradený do SDL až od verzie 2.0.2.
- Z x a y sa dozvieme, kde užívateľ klikol. Jedná sa o celé číslo udávané v pixeloch a merané relatívne k ľavému hornému rohu okna.
Úmyselne som vynechal najdôležitejšia časť - atribút button.
Ten môže nadobúdať jednu z piatich hodnôt a povie nám, ktorého tlačidlá
sa udalosť týka. Najčastejšie používané hodnoty sú
SDL_BUTTON_LEFT
, SDL_BUTTON_MIDDLE
,
SDL_BUTTON_RIGHT
pre lacné, prostredný (koliesko) a pravé
tlačidlo. Na Windows som zistil, že aj keď nastavíme tlačidla obrátene
(voľba "zameniť ľavé a pravé tlačidlo"), bude brať pravé tlačidlo ako
ľavé a obrátene, teda tak, ako zodpovedá ich funkcionalite. Pre vývojárov
určite dobrá správa.
SDL poskytuje naviac ešte ďalšie dve konštanty, a to
SDL_BUTTON_X1
a SDL_BUTTON_X2
pre myši s piatimi
tlačidlami (napríklad na boku). Bohužiaľ aktuálne takú myš nevlastným,
preto som funkčnosť nemohol overiť.
SDL_MouseMotionEvent
SDL_MouseMotionEvent informuje o posune myši na obrazovke. Opäť priložím definíciu a popis.
typedef struct SDL_MouseMotionEvent { Uint32 type; Uint32 timestamp; Uint32 windowID; Uint32 which; Uint32 state; Sint32 x; Sint32 y; Sint32 xrel; Sint32 yrel; } SDL_MouseMotionEvent;
Atribúty type, timestamp, windowID,
which i state sú zhodné s predchádzajúcou udalosťou,
preto sa pozrieme iba na charakteristické atribúty pre
SDL_MouseMotionEvent
. Atribúty x a y sú
súradnice, kde myš s pohybom skončila. Tieto súradnice sú relatívne k
aktuálnemu oknu. Atribúty xrel a yrel nám udávajú, o
koľko sa myš posunula v smere vodorovnom, prípadne horizontálnym.
SDL poskytuje aj dve funkcie, ktoré ukazovateľ myši presunú. Sú nimi SDL_WarpMouseInWindow
a SDL_WarpMouseGlobal. Prvá uvedená presunie myš na súradnice
relatívna k oknu aplikácie, druhá potom relatívna k obrazovke. Prečo by sme
tieto dve funkcie potrebovali? Predstavme si, že programujeme FPS (strieľačku
z prvej osoby). Ak by hráč presunul myš ku kraju okna, program by nedostával
správy o pohybe myši, pretože by sa myš vlastne nikam nevyvážali, ale
zostávala by pri okraji. V takýchto prípadoch budeme najčastejšie po
každom pohybe presúvať myš späť na stred obrazovky. Aplikácia tak bude
neustále zachytávať pohyby myši. Obe funkcie sami vyvolávajú udalosť
SDL_MouseMotionEvent
, ktorú budeme musieť z frontu udalostí
odstrániť. Teda za predpokladu, že aplikácia nebude udalosť znova
potrebovať. Ukážka bude v priloženom programe na konci článku.
V SDL môžeme tiež nariadiť, aby bola myš zachytávaná aj mimo okno. Použijeme na to funkciu SDL_CaptureMouse. Nie je ale doporučené toho využívať príliš často. Na niektorých zariadení táto funkcionalita ani nie je možná. Po nastavení sa môže stať, že ostatné aplikácie prestanú dostávať správy o pohybe myši, pretože pôjdu všetky správy našej aplikácii. Hodnoty súradníc, kde je myš, sú stále stiahnuté k oknu našej aplikácie, to znamená, že môžu nadobúdať aj záporných hodnôt, s čím je potrebné v aplikácii počítať.
SDL_MouseWheelEvent
Nakoniec tu máme SDL_MouseWheelEvent, ktorý nám povie
informácie o rotácii kolieska myši. V predchádzajúcej verzii SDL bola táto
udalosť zaradená pod SDL_MouseButtonEvent
s tým, že medzi
tlačidlami boli zaradená ešte konštanty SDL_BUTTON_WHEELUP
a
SDL_BUTTON_WHEELDOWN
. V novšej verzii už má koliesko svoju
samostatnú udalosť.
typedef struct SDL_MouseWheelEvent { Uint32 type; Uint32 timestamp; Uint32 windowID; Uint32 which; Sint32 x; Sint32 y; } SDL_MouseWheelEvent;
Zásadná sú atribúty x a y. Prvý z nich nám povie o horizontálnej rotácii kolieska - teda sprava do ľava. Pre rotáciu doprava bude obsahovať hodnotu kladnú, pre posun doľava hodnotu zápornú. Druhý atribút obsahuje dáta z vertikálnej rotáciu kolieska. Pokiaľ bude užívateľ točiť kolieskom nahor (od seba), bude hodnota záporná, obrátený smer bude generovať hodnoty kladné.
V dokumentácii je uvedený ešte atribút direction
, ktorý je
tu pravdepodobne kvôli ostatným platformám, konieckoncov rovnako ako atribút
x - koľko z nás má na myši koliesko, ktoré možno točiť do všetkých 4
strán? Niektoré platformy môžu mať prevrátenú orientáciu (budú
generovať záporné hodnoty tam, kde očakávame kladné). V
direction
je uložená informácia, ktorá nám to oznámi. Tento
atribút je relevantný až od verzie 2.0.4, ktorá nebola v čase písania
článku stabilné, preto sa ním ďalej zaoberať nebudeme.
Zmena kurzora
SDL poskytuje viacero funkcií, pomocou ktorých môžeme zmeniť vzhľad
kurzora. Tieto funkcie vracia ukazovateľ na SDL_Cursor
, ktorý je
nutné následne uvoľniť funkcií SDL_FreeCursor.
Jediný kurzor, ktorý nie je nutné uvoľniť, je predvolený. Vytvorený
kurzor potom aktivujeme funkcií SDL_SetCursor.
Základné funkcie pre vytváranie kurzora je SDL_CreateCursor. Tento kurzor môže byť iba čiernobiely a jeho vytvorenie nie je tak jednoduché, ako u ostatných funkcií, preto funkciu nebudem popisovať. Pre prípadných záujemcov je v dokumentácii SDL uvedený príklad.
Funkciu, ktorú budeme používať častejšie, je
SDL_CreateSystemCursor, ktorá vytvorí jeden z predpripravených
kurzorov, ktoré poskytuje operačný systém. Ako parameter prijíma
konštantu, ktorá definuje jednotlivé kurzory. Nájdeme tak klasické
systémové kurzory ako presýpacie hodiny, ruka (ktorá sa objaví po prejdení
na odkaz) a ďalšie. Zoznam je opäť v dokumentácii. Posledná funkcia (a pre
nás najzaujímavejšie), je funkcia SDL_CreateColorCursor. Kurzor
vytvorí z SDL_Surface
, ktorú odovzdáme ako parameter. Môžeme
nastaviť aj bod, ktorým je aktivačný miesto - miesto, z ktorého sa berie
vstup myši. Použijeme na to parametre hot_x
a hot_y
.
Toto miesto teda nemusí byť iba v rohu SDL_Surface
, ale môže
byť kdekoľvek. Ukážka bude opäť v programe na konci článku.
Kurzor môžeme v aplikácii aj úplne schovať, a to funkciou
SDL_ShowCursor. Odovzdáme ak v parametri SDL_ENABLE
alebo
SDL_DISABLE
, kurzor sa zobrazí alebo skryje. Pre zistenie
aktuálneho stavu môžeme odovzdať SDL_QUERY
a funkcie vráti
hodnotu 1, ak sa kurzor zobrazený, v opačnom prípade vráti 0.
Predposledný funkcia je SDL_GetCursor, ktorá vráti aktuálne
používaný kurzor, alebo NULL
, pokiaľ nie je kurzor na
zariadení podporovaný. A konečne posledná je
SDL_GetDefaultCursor, ktorá vráti predvolený kurzor, ktorý bol
systémom nastavený.
Aktuálny stav myši
U myši okrem stlačených tlačidiel môžeme zistiť aj jej aktuálnu
pozíciu. Všetky tri funkcie, ktoré SDL poskytuje, vracia ORované hodnoty
jednotlivých tlačidiel. Predtým, než konštanty použijeme, na ne musíme
aplikovať SDL_BUTTON
makro. Funkcia tiež prijímajú dva
ukazovatele typu int
, v ktorých sa nám vráti aktuálnej pozície
myši. Môžeme odovzdať NULL
, ak nás súradnice nezaujímajú.
Prvou funkciou je SDL_GetMouseState, ktorá uspeje, len ak je myš v
okne a vracia súradnice relatívna k tomuto oknu, ďalej je funkcia
SDL_GetRelativeMouseState, ktorá vracia súradnice z celej
obrazovky, ale stále relatívna k oknu - súradnice môžu byť aj záporné.
Posledná funkcia je SDL_GetGlobalMouseState, ktorá opäť berie
myš z celej obrazovky, ale zároveň sú hodnoty relatívnej k obrazovke -
ľavý horný roh má súradnice 0,0. Použitie je ukázané v nasledujúcom
kóde.
if (SDL_GetMouseState(NULL, NULL) & SDL_BUTTON(SDL_BUTTON_LEFT)) { SDL_Log("Levé tlačítko myši bylo stisknuto"); }
Príklad
Ako príklad som zvolil aplikáciu, ktorá si nastaví vlastné ukazovateľ, ktorý nemá aktivačný oblasť v ľavom hornom rohu. Červený štvorec sa potom pohybuje podľa pohybu myši, ktorá sa po prekročení definovanej plochy premiestni späť. Ľavým tlačidlom myši môžeme presunúť štvorec späť do stredu, pravým tlačidlom kurzor skryjeme. Aplikáciu ukončíme kombináciou Alt + F4.
V budúcom dieli zostaneme u udalostí a bližšie sa pozrieme na manipuláciu s frontou udalostí.
Stiahnuť
Stiahnutím nasledujúceho súboru súhlasíš s licenčnými podmienkamiStiahnuté 875x (38.19 kB)