#include "Crawler.h" #include "Menu.h" bool Menu::MOUSE_NAVIGATION=true; std::vectorMenu::stack; std::mapMenu::menus; Menu::Menu(){} Menu::Menu(vf2d size) :size(size){} void Menu::InitializeMenus(){ stack.reserve(32); menus[TEST]=InitializeTestMenu(); menus[TEST_2]=InitializeTestSubMenu(); for(MenuType type=TEST;typerect.pos.y].push_back(button); } void Menu::MenuSelect(Crawler*game){ if(selection==vi2d{-1,-1})return; buttons[selection.y][selection.x]->onClick(*this,game); if(buttons[selection.y][selection.x]->menuDest!=MenuType::ENUM_END){ if(stack.size()<32){ stack.push_back(&menus[buttons[selection.y][selection.x]->menuDest]);//Navigate to the next menu. }else{ std::cout<<"WARNING! Exceeded menu stack size limit!"<GetScreenSize()/2-size/2; for(auto&key:buttons){ for(auto&button:key.second){ button->hovered=false; } } if(!MOUSE_NAVIGATION){ if(selection!=vi2d{-1,-1})buttons[selection.y][selection.x]->hovered=true; }else{ for(auto&key:buttons){ for(auto&button:key.second){ if(geom2d::overlaps(geom2d::rect{button->rect.pos+upperLeftPos,button->rect.size},game->GetMousePos())){ button->hovered=true; } } } } KeyboardButtonNavigation(game); if(game->GetMouse(0).bPressed||game->GetKey(ENTER).bPressed||game->GetKey(SPACE).bPressed){ MOUSE_NAVIGATION=game->GetMouse(0).bPressed; //If a click occurs we use mouse controls. if(!MOUSE_NAVIGATION){ MenuSelect(game); //Key presses automatically highlight the first button if it's not highlighted. if(selection==vi2d{-1,-1}&&buttons.size()>0){ //Find the first possible button entry in the map... int firstInd=-1; for(auto&key:buttons){ if(buttons[key.first].size()>0){ firstInd=key.first; break; } } if(firstInd!=-1){ //This means we found a valid menu item. If we didn't find one don't highlight any menu item... selection={0,firstInd}; } } }else{//Mouse click. selection={-1,-1}; for(auto&key:buttons){ int index=0; for(auto&button:key.second){ if(geom2d::overlaps(geom2d::rect{button->rect.pos+upperLeftPos,button->rect.size},game->GetMousePos())){ selection={index,key.first}; break; } index++; } } MenuSelect(game); } } for(auto&key:buttons){ for(auto&button:key.second){ button->Update(game); } } }; void Menu::Draw(Crawler*game){ vf2d upperLeftPos=game->GetScreenSize()/2-size/2; game->FillRectDecal(upperLeftPos,size,VERY_DARK_BLUE); for(auto&key:buttons){ for(auto&button:key.second){ button->Draw(game,upperLeftPos); } } }; void Menu::OpenMenu(MenuType menu){ stack.clear(); stack.push_back(&(menus[menu])); } void Menu::KeyboardButtonNavigation(Crawler*game){ if(game->GetKey(RIGHT).bPressed){ if(selection==vi2d{-1,-1})return; MOUSE_NAVIGATION=false; selection.x=(selection.x+1)%buttons[selection.y].size(); } if(game->GetKey(LEFT).bPressed){ if(selection==vi2d{-1,-1})return; selection.x--; if(selection.x<0)selection.x+=buttons[selection.y].size(); } if(game->GetKey(DOWN).bPressed||game->GetKey(UP).bPressed){ if(game->GetKey(DOWN).bPressed){ MOUSE_NAVIGATION=false; bool found=false; bool selectedItem=false; if(selection==vi2d{-1,-1}){ //Highlight first item. for(auto&key:buttons){ selection.y=key.first; break; } }else{ for(auto&key:buttons){ if(found){ //Once we discover the previous element, the next element becomes our next selection. int previousButtonX=buttons[selection.y][selection.x]->rect.pos.x; selection.y=key.first; int index=0; for(auto&button:key.second){ //Try to match a button in the same column as this button first. if(previousButtonX==button->rect.pos.x){ selection.x=index; break; } index++; } selectedItem=true; break; } if(key.first==selection.y){ found=true; } } if(!selectedItem){ //This means we need to loop around instead and pick the first one. for(auto&key:buttons){ selection.y=key.first; break; } } } } if(game->GetKey(UP).bPressed){ MOUSE_NAVIGATION=false; if(selection==vi2d{-1,-1}){ //Highlight last item. for(auto&key:buttons){ selection.y=key.first; } }else{ int prevInd=-1; for(auto&key:buttons){ if(key.first==selection.y){ break; } prevInd=key.first; } if(prevInd!=-1){ int previousButtonX=buttons[selection.y][selection.x]->rect.pos.x; selection.y=prevInd; int index=0; for(auto&button:buttons[prevInd]){ //Try to match a button in the same column as this button first. if(previousButtonX==button->rect.pos.x){ selection.x=index; break; } index++; } }else{ //Since we didn't find it, it means we're at the top of the list or the list is empty. Go to the last element and use that one. int lastInd=-1; for(auto&key:buttons){ lastInd=key.first; } selection.y=lastInd; } } } //In both cases, we should clamp the X index to make sure it's still valid. if(selection.y!=-1){ selection.x=std::clamp(selection.x,0,int(buttons[selection.y].size())-1); }else{ selection.x=-1; } } }