Auto targeting a component when navigating/selecting in a ScrollableWindowComponent using gamepad/keyboard controls. Added analog stick navigation to load file menu.

pull/35/head
sigonasr2 1 year ago
parent df08aa9936
commit df10dc43a8
  1. 1
      Adventures in Lestoria/Adventures in Lestoria.vcxproj
  2. 3
      Adventures in Lestoria/Adventures in Lestoria.vcxproj.filters
  3. 22
      Adventures in Lestoria/Key.cpp
  4. 1
      Adventures in Lestoria/Key.h
  5. 9
      Adventures in Lestoria/LoadGameWindow.cpp
  6. 12
      Adventures in Lestoria/Menu.cpp
  7. 2
      Adventures in Lestoria/MenuComponent.h
  8. 28
      Adventures in Lestoria/ScrollableWindowComponent.h
  9. 7
      Adventures in Lestoria/TODO.txt
  10. 6
      Adventures in Lestoria/Version.h
  11. 2
      Adventures in Lestoria/assets/config/Interface.txt

@ -695,6 +695,7 @@
<Text Include="assets\config\gfx\backdrops.txt" />
<Text Include="assets\config\gfx\gfx.txt" />
<Text Include="assets\config\gfx\themes.txt" />
<Text Include="assets\config\Interface.txt" />
<Text Include="assets\config\items\Accessories.txt" />
<Text Include="assets\config\items\Equipment.txt" />
<Text Include="assets\config\items\ItemCategory.txt" />

@ -864,6 +864,9 @@
<Text Include="Chapter_1_2nd_Boss.txt">
<Filter>Documentation\Mechanics</Filter>
</Text>
<Text Include="assets\config\Interface.txt">
<Filter>Configurations</Filter>
</Text>
</ItemGroup>
<ItemGroup>
<Image Include="assets\heart.ico">

@ -62,6 +62,9 @@ bool Input::Pressed(){
if(gamepad->stillConnected&&gamepad->getButton(static_cast<GPButtons>(key)).bPressed)inputPressed=true;
}
}break;
case ANALOG:{
//An analog input can never be "pressed". No-op.
}break;
default:{
ERR("Invalid Control Scheme detected! We shouldn't be here!! Type is "<<type);
}
@ -88,6 +91,9 @@ bool Input::Held(){
if(gamepad->stillConnected&&gamepad->getButton(static_cast<GPButtons>(key)).bHeld)inputHeld=true;
}
}break;
case ANALOG:{
//An analog input can never be "held". No-op.
}break;
default:{
ERR("Invalid Control Scheme detected! We shouldn't be here!! Type is "<<type);
}
@ -114,6 +120,9 @@ bool Input::Released(){
if(gamepad->stillConnected&&gamepad->getButton(static_cast<GPButtons>(key)).bReleased)inputReleased=true;
}
}break;
case ANALOG:{
//An analog input can never be "released". No-op.
}break;
default:{
ERR("Invalid Control Scheme detected! We shouldn't be here!! Type is "<<type);
}
@ -139,6 +148,11 @@ float Input::Analog(){
}
}
}break;
case KEY:
case MOUSE:
case CONTROLLER:{
//Doesn't return analog inputs. No-op.
}break;
default:{
ERR("Invalid Control Scheme detected for analog controls! We shouldn't be here!! Type is "<<type);
}
@ -181,6 +195,14 @@ const bool InputGroup::Released()const{
return false;
}
const float InputGroup::Analog()const{
for(Input input:keys){
float analogVal=input.Analog();
if(analogVal!=0.f)return analogVal;
}
return 0.f;
}
std::string InputGroup::GetDisplayName(){
std::string combinationDisplay="";
for(Input input:keys){

@ -80,6 +80,7 @@ public:
const bool Pressed()const;
const bool Held()const;
const bool Released()const;
const float Analog()const;
std::string GetDisplayName();
};

@ -60,8 +60,13 @@ void Menu::InitializeLoadGameWindow(){
Component<MenuComponent>(type,"Go Back Button")->Click();
}}},
{game->KEY_SCROLL,{"Scroll Up/Down",[](MenuType type){
auto&scrollWindow=Component<ScrollableWindowComponent>(type,"Game Files List");
scrollWindow->SetScrollAmount(scrollWindow->GetScrollAmount()+game->KEY_SCROLL.Analog()*game->GetElapsedTime()*"Interface.AnalogScrollSpeed"_F);
auto scrollWindow=Component<ScrollableWindowComponent>(type,"Game Files List");
scrollWindow->SetScrollAmount(scrollWindow->GetScrollAmount()-vf2d{0,game->KEY_SCROLL.Analog()*game->GetElapsedTime()*"Interface.AnalogScrollSpeed"_F});
for(auto component:scrollWindow->GetComponents()){
if(geom2d::overlaps(scrollWindow->GetPos()+scrollWindow->GetSize()/2,geom2d::rect<float>{component.lock()->GetPos(),component.lock()->GetSize()})){
Menu::menus[type]->SetSelection(component);
}
}
}}},
}
,{ //Button Navigation Rules

@ -297,7 +297,7 @@ void Menu::KeyboardButtonNavigation(AiL*game,vf2d menuPos){
std::weak_ptr<MenuComponent>prevSelection=selection;
for(auto&[input,data]:inputGroups){
if(input.Released()){
if(input.Released()||input.Analog()!=0.f){
SetMouseNavigation(false);
auto&action=data.second;
if(std::holds_alternative<ButtonName>(action))Component<MenuComponent>(type,std::get<ButtonName>(action))->Click();
@ -641,6 +641,11 @@ void Menu::SetSelection(std::weak_ptr<MenuComponent>button){
!button.lock()->parentComponent.expired()&&navigationGroups.count(button.lock()->parentComponent.lock()->GetName())){
keyboardSelection=button;
}
if(!UsingMouseNavigation()&&!button.lock()->parentComponent.expired()){
auto scrollWindow=button.lock()->parentComponent.lock();
scrollWindow->HandleOutsideDisabledButtonSelection(Menu::menus[button.lock()->parentMenu]->components[button.lock()->GetName()]);
}
}
void Menu::SetSelection(std::string_view button){
@ -649,6 +654,11 @@ void Menu::SetSelection(std::string_view button){
!selection.lock()->parentComponent.expired()&&navigationGroups.count(selection.lock()->parentComponent.lock()->GetName())){
keyboardSelection=selection;
}
if(!UsingMouseNavigation()&&!selection.lock()->parentComponent.expired()){
auto scrollWindow=selection.lock()->parentComponent.lock();
scrollWindow->HandleOutsideDisabledButtonSelection(Menu::menus[selection.lock()->parentMenu]->components[selection.lock()->GetName()]);
}
}
void Menu::SetSelection(std::variant<std::string,std::weak_ptr<MenuComponent>>button){

@ -127,7 +127,7 @@ protected:
virtual void OnHover();
public:
MenuType parentMenu=MenuType::ENUM_END;
std::weak_ptr<MenuComponent>parentComponent{};
std::weak_ptr<ScrollableWindowComponent>parentComponent{};
MenuComponent(geom2d::rect<float>rect,std::string label,MenuFunc onClick,ButtonAttr attributes=ButtonAttr::NONE);
MenuComponent(geom2d::rect<float>rect,std::string label,MenuType menuDest,MenuFunc onClick,ButtonAttr attributes=ButtonAttr::NONE);
MenuComponent(geom2d::rect<float>rect,std::string label,MenuType menuDest,MenuFunc onClick,vf2d labelScaling,ButtonAttr attributes=ButtonAttr::NONE);

@ -54,7 +54,8 @@ protected:
float scrollBarTop=0;
bool scrollBarSelected=false;
float scrollBarHoverTime=0;
vf2d scrollOffset;
vf2d scrollOffset{};
vf2d targetScrollOffset{};
protected:
inline bool OnScreen(std::weak_ptr<MenuComponent>component){
return geom2d::overlaps(geom2d::rect<float>{{},rect.size},geom2d::rect<float>{component.lock()->rect.pos+vf2d{2,2},component.lock()->rect.size-vf2d{2,2}});
@ -86,13 +87,14 @@ public:
CalculateBounds();
}
virtual inline void SetScrollAmount(vf2d scrollOffset){
this->scrollOffset=scrollOffset;
for(std::weak_ptr<MenuComponent>component:components){
component.lock()->rect.pos=component.lock()->originalPos+scrollOffset;
}
this->targetScrollOffset=scrollOffset;
}
virtual inline vf2d GetScrollAmount(){
return scrollOffset;
return targetScrollOffset;
}
virtual bool GetHoverState(AiL*game,MenuComponent*child)override{
return geom2d::overlaps(geom2d::rect<float>{Menu::menus[parentMenu]->pos+rect.pos,rect.size},game->GetMousePos())&& //Make sure the mouse is inside the parent window component first....
geom2d::overlaps(geom2d::rect<float>{Menu::menus[parentMenu]->pos+rect.pos+child->rect.pos,child->rect.size},game->GetMousePos());
}
protected:
virtual inline void AfterCreate()override{
@ -141,6 +143,10 @@ protected:
scrollBarHoverTime=std::max(scrollBarHoverTime-game->GetElapsedTime(),0.f);
}
for(std::weak_ptr<MenuComponent>component:components){
component.lock()->rect.pos=component.lock()->originalPos+targetScrollOffset;
}
if(game->GetMouseWheel()!=0){
if(game->GetMouseWheel()>0){
SetScrollAmount(GetScrollAmount()+vf2d{0,"ThemeGlobal.MenuScrollWheelSpeed"_F});
@ -150,8 +156,10 @@ protected:
}
if(bounds.size.y-rect.size.y>0){
scrollOffset.y=std::clamp(GetScrollAmount().y,-(bounds.size.y-rect.size.y),0.f);
SetScrollAmount({GetScrollAmount().x,std::clamp(GetScrollAmount().y,-(bounds.size.y-rect.size.y),0.f)});
}else{
scrollOffset.y=0;
SetScrollAmount({GetScrollAmount().x,0});
}
@ -195,10 +203,6 @@ protected:
DrawScrollbar(window,{},focused);
}
}
virtual bool GetHoverState(AiL*game,MenuComponent*child)override{
return geom2d::overlaps(geom2d::rect<float>{Menu::menus[parentMenu]->pos+rect.pos,rect.size},game->GetMousePos())&& //Make sure the mouse is inside the parent window component first....
geom2d::overlaps(geom2d::rect<float>{Menu::menus[parentMenu]->pos+rect.pos+child->rect.pos,child->rect.size},game->GetMousePos());
}
//Calculates the bounds of all components.
inline void CalculateBounds(){
bounds={};
@ -228,7 +232,7 @@ public:
std::shared_ptr<T> _AddComponent(std::string key,std::shared_ptr<T>button){
components.push_back(button);
button->renderInMain=false; //Now we are in control!
button->parentComponent=Menu::menus[parentMenu]->components[this->GetName()];
button->parentComponent=DYNAMIC_POINTER_CAST<ScrollableWindowComponent>(Menu::menus[parentMenu]->components[this->GetName()]);
button->disabled=disabled;
CalculateBounds();
@ -244,7 +248,7 @@ public:
}
virtual inline bool HandleOutsideDisabledButtonSelection(std::weak_ptr<MenuComponent>disabledButton)override{
//Set the offset so the center is highlighted by this button.
SetScrollAmount(vf2d{GetScrollAmount().x,-disabledButton.lock()->rect.pos.y+disabledButton.lock()->rect.size.y});
SetScrollAmount(vf2d{GetScrollAmount().x,GetScrollAmount().y-disabledButton.lock()->rect.pos.y+disabledButton.lock()->rect.size.y});
return true;
};
virtual void Cleanup()override{}

@ -1,6 +1,5 @@
January 1st
===========
Fix Listeners so they do not leak! (Add a proper listener class and have all listeners inherit from it.)
The Hub / NPC Interactions
Settings Menu
- Any settings should be saved to the save file!
@ -12,7 +11,6 @@ Settings Menu
-We have to save keybinds to the save file.
- Fix Stage Completed screen, item displays can hit the scrollbar.
- Monster spawn list is not populated in Emscripten?
January 31st
============
@ -26,15 +24,16 @@ Story proofreading/correcting/storyboarding
- Export/Import Save Files Online/Offline
- Consider controls for fine-tuning music and how they sound during events.
- Lock up unimplemented classes.
- Don't enable all stage plates normally.
A "Debug" version of the game that simply outputs all std::cout to a file as well (debug.log).
ERR messages become just output messages in release build and won't crash the game.
- Hide mouse cursor during controller play. Reveal it again during mouse play.
- Resource Packs
- Getting hurt has additional effects.
mainMenuWindow->SetupKeyboardNavigation(

@ -37,9 +37,9 @@ All rights reserved.
#pragma endregion
#pragma once
#define VERSION_MAJOR 0
#define VERSION_MINOR 2
#define VERSION_PATCH 1
#define VERSION_BUILD 6037
#define VERSION_MINOR 3
#define VERSION_PATCH 0
#define VERSION_BUILD 6071
#define stringify(a) stringify_(a)
#define stringify_(a) #a

@ -1,7 +1,7 @@
Interface
{
# In pixels/sec
AnalogScrollSpeed = 120
AnalogScrollSpeed = 220
# The size of each side of the 9-patch menu sprite.
9PatchSize = 24,24

Loading…
Cancel
Save