/* * Copyright (C) 2024 Tristan Riehs * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ #include "config.h" #include #include #include #include #include #include #include "disp.h" #include "calc_data.h" #include "input.h" #define DEFAULT_HEIGHT 200 #define DEFAULT_WIDTH (DEFAULT_HEIGHT*16/9) #define MAX_FONTSIZE 100 static struct calc_data calcs[CALC_COUNT] = {0}; static int current_idx = 0; void ray_init(void) { #ifndef NDEBUG SetTraceLogLevel(LOG_DEBUG); #else SetTraceLogLevel(LOG_ERROR); #endif InitWindow(DEFAULT_WIDTH, DEFAULT_HEIGHT, "calculer"); if (!IsWindowReady()) { fprintf(stderr, "calculer: error initialiazing Raylib \ window\n"); exit(1); } SetTargetFPS(60); SetWindowState(FLAG_WINDOW_RESIZABLE); BeginDrawing(); ClearBackground(RAYWHITE); EndDrawing(); current_idx = 0; TraceLog(LOG_INFO, "window successfully initialized"); } static int min(int x, int y) { if (x < y) return x; else return y; } static void draw_calc(void) { char txt[64] = {0}; int win_width, win_height; int txt_width; int font_size; sprintf(txt, "%d + %d", calcs[current_idx].x, calcs[current_idx].y); win_width = GetScreenWidth(); win_height = GetScreenHeight(); font_size = min(win_height/3, MAX_FONTSIZE); txt_width = MeasureText(txt, font_size); TraceLog(LOG_DEBUG, "win_width = %d", win_width); TraceLog(LOG_DEBUG, "win_height = %d", win_height); TraceLog(LOG_DEBUG, "txt_width = %d", txt_width); TraceLog(LOG_DEBUG, "font_size = %d", font_size); int max_txt_width = win_width*3/4/2; if (txt_width > max_txt_width) { float scale = ((float) txt_width)/max_txt_width; font_size = font_size/scale; txt_width = MeasureText(txt, font_size); } DrawText(txt, (win_width/4)-(txt_width/2), win_height/6, font_size, GRAY); TraceLog(LOG_INFO, "calulation %d + %d successfully drawn", calcs[current_idx].x, calcs[current_idx].y); } static void draw_input(void) { char txt[64] = {0}; int win_width, win_height; int txt_width; int font_size; sprintf(txt, "%d", calcs[current_idx].input); win_width = GetScreenWidth(); win_height = GetScreenHeight(); font_size = min(win_height/4, 3*MAX_FONTSIZE/4); txt_width = MeasureText(txt, font_size); if (txt_width > win_width) { float scale = txt_width/win_width; font_size = font_size/scale; txt_width = MeasureText(txt, font_size); } DrawText(txt, (win_width/4)-(txt_width/2), win_height*4/6, font_size, DARKGRAY); TraceLog(LOG_INFO, "input successfully drawn"); } static void draw_res(void) { char txt[64] = {0}; Color col; int win_width, win_height; int txt_width; int font_size; win_width = GetScreenWidth(); win_height = GetScreenHeight(); font_size = min(win_height/CALC_COUNT, MAX_FONTSIZE/2); txt_width = MeasureText("60 + 60 = 120 10000ms", font_size); if (txt_width > win_width/2) { float scale = ((float) txt_width)/(win_width/2); font_size = font_size/scale; } int j = loop_backwards(current_idx); int line = 0; while ((calcs[j].ms != 0) && (line < CALC_COUNT)) { if (calcs[j].right) col = GREEN; else col = RED; sprintf(txt, "%d + %d = %d %dms", calcs[j].x, calcs[j].y, calcs[j].input, calcs[j].ms); txt_width = MeasureText(txt, font_size); DrawText(txt, win_width-txt_width, (int) font_size*1.2*line, font_size, col); j = loop_backwards(j); line++; } } static void redraw(void) { BeginDrawing(); ClearBackground(RAYWHITE); draw_calc(); draw_input(); draw_res(); EndDrawing(); } void ray_display_calc(int x, int y) { current_idx = (current_idx + 1)%CALC_COUNT; calcs[current_idx].x = x; calcs[current_idx].y = y; calcs[current_idx].ms = 0; calcs[current_idx].input = 0; redraw(); } static void check_digit(int digit) { if (IsKeyPressed(KEY_ZERO + digit)) { calcs[current_idx].input = add_input_digit(calcs[current_idx].input, digit); TraceLog(LOG_INFO, "digit %d added to input", digit); TraceLog(LOG_INFO, "input is now %d", calcs[current_idx].input); redraw(); } } static void check_digits(void) { for (int i = 0; i < 10; i++) check_digit(i); } int ray_read_input(void) { TraceLog(LOG_INFO, "waiting for user input"); calcs[current_idx].input = 0; while (!WindowShouldClose()) { PollInputEvents(); if (IsWindowResized()) redraw(); if (IsKeyPressed(KEY_ENTER)) return calcs[current_idx].input; if (IsKeyPressed(KEY_Q) || IsKeyPressed(KEY_A)) return DISP_QUIT; #ifndef NDEBUG if (IsKeyPressed(KEY_R) || IsKeyPressed(KEY_G)) return DISP_RELOAD; #endif if (IsKeyPressed(KEY_BACKSPACE)) { calcs[current_idx].input = rm_input_digit(calcs[current_idx].input); redraw(); } check_digits(); } return DISP_QUIT; } void ray_display_res(bool right, int ms) { calcs[current_idx].right = right; calcs[current_idx].ms = ms; redraw(); } void ray_destroy(void) { CloseWindow(); } #ifndef NDEBUG void * ray_pre_reload(void) { char *data = malloc(sizeof(calcs) + sizeof(current_idx)); memcpy(data, &calcs, sizeof(calcs)); memcpy(data + sizeof(calcs), ¤t_idx, sizeof(current_idx)); TraceLog(LOG_INFO, "pre-reload actions done"); return data; } void ray_post_reload(void *state) { char *data = state; memcpy(&calcs, data, sizeof(calcs)); memcpy(¤t_idx, data + sizeof(calcs), sizeof(current_idx)); free(data); TraceLog(LOG_INFO, "post-reload actions done"); } #endif #ifdef NDEBUG static struct disp __ray_disp = { .init = ray_init, .display_calc = ray_display_calc, .read_input = ray_read_input, .display_res = ray_display_res, .destroy = ray_destroy }; struct disp *ray_disp = &__ray_disp; #endif