Handle mouse buttons for rebinding controls. Release Build 6956.

This commit is contained in:
sigonasr2 2024-02-10 03:06:30 -06:00
parent 35cc847671
commit 0a9136e6c4
15 changed files with 118 additions and 40 deletions

View File

@ -2533,25 +2533,29 @@ void AiL::InitializeDefaultKeybinds(){
KEY_UNEQUIP.AddKeybind({KEY,R});
KEY_UNEQUIP.AddKeybind({CONTROLLER,static_cast<int>(GPButtons::FACE_U)});
#define TieMenuNameToGroup(KEY_NAME) \
InputGroup::menuNamesToInputGroups[DATA["Inputs"][#KEY_NAME].GetString()]=&KEY_NAME;
#define TieMenuNameToMenuInputGroup(KEY_NAME) \
InputGroup::menuNamesToInputGroups[DATA["Inputs"][#KEY_NAME].GetString()]=&KEY_NAME; \
InputGroup::menuInputGroups.push_back(DATA["Inputs"][#KEY_NAME].GetString());
#define TieMenuNameToGameplayInputGroup(KEY_NAME) \
InputGroup::menuNamesToInputGroups[DATA["Inputs"][#KEY_NAME].GetString()]=&KEY_NAME; \
InputGroup::gameplayInputGroups.push_back(DATA["Inputs"][#KEY_NAME].GetString());
TieMenuNameToGroup(KEY_CONFIRM)
TieMenuNameToGroup(KEY_ATTACK);
TieMenuNameToGroup(KEY_LEFT);
TieMenuNameToGroup(KEY_RIGHT);
TieMenuNameToGroup(KEY_UP);
TieMenuNameToGroup(KEY_DOWN);
TieMenuNameToGroup(KEY_MENU);
TieMenuNameToGroup(KEY_BACK);
TieMenuNameToGroup(Player::KEY_ABILITY1);
TieMenuNameToGroup(Player::KEY_ABILITY2);
TieMenuNameToGroup(Player::KEY_ABILITY3);
TieMenuNameToGroup(Player::KEY_ABILITY4);
TieMenuNameToGroup(Player::KEY_DEFENSIVE);
TieMenuNameToGroup(Player::KEY_ITEM1);
TieMenuNameToGroup(Player::KEY_ITEM2);
TieMenuNameToGroup(Player::KEY_ITEM3);
TieMenuNameToMenuInputGroup(KEY_CONFIRM)
TieMenuNameToMenuInputGroup(KEY_LEFT);
TieMenuNameToMenuInputGroup(KEY_RIGHT);
TieMenuNameToMenuInputGroup(KEY_UP);
TieMenuNameToMenuInputGroup(KEY_DOWN);
TieMenuNameToMenuInputGroup(KEY_MENU);
TieMenuNameToMenuInputGroup(KEY_BACK);
TieMenuNameToGameplayInputGroup(KEY_ATTACK);
TieMenuNameToGameplayInputGroup(Player::KEY_ABILITY1);
TieMenuNameToGameplayInputGroup(Player::KEY_ABILITY2);
TieMenuNameToGameplayInputGroup(Player::KEY_ABILITY3);
TieMenuNameToGameplayInputGroup(Player::KEY_ABILITY4);
TieMenuNameToGameplayInputGroup(Player::KEY_DEFENSIVE);
TieMenuNameToGameplayInputGroup(Player::KEY_ITEM1);
TieMenuNameToGameplayInputGroup(Player::KEY_ITEM2);
TieMenuNameToGameplayInputGroup(Player::KEY_ITEM3);
InputGroup::menuNamesToInputGroups.SetInitialized();
}
@ -3133,10 +3137,6 @@ void AiL::GetAnyKeyRelease(Key key){
#pragma region New keyboard input binding listener
using A=Attribute;
if(Menu::IsMenuOpen()&&Menu::stack.back()==Menu::menus[NEW_INPUT]&&Menu::menus[NEW_INPUT]->B(A::IS_KEYBOARD)){ //We are requesting a brand new input.
if(key==ESCAPE){ //If we hit escape we don't bother with setting the input and leave immediately.
Menu::CloseMenu();
return;
}
using A=Attribute;
if(InputGroup::menuNamesToInputGroups.count(Menu::menus[NEW_INPUT]->S(A::KEYBIND))){
InputGroup::menuNamesToInputGroups[Menu::menus[NEW_INPUT]->S(A::KEYBIND)]->SetNewPrimaryKeybind(Input{KEY,key});
@ -3155,3 +3155,44 @@ void AiL::GetAnyKeyPress(Key key){
GameState::STATE->GetAnyKeyPress(key);
}
}
void AiL::GetAnyMouseRelease(int32_t mouseButton){
#pragma region New mouse input binding listener
using A=Attribute;
if(Menu::IsMenuOpen()&&Menu::stack.back()==Menu::menus[NEW_INPUT]&&Menu::menus[NEW_INPUT]->B(A::IS_KEYBOARD)){ //We are requesting a brand new input.
using A=Attribute;
const std::vector<std::string>*inputGroup=&InputGroup::menuInputGroups; //First we detect which input group this mouse binding is for. Each group can individually have one key bound to each mouse button, that's why we first detect which group we actually care about.
for(const std::string&groupName:InputGroup::gameplayInputGroups){
if(groupName==Menu::menus[NEW_INPUT]->S(A::KEYBIND)){
inputGroup=&InputGroup::gameplayInputGroups;
}
}
//Next we need to iterate through that group and check for any already-bound buttons for the mouse button we are about to apply. Get rid of the keybinds from there.
for(const std::string&menuItem:*inputGroup){
InputGroup&group=*InputGroup::menuNamesToInputGroups[menuItem];
std::vector<Input>keybindsToRemove;
for(Input&input:group.keyOrder){
if(input.GetType()==MOUSE&&input.GetKeyCode()==mouseButton){
keybindsToRemove.push_back(input);
}
}
for(Input&input:keybindsToRemove){
group.RemoveKeybind(input);
}
}
if(InputGroup::menuNamesToInputGroups.count(Menu::menus[NEW_INPUT]->S(A::KEYBIND))){
InputGroup::menuNamesToInputGroups[Menu::menus[NEW_INPUT]->S(A::KEYBIND)]->AddKeybind(Input{MOUSE,mouseButton});
Menu::alreadyClicked=true;
Menu::CloseMenu();
}
}
#pragma endregion
GameState::STATE->GetAnyMouseRelease(mouseButton);
}
void AiL::GetAnyMousePress(int32_t mouseButton){
GameState::STATE->GetAnyMousePress(mouseButton);
}

View File

@ -163,6 +163,8 @@ public:
bool OnUserDestroy() override;
void GetAnyKeyPress(Key key)override final;
void GetAnyKeyRelease(Key key)override final;
void GetAnyMousePress(int32_t mouseButton)override final;
void GetAnyMouseRelease(int32_t mouseButton)override final;
public:
geom2d::rect<float>NO_COLLISION={{0.f,0.f,},{0.f,0.f}};
TileTransformedView view;

View File

@ -81,3 +81,5 @@ GameState::~GameState(){}
void GameState::GetAnyKeyPress(Key k){}
void GameState::GetAnyKeyRelease(Key k){}
void GameState::GetAnyMousePress(int32_t mouseButton){}
void GameState::GetAnyMouseRelease(int32_t mouseButton){}

View File

@ -69,5 +69,7 @@ public:
virtual void Draw(AiL*game)=0;
virtual void GetAnyKeyPress(Key k);
virtual void GetAnyKeyRelease(Key k);
virtual void GetAnyMousePress(int32_t mouseButton);
virtual void GetAnyMouseRelease(int32_t mouseButton);
static void ChangeState(States::State newState,float fadeOutDuration=0);
};

View File

@ -82,7 +82,7 @@ void Menu::InitializeKeyboardInputWindow(){
cancelButtonDisplayName=GenericKey::keyLiteral[{CONTROLLER,static_cast<int>(GPButtons::SELECT)}].displayName;
keyTypeName="button";
}
Component<MenuLabel>(NEW_INPUT,"New Keybind Label")->SetLabel(std::format("Press a new {} for '{}'\n\nPress {} to cancel.",keyTypeName,keybindName,cancelButtonDisplayName));
Component<MenuLabel>(NEW_INPUT,"New Keybind Label")->SetLabel(std::format("Press a new {} for '{}'",keyTypeName,keybindName));
Menu::OpenMenu(NEW_INPUT);
return true;
})END;
@ -113,7 +113,7 @@ void Menu::InitializeKeyboardInputWindow(){
cancelButtonDisplayName=GenericKey::keyLiteral[{CONTROLLER,static_cast<int>(GPButtons::SELECT)}].displayName;
keyTypeName="button";
}
Component<MenuLabel>(NEW_INPUT,"New Keybind Label")->SetLabel(std::format("Press a new {} for '{}'\n\nPress {} to cancel.",keyTypeName,keybindName,cancelButtonDisplayName));
Component<MenuLabel>(NEW_INPUT,"New Keybind Label")->SetLabel(std::format("Press a new {} for '{}'",keyTypeName,keybindName));
Menu::OpenMenu(NEW_INPUT);
return true;
})END;

View File

@ -46,6 +46,8 @@ INCLUDE_GFX
bool Input::usingGamepad;
safemap<std::string,InputGroup*>InputGroup::menuNamesToInputGroups;
std::vector<std::string>InputGroup::menuInputGroups;
std::vector<std::string>InputGroup::gameplayInputGroups;
Input::Input(InputType type,int key)
:type(type),key(key){}
@ -309,15 +311,36 @@ void InputGroup::DrawInput(const std::variant<AiL*const,TileTransformedView*cons
vf2d buttonImgSize{};
std::vector<std::variant<Decal*,std::string>>buttonImgs;
if(type!=CONTROLLER){
for(const Input&input:keyOrder){
if(input.GetType()==MOUSE){
if(input.HasIcon()){
buttonImgSize.x+=input.GetIcon().Sprite()->width+"Interface.InputHelperSpacing"_F;
buttonImgSize.y=std::max(buttonImgSize.y,float(input.GetIcon().Sprite()->height));
buttonImgs.push_back(input.GetIcon().Decal());
}else{
buttonImgSize.x+=game->GetTextSizeProp(input.GetDisplayName()).x+"Interface.InputHelperSpacing"_F;
buttonImgSize.y=std::max(buttonImgSize.y,float(game->GetTextSizeProp(input.GetDisplayName()).y)+"Interface.InputHelperSpacing"_F);
buttonImgs.push_back(input.GetDisplayName());
}
}
}
}
if(primaryKey.has_value()){
if(primaryKey.value().HasIcon()){
buttonImgSize+=primaryKey.value().GetIcon().Sprite()->Size()+vf2d{"Interface.InputHelperSpacing"_F,"Interface.InputHelperSpacing"_F};
buttonImgSize.x+=primaryKey.value().GetIcon().Sprite()->width+"Interface.InputHelperSpacing"_F;
buttonImgSize.y=std::max(buttonImgSize.y,float(primaryKey.value().GetIcon().Sprite()->height));
buttonImgs.push_back(primaryKey.value().GetIcon().Decal());
}else{
buttonImgSize+=game->GetTextSizeProp(primaryKey.value().GetDisplayName())+vf2d{"Interface.InputHelperSpacing"_F,"Interface.InputHelperSpacing"_F};
buttonImgSize.x+=game->GetTextSizeProp(primaryKey.value().GetDisplayName()).x+"Interface.InputHelperSpacing"_F;
buttonImgSize.y=std::max(buttonImgSize.y,float(game->GetTextSizeProp(primaryKey.value().GetDisplayName()).y)+"Interface.InputHelperSpacing"_F);
buttonImgs.push_back(primaryKey.value().GetDisplayName());
}
}
vf2d descriptionTextSize=game->GetTextSizeProp(displayText);
vf2d offset=-((buttonImgSize+descriptionTextSize)/2.f);
for(auto&button:buttonImgs){
@ -326,7 +349,7 @@ void InputGroup::DrawInput(const std::variant<AiL*const,TileTransformedView*cons
#pragma region Render Macro
#define Render(rendererType) \
std::get<rendererType*const>(renderer)->DrawDecal(pos+offset,img,{1.f,1.f},{255,255,255,alpha});
std::get<rendererType*const>(renderer)->DrawDecal(pos+offset-vf2d{0.f,2.f},img,{1.f,1.f},{255,255,255,alpha});
#pragma endregion
if(std::holds_alternative<AiL*const>(renderer)){
Render(AiL);
@ -483,9 +506,9 @@ std::map<std::pair<InputType,int>,GenericKey::KeyInfo> GenericKey::keyLiteral={
{{KEY, olc::ENUM_END},{""}},
{{KEY, SHOULDER},{"Q-E","themes/button_qe.png"}},
{{KEY, ARROWS},{"Arrow Keys","themes/button_arrows.png"}},
{{MOUSE, Mouse::LEFT},{"L.MOUSE"}},
{{MOUSE, Mouse::RIGHT},{"R.MOUSE"}},
{{MOUSE, Mouse::MIDDLE},{"M.MOUSE"}},
{{MOUSE, Mouse::LEFT},{"L.MOUSE","themes/lmb.png"}},
{{MOUSE, Mouse::RIGHT},{"R.MOUSE","themes/rmb.png"}},
{{MOUSE, Mouse::MIDDLE},{"M.MOUSE","themes/mmb.png"}},
{{CONTROLLER, static_cast<int>(GPButtons::FACE_D)},{"A/X","themes/button_d.png"}},
{{CONTROLLER, static_cast<int>(GPButtons::FACE_L)},{"X/Square","themes/button_l.png"}},
{{CONTROLLER, static_cast<int>(GPButtons::FACE_R)},{"B/Circle","themes/button_r.png"}},
@ -636,11 +659,6 @@ void InputListener::Update(){
for(size_t button=0;bool hasButton:gamepad->availableButtons){
GPButtons releasedButton=olc::GPButtons(button);
if(gamepad->getButton(releasedButton).bReleased){
if(releasedButton==GPButtons::SELECT){ //If we hit select we don't bother with setting the input and leave immediately.
Menu::CloseMenu();
return;
}
InputGroup::menuNamesToInputGroups[Menu::menus[NEW_INPUT]->S(A::KEYBIND)]->SetNewPrimaryKeybind(Input{CONTROLLER,int(button)});
Menu::alreadyClicked=true;
Menu::CloseMenu();

View File

@ -95,6 +95,8 @@ class InputGroup{
std::set<Input>keys;
std::vector<Input>keyOrder; //A list of keys inserted in order, for primary key mapping.
static safemap<std::string,InputGroup*>menuNamesToInputGroups;
static std::vector<std::string>menuInputGroups;
static std::vector<std::string>gameplayInputGroups;
void RemovePrimaryKeybind(InputType type);
void AddPrimaryKeybind(Input key);

View File

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

View File

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

View File

@ -60,6 +60,9 @@ Images
GFX_Button_Face_L2 = themes/button_l2.png
GFX_Button_Face_R1 = themes/button_r1.png
GFX_Button_Face_R2 = themes/button_r2.png
GFX_LMB = themes/lmb.png
GFX_RMB = themes/rmb.png
GFX_MMB = themes/mmb.png
GFX_Button_SHOULDER_QE = themes/button_qe.png
GFX_Button_SHOULDER_L1R1 = themes/button_r1l1.png
GFX_Button_AnalogStick = themes/button_analogstick.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.4 KiB

View File

@ -1000,6 +1000,8 @@ namespace olc
virtual bool OnUserDestroy();
virtual void GetAnyKeyPress(Key key);
virtual void GetAnyKeyRelease(Key key);
virtual void GetAnyMousePress(int32_t mouseButton);
virtual void GetAnyMouseRelease(int32_t mouseButton);
// Called when a text entry is confirmed with "enter" key
virtual void OnTextEntryComplete(const std::string& sText);
@ -4447,6 +4449,10 @@ namespace olc
{ }
void PixelGameEngine::GetAnyKeyRelease(Key key)
{ }
void PixelGameEngine::GetAnyMousePress(int32_t mouseButton)
{ }
void PixelGameEngine::GetAnyMouseRelease(int32_t mouseButton)
{ }
void PixelGameEngine::OnTextEntryComplete(const std::string& sText) { UNUSED(sText); }
bool PixelGameEngine::OnConsoleCommand(const std::string& sCommand) { UNUSED(sCommand); return false; }
@ -4675,12 +4681,14 @@ namespace olc
pKeys[i].bPressed = !pKeys[i].bHeld;
pKeys[i].bHeld = true;
if(pKeys==pKeyboardState)GetAnyKeyPress(Key(i)); //Only produce an event when it's for the keyboard.
else if(pKeys==pMouseState)GetAnyMousePress(i); //Only produce an event when it's for the mouse.
}
else
{
pKeys[i].bReleased = true;
pKeys[i].bHeld = false;
if(pKeys==pKeyboardState)GetAnyKeyRelease(Key(i)); //Only produce an event when it's for the keyboard.
else if(pKeys==pMouseState)GetAnyMouseRelease(i); //Only produce an event when it's for the mouse.
}
}
pStateOld[i] = pStateNew[i];