Tutorial de SDL – Parte 55 – Multitoque

Continuando nossa série de artigos traduzidos do site lazyfoo, veremos agora como lidar com gestos multi-toque na tela de um dispositivo móvel.
Nesse artigo, estaremos usando a funcionalidade embutida do SDL 2 para lidar com gestos multi-toque como arrastar e rotacionar.

//Scene textures
LTexture gPinchCloseTexture;
LTexture gPinchOpenTexture;
LTexture gRotateTexture;

Como no artigo anterior, usaremos um conjunto de texturas para mostrar que tipo de evento está acontecendo.

            //Main loop flag
            bool quit = false;
            //Event handler
            SDL_Event e;
            //Touch variables
            SDL_Point touchLocation = { gScreenRect.w / 2, gScreenRect.h / 2 };
            LTexture* currentTexture = &gPinchOpenTexture;

Também como no artigo anterior, precisamos manter um registro do local onde o toque ocorreu e da textura a ser renderizada.

                    //Multi touch gesture
                    else if( e.type == SDL_MULTIGESTURE )
                    {
                        //Rotation detected
                        if( fabs( e.mgesture.dTheta ) > 3.14 / 180.0 )
                        {
                            touchLocation.x = e.mgesture.x * gScreenRect.w;
                            touchLocation.y = e.mgesture.y * gScreenRect.h;
                            currentTexture = &gRotateTexture;
                        }

Quando um evento multi-toque acontece, um evento SDL_MultiGestureEvent é disparado. Aqui verificamos por rotações primeiro, checando pelo ângulo do gesto. O que é preciso lembrar aqui é que a menor rotação será reportada, assim se você arrastar e rotacionar por uma fração de radianos, irá mostrar o gesto. Aqui verificamos se a rotação é ao menos de 1 grau antes de reportar como uma rotação. Se a rotação for grande o suficiente, configuramos o local do gesto e a textura.

                        //Pinch detected
                        else if( fabs( e.mgesture.dDist ) > 0.002 )
                        {
                            touchLocation.x = e.mgesture.x * gScreenRect.w;
                            touchLocation.y = e.mgesture.y * gScreenRect.h;
                            //Pinch open
                            if( e.mgesture.dDist > 0 )
                            {
                                currentTexture = &gPinchOpenTexture;
                            }
                            //Pinch close
                            else
                            {
                                currentTexture = &gPinchCloseTexture;
                            }
                        }
                    }

Se a rotação não for grande o suficiente, verificamos que a distância do arrasto. Sempre lembre-se que as coordenadas são normalizadas, então um arrasto de 10 pixels em um tablet cuja resolução é 1920 pixels será reportada como 0.0052. Se o arrasto for grande o suficiente, configuramos a posição do gesto e então verificamos se o arrasto foi para abrir ou fechar.

                //Clear screen
                SDL_SetRenderDrawColor( gRenderer, 0xFF, 0xFF, 0xFF, 0xFF );
                SDL_RenderClear( gRenderer );
                //Render touch texture
                currentTexture->render( touchLocation.x - currentTexture->getWidth() / 2, touchLocation.y - currentTexture->getHeight() / 2 );
                //Update screen
                SDL_RenderPresent( gRenderer );

Assim como no artigo anteror, na renderização mostramos a textura do gesto e a posição do gesto.

Baixe os arquivo de mídia e do código fonte desse artigo aqui.