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.
This commit is contained in:
Kyzentun
2014-09-04 01:23:28 -06:00
parent e3f8d272c1
commit f2fdaa0cf5
17 changed files with 574 additions and 815 deletions
+1 -1
View File
@@ -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.
}
+4 -1
View File
@@ -6,7 +6,10 @@
void AutoActor::Unload()
{
delete m_pActor;
if(m_pActor != NULL)
{
delete m_pActor;
}
m_pActor=NULL;
}
+20 -27
View File
@@ -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
+7
View File
@@ -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." );
+1
View File
@@ -150,6 +150,7 @@ public:
void ReadMappingsFromDisk();
void SaveMappingsToDisk();
void ResetMappingsToDefault();
void ClearAllMappings();
+386 -73
View File
@@ -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; b<m_KeysToMap.size(); b++ )
{
m_Line.push_back(new ActorFrame);
KeyToMap *pKey = &m_KeysToMap[b];
{
@@ -96,7 +138,7 @@ void ScreenMapControllers::Init()
RString sText = GameButtonToLocalizedString( INPUTMAPPER->GetInputScheme(), 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; s<NUM_SHOWN_GAME_TO_DEVICE_SLOTS; s++ )
{
pKey->m_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<SetListEntry>::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<float>(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<int>(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
+67 -3
View File
@@ -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<SetListEntry> m_SetList;
set<SetListEntry>::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<ActionRow> m_Actions;
vector<ActorFrame*> 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
-532
View File
@@ -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; b<m_KeysToMap.size(); b++ )
{
KeyToMap *pKey = &m_KeysToMap[b];
{
BitmapText *pName = new BitmapText;
pName->SetName( "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<PlayerNumber> 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<ScreenMapControllers2>
{
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.
*/
-136
View File
@@ -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<KeyToMap> m_KeysToMap;
BitmapText m_textDevices;
//vector<BitmapText> m_textMappingLabels[NUM_PLAYERS];
BitmapText m_textAddMapping[NUM_PLAYERS];
// possible inputs
int m_iInputChoice;
ActorScroller m_InputScroller;
ActorFrame m_InputLine[NUM_GameButton];
ThemeMetric<bool> WRAP_INPUT_SCROLLER;
ThemeMetric<bool> LOOP_INPUT_SCROLLER;
ThemeMetric<float> INPUT_SCROLLER_SECONDS_PER_ITEM;
ThemeMetric<float> INPUT_SCROLLER_NUM_ITEMS_TO_DRAW;
ThemeMetric<LuaReference> INPUT_SCROLLER_TRANSFORM;
ThemeMetric<int> 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<bool> WRAP_MAPPING_SCROLLER;
ThemeMetric<bool> LOOP_MAPPING_SCROLLER;
ThemeMetric<float> MAPPING_SCROLLER_SECONDS_PER_ITEM;
ThemeMetric<float> MAPPING_SCROLLER_NUM_ITEMS_TO_DRAW;
ThemeMetric<LuaReference> MAPPING_SCROLLER_TRANSFORM;
ThemeMetric<int> 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.
*/