cscg22-gearboy

CSCG 2022 Challenge 'Gearboy'
git clone https://git.sinitax.com/sinitax/cscg22-gearboy
Log | Files | Refs | sfeed.txt

SDL_touch.c (9036B)


      1/*
      2  Simple DirectMedia Layer
      3  Copyright (C) 1997-2014 Sam Lantinga <slouken@libsdl.org>
      4
      5  This software is provided 'as-is', without any express or implied
      6  warranty.  In no event will the authors be held liable for any damages
      7  arising from the use of this software.
      8
      9  Permission is granted to anyone to use this software for any purpose,
     10  including commercial applications, and to alter it and redistribute it
     11  freely, subject to the following restrictions:
     12
     13  1. The origin of this software must not be misrepresented; you must not
     14     claim that you wrote the original software. If you use this software
     15     in a product, an acknowledgment in the product documentation would be
     16     appreciated but is not required.
     17  2. Altered source versions must be plainly marked as such, and must not be
     18     misrepresented as being the original software.
     19  3. This notice may not be removed or altered from any source distribution.
     20*/
     21#include "../SDL_internal.h"
     22
     23/* General touch handling code for SDL */
     24
     25#include "SDL_assert.h"
     26#include "SDL_events.h"
     27#include "SDL_events_c.h"
     28
     29
     30static int SDL_num_touch = 0;
     31static SDL_Touch **SDL_touchDevices = NULL;
     32
     33
     34/* Public functions */
     35int
     36SDL_TouchInit(void)
     37{
     38    return (0);
     39}
     40
     41int
     42SDL_GetNumTouchDevices(void)
     43{
     44    return SDL_num_touch;
     45}
     46
     47SDL_TouchID
     48SDL_GetTouchDevice(int index)
     49{
     50    if (index < 0 || index >= SDL_num_touch) {
     51        SDL_SetError("Unknown touch device");
     52        return 0;
     53    }
     54    return SDL_touchDevices[index]->id;
     55}
     56
     57static int
     58SDL_GetTouchIndex(SDL_TouchID id)
     59{
     60    int index;
     61    SDL_Touch *touch;
     62
     63    for (index = 0; index < SDL_num_touch; ++index) {
     64        touch = SDL_touchDevices[index];
     65        if (touch->id == id) {
     66            return index;
     67        }
     68    }
     69    return -1;
     70}
     71
     72SDL_Touch *
     73SDL_GetTouch(SDL_TouchID id)
     74{
     75    int index = SDL_GetTouchIndex(id);
     76    if (index < 0 || index >= SDL_num_touch) {
     77        SDL_SetError("Unknown touch device");
     78        return NULL;
     79    }
     80    return SDL_touchDevices[index];
     81}
     82
     83static int
     84SDL_GetFingerIndex(const SDL_Touch * touch, SDL_FingerID fingerid)
     85{
     86    int index;
     87    for (index = 0; index < touch->num_fingers; ++index) {
     88        if (touch->fingers[index]->id == fingerid) {
     89            return index;
     90        }
     91    }
     92    return -1;
     93}
     94
     95SDL_Finger *
     96SDL_GetFinger(const SDL_Touch * touch, SDL_FingerID id)
     97{
     98    int index = SDL_GetFingerIndex(touch, id);
     99    if (index < 0 || index >= touch->num_fingers) {
    100        return NULL;
    101    }
    102    return touch->fingers[index];
    103}
    104
    105int
    106SDL_GetNumTouchFingers(SDL_TouchID touchID)
    107{
    108    SDL_Touch *touch = SDL_GetTouch(touchID);
    109    if (touch) {
    110        return touch->num_fingers;
    111    }
    112    return 0;
    113}
    114
    115SDL_Finger *
    116SDL_GetTouchFinger(SDL_TouchID touchID, int index)
    117{
    118    SDL_Touch *touch = SDL_GetTouch(touchID);
    119    if (!touch) {
    120        return NULL;
    121    }
    122    if (index < 0 || index >= touch->num_fingers) {
    123        SDL_SetError("Unknown touch finger");
    124        return NULL;
    125    }
    126    return touch->fingers[index];
    127}
    128
    129int
    130SDL_AddTouch(SDL_TouchID touchID, const char *name)
    131{
    132    SDL_Touch **touchDevices;
    133    int index;
    134
    135    index = SDL_GetTouchIndex(touchID);
    136    if (index >= 0) {
    137        return index;
    138    }
    139
    140    /* Add the touch to the list of touch */
    141    touchDevices = (SDL_Touch **) SDL_realloc(SDL_touchDevices,
    142                                      (SDL_num_touch + 1) * sizeof(*touchDevices));
    143    if (!touchDevices) {
    144        return SDL_OutOfMemory();
    145    }
    146
    147    SDL_touchDevices = touchDevices;
    148    index = SDL_num_touch++;
    149
    150    SDL_touchDevices[index] = (SDL_Touch *) SDL_malloc(sizeof(*SDL_touchDevices[index]));
    151    if (!SDL_touchDevices[index]) {
    152        return SDL_OutOfMemory();
    153    }
    154
    155    /* we're setting the touch properties */
    156    SDL_touchDevices[index]->id = touchID;
    157    SDL_touchDevices[index]->num_fingers = 0;
    158    SDL_touchDevices[index]->max_fingers = 0;
    159    SDL_touchDevices[index]->fingers = NULL;
    160
    161    /* Record this touch device for gestures */
    162    /* We could do this on the fly in the gesture code if we wanted */
    163    SDL_GestureAddTouch(touchID);
    164
    165    return index;
    166}
    167
    168static int
    169SDL_AddFinger(SDL_Touch *touch, SDL_FingerID fingerid, float x, float y, float pressure)
    170{
    171    SDL_Finger *finger;
    172
    173    if (touch->num_fingers == touch->max_fingers) {
    174        SDL_Finger **new_fingers;
    175        new_fingers = (SDL_Finger **)SDL_realloc(touch->fingers, (touch->max_fingers+1)*sizeof(*touch->fingers));
    176        if (!new_fingers) {
    177            return SDL_OutOfMemory();
    178        }
    179        touch->fingers = new_fingers;
    180        touch->fingers[touch->max_fingers] = (SDL_Finger *)SDL_malloc(sizeof(*finger));
    181        if (!touch->fingers[touch->max_fingers]) {
    182            return SDL_OutOfMemory();
    183        }
    184        touch->max_fingers++;
    185    }
    186
    187    finger = touch->fingers[touch->num_fingers++];
    188    finger->id = fingerid;
    189    finger->x = x;
    190    finger->y = y;
    191    finger->pressure = pressure;
    192    return 0;
    193}
    194
    195static int
    196SDL_DelFinger(SDL_Touch* touch, SDL_FingerID fingerid)
    197{
    198    SDL_Finger *temp;
    199
    200    int index = SDL_GetFingerIndex(touch, fingerid);
    201    if (index < 0) {
    202        return -1;
    203    }
    204
    205    touch->num_fingers--;
    206    temp = touch->fingers[index];
    207    touch->fingers[index] = touch->fingers[touch->num_fingers];
    208    touch->fingers[touch->num_fingers] = temp;
    209    return 0;
    210}
    211
    212int
    213SDL_SendTouch(SDL_TouchID id, SDL_FingerID fingerid,
    214              SDL_bool down, float x, float y, float pressure)
    215{
    216    int posted;
    217    SDL_Finger *finger;
    218
    219    SDL_Touch* touch = SDL_GetTouch(id);
    220    if (!touch) {
    221        return -1;
    222    }
    223
    224    finger = SDL_GetFinger(touch, fingerid);
    225    if (down) {
    226        if (finger) {
    227            /* This finger is already down */
    228            return 0;
    229        }
    230
    231        if (SDL_AddFinger(touch, fingerid, x, y, pressure) < 0) {
    232            return 0;
    233        }
    234
    235        posted = 0;
    236        if (SDL_GetEventState(SDL_FINGERDOWN) == SDL_ENABLE) {
    237            SDL_Event event;
    238            event.tfinger.type = SDL_FINGERDOWN;
    239            event.tfinger.touchId = id;
    240            event.tfinger.fingerId = fingerid;
    241            event.tfinger.x = x;
    242            event.tfinger.y = y;
    243            event.tfinger.dx = 0;
    244            event.tfinger.dy = 0;
    245            event.tfinger.pressure = pressure;
    246            posted = (SDL_PushEvent(&event) > 0);
    247        }
    248    } else {
    249        if (!finger) {
    250            /* This finger is already up */
    251            return 0;
    252        }
    253
    254        posted = 0;
    255        if (SDL_GetEventState(SDL_FINGERUP) == SDL_ENABLE) {
    256            SDL_Event event;
    257            event.tfinger.type = SDL_FINGERUP;
    258            event.tfinger.touchId =  id;
    259            event.tfinger.fingerId = fingerid;
    260            /* I don't trust the coordinates passed on fingerUp */
    261            event.tfinger.x = finger->x;
    262            event.tfinger.y = finger->y;
    263            event.tfinger.dx = 0;
    264            event.tfinger.dy = 0;
    265            event.tfinger.pressure = pressure;
    266            posted = (SDL_PushEvent(&event) > 0);
    267        }
    268
    269        SDL_DelFinger(touch, fingerid);
    270    }
    271    return posted;
    272}
    273
    274int
    275SDL_SendTouchMotion(SDL_TouchID id, SDL_FingerID fingerid,
    276                    float x, float y, float pressure)
    277{
    278    SDL_Touch *touch;
    279    SDL_Finger *finger;
    280    int posted;
    281    float xrel, yrel, prel;
    282
    283    touch = SDL_GetTouch(id);
    284    if (!touch) {
    285        return -1;
    286    }
    287
    288    finger = SDL_GetFinger(touch,fingerid);
    289    if (!finger) {
    290        return SDL_SendTouch(id, fingerid, SDL_TRUE, x, y, pressure);
    291    }
    292
    293    xrel = x - finger->x;
    294    yrel = y - finger->y;
    295    prel = pressure - finger->pressure;
    296
    297    /* Drop events that don't change state */
    298    if (!xrel && !yrel && !prel) {
    299#if 0
    300        printf("Touch event didn't change state - dropped!\n");
    301#endif
    302        return 0;
    303    }
    304
    305    /* Update internal touch coordinates */
    306    finger->x = x;
    307    finger->y = y;
    308    finger->pressure = pressure;
    309
    310    /* Post the event, if desired */
    311    posted = 0;
    312    if (SDL_GetEventState(SDL_FINGERMOTION) == SDL_ENABLE) {
    313        SDL_Event event;
    314        event.tfinger.type = SDL_FINGERMOTION;
    315        event.tfinger.touchId = id;
    316        event.tfinger.fingerId = fingerid;
    317        event.tfinger.x = x;
    318        event.tfinger.y = y;
    319        event.tfinger.dx = xrel;
    320        event.tfinger.dy = yrel;
    321        event.tfinger.pressure = pressure;
    322        posted = (SDL_PushEvent(&event) > 0);
    323    }
    324    return posted;
    325}
    326
    327void
    328SDL_DelTouch(SDL_TouchID id)
    329{
    330    int i;
    331    int index = SDL_GetTouchIndex(id);
    332    SDL_Touch *touch = SDL_GetTouch(id);
    333
    334    if (!touch) {
    335        return;
    336    }
    337
    338    for (i = 0; i < touch->max_fingers; ++i) {
    339        SDL_free(touch->fingers[i]);
    340    }
    341    SDL_free(touch->fingers);
    342    SDL_free(touch);
    343
    344    SDL_num_touch--;
    345    SDL_touchDevices[index] = SDL_touchDevices[SDL_num_touch];
    346}
    347
    348void
    349SDL_TouchQuit(void)
    350{
    351    int i;
    352
    353    for (i = SDL_num_touch; i--; ) {
    354        SDL_DelTouch(SDL_touchDevices[i]->id);
    355    }
    356    SDL_assert(SDL_num_touch == 0);
    357
    358    SDL_free(SDL_touchDevices);
    359    SDL_touchDevices = NULL;
    360}
    361
    362/* vi: set ts=4 sw=4 expandtab: */