123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171 |
- #include "button.h"
- #include <stdio.h>
- #include <stdlib.h>
- #define ERROR(...) fprintf(stderr, __VA_ARGS__)
- Button *buttonNew(const char *text, float x, float y, float w, float h,
- SDL_Texture *inactive, SDL_Texture *active,
- SDL_Color textColor, TTF_Font *font, ButtonSoundSet sounds,
- const Window *window) {
- Button *button = malloc(sizeof(Button));
- if (!button) {
- ERROR("error: out of memory\n");
- exit(EXIT_FAILURE);
- }
- if (text) {
- button->text = strdup(text);
- if (!text) {
- ERROR("error: out of memory\n");
- free(button);
- exit(EXIT_FAILURE);
- }
- } else {
- button->text = NULL;
- }
- button->x = x;
- button->y = y;
- button->w = w;
- button->h = h;
- button->inactive = inactive;
- button->active = active;
- button->current = inactive;
- button->font = font;
- button->textColor = textColor;
- button->sounds = sounds;
- button->action = NULL;
- button->renderedText = NULL;
- button->down = 0;
- buttonUpdate(button, window);
- return button;
- }
- void buttonDelete(Button *button) {
- if (button->text && strlen(button->text)) {
- free(button->text);
- SDL_DestroyTexture(button->renderedText);
- }
- free(button);
- }
- void buttonDraw(const Button *button, const Window *window) {
- float bw = button->w;
- float bh = button->h;
- int ww, wh;
- SDL_GetWindowSize(window->obj, &ww, &wh);
- if (button->w == 0 && button->h == 0) {
- bh = (float)button->textW / ww;
- bw = (float)button->textH / wh;
- } else if (button->w == 0) {
- bw = (((wh * button->h) * button->textH) / button->textW) / ww;
- } else if (button->h == 0) {
- bh = (((ww * button->w) * button->textH) / button->textW) / wh;
- }
- SDL_Rect backArea = {ww * button->x, wh * button->y, ww * bw, wh * bh};
- SDL_RenderCopy(window->render, button->current, NULL, &backArea);
- if (button->text && strlen(button->text)) {
- SDL_Rect textArea = {backArea.x * (1.0f + BUTTON_PADDING),
- backArea.y * (1.0f + BUTTON_PADDING),
- backArea.w * (1.0f - (2 * BUTTON_PADDING)),
- backArea.h * (1.0f - (2 * BUTTON_PADDING))};
- SDL_RenderCopy(window->render, button->renderedText, NULL, &textArea);
- }
- }
- void buttonUpdate(Button *button, const Window *window) {
- if (button->renderedText) {
- SDL_DestroyTexture(button->renderedText);
- }
- if (button->text && strlen(button->text)) {
- SDL_Surface *surface = TTF_RenderText_Blended(
- button->font, button->text, button->textColor);
- if (!surface) {
- ERROR("error: sdl2: ttf: %s\n", TTF_GetError());
- exit(EXIT_FAILURE);
- }
- button->textW = surface->w;
- button->textH = surface->h;
- button->renderedText =
- SDL_CreateTextureFromSurface(window->render, surface);
- SDL_FreeSurface(surface);
- if (!button->renderedText) {
- ERROR("error: sdl2: %s\n", SDL_GetError());
- exit(EXIT_FAILURE);
- }
- }
- }
- static int intersectsButton(const Button *button, float bw, float bh, float x,
- float y) {
- return x >= button->x && y >= button->y && x <= button->x + bw &&
- y <= button->y + bh;
- }
- void buttonProcessInput(Button *button, Window *window,
- const SDL_Event *event) {
- int ww, wh;
- SDL_GetWindowSize(window->obj, &ww, &wh);
- float bw = button->w;
- float bh = button->h;
- if (button->w == 0 && button->h == 0) {
- bh = (float)button->textW / ww;
- bw = (float)button->textH / wh;
- } else if (button->w == 0) {
- bw = (((wh * button->h) * button->textH) / button->textW) / ww;
- } else if (button->h == 0) {
- bh = (((ww * button->w) * button->textH) / button->textW) / wh;
- }
- if (event->type == SDL_MOUSEMOTION) {
- float x = (float)event->motion.x / ww;
- float y = (float)event->motion.y / wh;
- if (intersectsButton(button, bw, bh, x, y)) {
- if (button->active && button->current != button->active) {
- if (button->sounds.hover) {
- Mix_PlayChannel(-1, button->sounds.hover, 0);
- }
- button->current = button->active;
- }
- } else {
- if (button->current != button->inactive) {
- if (button->sounds.hover) {
- Mix_PlayChannel(-1, button->sounds.hover, 0);
- }
- button->current = button->inactive;
- }
- if (button->down) {
- button->down = 0;
- }
- }
- } else if (event->type == SDL_MOUSEBUTTONDOWN &&
- event->button.button == SDL_BUTTON_LEFT) {
- float x = (float)event->button.x / ww;
- float y = (float)event->button.y / wh;
- if (intersectsButton(button, bw, bh, x, y)) {
- button->down = 1;
- if (button->sounds.down) {
- Mix_PlayChannel(-1, button->sounds.down, 0);
- }
- }
- } else if (event->type == SDL_MOUSEBUTTONUP &&
- event->button.button == SDL_BUTTON_LEFT) {
- float x = (float)event->button.x / ww;
- float y = (float)event->button.y / wh;
- if (intersectsButton(button, bw, bh, x, y) && button->down) {
- button->down = 0;
- if (button->sounds.up) {
- Mix_PlayChannel(-1, button->sounds.up, 0);
- }
- if (button->action) {
- button->action(button, window, x - button->x, y - button->y);
- }
- button->current = button->inactive;
- }
- }
- }
- void buttonGetCenter(const Button *button, Point *point) {
- point->x = button->x + (button->w / 2);
- point->y = button->y + (button->w / 2);
- }
|