Merge branch 'keymapping_sanity' of https://github.com/kyzentun/stepmania
This commit is contained in:
@@ -0,0 +1,20 @@
|
||||
return Def.ActorFrame{
|
||||
InitCommand=cmd(x,SCREEN_CENTER_X;y,SCREEN_CENTER_Y),
|
||||
Def.Quad{
|
||||
InitCommand=cmd(zoomto,SCREEN_WIDTH,SCREEN_HEIGHT;diffuse,Color.Black;diffusealpha,0),
|
||||
SetTextCommand=cmd(stoptweening;diffusealpha,1;linear,0.5;diffusealpha,0.8),
|
||||
TweenOffCommand=cmd(stoptweening;linear,0.5;diffusealpha,0),
|
||||
},
|
||||
Def.ActorFrame{
|
||||
Def.BitmapText{
|
||||
Font="Common Normal",
|
||||
InitCommand=cmd(y,10;wrapwidthpixels,SCREEN_WIDTH-48;diffusealpha,0),
|
||||
SetTextCommand= function(self, param)
|
||||
self:settext(param.Text)
|
||||
self:playcommand("TweenOn")
|
||||
end,
|
||||
TweenOnCommand=cmd(stoptweening;diffusealpha,0;sleep,0.5125;linear,0.125;diffusealpha,1),
|
||||
TweenOffCommand=cmd(stoptweening;linear,0.5;diffusealpha,0),
|
||||
},
|
||||
},
|
||||
}
|
||||
@@ -1362,6 +1362,7 @@ Reload=Reload
|
||||
Reload Overlay Screens=Reload Overlay Screens
|
||||
Reload Theme and Textures=Reload Theme and Textures
|
||||
Rendering Stats=Rendering Stats
|
||||
Reset key mapping to default=Reset key mapping to default
|
||||
Screen Test Mode=Screen Test Mode
|
||||
Send Off To Screen=Send Off To Screen
|
||||
Send On To Screen=Send On To Screen
|
||||
@@ -1562,11 +1563,16 @@ Default=Default
|
||||
HeaderText=Map Controllers
|
||||
InvalidButton=That key can not be mapped.
|
||||
KeyName=Key Name
|
||||
MenuLeftMissing=Nothing is mapped to MenuLeft
|
||||
MenuRightMissing=Nothing is mapped to MenuRight
|
||||
NoSetListPrompt=No entries in the list to set. Add entries to the list by hitting 'm' when the cursor is on them.
|
||||
%s slots=%s slots
|
||||
OperatorMissing=Nothing is mapped to Operator
|
||||
Primary=Primary
|
||||
SavePrompt=Save settings before exiting?
|
||||
Secondary=Secondary
|
||||
StartMissing=Nothing is mapped to Start
|
||||
VitalButtons=Buttons vital for navigating menus are not mapped:
|
||||
WarningHeader=WARNING!
|
||||
WarningText=Please ensure that you do not overwrite any important keymappings, such as:\n&MENULEFT; LEFT &MENURIGHT; RIGHT &MENUUP; UP &MENUDOWN; DOWN &START; START &BACK; BACK or &SELECT; SELECT. Do not apply keymappings that you do not know the function of or unmap important keys!
|
||||
|
||||
|
||||
@@ -2870,6 +2870,8 @@ AutoDismissWarningSecs=2.5
|
||||
LinesVisible=16
|
||||
# This sets how long the NoSetListPrompt will show before being sent TweenOff.
|
||||
AutoDismissNoSetListPromptSecs=5
|
||||
# The time to auto dismiss the sanity warning if the current mapping is not sane.
|
||||
AutoDismissSanitySecs=5
|
||||
#
|
||||
# The position of the Devices list and its On/Off commands.
|
||||
DevicesX=SCREEN_CENTER_X
|
||||
|
||||
@@ -661,6 +661,67 @@ void InputMapper::ResetMappingsToDefault()
|
||||
AddDefaultMappingsForCurrentGameIfUnmapped();
|
||||
}
|
||||
|
||||
void InputMapper::CheckButtonAndAddToReason(GameButton menu, vector<RString>& full_reason, RString const& sub_reason)
|
||||
{
|
||||
vector<GameInput> inputs;
|
||||
bool exists= false;
|
||||
// Only player 1 is checked because the player 2 buttons are rarely
|
||||
// unmapped and do not exist on some keyboard models. -Kyz
|
||||
GetInputScheme()->MenuButtonToGameInputs(menu, PLAYER_1, inputs);
|
||||
if(!inputs.empty())
|
||||
{
|
||||
vector<DeviceInput> device_inputs;
|
||||
FOREACH(GameInput, inputs, inp)
|
||||
{
|
||||
for(int slot= 0; slot < NUM_GAME_TO_DEVICE_SLOTS; ++slot)
|
||||
{
|
||||
device_inputs.push_back(m_mappings.m_GItoDI[inp->controller][inp->button][slot]);
|
||||
}
|
||||
}
|
||||
FOREACH(DeviceInput, device_inputs, inp)
|
||||
{
|
||||
if(!inp->IsValid())
|
||||
{
|
||||
continue;
|
||||
}
|
||||
int use_count= 0;
|
||||
FOREACH_ENUM(GameController, cont)
|
||||
{
|
||||
FOREACH_GameButtonInScheme(GetInputScheme(), gb)
|
||||
{
|
||||
for(int slot= 0; slot < NUM_GAME_TO_DEVICE_SLOTS; ++slot)
|
||||
{
|
||||
use_count+= ((*inp) == m_mappings.m_GItoDI[cont][gb][slot]);
|
||||
}
|
||||
}
|
||||
}
|
||||
// If the device input is used more than once, it's a case where a
|
||||
// default mapped key was remapped to some other game button. -Kyz
|
||||
if(use_count == 1)
|
||||
{
|
||||
exists= true;
|
||||
}
|
||||
}
|
||||
}
|
||||
if(!exists)
|
||||
{
|
||||
full_reason.push_back(sub_reason);
|
||||
}
|
||||
}
|
||||
|
||||
void InputMapper::SanityCheckMappings(vector<RString>& reason)
|
||||
{
|
||||
// This is just to check whether the current mapping has the minimum
|
||||
// necessary to navigate the menus so the user can reach the config screen.
|
||||
// For this purpose, only the following keys are needed:
|
||||
// MenuLeft, MenuRight, Start, Operator
|
||||
// The InputScheme handles OnlyDedicatedMenuButtons logic. -Kyz
|
||||
CheckButtonAndAddToReason(GAME_BUTTON_MENULEFT, reason, "MenuLeftMissing");
|
||||
CheckButtonAndAddToReason(GAME_BUTTON_MENURIGHT, reason, "MenuRightMissing");
|
||||
CheckButtonAndAddToReason(GAME_BUTTON_START, reason, "StartMissing");
|
||||
CheckButtonAndAddToReason(GAME_BUTTON_OPERATOR, reason, "OperatorMissing");
|
||||
}
|
||||
|
||||
static LocalizedString CONNECTED ( "InputMapper", "Connected" );
|
||||
static LocalizedString DISCONNECTED ( "InputMapper", "Disconnected" );
|
||||
static LocalizedString AUTOMAPPING_ALL_JOYSTICKS ( "InputMapper", "Auto-mapping all joysticks." );
|
||||
|
||||
@@ -152,6 +152,8 @@ public:
|
||||
void ReadMappingsFromDisk();
|
||||
void SaveMappingsToDisk();
|
||||
void ResetMappingsToDefault();
|
||||
void CheckButtonAndAddToReason(GameButton menu, vector<RString>& full_reason, RString const& sub_reason);
|
||||
void SanityCheckMappings(vector<RString>& reason);
|
||||
|
||||
void ClearAllMappings();
|
||||
|
||||
|
||||
@@ -12,6 +12,7 @@
|
||||
#include "ScreenGameplay.h"
|
||||
#include "RageSoundManager.h"
|
||||
#include "GameSoundManager.h"
|
||||
#include "InputMapper.h"
|
||||
#include "RageTextureManager.h"
|
||||
#include "MemoryCardManager.h"
|
||||
#include "NoteSkinManager.h"
|
||||
@@ -544,6 +545,7 @@ static LocalizedString PROFILE ( "ScreenDebugOverlay", "Profile" );
|
||||
static LocalizedString CLEAR_PROFILE_STATS ( "ScreenDebugOverlay", "Clear Profile Stats" );
|
||||
static LocalizedString FILL_PROFILE_STATS ( "ScreenDebugOverlay", "Fill Profile Stats" );
|
||||
static LocalizedString SEND_NOTES_ENDED ( "ScreenDebugOverlay", "Send Notes Ended" );
|
||||
static LocalizedString RESET_KEY_MAP ("ScreenDebugOverlay", "Reset key mapping to default");
|
||||
static LocalizedString RELOAD ( "ScreenDebugOverlay", "Reload" );
|
||||
static LocalizedString RESTART ( "ScreenDebugOverlay", "Restart" );
|
||||
static LocalizedString SCREEN_ON ( "ScreenDebugOverlay", "Send On To Screen" );
|
||||
@@ -952,6 +954,19 @@ class DebugLineSendNotesEnded : public IDebugLine
|
||||
}
|
||||
};
|
||||
|
||||
class DebugLineResetKeyMapping : public IDebugLine
|
||||
{
|
||||
virtual RString GetDisplayTitle() { return RESET_KEY_MAP.GetValue(); }
|
||||
virtual RString GetDisplayValue() { return RString(); }
|
||||
virtual bool IsEnabled() { return true; }
|
||||
virtual void DoAndLog( RString &sMessageOut )
|
||||
{
|
||||
INPUTMAPPER->ResetMappingsToDefault();
|
||||
INPUTMAPPER->SaveMappingsToDisk();
|
||||
IDebugLine::DoAndLog( sMessageOut );
|
||||
}
|
||||
};
|
||||
|
||||
class DebugLineReloadCurrentScreen : public IDebugLine
|
||||
{
|
||||
virtual RString GetDisplayTitle() { return RELOAD.GetValue(); }
|
||||
@@ -1272,6 +1287,7 @@ DECLARE_ONE( DebugLineVisualDelayDown );
|
||||
DECLARE_ONE( DebugLineVisualDelayUp );
|
||||
DECLARE_ONE( DebugLineForceCrash );
|
||||
DECLARE_ONE( DebugLineUptime );
|
||||
DECLARE_ONE( DebugLineResetKeyMapping );
|
||||
|
||||
|
||||
/*
|
||||
|
||||
@@ -200,6 +200,10 @@ void ScreenMapControllers::Init()
|
||||
m_NoSetListPrompt->SetName("NoSetListPrompt");
|
||||
this->AddChild(m_NoSetListPrompt);
|
||||
|
||||
m_SanityMessage.Load(THEME->GetPathG(m_sName, "sanitymessage"));
|
||||
m_SanityMessage->SetName("SanityMessage");
|
||||
this->AddChild(m_SanityMessage);
|
||||
|
||||
m_Warning.Load(THEME->GetPathG(m_sName, "warning"));
|
||||
m_Warning->SetName("Warning");
|
||||
m_Warning->SetDrawOrder(DRAW_ORDER_TRANSITIONS);
|
||||
@@ -222,6 +226,7 @@ void ScreenMapControllers::BeginScreen()
|
||||
m_fLockInputSecs= THEME->GetMetricF(m_sName, "LockInputSecs");
|
||||
m_AutoDismissWarningSecs= THEME->GetMetricF(m_sName, "AutoDismissWarningSecs");
|
||||
m_AutoDismissNoSetListPromptSecs= 0.0f;
|
||||
m_AutoDismissSanitySecs= 0.0f;
|
||||
m_Warning->PlayCommand("TweenOn");
|
||||
}
|
||||
|
||||
@@ -247,6 +252,14 @@ void ScreenMapControllers::Update( float fDeltaTime )
|
||||
m_NoSetListPrompt->PlayCommand("TweenOff");
|
||||
}
|
||||
}
|
||||
if(m_AutoDismissSanitySecs > 0.0f)
|
||||
{
|
||||
m_AutoDismissSanitySecs-= fDeltaTime;
|
||||
if(m_AutoDismissSanitySecs <= 0.0f)
|
||||
{
|
||||
m_SanityMessage->PlayCommand("TweenOff");
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// Update devices text
|
||||
@@ -349,6 +362,18 @@ bool ScreenMapControllers::Input( const InputEventPlus &input )
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
if(m_AutoDismissSanitySecs > 0.0f)
|
||||
{
|
||||
if(input.type == IET_FIRST_PRESS &&
|
||||
input.DeviceI.device == DEVICE_KEYBOARD &&
|
||||
input.DeviceI.button == KEY_ENTER)
|
||||
{
|
||||
m_AutoDismissSanitySecs = 0.0f;
|
||||
m_SanityMessage->PlayCommand("TweenOff");
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
if( input.type != IET_FIRST_PRESS && input.type != IET_REPEAT )
|
||||
{
|
||||
@@ -706,8 +731,11 @@ void ScreenMapControllers::ReloadFromDisk()
|
||||
|
||||
void ScreenMapControllers::SaveToDisk()
|
||||
{
|
||||
INPUTMAPPER->SaveMappingsToDisk();
|
||||
m_ChangeOccurred= false;
|
||||
if(SanityCheckWrapper())
|
||||
{
|
||||
INPUTMAPPER->SaveMappingsToDisk();
|
||||
m_ChangeOccurred= false;
|
||||
}
|
||||
}
|
||||
|
||||
void ScreenMapControllers::SetListMode()
|
||||
@@ -732,8 +760,13 @@ void ScreenMapControllers::ExitAction()
|
||||
{
|
||||
if(m_ChangeOccurred)
|
||||
{
|
||||
ScreenPrompt::Prompt(SM_DoSaveAndExit, SAVE_PROMPT, PROMPT_YES_NO_CANCEL,
|
||||
ANSWER_YES);
|
||||
// If the current mapping doesn't pass the sanity check, then the user
|
||||
// can't navigate the prompt screen to pick a choice. -Kyz
|
||||
if(SanityCheckWrapper())
|
||||
{
|
||||
ScreenPrompt::Prompt(SM_DoSaveAndExit, SAVE_PROMPT,
|
||||
PROMPT_YES_NO_CANCEL, ANSWER_YES);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -742,6 +775,30 @@ void ScreenMapControllers::ExitAction()
|
||||
}
|
||||
}
|
||||
|
||||
bool ScreenMapControllers::SanityCheckWrapper()
|
||||
{
|
||||
vector<RString> reasons_not_sane;
|
||||
INPUTMAPPER->SanityCheckMappings(reasons_not_sane);
|
||||
if(reasons_not_sane.empty())
|
||||
{
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
FOREACH(RString, reasons_not_sane, reason)
|
||||
{
|
||||
*reason= THEME->GetString("ScreenMapControllers", *reason);
|
||||
}
|
||||
RString joined_reasons= join("\n", reasons_not_sane);
|
||||
joined_reasons= THEME->GetString("ScreenMapControllers", "VitalButtons") + "\n" + joined_reasons;
|
||||
Message msg("SetText");
|
||||
msg.SetParam("Text", joined_reasons);
|
||||
m_SanityMessage->HandleMessage(msg);
|
||||
m_AutoDismissSanitySecs= THEME->GetMetricF(m_sName, "AutoDismissSanitySecs");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
void ScreenMapControllers::ActionRow::Load(RString const& scr_name,
|
||||
RString const& name, ScreenMapControllers::action_fun_t action,
|
||||
ActorFrame* line, ActorScroller* scroller)
|
||||
|
||||
@@ -72,6 +72,9 @@ private:
|
||||
float m_AutoDismissNoSetListPromptSecs;
|
||||
AutoActor m_NoSetListPrompt;
|
||||
|
||||
float m_AutoDismissSanitySecs;
|
||||
AutoActor m_SanityMessage;
|
||||
|
||||
struct SetListEntry
|
||||
{
|
||||
int m_button;
|
||||
@@ -111,6 +114,7 @@ private:
|
||||
void SaveToDisk();
|
||||
void SetListMode();
|
||||
void ExitAction();
|
||||
bool SanityCheckWrapper();
|
||||
|
||||
vector<ActionRow> m_Actions;
|
||||
|
||||
|
||||
Reference in New Issue
Block a user