@ -24,81 +24,171 @@ void Menu::InitializeMenus(){
}
void Menu : : AddButton ( const MenuButton & button ) {
buttons . push_back ( button ) ;
buttons [ button . rect . pos . y ] . push_back ( button ) ;
}
void Menu : : MenuSelect ( Crawler * game ) {
if ( selection = = - 1 ) return ;
buttons [ selection ] . onClick ( * this , game ) ;
if ( buttons [ selection ] . menuDest ! = MenuType : : ENUM_END ) {
if ( stack . size ( ) < 32 ) {
stack . push_back ( & menus [ buttons [ selection ] . menuDest ] ) ; //Navigate to the next menu.
} else {
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! " < < std : : endl ;
throw ;
}
}
}
}
}
void Menu : : Update ( Crawler * game ) {
vf2d upperLeftPos = game - > GetScreenSize ( ) / 2 - size / 2 ;
for ( MenuButton & button : buttons ) {
button . hovered = false ;
for ( auto & key : buttons ) {
for ( auto & button : key . second ) {
button . hovered = false ;
}
}
if ( ! MOUSE_NAVIGATION ) {
if ( selection ! = - 1 ) buttons [ selection ] . hovered = true ;
if ( selection ! = vi2d { - 1 , - 1 } ) buttons [ selection . y ] [ selection . x ] . hovered = true ;
} else {
for ( MenuButton & button : buttons ) {
if ( geom2d : : overlaps ( geom2d : : rect < float > { button . rect . pos + upperLeftPos , button . rect . size } , game - > GetMousePos ( ) ) ) {
button . hovered = true ;
for ( auto & key : buttons ) {
for ( auto & button : key . second ) {
if ( geom2d : : overlaps ( geom2d : : rect < float > { button . rect . pos + upperLeftPos , button . rect . size } , game - > GetMousePos ( ) ) ) {
button . hovered = true ;
}
}
}
}
if ( game - > GetKey ( RIGHT ) . bPressed | | game - > GetKey ( DOWN ) . bPressed ) {
MOUSE_NAVIGATION = false ;
selection = ( selection + 1 ) % buttons . size ( ) ;
}
if ( game - > GetKey ( LEFT ) . bPressed | | game - > GetKey ( UP ) . bPressed ) {
MOUSE_NAVIGATION = false ;
selection - - ;
if ( selection < 0 ) selection + = buttons . size ( ) ;
}
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 = = - 1 & & buttons . size ( ) > 0 ) {
selection = 0 ;
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 ;
int index = 0 ;
for ( MenuButton & button : buttons ) {
if ( geom2d : : overlaps ( geom2d : : rect < float > { button . rect . pos + upperLeftPos , button . rect . size } , game - > GetMousePos ( ) ) ) {
selection = index ;
break ;
selection = { - 1 , - 1 } ;
for ( auto & key : buttons ) {
int index = 0 ;
for ( auto & button : key . second ) {
if ( geom2d : : overlaps ( geom2d : : rect < float > { button . rect . pos + upperLeftPos , button . rect . size } , game - > GetMousePos ( ) ) ) {
selection = { index , key . first } ;
break ;
}
index + + ;
}
index + + ;
}
MenuSelect ( game ) ;
}
}
for ( MenuButton & button : buttons ) {
button . Update ( 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 ( MenuButton & button : buttons ) {
button . Draw ( game , upperLeftPos ) ;
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.
selection . y = key . first ;
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 ) {
selection . y = prevInd ;
} 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 ;
}
}
}