Improved menu class

This commit is contained in:
2021-08-30 20:58:57 +02:00
parent 74c08884ae
commit 22ca349171
5 changed files with 156 additions and 180 deletions

View File

@@ -28,7 +28,6 @@ void Menu::init(std::string name, int x, int y, int backgroundType)
mSelector.index = 0;
mTotalItems = 0;
mItemSelected = MENU_NO_OPTION;
mVerticalPadding = 1;
mPosX = x;
mPosY = y;
mRectBG.rect.x = 0;
@@ -42,8 +41,8 @@ void Menu::init(std::string name, int x, int y, int backgroundType)
mIsCenteredOnX = false;
mIsCenteredOnY = false;
mAreElementsCenteredOnX = false;
mCenterX = x + ((SCREEN_WIDTH - x) / 2);
mCenterY = y + ((SCREEN_HEIGHT - y) / 2);
mCenterX = 0;
mCenterY = 0;
mWidestItem = 0;
mColorGreyed = {128, 128, 128};
@@ -54,14 +53,12 @@ void Menu::init(std::string name, int x, int y, int backgroundType)
mSelector.originH = 0;
mSelector.targetH = 0;
mSelector.incH = 0;
mSelector.y = 0;
mSelector.numJumps = 4;
mSelector.y = 0.0f;
mSelector.h = 0.0f;
mSelector.numJumps = 8;
mSelector.moving = false;
mSelector.resizing = false;
mSelector.rect.x = 0;
mSelector.rect.y = 0;
mSelector.rect.w = 0;
mSelector.rect.h = 0;
mSelector.rect = {0, 0, 0, 0};
mSelector.r = 0;
mSelector.g = 0;
mSelector.b = 0;
@@ -71,12 +68,12 @@ void Menu::init(std::string name, int x, int y, int backgroundType)
for (int i = 0; i < MENU_MAX_ITEMS; i++)
{
mItem[i].label = "";
mItem[i].w = 0;
mItem[i].h = 0;
mItem[i].x = 0;
mItem[i].y = 0;
mItem[i].hPaddingUp = 0;
mItem[i].rect = {0, 0, 0, 0};
mItem[i].hPaddingDown = 0;
mItem[i].selectable = false;
mItem[i].greyed = false;
mItem[i].linkedDown = false;
mItem[i].linkedUp = false;
}
}
@@ -103,6 +100,7 @@ std::string Menu::getName()
// Obtiene el valor de la variable
Uint8 Menu::getItemSelected()
{
// Al llamar a esta funcion, se obtiene el valor y se borra
const int temp = mItemSelected;
mItemSelected = MENU_NO_OPTION;
return temp;
@@ -131,34 +129,36 @@ void Menu::updateSelector()
mSelector.moving = false;
}
}
mSelector.rect.y = int(mSelector.y) - 1;
mSelector.rect.y = int(mSelector.y);
}
else
{
mSelector.rect.y = int(mSelector.y) - 1;
mSelector.rect.y = int(mSelector.y);
}
if (mSelector.resizing)
{
// Calcula el incremento en H
mSelector.rect.h += mSelector.incH;
mSelector.h += mSelector.incH;
if (mSelector.incH > 0) // Crece
{
if (mSelector.rect.h > mSelector.targetH) // Ha llegado al destino
if (mSelector.h > mSelector.targetH) // Ha llegado al destino
{
mSelector.originH = mSelector.rect.h = mSelector.targetH;
//mSelector.originH = mSelector.targetH = mSelector.rect.h = getSelectorHeight(mSelector.index);
mSelector.originH = mSelector.h = mSelector.targetH;
mSelector.resizing = false;
}
}
if (mSelector.incH < 0) // Decrece
{
if (mSelector.rect.h < mSelector.targetH) // Ha llegado al destino
if (mSelector.h < mSelector.targetH) // Ha llegado al destino
{
mSelector.originH = mSelector.rect.h = mSelector.targetH;
//mSelector.originH = mSelector.targetH = mSelector.rect.h = getSelectorHeight(mSelector.index);
mSelector.originH = mSelector.h = mSelector.targetH;
mSelector.resizing = false;
}
}
//mSelector.rect.h = getSelectorHeight(mSelector.index);
mSelector.rect.h = int(mSelector.h);
}
else
{
@@ -166,25 +166,16 @@ void Menu::updateSelector()
}
}
// Establece el origen del selector
void Menu::setSelectorOrigin(int value)
{
mSelector.originY = value;
}
// Establece el destino del selector
void Menu::setSelectorTarget(int value)
{
mSelector.targetY = value;
}
// Coloca el selector en una posición específica
void Menu::setSelectorPos(Uint8 index)
{
if (index < mTotalItems)
{
mSelector.index = index;
mSelector.y = mSelector.originY = mSelector.targetY = mItem[mSelector.index].y;
mSelector.rect.y = mSelector.y = mSelector.originY = mSelector.targetY = mItem[mSelector.index].rect.y;
mSelector.rect.w = mRectBG.rect.w;
mSelector.rect.x = mRectBG.rect.x;
mSelector.originH = mSelector.targetH = mSelector.rect.h = getSelectorHeight(mSelector.index);
mSelector.moving = false;
mSelector.resizing = false;
}
@@ -197,12 +188,8 @@ Uint16 Menu::getWidestItem()
// Obtenemos la anchura del item mas ancho
for (int i = 0; i < mTotalItems; i++)
{
if (mItem[i].w > result)
{
result = mItem[i].w;
}
}
if (mItem[i].rect.w > result)
result = mItem[i].rect.w;
return result;
}
@@ -212,18 +199,12 @@ void Menu::reset()
{
mItemSelected = MENU_NO_OPTION;
mSelector.index = 0;
mSelector.originY = mSelector.targetY = mSelector.y = mItem[0].y;
mSelector.originH = mSelector.targetH = mItem[0].h;
mSelector.originY = mSelector.targetY = mSelector.y = mItem[0].rect.y;
mSelector.originH = mSelector.targetH = mItem[0].rect.h;
mSelector.moving = false;
mSelector.resizing = false;
}
// Deja el menu sin elemento seleccionado
void Menu::deselectItem()
{
mItemSelected = MENU_NO_OPTION;
}
// Actualiza el menu para recolocarlo correctamente y establecer el tamaño
void Menu::reorganize()
{
@@ -240,9 +221,12 @@ void Menu::reorganize()
bool Menu::increaseSelectorIndex()
{
bool success = false;
mSelector.y = mSelector.originY = mItem[mSelector.index].y;
mSelector.rect.h = mSelector.originH = getSelectorHeight(mSelector.index);
// Obten las coordenadas del elemento actual
mSelector.y = mSelector.originY = mItem[mSelector.index].rect.y;
mSelector.h = mSelector.originH = getSelectorHeight(mSelector.index);
// Calcula cual es el siguiente elemento
if (mSelector.index < (mTotalItems - 1))
{
mSelector.index++;
@@ -251,11 +235,18 @@ bool Menu::increaseSelectorIndex()
success = true;
}
mSelector.targetY = mItem[mSelector.index].y;
mSelector.despY = (mSelector.targetY - mSelector.originY) / mSelector.numJumps;
mSelector.targetH = getSelectorHeight(mSelector.index);
mSelector.incH = (mSelector.targetH - mSelector.originH) / mSelector.numJumps;
mSelector.moving = true;
if (success)
{ // Establece las coordenadas y altura de destino
mSelector.targetY = mItem[mSelector.index].rect.y;
mSelector.despY = (mSelector.targetY - mSelector.originY) / mSelector.numJumps;
mSelector.targetH = getSelectorHeight(mSelector.index);
mSelector.incH = (mSelector.targetH - mSelector.originH) / mSelector.numJumps;
mSelector.moving = true;
if (mSelector.incH != 0)
mSelector.resizing = true;
}
return success;
}
@@ -264,9 +255,12 @@ bool Menu::increaseSelectorIndex()
bool Menu::decreaseSelectorIndex()
{
bool success = false;
mSelector.y = mSelector.originY = mItem[mSelector.index].y;
mSelector.rect.h = mSelector.originH = getSelectorHeight(mSelector.index);
// Obten las coordenadas del elemento actual
mSelector.y = mSelector.originY = mItem[mSelector.index].rect.y;
mSelector.h = mSelector.originH = getSelectorHeight(mSelector.index);
// Calcula cual es el siguiente elemento
if (mSelector.index > 0)
{
mSelector.index--;
@@ -275,11 +269,19 @@ bool Menu::decreaseSelectorIndex()
success = true;
}
mSelector.targetY = mItem[mSelector.index].y;
mSelector.despY = (mSelector.targetY - mSelector.originY) / mSelector.numJumps;
mSelector.targetH = getSelectorHeight(mSelector.index);
mSelector.incH = (mSelector.targetH - mSelector.originH) / mSelector.numJumps;
mSelector.moving = true;
if (success)
{ // Establece las coordenadas y altura de destino
mSelector.targetY = mItem[mSelector.index].rect.y;
mSelector.despY = (mSelector.targetY - mSelector.originY) / mSelector.numJumps;
mSelector.targetH = getSelectorHeight(mSelector.index);
mSelector.incH = (mSelector.targetH - mSelector.originH) / mSelector.numJumps;
mSelector.moving = true;
if (mSelector.incH != 0)
mSelector.resizing = true;
}
return success;
}
@@ -300,8 +302,11 @@ void Menu::render()
}
// Renderiza el rectangulo del selector
SDL_Rect temp = mSelector.rect;
temp.y--;
temp.h++;
SDL_SetRenderDrawColor(mRenderer, mSelector.r, mSelector.g, mSelector.b, mSelector.a);
SDL_RenderFillRect(mRenderer, &mSelector.rect);
SDL_RenderFillRect(mRenderer, &temp);
// Renderiza el borde del fondo
if (mBackgroundType == MENU_BACKGROUND_SOLID)
@@ -316,47 +321,49 @@ void Menu::render()
if (i == mSelector.index)
{
const color_t color = {mSelector.itemR, mSelector.itemG, mSelector.itemB};
mText->writeColored(mItem[i].x, mItem[i].y, mItem[i].label, color);
mText->writeColored(mItem[i].rect.x, mItem[i].rect.y, mItem[i].label, color);
}
else if (mItem[i].selectable)
{
mText->write(mItem[i].x, mItem[i].y, mItem[i].label);
mText->write(mItem[i].rect.x, mItem[i].rect.y, mItem[i].label);
}
else if (mItem[i].greyed)
{
mText->writeColored(mItem[i].x, mItem[i].y, mItem[i].label, mColorGreyed);
mText->writeColored(mItem[i].rect.x, mItem[i].rect.y, mItem[i].label, mColorGreyed);
}
else // No seleccionable
{
if ((mItem[i].linkedUp) && (i == mSelector.index + 1))
{
const color_t color = {mSelector.itemR, mSelector.itemG, mSelector.itemB};
mText->writeColored(mItem[i].x, mItem[i].y, mItem[i].label, color);
mText->writeColored(mItem[i].rect.x, mItem[i].rect.y, mItem[i].label, color);
}
else // No enlazado con el de arriba
{
mText->write(mItem[i].x, mItem[i].y, mItem[i].label);
mText->write(mItem[i].rect.x, mItem[i].rect.y, mItem[i].label);
}
}
//borrar
//mText->write(0, 0, std::to_string(mSelector.h) + " " + std::to_string(mSelector.incH) + " " + std::to_string(mSelector.resizing));
//mText->write(0, 8, std::to_string(mSelector.y) + " " + std::to_string(mSelector.despY) + " " + std::to_string(mSelector.moving));
}
}
// Establece el rectangulo de fondo del menu y el selector
void Menu::setRectSize()
{
mRectBG.rect.w = findWidth();
mRectBG.rect.h = findHeight();
mRectBG.rect.w = findWidth() + mText->getCharacterWidth();
mRectBG.rect.h = findHeight() + mText->getCharacterWidth();
// La posición X es la del menú menos medio caracter
mRectBG.rect.x = mPosX - (mText->getCharacterWidth() / 2);
// La posición Y es la del menu menos la altura de medio caracter i el padding
mRectBG.rect.y = mPosY - (mText->getCharacterWidth() / 2) - mVerticalPadding;
// La posición Y es la del menu menos la altura de medio caracter
mRectBG.rect.y = mPosY - (mText->getCharacterWidth() / 2);
// Establecemos los valores del rectangulo del selector a partir de los valores del rectangulo de fondo
mSelector.rect.h = getSelectorHeight(mSelector.index);
mSelector.rect.w = mRectBG.rect.w;
mSelector.rect.x = mRectBG.rect.x;
setSelectorPos(mSelector.index);
}
// Establece el valor de la variable
@@ -400,28 +407,17 @@ void Menu::centerMenuOnX(int value)
mCenterX = value;
// Actualiza el rectangulo de fondo para recalcular las dimensiones
setRectSize();
// Obten el acho del menu
mWidestItem = getWidestItem();
//setRectSize();
// Establece la nueva posición centrada en funcion del elemento más ancho
mPosX = (value) - (mWidestItem / 2);
mPosX = (value) - (findWidth() / 2);
// Reposiciona los elementos del menu
for (int i = 0; i < MENU_MAX_ITEMS; i++)
{
mItem[i].x = mPosX;
}
mItem[i].rect.x = mPosX;
// Recalcula el rectangulo de fondo
setRectSize();
// Recoloca el selector
mSelector.originY = mSelector.targetY = mSelector.y = mItem[mSelector.index].y;
mSelector.moving = false;
mSelector.originH = mSelector.targetH = mSelector.rect.h = mItem[mSelector.index].h;
mSelector.resizing = false;
}
// Centra el menu respecto un punto en el eje Y
@@ -431,25 +427,16 @@ void Menu::centerMenuOnY(int value)
mCenterY = value;
// Actualiza el rectangulo de fondo para recalcular las dimensiones
setRectSize();
// Obten el alto del menu
mHeight = findHeight();
//setRectSize();
// Establece la nueva posición centrada en funcion del elemento más ancho
mPosY = (value) - (mHeight / 2);
mPosY = (value) - (findHeight() / 2);
// Reposiciona los elementos del menu
replaceElementsOnY();
// Recalcula el rectangulo de fondo
setRectSize();
// Recoloca el selector
mSelector.originY = mSelector.targetY = mSelector.y = mItem[mSelector.index].y;
mSelector.moving = false;
mSelector.originH = mSelector.targetH = mSelector.rect.h = mItem[mSelector.index].h;
mSelector.resizing = false;
}
// Centra los elementos del menu en el eje X
@@ -458,40 +445,41 @@ void Menu::centerMenuElementsOnX()
mAreElementsCenteredOnX = true;
for (int i = 0; i < mTotalItems; i++)
mItem[i].x = (mCenterX - (mItem[i].w / 2));
mItem[i].rect.x = (mCenterX - (mItem[i].rect.w / 2));
}
// Añade un item al menu
void Menu::addItem(std::string text, const Uint8 hPaddingUp, const Uint8 hPaddingDown, bool selectable, bool greyed, bool linkedDown)
void Menu::addItem(std::string text, Uint8 hPaddingDown, bool selectable, bool greyed, bool linkedDown)
{
// Si es el primer item coge la posición en el eje Y del propio menu
if (mTotalItems == 0)
mItem[mTotalItems].y = mPosY;
mItem[mTotalItems].rect.y = mPosY;
else
// En caso contrario, coge la posición en el eje Y a partir del elemento anterior
mItem[mTotalItems].y = mItem[mTotalItems - 1].y + mItem[mTotalItems - 1].h + mItem[mTotalItems - 1].hPaddingDown;
mItem[mTotalItems].rect.y = mItem[mTotalItems - 1].rect.y + mItem[mTotalItems - 1].rect.h + mItem[mTotalItems - 1].hPaddingDown;
mItem[mTotalItems].label = text;
mItem[mTotalItems].w = mText->lenght(mItem[mTotalItems].label);
mItem[mTotalItems].h = mText->getCharacterWidth() + (mVerticalPadding * 2);
mItem[mTotalItems].x = mPosX;
mItem[mTotalItems].hPaddingUp = hPaddingUp;
setItemCaption(mTotalItems, text);
mItem[mTotalItems].rect.x = mPosX;
mItem[mTotalItems].hPaddingDown = hPaddingDown;
mItem[mTotalItems].selectable = selectable;
mItem[mTotalItems].greyed = greyed;
mItem[mTotalItems].linkedDown = linkedDown;
mItem[mTotalItems + 1].linkedUp = linkedDown;
if (mTotalItems > 0)
if (mItem[mTotalItems - 1].linkedDown)
mItem[mTotalItems].linkedUp = true;
setTotalItems(mTotalItems + 1);
mCenterX = mPosX + (findWidth() / 2);
//setSelectorPos(0);
reorganize();
setSelectorPos(0);
}
// Cambia el texto de un item
void Menu::setItemCaption(Uint8 index, std::string text)
{
mItem[index].label = text;
mItem[index].w = mText->lenght(mItem[index].label);
mItem[index].rect.w = mText->lenght(mItem[index].label);
mItem[index].rect.h = mText->getCharacterWidth();
reorganize();
}
@@ -532,17 +520,7 @@ void Menu::checkInput()
// Calcula el ancho del menu
Uint16 Menu::findWidth()
{
Uint16 width = 0;
// Obtenemos la anchura del item mas ancho
for (int i = 0; i < mTotalItems; i++)
if (mItem[i].w > width)
width = mItem[i].w;
// La anchura de la cadena más larga, mas un caracter
width += (mText->getCharacterWidth() * 1);
return width;
return getWidestItem();
}
// Calcula el alto del menu
@@ -552,10 +530,7 @@ Uint16 Menu::findHeight()
// Obtenemos la altura de la suma de alturas de los items
for (int i = 0; i < mTotalItems; i++)
height += mItem[i].h + mItem[i].hPaddingDown;
// La altura de la suma de los items mas un caracter y menos un pixel (porque el texto en realidad es de 7 pixeles)
height += (mText->getCharacterWidth() * 1) - 1;
height += mItem[i].rect.h + mItem[i].hPaddingDown;
return height;
}
@@ -563,10 +538,10 @@ Uint16 Menu::findHeight()
// Recoloca los elementos del menu en el eje Y
void Menu::replaceElementsOnY()
{
mItem[0].y = mPosY;
mItem[0].rect.y = mPosY;
for (int i = 1; i < mTotalItems; i++)
mItem[i].y = mItem[i - 1].y + mItem[i - 1].h + mItem[i - 1].hPaddingDown;
mItem[i].rect.y = mItem[i - 1].rect.y + mItem[i - 1].rect.h + mItem[i - 1].hPaddingDown;
}
// Establece el estado seleccionable de un item
@@ -591,7 +566,7 @@ void Menu::setLinkedDown(Uint8 index, bool value)
int Menu::getSelectorHeight(int value)
{
if (mItem[value].linkedDown)
return mItem[value + 1].y + mItem[value + 1].h - mItem[value].y - 1;
return mItem[value].rect.h + mItem[value].hPaddingDown + mItem[value + 1].rect.h;
else
return mItem[value].h - 1;
return mItem[value].rect.h;
}