302 lines
9.5 KiB
C++
302 lines
9.5 KiB
C++
#include "on_screen_keyboard.h"
|
|
// #include <iostream>
|
|
|
|
// Constructor
|
|
OnScreenKeyboard::OnScreenKeyboard(SDL_Renderer *renderer, Input *input, string bitmapFile, string textFile, options_t *options, int width, int height, string output, color_t color)
|
|
{
|
|
// Inicializa variables
|
|
this->renderer = renderer;
|
|
this->options = options;
|
|
this->input = input;
|
|
this->width = width;
|
|
this->height = height;
|
|
|
|
// Crea objetos
|
|
text = new Text(textFile, bitmapFile, renderer);
|
|
texture = SDL_CreateTexture(renderer, SDL_PIXELFORMAT_RGBA8888, SDL_TEXTUREACCESS_TARGET, width, height);
|
|
textureCursor = SDL_CreateTexture(renderer, SDL_PIXELFORMAT_RGBA8888, SDL_TEXTUREACCESS_TARGET, text->getCharacterSize() * 2, text->getCharacterSize() * 2);
|
|
SDL_SetTextureBlendMode(textureCursor, SDL_BLENDMODE_BLEND);
|
|
|
|
// Inicializa variables
|
|
this->output = output;
|
|
char_upper = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
|
|
char_lower = "abcdefghijklmnopqrstuvwxyz";
|
|
char_numbers = "0123456789";
|
|
char_symbol = " !\"#$%&'()*+,-./:;<=>?@[]";
|
|
use_char_upper = true;
|
|
use_char_lower = false;
|
|
use_char_numbers = false;
|
|
use_char_symbol = false;
|
|
setLayout();
|
|
caption = "";
|
|
dest = {(options->screen.nativeWidth - width) / 2, (options->screen.nativeHeight - height) / 2, width, height};
|
|
cursor.col = 0;
|
|
cursor.row = 0;
|
|
cursor.dest = {0, 0, 16, 16};
|
|
|
|
// Rellena la textura de fondo con el color y el texto
|
|
fillTexture();
|
|
|
|
// Rellena la textura del cursor
|
|
SDL_SetRenderTarget(renderer, textureCursor);
|
|
color_t c = {192, 0, 0};
|
|
SDL_SetRenderDrawColor(renderer, c.r, c.g, c.b, 255);
|
|
SDL_RenderClear(renderer);
|
|
c = lightenColor(c, 20);
|
|
SDL_SetRenderDrawColor(renderer, c.r, c.g, c.b, 255);
|
|
SDL_RenderDrawRect(renderer, NULL);
|
|
SDL_SetRenderTarget(renderer, nullptr);
|
|
}
|
|
|
|
// Destructor
|
|
OnScreenKeyboard::~OnScreenKeyboard()
|
|
{
|
|
// Libera la memoria de los objetos
|
|
if (text != nullptr)
|
|
{
|
|
delete text;
|
|
}
|
|
|
|
if (texture != nullptr)
|
|
{
|
|
SDL_DestroyTexture(texture);
|
|
}
|
|
}
|
|
|
|
// Rellena la textura de fondo con el color y el texto
|
|
void OnScreenKeyboard::fillTexture()
|
|
{
|
|
// Destruye la textura si la hubiera
|
|
if (texture)
|
|
SDL_DestroyTexture(texture);
|
|
|
|
// Crea la textura
|
|
height = (text->getCharacterSize() * 4) + (text->getCharacterSize() * rows * 2);
|
|
texture = SDL_CreateTexture(renderer, SDL_PIXELFORMAT_RGBA8888, SDL_TEXTUREACCESS_TARGET, width, height);
|
|
dest = {(options->screen.nativeWidth - width) / 2, (options->screen.nativeHeight - height) / 2, width, height};
|
|
|
|
// Empieza a dibujar en la textura
|
|
SDL_SetRenderTarget(renderer, texture);
|
|
|
|
// Establece el color de fondo
|
|
SDL_SetRenderDrawColor(renderer, bgColor.r, bgColor.g, bgColor.b, 255);
|
|
SDL_RenderClear(renderer);
|
|
color_t color = lightenColor(bgColor, 20);
|
|
SDL_SetRenderDrawColor(renderer, color.r, color.g, color.b, 255);
|
|
SDL_RenderDrawRect(renderer, NULL);
|
|
|
|
// Escribe el texto que aparece en el objeto
|
|
text->write(text->getCharacterSize(), text->getCharacterSize(), caption);
|
|
|
|
// Dibuja el cuadro donde va el texto que se escribirá
|
|
const color_t darkColor = darkenColor(bgColor, 10);
|
|
SDL_SetRenderDrawColor(renderer, darkColor.r, darkColor.g, darkColor.b, 255);
|
|
const int x_rect = (text->getCharacterSize() * 2) + text->lenght(caption);
|
|
const int y_rect = text->getCharacterSize();
|
|
const int w_rect = width - text->getCharacterSize() - x_rect;
|
|
const int h_rect = text->getCharacterSize();
|
|
outputDest = {x_rect, y_rect, w_rect, h_rect};
|
|
SDL_RenderFillRect(renderer, &outputDest);
|
|
|
|
// Dibuja los caracteres que conformaran el teclado
|
|
const int dist = text->getCharacterSize() * 2;
|
|
const int offset_x = text->getCharacterSize();
|
|
const int offset_y = text->getCharacterSize() * 3;
|
|
for (int j = 0; j < rows; ++j)
|
|
for (int i = 0; i < columns; ++i)
|
|
{
|
|
const int pos = i + (j * columns);
|
|
if (pos < (int)layout.size())
|
|
{
|
|
// color_t color = randColor();
|
|
// SDL_SetRenderDrawColor(renderer, color.r, color.g, color.b, 255);
|
|
// SDL_Rect rect = {offset_x + (layout.at(pos).col * dist), offset_y + (layout.at(pos).row * dist), dist, dist};
|
|
// SDL_RenderFillRect(renderer, &rect);
|
|
// text->write(offset_x + (layout.at(pos).col * dist) + (dist / 2), offset_y + (layout.at(pos).row * dist) + (dist / 2), layout.at(pos).caption);
|
|
text->writeCentered(offset_x + (layout.at(pos).col * dist) + (dist / 2), offset_y + (layout.at(pos).row * dist) + (dist / 4), layout.at(pos).caption);
|
|
}
|
|
}
|
|
|
|
// Deja de dibujar en la textura
|
|
SDL_SetRenderTarget(renderer, nullptr);
|
|
}
|
|
|
|
// Calcula cuantos caracteres se utilizaran para crear el teclado
|
|
int OnScreenKeyboard::getTotalChars()
|
|
{
|
|
int total = 0;
|
|
total += use_char_upper ? char_upper.length() : 0;
|
|
total += use_char_lower ? char_lower.length() : 0;
|
|
total += use_char_numbers ? char_numbers.length() : 0;
|
|
total += use_char_symbol ? char_symbol.length() : 0;
|
|
return total;
|
|
}
|
|
|
|
// Calcula cuantas columnas necesita el teclado
|
|
int OnScreenKeyboard::getColumns()
|
|
{
|
|
const int keyWidth = text->getCharacterSize() * 2;
|
|
int rowWidth = width - text->getCharacterSize();
|
|
|
|
return rowWidth / keyWidth;
|
|
}
|
|
|
|
// Calcula cuantas filas necesita el teclado
|
|
int OnScreenKeyboard::getRows()
|
|
{
|
|
return (totalChars / getColumns()) + 1;
|
|
}
|
|
|
|
// Establece la disposición del teclado
|
|
void OnScreenKeyboard::setLayout()
|
|
{
|
|
totalChars = getTotalChars();
|
|
columns = getColumns();
|
|
rows = getRows();
|
|
int index_col = 0;
|
|
int index_row = 0;
|
|
|
|
// Establece los caracteres a escribir
|
|
string allChars = "";
|
|
allChars = use_char_upper ? allChars + char_upper : allChars;
|
|
allChars = use_char_lower ? allChars + char_lower : allChars;
|
|
allChars = use_char_numbers ? allChars + char_numbers : allChars;
|
|
allChars = use_char_symbol ? allChars + char_symbol : allChars;
|
|
|
|
layout.clear();
|
|
for (int i = 0; i < (int)allChars.length(); ++i)
|
|
{
|
|
key_t key;
|
|
key.col = index_col;
|
|
key.row = index_row;
|
|
key.caption = allChars.substr(i, 1);
|
|
layout.push_back(key);
|
|
|
|
// std::cout << key.caption << " " << key.col << " " << key.row << " " << std::endl;
|
|
|
|
++index_col;
|
|
if (index_col == columns)
|
|
{
|
|
index_col = 0;
|
|
++index_row;
|
|
}
|
|
}
|
|
}
|
|
|
|
// Comprueba las entradas
|
|
void OnScreenKeyboard::checkInput()
|
|
{
|
|
if (input->checkInput(INPUT_LEFT, REPEAT_FALSE))
|
|
decCursorCol();
|
|
|
|
if (input->checkInput(INPUT_RIGHT, REPEAT_FALSE))
|
|
incCursorCol();
|
|
|
|
if (input->checkInput(INPUT_UP, REPEAT_FALSE))
|
|
decCursorRow();
|
|
|
|
if (input->checkInput(INPUT_DOWN, REPEAT_FALSE))
|
|
incCursorRow();
|
|
|
|
if (input->checkInput(INPUT_ACCEPT, REPEAT_FALSE))
|
|
addChar();
|
|
|
|
if (input->checkInput(INPUT_CANCEL, REPEAT_FALSE))
|
|
removeChar();
|
|
}
|
|
|
|
// Disminuye en una columna la posición del cursor
|
|
void OnScreenKeyboard::decCursorCol()
|
|
{
|
|
cursor.col = cursor.col > 0 ? cursor.col - 1 : columns - 1;
|
|
}
|
|
|
|
// Incrementa en una columna la posición del cursor
|
|
void OnScreenKeyboard::incCursorCol()
|
|
{
|
|
++cursor.col %= columns;
|
|
}
|
|
|
|
// Disminuye en una fila la posición del cursor
|
|
void OnScreenKeyboard::decCursorRow()
|
|
{
|
|
cursor.row = cursor.row > 0 ? cursor.row - 1 : rows - 1;
|
|
}
|
|
|
|
// Aumenta en una fila la posición del cursor
|
|
void OnScreenKeyboard::incCursorRow()
|
|
{
|
|
++cursor.row %= rows;
|
|
}
|
|
|
|
// Actualiza la posición de la textura del cursor
|
|
void OnScreenKeyboard::updateCursor()
|
|
{
|
|
const int offset_x = text->getCharacterSize();
|
|
const int offset_y = text->getCharacterSize() * 3;
|
|
|
|
cursor.dest.x = dest.x + offset_x + (cursor.col * cursor.dest.w);
|
|
cursor.dest.y = dest.y + offset_y + (cursor.row * cursor.dest.h);
|
|
}
|
|
|
|
// Añade un caracter a la salida
|
|
void OnScreenKeyboard::addChar()
|
|
{
|
|
const int pos = cursor.col + cursor.row * columns;
|
|
if (pos < (int)layout.size())
|
|
output = output + layout.at(pos).caption;
|
|
}
|
|
|
|
// Borra el último caracter de la salida
|
|
void OnScreenKeyboard::removeChar()
|
|
{
|
|
if (output.length() > 0)
|
|
output = output.substr(0, output.length() - 1);
|
|
}
|
|
|
|
// Actualiza la lógica del objeto
|
|
void OnScreenKeyboard::update()
|
|
{
|
|
// Comprueba las entradas
|
|
checkInput();
|
|
|
|
// Actualiza la posición de la textura del cursor
|
|
updateCursor();
|
|
}
|
|
|
|
// Dibuja el objeto en pantalla
|
|
void OnScreenKeyboard::render()
|
|
{
|
|
SDL_RenderCopy(renderer, texture, nullptr, &dest);
|
|
SDL_RenderCopy(renderer, textureCursor, nullptr, &cursor.dest);
|
|
|
|
const int pos = cursor.col + cursor.row * columns;
|
|
const string key = pos < (int)layout.size() ? layout.at(pos).caption : "";
|
|
text->writeDX(TXT_CENTER | TXT_COLOR, cursor.dest.x + cursor.dest.w / 2, cursor.dest.y + cursor.dest.w / 4, key, 1, {0, 255, 0});
|
|
text->write(dest.x + outputDest.x, dest.y + outputDest.y, output);
|
|
}
|
|
|
|
// Establece el color de fondo
|
|
void OnScreenKeyboard::setBgColor(color_t color)
|
|
{
|
|
bgColor = color;
|
|
fillTexture();
|
|
}
|
|
|
|
// Establece el texto a mostrar junto al texto a introducir
|
|
void OnScreenKeyboard::setCaption(string text)
|
|
{
|
|
caption = text;
|
|
fillTexture();
|
|
}
|
|
|
|
// Establece qué caracteres ofrecerá el objeto
|
|
void OnScreenKeyboard::setChars(Uint8 mode)
|
|
{
|
|
use_char_upper = ((mode & USE_UPPER) == USE_UPPER);
|
|
use_char_lower = ((mode & USE_LOWER) == USE_LOWER);
|
|
use_char_numbers = ((mode & USE_NUMBER) == USE_NUMBER);
|
|
use_char_symbol = ((mode & USE_SYMBOL) == USE_SYMBOL);
|
|
setLayout();
|
|
fillTexture();
|
|
} |