Auto targeting a component when navigating/selecting in a ScrollableWindowComponent using gamepad/keyboard controls. Added analog stick navigation to load file menu.
This commit is contained in:
parent
df08aa9936
commit
df10dc43a8
@ -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…
x
Reference in New Issue
Block a user