486 lines
11 KiB
C++
486 lines
11 KiB
C++
#include "const.h"
|
|
#include "menu.h"
|
|
|
|
// Constructor
|
|
Menu::Menu(SDL_Renderer *renderer, Text *text, Input *input, std::string *fileList)
|
|
{
|
|
mRenderer = renderer;
|
|
mText = text;
|
|
mInput = input;
|
|
mFileList = fileList;
|
|
}
|
|
|
|
Menu::~Menu()
|
|
{
|
|
mRenderer = nullptr;
|
|
mText = nullptr;
|
|
mInput = nullptr;
|
|
mFileList = nullptr;
|
|
}
|
|
|
|
// Inicializador
|
|
void Menu::init(std::string name, int x, int y, int backgroundType)
|
|
{
|
|
loadMedia();
|
|
|
|
// Inicia variables
|
|
mName = name;
|
|
mSelector.index = 0;
|
|
mTotalItems = 0;
|
|
mItemSelected = MENU_NO_OPTION;
|
|
mVerticalPadding = 1;
|
|
mPosX = x;
|
|
mPosY = y;
|
|
mRectBG.rect.x = 0;
|
|
mRectBG.rect.y = 0;
|
|
mRectBG.rect.w = 0;
|
|
mRectBG.rect.h = 0;
|
|
mRectBG.r = 0;
|
|
mRectBG.g = 0;
|
|
mRectBG.b = 0;
|
|
mSelector.rect.x = 0;
|
|
mSelector.rect.y = 0;
|
|
mSelector.rect.w = 0;
|
|
mSelector.rect.h = 0;
|
|
mSelector.r = 0;
|
|
mSelector.g = 0;
|
|
mSelector.b = 0;
|
|
mSelector.a = 255;
|
|
mBackgroundType = backgroundType;
|
|
mIsCentered = false;
|
|
mAreElementsCentered = false;
|
|
mCenter = x + ((SCREEN_WIDTH - x) / 2);
|
|
mWidestItem = 0;
|
|
|
|
// Selector
|
|
mSelector.origin = 0;
|
|
mSelector.target = 0;
|
|
mSelector.y = 0;
|
|
mSelector.numJumps = 4;
|
|
mSelector.despY = 0;
|
|
mSelector.moving = false;
|
|
|
|
// Sprite con los graficos del selector
|
|
//mSelectorSprite.setWidth(8);
|
|
//mSelectorSprite.setHeight(8);
|
|
//mSelectorSprite.setPosX(0);
|
|
//mSelectorSprite.setPosY(0);
|
|
//mSelectorSprite.setTexture(texture);
|
|
//mSelectorSprite.setRenderer(renderer);
|
|
//mSelectorSprite.setSpriteClip(0, 0, mSelectorSprite.getWidth(), mSelectorSprite.getHeight());
|
|
|
|
// Elementos del menu
|
|
for (int i = 0; i < 10; 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].hPaddingDown = 0;
|
|
}
|
|
|
|
// Mueve el grafico del selector al elemento seleccionado
|
|
//moveSelectorSprite(mSelector.index);
|
|
}
|
|
|
|
// Carga los recursos necesarios para la sección 'Title'
|
|
bool Menu::loadMedia()
|
|
{
|
|
// Indicador de éxito en la carga
|
|
bool success = true;
|
|
|
|
// Sonidos
|
|
mSoundMove = JA_LoadSound(mFileList[17].c_str());
|
|
mSoundAccept = JA_LoadSound(mFileList[18].c_str());
|
|
mSoundCancel = JA_LoadSound(mFileList[16].c_str());
|
|
|
|
return success;
|
|
}
|
|
|
|
// Obtiene el nombre del menu
|
|
std::string Menu::getName()
|
|
{
|
|
return mName;
|
|
}
|
|
|
|
// Obtiene el valor de la variable
|
|
Uint8 Menu::getItemSelected()
|
|
{
|
|
const int temp = mItemSelected;
|
|
mItemSelected = MENU_NO_OPTION;
|
|
return temp;
|
|
}
|
|
|
|
// Mueve el grafico del selector al elemento seleccionado
|
|
/*void Menu::moveSelectorSprite(int pos)
|
|
{
|
|
mSelector.rect.y = mItem[pos].y - 1;
|
|
}*/
|
|
|
|
// Actualiza la posicion y el estado del selector
|
|
void Menu::updateSelector()
|
|
{
|
|
if (mSelector.moving)
|
|
{
|
|
mSelector.y += mSelector.despY;
|
|
if (mSelector.despY > 0) // Va hacia abajo
|
|
{
|
|
if (mSelector.y > mSelector.target) // Ha llegado al destino
|
|
{
|
|
mSelector.origin = mSelector.y = mSelector.target;
|
|
mSelector.moving = false;
|
|
}
|
|
}
|
|
if (mSelector.despY < 0) // Va hacia abajo
|
|
{
|
|
if (mSelector.y < mSelector.target) // Ha llegado al destino
|
|
{
|
|
mSelector.origin = mSelector.y = mSelector.target;
|
|
mSelector.moving = false;
|
|
}
|
|
}
|
|
mSelector.rect.y = int(mSelector.y) - 1;
|
|
}
|
|
else
|
|
{
|
|
mSelector.rect.y = int(mSelector.y) - 1;
|
|
}
|
|
}
|
|
|
|
// Establece el origen del selector
|
|
void Menu::setSelectorOrigin(int value)
|
|
{
|
|
mSelector.origin = value;
|
|
}
|
|
|
|
// Establece el destino del selector
|
|
void Menu::setSelectorTarget(int value)
|
|
{
|
|
mSelector.target = value;
|
|
}
|
|
|
|
// Coloca el selector en una posición específica
|
|
void Menu::setSelectorPos(Uint8 index)
|
|
{
|
|
if (index < mTotalItems)
|
|
{
|
|
mSelector.index = index;
|
|
mSelector.y = mSelector.origin = mSelector.target = mItem[mSelector.index].y;
|
|
mSelector.moving = false;
|
|
}
|
|
}
|
|
|
|
// Obtiene la anchura del elemento más ancho del menu
|
|
Uint16 Menu::getWidestItem()
|
|
{
|
|
Uint16 result = 0;
|
|
|
|
// Obtenemos la anchura del item mas ancho
|
|
for (int i = 0; i < mTotalItems; i++)
|
|
{
|
|
if (mItem[i].w > result)
|
|
{
|
|
result = mItem[i].w;
|
|
}
|
|
}
|
|
|
|
return result;
|
|
}
|
|
|
|
// Deja el menu apuntando al primer elemento
|
|
void Menu::reset()
|
|
{
|
|
mItemSelected = MENU_NO_OPTION;
|
|
mSelector.index = 0;
|
|
//moveSelectorSprite(mSelector.index);
|
|
mSelector.origin = mSelector.target = mSelector.y = mItem[0].y;
|
|
mSelector.moving = 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()
|
|
{
|
|
setRectSize();
|
|
if (mIsCentered)
|
|
centerMenu(mCenter);
|
|
if (mAreElementsCentered)
|
|
centerMenuElements();
|
|
}
|
|
|
|
// Deja el menu apuntando al siguiente elemento
|
|
bool Menu::increaseSelectorIndex()
|
|
{
|
|
bool success = false;
|
|
mSelector.y = mSelector.origin = mItem[mSelector.index].y;
|
|
|
|
if (mSelector.index < (mTotalItems - 1))
|
|
{
|
|
mSelector.index++;
|
|
success = true;
|
|
}
|
|
|
|
mSelector.target = mItem[mSelector.index].y;
|
|
mSelector.despY = (mSelector.target - mSelector.origin) / mSelector.numJumps;
|
|
mSelector.moving = true;
|
|
return success;
|
|
}
|
|
|
|
// Deja el menu apuntando al elemento anterior
|
|
bool Menu::decreaseSelectorIndex()
|
|
{
|
|
bool success = false;
|
|
mSelector.y = mSelector.origin = mItem[mSelector.index].y;
|
|
|
|
if (mSelector.index > 0)
|
|
{
|
|
mSelector.index--;
|
|
success = true;
|
|
}
|
|
|
|
mSelector.target = mItem[mSelector.index].y;
|
|
mSelector.despY = (mSelector.target - mSelector.origin) / mSelector.numJumps;
|
|
mSelector.moving = true;
|
|
return success;
|
|
}
|
|
|
|
// Actualiza la logica del menu
|
|
void Menu::update()
|
|
{
|
|
updateSelector();
|
|
}
|
|
|
|
// Pinta el menu en pantalla
|
|
void Menu::render()
|
|
{
|
|
// Rendereritza el fondo del menu
|
|
if (mBackgroundType == MENU_BACKGROUND_SOLID)
|
|
{
|
|
SDL_SetRenderDrawColor(mRenderer, mRectBG.r, mRectBG.g, mRectBG.b, mRectBG.a);
|
|
SDL_RenderFillRect(mRenderer, &mRectBG.rect);
|
|
}
|
|
|
|
// Renderiza el rectangulo del selector
|
|
SDL_SetRenderDrawColor(mRenderer, mSelector.r, mSelector.g, mSelector.b, mSelector.a);
|
|
SDL_RenderFillRect(mRenderer, &mSelector.rect);
|
|
|
|
// Renderiza el borde del fondo
|
|
if (mBackgroundType == MENU_BACKGROUND_SOLID)
|
|
{
|
|
SDL_SetRenderDrawColor(mRenderer, mRectBG.r, mRectBG.g, mRectBG.b, 255);
|
|
SDL_RenderDrawRect(mRenderer, &mRectBG.rect);
|
|
}
|
|
|
|
// Renderiza el sprite del selector
|
|
//mSelectorSprite.render();
|
|
|
|
// Renderitza el text
|
|
for (int i = 0; i < mTotalItems; i++)
|
|
{
|
|
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);
|
|
}
|
|
else
|
|
{
|
|
mText->write(mItem[i].x, mItem[i].y, mItem[i].label, 0);
|
|
}
|
|
}
|
|
}
|
|
|
|
// Establece el rectangulo de fondo del menu y el selector
|
|
void Menu::setRectSize()
|
|
{
|
|
Uint8 i = 0;
|
|
mRectBG.rect.w = 0;
|
|
mRectBG.rect.h = 0;
|
|
mSelector.rect.w = 0;
|
|
mSelector.rect.h = 0;
|
|
|
|
// Obtenemos la anchura del item mas ancho y la altura de la suma de alturas de los items
|
|
for (i = 0; i < mTotalItems; i++)
|
|
{
|
|
if (mItem[i].w > mRectBG.rect.w)
|
|
{
|
|
mRectBG.rect.w = mItem[i].w;
|
|
}
|
|
mRectBG.rect.h += mItem[i].h + mItem[i].hPaddingDown;
|
|
}
|
|
|
|
// La anchura de la cadena más larga, mas un caracter, mas la anchura del sprite del selector
|
|
mRectBG.rect.w += (mText->getSize() * 1); // + mSelectorSprite.getWidth();
|
|
|
|
// La altura de la suma de los items mas un caracter y menos un pixel (porque el texto en realidad es de 7 pixeles)
|
|
mRectBG.rect.h += (mText->getSize() * 1) - 1;
|
|
|
|
// La posición X es la del menú menos la anchura del sprite del selector y menos medio caracter
|
|
mRectBG.rect.x = mPosX - (mText->getSize() / 2); // - mSelectorSprite.getWidth();
|
|
|
|
// La posición Y es la del menu menos la altura de medio caracter i el padding
|
|
mRectBG.rect.y = mPosY - (mText->getSize() / 2) - mVerticalPadding;
|
|
|
|
// Establecemos los valores del rectangulo del selector a partir de los valores del rectangulo de fondo
|
|
mSelector.rect.h = (mText->getSize() * 1) + 1;
|
|
mSelector.rect.w = mRectBG.rect.w;
|
|
mSelector.rect.x = mRectBG.rect.x;
|
|
}
|
|
|
|
// Establece el valor de la variable
|
|
void Menu::setTotalItems(int num)
|
|
{
|
|
mTotalItems = num;
|
|
}
|
|
|
|
// Establece el color del rectangulo de fondo
|
|
void Menu::setBackgroundColor(int r, int g, int b, int alpha)
|
|
{
|
|
mRectBG.r = r;
|
|
mRectBG.g = g;
|
|
mRectBG.b = b;
|
|
mRectBG.a = alpha;
|
|
}
|
|
|
|
// Establece el color del rectangulo del selector
|
|
void Menu::setSelectorColor(int r, int g, int b, int alpha)
|
|
{
|
|
mSelector.r = r;
|
|
mSelector.g = g;
|
|
mSelector.b = b;
|
|
mSelector.a = alpha;
|
|
}
|
|
|
|
// Establece el color del texto del selector
|
|
void Menu::setSelectorTextColor(int r, int g, int b)
|
|
{
|
|
mSelector.itemR = r;
|
|
mSelector.itemG = g;
|
|
mSelector.itemB = b;
|
|
}
|
|
|
|
// Centra el menu respecto un punto
|
|
void Menu::centerMenu(int value)
|
|
{
|
|
mIsCentered = true;
|
|
mCenter = value;
|
|
|
|
// Actualiza el rectangulo de fondo para recalcular las dimensiones
|
|
setRectSize();
|
|
|
|
// Obten el acho del menu
|
|
mWidestItem = getWidestItem();
|
|
|
|
// Establece la nueva posición centrada en funcion del elemento más ancho
|
|
mPosX = (value) - (mWidestItem / 2);
|
|
|
|
// Reposiciona los elementos del menu
|
|
for (int i = 0; i < 10; i++)
|
|
{
|
|
mItem[i].x = mPosX;
|
|
}
|
|
|
|
// Recalcula el rectangulo de fondo
|
|
setRectSize();
|
|
|
|
// Recoloca el selector
|
|
mSelector.origin = mSelector.target = mSelector.y = mItem[mSelector.index].y;
|
|
mSelector.moving = false;
|
|
//moveSelectorSprite(mSelector.index);
|
|
}
|
|
|
|
// Centra los elementos del menu
|
|
void Menu::centerMenuElements()
|
|
{
|
|
mAreElementsCentered = true;
|
|
|
|
for (int i = 0; i < mTotalItems; i++)
|
|
{
|
|
//mItem[i].x = (mCenter - ((mText->lenght(mItem[i].label, 0)) / 2));
|
|
mItem[i].x = (mCenter - (mItem[i].w / 2));
|
|
}
|
|
|
|
// Mueve el grafico del selector al elemento seleccionado
|
|
//moveSelectorSprite(mSelector.index);
|
|
}
|
|
|
|
// Añade un item al menu
|
|
void Menu::addItem(std::string text, const Uint8 hPaddingUp, const Uint8 hPaddingDown)
|
|
{
|
|
// Si es el primer item coge la posición y del propio menu
|
|
if (mTotalItems == 0)
|
|
{
|
|
mItem[mTotalItems].label = text;
|
|
mItem[mTotalItems].w = mText->lenght(mItem[mTotalItems].label, 0);
|
|
mItem[mTotalItems].h = mText->getSize() + (mVerticalPadding * 2);
|
|
mItem[mTotalItems].x = mPosX;
|
|
mItem[mTotalItems].y = mPosY;
|
|
mItem[mTotalItems].hPaddingUp = hPaddingUp;
|
|
mItem[mTotalItems].hPaddingDown = hPaddingDown;
|
|
}
|
|
else
|
|
{
|
|
// En caso contrario, coge la posición y a partir del elemento anterior
|
|
if (mTotalItems < 10)
|
|
{
|
|
mItem[mTotalItems].label = text;
|
|
mItem[mTotalItems].w = mText->lenght(mItem[mTotalItems].label, 0);
|
|
mItem[mTotalItems].h = mText->getSize() + (mVerticalPadding * 2);
|
|
mItem[mTotalItems].x = mPosX;
|
|
mItem[mTotalItems].y = mItem[mTotalItems - 1].y + mItem[mTotalItems - 1].h + mItem[mTotalItems - 1].hPaddingDown;
|
|
mItem[mTotalItems].hPaddingUp = hPaddingUp;
|
|
mItem[mTotalItems].hPaddingDown = hPaddingDown;
|
|
}
|
|
}
|
|
setTotalItems(mTotalItems + 1);
|
|
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, 0);
|
|
reorganize();
|
|
}
|
|
|
|
// Establece el indice del itemm que se usará por defecto al cancelar el menu
|
|
void Menu::setDefaultActionWhenCancel(Uint8 item)
|
|
{
|
|
mDefaultActionWhenCancel = item;
|
|
}
|
|
|
|
// Gestiona la entrada de teclado y mando durante el menu
|
|
void Menu::checkInput()
|
|
{
|
|
if (mInput->checkInput(INPUT_UP, REPEAT_FALSE))
|
|
{
|
|
if (decreaseSelectorIndex())
|
|
JA_PlaySound(mSoundMove);
|
|
}
|
|
|
|
if (mInput->checkInput(INPUT_DOWN, REPEAT_FALSE))
|
|
{
|
|
if (increaseSelectorIndex())
|
|
JA_PlaySound(mSoundMove);
|
|
}
|
|
|
|
if (mInput->checkInput(INPUT_ACCEPT, REPEAT_FALSE))
|
|
{
|
|
mItemSelected = mSelector.index;
|
|
JA_PlaySound(mSoundAccept);
|
|
}
|
|
|
|
if (mInput->checkInput(INPUT_CANCEL, REPEAT_FALSE))
|
|
{
|
|
mItemSelected = mDefaultActionWhenCancel;
|
|
JA_PlaySound(mSoundCancel);
|
|
}
|
|
} |