#include "window.h" #include #include #define ERROR(...) fprintf(stderr, __VA_ARGS__) Window *windowNew(const char *title, int width, int height) { Window *window = malloc(sizeof(Window)); if (!window) { ERROR("error: out of memory\n"); exit(EXIT_FAILURE); } window->obj = SDL_CreateWindow(title, SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, width, height, SDL_WINDOW_SHOWN | SDL_WINDOW_RESIZABLE); if (!window->obj) { ERROR("error: sdl2: %s\n", SDL_GetError()); free(window); exit(EXIT_FAILURE); } window->render = SDL_CreateRenderer( window->obj, -1, SDL_RENDERER_ACCELERATED | SDL_RENDERER_PRESENTVSYNC); if (!window->render) { ERROR("error: sdl2: %s\n", SDL_GetError()); SDL_DestroyWindow(window->obj); free(window); exit(EXIT_FAILURE); } window->background = NULL; window->focus.x = 0.0f; window->focus.y = 0.0f; window->targetFocus.x = 0.0f; window->targetFocus.y = 0.0f; window->zoom = 1.0f; window->state = WINDOW_STATE_NORMAL; return window; } void windowDelete(Window *window) { SDL_DestroyRenderer(window->render); SDL_DestroyWindow(window->obj); free(window); } static void zoomRect(const Window *window, SDL_Rect *rect) { int winW, winH; SDL_GetWindowSize(window->obj, &winW, &winH); int texW, texH; SDL_QueryTexture(window->background, NULL, NULL, &texW, &texH); const Point *focus = &window->focus; rect->x = (texW * focus->x) - (texW / window->zoom / 2); rect->y = (texH * focus->y) - (texH / window->zoom / 2); rect->w = texW / window->zoom; rect->h = texH / window->zoom; } void windowDraw(Window *window) { window->lastTime = window->nowTime; window->nowTime = SDL_GetPerformanceCounter(); window->delta = (double)(((window->nowTime - window->lastTime) * 1000) / SDL_GetPerformanceFrequency()); SDL_SetRenderDrawColor(window->render, 0xFF, 0xFF, 0xFF, SDL_ALPHA_OPAQUE); SDL_RenderClear(window->render); if (window->background) { if (window->state == WINDOW_STATE_ZOOMING_IN) { window->zoom += MAX_ZOOM * (window->delta / ZOOM_TIME); window->focus.x += (window->targetFocus.x - window->startFocus.x) * (window->delta / ZOOM_TIME); window->focus.y += (window->targetFocus.y - window->startFocus.y) * (window->delta / ZOOM_TIME); if (window->zoom >= MAX_ZOOM) { window->state = WINDOW_STATE_ZOOMED; } } else if (window->state == WINDOW_STATE_ZOOMING_OUT) { window->zoom -= MAX_ZOOM * (window->delta / ZOOM_TIME); window->focus.x += (window->targetFocus.x - window->startFocus.x) * (window->delta / ZOOM_TIME); window->focus.y += (window->targetFocus.y - window->startFocus.y) * (window->delta / ZOOM_TIME); if (window->zoom <= 1.0f) { window->state = WINDOW_STATE_NORMAL; } } if (window->state == WINDOW_STATE_NORMAL) { SDL_RenderCopy(window->render, window->background, NULL, NULL); } else { SDL_Rect area; zoomRect(window, &area); SDL_RenderCopy(window->render, window->background, &area, NULL); } } } void windowUpdate(Window *window) { SDL_RenderPresent(window->render); } void windowZoomTo(Window *window, float x, float y) { window->zoom = 1.0f; window->startFocus.x = 0.5f; window->startFocus.y = 0.5f; window->focus = window->startFocus; window->targetFocus.x = x; window->targetFocus.y = y; window->state = WINDOW_STATE_ZOOMING_IN; } void windowZoomOut(Window *window) { window->startFocus = window->focus; window->targetFocus.x = 0.5f; window->targetFocus.y = 0.5f; window->state = WINDOW_STATE_ZOOMING_OUT; }