Implemented class selection window controller/keyboard compatibility. Added selection passthrough for disabled/grayed out items. Change hover fade-in for toggleable buttons. Release Build 6988.

pull/35/head
sigonasr2 10 months ago
parent f5bcd4f869
commit a449932226
  1. 16
      Adventures in Lestoria/AdventuresInLestoria.cpp
  2. 5
      Adventures in Lestoria/AdventuresInLestoria.h
  3. 126
      Adventures in Lestoria/ClassSelectionWindow.cpp
  4. 10
      Adventures in Lestoria/Menu.cpp
  5. 1
      Adventures in Lestoria/Menu.h
  6. 17
      Adventures in Lestoria/MenuAnimatedIconToggleButton.h
  7. 1
      Adventures in Lestoria/MenuComponent.cpp
  8. 6
      Adventures in Lestoria/MenuType.h
  9. 4
      Adventures in Lestoria/SaveFileWindow.cpp
  10. 2
      Adventures in Lestoria/Version.h
  11. BIN
      x64/Release/Adventures in Lestoria.exe

@ -113,6 +113,11 @@ InputGroup AiL::KEY_START;
InputGroup AiL::KEY_SELECT; InputGroup AiL::KEY_SELECT;
InputGroup AiL::KEY_UNEQUIP; InputGroup AiL::KEY_UNEQUIP;
InputGroup AiL::KEY_FACEUP;
InputGroup AiL::KEY_FACERIGHT;
InputGroup AiL::KEY_FACELEFT;
InputGroup AiL::KEY_FACEDOWN;
InputGroup AiL::KEY_SCROLLDOWN; InputGroup AiL::KEY_SCROLLDOWN;
InputGroup AiL::KEY_SCROLLUP; InputGroup AiL::KEY_SCROLLUP;
InputGroup AiL::KEY_FASTSCROLLDOWN; InputGroup AiL::KEY_FASTSCROLLDOWN;
@ -2504,7 +2509,7 @@ void AiL::InitializeDefaultKeybinds(){
KEY_FASTSCROLLDOWN.AddKeybind({CONTROLLER,static_cast<int>(GPButtons::R1)}); KEY_FASTSCROLLDOWN.AddKeybind({CONTROLLER,static_cast<int>(GPButtons::R1)});
KEY_FASTSCROLLDOWN.AddKeybind({CONTROLLER,static_cast<int>(GPButtons::R2)}); KEY_FASTSCROLLDOWN.AddKeybind({CONTROLLER,static_cast<int>(GPButtons::R2)});
KEY_CHANGE_LOADOUT.AddKeybind({KEY,X}); KEY_CHANGE_LOADOUT.AddKeybind({KEY,R});
KEY_CHANGE_LOADOUT.AddKeybind({CONTROLLER,static_cast<int>(GPButtons::FACE_U)}); KEY_CHANGE_LOADOUT.AddKeybind({CONTROLLER,static_cast<int>(GPButtons::FACE_U)});
KEY_START.AddKeybind({KEY,RETURN}); KEY_START.AddKeybind({KEY,RETURN});
@ -2512,6 +2517,15 @@ void AiL::InitializeDefaultKeybinds(){
KEY_SELECT.AddKeybind({KEY,ESCAPE}); KEY_SELECT.AddKeybind({KEY,ESCAPE});
KEY_SELECT.AddKeybind({CONTROLLER,static_cast<int>(GPButtons::SELECT)}); KEY_SELECT.AddKeybind({CONTROLLER,static_cast<int>(GPButtons::SELECT)});
KEY_FACEUP.AddKeybind({KEY,R});
KEY_FACEUP.AddKeybind({CONTROLLER,static_cast<int>(GPButtons::FACE_U)});
KEY_FACERIGHT.AddKeybind({KEY,Z});
KEY_FACERIGHT.AddKeybind({CONTROLLER,static_cast<int>(GPButtons::FACE_R)});
KEY_FACELEFT.AddKeybind({KEY,F});
KEY_FACELEFT.AddKeybind({CONTROLLER,static_cast<int>(GPButtons::FACE_L)});
KEY_FACEDOWN.AddKeybind({KEY,X});
KEY_FACEDOWN.AddKeybind({CONTROLLER,static_cast<int>(GPButtons::FACE_D)});
KEY_SCROLLLEFT.AddKeybind({ANALOG,static_cast<int>(GPAxes::LX)}); KEY_SCROLLLEFT.AddKeybind({ANALOG,static_cast<int>(GPAxes::LX)});
KEY_SCROLLLEFT.AddKeybind({ANALOG,static_cast<int>(GPAxes::RX)}); KEY_SCROLLLEFT.AddKeybind({ANALOG,static_cast<int>(GPAxes::RX)});
KEY_SCROLLRIGHT.AddKeybind({ANALOG,static_cast<int>(GPAxes::LX)}); KEY_SCROLLRIGHT.AddKeybind({ANALOG,static_cast<int>(GPAxes::LX)});

@ -86,6 +86,11 @@ public:
static InputGroup KEY_START; static InputGroup KEY_START;
static InputGroup KEY_SELECT; static InputGroup KEY_SELECT;
static InputGroup KEY_FACEUP;
static InputGroup KEY_FACERIGHT;
static InputGroup KEY_FACELEFT;
static InputGroup KEY_FACEDOWN;
static InputGroup KEY_FASTSCROLLDOWN; static InputGroup KEY_FASTSCROLLDOWN;
static InputGroup KEY_FASTSCROLLUP; static InputGroup KEY_FASTSCROLLUP;
static InputGroup KEY_SCROLLDOWN; static InputGroup KEY_SCROLLDOWN;

@ -73,9 +73,9 @@ void Menu::InitializeClassSelectionWindow(){
vf2d navigationButtonSize={24*2.5f,16}; vf2d navigationButtonSize={24*2.5f,16};
classSelectionWindow->ADD("Back",MenuComponent)(geom2d::rect<float>{{6,outlineSize.y+29-navigationButtonSize.y-2},navigationButtonSize},"Back",[](MenuFuncData){Menu::CloseMenu();return true;})END; classSelectionWindow->ADD("Back",MenuComponent)(geom2d::rect<float>{{6,outlineSize.y+29-navigationButtonSize.y-14},navigationButtonSize},"Back",[](MenuFuncData){Menu::CloseMenu();return true;})END;
classSelectionWindow->ADD("Confirm",MenuComponent)(geom2d::rect<float>{{outlineSize.x+4-navigationButtonSize.x-2,outlineSize.y+29-navigationButtonSize.y-2},navigationButtonSize},"Confirm",[](MenuFuncData data){ classSelectionWindow->ADD("Confirm",MenuComponent)(geom2d::rect<float>{{outlineSize.x+4-navigationButtonSize.x-2,outlineSize.y+29-navigationButtonSize.y-14},navigationButtonSize},"Confirm",[](MenuFuncData data){
std::string selectedClass=data.component.lock()->S(A::CLASS_SELECTION); std::string selectedClass=data.component.lock()->S(A::CLASS_SELECTION);
data.game->ChangePlayerClass(classutils::StringToClass(selectedClass)); data.game->ChangePlayerClass(classutils::StringToClass(selectedClass));
#ifdef __EMSCRIPTEN__ #ifdef __EMSCRIPTEN__
@ -134,15 +134,16 @@ void Menu::InitializeClassSelectionWindow(){
vf2d backgroundSize={floor(outlineSize.y/3-buttonPadding.y*3),outlineSize.y/3-buttonPadding.y*3}; //The floor is for fixing a small pixel rounding bug. vf2d backgroundSize={floor(outlineSize.y/3-buttonPadding.y*3),outlineSize.y/3-buttonPadding.y*3}; //The floor is for fixing a small pixel rounding bug.
classSelectionWindow->ADD(className+" Background",MenuLabel)(geom2d::rect<float>{backgroundOffsetPos,backgroundSize},"",1,ComponentAttr::OUTLINE|ComponentAttr::BACKGROUND)END; auto classLabel=classSelectionWindow->ADD(className+" Background",MenuLabel)(geom2d::rect<float>{backgroundOffsetPos,backgroundSize},"",1,ComponentAttr::OUTLINE|ComponentAttr::BACKGROUND)END;
classSelectionWindow->ADD(className+" Button",MenuComponent)(geom2d::rect<float>{offsetPos,buttonSize},"Info",CLASS_INFO, auto classButton=classSelectionWindow->ADD(className+" Button",MenuComponent)(geom2d::rect<float>{offsetPos,buttonSize},"Info",CLASS_INFO,
[](MenuFuncData data){ [](MenuFuncData data){
data.menu.S(A::CLASS_SELECTION)=data.component.lock()->S(A::CLASS_SELECTION); data.menu.S(A::CLASS_SELECTION)=data.component.lock()->S(A::CLASS_SELECTION);
delete Menu::menus[CLASS_INFO]; delete Menu::menus[CLASS_INFO];
Menu::InitializeClassInfoWindow(); Menu::InitializeClassInfoWindow();
return true; return true;
})END })END;
->S(A::CLASS_SELECTION)=className; classButton->S(A::CLASS_SELECTION)=className;
classSelectionWindow->ADD(className+" Label",MenuLabel)(geom2d::rect<float>{backgroundOffsetPos,buttonSize},className,1,ComponentAttr::SHADOW)END; classSelectionWindow->ADD(className+" Label",MenuLabel)(geom2d::rect<float>{backgroundOffsetPos,buttonSize},className,1,ComponentAttr::SHADOW)END;
auto classSprite=classSelectionWindow->ADD(className+" Icon",MenuAnimatedIconToggleButton)(geom2d::rect<float>{backgroundOffsetPos+vf2d{0,12},backgroundSize+vf2d{0,-buttonSize.y-12}},classAnimationName,[](MenuFuncData data){ auto classSprite=classSelectionWindow->ADD(className+" Icon",MenuAnimatedIconToggleButton)(geom2d::rect<float>{backgroundOffsetPos+vf2d{0,12},backgroundSize+vf2d{0,-buttonSize.y-12}},classAnimationName,[](MenuFuncData data){
data.menu.components["Confirm"]->Enable(true); data.menu.components["Confirm"]->Enable(true);
@ -150,6 +151,12 @@ void Menu::InitializeClassSelectionWindow(){
return true; return true;
})END; })END;
if(i>=3){
classLabel->SetGrayedOut(true);
classButton->SetGrayedOut(true);
classSprite->SetGrayedOut(true);
}
classSprite->S(A::CLASS_SELECTION)=className; classSprite->S(A::CLASS_SELECTION)=className;
toggleGroup.push_back(classSprite); toggleGroup.push_back(classSprite);
@ -172,4 +179,111 @@ void Menu::InitializeClassSelectionWindow(){
for(std::weak_ptr<IToggleable>item:toggleGroup){ for(std::weak_ptr<IToggleable>item:toggleGroup){
item.lock()->SetToggleGroup(toggleGroup); item.lock()->SetToggleGroup(toggleGroup);
} }
classSelectionWindow->SetupKeyboardNavigation(
[](MenuType type,Data&returnData){ //On Open
returnData=Warrior::name+" Button";
},
{ //Button Key
{game->KEY_BACK,{"Back",[](MenuType type){
Component<MenuComponent>(type,"Back")->Click();
}}},
{game->KEY_START,{"Confirm",[](MenuType type){
Component<MenuComponent>(type,"Confirm")->Click();
}}},
{game->KEY_FACEUP,{"Change Player Name",[](MenuType type){
Component<SaveFileNameButton>(type,"Character Name Box")->Click();
}}},
}
,{ //Button Navigation Rules
{Warrior::name+" Button",{
.up=Warrior::name+" Icon",
.down=Thief::name+" Icon",
.left="Back",
.right=Ranger::name+" Button",
}},
{Warrior::name+" Icon",{
.up="Character Name Box",
.down=Warrior::name+" Button",
.left="Back",
.right=Ranger::name+" Icon",
}},
{Ranger::name+" Button",{
.up=Ranger::name+" Icon",
.down=Trapper::name+" Icon",
.left=Warrior::name+" Button",
.right=Wizard::name+" Button",
}},
{Ranger::name+" Icon",{
.up="Character Name Box",
.down=Ranger::name+" Button",
.left=Warrior::name+" Icon",
.right=Wizard::name+" Icon",
}},
{Wizard::name+" Button",{
.up=Wizard::name+" Icon",
.down=Witch::name+" Icon",
.left=Ranger::name+" Button",
.right="Confirm",
}},
{Wizard::name+" Icon",{
.up="Character Name Box",
.down=Wizard::name+" Button",
.left=Ranger::name+" Icon",
.right="Confirm",
}},
{Thief::name+" Button",{
.up=Thief::name+" Icon",
.down="Character Name Box",
.left="Back",
.right=Trapper::name+" Button",
}},
{Thief::name+" Icon",{
.up=Warrior::name+" Button",
.down=Thief::name+" Button",
.left="Back",
.right=Trapper::name+" Icon",
}},
{Trapper::name+" Button",{
.up=Trapper::name+" Icon",
.down="Character Name Box",
.left=Thief::name+" Button",
.right=Witch::name+" Button",
}},
{Trapper::name+" Icon",{
.up=Ranger::name+" Button",
.down=Trapper::name+" Button",
.left=Thief::name+" Icon",
.right=Witch::name+" Icon",
}},
{Witch::name+" Button",{
.up=Witch::name+" Icon",
.down="Character Name Box",
.left=Trapper::name+" Button",
.right="Confirm",
}},
{Witch::name+" Icon",{
.up=Wizard::name+" Button",
.down=Witch::name+" Button",
.left=Trapper::name+" Icon",
.right="Confirm",
}},
{"Character Name Box",{
.up=Witch::name+" Button",
.down=Wizard::name+" Icon",
}},
{"Confirm",{
.up=Wizard::name+" Button",
.down=Wizard::name+" Button",
.left=Wizard::name+" Button",
.right="Back",
}},
{"Back",{
.up=Warrior::name+" Button",
.down=Warrior::name+" Button",
.left="Confirm",
.right=Warrior::name+" Button",
}},
});
} }

@ -44,6 +44,7 @@ All rights reserved.
#include "ScrollableWindowComponent.h" #include "ScrollableWindowComponent.h"
#include "RowInventoryScrollableWindowComponent.h" #include "RowInventoryScrollableWindowComponent.h"
#include "MenuItemItemButton.h" #include "MenuItemItemButton.h"
#include <variant>
INCLUDE_ITEM_CATEGORIES INCLUDE_ITEM_CATEGORIES
INCLUDE_DATA INCLUDE_DATA
@ -294,6 +295,7 @@ void Menu::OpenMenu(MenuType menu,bool cover){
if(menus[menu]->onOpenFunc){ if(menus[menu]->onOpenFunc){
Data returnData; Data returnData;
menus[menu]->onOpenFunc(menu,returnData); menus[menu]->onOpenFunc(menu,returnData);
menus[menu]->defaultButton=returnData;
if(std::holds_alternative<ButtonName>(returnData)&&std::get<ButtonName>(returnData).length()>0||std::holds_alternative<std::weak_ptr<MenuComponent>>(returnData))menus[menu]->SetSelection(returnData,true); if(std::holds_alternative<ButtonName>(returnData)&&std::get<ButtonName>(returnData).length()>0||std::holds_alternative<std::weak_ptr<MenuComponent>>(returnData))menus[menu]->SetSelection(returnData,true);
} }
stack.push_back(menus[menu]); stack.push_back(menus[menu]);
@ -335,16 +337,15 @@ void Menu::KeyboardButtonNavigation(AiL*game,vf2d menuPos){
} }
} }
} }
if(!selection.expired()){ if(!selection.expired()){
do{
if(navigationGroups.size()==0)break; //We don't do anything here when there are no navigation groups.
std::string selectionButtonName=selection.lock()->GetName(); std::string selectionButtonName=selection.lock()->GetName();
if(!selection.lock()->parentComponent.expired()){ //If a component has a parent, then we use the parent as the identifier for what should happen next. if(!selection.lock()->parentComponent.expired()){ //If a component has a parent, then we use the parent as the identifier for what should happen next.
selectionButtonName=selection.lock()->parentComponent.lock()->GetName(); selectionButtonName=selection.lock()->parentComponent.lock()->GetName();
} }
if(navigationGroups.count(selectionButtonName)){ if(navigationGroups.count(selectionButtonName)){
Navigation nav=navigationGroups[selectionButtonName]; Navigation nav=navigationGroups[selectionButtonName];
if(game->KEY_UP.PressedDAS()||game->KEY_SCROLLUP.AnalogDAS()<-0.2f){ if(game->KEY_UP.PressedDAS()||game->KEY_SCROLLUP.AnalogDAS()<-0.2f){
SetMouseNavigation(false); SetMouseNavigation(false);
if(std::holds_alternative<std::string>(nav.up)&&std::get<std::string>(nav.up).length()>0)SetSelection(std::string_view(std::get<std::string>(nav.up))); if(std::holds_alternative<std::string>(nav.up)&&std::get<std::string>(nav.up).length()>0)SetSelection(std::string_view(std::get<std::string>(nav.up)));
@ -385,7 +386,10 @@ void Menu::KeyboardButtonNavigation(AiL*game,vf2d menuPos){
SetSelection(returnData); SetSelection(returnData);
} }
} }
}else{
if(std::holds_alternative<ButtonName>(defaultButton)&&std::get<ButtonName>(defaultButton).length()>0||std::holds_alternative<std::weak_ptr<MenuComponent>>(defaultButton))SetSelection(defaultButton,true);
} }
}while(selection.lock()->disabled||selection.lock()->grayedOut);
} }
if(game->KEY_UP.Released()||game->KEY_RIGHT.Released()||game->KEY_LEFT.Released()||game->KEY_DOWN.Released()|| if(game->KEY_UP.Released()||game->KEY_RIGHT.Released()||game->KEY_LEFT.Released()||game->KEY_DOWN.Released()||

@ -229,6 +229,7 @@ private:
MenuDataFunc onOpenFunc; MenuDataFunc onOpenFunc;
std::weak_ptr<MenuComponent>selection; std::weak_ptr<MenuComponent>selection;
std::weak_ptr<MenuComponent>keyboardSelection; std::weak_ptr<MenuComponent>keyboardSelection;
Data defaultButton;
InputHelper helpDisplay; InputHelper helpDisplay;

@ -55,15 +55,24 @@ public:
button.lock()->Select(); button.lock()->Select();
button.lock()->_onClick(data); button.lock()->_onClick(data);
return true; return true;
}),_onClick(onClick){} }),_onClick(onClick){
background=false;
}
protected: protected:
virtual inline void Update(AiL*game)override{ virtual inline void Update(AiL*game)override{
MenuAnimatedIconButton::Update(game); MenuAnimatedIconButton::Update(game);
if(IsSelected()){
hoverEffect="ThemeGlobal.HighlightTime"_F; //A hack that allows us to make it look like we have this selected.
}
} }
virtual inline void DrawDecal(ViewPort&window,bool focused)override{ virtual inline void DrawDecal(ViewPort&window,bool focused)override{
using A=Attribute;
Pixel backCol=PixelLerp(Menu::themes[Menu::themeSelection].GetButtonCol(),Menu::themes[Menu::themeSelection].GetHighlightCol(),hoverEffect/"ThemeGlobal.HighlightTime"_F);
if(grayedOut){
backCol=DARK_GREY;
}
window.FillRectDecal(rect.pos+V(A::DRAW_OFFSET),rect.size,backCol);
if(IsSelected()){
window.FillRectDecal(rect.pos+V(A::DRAW_OFFSET),rect.size,PixelLerp(Menu::themes[Menu::themeSelection].GetButtonCol(),Menu::themes[Menu::themeSelection].GetHighlightCol(),util::lerp(0.75f,1.0f,hoverEffect/"ThemeGlobal.HighlightTime"_F)));
}
MenuAnimatedIconButton::DrawDecal(window,focused); MenuAnimatedIconButton::DrawDecal(window,focused);
if(IsSelected()){ if(IsSelected()){
window.DrawRectDecal(rect.pos+vi2d{2,2},rect.size-vi2d{4,4},YELLOW); window.DrawRectDecal(rect.pos+vi2d{2,2},rect.size-vi2d{4,4},YELLOW);

@ -248,6 +248,7 @@ void MenuComponent::OnPlayerMoneyUpdate(uint32_t newMoney){}
void MenuComponent::OnChapterUpdate(uint8_t newChapter){} void MenuComponent::OnChapterUpdate(uint8_t newChapter){}
void MenuComponent::Click(){ void MenuComponent::Click(){
if(grayedOut||disabled)return;
bool buttonStillValid=onClick(MenuFuncData{*Menu::menus[parentMenu],game,Menu::menus[parentMenu]->components[name]}); bool buttonStillValid=onClick(MenuFuncData{*Menu::menus[parentMenu],game,Menu::menus[parentMenu]->components[name]});
if(buttonStillValid){ if(buttonStillValid){
if(menuDest!=MenuType::ENUM_END){ if(menuDest!=MenuType::ENUM_END){

@ -41,10 +41,10 @@ enum MenuType{
/////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////
/*DO NOT REMOVE!!*/ENUM_START,/////////////////////////////// /*DO NOT REMOVE!!*/ENUM_START,///////////////////////////////
/////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////
// 19% Controller Compatibility. (100 total items, 4 items per menu * 25 menus) // 27% Controller Compatibility. (100 total items, 4 items per menu * 25 menus)
INVENTORY_CONSUMABLES, //100% Controller Compatibility INVENTORY_CONSUMABLES, //100% Controller Compatibility
CLASS_INFO, //100% Controller Compatibility CLASS_INFO, //100% Controller Compatibility
CLASS_SELECTION, //0% Controller Compatibility CLASS_SELECTION, //100% Controller Compatibility
MAIN_MENU, //100% Controller Compatibility MAIN_MENU, //100% Controller Compatibility
OVERWORLD_LEVEL_SELECT, //75% Controller Compatibility - Scrolling for keyboard? OVERWORLD_LEVEL_SELECT, //75% Controller Compatibility - Scrolling for keyboard?
ITEM_LOADOUT, //0% Controller Compatibility ITEM_LOADOUT, //0% Controller Compatibility
@ -59,7 +59,7 @@ enum MenuType{
CRAFT_ITEM, //0% Controller Compatibility CRAFT_ITEM, //0% Controller Compatibility
CRAFT_CONSUMABLE, //0% Controller Compatibility CRAFT_CONSUMABLE, //0% Controller Compatibility
CONSUMABLE_CRAFT_ITEM, //0% Controller Compatibility CONSUMABLE_CRAFT_ITEM, //0% Controller Compatibility
SAVE_FILE_NAME, //0% Controller Compatibility SAVE_FILE_NAME, //100% Controller Compatibility
LOAD_GAME, //75% Controller Compatibility LOAD_GAME, //75% Controller Compatibility
USER_ID, //0% Controller Compatibility USER_ID, //0% Controller Compatibility
SETTINGS, //0% Controller Compatibility SETTINGS, //0% Controller Compatibility

@ -60,10 +60,10 @@ void Menu::InitializeSaveFileWindow(){
returnData="Continue Button"; returnData="Continue Button";
}, },
{ //Button Key { //Button Key
{game->KEY_START,{"Confirm Filename",[](MenuType type){ {game->KEY_START,{"Confirm Character Name",[](MenuType type){
Component<MenuComponent>(type,"Continue Button")->Click(); Component<MenuComponent>(type,"Continue Button")->Click();
}}}, }}},
{game->KEY_SELECT,{"Return to Title Screen",[](MenuType type){ {game->KEY_SELECT,{"Cancel",[](MenuType type){
Component<MenuComponent>(type,"Back Button")->Click(); Component<MenuComponent>(type,"Back Button")->Click();
}}}, }}},
}, },

@ -39,7 +39,7 @@ All rights reserved.
#define VERSION_MAJOR 0 #define VERSION_MAJOR 0
#define VERSION_MINOR 3 #define VERSION_MINOR 3
#define VERSION_PATCH 0 #define VERSION_PATCH 0
#define VERSION_BUILD 6961 #define VERSION_BUILD 6988
#define stringify(a) stringify_(a) #define stringify(a) stringify_(a)
#define stringify_(a) #a #define stringify_(a) #a

Loading…
Cancel
Save