From f2fdaa0cf5b9a4789acbfb884283aec5b4e59b4b Mon Sep 17 00:00:00 2001 From: Kyzentun Date: Thu, 4 Sep 2014 01:23:28 -0600 Subject: [PATCH] Massively improved Config Key/Joy Mappings screen. Warning is dismissable now, and cursor does not start in a position that will change a setting. New special actions added: ClearToDefault, ReloadFromDisk, SaveToDisk, SetListMode. Exit is a special action. Player is prompted to save when exiting screen instead of saving after every action. Special actions fallback on Graphics/SMC action if they don't have their own. Moved SMC overlay to Graphics/SMC warning. Metrics for configuring input lock time, warning autodismiss time, lines visible, and NoSetListPrompt autodismiss time. Header row added for cursor to start on. ScreenMapControllers2 deleted as obsolete. BitmapText:maxwidth changed to factor the zoom of the actor into the calculation. --- .../ScreenMapControllers overlay.lua | 27 - .../Graphics/ScreenMapControllers action.lua | 16 + .../Graphics/ScreenMapControllers exit.lua | 10 - .../ScreenMapControllers nosetlistprompt.lua | 17 + .../Graphics/ScreenMapControllers warning.lua | 24 + Themes/_fallback/Languages/en.ini | 14 +- Themes/_fallback/metrics.ini | 21 +- Themes/default/metrics.ini | 1 + src/ActorUtil.cpp | 2 +- src/AutoActor.cpp | 5 +- src/BitmapText.cpp | 47 +- src/InputMapper.cpp | 7 + src/InputMapper.h | 1 + src/ScreenMapControllers.cpp | 459 ++++++++++++--- src/ScreenMapControllers.h | 70 ++- src/ScreenMapControllers2.cpp | 532 ------------------ src/ScreenMapControllers2.h | 136 ----- 17 files changed, 574 insertions(+), 815 deletions(-) delete mode 100644 Themes/_fallback/BGAnimations/ScreenMapControllers overlay.lua create mode 100644 Themes/_fallback/Graphics/ScreenMapControllers action.lua delete mode 100644 Themes/_fallback/Graphics/ScreenMapControllers exit.lua create mode 100644 Themes/_fallback/Graphics/ScreenMapControllers nosetlistprompt.lua create mode 100644 Themes/_fallback/Graphics/ScreenMapControllers warning.lua delete mode 100644 src/ScreenMapControllers2.cpp delete mode 100644 src/ScreenMapControllers2.h diff --git a/Themes/_fallback/BGAnimations/ScreenMapControllers overlay.lua b/Themes/_fallback/BGAnimations/ScreenMapControllers overlay.lua deleted file mode 100644 index 9f90de1fc3..0000000000 --- a/Themes/_fallback/BGAnimations/ScreenMapControllers overlay.lua +++ /dev/null @@ -1,27 +0,0 @@ -local waitTime = 7.5 - -local t = Def.ActorFrame { - InitCommand=cmd(x,SCREEN_CENTER_X;y,SCREEN_CENTER_Y); - OnCommand=cmd(queuecommand,"TweenOn";sleep,waitTime;queuecommand,"TweenOff"); -} -t[#t+1] = Def.Quad { - InitCommand=cmd(zoomto,SCREEN_WIDTH,SCREEN_HEIGHT;diffuse,Color.Black); - TweenOnCommand=cmd(diffusealpha,1;linear,0.5;diffusealpha,0.8); - TweenOffCommand=cmd(linear,0.5;diffusealpha,0); -}; -t[#t+1] = Def.ActorFrame { - LoadFont("Common Normal") .. { - Text=ScreenString("WarningHeader"); - InitCommand=cmd(y,-70;diffuse,Color.Red); - TweenOnCommand=cmd(diffusealpha,0;zoomx,2;zoomy,0;sleep,0.5;smooth,0.25;zoom,1;diffusealpha,1); - TweenOffCommand=cmd(linear,0.5;diffusealpha,0); - }; - LoadFont("Common Normal") .. { - Text=ScreenString("WarningText"); - InitCommand=cmd(y,10;wrapwidthpixels,SCREEN_WIDTH-48); - TweenOnCommand=cmd(diffusealpha,0;sleep,0.5125;linear,0.125;diffusealpha,1); - TweenOffCommand=cmd(linear,0.5;diffusealpha,0); - }; -}; - -return t \ No newline at end of file diff --git a/Themes/_fallback/Graphics/ScreenMapControllers action.lua b/Themes/_fallback/Graphics/ScreenMapControllers action.lua new file mode 100644 index 0000000000..0ff5737aa3 --- /dev/null +++ b/Themes/_fallback/Graphics/ScreenMapControllers action.lua @@ -0,0 +1,16 @@ +return LoadFont("Common Normal") .. { + InitCommand= cmd(x, SCREEN_CENTER_X; zoom, .75; shadowlength, 0; diffuse, color("#808080")), + OnCommand= function(self) + self:diffusealpha(0) + self:decelerate(0.5) + self:diffusealpha(1) + -- fancy effect: Look at the name (which is set by the screen) to set text + self:settext( + THEME:GetString("ScreenMapControllers", "Action" .. self:GetName())) + end, + OffCommand=cmd(stoptweening;accelerate,0.3;diffusealpha,0;queuecommand,"Hide"); + HideCommand=cmd(visible,false); + + GainFocusCommand=cmd(diffuseshift;effectcolor2,color("#808080");effectcolor1,color("#FFFFFF")); + LoseFocusCommand=cmd(stopeffect); +}; diff --git a/Themes/_fallback/Graphics/ScreenMapControllers exit.lua b/Themes/_fallback/Graphics/ScreenMapControllers exit.lua deleted file mode 100644 index e922b168d6..0000000000 --- a/Themes/_fallback/Graphics/ScreenMapControllers exit.lua +++ /dev/null @@ -1,10 +0,0 @@ -return LoadFont("Common Normal") .. { - Text="Exit"; - InitCommand=cmd(x,SCREEN_CENTER_X;zoom,0.75;shadowlength,0;diffuse,color("#808080")); - OnCommand=cmd(diffusealpha,0;decelerate,0.5;diffusealpha,1); - OffCommand=cmd(stoptweening;accelerate,0.3;diffusealpha,0;queuecommand,"Hide"); - HideCommand=cmd(visible,false); - - GainFocusCommand=cmd(diffuseshift;effectcolor2,color("#808080");effectcolor1,color("#FFFFFF")); - LoseFocusCommand=cmd(stopeffect); -}; diff --git a/Themes/_fallback/Graphics/ScreenMapControllers nosetlistprompt.lua b/Themes/_fallback/Graphics/ScreenMapControllers nosetlistprompt.lua new file mode 100644 index 0000000000..a965e5f5e7 --- /dev/null +++ b/Themes/_fallback/Graphics/ScreenMapControllers nosetlistprompt.lua @@ -0,0 +1,17 @@ +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), + TweenOnCommand=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", + Text=ScreenString("NoSetListPrompt"), + InitCommand=cmd(y,10;wrapwidthpixels,SCREEN_WIDTH-48;diffusealpha,0), + TweenOnCommand=cmd(stoptweening;diffusealpha,0;sleep,0.5125;linear,0.125;diffusealpha,1), + TweenOffCommand=cmd(stoptweening;linear,0.5;diffusealpha,0), + }, + }, +} diff --git a/Themes/_fallback/Graphics/ScreenMapControllers warning.lua b/Themes/_fallback/Graphics/ScreenMapControllers warning.lua new file mode 100644 index 0000000000..908f127ab4 --- /dev/null +++ b/Themes/_fallback/Graphics/ScreenMapControllers warning.lua @@ -0,0 +1,24 @@ +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), + TweenOnCommand=cmd(diffusealpha,1;linear,0.5;diffusealpha,0.8), + TweenOffCommand=cmd(linear,0.5;diffusealpha,0), + }, + Def.ActorFrame{ + Def.BitmapText{ + Font="Common Normal", + Text=ScreenString("WarningHeader"), + InitCommand=cmd(y,-80;diffuse,Color.Red), + TweenOnCommand=cmd(diffusealpha,0;zoomx,2;zoomy,0;sleep,0.5;smooth,0.25;zoom,1;diffusealpha,1), + TweenOffCommand=cmd(linear,0.5;diffusealpha,0), + }, + Def.BitmapText{ + Font="Common Normal", + Text=ScreenString("WarningText"), + InitCommand=cmd(y,10;wrapwidthpixels,SCREEN_WIDTH-48), + TweenOnCommand=cmd(diffusealpha,0;sleep,0.5125;linear,0.125;diffusealpha,1), + TweenOffCommand=cmd(linear,0.5;diffusealpha,0), + }, + }, +} diff --git a/Themes/_fallback/Languages/en.ini b/Themes/_fallback/Languages/en.ini index 4757b676c6..1d3b381432 100644 --- a/Themes/_fallback/Languages/en.ini +++ b/Themes/_fallback/Languages/en.ini @@ -1531,15 +1531,23 @@ Warning=Warning BodyText=The StepMania program source code is licensed under a permissive open-source license.\n\nThe StepMania name and logos are protected by Trademark law.\n\nThe StepMania default theme SOUNDS ARE SEPARATELY OWNED BY THE AUTHORS. ALL OTHER THEME COMPONENTS ARE LICENSED UNDER THE STEPMANIA LICENSE.\n\nSee license.txt for details. [ScreenMapControllers] +ActionClear=Clear To Default +ActionReload=Reload From Disk +ActionSave=Save To Disk +ActionSetList=Assign List +ActionExit=Exit +Default=Default HeaderText=Map Controllers InvalidButton=That key can not be mapped. +KeyName=Key Name +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 +Primary=Primary +SavePrompt=Save settings before exiting? +Secondary=Secondary 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! -[ScreenMapControllers2] -Add Mapping=Add Mapping - [ScreenNetRoom] Enter a description for the room:=Enter a description for the room: Enter a password for the room (blank, no password):=Enter a password for the room (blank, no password): diff --git a/Themes/_fallback/metrics.ini b/Themes/_fallback/metrics.ini index 50299c88b9..a9e94e5202 100644 --- a/Themes/_fallback/metrics.ini +++ b/Themes/_fallback/metrics.ini @@ -2855,13 +2855,28 @@ Fallback="ScreenOptionsServiceChild" NextScreen="ScreenOptionsService" HelpText=Screen.String("HelpTextMapControllers") # -ScreenOnCommand=%function(self) MESSAGEMAN:Broadcast("KeyConfigRequestStall"); self:lockinput(5); end; +LockInputSecs=2.5 +AutoDismissWarningSecs=2.5 +LinesVisible=16 +AutoDismissNoSetListPromptSecs=5 # DevicesX=SCREEN_CENTER_X DevicesY=SCREEN_TOP+24 DevicesOnCommand=zoom,0.75;draworder,5;strokecolor,color("0,0,0,1") DevicesOffCommand= # +HeaderP1S1Command=x,SCREEN_CENTER_X-270 +HeaderP1S2Command=x,SCREEN_CENTER_X-195 +HeaderP1S3Command=x,SCREEN_CENTER_X-120 +HeaderP2S1Command=x,SCREEN_CENTER_X+120 +HeaderP2S2Command=x,SCREEN_CENTER_X+195 +HeaderP2S3Command=x,SCREEN_CENTER_X+270 +# +headerCenterOnCommand=x,SCREEN_CENTER_X;y,-6;zoom,0.7;shadowlength,1;ztest,true +HeaderOnCommand=diffuse,color("#808080");shadowlength,0;zoom,0.75;maxwidth,130; +HeaderGainFocusCommand=diffuse,color("#808080");diffuseshift;effectcolor2,color("#808080");effectcolor1,color("#FFFFFF") +HeaderLoseFocusCommand=diffuse,color("#808080");stopeffect +# ButtonsToMap="" MappedToP1S1Command=x,SCREEN_CENTER_X-270 MappedToP1S2Command=x,SCREEN_CENTER_X-195 @@ -2870,11 +2885,13 @@ MappedToP2S1Command=x,SCREEN_CENTER_X+120 MappedToP2S2Command=x,SCREEN_CENTER_X+195 MappedToP2S3Command=x,SCREEN_CENTER_X+270 # -MappedToOnCommand=diffuse,color("#808080");shadowlength,0;maxwidth,150;zoom,0.75 +MappedToOnCommand=diffuse,color("#808080");shadowlength,0;zoom,0.75;maxwidth,130 MappedToWaitingCommand=diffuse,color("#FF8080");pulse;effectperiod,0.5;effectmagnitude,0.8,1.3,0 MappedToMappedInputCommand=diffuse,color("#808080");diffuseshift;effectcolor2,color("#808080");effectcolor1,color("#FFFFFF") MappedToGainFocusCommand=diffuse,color("#808080");diffuseshift;effectcolor2,color("#808080");effectcolor1,color("#FFFFFF") MappedToLoseFocusCommand=diffuse,color("#808080");stopeffect +MappedToGainMarkCommand=textglowmode,'TextGlowMode_Inner';glow,color("#FF00007f") +MappedToLoseMarkCommand=textglowmode,'TextGlowMode_Inner';glow,color("#FF000000") # LineScrollerOnCommand=%function(self) self:draworder(-1); self:y(64) self:setsecondsperitem(0.1) self:SetTransformFromHeight(24) end LineScrollerOffCommand= diff --git a/Themes/default/metrics.ini b/Themes/default/metrics.ini index 3eb592a0ed..36ed3d2482 100644 --- a/Themes/default/metrics.ini +++ b/Themes/default/metrics.ini @@ -1339,6 +1339,7 @@ ItemsLongRowSharedX=SCREEN_CENTER_X [OptionRowMiniMenuContext] [ScreenMapControllers] +LinesVisible=15 [ScreenTestInput] diff --git a/src/ActorUtil.cpp b/src/ActorUtil.cpp index 6bbeb84e42..8a1910f058 100644 --- a/src/ActorUtil.cpp +++ b/src/ActorUtil.cpp @@ -221,7 +221,7 @@ Actor *ActorUtil::LoadFromNode( const XNode* _pNode, Actor *pParentActor ) // sClass is invalid RString sError = ssprintf( "%s: invalid Class \"%s\"", ActorUtil::GetWhere(&node).c_str(), sClass.c_str() ); - Dialog::OK( sError ); + LuaHelpers::ReportScriptError(sError); return new Actor; // Return a dummy object so that we don't crash in AutoActor later. } diff --git a/src/AutoActor.cpp b/src/AutoActor.cpp index 26fdb4757f..b3620f96c5 100644 --- a/src/AutoActor.cpp +++ b/src/AutoActor.cpp @@ -6,7 +6,10 @@ void AutoActor::Unload() { - delete m_pActor; + if(m_pActor != NULL) + { + delete m_pActor; + } m_pActor=NULL; } diff --git a/src/BitmapText.cpp b/src/BitmapText.cpp index eb4093afb0..6cd5586650 100644 --- a/src/BitmapText.cpp +++ b/src/BitmapText.cpp @@ -513,35 +513,28 @@ void BitmapText::UnSetDistortion() void BitmapText::UpdateBaseZoom() { - if( m_fMaxWidth == 0 ) - { - this->SetBaseZoomX( 1 ); - } - else - { - const float fWidth = GetUnzoomedWidth(); - if( fWidth != 0 ) // don't divide by 0 - { - // Never decrease the zoom. - const float fZoom = min( 1, m_fMaxWidth/fWidth ); - this->SetBaseZoomX( fZoom ); - } + // don't divide by 0 + // Never apply a zoom greater than 1. + // Factor in the non-base zoom so that maxwidth will be in terms of theme + // pixels when zoom is used. +#define APPLY_DIMENSION_ZOOM(dimension_max, dimension_get, dimension_zoom_get, base_zoom_set) \ + if(dimension_max == 0) \ + { \ + base_zoom_set(1); \ + } \ + else \ + { \ + const float dimension= dimension_get() / dimension_zoom_get(); \ + if(dimension != 0) \ + { \ + const float zoom= min(1, dimension_max / dimension); \ + base_zoom_set(zoom); \ + } \ } - if( m_fMaxHeight == 0 ) - { - this->SetBaseZoomY( 1 ); - } - else - { - const float fHeight = GetUnzoomedHeight(); - if( fHeight != 0 ) // don't divide by 0 - { - // Never decrease the zoom. - const float fZoom = min( 1, m_fMaxHeight/fHeight ); - this->SetBaseZoomY( fZoom ); - } - } + APPLY_DIMENSION_ZOOM(m_fMaxWidth, GetUnzoomedWidth, GetZoomX, SetBaseZoomX); + APPLY_DIMENSION_ZOOM(m_fMaxHeight, GetUnzoomedHeight, GetZoomY, SetBaseZoomY); +#undef APPLY_DIMENSION_ZOOM } bool BitmapText::StringWillUseAlternate( const RString& sText, const RString& sAlternateText ) const diff --git a/src/InputMapper.cpp b/src/InputMapper.cpp index c2bd98106a..cc61833c64 100644 --- a/src/InputMapper.cpp +++ b/src/InputMapper.cpp @@ -654,6 +654,13 @@ void InputMapper::SaveMappingsToDisk() m_mappings.WriteMappings( m_pInputScheme, SpecialFiles::KEYMAPS_PATH ); } +void InputMapper::ResetMappingsToDefault() +{ + m_mappings.Clear(); + UpdateTempDItoGI(); + AddDefaultMappingsForCurrentGameIfUnmapped(); +} + static LocalizedString CONNECTED ( "InputMapper", "Connected" ); static LocalizedString DISCONNECTED ( "InputMapper", "Disconnected" ); static LocalizedString AUTOMAPPING_ALL_JOYSTICKS ( "InputMapper", "Auto-mapping all joysticks." ); diff --git a/src/InputMapper.h b/src/InputMapper.h index dfad769167..9d2f2c10f5 100644 --- a/src/InputMapper.h +++ b/src/InputMapper.h @@ -150,6 +150,7 @@ public: void ReadMappingsFromDisk(); void SaveMappingsToDisk(); + void ResetMappingsToDefault(); void ClearAllMappings(); diff --git a/src/ScreenMapControllers.cpp b/src/ScreenMapControllers.cpp index ed9fe0965a..adf39b6707 100644 --- a/src/ScreenMapControllers.cpp +++ b/src/ScreenMapControllers.cpp @@ -1,6 +1,7 @@ #include "global.h" #include "ScreenMapControllers.h" #include "ScreenManager.h" +#include "ScreenPrompt.h" #include "RageLog.h" #include "RageInput.h" #include "InputMapper.h" @@ -9,8 +10,10 @@ #include "InputEventPlus.h" #include "LocalizedString.h" +AutoScreenMessage(SM_DoSaveAndExit); #define BUTTONS_TO_MAP THEME->GetMetric ( m_sName, "ButtonsToMap" ) static LocalizedString INVALID_BUTTON ( "ScreenMapControllers", "InvalidButton" ); +static LocalizedString SAVE_PROMPT("ScreenMapControllers", "SavePrompt"); #define MAPPED_TO_COMMAND(gc,slot) THEME->GetMetricA( m_sName, ssprintf("MappedToP%iS%iCommand", gc+1, slot+1) ) static const float g_fSecondsToWaitForInput = 0.05f; @@ -22,10 +25,26 @@ REGISTER_SCREEN_CLASS( ScreenMapControllers ); ScreenMapControllers::ScreenMapControllers() { + m_InSetListMode= false; + m_ChangeOccurred= false; this->SubscribeToMessage( Message_AutoJoyMappingApplied ); } +ScreenMapControllers::~ScreenMapControllers() +{ + for(size_t i= 0; i < m_Line.size(); ++i) + { + SAFE_DELETE(m_Line[i]); + } +} + static LocalizedString PLAYER_SLOTS( "ScreenMapControllers", "%s slots" ); +static LocalizedString SLOT_NAMES[3]= { + LocalizedString("ScreenMapControllers", "Primary"), + LocalizedString("ScreenMapControllers", "Secondary"), + LocalizedString("ScreenMapControllers", "Default") +}; +static LocalizedString KEYNAME("ScreenMapControllers", "KeyName"); void ScreenMapControllers::Init() { ScreenWithMenuElements::Init(); @@ -64,12 +83,11 @@ void ScreenMapControllers::Init() } } - int iRow = 0; - - // header row + // slot names row { + m_Line.push_back(new ActorFrame); FOREACH_ENUM( GameController, c ) - { + { BitmapText &text = m_textLabel[c]; text.LoadFromFont( THEME->GetPathF(m_sName,"title") ); PlayerNumber pn = (PlayerNumber)c; @@ -77,16 +95,40 @@ void ScreenMapControllers::Init() RString sText = ssprintf(PLAYER_SLOTS.GetValue(), PlayerNumberToLocalizedString(pn).c_str()); text.SetText( sText ); ActorUtil::LoadAllCommands( text, m_sName ); - m_Line[iRow].AddChild( &m_textLabel[c] ); + m_Line.back()->AddChild( &m_textLabel[c] ); } - m_LineScroller.AddChild( &m_Line[iRow] ); - - iRow++; + m_LineScroller.AddChild(m_Line.back()); + } + // header row + { + m_Line.push_back(new ActorFrame); + m_headerCenter.LoadFromFont(THEME->GetPathF(m_sName, "title")); + m_headerCenter.SetName("headerCenter"); + m_headerCenter.SetText(KEYNAME); + ActorUtil::LoadAllCommands(m_headerCenter, m_sName); + m_Line.back()->AddChild(&m_headerCenter); + FOREACH_ENUM(GameController, c) + { + for(int s= 0; s < NUM_SHOWN_GAME_TO_DEVICE_SLOTS; ++s) + { + BitmapText& text= m_headerLabels[c][s]; + text.LoadFromFont(THEME->GetPathF(m_sName, "title")); + PlayerNumber pn = (PlayerNumber)c; + text.SetName("Header"); + text.SetText(SLOT_NAMES[s]); + text.RunCommands(THEME->GetMetricA( + m_sName, ssprintf("HeaderP%iS%iCommand", c+1, s+1))); + ActorUtil::LoadAllCommands(text, m_sName); + m_Line.back()->AddChild(&text); + } + } + m_LineScroller.AddChild(m_Line.back()); } // normal rows for( unsigned b=0; bGetInputScheme(), pKey->m_GameButton ); pName->SetText( sText ); ActorUtil::LoadAllCommands( *pName, m_sName ); - m_Line[iRow].AddChild( pName ); + m_Line.back()->AddChild( pName ); } { BitmapText *pSecondary = new BitmapText; @@ -108,11 +150,11 @@ void ScreenMapControllers::Init() sText = GameButtonToLocalizedString( INPUTMAPPER->GetInputScheme(), mb ); ActorUtil::LoadAllCommands( *pSecondary, m_sName ); pSecondary->SetText( sText ); - m_Line[iRow].AddChild( pSecondary ); + m_Line.back()->AddChild( pSecondary ); } FOREACH_ENUM( GameController, c ) - { + { for( int s=0; sm_textMappedTo[c][s] = new BitmapText; @@ -120,34 +162,50 @@ void ScreenMapControllers::Init() pKey->m_textMappedTo[c][s]->LoadFromFont( THEME->GetPathF(m_sName,"entry") ); pKey->m_textMappedTo[c][s]->RunCommands( MAPPED_TO_COMMAND(c,s) ); ActorUtil::LoadAllCommands( *pKey->m_textMappedTo[c][s], m_sName ); - m_Line[iRow].AddChild( pKey->m_textMappedTo[c][s] ); + m_Line.back()->AddChild( pKey->m_textMappedTo[c][s] ); } } - m_Line[iRow].DeleteChildrenWhenDone(); - m_Line[iRow].SetName( "Line" ); - ActorUtil::LoadAllCommands( m_Line[iRow], m_sName ); - m_LineScroller.AddChild( &m_Line[iRow] ); - - iRow++; - } - - // exit row - { - m_sprExit.Load( THEME->GetPathG(m_sName,"exit") ); - m_sprExit->SetName( "Exit" ); - ActorUtil::LoadAllCommands( *m_sprExit, m_sName ); - - m_Line[iRow].AddChild( m_sprExit ); - m_LineScroller.AddChild( &m_Line[iRow] ); - - iRow++; + m_Line.back()->DeleteChildrenWhenDone(); + m_Line.back()->SetName( "Line" ); + ActorUtil::LoadAllCommands(m_Line.back(), m_sName); + m_LineScroller.AddChild(m_Line.back()); } +#define ADD_ACTION(index, a, b, c, d, e) \ + m_Line.push_back(new ActorFrame); \ + m_Actions[index].Load(a, b, c, d, e); + + m_Actions.resize(5); + ADD_ACTION(0, m_sName, "Clear", &ScreenMapControllers::ClearToDefault, + m_Line.back(), &m_LineScroller); + ADD_ACTION(1, m_sName, "Reload", &ScreenMapControllers::ReloadFromDisk, + m_Line.back(), &m_LineScroller); + ADD_ACTION(2, m_sName, "Save", &ScreenMapControllers::SaveToDisk, + m_Line.back(), &m_LineScroller); + ADD_ACTION(3, m_sName, "SetList", &ScreenMapControllers::SetListMode, + m_Line.back(), &m_LineScroller); + ADD_ACTION(4, m_sName, "Exit", &ScreenMapControllers::ExitAction, + m_Line.back(), &m_LineScroller); +#undef ADD_ACTION + + m_MaxDestItem= (1 + m_KeysToMap.size() + m_Actions.size()) - + THEME->GetMetricI("ScreenMapControllers", "LinesVisible"); + m_LineScroller.SetName( "LineScroller" ); ActorUtil::LoadAllCommands( m_LineScroller, m_sName ); m_LineScroller.SetNumItemsToDraw( (float) m_LineScroller.GetNumChildren()*2 ); m_LineScroller.Load2(); this->AddChild( &m_LineScroller ); + + m_NoSetListPrompt.Load(THEME->GetPathG(m_sName, "nosetlistprompt")); + m_NoSetListPrompt->SetName("NoSetListPrompt"); + this->AddChild(m_NoSetListPrompt); + + m_sprWarning.Load(THEME->GetPathG(m_sName, "warning")); + m_sprWarning->SetName("Warning"); + m_sprWarning->SetDrawOrder(DRAW_ORDER_TRANSITIONS); + this->AddChild(m_sprWarning); + LOAD_ALL_COMMANDS(m_sprWarning); } void ScreenMapControllers::BeginScreen() @@ -162,6 +220,10 @@ void ScreenMapControllers::BeginScreen() Refresh(); AfterChangeFocus(); + m_fLockInputSecs= THEME->GetMetricF(m_sName, "LockInputSecs"); + m_AutoDismissWarningSecs= THEME->GetMetricF(m_sName, "AutoDismissWarningSecs"); + m_AutoDismissNoSetListPromptSecs= 0.0f; + m_sprWarning->PlayCommand("TweenOn"); } @@ -169,34 +231,64 @@ void ScreenMapControllers::Update( float fDeltaTime ) { ScreenWithMenuElements::Update( fDeltaTime ); + if(m_fLockInputSecs <= 0.0f) + { + bool was_above= m_AutoDismissWarningSecs > 0.0f; + m_AutoDismissWarningSecs-= fDeltaTime; + if(was_above && m_AutoDismissWarningSecs <= 0.0f) + { + DismissWarning(); + } + } + if(m_AutoDismissNoSetListPromptSecs > 0.0f) + { + m_AutoDismissNoSetListPromptSecs-= fDeltaTime; + if(m_AutoDismissNoSetListPromptSecs <= 0.0f) + { + m_NoSetListPrompt->PlayCommand("TweenOff"); + } + } // // Update devices text // m_textDevices.SetText( INPUTMAN->GetDisplayDevicesString() ); - if( !m_WaitingForPress.IsZero() && m_DeviceIToMap.IsValid() ) // we're going to map an input { if( m_WaitingForPress.PeekDeltaTime() < g_fSecondsToWaitForInput ) return; /* keep waiting */ m_WaitingForPress.SetZero(); - ASSERT( m_iCurButton < (int) m_KeysToMap.size() ); - const KeyToMap *pKey = &m_KeysToMap[m_iCurButton]; + ASSERT(CursorOnKey()); + const KeyToMap *pKey = &m_KeysToMap[CurKeyIndex()]; GameInput curGameI( (GameController)m_iCurController, pKey->m_GameButton ); INPUTMAPPER->SetInputMap( m_DeviceIToMap, curGameI, m_iCurSlot ); INPUTMAPPER->AddDefaultMappingsForCurrentGameIfUnmapped(); - - // commit to disk after each change - INPUTMAPPER->SaveMappingsToDisk(); - - Refresh(); + m_ChangeOccurred= true; BitmapText *pText = pKey->m_textMappedTo[m_iCurController][m_iCurSlot]; - pText->PlayCommand( "MappedInput" ); + pText->PlayCommand("MappedInput"); + if(m_InSetListMode) + { + pText->PlayCommand("LoseMark"); + ++m_SetListCurrent; + if(m_SetListCurrent == m_SetList.end()) + { + m_InSetListMode= false; + m_SetList.clear(); + } + else + { + BeforeChangeFocus(); + SetCursorFromSetListCurrent(); + AfterChangeFocus(); + StartWaitingForPress(); + } + } + Refresh(); SCREENMAN->PlayStartSound(); } } @@ -230,16 +322,47 @@ static bool IsAxis( const DeviceInput& DeviceI ) bool ScreenMapControllers::Input( const InputEventPlus &input ) { - if( m_fLockInputSecs > 0 ) + if(m_fLockInputSecs > 0.0f) + { return false; + } + + if(m_AutoDismissWarningSecs > 0.0f) + { + if(input.type == IET_FIRST_PRESS && + input.DeviceI.device == DEVICE_KEYBOARD && + input.DeviceI.button == KEY_ENTER) + { + m_AutoDismissWarningSecs = 0.0f; + DismissWarning(); + } + return false; + } + + if(m_AutoDismissNoSetListPromptSecs > 0.0f) + { + if(input.type == IET_FIRST_PRESS && + input.DeviceI.device == DEVICE_KEYBOARD && + input.DeviceI.button == KEY_ENTER) + { + m_AutoDismissNoSetListPromptSecs = 0.0f; + m_NoSetListPrompt->PlayCommand("TweenOff"); + } + return false; + } if( input.type != IET_FIRST_PRESS && input.type != IET_REPEAT ) + { return false; // ignore + } if( IsTransitioning() ) + { return false; // ignore + } - LOG->Trace( "ScreenMapControllers::Input(): device: %d, button: %d", - input.DeviceI.device, input.DeviceI.button ); + // Whoever wants it can uncomment this log spew, I don't think it's necessary. -Kyz + // LOG->Trace( "ScreenMapControllers::Input(): device: %d, button: %d", + // input.DeviceI.device, input.DeviceI.button ); int button = input.DeviceI.button; bool bHandled = false; @@ -290,11 +413,12 @@ bool ScreenMapControllers::Input( const InputEventPlus &input ) case KEY_DEL: case KEY_SPACE: case KEY_BACK: // Clear the selected input mapping. - if( m_iCurButton == (int) m_KeysToMap.size() ) - break; // on exit - + if(!CursorOnKey()) { - const KeyToMap *pKey = &m_KeysToMap[m_iCurButton]; + break; + } + { + const KeyToMap *pKey = &m_KeysToMap[CurKeyIndex()]; GameInput curGameI( (GameController)m_iCurController, pKey->m_GameButton ); if( !INPUTMAPPER->ClearFromInputMap(curGameI, m_iCurSlot) ) break; @@ -302,17 +426,18 @@ bool ScreenMapControllers::Input( const InputEventPlus &input ) INPUTMAPPER->AddDefaultMappingsForCurrentGameIfUnmapped(); m_soundDelete.Play(); - - // commit to disk after each change - INPUTMAPPER->SaveMappingsToDisk(); bHandled = true; } break; case KEY_LEFT: // Move the selection left, wrapping up. - if( m_iCurButton == (int) m_KeysToMap.size() ) - break; // on exit + if(CursorOnAction()) + { + break; + } if( m_iCurSlot == 0 && m_iCurController == 0 ) + { break; // can't go left any more + } BeforeChangeFocus(); m_iCurSlot--; if( m_iCurSlot < 0 ) @@ -325,10 +450,14 @@ bool ScreenMapControllers::Input( const InputEventPlus &input ) bHandled = true; break; case KEY_RIGHT: // Move the selection right, wrapping down. - if( m_iCurButton == (int) m_KeysToMap.size() ) - break; // on exit + if(CursorOnAction()) + { + break; + } if( m_iCurSlot == NUM_CHANGABLE_SLOTS-1 && m_iCurController == NUM_GameController-1 ) + { break; // can't go right any more + } BeforeChangeFocus(); m_iCurSlot++; if( m_iCurSlot > NUM_CHANGABLE_SLOTS-1 ) @@ -341,8 +470,10 @@ bool ScreenMapControllers::Input( const InputEventPlus &input ) bHandled = true; break; case KEY_UP: // Move the selection up. - if( m_iCurButton == 0 ) - break; // can't go up any more + if(!CursorCanGoUp()) + { + break; + } BeforeChangeFocus(); m_iCurButton--; AfterChangeFocus(); @@ -350,8 +481,10 @@ bool ScreenMapControllers::Input( const InputEventPlus &input ) bHandled = true; break; case KEY_DOWN: // Move the selection down. - if( m_iCurButton == (int) m_KeysToMap.size() ) - break; // can't go down any more + if(!CursorCanGoDown()) + { + break; + } BeforeChangeFocus(); m_iCurButton++; AfterChangeFocus(); @@ -359,35 +492,50 @@ bool ScreenMapControllers::Input( const InputEventPlus &input ) bHandled = true; break; case KEY_ESC: // Quit the screen. - SCREENMAN->PlayStartSound(); - StartTransitioningScreen( SM_GoToNextScreen ); + ExitAction(); bHandled = true; break; + case KEY_Cm: + if(CursorOnKey()) + { + SetListEntry to_add(SetListEntry(CurKeyIndex(), m_iCurController, m_iCurSlot)); + set::iterator found= m_SetList.find(to_add); + if(found == m_SetList.end()) + { + m_SetList.insert(to_add); + GetActorWithFocus()->PlayCommand("GainMark"); + } + else + { + m_SetList.erase(found); + GetActorWithFocus()->PlayCommand("LoseMark"); + } + } + break; case KEY_ENTER: // Change the selection. case KEY_KP_ENTER: - if( m_iCurButton == (int) m_KeysToMap.size() ) + bHandled = true; + if(CursorOnAction()) { + (this->*m_Actions[CurActionIndex()].m_action)(); SCREENMAN->PlayStartSound(); - StartTransitioningScreen( SM_GoToNextScreen ); break; } - + if(CursorOnHeader()) { - const KeyToMap *pKey = &m_KeysToMap[m_iCurButton]; - BitmapText *pText = pKey->m_textMappedTo[m_iCurController][m_iCurSlot]; - pText->PlayCommand( "Waiting" ); + break; } - m_WaitingForPress.Touch(); - m_DeviceIToMap.MakeInvalid(); + StartWaitingForPress(); SCREENMAN->PlayStartSound(); - bHandled = true; break; } } // ScreenWithMenuElements::Input( input ); // default handler - LOG->Trace( "m_iCurSlot: %d m_iCurController: %d m_iCurButton: %d", m_iCurSlot, m_iCurController, m_iCurButton ); + // This trace is also useless log spew. Create a preference or something + // configurable if you disagree. -Kyz + // LOG->Trace( "m_iCurSlot: %d m_iCurController: %d m_iCurButton: %d", m_iCurSlot, m_iCurController, m_iCurButton ); Refresh(); return bHandled; @@ -395,10 +543,16 @@ bool ScreenMapControllers::Input( const InputEventPlus &input ) Actor *ScreenMapControllers::GetActorWithFocus() { - if( m_iCurButton == (int) m_KeysToMap.size() ) - return m_sprExit; + if(CursorOnAction()) + { + return m_Actions[CurActionIndex()].m_actor; + } + if(CursorOnHeader()) + { + return &(m_headerLabels[m_iCurController][m_iCurSlot]); + } - const KeyToMap *pKey = &m_KeysToMap[m_iCurButton]; + const KeyToMap *pKey = &m_KeysToMap[CurKeyIndex()]; return pKey->m_textMappedTo[m_iCurController][m_iCurSlot]; } @@ -434,7 +588,97 @@ void ScreenMapControllers::Refresh() } } - m_LineScroller.SetDestinationItem( (float) m_iCurButton ); + m_LineScroller.SetDestinationItem( + static_cast(min(m_iCurButton, m_MaxDestItem))); +} + +void ScreenMapControllers::DismissWarning() +{ + m_sprWarning->PlayCommand("TweenOff"); +} + +bool ScreenMapControllers::CursorOnAction() +{ + // We have a header row, the rows for the keys, and the action rows. + // So every row after m_KeysToMap.size is an action row. + return m_iCurButton >= static_cast(m_KeysToMap.size()+1); +} + +bool ScreenMapControllers::CursorOnHeader() +{ + // We have a header row before all others. + // So the header is at 0. + return m_iCurButton == 0; +} + +bool ScreenMapControllers::CursorOnKey() +{ + return !(CursorOnHeader() || CursorOnAction()); +} + +bool ScreenMapControllers::CursorCanGoUp() +{ + return m_iCurButton > 0; +} + +bool ScreenMapControllers::CursorCanGoDown() +{ + return m_iCurButton < m_KeysToMap.size() + m_Actions.size(); +} + +int ScreenMapControllers::CurKeyIndex() +{ + // The header row is at 0, so subtract 1 from m_iCurButton. + return m_iCurButton - 1; +} + +int ScreenMapControllers::CurActionIndex() +{ + // Subtract the header row and the keys. + return m_iCurButton - 1 - m_KeysToMap.size(); +} + +void ScreenMapControllers::SetCursorFromSetListCurrent() +{ + m_iCurButton= m_SetListCurrent->m_button + 1; + m_iCurController= m_SetListCurrent->m_controller; + m_iCurSlot= m_SetListCurrent->m_slot; +} + +void ScreenMapControllers::StartWaitingForPress() +{ + const KeyToMap *pKey = &m_KeysToMap[CurKeyIndex()]; + BitmapText *pText = pKey->m_textMappedTo[m_iCurController][m_iCurSlot]; + pText->PlayCommand( "Waiting" ); + m_WaitingForPress.Touch(); + m_DeviceIToMap.MakeInvalid(); +} + +void ScreenMapControllers::HandleScreenMessage(const ScreenMessage SM) +{ + if(SM == SM_DoSaveAndExit) + { + switch(ScreenPrompt::s_LastAnswer) + { + DEFAULT_FAIL(ScreenPrompt::s_LastAnswer); + case ANSWER_YES: + SaveToDisk(); + SCREENMAN->PlayStartSound(); + StartTransitioningScreen(SM_GoToNextScreen); + break; + case ANSWER_NO: + ReloadFromDisk(); + SCREENMAN->PlayStartSound(); + StartTransitioningScreen(SM_GoToNextScreen); + break; + case ANSWER_CANCEL: + break; + } + } + else + { + ScreenWithMenuElements::HandleScreenMessage(SM); + } } void ScreenMapControllers::HandleMessage( const Message &msg ) @@ -447,9 +691,78 @@ void ScreenMapControllers::HandleMessage( const Message &msg ) ScreenWithMenuElements::HandleMessage( msg ); } +void ScreenMapControllers::ClearToDefault() +{ + INPUTMAPPER->ResetMappingsToDefault(); +} + +void ScreenMapControllers::ReloadFromDisk() +{ + INPUTMAPPER->ReadMappingsFromDisk(); +} + +void ScreenMapControllers::SaveToDisk() +{ + INPUTMAPPER->SaveMappingsToDisk(); + m_ChangeOccurred= false; +} + +void ScreenMapControllers::SetListMode() +{ + if(m_SetList.size() < 1) + { + m_NoSetListPrompt->PlayCommand("TweenOn"); + m_AutoDismissNoSetListPromptSecs= THEME->GetMetricF(m_sName, "AutoDismissNoSetListPromptSecs"); + } + else + { + m_SetListCurrent= m_SetList.begin(); + m_InSetListMode= true; + BeforeChangeFocus(); + SetCursorFromSetListCurrent(); + AfterChangeFocus(); + StartWaitingForPress(); + } +} + +void ScreenMapControllers::ExitAction() +{ + if(m_ChangeOccurred) + { + ScreenPrompt::Prompt(SM_DoSaveAndExit, SAVE_PROMPT, PROMPT_YES_NO_CANCEL, + ANSWER_YES); + } + else + { + SCREENMAN->PlayStartSound(); + StartTransitioningScreen(SM_GoToNextScreen); + } +} + +void ScreenMapControllers::ActionRow::Load(RString const& scr_name, + RString const& name, ScreenMapControllers::action_fun_t action, + ActorFrame* line, ActorScroller* scroller) +{ + m_action= action; + RString lower_name= name; + lower_name.MakeLower(); + // Make the specific actor optional, use a fallback if it doesn't exist. + RString path= THEME->GetPathG(scr_name, lower_name, true); + if(path.empty()) + { + path= THEME->GetPathG(scr_name, "action"); + } + m_actor.Load(path); + m_actor->SetName(name); + ActorUtil::LoadAllCommands(*m_actor, scr_name); + line->AddChild(m_actor); + scroller->AddChild(line); +} + /* * (c) 2001-2005 Chris Danford, Glenn Maynard + * 2014 Eric Reese * All rights reserved. * * Permission is hereby granted, free of charge, to any person obtaining a diff --git a/src/ScreenMapControllers.h b/src/ScreenMapControllers.h index 5b36e933fe..ec83d89b2c 100644 --- a/src/ScreenMapControllers.h +++ b/src/ScreenMapControllers.h @@ -13,23 +13,38 @@ class ScreenMapControllers : public ScreenWithMenuElements { public: ScreenMapControllers(); + ~ScreenMapControllers(); virtual void Init(); virtual void BeginScreen(); virtual void Update( float fDeltaTime ); virtual bool Input( const InputEventPlus &input ); + virtual void HandleMessage( const Message &msg ); + virtual void HandleScreenMessage( const ScreenMessage SM ); private: - virtual void HandleMessage( const Message &msg ); Actor *GetActorWithFocus(); void BeforeChangeFocus(); void AfterChangeFocus(); void Refresh(); + void DismissWarning(); + bool CursorOnAction(); + bool CursorOnHeader(); + bool CursorOnKey(); + bool CursorCanGoUp(); + bool CursorCanGoDown(); + int CurKeyIndex(); + int CurActionIndex(); + void SetCursorFromSetListCurrent(); + void StartWaitingForPress(); int m_iCurController; int m_iCurButton; int m_iCurSlot; + int m_MaxDestItem; + + bool m_ChangeOccurred; RageTimer m_WaitingForPress; DeviceInput m_DeviceIToMap; @@ -46,10 +61,58 @@ private: BitmapText m_textDevices; BitmapText m_textLabel[NUM_GameController]; + BitmapText m_headerCenter; + BitmapText m_headerLabels[NUM_GameController][NUM_SHOWN_GAME_TO_DEVICE_SLOTS]; - AutoActor m_sprExit; + float m_AutoDismissWarningSecs; + AutoActor m_sprWarning; - ActorFrame m_Line[NUM_GameButton+2]; // label, normal lines, exit + float m_AutoDismissNoSetListPromptSecs; + AutoActor m_NoSetListPrompt; + + struct SetListEntry + { + int m_button; + int m_controller; + int m_slot; + SetListEntry(int b, int c, int s) + :m_button(b), m_controller(c), m_slot(s) {} + bool operator<(SetListEntry const& rhs) const + { + if(m_controller != rhs.m_controller) + { + return m_controller < rhs.m_controller; + } + if(m_button != rhs.m_button) + { + return m_button < rhs.m_button; + } + return m_slot < rhs.m_slot; + } + }; + set m_SetList; + set::iterator m_SetListCurrent; + bool m_InSetListMode; + + typedef void (ScreenMapControllers::* action_fun_t)(); + struct ActionRow + { + RString m_name; + AutoActor m_actor; + action_fun_t m_action; + void Load(RString const& scr_name, RString const& name, + ScreenMapControllers::action_fun_t action, ActorFrame* line, + ActorScroller* scroller); + }; + void ClearToDefault(); + void ReloadFromDisk(); + void SaveToDisk(); + void SetListMode(); + void ExitAction(); + + vector m_Actions; + + vector m_Line; ActorScroller m_LineScroller; RageSound m_soundChange; @@ -60,6 +123,7 @@ private: /* * (c) 2001-2004 Chris Danford + * 2014 Eric Reese * All rights reserved. * * Permission is hereby granted, free of charge, to any person obtaining a diff --git a/src/ScreenMapControllers2.cpp b/src/ScreenMapControllers2.cpp deleted file mode 100644 index 2d85c68840..0000000000 --- a/src/ScreenMapControllers2.cpp +++ /dev/null @@ -1,532 +0,0 @@ -#include "global.h" -#include "ScreenMapControllers2.h" -#include "ScreenManager.h" -#include "RageLog.h" -#include "GameState.h" -#include "RageInput.h" -#include "InputMapper.h" -#include "ThemeManager.h" -#include "ScreenDimensions.h" -#include "InputEventPlus.h" -#include "LocalizedString.h" -#include "Foreach.h" -#include "LuaBinding.h" - -static const float g_fSecondsToWaitForInput = 0.05f; - -static const char *MapControlsStateNames[] = { - "SelectingButton", - "EditingMappings" -}; -XToString( MapControlsState ); -LuaXType( MapControlsState ); - -REGISTER_SCREEN_CLASS( ScreenMapControllers2 ); - -ScreenMapControllers2::ScreenMapControllers2() -{ - this->SubscribeToMessage( Message_AutoJoyMappingApplied ); - m_MapControlsState = MCS_Button; - m_EditingButton = GAME_BUTTON_MENULEFT; - ZERO( m_iMappingChoice ); - ZERO( m_iNumMappingRows ); -} - -static LocalizedString ADD_MAPPING( "ScreenMapControllers2", "Add Mapping" ); -void ScreenMapControllers2::Init() -{ - ScreenWithMenuElements::Init(); - - // load sounds - m_soundChange.Load( THEME->GetPathS(m_sName,"change"), true ); - m_soundDelete.Load( THEME->GetPathS(m_sName,"delete"), true ); - - // set devices text - m_textDevices.LoadFromFont( THEME->GetPathF(m_sName,"devices") ); - m_textDevices.SetName( "Devices" ); - LOAD_ALL_COMMANDS_AND_SET_XY( m_textDevices ); - this->AddChild( &m_textDevices ); - - // button input scroller - WRAP_INPUT_SCROLLER.Load( m_sName, "WrapInputScroller" ); - LOOP_INPUT_SCROLLER.Load( m_sName, "LoopInputScroller" ); - INPUT_SCROLLER_SECONDS_PER_ITEM.Load( m_sName, "InputScrollerSecondsPerItem" ); - INPUT_SCROLLER_NUM_ITEMS_TO_DRAW.Load( m_sName, "InputScrollerNumItemsToDraw" ); - INPUT_SCROLLER_TRANSFORM.Load( m_sName, "InputScrollerTransform" ); - INPUT_SCROLLER_SUBDIVISIONS.Load( m_sName, "InputScrollerSubdivisions" ); - - // map all buttons for this game. (todo: re-add BUTTONS_TO_MAP support?) - FOREACH_GameButtonInScheme( INPUTMAPPER->GetInputScheme(), gb ) - { - KeyToMap k; - k.m_GameButton = gb; - m_KeysToMap.push_back( k ); - } - - // input button names - int iRow = 0; - for( unsigned b=0; bSetName( "ButtonName" ); - pName->LoadFromFont( THEME->GetPathF(m_sName,"ButtonName") ); - RString sText = GameButtonToLocalizedString( INPUTMAPPER->GetInputScheme(), pKey->m_GameButton ); - pName->SetText( sText ); - ActorUtil::LoadAllCommands( *pName, m_sName ); - pName->PlayCommand( b == (unsigned)m_iInputChoice ? "GainFocus" : "LoseFocus" ); - m_InputLine[iRow].AddChild( pName ); - } - - m_InputLine[iRow].DeleteChildrenWhenDone(); - m_InputLine[iRow].SetName( "InputLine" ); - ActorUtil::LoadAllCommands( m_InputLine[iRow], m_sName ); - m_InputScroller.AddChild( &m_InputLine[iRow] ); - - iRow++; - } - - m_InputScroller.SetName( "InputScroller" ); - LOAD_ALL_COMMANDS_AND_SET_XY( m_InputScroller ); - m_InputScroller.SetLoop( LOOP_INPUT_SCROLLER ); - m_InputScroller.SetNumItemsToDraw( INPUT_SCROLLER_NUM_ITEMS_TO_DRAW ); - m_InputScroller.Load2(); - m_InputScroller.SetTransformFromReference( INPUT_SCROLLER_TRANSFORM ); - m_InputScroller.SetSecondsPerItem( INPUT_SCROLLER_SECONDS_PER_ITEM ); - m_InputScroller.SetNumSubdivisions( INPUT_SCROLLER_SUBDIVISIONS ); - this->AddChild( &m_InputScroller ); - - // set player scrollers: - vector vpns; - FOREACH_PlayerNumber( p ) - vpns.push_back( p ); - - // per-player mappings - WRAP_MAPPING_SCROLLER.Load( m_sName, "WrapMappingScroller" ); - LOOP_MAPPING_SCROLLER.Load( m_sName, "LoopMappingScroller" ); - MAPPING_SCROLLER_SECONDS_PER_ITEM.Load( m_sName, "MappingScrollerSecondsPerItem" ); - MAPPING_SCROLLER_NUM_ITEMS_TO_DRAW.Load( m_sName, "MappingScrollerNumItemsToDraw" ); - MAPPING_SCROLLER_TRANSFORM.Load( m_sName, "MappingScrollerTransform" ); - MAPPING_SCROLLER_SUBDIVISIONS.Load( m_sName, "MappingScrollerSubdivisions" ); - - FOREACH( PlayerNumber, vpns, p ) - { - // mapping scroller - m_MappingScroller[*p].SetLoop( LOOP_MAPPING_SCROLLER ); - m_MappingScroller[*p].SetNumItemsToDraw( MAPPING_SCROLLER_NUM_ITEMS_TO_DRAW ); - m_MappingScroller[*p].Load2(); - m_MappingScroller[*p].SetTransformFromReference( MAPPING_SCROLLER_TRANSFORM ); - m_MappingScroller[*p].SetSecondsPerItem( MAPPING_SCROLLER_SECONDS_PER_ITEM ); - m_MappingScroller[*p].SetNumSubdivisions( MAPPING_SCROLLER_SUBDIVISIONS ); - m_MappingScroller[*p].SetName( "MappingScroller"+ssprintf("P%d",(*p)+1) ); - LOAD_ALL_COMMANDS_AND_SET_XY( m_MappingScroller[*p] ); - this->AddChild( &m_MappingScroller[*p] ); - } -} - -void ScreenMapControllers2::BeginScreen() -{ - m_iInputChoice = 0; - m_ActivePlayerMapping = PLAYER_1; - - ScreenWithMenuElements::BeginScreen(); - - m_WaitingForPress.SetZero(); - - Refresh(); -} - -void ScreenMapControllers2::Update( float fDeltaTime ) -{ - ScreenWithMenuElements::Update( fDeltaTime ); - - // Update devices text - m_textDevices.SetText( INPUTMAN->GetDisplayDevicesString() ); - - if( !m_WaitingForPress.IsZero() && m_DeviceIToMap.IsValid() ) - { - // we're going to map an input - if( m_WaitingForPress.PeekDeltaTime() < g_fSecondsToWaitForInput ) - return; // keep waiting - m_WaitingForPress.SetZero(); - - /* do stuff here */ - //ASSERT( m_iCurButton < (int) m_KeysToMap.size() ); - //const KeyToMap *pKey = &m_KeysToMap[m_iCurButton]; - //GameInput curGameI( (GameController)m_iCurController, pKey->m_GameButton ); - //INPUTMAPPER->SetInputMap( m_DeviceIToMap, curGameI, m_iCurSlot ); - //INPUTMAPPER->AddDefaultMappingsForCurrentGameIfUnmapped(); - - // commit to disk after each change - //INPUTMAPPER->SaveMappingsToDisk(); - - Refresh(); - - /* - BitmapText *pText = pKey->m_textMappedTo[m_iCurController][m_iCurSlot]; - pText->PlayCommand( "MappedInput" ); - */ - SCREENMAN->PlayStartSound(); - } -} - - -/* Note that this isn't necessarily correct. For example, JOY_LEFT might - * actually be a D-pad and not an axis. All this is actually doing is giving - * priority to some inputs over others; this function is unsuitable for other use. */ -static bool IsAxis( const DeviceInput& DeviceI ) -{ - if( !DeviceI.IsJoystick() ) - return false; - - static int axes[] = - { - JOY_LEFT, JOY_RIGHT, JOY_UP, JOY_DOWN, - JOY_LEFT_2, JOY_RIGHT_2, JOY_UP_2, JOY_DOWN_2, - JOY_Z_UP, JOY_Z_DOWN, - JOY_ROT_UP, JOY_ROT_DOWN, JOY_ROT_LEFT, JOY_ROT_RIGHT, JOY_ROT_Z_UP, JOY_ROT_Z_DOWN, - JOY_HAT_LEFT, JOY_HAT_RIGHT, JOY_HAT_UP, JOY_HAT_DOWN, - JOY_AUX_1, JOY_AUX_2, JOY_AUX_3, JOY_AUX_4, - -1 - }; - - for( int ax = 0; axes[ax] != -1; ++ax ) - if( DeviceI.button == axes[ax] ) - return true; - - return false; -} - -void ScreenMapControllers2::ChangeActivePlayer() -{ - m_ActivePlayerMapping = (m_ActivePlayerMapping == PLAYER_1) ? PLAYER_2 : PLAYER_1; - Message msg("ActivePlayerChanged"); - msg.SetParam("NewActivePlayer",m_ActivePlayerMapping); - MESSAGEMAN->Broadcast(msg); -} - -void ScreenMapControllers2::Input( const InputEventPlus &input ) -{ - if( input.type != IET_FIRST_PRESS && input.type != IET_REPEAT ) - return; // ignore - if( IsTransitioning() ) - return; // ignore - - LOG->Trace( "ScreenMapControllers2::Input(): device: %d, button: %d", - input.DeviceI.device, input.DeviceI.button ); - - int button = input.DeviceI.button; - - /* TRICKY: Some adapters map the PlayStation digital d-pad to both axes and - * buttons. We want buttons to be used for any mappings where possible - * because presses of buttons aren't mutually exclusive and presses of axes - * are (e.g. can't read presses of both Left and Right simultaneously). So, - * when the user presses a button, we'll wait until the next Update before - * adding a mapping so that we get a chance to see all input events the - * user's press of a panel. Prefer non-axis events over axis events. */ - if( !m_WaitingForPress.IsZero() ) - { - if( input.type != IET_FIRST_PRESS ) - return; - - // Don't allow function keys to be mapped. - if( input.DeviceI.device == DEVICE_KEYBOARD && (input.DeviceI.button >= KEY_F1 && input.DeviceI.button <= KEY_F12) ) - { - SCREENMAN->SystemMessage( "INVALID_BUTTON" ); - SCREENMAN->PlayInvalidSound(); - } - else - { - if( m_DeviceIToMap.IsValid() && - !IsAxis(m_DeviceIToMap) && - IsAxis(input.DeviceI) ) - { - LOG->Trace("Ignored input; non-axis event already received"); - return; // ignore this press - } - - m_DeviceIToMap = input.DeviceI; - } - } - else if( input.DeviceI.device == DEVICE_KEYBOARD ) - { - switch( button ) - { - // todo: m_MapControlsState checks - case KEY_UP: // mapping list up - { - if( m_MapControlsState == MCS_EditMappings ) - { - if( m_iMappingChoice[m_ActivePlayerMapping] == 0 ) - break; - m_iMappingChoice[m_ActivePlayerMapping]--; - } - } - break; - case KEY_DOWN: // mapping list down - { - if( m_MapControlsState == MCS_EditMappings ) - { - if( m_iMappingChoice[m_ActivePlayerMapping] == m_iNumMappingRows[m_ActivePlayerMapping] ) - break; - m_iMappingChoice[m_ActivePlayerMapping]++; - } - } - break; - case KEY_LEFT: // on P2, changing to P1 - { - if( m_MapControlsState == MCS_EditMappings ) - { - if(m_ActivePlayerMapping == PLAYER_2) - ChangeActivePlayer(); - } - } - break; - case KEY_RIGHT: // on P1, changing to P2 - { - if( m_MapControlsState == MCS_EditMappings ) - { - if(m_ActivePlayerMapping == PLAYER_1) - ChangeActivePlayer(); - } - } - break; - case KEY_DEL: - case KEY_BACK: - if( m_MapControlsState == MCS_EditMappings ) - { - // clear mapping - /* - if( m_iMappingChoice[m_ActivePlayerMapping] == m_iNumMappingRows[m_ActivePlayerMapping] ) - break; // on "add" - - { - // stuff - - m_soundDelete.Play(); - - // commit to disk after each change - INPUTMAPPER->SaveMappingsToDisk(); - } - */ - } - break; - case KEY_ESC: - { - if(m_MapControlsState == MCS_EditMappings) - { - // xxx: make sure it's not getting a button. - m_MapControlsState = MCS_Button; - SCREENMAN->PlayCancelSound(); - } - else - { - // Quit the screen. - SCREENMAN->PlayStartSound(); - StartTransitioningScreen( SM_GoToNextScreen ); - } - } - break; - case KEY_ENTER: - case KEY_KP_ENTER: - { - if( m_MapControlsState == MCS_EditMappings ) - { - // map button - LOG->Trace("got an enter press..."); - LOG->Trace( ssprintf("current choice: %i",m_iMappingChoice[m_ActivePlayerMapping]) ); - if( m_iMappingChoice[m_ActivePlayerMapping] == m_iNumMappingRows[m_ActivePlayerMapping] ) - { - // add - LOG->Trace("Adding a new mapping"); - } - else - { - // replace - LOG->Trace("Replacing an existing mapping"); - } - /* - m_WaitingForPress.Touch(); - m_DeviceIToMap.MakeInvalid(); - SCREENMAN->PlayStartSound(); - */ - } - } - break; - } - } - - ScreenWithMenuElements::Input( input ); // default handler - - Refresh(); -} - -void ScreenMapControllers2::Refresh() -{ - // update mapping scrollers - UpdateMappingScrollers(); -} - -void ScreenMapControllers2::HandleMessage( const Message &msg ) -{ - if( msg == Message_AutoJoyMappingApplied ) - { - Refresh(); - } - - ScreenWithMenuElements::HandleMessage( msg ); -} - -void ScreenMapControllers2::MenuStart( const InputEventPlus &input ) -{ - // MCS_EditMappings is handled in Input() above. - if( m_MapControlsState == MCS_Button ) - { - m_MapControlsState = MCS_EditMappings; - } -} - -void ScreenMapControllers2::UpdateMappingScrollers() -{ - FOREACH_ENUM( GameController, c ) - { - PlayerNumber pn = (PlayerNumber)c; - m_MappingScroller[pn].RemoveAllChildren(); - - int iLast = 0; - for(unsigned s = 0; s < NUM_SHOWN_GAME_TO_DEVICE_SLOTS; s++) - { - GameInput cur_gi( c, m_EditingButton ); - DeviceInput di; - RString sInput = ""; - if( INPUTMAPPER->GameToDevice( cur_gi, s, di ) ) - sInput = INPUTMAN->GetDeviceSpecificInputString(di); - - if( sInput != "" ) - { - m_MappingLine[iLast].RemoveAllChildren(); - // we have an input, add to the scroller - BitmapText *pText = new BitmapText; - pText->SetName( "MappedTo"+PlayerNumberToString(pn) ); - pText->LoadFromFont( THEME->GetPathF(m_sName,"Mapping") ); - ActorUtil::LoadAllCommands(pText,m_sName); - pText->PlayCommand( ((unsigned)m_iMappingChoice[pn] == s) ? "GainFocus" : "LoseFocus" ); - pText->SetText( sInput ); - - m_MappingLine[iLast].AddChild( pText ); - m_MappingLine[iLast].DeleteChildrenWhenDone(); - m_MappingLine[iLast].SetName("MappingLine"); - ActorUtil::LoadAllCommands(m_MappingLine[iLast],m_sName); - m_MappingScroller[pn].AddChild( &m_MappingLine[iLast] ); - iLast++; - } - } - - BitmapText &text = m_textAddMapping[pn]; - text.LoadFromFont( THEME->GetPathF(m_sName,"AddMapping") ); - text.SetName( "AddMapping"+PlayerNumberToString(pn) ); - ActorUtil::LoadAllCommands( text, m_sName ); - text.PlayCommand( (m_iMappingChoice[pn] == m_iNumMappingRows[pn]) ? "GainFocus" : "LoseFocus" ); - text.SetText( ADD_MAPPING ); - m_MappingScroller[pn].AddChild( &m_textAddMapping[c] ); - iLast++; - - m_iNumMappingRows[pn] = iLast; - - m_MappingScroller[pn].Load2(); - m_MappingScroller[pn].SetTransformFromReference( MAPPING_SCROLLER_TRANSFORM ); - m_MappingScroller[pn].SetCurrentAndDestinationItem( (float)m_iMappingChoice[pn] ); - } -} - -// change game/system button scroller selection -void ScreenMapControllers2::ChangeInputSelection(int iDir) -{ - m_InputLine[m_iInputChoice].PlayCommand("LoseFocus"); - m_iInputChoice += iDir; - m_soundChange.Play(); - m_InputLine[m_iInputChoice].PlayCommand("GainFocus"); - - // set scroller - m_InputScroller.SetCurrentAndDestinationItem( (float)m_iInputChoice ); - - // set current game button - KeyToMap *pKey = &m_KeysToMap[m_iInputChoice]; - m_EditingButton = pKey->m_GameButton; -} - -void ScreenMapControllers2::MenuUp( const InputEventPlus &input ) -{ - if( m_MapControlsState == MCS_Button ) - { - if( m_iInputChoice == 0 ) // limit - return; - ChangeInputSelection(-1); - } -} - -void ScreenMapControllers2::MenuDown( const InputEventPlus &input ) -{ - if( m_MapControlsState == MCS_Button ) - { - if( m_iInputChoice == (int)m_KeysToMap.size()-1 ) // limit - return; - ChangeInputSelection(1); - } -} - -void ScreenMapControllers2::TweenOnScreen() -{ - ScreenWithMenuElements::TweenOnScreen(); - - m_InputScroller.SetCurrentAndDestinationItem( (float)m_iInputChoice ); -} - -// lua start -#include "LuaBinding.h" - -/** @brief Allow Lua to have access to ScreenMapControllers2. */ -class LunaScreenMapControllers2: public Luna -{ -public: - //static int MapControlsState( T* p, lua_State *L ) // - //static int GetEditingGameButton( T* p, lua_State *L ) // GetEditingGameButton() - DEFINE_METHOD( GetInputIndex, GetInputIndex() ); - DEFINE_METHOD( GetNumInputs, GetNumInputs() ); - LunaScreenMapControllers2() - { - //ADD_METHOD( GetEditingGameButton ); - ADD_METHOD( GetInputIndex ); - ADD_METHOD( GetNumInputs ); - //ADD_METHOD( MapControlsState ); - } -}; - -LUA_REGISTER_DERIVED_CLASS( ScreenMapControllers2, ScreenWithMenuElements ) - - -/* - * (c) 2011 AJ Kelly - * All rights reserved. - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the - * "Software"), to deal in the Software without restriction, including - * without limitation the rights to use, copy, modify, merge, publish, - * distribute, and/or sell copies of the Software, and to permit persons to - * whom the Software is furnished to do so, provided that the above - * copyright notice(s) and this permission notice appear in all copies of - * the Software and that both the above copyright notice(s) and this - * permission notice appear in supporting documentation. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS - * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF - * THIRD PARTY RIGHTS. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR HOLDERS - * INCLUDED IN THIS NOTICE BE LIABLE FOR ANY CLAIM, OR ANY SPECIAL INDIRECT - * OR CONSEQUENTIAL DAMAGES, OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS - * OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR - * OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR - * PERFORMANCE OF THIS SOFTWARE. - */ diff --git a/src/ScreenMapControllers2.h b/src/ScreenMapControllers2.h deleted file mode 100644 index 87c76a1c74..0000000000 --- a/src/ScreenMapControllers2.h +++ /dev/null @@ -1,136 +0,0 @@ -/* ScreenMapControllers2 - Maps device input to game buttons. */ - -#ifndef SCREEN_MAP_CONTROLLERS2_H -#define SCREEN_MAP_CONTROLLERS2_H - -#include "ScreenWithMenuElements.h" -#include "BitmapText.h" -#include "InputMapper.h" -#include "ActorScroller.h" -#include "RageSound.h" -#include "EnumHelper.h" -#include "ThemeMetric.h" - -/* old inputmapper consts: -const int NUM_GAME_TO_DEVICE_SLOTS = 5; // five device inputs may map to one game input -const int NUM_SHOWN_GAME_TO_DEVICE_SLOTS = 3; -const int NUM_USER_GAME_TO_DEVICE_SLOTS = 2; -*/ -const int MAPPING_LINE = NUM_SHOWN_GAME_TO_DEVICE_SLOTS+1; // +1 for "Add Mapping" - -enum MapControlsState -{ - MCS_Button, // which button to edit mappings for - MCS_EditMappings, // player is editing mappings - NUM_MapControlsState, - MapControlsState_Invalid -}; -const RString& MapControlsStateToString( MapControlsState mct ); -LuaDeclareType( MapControlsState ); - -class ScreenMapControllers2 : public ScreenWithMenuElements -{ -public: - ScreenMapControllers2(); - virtual void Init(); - virtual void BeginScreen(); - //virtual void EndScreen(); - - virtual void Update( float fDeltaTime ); - virtual bool Input( const InputEventPlus &input ); - - virtual bool MenuUp( const InputEventPlus &input ); - virtual bool MenuDown( const InputEventPlus &input ); - virtual bool MenuStart( const InputEventPlus &input ); - virtual void TweenOnScreen(); - - MapControlsState GetMapControlsState(){ return m_MapControlsState; } - GameButton GetEditingGameButton() { return m_EditingButton; } - int GetInputIndex(){ return m_iInputChoice; } - int GetNumInputs(){ return m_KeysToMap.size(); } - int GetMappingIndex(PlayerNumber pn){ return m_iMappingChoice[pn]; } - - // Lua - virtual void PushSelf( lua_State *L ); - -protected: - virtual void HandleMessage( const Message &msg ); - - void ChangeActivePlayer(); - void ChangeInputSelection(int iDir); - void UpdateMappingScrollers(); - void Refresh(); - - MapControlsState m_MapControlsState; - RageTimer m_WaitingForPress; - DeviceInput m_DeviceIToMap; - - struct KeyToMap - { - GameButton m_GameButton; - BitmapText* m_textLabel; - }; - vector m_KeysToMap; - - BitmapText m_textDevices; - //vector m_textMappingLabels[NUM_PLAYERS]; - BitmapText m_textAddMapping[NUM_PLAYERS]; - - // possible inputs - int m_iInputChoice; - ActorScroller m_InputScroller; - ActorFrame m_InputLine[NUM_GameButton]; - ThemeMetric WRAP_INPUT_SCROLLER; - ThemeMetric LOOP_INPUT_SCROLLER; - ThemeMetric INPUT_SCROLLER_SECONDS_PER_ITEM; - ThemeMetric INPUT_SCROLLER_NUM_ITEMS_TO_DRAW; - ThemeMetric INPUT_SCROLLER_TRANSFORM; - ThemeMetric INPUT_SCROLLER_SUBDIVISIONS; - - // per-player button mappings. - GameButton m_EditingButton; - PlayerNumber m_ActivePlayerMapping; - int m_iMappingChoice[NUM_PLAYERS]; - int m_iNumMappingRows[NUM_PLAYERS]; - ActorScroller m_MappingScroller[NUM_PLAYERS]; - ActorFrame m_MappingLine[MAPPING_LINE]; - ThemeMetric WRAP_MAPPING_SCROLLER; - ThemeMetric LOOP_MAPPING_SCROLLER; - ThemeMetric MAPPING_SCROLLER_SECONDS_PER_ITEM; - ThemeMetric MAPPING_SCROLLER_NUM_ITEMS_TO_DRAW; - ThemeMetric MAPPING_SCROLLER_TRANSFORM; - ThemeMetric MAPPING_SCROLLER_SUBDIVISIONS; - - // should be handled in lua - //BitmapText m_textLabel[NUM_GameController]; - - RageSound m_soundChange; - RageSound m_soundDelete; -}; - -#endif - -/* - * (c) 2011 AJ Kelly - * All rights reserved. - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the - * "Software"), to deal in the Software without restriction, including - * without limitation the rights to use, copy, modify, merge, publish, - * distribute, and/or sell copies of the Software, and to permit persons to - * whom the Software is furnished to do so, provided that the above - * copyright notice(s) and this permission notice appear in all copies of - * the Software and that both the above copyright notice(s) and this - * permission notice appear in supporting documentation. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS - * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF - * THIRD PARTY RIGHTS. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR HOLDERS - * INCLUDED IN THIS NOTICE BE LIABLE FOR ANY CLAIM, OR ANY SPECIAL INDIRECT - * OR CONSEQUENTIAL DAMAGES, OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS - * OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR - * OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR - * PERFORMANCE OF THIS SOFTWARE. - */