Blog (19)
Komentarze (63)
Recenzje (0)

[OpenGL] Obsługa klawiatury

@vircung[OpenGL] Obsługa klawiatury04.07.2012 15:41

Dzisiaj chciałbym poruszyć temat możliwych do zarejestrowania funkcji. Dodatkowo zacznę implementować obsługę klawiatury aby można było w łatwy sposób wykryć wciśnięcie kilku klawiszy na raz. Wpis jest pisany w pewnym stopniu bez planu (oczywiście poruszane zagadnienia już w pewien sposób zostały przeze mnie przerobione). Jeżeli więc wpis nie "rozrośnie się" zbytnio to przejdę do tematu obsługi kamery oraz myszki. Zaczynajmy więc!

Słowem wstępu

Po pomyślnej konfiguracji projektu czas przejść do pisania kodu. Jak już wcześniej zostało powiedziane, wszystkie zmiany są zapisywane i umieszczane w repozytorium na github.com. Będę dodawał nowe commity w miarę dodawania nowych funkcji, zmiennych i modyfikacji. Czyli ogólnie pojętej funkcjonalności. W tym oraz w każdym kolejnym wpisie będę podawał linki do poszczególnych commitów abyś mógł w łatwy sposób śledzić postępy.

Funkcje klawiatury

Biblioteka GLUT udostępnia dwie funkcje do naciśnięć klawiszy na klawiaturze glutKeyboardFunc oraz glutSpecialFunc. Natomiast FreeGLUT dodaje kolejne dwie glutKeyboardUpFunc oraz glutSpecialUpFunc do zdarzeń zwolnienia klawisza.

Na samym początku trzeba oczywiście zdefiniować odpowiednie funkcje, oczywiście zgodne z dokumentacją. Niech ich standardową funkcjonalnością będzie wyświetlanie komunikatu o znaku klawisza, którego stan został zmieniony. Jeżeli będą to klawisze specjalne, wyświetlany będzie kod klawisza. Komunikaty będą wyświetlane na standardowym wyjściu log'u clog. Dlatego wymagane jest też dołączenie odpowiedniego nagłówka pozwalającego na to.

Warto już tutaj wspomnieć o tym, że klawisze podstawowe posiadają kod typu unsigned char. Oznacza to, że kody są z zakresu [0;255] i mogą być wyświetlane jako znak ASCII. Natomiast funkcja obsługująca klawisze specjalne rozróżnia je typem wyliczeniowym, który przekazywany jest jako int, zatem wyświetlanie ich jest kłopotliwe z uwagi na zakres typu. Dlatego będziemy wyświetlać tylko ich kod.

Implementacje

Konstrukcja funkcji obsługujących zwykłe klawisze jest prosta. Składa się ze switcha, który w prosty sposób będzie realizował zadanie.


void keyFunc(unsigned char key, int x, int y){

	switch(key) {
	default:
		std::clog << "Nacisnieo klawisz " << (char)key <<" kod "<< (int)key << "\n";
		break;
	}
}  

void keyUpFunc(unsigned char key, int x, int y){

	switch(key) {
	default:
		std::clog << "Zwoniono klawisz " << (char)key <<" kod "<< (int)key << "\n";
		break;
	}
}

Aby uzyskać podobną złożoność funkcji dla klawiszy specjalnych zdefiniujemy funkcję pomocniczą przyjmującą w parametrze kod klawisza, a zwracającą ciąg znaków. Pojawia się jednak problem, ponieważ w implementacji FreeGLUT nie doszukałem się zdefiniowania stałej przeznaczonej do używania w funkcji klawiszy specjalnych dla klawiszy CRTL, ALT, i SHIFT zarówno tych z lewej jak i prawej strony klawiatury. Natomiast funkcja normalnych klawiszy obsługuje je lecz nie rozróżnia strony lewej od prawej. Pozostaje więc odpowiednio zmodyfikować poprzednie funkcje aby klawisze były obsługiwane jak najdokładniej lecz nie podwójnie.


std::string getSpecialKeyString(int key){
	switch(key){
	case GLUT_KEY_F1:
		return "F1";
	case GLUT_KEY_F2:
		return "F2";
	case GLUT_KEY_F3:
		return "F3";
	case GLUT_KEY_F4:
		return "F4";
	case GLUT_KEY_F5:
		return "F5";
	case GLUT_KEY_F6:
		return "F6";
	case GLUT_KEY_F7:
		return "F7";
	case GLUT_KEY_F8:
		return "F8";
	case GLUT_KEY_F9:
		return "F9";
	case GLUT_KEY_F10:
		return "F10";
	case GLUT_KEY_F11:
		return "F11";
	case GLUT_KEY_F12:
		return "F12";
	case GLUT_KEY_PAGE_UP:
		return "PAGE UP";
	case GLUT_KEY_PAGE_DOWN:
		return "PAGE DOWN";
	case GLUT_KEY_HOME:
		return "HOME";
	case GLUT_KEY_END:
		return "END";
	case GLUT_KEY_LEFT:
		return "LEFT";
	case GLUT_KEY_RIGHT:
		return "RIGHT";
	case GLUT_KEY_UP:
		return "UP";
	case GLUT_KEY_DOWN:
		return "DOWN";
	case GLUT_KEY_INSERT:
		return "INSERT";
	case 0x70:
		return "LEFT SHIFT";
	case 0x71:
		return "RIGHT SHIFT";
	case 0x72:
		return "LEFT CTRL";
	case 0x73:
		return "RIGHT CTRL";
	case 0x74:
		return "LEFT ALT";
	case 0x75:
		return "RIGHT ALT";
	default:
		return "UNKNOWN";
	}
}

Funkcje przygotowane do zarejestrowania będą miały następujące postaci


void specialKey(int key, int x, int y){
	std::string _key = getSpecialKeyString(key);

	std::clog << "Nacisnieo klawisz " << _key.c_str() <<" kod "<< key << "\n";
}

void specialKeyUp(int key, int x, int y){
	std::string _key = getSpecialKeyString(key);

	std::clog << "Zwolniono klawisz " << _key.c_str() <<" kod "<< key << "\n";
}

Teraz pozostaje podpiąć je do odpowiednich zdarzeń GLUT w funkcji main bądź init.


	glutKeyboardFunc(keyFunc);
	glutKeyboardUpFunc(keyUpFunc);
	glutSpecialFunc(specialKey);
	glutSpecialUpFunc(specialKeyUp);

Wciśnij więcej niż 2

Pozostała jedna rzecz. Mianowicie detekcja wciśnięcia kilku klawiszy jednocześnie. W tym celu posłużymy się dwoma buforami. Będzie w nich przechowywany stan poszczególnych klawiszy oraz kombinacji klawiszy. Będzie odbywało się to poprzez zmianę flagi (wartości bool) w odpowiedniej tablicy, oczywiście utworzonej przez nas.


bool* keys = new bool[255]();
bool* specialKeys = new bool[128]();

Pierwsza tablica odpowiada normalnym klawiszom alfanumerycznym, druga natomiast klawiszom specjalnym. Rozmiar pierwszej tablicy nie powinien być zagadką. Zgodnie z tym co wyświetla się w oknie konsoli programu mamy nie więcej niż 128 klawiszy specjalnych, więc ta liczba wydaje się odpowiednią. Warto dodać, że tablice są od razu wypełniane wartością false. Zostaje teraz dodanie kilku linijek kody w celu zapalania (wartość true) i gaszenia (wartość false) wybranych flag w tablicach oraz oczywiście sprawdzenie, czy to rozwiązanie działa. Zalecam wybranie dowolnej kombinacji trzech klawiszy i wyświetlenie trójkąta tylko wtedy gdy są one jednocześnie wciśnięte, ja wybrałem klawisze LCTRL + LALT + LSHIFT. Po wykryciu wciśnięcia klawisza dobrze jest zarządać odświerzenia okna, można to uzyskać za pomoca funkcji glutPostRedisplay(). Dla ułatwienia rozróżniania tych klawiszy dodałem dodatkowe definicje dla compilatora.


#define  GLUT_KEY_LSHIFT    0x0070
#define  GLUT_KEY_RSHIFT    0x0071
#define  GLUT_KEY_LCTRL     0x0072
#define  GLUT_KEY_RCTRL     0x0073
#define  GLUT_KEY_LALT      0x0074
#define  GLUT_KEY_RALT      0x0075

Na tym zakończę implementowanie obsługi klawiatury. Na koniec dodam, że możliwe jest zdefiniowane kilku takich funkcji o odpowiednio podpinanie ich do GLUT'a w czasie wykonywania programu. Zademonstruję to w którymś z najbliższych wpisów. Jak zwykle zachęcam do zostawiania komentarzy. Finalny kod z dzisiejszego wpisu znajdziecie w tym commicie.

Ciao :)

Szanowna Użytkowniczko! Szanowny Użytkowniku!
×
Aby dalej móc dostarczać coraz lepsze materiały redakcyjne i udostępniać coraz lepsze usługi, potrzebujemy zgody na dopasowanie treści marketingowych do Twojego zachowania. Twoje dane są u nas bezpieczne, a zgodę możesz wycofać w każdej chwili na podstronie polityka prywatności.

Kliknij "PRZECHODZĘ DO SERWISU" lub na symbol "X" w górnym rogu tej planszy, jeżeli zgadzasz się na przetwarzanie przez Wirtualną Polskę i naszych Zaufanych Partnerów Twoich danych osobowych, zbieranych w ramach korzystania przez Ciebie z usług, portali i serwisów internetowych Wirtualnej Polski (w tym danych zapisywanych w plikach cookies) w celach marketingowych realizowanych na zlecenie naszych Zaufanych Partnerów. Jeśli nie zgadzasz się na przetwarzanie Twoich danych osobowych skorzystaj z ustawień w polityce prywatności. Zgoda jest dobrowolna i możesz ją w dowolnym momencie wycofać zmieniając ustawienia w polityce prywatności (w której znajdziesz odpowiedzi na wszystkie pytania związane z przetwarzaniem Twoich danych osobowych).

Od 25 maja 2018 roku obowiązuje Rozporządzenie Parlamentu Europejskiego i Rady (UE) 2016/679 (określane jako "RODO"). W związku z tym chcielibyśmy poinformować o przetwarzaniu Twoich danych oraz zasadach, na jakich odbywa się to po dniu 25 maja 2018 roku.

Kto będzie administratorem Twoich danych?

Administratorami Twoich danych będzie Wirtualna Polska Media Spółka Akcyjna z siedzibą w Warszawie, oraz pozostałe spółki z grupy Wirtualna Polska, jak również nasi Zaufani Partnerzy, z którymi stale współpracujemy. Szczegółowe informacje dotyczące administratorów znajdują się w polityce prywatności.

O jakich danych mówimy?

Chodzi o dane osobowe, które są zbierane w ramach korzystania przez Ciebie z naszych usług, portali i serwisów internetowych udostępnianych przez Wirtualną Polskę, w tym zapisywanych w plikach cookies, które są instalowane na naszych stronach przez Wirtualną Polskę oraz naszych Zaufanych Partnerów.

Dlaczego chcemy przetwarzać Twoje dane?

Przetwarzamy je dostarczać coraz lepsze materiały redakcyjne, dopasować ich tematykę do Twoich zainteresowań, tworzyć portale i serwisy internetowe, z których będziesz korzystać z przyjemnością, zapewniać większe bezpieczeństwo usług, udoskonalać nasze usługi i maksymalnie dopasować je do Twoich zainteresowań, pokazywać reklamy dopasowane do Twoich potrzeb. Szczegółowe informacje dotyczące celów przetwarzania Twoich danych znajdują się w polityce prywatności.

Komu możemy przekazać dane?

Twoje dane możemy przekazywać podmiotom przetwarzającym je na nasze zlecenie oraz podmiotom uprawnionym do uzyskania danych na podstawie obowiązującego prawa – oczywiście tylko, gdy wystąpią z żądaniem w oparciu o stosowną podstawę prawną.

Jakie masz prawa w stosunku do Twoich danych?

Masz prawo żądania dostępu, sprostowania, usunięcia lub ograniczenia przetwarzania danych. Możesz wycofać zgodę na przetwarzanie, zgłosić sprzeciw oraz skorzystać z innych praw wymienionych szczegółowo w polityce prywatności.

Jakie są podstawy prawne przetwarzania Twoich danych?

Podstawą prawną przetwarzania Twoich danych w celu świadczenia usług jest niezbędność do wykonania umów o ich świadczenie (tymi umowami są zazwyczaj regulaminy). Podstawą prawną przetwarzania danych w celu pomiarów statystycznych i marketingu własnego administratorów jest tzw. uzasadniony interes administratora. Przetwarzanie Twoich danych w celach marketingowych realizowanych przez Wirtualną Polskę na zlecenie Zaufanych Partnerów i bezpośrednio przez Zaufanych Partnerów będzie odbywać się na podstawie Twojej dobrowolnej zgody.