Added partial keyboard functionality to character equip menu. Fix bugs with scrolling reset system. Release Build 7162.

pull/35/head
sigonasr2 12 months ago
parent c35f1509f4
commit fd9fdc0924
  1. 86
      Adventures in Lestoria/CharacterMenuWindow.cpp
  2. 41
      Adventures in Lestoria/Menu.cpp
  3. 2
      Adventures in Lestoria/Menu.h
  4. 8
      Adventures in Lestoria/OverworldMenuWindow.cpp
  5. 6
      Adventures in Lestoria/ScrollableWindowComponent.h
  6. 1
      Adventures in Lestoria/State_OverworldMap.cpp
  7. 1
      Adventures in Lestoria/State_OverworldMap.h
  8. 2
      Adventures in Lestoria/Version.h
  9. BIN
      x64/Release/Adventures in Lestoria.exe

@ -49,12 +49,14 @@ All rights reserved.
#include "RowItemDisplay.h" #include "RowItemDisplay.h"
#include "SoundEffect.h" #include "SoundEffect.h"
#include "ProgressBar.h" #include "ProgressBar.h"
#include <bit>
INCLUDE_game INCLUDE_game
INCLUDE_GFX INCLUDE_GFX
void Menu::InitializeCharacterMenuWindow(){ void Menu::InitializeCharacterMenuWindow(){
static bool equipmentWindowOpened=false; static bool equipmentWindowOpened=false;
static int lastEquipButtonOpened=0;
vf2d windowSize=game->GetScreenSize()-vf2d{52,52}; vf2d windowSize=game->GetScreenSize()-vf2d{52,52};
Menu*characterMenuWindow=CreateMenu(CHARACTER_MENU,CENTERED,windowSize); Menu*characterMenuWindow=CreateMenu(CHARACTER_MENU,CENTERED,windowSize);
@ -76,6 +78,7 @@ void Menu::InitializeCharacterMenuWindow(){
"Crit Dmg", "Crit Dmg",
}; };
const static std::array<std::string,8>slotNames{"Helmet","Weapon","Armor","Gloves","Pants","Shoes","Ring 1","Ring 2"};
characterMenuWindow->ADD("Equip Selection Outline",MenuComponent)(geom2d::rect<float>{{123,28},{120,windowSize.y-37}},"",DO_NOTHING,ButtonAttr::UNSELECTABLE)END characterMenuWindow->ADD("Equip Selection Outline",MenuComponent)(geom2d::rect<float>{{123,28},{120,windowSize.y-37}},"",DO_NOTHING,ButtonAttr::UNSELECTABLE)END
->Disable(); ->Disable();
@ -94,6 +97,7 @@ void Menu::InitializeCharacterMenuWindow(){
std::weak_ptr<StatLabel>statDisplayLabel=Component<StatLabel>(CHARACTER_MENU,"Attribute "+std::string(ItemAttribute::Get(attribute).Name())+" Label"); std::weak_ptr<StatLabel>statDisplayLabel=Component<StatLabel>(CHARACTER_MENU,"Attribute "+std::string(ItemAttribute::Get(attribute).Name())+" Label");
statDisplayLabel.lock()->SetStatChangeAmt(0); statDisplayLabel.lock()->SetStatChangeAmt(0);
} }
data.menu.SetSelection(std::string_view(std::format("Equip Slot {}",slotNames[std::bit_width(unsigned(data.menu.I(A::EQUIP_TYPE)))-1])));
equipmentWindowOpened=false; equipmentWindowOpened=false;
return true; return true;
})DEPTH 0 END; })DEPTH 0 END;
@ -119,11 +123,11 @@ void Menu::InitializeCharacterMenuWindow(){
y-=8; y-=8;
labelY-=8; labelY-=8;
} }
const static std::array<std::string,8>slotNames{"Helmet","Weapon","Armor","Gloves","Pants","Shoes","Ring 1","Ring 2"};
EquipSlot slot=EquipSlot(equipSlot); EquipSlot slot=EquipSlot(equipSlot);
auto equipmentSlot=characterMenuWindow->ADD("Equip Slot "+slotNames[i],EquipSlotButton)(geom2d::rect<float>{{x,y+28},{24,24}},slot,MenuType::ENUM_END, auto equipmentSlot=characterMenuWindow->ADD("Equip Slot "+slotNames[i],EquipSlotButton)(geom2d::rect<float>{{x,y+28},{24,24}},slot,MenuType::ENUM_END,
[&](MenuFuncData data){ [&](MenuFuncData data){
EquipSlot slot=EquipSlot(data.component.lock()->I(Attribute::EQUIP_TYPE)); EquipSlot slot=EquipSlot(data.component.lock()->I(Attribute::EQUIP_TYPE));
data.menu.I(A::EQUIP_TYPE)=int(slot);
const std::vector<std::shared_ptr<Item>>&equips=Inventory::get("Equipment"); const std::vector<std::shared_ptr<Item>>&equips=Inventory::get("Equipment");
const std::vector<std::shared_ptr<Item>>&accessories=Inventory::get("Accessories"); const std::vector<std::shared_ptr<Item>>&accessories=Inventory::get("Accessories");
@ -232,6 +236,7 @@ void Menu::InitializeCharacterMenuWindow(){
counter++; counter++;
} }
equipList->I(Attribute::INDEXED_THEME)=data.component.lock()->I(Attribute::INDEXED_THEME); equipList->I(Attribute::INDEXED_THEME)=data.component.lock()->I(Attribute::INDEXED_THEME);
Component<MenuComponent>(data.component.lock()->parentMenu,"Equip Selection Outline")->Enable(); Component<MenuComponent>(data.component.lock()->parentMenu,"Equip Selection Outline")->Enable();
equipList->Enable(); equipList->Enable();
@ -239,6 +244,26 @@ void Menu::InitializeCharacterMenuWindow(){
Component<MenuComponent>(data.component.lock()->parentMenu,"Equip Selection Select Button")->Enable(); Component<MenuComponent>(data.component.lock()->parentMenu,"Equip Selection Select Button")->Enable();
Component<CharacterRotatingDisplay>(data.component.lock()->parentMenu,"Character Rotating Display")->Disable(); Component<CharacterRotatingDisplay>(data.component.lock()->parentMenu,"Character Rotating Display")->Disable();
equipmentWindowOpened=true; equipmentWindowOpened=true;
auto equipmentList=equipList->GetComponents();
auto itemEquipped=std::find_if(equipmentList.begin(),equipmentList.end(),[&](std::weak_ptr<MenuComponent>&component){
return !ISBLANK(Inventory::GetEquip(slot))&&&*DYNAMIC_POINTER_CAST<RowItemDisplay>(component)->GetItem().lock()==&*Inventory::GetEquip(slot).lock();
});
if(itemEquipped!=equipmentList.end()){
data.menu.SetSelection(*itemEquipped,true,true);
if(Menu::UsingMouseNavigation()){
equipList->HandleOutsideDisabledButtonSelection(*itemEquipped);
}
}else
if(equipmentList.size()>0){
data.menu.SetSelection(equipmentList[0],true,true);
if(Menu::UsingMouseNavigation()){
equipList->HandleOutsideDisabledButtonSelection(equipmentList[0]);
}
}else{
data.menu.SetSelection("Equip Selection Select Button"sv);
}
return true; return true;
},[](MenuFuncData data){//On Mouse Hover },[](MenuFuncData data){//On Mouse Hover
EquipSlot slot=DYNAMIC_POINTER_CAST<EquipSlotButton>(data.component.lock())->GetSlot(); EquipSlot slot=DYNAMIC_POINTER_CAST<EquipSlotButton>(data.component.lock())->GetSlot();
@ -287,4 +312,63 @@ void Menu::InitializeCharacterMenuWindow(){
itemDescriptionDisplay->Disable(); itemDescriptionDisplay->Disable();
itemEquipNameDisplay->Disable(); itemEquipNameDisplay->Disable();
itemEquipDescriptionDisplay->Disable(); itemEquipDescriptionDisplay->Disable();
characterMenuWindow->SetupKeyboardNavigation(
[](MenuType type,Data&returnData){ //On Open
returnData=std::format("Equip Slot {}",slotNames[0]);
},
{ //Button Key
{game->KEY_BACK,{"Back",[](MenuType type){
Component<MenuComponent>(type,"Back button")->Click();
}}},
{game->KEY_CONFIRM,{"Select",[](MenuType type){}}},
}
,{ //Button Navigation Rules
{"Equip List",{}},
{std::format("Equip Slot {}", slotNames[0]),{
.up="Back button",
.down=std::format("Equip Slot {}", slotNames[2]),
.left=std::format("Equip Slot {}", slotNames[1]),
.right=std::format("Equip Slot {}", slotNames[1]),}},
{std::format("Equip Slot {}", slotNames[1]),{
.up="Back button",
.down=std::format("Equip Slot {}", slotNames[3]),
.left=std::format("Equip Slot {}", slotNames[0]),
.right=std::format("Equip Slot {}", slotNames[0]),}},
{std::format("Equip Slot {}", slotNames[2]),{
.up=std::format("Equip Slot {}", slotNames[0]),
.down=std::format("Equip Slot {}", slotNames[4]),
.left=std::format("Equip Slot {}", slotNames[3]),
.right=std::format("Equip Slot {}", slotNames[3]),}},
{std::format("Equip Slot {}", slotNames[3]),{
.up=std::format("Equip Slot {}", slotNames[1]),
.down=std::format("Equip Slot {}", slotNames[5]),
.left=std::format("Equip Slot {}", slotNames[2]),
.right=std::format("Equip Slot {}", slotNames[2]),}},
{std::format("Equip Slot {}", slotNames[4]),{
.up=std::format("Equip Slot {}", slotNames[2]),
.down=std::format("Equip Slot {}", slotNames[6]),
.left=std::format("Equip Slot {}", slotNames[5]),
.right=std::format("Equip Slot {}", slotNames[5]),}},
{std::format("Equip Slot {}", slotNames[5]),{
.up=std::format("Equip Slot {}", slotNames[3]),
.down=std::format("Equip Slot {}", slotNames[7]),
.left=std::format("Equip Slot {}", slotNames[4]),
.right=std::format("Equip Slot {}", slotNames[4]),}},
{std::format("Equip Slot {}", slotNames[6]),{
.up=std::format("Equip Slot {}", slotNames[4]),
.down="Back button",
.left=std::format("Equip Slot {}", slotNames[7]),
.right=std::format("Equip Slot {}", slotNames[7]),}},
{std::format("Equip Slot {}", slotNames[7]),{
.up=std::format("Equip Slot {}", slotNames[5]),
.down="Back button",
.left=std::format("Equip Slot {}", slotNames[6]),
.right=std::format("Equip Slot {}", slotNames[6]),}},
{"Back button",{
.up=std::format("Equip Slot {}", slotNames[7]),
.down=std::format("Equip Slot {}", slotNames[0]),
.left=std::format("Equip Slot {}", slotNames[7]),
.right=std::format("Equip Slot {}", slotNames[6]),}},
});
} }

@ -304,6 +304,13 @@ void Menu::OpenMenu(MenuType menu,bool cover){
void Menu::KeyboardButtonNavigation(AiL*game,vf2d menuPos){ void Menu::KeyboardButtonNavigation(AiL*game,vf2d menuPos){
std::weak_ptr<MenuComponent>prevSelection=selection; std::weak_ptr<MenuComponent>prevSelection=selection;
if(game->KEY_UP.Released()||game->KEY_RIGHT.Released()||game->KEY_LEFT.Released()||game->KEY_DOWN.Released()||
game->KEY_BACK.Released()||game->KEY_CONFIRM.Released()||game->KEY_START.Released()||game->KEY_SELECT.Released()||
game->KEY_SCROLLDOWN.Released()||game->KEY_SCROLLUP.Released()||game->KEY_SCROLLVERT.Analog()!=0.f||game->KEY_MENU.Released()){
SetMouseNavigation(game->GetMouse(Mouse::LEFT).bReleased||game->GetMouse(Mouse::RIGHT).bReleased||game->GetMouse(Mouse::MIDDLE).bReleased); //If a click occurs we use mouse controls.
buttonHoldTime=0;
}
if(!Menu::UsingMouseNavigation()){ if(!Menu::UsingMouseNavigation()){
for(auto&[input,data]:inputGroups){ for(auto&[input,data]:inputGroups){
bool activated=false; bool activated=false;
@ -399,12 +406,6 @@ void Menu::KeyboardButtonNavigation(AiL*game,vf2d menuPos){
}while(iterationCount<MAX_ITERATIONS&&(selection.lock()->grayedOut||selection.lock()->disable)); }while(iterationCount<MAX_ITERATIONS&&(selection.lock()->grayedOut||selection.lock()->disable));
} }
if(game->KEY_UP.Released()||game->KEY_RIGHT.Released()||game->KEY_LEFT.Released()||game->KEY_DOWN.Released()||
game->KEY_BACK.Released()||game->KEY_CONFIRM.Released()||game->KEY_START.Released()||game->KEY_SELECT.Released()||
game->KEY_SCROLLDOWN.Released()||game->KEY_SCROLLUP.Released()||game->KEY_SCROLLVERT.Analog()!=0.f){
SetMouseNavigation(game->GetMouse(Mouse::LEFT).bReleased||game->GetMouse(Mouse::RIGHT).bReleased||game->GetMouse(Mouse::MIDDLE).bReleased); //If a click occurs we use mouse controls.
buttonHoldTime=0;
}
if(&*prevSelection.lock()!=&*selection.lock()){ if(&*prevSelection.lock()!=&*selection.lock()){
if(!selection.expired()&&selection.lock()->disableOutsideWindow){ if(!selection.expired()&&selection.lock()->disableOutsideWindow){
bool handled=false; bool handled=false;
@ -681,17 +682,18 @@ void Menu::SetSelection(std::weak_ptr<MenuComponent>button,const bool scroll,con
keyboardSelection=button; keyboardSelection=button;
} }
if(scroll&&!UsingMouseNavigation()&&!button.lock()->parentComponent.expired()){
auto scrollWindow=button.lock()->parentComponent.lock();
scrollWindow->HandleOutsideDisabledButtonSelection(Menu::menus[button.lock()->parentMenu]->components[button.lock()->GetName()]);
scrollWindow->selectionIndex=scrollWindow->GetComponentIndex(selection);
}
if(!selection.lock()->parentComponent.expired()&&reset){ if(!selection.lock()->parentComponent.expired()&&reset){
auto scrollWindow=selection.lock()->parentComponent.lock(); auto scrollWindow=selection.lock()->parentComponent.lock();
scrollWindow->targetScrollOffset.y=0.f; scrollWindow->targetScrollOffset.y=0.f;
scrollWindow->scrollOffset.y=0.f;
scrollWindow->selectionIndex=0.f; scrollWindow->selectionIndex=0.f;
} }
if(scroll&&!UsingMouseNavigation()&&!button.lock()->parentComponent.expired()){
auto scrollWindow=button.lock()->parentComponent.lock();
scrollWindow->HandleOutsideDisabledButtonSelection(Menu::menus[button.lock()->parentMenu]->components[button.lock()->GetName()]);
scrollWindow->selectionIndex=scrollWindow->GetComponentIndex(selection);
}
} }
void Menu::SetSelection(std::string_view button,const bool scroll,const bool reset){ void Menu::SetSelection(std::string_view button,const bool scroll,const bool reset){
@ -701,20 +703,21 @@ void Menu::SetSelection(std::string_view button,const bool scroll,const bool res
keyboardSelection=selection; keyboardSelection=selection;
} }
if(scroll&&!UsingMouseNavigation()&&!selection.lock()->parentComponent.expired()){
auto scrollWindow=selection.lock()->parentComponent.lock();
scrollWindow->HandleOutsideDisabledButtonSelection(Menu::menus[selection.lock()->parentMenu]->components[selection.lock()->GetName()]);
scrollWindow->selectionIndex=scrollWindow->GetComponentIndex(selection);
}
if(!selection.lock()->parentComponent.expired()&&reset){ if(!selection.lock()->parentComponent.expired()&&reset){
auto scrollWindow=selection.lock()->parentComponent.lock(); auto scrollWindow=selection.lock()->parentComponent.lock();
scrollWindow->targetScrollOffset.y=0.f; scrollWindow->targetScrollOffset.y=0.f;
scrollWindow->scrollOffset.y=0.f;
scrollWindow->selectionIndex=0.f; scrollWindow->selectionIndex=0.f;
} }
if(scroll&&!UsingMouseNavigation()&&!selection.lock()->parentComponent.expired()){
auto scrollWindow=selection.lock()->parentComponent.lock();
scrollWindow->HandleOutsideDisabledButtonSelection(Menu::menus[selection.lock()->parentMenu]->components[selection.lock()->GetName()]);
scrollWindow->selectionIndex=scrollWindow->GetComponentIndex(selection);
}
} }
void Menu::SetSelection(std::variant<std::string,std::weak_ptr<MenuComponent>>button,const bool reset){ void Menu::SetSelection(Data button,const bool reset){
if(std::holds_alternative<std::string>(button)){ if(std::holds_alternative<std::string>(button)){
SetSelection(std::string_view(std::get<std::string>(button)),true,reset); SetSelection(std::string_view(std::get<std::string>(button)),true,reset);
}else }else

@ -193,7 +193,7 @@ public:
void RecalculateComponentCount(); void RecalculateComponentCount();
void SetSelection(std::string_view button,const bool scroll=true,const bool reset=false); // Use the reset parameter when a window is opening up, as this will cause the window now to scroll to its previous target. void SetSelection(std::string_view button,const bool scroll=true,const bool reset=false); // Use the reset parameter when a window is opening up, as this will cause the window now to scroll to its previous target.
void SetSelection(std::weak_ptr<MenuComponent>button,const bool scroll=true,const bool reset=false); // Use the reset parameter when a window is opening up, as this will cause the window now to scroll to its previous target. void SetSelection(std::weak_ptr<MenuComponent>button,const bool scroll=true,const bool reset=false); // Use the reset parameter when a window is opening up, as this will cause the window now to scroll to its previous target.
void SetSelection(std::variant<std::string,std::weak_ptr<MenuComponent>>button,const bool reset=false); // Use the reset parameter when a window is opening up, as this will cause the window now to scroll to its previous target. void SetSelection(Data button,const bool reset=false); // Use the reset parameter when a window is opening up, as this will cause the window now to scroll to its previous target.
const std::weak_ptr<MenuComponent>GetSelection()const; const std::weak_ptr<MenuComponent>GetSelection()const;
const std::weak_ptr<MenuComponent>GetKeySelection()const; const std::weak_ptr<MenuComponent>GetKeySelection()const;
private: private:

@ -70,10 +70,14 @@ void Menu::InitializeOverworldMenuWindow(){
}, },
{ //Button Key { //Button Key
{game->KEY_BACK,{"Close Menu",[](MenuType type){ {game->KEY_BACK,{"Close Menu",[](MenuType type){
Menu::CloseMenu(); if(Menu::stack.back()->GetType()==OVERWORLD_MENU){ //HACK ALERT! This is in case we hit the menu key from the resume button as it too closes the menu, so this is a double close attempt.
Menu::CloseMenu();
}
}}}, }}},
{game->KEY_MENU,{"Close Menu",[](MenuType type){ {game->KEY_MENU,{"Close Menu",[](MenuType type){
Menu::CloseMenu(); if(Menu::stack.back()->GetType()==OVERWORLD_MENU){ //HACK ALERT! This is in case we hit the menu key from the resume button as it too closes the menu, so this is a double close attempt.
Menu::CloseMenu();
}
}}}, }}},
{game->KEY_CONFIRM,{"Select",[](MenuType type){}}}, {game->KEY_CONFIRM,{"Select",[](MenuType type){}}},
} }

@ -105,6 +105,12 @@ public:
geom2d::overlaps(geom2d::rect<float>{Menu::menus[parentMenu]->pos+rect.pos+child->rect.pos,child->rect.size},game->GetMousePos()); geom2d::overlaps(geom2d::rect<float>{Menu::menus[parentMenu]->pos+rect.pos+child->rect.pos,child->rect.size},game->GetMousePos());
} }
inline void SetSelectionIndex(const float val){
float prevIndex=selectionIndex;
selectionIndex=std::clamp(selectionIndex+val,0.f,float(components.size()-1));
if(size_t(prevIndex)!=size_t(selectionIndex)){Menu::menus[parentMenu]->SetSelection(components[size_t(selectionIndex)],false);}
}
inline void IncreaseSelectionIndex(const float val){ inline void IncreaseSelectionIndex(const float val){
float prevIndex=selectionIndex; float prevIndex=selectionIndex;
selectionIndex=std::clamp(selectionIndex+val,0.f,float(components.size()-1)); selectionIndex=std::clamp(selectionIndex+val,0.f,float(components.size()-1));

@ -205,6 +205,7 @@ void State_OverworldMap::Draw(AiL*game){
game->view.DrawRotatedDecal(game->GetPlayer()->GetPos()+vf2d{arrowDist,GetAngle(medianAngle)}.cart(),GFX["overworld_arrow.png"].Decal(),GetAngle(medianAngle),GFX["overworld_arrow.png"].Sprite()->Size()/2,{1.f,1.f},{199,48,55}); game->view.DrawRotatedDecal(game->GetPlayer()->GetPos()+vf2d{arrowDist,GetAngle(medianAngle)}.cart(),GFX["overworld_arrow.png"].Decal(),GetAngle(medianAngle),GFX["overworld_arrow.png"].Sprite()->Size()/2,{1.f,1.f},{199,48,55});
} }
}; };
void State_OverworldMap::DrawOverlay(AiL*game){}
void State_OverworldMap::SetStageMarker(std::string connectionName){ void State_OverworldMap::SetStageMarker(std::string connectionName){
for(ConnectionPoint&connection:connections){ for(ConnectionPoint&connection:connections){
if(connection.name==connectionName){ if(connection.name==connectionName){

@ -58,6 +58,7 @@ public:
virtual void OnStateChange(GameState*prevState)override final; virtual void OnStateChange(GameState*prevState)override final;
virtual void OnUserUpdate(AiL*game)override final; virtual void OnUserUpdate(AiL*game)override final;
virtual void Draw(AiL*game)override final; virtual void Draw(AiL*game)override final;
virtual void DrawOverlay(AiL*game)override final;
static void StartLevel(); static void StartLevel();
static void UpdateCurrentConnectionPoint(const ConnectionPoint&connection); static void UpdateCurrentConnectionPoint(const ConnectionPoint&connection);
}; };

@ -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 7118 #define VERSION_BUILD 7162
#define stringify(a) stringify_(a) #define stringify(a) stringify_(a)
#define stringify_(a) #a #define stringify_(a) #a

Loading…
Cancel
Save