From 8132bc8ddddc7df3df717b20bb35c51e0aecff3e Mon Sep 17 00:00:00 2001 From: Allan POINT Date: Fri, 7 Jan 2022 12:06:56 +0100 Subject: [PATCH] Add TextLabel and TextInput (not yet finished) --- Pontu/entryPoints/test.c | 11 +- Pontu/include/engine/TextInput.h | 96 ++++++++++++++ Pontu/include/engine/TextLabel.h | 12 ++ Pontu/include/view/MenuConnection.h | 10 ++ Pontu/rsrc/font/retro.TTF | 1 + Pontu/src/engine/FontLoader.c | 1 + Pontu/src/engine/TextInput.c | 190 ++++++++++++++++++++++++++++ Pontu/src/view/MenuConnection.c | 17 +++ Pontu/test/testTextInput.c | 118 +++++++++++++++++ 9 files changed, 451 insertions(+), 5 deletions(-) create mode 100644 Pontu/include/engine/TextInput.h create mode 100644 Pontu/include/engine/TextLabel.h create mode 100644 Pontu/include/view/MenuConnection.h create mode 120000 Pontu/rsrc/font/retro.TTF create mode 100644 Pontu/src/engine/TextInput.c create mode 100644 Pontu/src/view/MenuConnection.c create mode 100644 Pontu/test/testTextInput.c diff --git a/Pontu/entryPoints/test.c b/Pontu/entryPoints/test.c index aedb171..c8e871a 100644 --- a/Pontu/entryPoints/test.c +++ b/Pontu/entryPoints/test.c @@ -1,17 +1,18 @@ -//#include "../test/testTextureLoader.c" -//#include "../test/testFontLoader.c" -#include "../test/testAudioHandler.c" +// #include "../test/testTextureLoader.c" +// #include "../test/testFontLoader.c" +// #include "../test/testAudioHandler.c" // #include "../test/testGenerateurTexture.c" - +#include "../test/testTextInput.c" /* This file is meant to be modified (used only to called other tests functions) */ int main(/*int argc, char *argv[]*/) { //testTextureLoader(); - testAudioHandler(); + //testAudioHandler(); //testFontLoader(); //testGenerateurTexture(); + testTextInput(); return 0; } diff --git a/Pontu/include/engine/TextInput.h b/Pontu/include/engine/TextInput.h new file mode 100644 index 0000000..415cfdf --- /dev/null +++ b/Pontu/include/engine/TextInput.h @@ -0,0 +1,96 @@ +#ifndef TEXT_INPUT_INCLUDED +/** + * \file TextInput.h + * \brief Basic TextInput + * \author Allan Point + * \date 05/01/2022 + */ + +#define TEXT_INPUT_INCLUDED + +#include +#include +#include +#include + + +/** + * \struct TextInput + * \typedef + * \brief A text-inputable zone representation + * \author Allan Point + * \copyright CECILL + * \date 05/01/2022 + */ +typedef struct +{ + char* value; + int cursorPosition; + SDL_Rect size; + bool isActive; + SDL_Color textColor; + TTF_Font* textFont; +}TextInput; + +/** + * \brief Add a character on the right place on the textInput + * \param[in,out] textInput Memmory address of the TextInput to modify + * \param[in] charToAdd Character to add at the curent cursor position + * \return True if all goes right. Else false. + * \author Allan Point + * \date 05/01/2022 + * \copyright CECILL + */ +bool addCharcterToInputTextValueAtCursor(TextInput* textInput, const char charToAdd); + +/** + * \brief Remove a character from the TextInput + * \param[in,out] textInput TextInput to modify + * \return True if all goes right. Esle false. + * \author Allan Point + * \date 05/01/2022 + * \copyright CECILL + */ +bool removeCharcterToInputTextValueAtCursor(TextInput* textInput); + +/** + * \brief Draw a text input on a renderer + * \param[in,out] renderer The renderer to draw on + * \param[in] textInput The TextInput to be drawn + * \return True on success. Esle false; + * \author Allan POINT + * \date 05/01/2022 + * \copyright CECILL + */ +bool drawTextInputOnRenderer(SDL_Renderer* renderer, const TextInput* textInput); + +/** + * \brief Initalize a TextInput + * \details value="" + * \details cursorPosition=0 + * \details size is given by user + * \details isActive=false + * \details By default, color is true black, else textColor is given by user + * \details textFont is given by user + * \param[out] textInput Address of a TextInput to init + * \param[in] size Reprsentation of the position, width and height of the TextInput + * \param[in] textColor Color of the text, if NULL is given, colorText will be black + * \param[in] textFont Font for the text + * \return True on succsess. Esle false. + * \author Allan POINT + * \date 05/01/2022 + * \copyright CECILL + */ +bool initTextInput(TextInput* textInput, const SDL_Rect* size, const SDL_Color* textColor, const TTF_Font* textFont); + +/* + * \brief Free what is needed to be free and clear all data in the TextInput + * \param[out] textInput TextInput to clean + * \return True on success. Else false. + * \author Allan POINT + * \date 07/01/2022 + * \copyright CECILL + */ +bool destroyTextInput(TextInput* textInput); + +#endif diff --git a/Pontu/include/engine/TextLabel.h b/Pontu/include/engine/TextLabel.h new file mode 100644 index 0000000..56f63ab --- /dev/null +++ b/Pontu/include/engine/TextLabel.h @@ -0,0 +1,12 @@ +#ifndef TEXT_LABEL_INCLUDED +#define TEXT_LABEL_INCLUDED + +#include + +typedef struct +{ + char* text; + SDL_Rect textZone; +}TextLabel; + +#endif diff --git a/Pontu/include/view/MenuConnection.h b/Pontu/include/view/MenuConnection.h new file mode 100644 index 0000000..a6afc6e --- /dev/null +++ b/Pontu/include/view/MenuConnection.h @@ -0,0 +1,10 @@ +#ifndef MENU_CONNECTION_INCLUDED +#define MENU_CONNECTION_INCLUDED + +#include +#include +#include "engine/Button.h" + +bool drawMenuConnection(const SDL_Renderer* renderer); + +#endif diff --git a/Pontu/rsrc/font/retro.TTF b/Pontu/rsrc/font/retro.TTF new file mode 120000 index 0000000..eea9e6a --- /dev/null +++ b/Pontu/rsrc/font/retro.TTF @@ -0,0 +1 @@ +retro/retro.TTF \ No newline at end of file diff --git a/Pontu/src/engine/FontLoader.c b/Pontu/src/engine/FontLoader.c index 7db502c..31baadb 100644 --- a/Pontu/src/engine/FontLoader.c +++ b/Pontu/src/engine/FontLoader.c @@ -32,6 +32,7 @@ FontHandler loadFonts(void) } free(fontPathFile); } + return fontHandler; } bool freeFonts(FontHandler fontHandler) diff --git a/Pontu/src/engine/TextInput.c b/Pontu/src/engine/TextInput.c new file mode 100644 index 0000000..5fb90a9 --- /dev/null +++ b/Pontu/src/engine/TextInput.c @@ -0,0 +1,190 @@ +#include "engine/TextInput.h" + +bool addCharacterToInputTextValueAtCursor(TextInput* textInput, const char charToAdd) +{ + if(textInput == NULL) + { + return false; + } + if(textInput->cursorPosition >= strlen(textInput->value)) + { + return false; + } + char newValue[strlen(textInput->value)+1]; + + strncpy(newValue, textInput->value, textInput->cursorPosition); + strcat(newValue, &charToAdd); + strcat(newValue, textInput->value+textInput->cursorPosition+1); + + free(textInput->value); + textInput->value = (char*) malloc(strlen(newValue)); + if(textInput->value == NULL) + { + fprintf(stderr, "WARNING: Can't allocate memory space to TextInput\n"); + return false; + } + strcpy(textInput->value, newValue); + textInput->cursorPosition -= 1; + + return true; +} + +bool removeCharacterToInputTextValueAtCursor(TextInput* textInput) +{ + int textLen = 0; + if(textInput == NULL) + { + return false; + } + if(textInput->value == NULL) + { + return true; + } + if(textInput->cursorPosition <= 0) + { + return true; + } + + textLen = strlen(textInput->value); + char tmp[textLen]; + + if(textInput->cursorPosition > textLen) + { + return false; + } + if(textLen == 0) + { + return true; + } + + strcpy(tmp, textInput->value); + strncpy(textInput->value, tmp, textInput->cursorPosition-1); + strcat(textInput->value, tmp+textInput->cursorPosition); + textInput->cursorPosition -= 1; + return true; +} + +bool drawTextInputOnRenderer(SDL_Renderer* renderer, const TextInput* textInput) +{ + SDL_Surface* textRendered = NULL; + SDL_Texture* inputTexture = SDL_CreateTexture(renderer, + SDL_PIXELFORMAT_RGBA8888, + SDL_TEXTUREACCESS_TARGET, + (textInput->size).w, + (textInput->size).h); + SDL_Color black = {0, 0, 0, 255}; + SDL_Color white = {200, 200, 200, 255}; + char textValue[strlen(textInput->value)+1]; + SDL_Rect size = {.x=0, .y=0, .w=textInput->size.w, .h=textInput->size.h}; + + if(inputTexture == NULL) + { + fprintf(stderr, "WARNING: Can't create TextInput texture: %s\n", SDL_GetError()); + return false; + } + if(SDL_SetRenderTarget(renderer, inputTexture) < 0) + { + fprintf(stderr, "WARNING: Can't set TextInput's texture as target: %s\n", SDL_GetError()); + return false; + } + if(SDL_SetRenderDrawColor(renderer, white.r, white.g, white.b, white.a) != 0) + { + fprintf(stderr, "WARNING: Can't change color: %s\n", SDL_GetError()); + return false; + } + if(SDL_RenderFillRect(renderer, &(textInput->size)) < 0) + { + fprintf(stderr, "WARNING: Can't fill TextInput: %s\n", SDL_GetError()); + return false; + } + if(SDL_SetRenderDrawColor(renderer, black.r, black.g, black.b, black.a) != 0) + { + fprintf(stderr, "WARNING: Can't change color: %s\n", SDL_GetError()); + return false; + } + if(SDL_RenderDrawRect(renderer, &size) < 0) + { + fprintf(stderr, "WARNING: Can't draw TextInput's border: %s\n", SDL_GetError()); + return false; + } + if(textInput->isActive) + { + strncpy(textValue, textInput->value, textInput->cursorPosition); + strcat(textValue, "|"); + strcat(textValue, textInput->value+textInput->cursorPosition+1); + }else + { + strcpy(textValue, textInput->value); + } + textRendered = TTF_RenderUTF8_Solid(textInput->textFont, textValue, textInput->textColor); + if(textRendered == NULL) + { + fprintf(stderr, "WARNING: Can't write on TextInput\n"); + return false; + } + if(SDL_SetRenderTarget(renderer, NULL) < 0) + { + fprintf(stderr, "WARNING: Can't unset TextInput's texture as target: %s\n", SDL_GetError()); + return false; + } + return SDL_RenderCopy(renderer, inputTexture, NULL, &textInput->size) == 0; +} + +bool initTextInput(TextInput* textInput, const SDL_Rect* size, const SDL_Color* textColor, const TTF_Font* font) +{ + if(textInput == NULL) + { + fprintf(stderr, "WARNING: Can't assign value to NULL to create TextInput\n"); + return false; + } + + textInput->value = (char*) malloc(strlen("TEST")); + if(textInput->value == NULL) + { + fprintf(stderr, "WARNING: Can't allocate memory space to TextInput\n"); + return false; + } + strcpy(textInput->value, "TEST"); + textInput->cursorPosition = 0; + if(size == NULL) + { + fprintf(stderr, "WARNING: Can't create a TextInput with a NULL size"); + return false; + } + + textInput->size = *size; + + if(textColor == NULL) + { + SDL_Color defautlColor = {0,0,0,0}; + textInput->textColor = defautlColor; + } + else + { + textInput->textColor = *textColor; + } + + if(font == NULL) + { + fprintf(stderr, "WARNING: Can't create a TextIntput with a NULL font\n"); + return false; + } + textInput->textFont = font; + return true; + +} + +bool destroyTextInput(TextInput* textInput) +{ + SDL_Rect initRect = { .x=0, .y=0, .w=0, .h=0}; + SDL_Color initColor = {0,0,0,0}; + + free(textInput->value); + textInput->cursorPosition = 0; + textInput->size = initRect; + textInput->isActive = false; + textInput->textColor = initColor; + textInput->textFont = NULL; + + return true; +} diff --git a/Pontu/src/view/MenuConnection.c b/Pontu/src/view/MenuConnection.c new file mode 100644 index 0000000..82f8899 --- /dev/null +++ b/Pontu/src/view/MenuConnection.c @@ -0,0 +1,17 @@ +#include "view/MenuConnection.h" + +bool drawMenuConnection(const SDL_Renderer* renderer) +{ + const char title[] = "Connexion"; + const unsigned int titleHeightPercetange = 8; + + const char pseudoLabel[] = "Pseudonyme: "; + const unsigned int pseudoLabelHeightPercentage = 16; + + const char colorLabel[] = "Couleur: "; + const unsigned int colorLabelHeihetPercentage = 18; + + + + return true; +} diff --git a/Pontu/test/testTextInput.c b/Pontu/test/testTextInput.c new file mode 100644 index 0000000..3108edc --- /dev/null +++ b/Pontu/test/testTextInput.c @@ -0,0 +1,118 @@ +#include +#include +#include "engine/TextureLoader.h" +#include "engine/FontLoader.h" +#include "engine/TextInput.h" + +//gcc test.c -I ../include $(sdl2-config --cflags --libs) + +int testTextInput(void) { + SDL_Window *window = NULL; + SDL_Renderer *renderer = NULL; + SDL_Texture* picture; + TextInput textInput; + int statut = EXIT_FAILURE; + char* path = "rsrc/img/Lenna.png"; + + if(0 != SDL_Init(SDL_INIT_VIDEO)) + { + fprintf(stderr, "Erreur SDL_INIT: %s\n", SDL_GetError()); + goto Quit; + } + + //fenetre + window = SDL_CreateWindow("FenĂȘtre", SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, 640,480, SDL_WINDOW_SHOWN); + if(window == NULL) + { + fprintf(stderr, "Erreur SDL_CreateWindow: %s\n", SDL_GetError()); + goto Quit; + } + + //rendu + renderer = SDL_CreateRenderer(window, -1, SDL_RENDERER_ACCELERATED); + if(renderer == NULL) + { + fprintf(stderr, "Erreur SDL_CreateRenderer: %s\n", SDL_GetError()); + goto Quit; + } + + //Fonts + if(TTF_Init() == -1) + { + fprintf(stderr, "Erreur: TTF_Init: %s\n", TTF_GetError()); + goto Quit; + } + + if(0 != SDL_SetRenderDrawColor(renderer, 0,0,0,0)) //choisi la couleur avec laquelle travailler + { + fprintf(stderr, "Erreur SDL_SetRenderDrawColor: %s\n", SDL_GetError()); + goto Quit; + } + + if(0 != SDL_RenderClear(renderer)) //efface le rendu en le repeignant avec la couleur choisi + { + fprintf(stderr, "Erreur SDL_SetRenderDrawColor: %s\n", SDL_GetError()); + goto Quit; + } + + if(0 != SDL_SetRenderDrawColor(renderer, 255,255,255,255)) //choisi la couleur avec laquelle travailler + { + fprintf(stderr, "Erreur SDL_SetRenderDrawColor: %s\n", SDL_GetError()); + goto Quit; + } + + + SDL_bool quit = SDL_FALSE; + SDL_Event event; + + + picture = createTextureFromPath(renderer, path); + FontHandler fontHandler = loadFonts(); + + // TextInput + SDL_Rect size = {.x=10, .y=10, .w=90, .h=20}; + if(!initTextInput(&textInput, &size, NULL, fontHandler.fonts[FONT_retro])) + { + fprintf(stderr, "WARNING: can't init TextInput\n"); + goto Quit; + } + + + + SDL_RenderPresent(renderer); + + + while(!quit) + { + while(SDL_PollEvent(&event)) + { + switch(event.type) + { + case SDL_QUIT: + quit = SDL_TRUE; + break; + case SDL_MOUSEBUTTONUP: + break; + } + } + SDL_RenderCopy(renderer, picture, NULL, NULL); + + if(!drawTextInputOnRenderer(renderer, &textInput)) + { + fprintf(stderr, "Can't draw TextInput\n"); + } + SDL_RenderPresent(renderer); + + SDL_Delay(20); + } + +Quit: + freeFonts(fontHandler); + if(renderer != NULL) + SDL_DestroyRenderer(renderer); + if(window != NULL) + SDL_DestroyWindow(window); + TTF_Quit(); + SDL_Quit(); + return statut; +}