2013-08-16 14:48:43 +00:00
// Copyright (c) 2013- PPSSPP Project.
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, version 2.0 or later versions.
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License 2.0 for more details.
// A copy of the GPL 2.0 should have been included with the program.
// If not, see http://www.gnu.org/licenses/
// Official git repository and contact information can be found at
// https://github.com/hrydgard/ppsspp and http://www.ppsspp.org/.
2021-03-03 04:42:55 +00:00
# include "ppsspp_config.h"
2014-09-05 21:21:07 +00:00
# include <algorithm>
# include <deque>
2017-02-27 20:57:46 +00:00
# include <mutex>
2021-08-28 20:57:22 +00:00
# include <unordered_map>
2014-09-05 21:21:07 +00:00
2020-10-04 21:24:14 +00:00
# include "Common/Render/TextureAtlas.h"
2020-10-04 18:48:47 +00:00
# include "Common/UI/Root.h"
# include "Common/UI/UI.h"
# include "Common/UI/Context.h"
# include "Common/UI/View.h"
# include "Common/UI/ViewGroup.h"
2022-11-17 11:19:17 +00:00
# include "Common/VR/PPSSPPVR.h"
2013-08-16 14:48:43 +00:00
2020-10-04 08:30:18 +00:00
# include "Common/Log.h"
2020-10-01 11:05:04 +00:00
# include "Common/Data/Color/RGBAUtil.h"
# include "Common/Data/Text/I18n.h"
# include "Common/Input/KeyCodes.h"
# include "Common/Input/InputState.h"
2021-08-29 23:43:15 +00:00
# include "Common/StringUtils.h"
2020-10-04 08:30:18 +00:00
# include "Common/System/Display.h"
# include "Common/System/System.h"
2023-03-22 21:17:53 +00:00
# include "Common/System/Request.h"
2021-10-08 01:45:15 +00:00
# include "Common/TimeUtil.h"
2020-10-03 22:25:21 +00:00
# include "Core/KeyMap.h"
2013-08-16 14:48:43 +00:00
# include "Core/HLE/sceCtrl.h"
2013-09-07 15:29:44 +00:00
# include "Core/System.h"
2013-08-16 14:48:43 +00:00
# include "Core/Config.h"
# include "UI/ControlMappingScreen.h"
2013-09-24 17:37:25 +00:00
# include "UI/GameSettingsScreen.h"
2023-02-01 13:58:16 +00:00
# include "UI/JoystickHistoryView.h"
2023-07-07 13:23:19 +00:00
# include "UI/OnScreenDisplay.h"
2013-08-16 14:48:43 +00:00
2021-10-10 09:49:53 +00:00
# if PPSSPP_PLATFORM(ANDROID)
# include "android/jni/app-android.h"
# endif
2023-03-31 22:12:14 +00:00
using KeyMap : : MultiInputMapping ;
2021-07-08 22:05:47 +00:00
class SingleControlMapper : public UI : : LinearLayout {
2013-08-17 08:34:38 +00:00
public :
2021-08-29 23:59:55 +00:00
SingleControlMapper ( int pspKey , std : : string keyName , ScreenManager * scrm , UI : : LinearLayoutParams * layoutParams = nullptr ) ;
2013-08-17 08:34:38 +00:00
2014-06-08 13:38:13 +00:00
int GetPspKey ( ) const { return pspKey_ ; }
2021-08-30 00:14:08 +00:00
2013-08-17 08:34:38 +00:00
private :
void Refresh ( ) ;
UI : : EventReturn OnAdd ( UI : : EventParams & params ) ;
2017-04-27 08:09:57 +00:00
UI : : EventReturn OnAddMouse ( UI : : EventParams & params ) ;
2013-08-17 08:34:38 +00:00
UI : : EventReturn OnDelete ( UI : : EventParams & params ) ;
UI : : EventReturn OnReplace ( UI : : EventParams & params ) ;
UI : : EventReturn OnReplaceAll ( UI : : EventParams & params ) ;
2024-10-10 09:55:07 +00:00
void MappedCallback ( const MultiInputMapping & kdf ) ;
2013-08-17 08:34:38 +00:00
enum Action {
NONE ,
REPLACEONE ,
REPLACEALL ,
ADD ,
} ;
2021-08-29 23:59:55 +00:00
UI : : Choice * addButton_ = nullptr ;
UI : : Choice * replaceAllButton_ = nullptr ;
std : : vector < UI : : View * > rows_ ;
Action action_ = NONE ;
2024-10-10 09:55:07 +00:00
int actionIndex_ = 0 ;
2013-08-17 08:34:38 +00:00
int pspKey_ ;
std : : string keyName_ ;
ScreenManager * scrm_ ;
} ;
2021-08-29 23:59:55 +00:00
SingleControlMapper : : SingleControlMapper ( int pspKey , std : : string keyName , ScreenManager * scrm , UI : : LinearLayoutParams * layoutParams )
: UI : : LinearLayout ( UI : : ORIENT_VERTICAL , layoutParams ) , pspKey_ ( pspKey ) , keyName_ ( keyName ) , scrm_ ( scrm ) {
2013-08-17 08:34:38 +00:00
Refresh ( ) ;
}
2021-07-08 22:05:47 +00:00
void SingleControlMapper : : Refresh ( ) {
2013-08-17 08:34:38 +00:00
Clear ( ) ;
2023-04-05 22:34:50 +00:00
auto mc = GetI18NCategory ( I18NCat : : MAPPABLECONTROLS ) ;
2013-08-30 14:01:17 +00:00
2024-04-11 12:50:42 +00:00
std : : map < std : : string , ImageID > keyImages = {
{ " Circle " , ImageID ( " I_CIRCLE " ) } ,
{ " Cross " , ImageID ( " I_CROSS " ) } ,
{ " Square " , ImageID ( " I_SQUARE " ) } ,
{ " Triangle " , ImageID ( " I_TRIANGLE " ) } ,
{ " Start " , ImageID ( " I_START " ) } ,
{ " Select " , ImageID ( " I_SELECT " ) } ,
{ " L " , ImageID ( " I_L " ) } ,
{ " R " , ImageID ( " I_R " ) }
} ;
2013-08-17 08:34:38 +00:00
using namespace UI ;
2013-08-16 14:48:43 +00:00
2021-09-24 09:13:01 +00:00
float itemH = 55.0f ;
2013-12-06 15:45:25 +00:00
2021-08-08 21:28:37 +00:00
float leftColumnWidth = 200 ;
2023-04-01 15:50:17 +00:00
float rightColumnWidth = 350 ; // TODO: Should be flexible somehow. Maybe we need to implement Measure.
2021-08-08 21:28:37 +00:00
LinearLayout * root = Add ( new LinearLayout ( ORIENT_HORIZONTAL , new LinearLayoutParams ( FILL_PARENT , WRAP_CONTENT ) ) ) ;
2013-12-06 15:45:25 +00:00
root - > SetSpacing ( 3.0f ) ;
2013-08-30 14:01:17 +00:00
auto iter = keyImages . find ( keyName_ ) ;
// First, look among images.
if ( iter ! = keyImages . end ( ) ) {
2021-08-29 23:59:55 +00:00
replaceAllButton_ = new Choice ( iter - > second , new LinearLayoutParams ( leftColumnWidth , itemH ) ) ;
2013-08-30 14:01:17 +00:00
} else {
// No image? Let's translate.
2024-10-10 09:55:07 +00:00
replaceAllButton_ = new Choice ( mc - > T ( keyName_ ) , new LinearLayoutParams ( leftColumnWidth , itemH ) ) ;
2021-08-29 23:59:55 +00:00
replaceAllButton_ - > SetCentered ( true ) ;
2013-08-30 14:01:17 +00:00
}
2021-08-29 23:59:55 +00:00
root - > Add ( replaceAllButton_ ) - > OnClick . Handle ( this , & SingleControlMapper : : OnReplaceAll ) ;
2013-08-30 14:01:17 +00:00
2021-08-29 23:59:55 +00:00
addButton_ = root - > Add ( new Choice ( " + " , new LayoutParams ( WRAP_CONTENT , itemH ) ) ) ;
addButton_ - > OnClick . Handle ( this , & SingleControlMapper : : OnAdd ) ;
2017-04-27 08:09:57 +00:00
if ( g_Config . bMouseControl ) {
Choice * p = root - > Add ( new Choice ( " M " , new LayoutParams ( WRAP_CONTENT , itemH ) ) ) ;
2021-07-08 22:05:47 +00:00
p - > OnClick . Handle ( this , & SingleControlMapper : : OnAddMouse ) ;
2017-04-27 08:09:57 +00:00
}
2014-06-09 20:26:23 +00:00
2021-08-08 21:28:37 +00:00
LinearLayout * rightColumn = root - > Add ( new LinearLayout ( ORIENT_VERTICAL , new LinearLayoutParams ( rightColumnWidth , WRAP_CONTENT ) ) ) ;
2013-08-20 13:40:19 +00:00
rightColumn - > SetSpacing ( 2.0f ) ;
2023-03-31 22:12:14 +00:00
std : : vector < MultiInputMapping > mappings ;
2023-03-29 09:59:31 +00:00
KeyMap : : InputMappingsFromPspButton ( pspKey_ , & mappings , false ) ;
2013-08-16 14:48:43 +00:00
2021-09-07 22:19:18 +00:00
rows_ . clear ( ) ;
2013-08-17 08:34:38 +00:00
for ( size_t i = 0 ; i < mappings . size ( ) ; i + + ) {
2023-04-01 13:00:22 +00:00
std : : string multiMappingString = mappings [ i ] . ToVisualString ( ) ;
2013-08-17 08:34:38 +00:00
LinearLayout * row = rightColumn - > Add ( new LinearLayout ( ORIENT_HORIZONTAL , new LinearLayoutParams ( FILL_PARENT , WRAP_CONTENT ) ) ) ;
2022-11-23 10:13:21 +00:00
row - > SetSpacing ( 2.0f ) ;
2021-08-29 23:59:55 +00:00
rows_ . push_back ( row ) ;
2021-08-08 21:28:37 +00:00
2023-04-01 13:00:22 +00:00
Choice * c = row - > Add ( new Choice ( multiMappingString , new LinearLayoutParams ( FILL_PARENT , itemH , 1.0f ) ) ) ;
2021-08-29 23:59:55 +00:00
c - > SetTag ( StringFromFormat ( " %d_Change%d " , ( int ) i , pspKey_ ) ) ;
2021-07-08 22:05:47 +00:00
c - > OnClick . Handle ( this , & SingleControlMapper : : OnReplace ) ;
2013-08-20 17:20:03 +00:00
2022-11-23 10:13:21 +00:00
Choice * d = row - > Add ( new Choice ( ImageID ( " I_TRASHCAN " ) , new LayoutParams ( WRAP_CONTENT , itemH ) ) ) ;
2021-08-29 23:59:55 +00:00
d - > SetTag ( StringFromFormat ( " %d_Del%d " , ( int ) i , pspKey_ ) ) ;
2021-07-08 22:05:47 +00:00
d - > OnClick . Handle ( this , & SingleControlMapper : : OnDelete ) ;
2013-08-16 14:48:43 +00:00
}
2024-10-10 09:55:07 +00:00
if ( mappings . empty ( ) ) {
2013-08-17 08:34:38 +00:00
// look like an empty line
2013-12-06 15:45:25 +00:00
Choice * c = rightColumn - > Add ( new Choice ( " " , new LinearLayoutParams ( FILL_PARENT , itemH ) ) ) ;
2021-07-08 22:05:47 +00:00
c - > OnClick . Handle ( this , & SingleControlMapper : : OnAdd ) ;
2013-08-17 08:34:38 +00:00
}
}
2023-12-14 11:23:31 +00:00
void SingleControlMapper : : MappedCallback ( const MultiInputMapping & kdf ) {
2023-05-05 20:26:27 +00:00
if ( kdf . empty ( ) ) {
// Don't want to try to add this.
return ;
}
2013-08-17 08:34:38 +00:00
switch ( action_ ) {
2013-08-17 09:18:45 +00:00
case ADD :
2023-03-29 09:59:31 +00:00
KeyMap : : SetInputMapping ( pspKey_ , kdf , false ) ;
2021-08-29 23:59:55 +00:00
addButton_ - > SetFocus ( ) ;
2013-08-17 09:18:45 +00:00
break ;
2013-08-17 08:34:38 +00:00
case REPLACEALL :
2023-03-29 09:59:31 +00:00
KeyMap : : SetInputMapping ( pspKey_ , kdf , true ) ;
2021-08-29 23:59:55 +00:00
replaceAllButton_ - > SetFocus ( ) ;
2013-08-17 08:34:38 +00:00
break ;
case REPLACEONE :
2021-09-08 06:54:59 +00:00
{
bool success = KeyMap : : ReplaceSingleKeyMapping ( pspKey_ , actionIndex_ , kdf ) ;
if ( ! success ) {
replaceAllButton_ - > SetFocus ( ) ; // Last got removed as a duplicate
2022-01-07 04:40:29 +00:00
} else if ( actionIndex_ < ( int ) rows_ . size ( ) ) {
2021-08-29 23:59:55 +00:00
rows_ [ actionIndex_ ] - > SetFocus ( ) ;
2021-09-08 06:54:59 +00:00
} else {
2021-08-29 23:59:55 +00:00
SetFocus ( ) ;
2021-09-08 06:54:59 +00:00
}
2013-08-17 08:34:38 +00:00
break ;
2021-09-08 06:54:59 +00:00
}
2013-08-17 11:26:19 +00:00
default :
2021-08-29 23:59:55 +00:00
SetFocus ( ) ;
break ;
2013-08-17 08:34:38 +00:00
}
2023-04-01 20:30:34 +00:00
KeyMap : : UpdateNativeMenuKeys ( ) ;
2017-04-26 14:48:55 +00:00
g_Config . bMapMouse = false ;
2013-08-17 08:34:38 +00:00
}
2021-07-08 22:05:47 +00:00
UI : : EventReturn SingleControlMapper : : OnReplace ( UI : : EventParams & params ) {
2013-08-17 08:34:38 +00:00
actionIndex_ = atoi ( params . v - > Tag ( ) . c_str ( ) ) ;
action_ = REPLACEONE ;
2023-04-05 22:34:50 +00:00
scrm_ - > push ( new KeyMappingNewKeyDialog ( pspKey_ , true , std : : bind ( & SingleControlMapper : : MappedCallback , this , std : : placeholders : : _1 ) , I18NCat : : KEYMAPPING ) ) ;
2013-08-17 08:34:38 +00:00
return UI : : EVENT_DONE ;
}
2021-07-08 22:05:47 +00:00
UI : : EventReturn SingleControlMapper : : OnReplaceAll ( UI : : EventParams & params ) {
2013-08-17 08:34:38 +00:00
action_ = REPLACEALL ;
2023-04-05 22:34:50 +00:00
scrm_ - > push ( new KeyMappingNewKeyDialog ( pspKey_ , true , std : : bind ( & SingleControlMapper : : MappedCallback , this , std : : placeholders : : _1 ) , I18NCat : : KEYMAPPING ) ) ;
2013-08-17 08:34:38 +00:00
return UI : : EVENT_DONE ;
}
2021-07-08 22:05:47 +00:00
UI : : EventReturn SingleControlMapper : : OnAdd ( UI : : EventParams & params ) {
2013-08-17 09:18:45 +00:00
action_ = ADD ;
2023-04-05 22:34:50 +00:00
scrm_ - > push ( new KeyMappingNewKeyDialog ( pspKey_ , true , std : : bind ( & SingleControlMapper : : MappedCallback , this , std : : placeholders : : _1 ) , I18NCat : : KEYMAPPING ) ) ;
2013-08-17 08:34:38 +00:00
return UI : : EVENT_DONE ;
}
2021-07-08 22:05:47 +00:00
UI : : EventReturn SingleControlMapper : : OnAddMouse ( UI : : EventParams & params ) {
2017-04-27 08:09:57 +00:00
action_ = ADD ;
g_Config . bMapMouse = true ;
2023-04-05 22:34:50 +00:00
scrm_ - > push ( new KeyMappingNewMouseKeyDialog ( pspKey_ , true , std : : bind ( & SingleControlMapper : : MappedCallback , this , std : : placeholders : : _1 ) , I18NCat : : KEYMAPPING ) ) ;
2017-04-27 08:09:57 +00:00
return UI : : EVENT_DONE ;
}
2013-08-17 08:34:38 +00:00
2021-07-08 22:05:47 +00:00
UI : : EventReturn SingleControlMapper : : OnDelete ( UI : : EventParams & params ) {
2013-08-17 09:18:45 +00:00
int index = atoi ( params . v - > Tag ( ) . c_str ( ) ) ;
2023-04-01 17:56:02 +00:00
KeyMap : : DeleteNthMapping ( pspKey_ , index ) ;
2021-08-29 23:59:55 +00:00
2022-01-07 04:40:29 +00:00
if ( index + 1 < ( int ) rows_ . size ( ) )
2021-08-29 23:59:55 +00:00
rows_ [ index ] - > SetFocus ( ) ;
else
SetFocus ( ) ;
2013-08-17 08:34:38 +00:00
return UI : : EVENT_DONE ;
}
2024-05-21 09:17:34 +00:00
struct BindingCategory {
const char * catName ;
int firstKey ;
} ;
// Category name, first input from psp_button_names.
static const BindingCategory cats [ ] = {
{ " Standard PSP controls " , CTRL_UP } ,
{ " Control modifiers " , VIRTKEY_ANALOG_ROTATE_CW } ,
{ " Emulator controls " , VIRTKEY_FASTFORWARD } ,
{ " Extended PSP controls " , VIRTKEY_AXIS_RIGHT_Y_MAX } ,
2024-07-22 09:36:12 +00:00
{ } , // sentinel
2024-05-21 09:17:34 +00:00
} ;
2013-08-17 08:34:38 +00:00
void ControlMappingScreen : : CreateViews ( ) {
using namespace UI ;
2014-06-08 13:38:13 +00:00
mappers_ . clear ( ) ;
2013-08-17 08:34:38 +00:00
2023-04-05 22:34:50 +00:00
auto km = GetI18NCategory ( I18NCat : : KEYMAPPING ) ;
2013-08-17 08:34:38 +00:00
root_ = new LinearLayout ( ORIENT_HORIZONTAL ) ;
2015-07-04 15:01:32 +00:00
LinearLayout * leftColumn = new LinearLayout ( ORIENT_VERTICAL , new LinearLayoutParams ( 200 , FILL_PARENT , Margins ( 10 , 0 , 0 , 10 ) ) ) ;
2023-08-24 08:58:50 +00:00
leftColumn - > Add ( new Choice ( km - > T ( " Clear All " ) ) ) - > OnClick . Add ( [ ] ( UI : : EventParams & ) {
KeyMap : : ClearAllMappings ( ) ;
return UI : : EVENT_DONE ;
} ) ;
leftColumn - > Add ( new Choice ( km - > T ( " Default All " ) ) ) - > OnClick . Add ( [ ] ( UI : : EventParams & ) {
KeyMap : : RestoreDefault ( ) ;
return UI : : EVENT_DONE ;
} ) ;
2015-10-04 11:25:22 +00:00
std : : string sysName = System_GetProperty ( SYSPROP_NAME ) ;
// If there's a builtin controller, restore to default should suffice. No need to conf the controller on top.
if ( ! KeyMap : : HasBuiltinController ( sysName ) & & KeyMap : : GetSeenPads ( ) . size ( ) ) {
2015-07-01 21:54:35 +00:00
leftColumn - > Add ( new Choice ( km - > T ( " Autoconfigure " ) ) ) - > OnClick . Handle ( this , & ControlMappingScreen : : OnAutoConfigure ) ;
2014-05-19 21:29:35 +00:00
}
2021-07-09 11:10:16 +00:00
2023-08-24 08:58:50 +00:00
leftColumn - > Add ( new Choice ( km - > T ( " Show PSP " ) ) ) - > OnClick . Add ( [ = ] ( UI : : EventParams & ) {
screenManager ( ) - > push ( new VisualMappingScreen ( gamePath_ ) ) ;
return UI : : EVENT_DONE ;
} ) ;
2023-07-07 08:33:27 +00:00
leftColumn - > Add ( new CheckBox ( & g_Config . bAllowMappingCombos , km - > T ( " Allow combo mappings " ) ) ) ;
2024-01-29 17:05:03 +00:00
leftColumn - > Add ( new CheckBox ( & g_Config . bStrictComboOrder , km - > T ( " Strict combo input order " ) ) ) ;
2021-08-28 20:57:22 +00:00
2013-08-17 08:34:38 +00:00
leftColumn - > Add ( new Spacer ( new LinearLayoutParams ( 1.0f ) ) ) ;
2015-07-04 15:01:32 +00:00
AddStandardBack ( leftColumn ) ;
2013-12-02 14:15:19 +00:00
2014-06-08 13:38:13 +00:00
rightScroll_ = new ScrollView ( ORIENT_VERTICAL , new LinearLayoutParams ( 1.0f ) ) ;
2016-01-23 06:52:13 +00:00
rightScroll_ - > SetTag ( " ControlMapping " ) ;
2021-08-08 21:28:37 +00:00
LinearLayout * rightColumn = new LinearLayoutList ( ORIENT_VERTICAL ) ;
2014-06-08 13:38:13 +00:00
rightScroll_ - > Add ( rightColumn ) ;
2013-08-17 08:34:38 +00:00
root_ - > Add ( leftColumn ) ;
2014-06-08 13:38:13 +00:00
root_ - > Add ( rightScroll_ ) ;
2013-08-17 08:34:38 +00:00
2023-12-21 10:16:10 +00:00
size_t numMappableKeys = 0 ;
const KeyMap : : KeyMap_IntStrPair * mappableKeys = KeyMap : : GetMappableKeys ( & numMappableKeys ) ;
2023-12-20 15:20:26 +00:00
int curCat = - 1 ;
CollapsibleSection * curSection = nullptr ;
2023-12-21 10:16:10 +00:00
for ( size_t i = 0 ; i < numMappableKeys ; i + + ) {
2023-12-20 15:20:26 +00:00
if ( curCat < ( int ) ARRAY_SIZE ( cats ) & & mappableKeys [ i ] . key = = cats [ curCat + 1 ] . firstKey ) {
2024-01-29 16:57:01 +00:00
if ( curCat > = 0 ) {
2024-05-21 09:15:54 +00:00
curSection - > SetOpenPtr ( & categoryToggles_ [ curCat ] ) ;
2023-12-20 15:20:26 +00:00
}
curCat + + ;
curSection = rightColumn - > Add ( new CollapsibleSection ( km - > T ( cats [ curCat ] . catName ) ) ) ;
curSection - > SetSpacing ( 6.0f ) ;
}
SingleControlMapper * mapper = curSection - > Add (
2021-08-29 23:59:55 +00:00
new SingleControlMapper ( mappableKeys [ i ] . key , mappableKeys [ i ] . name , screenManager ( ) ,
2021-08-08 21:28:37 +00:00
new LinearLayoutParams ( FILL_PARENT , WRAP_CONTENT ) ) ) ;
2021-08-29 23:43:15 +00:00
mapper - > SetTag ( StringFromFormat ( " KeyMap%s " , mappableKeys [ i ] . name ) ) ;
2014-06-08 13:38:13 +00:00
mappers_ . push_back ( mapper ) ;
2013-08-17 08:34:38 +00:00
}
2024-01-29 16:57:01 +00:00
if ( curCat > = 0 & & curSection ) {
2024-05-21 09:15:54 +00:00
curSection - > SetOpenPtr ( & categoryToggles_ [ curCat ] ) ;
2023-12-20 15:20:26 +00:00
}
2024-07-22 09:36:12 +00:00
_dbg_assert_ ( curCat = = ARRAY_SIZE ( cats ) - 2 ) ; // count the sentinel
2021-08-29 15:02:52 +00:00
keyMapGeneration_ = KeyMap : : g_controllerMapGeneration ;
}
void ControlMappingScreen : : update ( ) {
if ( KeyMap : : HasChanged ( keyMapGeneration_ ) ) {
RecreateViews ( ) ;
}
2022-11-22 21:53:54 +00:00
UIDialogScreenWithGameBackground : : update ( ) ;
2022-11-17 11:19:17 +00:00
SetVRAppMode ( VRAppMode : : VR_MENU_MODE ) ;
2013-08-17 08:34:38 +00:00
}
2014-05-19 21:29:35 +00:00
UI : : EventReturn ControlMappingScreen : : OnAutoConfigure ( UI : : EventParams & params ) {
std : : vector < std : : string > items ;
2014-05-21 15:40:00 +00:00
const auto seenPads = KeyMap : : GetSeenPads ( ) ;
for ( auto s = seenPads . begin ( ) , end = seenPads . end ( ) ; s ! = end ; + + s ) {
items . push_back ( * s ) ;
2014-05-19 21:29:35 +00:00
}
2023-04-05 22:34:50 +00:00
auto km = GetI18NCategory ( I18NCat : : KEYMAPPING ) ;
2023-01-11 09:36:00 +00:00
UI : : ListPopupScreen * autoConfList = new UI : : ListPopupScreen ( km - > T ( " Autoconfigure for device " ) , items , - 1 ) ;
2017-03-22 01:27:57 +00:00
if ( params . v )
autoConfList - > SetPopupOrigin ( params . v ) ;
2014-05-19 21:29:35 +00:00
screenManager ( ) - > push ( autoConfList ) ;
return UI : : EVENT_DONE ;
}
void ControlMappingScreen : : dialogFinished ( const Screen * dialog , DialogResult result ) {
2024-10-22 09:59:41 +00:00
if ( result = = DR_OK & & ! strcmp ( dialog - > tag ( ) , " listpopup " ) ) {
2023-01-11 09:36:00 +00:00
UI : : ListPopupScreen * popup = ( UI : : ListPopupScreen * ) dialog ;
2014-05-19 21:29:35 +00:00
KeyMap : : AutoConfForPad ( popup - > GetChoiceString ( ) ) ;
}
}
2013-08-16 15:16:11 +00:00
void KeyMappingNewKeyDialog : : CreatePopupContents ( UI : : ViewGroup * parent ) {
using namespace UI ;
2013-08-16 14:48:43 +00:00
2023-04-05 22:34:50 +00:00
auto km = GetI18NCategory ( I18NCat : : KEYMAPPING ) ;
auto mc = GetI18NCategory ( I18NCat : : MAPPABLECONTROLS ) ;
2013-08-16 14:48:43 +00:00
2013-08-16 15:16:11 +00:00
std : : string pspButtonName = KeyMap : : GetPspButtonName ( this - > pspBtn_ ) ;
2013-08-16 14:48:43 +00:00
2024-01-19 12:44:49 +00:00
parent - > Add ( new TextView ( std : : string ( km - > T ( " Map a new key for " ) ) + " " + std : : string ( mc - > T ( pspButtonName ) ) , new LinearLayoutParams ( Margins ( 10 , 0 ) ) ) ) ;
2023-04-01 15:50:17 +00:00
parent - > Add ( new TextView ( std : : string ( mapping_ . ToVisualString ( ) ) , new LinearLayoutParams ( Margins ( 10 , 0 ) ) ) ) ;
2023-07-07 13:23:19 +00:00
comboMappingsNotEnabled_ = parent - > Add ( new NoticeView ( NoticeLevel : : WARN , km - > T ( " Combo mappings are not enabled " ) , " " , new LinearLayoutParams ( Margins ( 10 , 0 ) ) ) ) ;
2023-07-07 08:33:27 +00:00
comboMappingsNotEnabled_ - > SetVisibility ( UI : : V_GONE ) ;
2022-11-17 18:13:04 +00:00
SetVRAppMode ( VRAppMode : : VR_CONTROLLER_MAPPING_MODE ) ;
2013-08-16 14:48:43 +00:00
}
2014-06-15 11:04:59 +00:00
bool KeyMappingNewKeyDialog : : key ( const KeyInput & key ) {
2023-05-06 13:09:12 +00:00
if ( ignoreInput_ )
return true ;
2023-04-01 15:50:17 +00:00
if ( time_now_d ( ) < delayUntil_ )
return true ;
2023-07-07 08:33:27 +00:00
2013-08-16 14:48:43 +00:00
if ( key . flags & KEY_DOWN ) {
2017-04-27 09:12:11 +00:00
if ( key . keyCode = = NKCODE_EXT_MOUSEBUTTON_1 ) {
2023-04-01 15:50:17 +00:00
// Don't map
2014-06-15 11:04:59 +00:00
return true ;
2013-08-16 14:48:43 +00:00
}
2023-04-01 15:50:17 +00:00
if ( pspBtn_ = = VIRTKEY_SPEED_ANALOG & & ! UI : : IsEscapeKey ( key ) ) {
// Only map analog values to this mapping.
2022-07-04 20:10:42 +00:00
return true ;
2023-04-01 15:50:17 +00:00
}
2013-08-19 22:49:25 +00:00
2023-04-01 15:50:17 +00:00
InputMapping newMapping ( key . deviceId , key . keyCode ) ;
if ( ! ( key . flags & KEY_IS_REPEAT ) ) {
2023-07-07 08:33:27 +00:00
if ( ! g_Config . bAllowMappingCombos & & ! mapping_ . mappings . empty ( ) ) {
comboMappingsNotEnabled_ - > SetVisibility ( UI : : V_VISIBLE ) ;
} else if ( ! mapping_ . mappings . contains ( newMapping ) ) {
2023-04-01 15:50:17 +00:00
mapping_ . mappings . push_back ( newMapping ) ;
RecreateViews ( ) ;
}
}
}
if ( key . flags & KEY_UP ) {
2023-05-05 21:00:01 +00:00
// If the key released wasn't part of the mapping, ignore it here. Some device can cause
// stray key-up events.
InputMapping upMapping ( key . deviceId , key . keyCode ) ;
if ( ! mapping_ . mappings . contains ( upMapping ) ) {
return true ;
}
2023-04-01 15:50:17 +00:00
if ( callback_ )
callback_ ( mapping_ ) ;
2021-08-28 22:04:16 +00:00
TriggerFinish ( DR_YES ) ;
2013-08-16 14:48:43 +00:00
}
2014-06-15 11:04:59 +00:00
return true ;
2013-08-16 14:48:43 +00:00
}
2021-10-08 01:45:15 +00:00
void KeyMappingNewKeyDialog : : SetDelay ( float t ) {
delayUntil_ = time_now_d ( ) + t ;
}
2017-04-27 09:12:11 +00:00
void KeyMappingNewMouseKeyDialog : : CreatePopupContents ( UI : : ViewGroup * parent ) {
using namespace UI ;
2023-04-05 22:34:50 +00:00
auto km = GetI18NCategory ( I18NCat : : KEYMAPPING ) ;
2017-04-27 09:12:11 +00:00
parent - > Add ( new TextView ( std : : string ( km - > T ( " You can press ESC to cancel. " ) ) , new LinearLayoutParams ( Margins ( 10 , 0 ) ) ) ) ;
2022-11-17 18:13:04 +00:00
SetVRAppMode ( VRAppMode : : VR_CONTROLLER_MAPPING_MODE ) ;
2017-04-27 09:12:11 +00:00
}
bool KeyMappingNewMouseKeyDialog : : key ( const KeyInput & key ) {
if ( mapped_ )
return false ;
2023-05-06 13:09:12 +00:00
if ( ignoreInput_ )
return true ;
2017-04-27 09:12:11 +00:00
if ( key . flags & KEY_DOWN ) {
if ( key . keyCode = = NKCODE_ESCAPE ) {
TriggerFinish ( DR_OK ) ;
g_Config . bMapMouse = false ;
return false ;
}
mapped_ = true ;
2023-05-05 21:00:01 +00:00
2021-08-28 22:04:16 +00:00
TriggerFinish ( DR_YES ) ;
2017-04-27 09:12:11 +00:00
g_Config . bMapMouse = false ;
2023-12-20 09:35:02 +00:00
if ( callback_ ) {
MultiInputMapping kdf ( InputMapping ( key . deviceId , key . keyCode ) ) ;
2017-04-27 09:12:11 +00:00
callback_ ( kdf ) ;
2023-12-20 09:35:02 +00:00
}
2017-04-27 09:12:11 +00:00
}
return true ;
}
2023-12-28 12:36:03 +00:00
// Only used during the bind process. In other places, it's configurable for some types of axis, like trigger.
const float AXIS_BIND_THRESHOLD = 0.75f ;
const float AXIS_BIND_RELEASE_THRESHOLD = 0.35f ; // Used during mapping only to detect a "key-up" reliably.
2022-12-31 20:44:52 +00:00
void KeyMappingNewKeyDialog : : axis ( const AxisInput & axis ) {
2023-04-01 15:50:17 +00:00
if ( time_now_d ( ) < delayUntil_ )
2022-12-31 20:44:52 +00:00
return ;
2023-05-06 13:09:12 +00:00
if ( ignoreInput_ )
return ;
2017-04-27 09:12:11 +00:00
if ( axis . value > AXIS_BIND_THRESHOLD ) {
2023-04-01 15:50:17 +00:00
InputMapping mapping ( axis . deviceId , axis . axisId , 1 ) ;
triggeredAxes_ . insert ( mapping ) ;
2023-07-11 09:00:57 +00:00
if ( ! g_Config . bAllowMappingCombos & & ! mapping_ . mappings . empty ( ) ) {
2023-12-20 14:37:46 +00:00
if ( mapping_ . mappings . size ( ) = = 1 & & mapping ! = mapping_ . mappings [ 0 ] )
comboMappingsNotEnabled_ - > SetVisibility ( UI : : V_VISIBLE ) ;
2023-07-11 09:00:57 +00:00
} else if ( ! mapping_ . mappings . contains ( mapping ) ) {
2023-04-01 15:50:17 +00:00
mapping_ . mappings . push_back ( mapping ) ;
RecreateViews ( ) ;
}
} else if ( axis . value < - AXIS_BIND_THRESHOLD ) {
InputMapping mapping ( axis . deviceId , axis . axisId , - 1 ) ;
triggeredAxes_ . insert ( mapping ) ;
2023-07-11 09:00:57 +00:00
if ( ! g_Config . bAllowMappingCombos & & ! mapping_ . mappings . empty ( ) ) {
2023-12-20 14:37:46 +00:00
if ( mapping_ . mappings . size ( ) = = 1 & & mapping ! = mapping_ . mappings [ 0 ] )
comboMappingsNotEnabled_ - > SetVisibility ( UI : : V_VISIBLE ) ;
2023-07-11 09:00:57 +00:00
} else if ( ! mapping_ . mappings . contains ( mapping ) ) {
2023-04-01 15:50:17 +00:00
mapping_ . mappings . push_back ( mapping ) ;
RecreateViews ( ) ;
}
} else if ( fabsf ( axis . value ) < AXIS_BIND_RELEASE_THRESHOLD ) {
InputMapping neg ( axis . deviceId , axis . axisId , - 1 ) ;
InputMapping pos ( axis . deviceId , axis . axisId , 1 ) ;
if ( triggeredAxes_ . find ( neg ) ! = triggeredAxes_ . end ( ) | | triggeredAxes_ . find ( pos ) ! = triggeredAxes_ . end ( ) ) {
// "Key-up" the axis.
TriggerFinish ( DR_YES ) ;
if ( callback_ )
callback_ ( mapping_ ) ;
}
2017-04-27 09:12:11 +00:00
}
}
2022-12-31 20:44:52 +00:00
void KeyMappingNewMouseKeyDialog : : axis ( const AxisInput & axis ) {
2017-04-27 09:12:11 +00:00
if ( mapped_ )
2022-12-31 20:44:52 +00:00
return ;
2014-01-06 22:58:59 +00:00
2013-08-16 14:48:43 +00:00
if ( axis . value > AXIS_BIND_THRESHOLD ) {
2014-06-08 13:38:13 +00:00
mapped_ = true ;
2021-08-28 22:04:16 +00:00
TriggerFinish ( DR_YES ) ;
2023-12-20 09:35:02 +00:00
if ( callback_ ) {
MultiInputMapping kdf ( InputMapping ( axis . deviceId , axis . axisId , 1 ) ) ;
2013-08-17 08:34:38 +00:00
callback_ ( kdf ) ;
2023-12-20 09:35:02 +00:00
}
2013-08-16 14:48:43 +00:00
}
2013-08-16 15:16:11 +00:00
2013-08-16 14:48:43 +00:00
if ( axis . value < - AXIS_BIND_THRESHOLD ) {
2014-06-08 13:38:13 +00:00
mapped_ = true ;
2021-08-28 22:04:16 +00:00
TriggerFinish ( DR_YES ) ;
2023-12-20 09:35:02 +00:00
if ( callback_ ) {
MultiInputMapping kdf ( InputMapping ( axis . deviceId , axis . axisId , - 1 ) ) ;
2013-08-17 08:34:38 +00:00
callback_ ( kdf ) ;
2023-12-20 09:35:02 +00:00
}
2013-08-16 14:48:43 +00:00
}
}
2014-09-05 21:21:07 +00:00
2022-11-22 21:53:54 +00:00
AnalogSetupScreen : : AnalogSetupScreen ( const Path & gamePath ) : UIDialogScreenWithGameBackground ( gamePath ) {
2023-03-26 09:35:42 +00:00
mapper_ . SetCallbacks (
2023-03-30 08:47:28 +00:00
[ ] ( int vkey , bool down ) { } ,
2023-03-29 11:50:57 +00:00
[ ] ( int vkey , float analogValue ) { } ,
2023-03-30 08:47:28 +00:00
[ & ] ( uint32_t bitsToSet , uint32_t bitsToClear ) { } ,
2023-03-26 09:35:42 +00:00
[ & ] ( int stick , float x , float y ) {
2023-03-31 09:11:46 +00:00
analogX_ [ stick ] = x ;
analogY_ [ stick ] = y ;
} ,
[ & ] ( int stick , float x , float y ) {
rawX_ [ stick ] = x ;
rawY_ [ stick ] = y ;
} ) ;
2021-07-09 14:14:32 +00:00
}
void AnalogSetupScreen : : update ( ) {
2023-08-23 16:42:20 +00:00
mapper_ . Update ( time_now_d ( ) ) ;
2021-07-09 14:14:32 +00:00
// We ignore the secondary stick for now and just use the two views
// for raw and psp input.
if ( stickView_ [ 0 ] ) {
2021-07-09 15:04:59 +00:00
stickView_ [ 0 ] - > SetXY ( analogX_ [ 0 ] , analogY_ [ 0 ] ) ;
2021-07-09 14:14:32 +00:00
}
if ( stickView_ [ 1 ] ) {
2021-07-09 15:04:59 +00:00
stickView_ [ 1 ] - > SetXY ( rawX_ [ 0 ] , rawY_ [ 0 ] ) ;
2021-07-09 14:14:32 +00:00
}
UIScreen : : update ( ) ;
}
2021-07-09 11:10:16 +00:00
bool AnalogSetupScreen : : key ( const KeyInput & key ) {
2021-08-21 22:13:01 +00:00
bool retval = UIScreen : : key ( key ) ;
// Allow testing auto-rotation. If it collides with UI keys, too bad.
2021-07-09 14:14:32 +00:00
bool pauseTrigger = false ;
mapper_ . Key ( key , & pauseTrigger ) ;
2015-09-17 20:46:59 +00:00
if ( UI : : IsEscapeKey ( key ) ) {
2017-03-20 00:43:03 +00:00
TriggerFinish ( DR_BACK ) ;
2021-08-21 22:13:01 +00:00
return retval ;
2015-09-17 20:46:59 +00:00
}
2021-08-21 22:13:01 +00:00
return retval ;
2015-01-03 16:55:15 +00:00
}
2022-12-31 20:44:52 +00:00
void AnalogSetupScreen : : axis ( const AxisInput & axis ) {
2021-07-09 11:10:16 +00:00
// We DON'T call UIScreen::Axis here! Otherwise it'll try to move the UI focus around.
// UIScreen::axis(axis);
// Instead we just send the input directly to the mapper, that we'll visualize.
2023-09-27 15:34:34 +00:00
mapper_ . Axis ( & axis , 1 ) ;
2015-08-27 23:22:45 +00:00
}
2021-07-09 11:10:16 +00:00
void AnalogSetupScreen : : CreateViews ( ) {
2015-01-03 16:55:15 +00:00
using namespace UI ;
2023-04-05 22:34:50 +00:00
auto di = GetI18NCategory ( I18NCat : : DIALOG ) ;
2015-01-04 01:01:05 +00:00
2021-07-09 11:10:16 +00:00
root_ = new LinearLayout ( ORIENT_HORIZONTAL ) ;
2014-09-05 21:21:07 +00:00
2021-07-09 11:10:16 +00:00
LinearLayout * leftColumn = root_ - > Add ( new LinearLayout ( ORIENT_VERTICAL , new LinearLayoutParams ( 300.0f , FILL_PARENT ) ) ) ;
LinearLayout * rightColumn = root_ - > Add ( new LinearLayout ( ORIENT_VERTICAL , new LinearLayoutParams ( 1.0f ) ) ) ;
2014-09-05 21:21:07 +00:00
2023-04-05 22:34:50 +00:00
auto co = GetI18NCategory ( I18NCat : : CONTROLS ) ;
2021-07-09 15:25:00 +00:00
ScrollView * scroll = leftColumn - > Add ( new ScrollView ( ORIENT_VERTICAL , new LinearLayoutParams ( 1.0 ) ) ) ;
LinearLayout * scrollContents = scroll - > Add ( new LinearLayout ( ORIENT_VERTICAL , new LinearLayoutParams ( 300.0f , WRAP_CONTENT ) ) ) ;
scrollContents - > Add ( new ItemHeader ( co - > T ( " Analog Settings " , " Analog Settings " ) ) ) ;
2021-07-09 17:17:41 +00:00
// TODO: Would be nicer if these didn't pop up...
2023-04-05 08:16:21 +00:00
scrollContents - > Add ( new PopupSliderChoiceFloat ( & g_Config . fAnalogDeadzone , 0.0f , 0.5f , 0.15f , co - > T ( " Deadzone radius " ) , 0.01f , screenManager ( ) , " / 1.0 " ) ) ;
scrollContents - > Add ( new PopupSliderChoiceFloat ( & g_Config . fAnalogInverseDeadzone , 0.0f , 1.0f , 0.0f , co - > T ( " Low end radius " ) , 0.01f , screenManager ( ) , " / 1.0 " ) ) ;
scrollContents - > Add ( new PopupSliderChoiceFloat ( & g_Config . fAnalogSensitivity , 0.0f , 2.0f , 1.1f , co - > T ( " Sensitivity (scale) " , " Sensitivity " ) , 0.01f , screenManager ( ) , " x " ) ) ;
2021-07-09 17:17:41 +00:00
// TODO: This should probably be a slider.
scrollContents - > Add ( new CheckBox ( & g_Config . bAnalogIsCircular , co - > T ( " Circular stick input " ) ) ) ;
2023-04-05 08:16:21 +00:00
scrollContents - > Add ( new PopupSliderChoiceFloat ( & g_Config . fAnalogAutoRotSpeed , 0.1f , 20.0f , 8.0f , co - > T ( " Auto-rotation speed " ) , 1.0f , screenManager ( ) ) ) ;
2021-07-09 15:25:00 +00:00
scrollContents - > Add ( new Choice ( co - > T ( " Reset to defaults " ) ) ) - > OnClick . Handle ( this , & AnalogSetupScreen : : OnResetToDefaults ) ;
2014-09-05 21:21:07 +00:00
2021-07-09 11:10:16 +00:00
LinearLayout * theTwo = new LinearLayout ( ORIENT_HORIZONTAL , new LinearLayoutParams ( 1.0f ) ) ;
2014-09-05 21:21:07 +00:00
2021-07-09 15:13:08 +00:00
stickView_ [ 0 ] = theTwo - > Add ( new JoystickHistoryView ( StickHistoryViewType : : OUTPUT , co - > T ( " Calibrated " ) , new LinearLayoutParams ( 1.0f ) ) ) ;
2021-07-09 17:17:41 +00:00
stickView_ [ 1 ] = theTwo - > Add ( new JoystickHistoryView ( StickHistoryViewType : : INPUT , co - > T ( " Raw input " ) , new LinearLayoutParams ( 1.0f ) ) ) ;
2014-09-05 21:21:07 +00:00
2021-07-09 11:10:16 +00:00
rightColumn - > Add ( theTwo ) ;
2014-09-05 21:21:07 +00:00
2021-07-09 11:10:16 +00:00
leftColumn - > Add ( new Button ( di - > T ( " Back " ) , new LayoutParams ( FILL_PARENT , WRAP_CONTENT ) ) ) - > OnClick . Handle < UIScreen > ( this , & UIScreen : : OnBack ) ;
}
2015-01-03 16:55:15 +00:00
2021-07-09 15:13:08 +00:00
UI : : EventReturn AnalogSetupScreen : : OnResetToDefaults ( UI : : EventParams & e ) {
2021-07-09 15:25:00 +00:00
g_Config . fAnalogDeadzone = 0.15f ;
2021-07-09 15:13:08 +00:00
g_Config . fAnalogInverseDeadzone = 0.0f ;
g_Config . fAnalogSensitivity = 1.1f ;
g_Config . bAnalogIsCircular = false ;
g_Config . fAnalogAutoRotSpeed = 8.0f ;
return UI : : EVENT_DONE ;
}
2021-08-28 20:57:22 +00:00
class Backplate : public UI : : InertView {
public :
2024-10-10 09:55:07 +00:00
explicit Backplate ( float scale , UI : : LayoutParams * layoutParams = nullptr ) : InertView ( layoutParams ) , scale_ ( scale ) { }
2021-08-28 20:57:22 +00:00
void Draw ( UIContext & dc ) override {
2022-11-28 03:19:45 +00:00
for ( float dy = 0.0f ; dy < = 4.0f ; dy + = 1.0f ) {
for ( float dx = 0.0f ; dx < = 4.0f ; dx + = 1.0f ) {
if ( dx = = 2.0f & & dy = = 2.0f )
continue ;
DrawPSP ( dc , dx , dy , 0x06C1B6B6 ) ;
}
}
DrawPSP ( dc , 2.0f , 2.0f , 0xC01C1818 ) ;
}
void DrawPSP ( UIContext & dc , float xoff , float yoff , uint32_t color ) {
2021-08-28 20:57:22 +00:00
using namespace UI ;
const AtlasImage * whiteImage = dc . Draw ( ) - > GetAtlas ( ) - > getImage ( dc . theme - > whiteImage ) ;
float centerU = ( whiteImage - > u1 + whiteImage - > u2 ) * 0.5f ;
float centerV = ( whiteImage - > v1 + whiteImage - > v2 ) * 0.5f ;
auto V = [ & ] ( float x , float y ) {
2022-11-28 03:19:45 +00:00
dc . Draw ( ) - > V ( bounds_ . x + ( x + xoff ) * scale_ , bounds_ . y + ( y + yoff ) * scale_ , color , centerU , centerV ) ;
2021-08-28 20:57:22 +00:00
} ;
auto R = [ & ] ( float x1 , float y1 , float x2 , float y2 ) {
V ( x1 , y1 ) ; V ( x2 , y1 ) ; V ( x2 , y2 ) ;
V ( x1 , y1 ) ; V ( x2 , y2 ) ; V ( x1 , y2 ) ;
} ;
// Curved left side.
V ( 12.0f , 44.0f ) ; V ( 30.0f , 16.0f ) ; V ( 30.0f , 44.0f ) ;
V ( 0.0f , 80.0f ) ; V ( 12.0f , 44.0f ) ; V ( 12.0f , 80.0f ) ;
R ( 12.0f , 44.0f , 30.0f , 80.0f ) ;
R ( 0.0f , 80.0f , 30.0f , 114.0f ) ;
V ( 0.0f , 114.0f ) ; V ( 12.0f , 114.0f ) ; V ( 12.0f , 154.0f ) ;
R ( 12.0f , 114.0f , 30.0f , 154.0f ) ;
V ( 12.0f , 154.0f ) ; V ( 30.0f , 154.0f ) ; V ( 30.0f , 180.0f ) ;
// Left side.
V ( 30.0f , 16.0f ) ; V ( 64.0f , 13.0f ) ; V ( 64.0f , 184.0f ) ;
V ( 30.0f , 16.0f ) ; V ( 64.0f , 184.0f ) ; V ( 30.0f , 180.0f ) ;
V ( 64.0f , 13.0f ) ; V ( 76.0f , 0.0f ) ; V ( 76.0f , 13.0f ) ;
V ( 64.0f , 184.0f ) ; V ( 76.0f , 200.0f ) ; V ( 76.0f , 184.0f ) ;
R ( 64.0f , 13.0f , 76.0f , 184.0f ) ;
// Center.
2021-09-12 13:11:58 +00:00
R ( 76.0f , 0.0f , 400.0f , 13.0f ) ;
R ( 76.0f , 167.0f , 400.0f , 200.0f ) ;
R ( 76.0f , 13.0f , 99.0f , 167.0f ) ;
R ( 377.0f , 13.0f , 400.0f , 167.0f ) ;
2021-08-28 20:57:22 +00:00
// Right side.
V ( 400.0f , 0.0f ) ; V ( 412.0f , 13.0f ) ; V ( 400.0f , 13.0f ) ;
V ( 400.0f , 184.0f ) ; V ( 412.0f , 184.0f ) ; V ( 400.0f , 200.0f ) ;
R ( 400.0f , 13.0f , 412.0f , 184.0f ) ;
V ( 412.0f , 13.0f ) ; V ( 446.0f , 16.0f ) ; V ( 446.0f , 180.0f ) ;
V ( 412.0f , 13.0f ) ; V ( 446.0f , 180.0f ) ; V ( 412.0f , 184.0f ) ;
// Curved right side.
V ( 446.0f , 16.0f ) ; V ( 462.0f , 44.0f ) ; V ( 446.0f , 44.0f ) ;
V ( 462.0f , 44.0f ) ; V ( 474.0f , 80.0f ) ; V ( 462.0f , 80.0f ) ;
R ( 446.0f , 44.0f , 462.0f , 80.0f ) ;
R ( 446.0f , 80.0f , 474.0f , 114.0f ) ;
V ( 462.0f , 114.0f ) ; V ( 474.0f , 114.0f ) ; V ( 462.0f , 154.0f ) ;
R ( 446.0f , 114.0f , 462.0f , 154.0f ) ;
V ( 446.0f , 154.0f ) ; V ( 462.0f , 154.0f ) ; V ( 446.0f , 180.0f ) ;
}
void GetContentDimensions ( const UIContext & dc , float & w , float & h ) const override {
2022-11-28 03:19:45 +00:00
w = 478.0f * scale_ ;
h = 204.0f * scale_ ;
2021-08-28 20:57:22 +00:00
}
protected :
float scale_ = 1.0f ;
} ;
class MockScreen : public UI : : InertView {
public :
2024-10-10 09:55:07 +00:00
explicit MockScreen ( UI : : LayoutParams * layoutParams = nullptr ) : InertView ( layoutParams ) {
2021-08-28 20:57:22 +00:00
}
void Draw ( UIContext & dc ) override {
2021-09-12 13:11:58 +00:00
ImageID bg = ImageID ( " I_PSP_DISPLAY " ) ;
dc . Draw ( ) - > DrawImageStretch ( bg , bounds_ , 0x7FFFFFFF ) ;
2021-08-28 20:57:22 +00:00
}
} ;
2021-08-28 21:24:12 +00:00
class MockButton : public UI : : Clickable {
2021-08-28 20:57:22 +00:00
public :
MockButton ( int button , ImageID img , ImageID bg , float angle , UI : : LayoutParams * layoutParams = nullptr )
2021-08-28 21:24:12 +00:00
: Clickable ( layoutParams ) , button_ ( button ) , img_ ( img ) , bgImg_ ( bg ) , angle_ ( angle ) {
2021-08-28 20:57:22 +00:00
}
void Draw ( UIContext & dc ) override {
uint32_t c = 0xFFFFFFFF ;
2021-08-28 22:04:16 +00:00
if ( HasFocus ( ) | | Selected ( ) )
2022-02-14 12:57:22 +00:00
c = dc . theme - > itemFocusedStyle . background . color ;
2021-08-28 20:57:22 +00:00
float scales [ 2 ] { } ;
if ( bgImg_ . isValid ( ) )
dc . Draw ( ) - > DrawImageRotatedStretch ( bgImg_ , bounds_ , scales , angle_ , c , flipHBG_ ) ;
if ( img_ . isValid ( ) ) {
2021-09-12 13:11:58 +00:00
scales [ 0 ] * = scaleX_ ;
scales [ 1 ] * = scaleY_ ;
2023-01-29 01:42:23 +00:00
if ( timeLastPressed_ > = 0.0 ) {
double sincePress = time_now_d ( ) - timeLastPressed_ ;
if ( sincePress < 1.0 ) {
c = colorBlend ( c , dc . theme - > itemDownStyle . background . color , ( float ) sincePress ) ;
}
}
2021-08-28 20:57:22 +00:00
dc . Draw ( ) - > DrawImageRotatedStretch ( img_ , bounds_ . Offset ( offsetX_ , offsetY_ ) , scales , angle_ , c ) ;
}
}
MockButton * SetScale ( float s ) {
2021-09-12 13:11:58 +00:00
scaleX_ = s ;
scaleY_ = s ;
return this ;
}
MockButton * SetScale ( float x , float y ) {
scaleX_ = x ;
scaleY_ = y ;
2021-08-28 20:57:22 +00:00
return this ;
}
2024-10-10 12:10:30 +00:00
MockButton * SetFlipHBG ( bool b ) {
flipHBG_ = b ;
2021-08-28 20:57:22 +00:00
return this ;
}
MockButton * SetOffset ( float x , float y ) {
offsetX_ = x ;
offsetY_ = y ;
return this ;
}
2021-08-28 22:04:16 +00:00
MockButton * SetSelectedButton ( int * s ) {
selectedButton_ = s ;
return this ;
}
bool Selected ( ) {
return selectedButton_ & & * selectedButton_ = = button_ ;
}
2024-10-10 12:10:30 +00:00
int Button ( ) const {
2021-08-28 21:24:12 +00:00
return button_ ;
2021-08-28 20:57:22 +00:00
}
2023-01-29 01:42:23 +00:00
void NotifyPressed ( ) {
timeLastPressed_ = time_now_d ( ) ;
}
2021-08-28 22:04:16 +00:00
private :
2021-08-28 20:57:22 +00:00
int button_ ;
ImageID img_ ;
ImageID bgImg_ ;
float angle_ ;
2021-09-12 13:11:58 +00:00
float scaleX_ = 1.0f ;
float scaleY_ = 1.0f ;
2021-08-28 20:57:22 +00:00
float offsetX_ = 0.0f ;
float offsetY_ = 0.0f ;
2021-08-28 22:04:16 +00:00
bool flipHBG_ = false ;
int * selectedButton_ = nullptr ;
2023-01-29 01:42:23 +00:00
double timeLastPressed_ = - 1.0 ;
2021-08-28 20:57:22 +00:00
} ;
class MockPSP : public UI : : AnchorLayout {
public :
static constexpr float SCALE = 1.4f ;
2024-10-10 12:10:30 +00:00
explicit MockPSP ( UI : : LayoutParams * layoutParams = nullptr ) ;
2021-08-28 22:04:16 +00:00
void SelectButton ( int btn ) ;
2021-08-30 00:08:27 +00:00
void FocusButton ( int btn ) ;
2023-01-29 01:42:23 +00:00
void NotifyPressed ( int btn ) ;
2021-08-28 22:23:46 +00:00
float GetPopupOffset ( ) ;
2021-08-28 20:57:22 +00:00
2023-01-29 01:41:43 +00:00
bool SubviewFocused ( View * view ) override ;
2021-08-28 22:04:16 +00:00
UI : : Event ButtonClick ;
2021-08-28 20:57:22 +00:00
2021-08-28 22:04:16 +00:00
private :
UI : : AnchorLayoutParams * LayoutAt ( float l , float t , float r , float b ) ;
UI : : AnchorLayoutParams * LayoutSize ( float w , float h , float l , float t ) ;
MockButton * AddButton ( int button , ImageID img , ImageID bg , float angle , UI : : LayoutParams * lp ) ;
2021-08-28 20:57:22 +00:00
2021-08-28 22:04:16 +00:00
UI : : EventReturn OnSelectButton ( UI : : EventParams & e ) ;
2021-08-28 20:57:22 +00:00
2021-08-28 22:04:16 +00:00
std : : unordered_map < int , MockButton * > buttons_ ;
2023-01-29 01:41:43 +00:00
UI : : TextView * labelView_ = nullptr ;
2021-08-28 22:04:16 +00:00
int selectedButton_ = 0 ;
} ;
2021-08-28 20:57:22 +00:00
2021-08-28 22:04:16 +00:00
MockPSP : : MockPSP ( UI : : LayoutParams * layoutParams ) : AnchorLayout ( layoutParams ) {
Add ( new Backplate ( SCALE ) ) ;
Add ( new MockScreen ( LayoutAt ( 99.0f , 13.0f , 97.0f , 33.0f ) ) ) ;
// Left side.
AddButton ( VIRTKEY_AXIS_Y_MAX , ImageID ( " I_STICK_LINE " ) , ImageID ( " I_STICK_BG_LINE " ) , 0.0f , LayoutSize ( 34.0f , 34.0f , 35.0f , 133.0f ) ) ;
AddButton ( CTRL_LEFT , ImageID ( " I_ARROW " ) , ImageID ( " I_DIR_LINE " ) , M_PI * 0.0f , LayoutSize ( 28.0f , 20.0f , 14.0f , 75.0f ) ) - > SetOffset ( - 4.0f * SCALE , 0.0f ) ;
AddButton ( CTRL_UP , ImageID ( " I_ARROW " ) , ImageID ( " I_DIR_LINE " ) , M_PI * 0.5f , LayoutSize ( 20.0f , 28.0f , 40.0f , 50.0f ) ) - > SetOffset ( 0.0f , - 4.0f * SCALE ) ;
AddButton ( CTRL_RIGHT , ImageID ( " I_ARROW " ) , ImageID ( " I_DIR_LINE " ) , M_PI * 1.0f , LayoutSize ( 28.0f , 20.0f , 58.0f , 75.0f ) ) - > SetOffset ( 4.0f * SCALE , 0.0f ) ;
AddButton ( CTRL_DOWN , ImageID ( " I_ARROW " ) , ImageID ( " I_DIR_LINE " ) , M_PI * 1.5f , LayoutSize ( 20.0f , 28.0f , 40.0f , 92.0f ) ) - > SetOffset ( 0.0f , 4.0f * SCALE ) ;
// Top.
AddButton ( CTRL_LTRIGGER , ImageID ( " I_L " ) , ImageID ( " I_SHOULDER_LINE " ) , 0.0f , LayoutSize ( 50.0f , 16.0f , 29.0f , 0.0f ) ) ;
AddButton ( CTRL_RTRIGGER , ImageID ( " I_R " ) , ImageID ( " I_SHOULDER_LINE " ) , 0.0f , LayoutSize ( 50.0f , 16.0f , 397.0f , 0.0f ) ) - > SetFlipHBG ( true ) ;
// Bottom.
2021-09-12 13:11:58 +00:00
AddButton ( CTRL_HOME , ImageID ( " I_HOME " ) , ImageID ( " I_RECT_LINE " ) , 0.0f , LayoutSize ( 28.0f , 14.0f , 88.0f , 181.0f ) ) - > SetScale ( 1.0f , 0.65f ) ;
2021-08-28 22:04:16 +00:00
AddButton ( CTRL_SELECT , ImageID ( " I_SELECT " ) , ImageID ( " I_RECT_LINE " ) , 0.0f , LayoutSize ( 28.0f , 14.0f , 330.0f , 181.0f ) ) ;
AddButton ( CTRL_START , ImageID ( " I_START " ) , ImageID ( " I_RECT_LINE " ) , 0.0f , LayoutSize ( 28.0f , 14.0f , 361.0f , 181.0f ) ) ;
// Right side.
AddButton ( CTRL_TRIANGLE , ImageID ( " I_TRIANGLE " ) , ImageID ( " I_ROUND_LINE " ) , 0.0f , LayoutSize ( 23.0f , 23.0f , 419.0f , 46.0f ) ) - > SetScale ( 0.7f ) - > SetOffset ( 0.0f , - 1.0f * SCALE ) ;
AddButton ( CTRL_CIRCLE , ImageID ( " I_CIRCLE " ) , ImageID ( " I_ROUND_LINE " ) , 0.0f , LayoutSize ( 23.0f , 23.0f , 446.0f , 74.0f ) ) - > SetScale ( 0.7f ) ;
AddButton ( CTRL_CROSS , ImageID ( " I_CROSS " ) , ImageID ( " I_ROUND_LINE " ) , 0.0f , LayoutSize ( 23.0f , 23.0f , 419.0f , 102.0f ) ) - > SetScale ( 0.7f ) ;
AddButton ( CTRL_SQUARE , ImageID ( " I_SQUARE " ) , ImageID ( " I_ROUND_LINE " ) , 0.0f , LayoutSize ( 23.0f , 23.0f , 392.0f , 74.0f ) ) - > SetScale ( 0.7f ) ;
2023-01-29 01:41:43 +00:00
labelView_ = Add ( new UI : : TextView ( " " ) ) ;
labelView_ - > SetShadow ( true ) ;
labelView_ - > SetVisibility ( UI : : V_GONE ) ;
2021-08-28 22:04:16 +00:00
}
2021-08-28 21:24:12 +00:00
2021-08-28 22:04:16 +00:00
void MockPSP : : SelectButton ( int btn ) {
selectedButton_ = btn ;
}
2021-08-28 20:57:22 +00:00
2021-08-30 00:08:27 +00:00
void MockPSP : : FocusButton ( int btn ) {
2023-01-29 01:41:43 +00:00
MockButton * view = buttons_ [ btn ] ;
if ( view ) {
2021-08-30 00:08:27 +00:00
view - > SetFocus ( ) ;
2023-01-29 01:41:43 +00:00
} else {
labelView_ - > SetVisibility ( UI : : V_GONE ) ;
}
}
2023-01-29 01:42:23 +00:00
void MockPSP : : NotifyPressed ( int btn ) {
MockButton * view = buttons_ [ btn ] ;
if ( view )
view - > NotifyPressed ( ) ;
}
2023-01-29 01:41:43 +00:00
bool MockPSP : : SubviewFocused ( View * view ) {
for ( auto it : buttons_ ) {
if ( view = = it . second ) {
labelView_ - > SetVisibility ( UI : : V_VISIBLE ) ;
labelView_ - > SetText ( KeyMap : : GetPspButtonName ( it . first ) ) ;
const Bounds & pos = view - > GetBounds ( ) . Offset ( - GetBounds ( ) . x , - GetBounds ( ) . y ) ;
labelView_ - > ReplaceLayoutParams ( new UI : : AnchorLayoutParams ( pos . centerX ( ) , pos . y2 ( ) + 5 , UI : : NONE , UI : : NONE ) ) ;
}
}
return AnchorLayout : : SubviewFocused ( view ) ;
2021-08-30 00:08:27 +00:00
}
2021-08-28 22:23:46 +00:00
float MockPSP : : GetPopupOffset ( ) {
MockButton * view = buttons_ [ selectedButton_ ] ;
if ( ! view )
return 0.0f ;
float ypos = view - > GetBounds ( ) . centerY ( ) ;
if ( ypos > bounds_ . centerY ( ) ) {
return - 0.25f ;
}
return 0.25f ;
}
2021-08-28 22:04:16 +00:00
UI : : AnchorLayoutParams * MockPSP : : LayoutAt ( float l , float t , float r , float b ) {
return new UI : : AnchorLayoutParams ( l * SCALE , t * SCALE , r * SCALE , b * SCALE ) ;
}
UI : : AnchorLayoutParams * MockPSP : : LayoutSize ( float w , float h , float l , float t ) {
return new UI : : AnchorLayoutParams ( w * SCALE , h * SCALE , l * SCALE , t * SCALE , UI : : NONE , UI : : NONE ) ;
}
2021-08-28 21:24:12 +00:00
2021-08-28 22:04:16 +00:00
MockButton * MockPSP : : AddButton ( int button , ImageID img , ImageID bg , float angle , UI : : LayoutParams * lp ) {
MockButton * view = Add ( new MockButton ( button , img , bg , angle , lp ) ) ;
view - > OnClick . Handle ( this , & MockPSP : : OnSelectButton ) ;
view - > SetSelectedButton ( & selectedButton_ ) ;
buttons_ [ button ] = view ;
return view ;
}
2021-08-28 20:57:22 +00:00
2021-08-28 22:04:16 +00:00
UI : : EventReturn MockPSP : : OnSelectButton ( UI : : EventParams & e ) {
auto view = ( MockButton * ) e . v ;
e . a = view - > Button ( ) ;
return ButtonClick . Dispatch ( e ) ;
}
static std : : vector < int > bindAllOrder {
CTRL_LTRIGGER ,
CTRL_RTRIGGER ,
CTRL_UP ,
CTRL_DOWN ,
CTRL_LEFT ,
CTRL_RIGHT ,
VIRTKEY_AXIS_Y_MAX ,
VIRTKEY_AXIS_Y_MIN ,
VIRTKEY_AXIS_X_MIN ,
VIRTKEY_AXIS_X_MAX ,
CTRL_HOME ,
CTRL_SELECT ,
CTRL_START ,
CTRL_CROSS ,
CTRL_CIRCLE ,
CTRL_TRIANGLE ,
CTRL_SQUARE ,
2021-08-28 20:57:22 +00:00
} ;
void VisualMappingScreen : : CreateViews ( ) {
using namespace UI ;
2023-04-05 22:34:50 +00:00
auto km = GetI18NCategory ( I18NCat : : KEYMAPPING ) ;
2021-08-28 20:57:22 +00:00
root_ = new LinearLayout ( ORIENT_HORIZONTAL ) ;
constexpr float leftColumnWidth = 200.0f ;
LinearLayout * leftColumn = new LinearLayout ( ORIENT_VERTICAL , new LinearLayoutParams ( leftColumnWidth , FILL_PARENT , Margins ( 10 , 0 , 0 , 10 ) ) ) ;
2021-08-28 22:04:16 +00:00
leftColumn - > Add ( new Choice ( km - > T ( " Bind All " ) ) ) - > OnClick . Handle ( this , & VisualMappingScreen : : OnBindAll ) ;
leftColumn - > Add ( new CheckBox ( & replace_ , km - > T ( " Replace " ) , " " ) ) ;
2021-08-28 20:57:22 +00:00
leftColumn - > Add ( new Spacer ( new LinearLayoutParams ( 1.0f ) ) ) ;
AddStandardBack ( leftColumn ) ;
Bounds bounds = screenManager ( ) - > getUIContext ( ) - > GetLayoutBounds ( ) ;
// Account for left side.
bounds . w - = leftColumnWidth + 10.0f ;
AnchorLayout * rightColumn = new AnchorLayout ( new LinearLayoutParams ( bounds . w , FILL_PARENT , 1.0f ) ) ;
2021-08-28 22:04:16 +00:00
psp_ = rightColumn - > Add ( new MockPSP ( new AnchorLayoutParams ( bounds . centerX ( ) , bounds . centerY ( ) , NONE , NONE , true ) ) ) ;
psp_ - > ButtonClick . Handle ( this , & VisualMappingScreen : : OnMapButton ) ;
2021-08-28 20:57:22 +00:00
root_ - > Add ( leftColumn ) ;
root_ - > Add ( rightColumn ) ;
}
2021-08-28 21:24:12 +00:00
2023-01-29 01:42:23 +00:00
bool VisualMappingScreen : : key ( const KeyInput & key ) {
if ( key . flags & KEY_DOWN ) {
std : : vector < int > pspKeys ;
2023-03-29 09:59:31 +00:00
KeyMap : : InputMappingToPspButton ( InputMapping ( key . deviceId , key . keyCode ) , & pspKeys ) ;
2023-01-29 01:42:23 +00:00
for ( int pspKey : pspKeys ) {
switch ( pspKey ) {
case VIRTKEY_AXIS_X_MIN :
case VIRTKEY_AXIS_Y_MIN :
case VIRTKEY_AXIS_X_MAX :
case VIRTKEY_AXIS_Y_MAX :
psp_ - > NotifyPressed ( VIRTKEY_AXIS_Y_MAX ) ;
break ;
default :
psp_ - > NotifyPressed ( pspKey ) ;
break ;
}
}
}
return UIDialogScreenWithGameBackground : : key ( key ) ;
}
void VisualMappingScreen : : axis ( const AxisInput & axis ) {
std : : vector < int > results ;
if ( axis . value > = g_Config . fAnalogDeadzone * 0.7f )
2023-03-29 09:59:31 +00:00
KeyMap : : InputMappingToPspButton ( InputMapping ( axis . deviceId , axis . axisId , 1 ) , & results ) ;
2023-01-29 01:42:23 +00:00
if ( axis . value < = g_Config . fAnalogDeadzone * - 0.7f )
2023-03-29 09:59:31 +00:00
KeyMap : : InputMappingToPspButton ( InputMapping ( axis . deviceId , axis . axisId , - 1 ) , & results ) ;
2023-01-29 01:42:23 +00:00
for ( int result : results ) {
switch ( result ) {
case VIRTKEY_AXIS_X_MIN :
case VIRTKEY_AXIS_Y_MIN :
case VIRTKEY_AXIS_X_MAX :
case VIRTKEY_AXIS_Y_MAX :
psp_ - > NotifyPressed ( VIRTKEY_AXIS_Y_MAX ) ;
break ;
default :
psp_ - > NotifyPressed ( result ) ;
break ;
}
}
UIDialogScreenWithGameBackground : : axis ( axis ) ;
}
2021-08-28 22:23:46 +00:00
void VisualMappingScreen : : resized ( ) {
2022-11-22 21:53:54 +00:00
UIDialogScreenWithGameBackground : : resized ( ) ;
2021-08-28 22:23:46 +00:00
RecreateViews ( ) ;
}
2021-08-28 21:24:12 +00:00
2021-08-28 22:23:46 +00:00
UI : : EventReturn VisualMappingScreen : : OnMapButton ( UI : : EventParams & e ) {
2021-08-28 21:37:53 +00:00
nextKey_ = e . a ;
2021-10-08 01:45:15 +00:00
MapNext ( false ) ;
2021-08-28 22:04:16 +00:00
return UI : : EVENT_DONE ;
}
UI : : EventReturn VisualMappingScreen : : OnBindAll ( UI : : EventParams & e ) {
bindAll_ = 0 ;
nextKey_ = bindAllOrder [ bindAll_ ] ;
2021-10-08 01:45:15 +00:00
MapNext ( false ) ;
2021-08-28 21:24:12 +00:00
return UI : : EVENT_DONE ;
}
2021-08-28 21:37:53 +00:00
2023-12-14 11:23:31 +00:00
void VisualMappingScreen : : HandleKeyMapping ( const KeyMap : : MultiInputMapping & key ) {
2023-03-29 09:59:31 +00:00
KeyMap : : SetInputMapping ( nextKey_ , key , replace_ ) ;
2023-04-01 20:30:34 +00:00
KeyMap : : UpdateNativeMenuKeys ( ) ;
2021-08-28 22:04:16 +00:00
if ( bindAll_ < 0 ) {
// For analog, we do each direction in a row.
if ( nextKey_ = = VIRTKEY_AXIS_Y_MAX )
nextKey_ = VIRTKEY_AXIS_Y_MIN ;
else if ( nextKey_ = = VIRTKEY_AXIS_Y_MIN )
nextKey_ = VIRTKEY_AXIS_X_MIN ;
else if ( nextKey_ = = VIRTKEY_AXIS_X_MIN )
nextKey_ = VIRTKEY_AXIS_X_MAX ;
2021-08-30 00:08:27 +00:00
else {
if ( nextKey_ = = VIRTKEY_AXIS_X_MAX )
psp_ - > FocusButton ( VIRTKEY_AXIS_Y_MAX ) ;
else
psp_ - > FocusButton ( nextKey_ ) ;
2021-08-28 22:04:16 +00:00
nextKey_ = 0 ;
2021-08-30 00:08:27 +00:00
}
2021-08-28 22:04:16 +00:00
} else if ( ( size_t ) bindAll_ + 1 < bindAllOrder . size ( ) ) {
bindAll_ + + ;
nextKey_ = bindAllOrder [ bindAll_ ] ;
} else {
bindAll_ = - 1 ;
2021-08-28 21:37:53 +00:00
nextKey_ = 0 ;
2021-08-28 22:04:16 +00:00
}
2021-08-28 21:37:53 +00:00
}
void VisualMappingScreen : : dialogFinished ( const Screen * dialog , DialogResult result ) {
2021-08-28 22:04:16 +00:00
if ( result = = DR_YES & & nextKey_ ! = 0 ) {
2021-10-08 01:45:15 +00:00
MapNext ( true ) ;
2021-08-28 21:37:53 +00:00
} else {
2021-08-30 00:08:27 +00:00
// This means they canceled.
if ( nextKey_ ! = 0 )
psp_ - > FocusButton ( nextKey_ ) ;
2021-08-28 21:37:53 +00:00
nextKey_ = 0 ;
2021-08-28 22:04:16 +00:00
bindAll_ = - 1 ;
psp_ - > SelectButton ( 0 ) ;
2021-08-28 21:37:53 +00:00
}
2021-08-28 22:23:46 +00:00
}
2021-08-28 22:04:16 +00:00
2021-10-08 01:45:15 +00:00
void VisualMappingScreen : : MapNext ( bool successive ) {
2021-08-28 22:23:46 +00:00
if ( nextKey_ = = VIRTKEY_AXIS_Y_MIN | | nextKey_ = = VIRTKEY_AXIS_X_MIN | | nextKey_ = = VIRTKEY_AXIS_X_MAX ) {
psp_ - > SelectButton ( VIRTKEY_AXIS_Y_MAX ) ;
} else {
psp_ - > SelectButton ( nextKey_ ) ;
}
2023-04-05 22:34:50 +00:00
auto dialog = new KeyMappingNewKeyDialog ( nextKey_ , true , std : : bind ( & VisualMappingScreen : : HandleKeyMapping , this , std : : placeholders : : _1 ) , I18NCat : : KEYMAPPING ) ;
2021-08-28 22:23:46 +00:00
Bounds bounds = screenManager ( ) - > getUIContext ( ) - > GetLayoutBounds ( ) ;
dialog - > SetPopupOffset ( psp_ - > GetPopupOffset ( ) * bounds . h ) ;
2021-10-08 01:45:15 +00:00
dialog - > SetDelay ( successive ? 0.5f : 0.1f ) ;
2021-08-28 22:23:46 +00:00
screenManager ( ) - > push ( dialog ) ;
2021-08-28 21:37:53 +00:00
}