merge squash feat/mapping_setting

This commit is contained in:
Greenlamp 2024-05-21 14:28:17 +02:00
parent 3fd1ecf6a7
commit 9e5b5c2a42
43 changed files with 5992 additions and 312 deletions

View File

@ -146,7 +146,9 @@ body {
margin-left: 10%;
}
#touchControls:not([data-ui-mode='STARTER_SELECT']) #apad .apadRectBtnContainer > .apadSqBtn, #touchControls:not([data-ui-mode='STARTER_SELECT']) #apad .apadSqBtnContainer {
#touchControls:not([data-ui-mode='STARTER_SELECT']):not([data-ui-mode='SETTINGS']):not([data-ui-mode='SETTINGS_GAMEPAD']):not([data-ui-mode='SETTINGS_KEYBOARD']) #apad .apadRectBtnContainer > .apadSqBtn,
#touchControls:not([data-ui-mode='STARTER_SELECT']):not([data-ui-mode='SETTINGS']):not([data-ui-mode='SETTINGS_GAMEPAD']):not([data-ui-mode='SETTINGS_KEYBOARD']) #apad .apadSqBtnContainer
{
display: none;
}

View File

@ -0,0 +1,348 @@
{"frames": {
"T_P4_Circle_Color_Default.png":
{
"frame": {"x":0,"y":0,"w":128,"h":128},
"rotated": false,
"trimmed": false,
"spriteSourceSize": {"x":0,"y":0,"w":128,"h":128},
"sourceSize": {"w":128,"h":128}
},
"T_P4_Circle_Default.png":
{
"frame": {"x":128,"y":0,"w":128,"h":128},
"rotated": false,
"trimmed": false,
"spriteSourceSize": {"x":0,"y":0,"w":128,"h":128},
"sourceSize": {"w":128,"h":128}
},
"T_P4_Cross_Color_Default.png":
{
"frame": {"x":256,"y":0,"w":128,"h":128},
"rotated": false,
"trimmed": false,
"spriteSourceSize": {"x":0,"y":0,"w":128,"h":128},
"sourceSize": {"w":128,"h":128}
},
"T_P4_Cross_Default.png":
{
"frame": {"x":384,"y":0,"w":128,"h":128},
"rotated": false,
"trimmed": false,
"spriteSourceSize": {"x":0,"y":0,"w":128,"h":128},
"sourceSize": {"w":128,"h":128}
},
"T_P4_Dpad_Default.png":
{
"frame": {"x":512,"y":0,"w":128,"h":128},
"rotated": false,
"trimmed": false,
"spriteSourceSize": {"x":0,"y":0,"w":128,"h":128},
"sourceSize": {"w":128,"h":128}
},
"T_P4_Dpad_Down_Default.png":
{
"frame": {"x":640,"y":0,"w":128,"h":128},
"rotated": false,
"trimmed": false,
"spriteSourceSize": {"x":0,"y":0,"w":128,"h":128},
"sourceSize": {"w":128,"h":128}
},
"T_P4_Dpad_Left_Default.png":
{
"frame": {"x":768,"y":0,"w":128,"h":128},
"rotated": false,
"trimmed": false,
"spriteSourceSize": {"x":0,"y":0,"w":128,"h":128},
"sourceSize": {"w":128,"h":128}
},
"T_P4_Dpad_Right_Default.png":
{
"frame": {"x":896,"y":0,"w":128,"h":128},
"rotated": false,
"trimmed": false,
"spriteSourceSize": {"x":0,"y":0,"w":128,"h":128},
"sourceSize": {"w":128,"h":128}
},
"T_P4_Dpad_UP_Default.png":
{
"frame": {"x":1024,"y":0,"w":128,"h":128},
"rotated": false,
"trimmed": false,
"spriteSourceSize": {"x":0,"y":0,"w":128,"h":128},
"sourceSize": {"w":128,"h":128}
},
"T_P4_Dpad_X_Default.png":
{
"frame": {"x":1152,"y":0,"w":128,"h":128},
"rotated": false,
"trimmed": false,
"spriteSourceSize": {"x":0,"y":0,"w":128,"h":128},
"sourceSize": {"w":128,"h":128}
},
"T_P4_Dpad_Y_Default.png":
{
"frame": {"x":1280,"y":0,"w":128,"h":128},
"rotated": false,
"trimmed": false,
"spriteSourceSize": {"x":0,"y":0,"w":128,"h":128},
"sourceSize": {"w":128,"h":128}
},
"T_P4_L1_Default.png":
{
"frame": {"x":1408,"y":0,"w":128,"h":128},
"rotated": false,
"trimmed": false,
"spriteSourceSize": {"x":0,"y":0,"w":128,"h":128},
"sourceSize": {"w":128,"h":128}
},
"T_P4_L2_Default.png":
{
"frame": {"x":1536,"y":0,"w":128,"h":128},
"rotated": false,
"trimmed": false,
"spriteSourceSize": {"x":0,"y":0,"w":128,"h":128},
"sourceSize": {"w":128,"h":128}
},
"T_P4_L_2D_Default.png":
{
"frame": {"x":1664,"y":0,"w":128,"h":128},
"rotated": false,
"trimmed": false,
"spriteSourceSize": {"x":0,"y":0,"w":128,"h":128},
"sourceSize": {"w":128,"h":128}
},
"T_P4_L_Default.png":
{
"frame": {"x":0,"y":128,"w":128,"h":128},
"rotated": false,
"trimmed": false,
"spriteSourceSize": {"x":0,"y":0,"w":128,"h":128},
"sourceSize": {"w":128,"h":128}
},
"T_P4_L_Down_Default.png":
{
"frame": {"x":128,"y":128,"w":128,"h":128},
"rotated": false,
"trimmed": false,
"spriteSourceSize": {"x":0,"y":0,"w":128,"h":128},
"sourceSize": {"w":128,"h":128}
},
"T_P4_L_Left_Default.png":
{
"frame": {"x":256,"y":128,"w":128,"h":128},
"rotated": false,
"trimmed": false,
"spriteSourceSize": {"x":0,"y":0,"w":128,"h":128},
"sourceSize": {"w":128,"h":128}
},
"T_P4_L_Right_Default.png":
{
"frame": {"x":384,"y":128,"w":128,"h":128},
"rotated": false,
"trimmed": false,
"spriteSourceSize": {"x":0,"y":0,"w":128,"h":128},
"sourceSize": {"w":128,"h":128}
},
"T_P4_L_UP_Default.png":
{
"frame": {"x":512,"y":128,"w":128,"h":128},
"rotated": false,
"trimmed": false,
"spriteSourceSize": {"x":0,"y":0,"w":128,"h":128},
"sourceSize": {"w":128,"h":128}
},
"T_P4_L_X_Default.png":
{
"frame": {"x":640,"y":128,"w":128,"h":128},
"rotated": false,
"trimmed": false,
"spriteSourceSize": {"x":0,"y":0,"w":128,"h":128},
"sourceSize": {"w":128,"h":128}
},
"T_P4_L_Y_Default.png":
{
"frame": {"x":768,"y":128,"w":128,"h":128},
"rotated": false,
"trimmed": false,
"spriteSourceSize": {"x":0,"y":0,"w":128,"h":128},
"sourceSize": {"w":128,"h":128}
},
"T_P4_Left_Stick_Click_Alt_Default.png":
{
"frame": {"x":896,"y":128,"w":128,"h":128},
"rotated": false,
"trimmed": false,
"spriteSourceSize": {"x":0,"y":0,"w":128,"h":128},
"sourceSize": {"w":128,"h":128}
},
"T_P4_Left_Stick_Click_Default-1.png":
{
"frame": {"x":1024,"y":128,"w":128,"h":128},
"rotated": false,
"trimmed": false,
"spriteSourceSize": {"x":0,"y":0,"w":128,"h":128},
"sourceSize": {"w":128,"h":128}
},
"T_P4_Left_Stick_Click_Default.png":
{
"frame": {"x":1152,"y":128,"w":128,"h":128},
"rotated": false,
"trimmed": false,
"spriteSourceSize": {"x":0,"y":0,"w":128,"h":128},
"sourceSize": {"w":128,"h":128}
},
"T_P4_Options_Default.png":
{
"frame": {"x":1280,"y":128,"w":128,"h":128},
"rotated": false,
"trimmed": false,
"spriteSourceSize": {"x":0,"y":0,"w":128,"h":128},
"sourceSize": {"w":128,"h":128}
},
"T_P4_R1_Default.png":
{
"frame": {"x":1408,"y":128,"w":128,"h":128},
"rotated": false,
"trimmed": false,
"spriteSourceSize": {"x":0,"y":0,"w":128,"h":128},
"sourceSize": {"w":128,"h":128}
},
"T_P4_R2_Default.png":
{
"frame": {"x":1536,"y":128,"w":128,"h":128},
"rotated": false,
"trimmed": false,
"spriteSourceSize": {"x":0,"y":0,"w":128,"h":128},
"sourceSize": {"w":128,"h":128}
},
"T_P4_R_2D_Default.png":
{
"frame": {"x":1664,"y":128,"w":128,"h":128},
"rotated": false,
"trimmed": false,
"spriteSourceSize": {"x":0,"y":0,"w":128,"h":128},
"sourceSize": {"w":128,"h":128}
},
"T_P4_R_Default.png":
{
"frame": {"x":0,"y":256,"w":128,"h":128},
"rotated": false,
"trimmed": false,
"spriteSourceSize": {"x":0,"y":0,"w":128,"h":128},
"sourceSize": {"w":128,"h":128}
},
"T_P4_R_Down_Default.png":
{
"frame": {"x":128,"y":256,"w":128,"h":128},
"rotated": false,
"trimmed": false,
"spriteSourceSize": {"x":0,"y":0,"w":128,"h":128},
"sourceSize": {"w":128,"h":128}
},
"T_P4_R_Left_Default.png":
{
"frame": {"x":256,"y":256,"w":128,"h":128},
"rotated": false,
"trimmed": false,
"spriteSourceSize": {"x":0,"y":0,"w":128,"h":128},
"sourceSize": {"w":128,"h":128}
},
"T_P4_R_Right_Default.png":
{
"frame": {"x":384,"y":256,"w":128,"h":128},
"rotated": false,
"trimmed": false,
"spriteSourceSize": {"x":0,"y":0,"w":128,"h":128},
"sourceSize": {"w":128,"h":128}
},
"T_P4_R_UP_Default.png":
{
"frame": {"x":512,"y":256,"w":128,"h":128},
"rotated": false,
"trimmed": false,
"spriteSourceSize": {"x":0,"y":0,"w":128,"h":128},
"sourceSize": {"w":128,"h":128}
},
"T_P4_R_X_Default.png":
{
"frame": {"x":640,"y":256,"w":128,"h":128},
"rotated": false,
"trimmed": false,
"spriteSourceSize": {"x":0,"y":0,"w":128,"h":128},
"sourceSize": {"w":128,"h":128}
},
"T_P4_R_Y_Default.png":
{
"frame": {"x":768,"y":256,"w":128,"h":128},
"rotated": false,
"trimmed": false,
"spriteSourceSize": {"x":0,"y":0,"w":128,"h":128},
"sourceSize": {"w":128,"h":128}
},
"T_P4_Right_Stick_Click_Alt_Default.png":
{
"frame": {"x":896,"y":256,"w":128,"h":128},
"rotated": false,
"trimmed": false,
"spriteSourceSize": {"x":0,"y":0,"w":128,"h":128},
"sourceSize": {"w":128,"h":128}
},
"T_P4_Share_Default.png":
{
"frame": {"x":1024,"y":256,"w":128,"h":128},
"rotated": false,
"trimmed": false,
"spriteSourceSize": {"x":0,"y":0,"w":128,"h":128},
"sourceSize": {"w":128,"h":128}
},
"T_P4_Square_Color_Default.png":
{
"frame": {"x":1152,"y":256,"w":128,"h":128},
"rotated": false,
"trimmed": false,
"spriteSourceSize": {"x":0,"y":0,"w":128,"h":128},
"sourceSize": {"w":128,"h":128}
},
"T_P4_Square_Default.png":
{
"frame": {"x":1280,"y":256,"w":128,"h":128},
"rotated": false,
"trimmed": false,
"spriteSourceSize": {"x":0,"y":0,"w":128,"h":128},
"sourceSize": {"w":128,"h":128}
},
"T_P4_Touch_Pad_Default.png":
{
"frame": {"x":1408,"y":256,"w":128,"h":128},
"rotated": false,
"trimmed": false,
"spriteSourceSize": {"x":0,"y":0,"w":128,"h":128},
"sourceSize": {"w":128,"h":128}
},
"T_P4_Triangle_Color_Default.png":
{
"frame": {"x":1536,"y":256,"w":128,"h":128},
"rotated": false,
"trimmed": false,
"spriteSourceSize": {"x":0,"y":0,"w":128,"h":128},
"sourceSize": {"w":128,"h":128}
},
"T_P4_Triangle_Default.png":
{
"frame": {"x":1664,"y":256,"w":128,"h":128},
"rotated": false,
"trimmed": false,
"spriteSourceSize": {"x":0,"y":0,"w":128,"h":128},
"sourceSize": {"w":128,"h":128}
}},
"meta": {
"app": "https://www.codeandweb.com/texturepacker",
"version": "1.0",
"image": "dualshock.png",
"format": "RGBA8888",
"size": {"w":1792,"h":384},
"scale": "1",
"smartupdate": "$TexturePacker:SmartUpdate:987743e379168b07fdf2bb169758063f:318efd1c2db07d7c85f4d230278c0da3:adc25708364be3d9e70074e95305c745$"
}
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 80 KiB

View File

@ -0,0 +1,644 @@
{"frames": [
{
"filename": "T_0_Key_Dark.png",
"frame": {"x":0,"y":0,"w":128,"h":128},
"rotated": false,
"trimmed": false,
"spriteSourceSize": {"x":0,"y":0,"w":128,"h":128},
"sourceSize": {"w":128,"h":128}
},
{
"filename": "T_1_Key_Dark.png",
"frame": {"x":128,"y":0,"w":128,"h":128},
"rotated": false,
"trimmed": false,
"spriteSourceSize": {"x":0,"y":0,"w":128,"h":128},
"sourceSize": {"w":128,"h":128}
},
{
"filename": "T_2_Key_Dark.png",
"frame": {"x":256,"y":0,"w":128,"h":128},
"rotated": false,
"trimmed": false,
"spriteSourceSize": {"x":0,"y":0,"w":128,"h":128},
"sourceSize": {"w":128,"h":128}
},
{
"filename": "T_3_Key_Dark-1.png",
"frame": {"x":384,"y":0,"w":128,"h":128},
"rotated": false,
"trimmed": false,
"spriteSourceSize": {"x":0,"y":0,"w":128,"h":128},
"sourceSize": {"w":128,"h":128}
},
{
"filename": "T_3_Key_Dark.png",
"frame": {"x":512,"y":0,"w":128,"h":128},
"rotated": false,
"trimmed": false,
"spriteSourceSize": {"x":0,"y":0,"w":128,"h":128},
"sourceSize": {"w":128,"h":128}
},
{
"filename": "T_5_Key_Dark.png",
"frame": {"x":640,"y":0,"w":128,"h":128},
"rotated": false,
"trimmed": false,
"spriteSourceSize": {"x":0,"y":0,"w":128,"h":128},
"sourceSize": {"w":128,"h":128}
},
{
"filename": "T_6_Key_Dark.png",
"frame": {"x":768,"y":0,"w":128,"h":128},
"rotated": false,
"trimmed": false,
"spriteSourceSize": {"x":0,"y":0,"w":128,"h":128},
"sourceSize": {"w":128,"h":128}
},
{
"filename": "T_7_Key_Dark.png",
"frame": {"x":896,"y":0,"w":128,"h":128},
"rotated": false,
"trimmed": false,
"spriteSourceSize": {"x":0,"y":0,"w":128,"h":128},
"sourceSize": {"w":128,"h":128}
},
{
"filename": "T_8_Key_Dark.png",
"frame": {"x":1024,"y":0,"w":128,"h":128},
"rotated": false,
"trimmed": false,
"spriteSourceSize": {"x":0,"y":0,"w":128,"h":128},
"sourceSize": {"w":128,"h":128}
},
{
"filename": "T_9_Key_Dark.png",
"frame": {"x":1152,"y":0,"w":128,"h":128},
"rotated": false,
"trimmed": false,
"spriteSourceSize": {"x":0,"y":0,"w":128,"h":128},
"sourceSize": {"w":128,"h":128}
},
{
"filename": "T_A_Key_Dark.png",
"frame": {"x":1280,"y":0,"w":128,"h":128},
"rotated": false,
"trimmed": false,
"spriteSourceSize": {"x":0,"y":0,"w":128,"h":128},
"sourceSize": {"w":128,"h":128}
},
{
"filename": "T_Alt_Key_Dark.png",
"frame": {"x":1408,"y":0,"w":128,"h":128},
"rotated": false,
"trimmed": false,
"spriteSourceSize": {"x":0,"y":0,"w":128,"h":128},
"sourceSize": {"w":128,"h":128}
},
{
"filename": "T_Asterisk_Key_Dark.png",
"frame": {"x":1536,"y":0,"w":128,"h":128},
"rotated": false,
"trimmed": false,
"spriteSourceSize": {"x":0,"y":0,"w":128,"h":128},
"sourceSize": {"w":128,"h":128}
},
{
"filename": "T_B_Key_Dark.png",
"frame": {"x":1664,"y":0,"w":128,"h":128},
"rotated": false,
"trimmed": false,
"spriteSourceSize": {"x":0,"y":0,"w":128,"h":128},
"sourceSize": {"w":128,"h":128}
},
{
"filename": "T_Backspace_Alt_Key_Dark.png",
"frame": {"x":1792,"y":0,"w":128,"h":128},
"rotated": false,
"trimmed": false,
"spriteSourceSize": {"x":0,"y":0,"w":128,"h":128},
"sourceSize": {"w":128,"h":128}
},
{
"filename": "T_BackSpace_Key_Dark.png",
"frame": {"x":1920,"y":0,"w":128,"h":128},
"rotated": false,
"trimmed": false,
"spriteSourceSize": {"x":0,"y":0,"w":128,"h":128},
"sourceSize": {"w":128,"h":128}
},
{
"filename": "T_Brackets_L_Key_Dark.png",
"frame": {"x":0,"y":128,"w":128,"h":128},
"rotated": false,
"trimmed": false,
"spriteSourceSize": {"x":0,"y":0,"w":128,"h":128},
"sourceSize": {"w":128,"h":128}
},
{
"filename": "T_Brackets_R_Key_Dark.png",
"frame": {"x":128,"y":128,"w":128,"h":128},
"rotated": false,
"trimmed": false,
"spriteSourceSize": {"x":0,"y":0,"w":128,"h":128},
"sourceSize": {"w":128,"h":128}
},
{
"filename": "T_C_Key_Dark.png",
"frame": {"x":256,"y":128,"w":128,"h":128},
"rotated": false,
"trimmed": false,
"spriteSourceSize": {"x":0,"y":0,"w":128,"h":128},
"sourceSize": {"w":128,"h":128}
},
{
"filename": "T_Crtl_Key_Dark.png",
"frame": {"x":384,"y":128,"w":128,"h":128},
"rotated": false,
"trimmed": false,
"spriteSourceSize": {"x":0,"y":0,"w":128,"h":128},
"sourceSize": {"w":128,"h":128}
},
{
"filename": "T_D_Key_Dark.png",
"frame": {"x":512,"y":128,"w":128,"h":128},
"rotated": false,
"trimmed": false,
"spriteSourceSize": {"x":0,"y":0,"w":128,"h":128},
"sourceSize": {"w":128,"h":128}
},
{
"filename": "T_Del_Key_Dark.png",
"frame": {"x":640,"y":128,"w":128,"h":128},
"rotated": false,
"trimmed": false,
"spriteSourceSize": {"x":0,"y":0,"w":128,"h":128},
"sourceSize": {"w":128,"h":128}
},
{
"filename": "T_Down_Key_Dark.png",
"frame": {"x":768,"y":128,"w":128,"h":128},
"rotated": false,
"trimmed": false,
"spriteSourceSize": {"x":0,"y":0,"w":128,"h":128},
"sourceSize": {"w":128,"h":128}
},
{
"filename": "T_E_Key_Dark.png",
"frame": {"x":896,"y":128,"w":128,"h":128},
"rotated": false,
"trimmed": false,
"spriteSourceSize": {"x":0,"y":0,"w":128,"h":128},
"sourceSize": {"w":128,"h":128}
},
{
"filename": "T_End_Key_Dark.png",
"frame": {"x":1024,"y":128,"w":128,"h":128},
"rotated": false,
"trimmed": false,
"spriteSourceSize": {"x":0,"y":0,"w":128,"h":128},
"sourceSize": {"w":128,"h":128}
},
{
"filename": "T_Enter_Alt_Key_Dark.png",
"frame": {"x":1152,"y":128,"w":128,"h":128},
"rotated": false,
"trimmed": false,
"spriteSourceSize": {"x":0,"y":0,"w":128,"h":128},
"sourceSize": {"w":128,"h":128}
},
{
"filename": "T_Esc_Key_Dark.png",
"frame": {"x":1280,"y":128,"w":128,"h":128},
"rotated": false,
"trimmed": false,
"spriteSourceSize": {"x":0,"y":0,"w":128,"h":128},
"sourceSize": {"w":128,"h":128}
},
{
"filename": "T_F1_Key_Dark.png",
"frame": {"x":1408,"y":128,"w":128,"h":128},
"rotated": false,
"trimmed": false,
"spriteSourceSize": {"x":0,"y":0,"w":128,"h":128},
"sourceSize": {"w":128,"h":128}
},
{
"filename": "T_F2_Key_Dark.png",
"frame": {"x":1536,"y":128,"w":128,"h":128},
"rotated": false,
"trimmed": false,
"spriteSourceSize": {"x":0,"y":0,"w":128,"h":128},
"sourceSize": {"w":128,"h":128}
},
{
"filename": "T_F3_Key_Dark.png",
"frame": {"x":1664,"y":128,"w":128,"h":128},
"rotated": false,
"trimmed": false,
"spriteSourceSize": {"x":0,"y":0,"w":128,"h":128},
"sourceSize": {"w":128,"h":128}
},
{
"filename": "T_F4_Key_Dark.png",
"frame": {"x":1792,"y":128,"w":128,"h":128},
"rotated": false,
"trimmed": false,
"spriteSourceSize": {"x":0,"y":0,"w":128,"h":128},
"sourceSize": {"w":128,"h":128}
},
{
"filename": "T_F5_Key_Dark.png",
"frame": {"x":1920,"y":128,"w":128,"h":128},
"rotated": false,
"trimmed": false,
"spriteSourceSize": {"x":0,"y":0,"w":128,"h":128},
"sourceSize": {"w":128,"h":128}
},
{
"filename": "T_F6_Key_Dark.png",
"frame": {"x":0,"y":256,"w":128,"h":128},
"rotated": false,
"trimmed": false,
"spriteSourceSize": {"x":0,"y":0,"w":128,"h":128},
"sourceSize": {"w":128,"h":128}
},
{
"filename": "T_F7_Key_Dark.png",
"frame": {"x":128,"y":256,"w":128,"h":128},
"rotated": false,
"trimmed": false,
"spriteSourceSize": {"x":0,"y":0,"w":128,"h":128},
"sourceSize": {"w":128,"h":128}
},
{
"filename": "T_F8_Key_Dark.png",
"frame": {"x":256,"y":256,"w":128,"h":128},
"rotated": false,
"trimmed": false,
"spriteSourceSize": {"x":0,"y":0,"w":128,"h":128},
"sourceSize": {"w":128,"h":128}
},
{
"filename": "T_F9_Key_Dark.png",
"frame": {"x":384,"y":256,"w":128,"h":128},
"rotated": false,
"trimmed": false,
"spriteSourceSize": {"x":0,"y":0,"w":128,"h":128},
"sourceSize": {"w":128,"h":128}
},
{
"filename": "T_F10_Key_Dark.png",
"frame": {"x":512,"y":256,"w":128,"h":128},
"rotated": false,
"trimmed": false,
"spriteSourceSize": {"x":0,"y":0,"w":128,"h":128},
"sourceSize": {"w":128,"h":128}
},
{
"filename": "T_F11_Key_Dark.png",
"frame": {"x":640,"y":256,"w":128,"h":128},
"rotated": false,
"trimmed": false,
"spriteSourceSize": {"x":0,"y":0,"w":128,"h":128},
"sourceSize": {"w":128,"h":128}
},
{
"filename": "T_F12_Key_Dark.png",
"frame": {"x":768,"y":256,"w":128,"h":128},
"rotated": false,
"trimmed": false,
"spriteSourceSize": {"x":0,"y":0,"w":128,"h":128},
"sourceSize": {"w":128,"h":128}
},
{
"filename": "T_F_Key_Dark.png",
"frame": {"x":896,"y":256,"w":128,"h":128},
"rotated": false,
"trimmed": false,
"spriteSourceSize": {"x":0,"y":0,"w":128,"h":128},
"sourceSize": {"w":128,"h":128}
},
{
"filename": "T_G_Key_Dark.png",
"frame": {"x":1024,"y":256,"w":128,"h":128},
"rotated": false,
"trimmed": false,
"spriteSourceSize": {"x":0,"y":0,"w":128,"h":128},
"sourceSize": {"w":128,"h":128}
},
{
"filename": "T_H_Key_Dark.png",
"frame": {"x":1152,"y":256,"w":128,"h":128},
"rotated": false,
"trimmed": false,
"spriteSourceSize": {"x":0,"y":0,"w":128,"h":128},
"sourceSize": {"w":128,"h":128}
},
{
"filename": "T_Home_Key_Dark.png",
"frame": {"x":1280,"y":256,"w":128,"h":128},
"rotated": false,
"trimmed": false,
"spriteSourceSize": {"x":0,"y":0,"w":128,"h":128},
"sourceSize": {"w":128,"h":128}
},
{
"filename": "T_I_Key_Dark.png",
"frame": {"x":1408,"y":256,"w":128,"h":128},
"rotated": false,
"trimmed": false,
"spriteSourceSize": {"x":0,"y":0,"w":128,"h":128},
"sourceSize": {"w":128,"h":128}
},
{
"filename": "T_Ins_Key_Dark.png",
"frame": {"x":1536,"y":256,"w":128,"h":128},
"rotated": false,
"trimmed": false,
"spriteSourceSize": {"x":0,"y":0,"w":128,"h":128},
"sourceSize": {"w":128,"h":128}
},
{
"filename": "T_J_Key_Dark.png",
"frame": {"x":1664,"y":256,"w":128,"h":128},
"rotated": false,
"trimmed": false,
"spriteSourceSize": {"x":0,"y":0,"w":128,"h":128},
"sourceSize": {"w":128,"h":128}
},
{
"filename": "T_K_Key_Dark.png",
"frame": {"x":1792,"y":256,"w":128,"h":128},
"rotated": false,
"trimmed": false,
"spriteSourceSize": {"x":0,"y":0,"w":128,"h":128},
"sourceSize": {"w":128,"h":128}
},
{
"filename": "T_Keyboard_R_Key_Dark-1.png",
"frame": {"x":1920,"y":256,"w":128,"h":128},
"rotated": false,
"trimmed": false,
"spriteSourceSize": {"x":0,"y":0,"w":128,"h":128},
"sourceSize": {"w":128,"h":128}
},
{
"filename": "T_Keyboard_R_Key_Dark.png",
"frame": {"x":0,"y":384,"w":128,"h":128},
"rotated": false,
"trimmed": false,
"spriteSourceSize": {"x":0,"y":0,"w":128,"h":128},
"sourceSize": {"w":128,"h":128}
},
{
"filename": "T_L_Key_Dark.png",
"frame": {"x":128,"y":384,"w":128,"h":128},
"rotated": false,
"trimmed": false,
"spriteSourceSize": {"x":0,"y":0,"w":128,"h":128},
"sourceSize": {"w":128,"h":128}
},
{
"filename": "T_Left_Key_Dark.png",
"frame": {"x":256,"y":384,"w":128,"h":128},
"rotated": false,
"trimmed": false,
"spriteSourceSize": {"x":0,"y":0,"w":128,"h":128},
"sourceSize": {"w":128,"h":128}
},
{
"filename": "T_M_Key_Dark.png",
"frame": {"x":384,"y":384,"w":128,"h":128},
"rotated": false,
"trimmed": false,
"spriteSourceSize": {"x":0,"y":0,"w":128,"h":128},
"sourceSize": {"w":128,"h":128}
},
{
"filename": "T_Minus_Key_Dark.png",
"frame": {"x":512,"y":384,"w":128,"h":128},
"rotated": false,
"trimmed": false,
"spriteSourceSize": {"x":0,"y":0,"w":128,"h":128},
"sourceSize": {"w":128,"h":128}
},
{
"filename": "T_N_Key_Dark.png",
"frame": {"x":640,"y":384,"w":128,"h":128},
"rotated": false,
"trimmed": false,
"spriteSourceSize": {"x":0,"y":0,"w":128,"h":128},
"sourceSize": {"w":128,"h":128}
},
{
"filename": "T_O_Key_Dark.png",
"frame": {"x":768,"y":384,"w":128,"h":128},
"rotated": false,
"trimmed": false,
"spriteSourceSize": {"x":0,"y":0,"w":128,"h":128},
"sourceSize": {"w":128,"h":128}
},
{
"filename": "T_P_Key_Dark.png",
"frame": {"x":896,"y":384,"w":128,"h":128},
"rotated": false,
"trimmed": false,
"spriteSourceSize": {"x":0,"y":0,"w":128,"h":128},
"sourceSize": {"w":128,"h":128}
},
{
"filename": "T_PageDown_Key_Dark.png",
"frame": {"x":1024,"y":384,"w":128,"h":128},
"rotated": false,
"trimmed": false,
"spriteSourceSize": {"x":0,"y":0,"w":128,"h":128},
"sourceSize": {"w":128,"h":128}
},
{
"filename": "T_PageUp_Key_Dark.png",
"frame": {"x":1152,"y":384,"w":128,"h":128},
"rotated": false,
"trimmed": false,
"spriteSourceSize": {"x":0,"y":0,"w":128,"h":128},
"sourceSize": {"w":128,"h":128}
},
{
"filename": "T_Plus_Tall_Key_Dark.png",
"frame": {"x":1280,"y":384,"w":128,"h":128},
"rotated": false,
"trimmed": false,
"spriteSourceSize": {"x":0,"y":0,"w":128,"h":128},
"sourceSize": {"w":128,"h":128}
},
{
"filename": "T_Q_Key_Dark.png",
"frame": {"x":1408,"y":384,"w":128,"h":128},
"rotated": false,
"trimmed": false,
"spriteSourceSize": {"x":0,"y":0,"w":128,"h":128},
"sourceSize": {"w":128,"h":128}
},
{
"filename": "T_Quotation_Key_Dark.png",
"frame": {"x":1536,"y":384,"w":128,"h":128},
"rotated": false,
"trimmed": false,
"spriteSourceSize": {"x":0,"y":0,"w":128,"h":128},
"sourceSize": {"w":128,"h":128}
},
{
"filename": "T_R_Key_Dark.png",
"frame": {"x":1664,"y":384,"w":128,"h":128},
"rotated": false,
"trimmed": false,
"spriteSourceSize": {"x":0,"y":0,"w":128,"h":128},
"sourceSize": {"w":128,"h":128}
},
{
"filename": "T_Right_Key_Dark.png",
"frame": {"x":1792,"y":384,"w":128,"h":128},
"rotated": false,
"trimmed": false,
"spriteSourceSize": {"x":0,"y":0,"w":128,"h":128},
"sourceSize": {"w":128,"h":128}
},
{
"filename": "T_S_Key_Dark.png",
"frame": {"x":1920,"y":384,"w":128,"h":128},
"rotated": false,
"trimmed": false,
"spriteSourceSize": {"x":0,"y":0,"w":128,"h":128},
"sourceSize": {"w":128,"h":128}
},
{
"filename": "T_Semicolon_Key_Dark.png",
"frame": {"x":0,"y":512,"w":128,"h":128},
"rotated": false,
"trimmed": false,
"spriteSourceSize": {"x":0,"y":0,"w":128,"h":128},
"sourceSize": {"w":128,"h":128}
},
{
"filename": "T_Shift_Key_Dark.png",
"frame": {"x":128,"y":512,"w":128,"h":128},
"rotated": false,
"trimmed": false,
"spriteSourceSize": {"x":0,"y":0,"w":128,"h":128},
"sourceSize": {"w":128,"h":128}
},
{
"filename": "T_Shift_Super_Wide_Key_Dark.png",
"frame": {"x":256,"y":512,"w":128,"h":128},
"rotated": false,
"trimmed": false,
"spriteSourceSize": {"x":0,"y":0,"w":128,"h":128},
"sourceSize": {"w":128,"h":128}
},
{
"filename": "T_Slash_Key_Dark.png",
"frame": {"x":384,"y":512,"w":128,"h":128},
"rotated": false,
"trimmed": false,
"spriteSourceSize": {"x":0,"y":0,"w":128,"h":128},
"sourceSize": {"w":128,"h":128}
},
{
"filename": "T_Space_Key_Dark.png",
"frame": {"x":512,"y":512,"w":128,"h":128},
"rotated": false,
"trimmed": false,
"spriteSourceSize": {"x":0,"y":0,"w":128,"h":128},
"sourceSize": {"w":128,"h":128}
},
{
"filename": "T_T_Key_Dark.png",
"frame": {"x":640,"y":512,"w":128,"h":128},
"rotated": false,
"trimmed": false,
"spriteSourceSize": {"x":0,"y":0,"w":128,"h":128},
"sourceSize": {"w":128,"h":128}
},
{
"filename": "T_Tab_Key_Dark.png",
"frame": {"x":768,"y":512,"w":128,"h":128},
"rotated": false,
"trimmed": false,
"spriteSourceSize": {"x":0,"y":0,"w":128,"h":128},
"sourceSize": {"w":128,"h":128}
},
{
"filename": "T_Tilde_Key_Dark.png",
"frame": {"x":896,"y":512,"w":128,"h":128},
"rotated": false,
"trimmed": false,
"spriteSourceSize": {"x":0,"y":0,"w":128,"h":128},
"sourceSize": {"w":128,"h":128}
},
{
"filename": "T_U_Key_Dark.png",
"frame": {"x":1024,"y":512,"w":128,"h":128},
"rotated": false,
"trimmed": false,
"spriteSourceSize": {"x":0,"y":0,"w":128,"h":128},
"sourceSize": {"w":128,"h":128}
},
{
"filename": "T_Up_Key_Dark.png",
"frame": {"x":1152,"y":512,"w":128,"h":128},
"rotated": false,
"trimmed": false,
"spriteSourceSize": {"x":0,"y":0,"w":128,"h":128},
"sourceSize": {"w":128,"h":128}
},
{
"filename": "T_V_Key_Dark.png",
"frame": {"x":1280,"y":512,"w":128,"h":128},
"rotated": false,
"trimmed": false,
"spriteSourceSize": {"x":0,"y":0,"w":128,"h":128},
"sourceSize": {"w":128,"h":128}
},
{
"filename": "T_W_Key_Dark.png",
"frame": {"x":1408,"y":512,"w":128,"h":128},
"rotated": false,
"trimmed": false,
"spriteSourceSize": {"x":0,"y":0,"w":128,"h":128},
"sourceSize": {"w":128,"h":128}
},
{
"filename": "T_X_Key_Dark.png",
"frame": {"x":1536,"y":512,"w":128,"h":128},
"rotated": false,
"trimmed": false,
"spriteSourceSize": {"x":0,"y":0,"w":128,"h":128},
"sourceSize": {"w":128,"h":128}
},
{
"filename": "T_Y_Key_Dark.png",
"frame": {"x":1664,"y":512,"w":128,"h":128},
"rotated": false,
"trimmed": false,
"spriteSourceSize": {"x":0,"y":0,"w":128,"h":128},
"sourceSize": {"w":128,"h":128}
},
{
"filename": "T_Z_Key_Dark.png",
"frame": {"x":1792,"y":512,"w":128,"h":128},
"rotated": false,
"trimmed": false,
"spriteSourceSize": {"x":0,"y":0,"w":128,"h":128},
"sourceSize": {"w":128,"h":128}
}],
"meta": {
"app": "https://www.codeandweb.com/texturepacker",
"version": "1.0",
"image": "keyboard.png",
"format": "RGBA8888",
"size": {"w":2048,"h":640},
"scale": "1",
"smartupdate": "$TexturePacker:SmartUpdate:c63c48370eadc7845a8cc15895f925a0:5ddaf57801c3bd84e190cd9b4786d52d:bad03abb89ad027d879c383c13fd51bc$"
}
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 51 KiB

View File

@ -0,0 +1,356 @@
{"frames": {
"T_S_A_Alt.png":
{
"frame": {"x":0,"y":0,"w":128,"h":128},
"rotated": false,
"trimmed": false,
"spriteSourceSize": {"x":0,"y":0,"w":128,"h":128},
"sourceSize": {"w":128,"h":128}
},
"T_S_B_Alt.png":
{
"frame": {"x":128,"y":0,"w":128,"h":128},
"rotated": false,
"trimmed": false,
"spriteSourceSize": {"x":0,"y":0,"w":128,"h":128},
"sourceSize": {"w":128,"h":128}
},
"T_S_Con_Alt.png":
{
"frame": {"x":256,"y":0,"w":128,"h":128},
"rotated": false,
"trimmed": false,
"spriteSourceSize": {"x":0,"y":0,"w":128,"h":128},
"sourceSize": {"w":128,"h":128}
},
"T_S_Con_Left_Alt.png":
{
"frame": {"x":384,"y":0,"w":128,"h":128},
"rotated": false,
"trimmed": false,
"spriteSourceSize": {"x":0,"y":0,"w":128,"h":128},
"sourceSize": {"w":128,"h":128}
},
"T_S_Con_Right_Alt.png":
{
"frame": {"x":512,"y":0,"w":128,"h":128},
"rotated": false,
"trimmed": false,
"spriteSourceSize": {"x":0,"y":0,"w":128,"h":128},
"sourceSize": {"w":128,"h":128}
},
"T_S_Con_Separate_Alt.png":
{
"frame": {"x":640,"y":0,"w":128,"h":128},
"rotated": false,
"trimmed": false,
"spriteSourceSize": {"x":0,"y":0,"w":128,"h":128},
"sourceSize": {"w":128,"h":128}
},
"T_S_Down_Alt.png":
{
"frame": {"x":768,"y":0,"w":128,"h":128},
"rotated": false,
"trimmed": false,
"spriteSourceSize": {"x":0,"y":0,"w":128,"h":128},
"sourceSize": {"w":128,"h":128}
},
"T_S_Dpad_Alt.png":
{
"frame": {"x":896,"y":0,"w":128,"h":128},
"rotated": false,
"trimmed": false,
"spriteSourceSize": {"x":0,"y":0,"w":128,"h":128},
"sourceSize": {"w":128,"h":128}
},
"T_S_Dpad_Down_Alt.png":
{
"frame": {"x":1024,"y":0,"w":128,"h":128},
"rotated": false,
"trimmed": false,
"spriteSourceSize": {"x":0,"y":0,"w":128,"h":128},
"sourceSize": {"w":128,"h":128}
},
"T_S_Dpad_Left_Alt.png":
{
"frame": {"x":1152,"y":0,"w":128,"h":128},
"rotated": false,
"trimmed": false,
"spriteSourceSize": {"x":0,"y":0,"w":128,"h":128},
"sourceSize": {"w":128,"h":128}
},
"T_S_Dpad_Right_Alt.png":
{
"frame": {"x":1280,"y":0,"w":128,"h":128},
"rotated": false,
"trimmed": false,
"spriteSourceSize": {"x":0,"y":0,"w":128,"h":128},
"sourceSize": {"w":128,"h":128}
},
"T_S_Dpad_Up_Alt.png":
{
"frame": {"x":0,"y":128,"w":128,"h":128},
"rotated": false,
"trimmed": false,
"spriteSourceSize": {"x":0,"y":0,"w":128,"h":128},
"sourceSize": {"w":128,"h":128}
},
"T_S_Dpad_X_Alt.png":
{
"frame": {"x":128,"y":128,"w":128,"h":128},
"rotated": false,
"trimmed": false,
"spriteSourceSize": {"x":0,"y":0,"w":128,"h":128},
"sourceSize": {"w":128,"h":128}
},
"T_S_Dpad_Y_Alt.png":
{
"frame": {"x":256,"y":128,"w":128,"h":128},
"rotated": false,
"trimmed": false,
"spriteSourceSize": {"x":0,"y":0,"w":128,"h":128},
"sourceSize": {"w":128,"h":128}
},
"T_S_Home_Alt.png":
{
"frame": {"x":384,"y":128,"w":128,"h":128},
"rotated": false,
"trimmed": false,
"spriteSourceSize": {"x":0,"y":0,"w":128,"h":128},
"sourceSize": {"w":128,"h":128}
},
"T_S_L_2D_Alt.png":
{
"frame": {"x":512,"y":128,"w":128,"h":128},
"rotated": false,
"trimmed": false,
"spriteSourceSize": {"x":0,"y":0,"w":128,"h":128},
"sourceSize": {"w":128,"h":128}
},
"T_S_L_Alt.png":
{
"frame": {"x":640,"y":128,"w":128,"h":128},
"rotated": false,
"trimmed": false,
"spriteSourceSize": {"x":0,"y":0,"w":128,"h":128},
"sourceSize": {"w":128,"h":128}
},
"T_S_L_Down_Alt.png":
{
"frame": {"x":768,"y":128,"w":128,"h":128},
"rotated": false,
"trimmed": false,
"spriteSourceSize": {"x":0,"y":0,"w":128,"h":128},
"sourceSize": {"w":128,"h":128}
},
"T_S_L_Left_Alt.png":
{
"frame": {"x":896,"y":128,"w":128,"h":128},
"rotated": false,
"trimmed": false,
"spriteSourceSize": {"x":0,"y":0,"w":128,"h":128},
"sourceSize": {"w":128,"h":128}
},
"T_S_L_Right_Alt.png":
{
"frame": {"x":1024,"y":128,"w":128,"h":128},
"rotated": false,
"trimmed": false,
"spriteSourceSize": {"x":0,"y":0,"w":128,"h":128},
"sourceSize": {"w":128,"h":128}
},
"T_S_L_Up_Alt.png":
{
"frame": {"x":1152,"y":128,"w":128,"h":128},
"rotated": false,
"trimmed": false,
"spriteSourceSize": {"x":0,"y":0,"w":128,"h":128},
"sourceSize": {"w":128,"h":128}
},
"T_S_L_X_Alt.png":
{
"frame": {"x":1280,"y":128,"w":128,"h":128},
"rotated": false,
"trimmed": false,
"spriteSourceSize": {"x":0,"y":0,"w":128,"h":128},
"sourceSize": {"w":128,"h":128}
},
"T_S_L_Y_Alt.png":
{
"frame": {"x":0,"y":256,"w":128,"h":128},
"rotated": false,
"trimmed": false,
"spriteSourceSize": {"x":0,"y":0,"w":128,"h":128},
"sourceSize": {"w":128,"h":128}
},
"T_S_LB_Alt.png":
{
"frame": {"x":128,"y":256,"w":128,"h":128},
"rotated": false,
"trimmed": false,
"spriteSourceSize": {"x":0,"y":0,"w":128,"h":128},
"sourceSize": {"w":128,"h":128}
},
"T_S_Left_Alt.png":
{
"frame": {"x":256,"y":256,"w":128,"h":128},
"rotated": false,
"trimmed": false,
"spriteSourceSize": {"x":0,"y":0,"w":128,"h":128},
"sourceSize": {"w":128,"h":128}
},
"T_S_LT_Alt.png":
{
"frame": {"x":384,"y":256,"w":128,"h":128},
"rotated": false,
"trimmed": false,
"spriteSourceSize": {"x":0,"y":0,"w":128,"h":128},
"sourceSize": {"w":128,"h":128}
},
"T_S_Minus_Alt.png":
{
"frame": {"x":512,"y":256,"w":128,"h":128},
"rotated": false,
"trimmed": false,
"spriteSourceSize": {"x":0,"y":0,"w":128,"h":128},
"sourceSize": {"w":128,"h":128}
},
"T_S_Plus_Alt.png":
{
"frame": {"x":640,"y":256,"w":128,"h":128},
"rotated": false,
"trimmed": false,
"spriteSourceSize": {"x":0,"y":0,"w":128,"h":128},
"sourceSize": {"w":128,"h":128}
},
"T_S_R_2D_Alt.png":
{
"frame": {"x":768,"y":256,"w":128,"h":128},
"rotated": false,
"trimmed": false,
"spriteSourceSize": {"x":0,"y":0,"w":128,"h":128},
"sourceSize": {"w":128,"h":128}
},
"T_S_R_Alt.png":
{
"frame": {"x":896,"y":256,"w":128,"h":128},
"rotated": false,
"trimmed": false,
"spriteSourceSize": {"x":0,"y":0,"w":128,"h":128},
"sourceSize": {"w":128,"h":128}
},
"T_S_R_Down_Alt.png":
{
"frame": {"x":1024,"y":256,"w":128,"h":128},
"rotated": false,
"trimmed": false,
"spriteSourceSize": {"x":0,"y":0,"w":128,"h":128},
"sourceSize": {"w":128,"h":128}
},
"T_S_R_Left_Alt.png":
{
"frame": {"x":1152,"y":256,"w":128,"h":128},
"rotated": false,
"trimmed": false,
"spriteSourceSize": {"x":0,"y":0,"w":128,"h":128},
"sourceSize": {"w":128,"h":128}
},
"T_S_R_Right_Alt.png":
{
"frame": {"x":1280,"y":256,"w":128,"h":128},
"rotated": false,
"trimmed": false,
"spriteSourceSize": {"x":0,"y":0,"w":128,"h":128},
"sourceSize": {"w":128,"h":128}
},
"T_S_R_Up_Alt.png":
{
"frame": {"x":0,"y":384,"w":128,"h":128},
"rotated": false,
"trimmed": false,
"spriteSourceSize": {"x":0,"y":0,"w":128,"h":128},
"sourceSize": {"w":128,"h":128}
},
"T_S_R_X_Alt.png":
{
"frame": {"x":128,"y":384,"w":128,"h":128},
"rotated": false,
"trimmed": false,
"spriteSourceSize": {"x":0,"y":0,"w":128,"h":128},
"sourceSize": {"w":128,"h":128}
},
"T_S_R_Y_Alt.png":
{
"frame": {"x":256,"y":384,"w":128,"h":128},
"rotated": false,
"trimmed": false,
"spriteSourceSize": {"x":0,"y":0,"w":128,"h":128},
"sourceSize": {"w":128,"h":128}
},
"T_S_RB_Alt.png":
{
"frame": {"x":384,"y":384,"w":128,"h":128},
"rotated": false,
"trimmed": false,
"spriteSourceSize": {"x":0,"y":0,"w":128,"h":128},
"sourceSize": {"w":128,"h":128}
},
"T_S_Right_Alt.png":
{
"frame": {"x":512,"y":384,"w":128,"h":128},
"rotated": false,
"trimmed": false,
"spriteSourceSize": {"x":0,"y":0,"w":128,"h":128},
"sourceSize": {"w":128,"h":128}
},
"T_S_RT_Alt.png":
{
"frame": {"x":640,"y":384,"w":128,"h":128},
"rotated": false,
"trimmed": false,
"spriteSourceSize": {"x":0,"y":0,"w":128,"h":128},
"sourceSize": {"w":128,"h":128}
},
"T_S_Square_Alt.png":
{
"frame": {"x":768,"y":384,"w":128,"h":128},
"rotated": false,
"trimmed": false,
"spriteSourceSize": {"x":0,"y":0,"w":128,"h":128},
"sourceSize": {"w":128,"h":128}
},
"T_S_Up_Alt.png":
{
"frame": {"x":896,"y":384,"w":128,"h":128},
"rotated": false,
"trimmed": false,
"spriteSourceSize": {"x":0,"y":0,"w":128,"h":128},
"sourceSize": {"w":128,"h":128}
},
"T_S_X_Alt.png":
{
"frame": {"x":1024,"y":384,"w":128,"h":128},
"rotated": false,
"trimmed": false,
"spriteSourceSize": {"x":0,"y":0,"w":128,"h":128},
"sourceSize": {"w":128,"h":128}
},
"T_S_Y_Alt.png":
{
"frame": {"x":1152,"y":384,"w":128,"h":128},
"rotated": false,
"trimmed": false,
"spriteSourceSize": {"x":0,"y":0,"w":128,"h":128},
"sourceSize": {"w":128,"h":128}
}},
"meta": {
"app": "https://www.codeandweb.com/texturepacker",
"version": "1.0",
"image": "nswitch.png",
"format": "RGBA8888",
"size": {"w":1408,"h":512},
"scale": "1",
"smartupdate": "$TexturePacker:SmartUpdate:9256c2fb9e9658d02a3c87f7803e4cf0:da5e7131e2452535087974b43fe1c89f:aeba0349fc8bd3742630ffd8f1f1df7a$"
}
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 30 KiB

View File

@ -0,0 +1,108 @@
{"frames": [
{
"filename": "select.png",
"frame": {"x":0,"y":0,"w":128,"h":128},
"rotated": false,
"trimmed": false,
"spriteSourceSize": {"x":0,"y":0,"w":128,"h":128},
"sourceSize": {"w":128,"h":128}
},
{
"filename": "start.png",
"frame": {"x":128,"y":0,"w":128,"h":128},
"rotated": false,
"trimmed": false,
"spriteSourceSize": {"x":0,"y":0,"w":128,"h":128},
"sourceSize": {"w":128,"h":128}
},
{
"filename": "T_X_A_White_Alt.png",
"frame": {"x":256,"y":0,"w":128,"h":128},
"rotated": false,
"trimmed": false,
"spriteSourceSize": {"x":0,"y":0,"w":128,"h":128},
"sourceSize": {"w":128,"h":128}
},
{
"filename": "T_X_B_White_Alt.png",
"frame": {"x":384,"y":0,"w":128,"h":128},
"rotated": false,
"trimmed": false,
"spriteSourceSize": {"x":0,"y":0,"w":128,"h":128},
"sourceSize": {"w":128,"h":128}
},
{
"filename": "T_X_Dpad_Down_Alt.png",
"frame": {"x":512,"y":0,"w":128,"h":128},
"rotated": false,
"trimmed": false,
"spriteSourceSize": {"x":0,"y":0,"w":128,"h":128},
"sourceSize": {"w":128,"h":128}
},
{
"filename": "T_X_Dpad_Left_Alt.png",
"frame": {"x":640,"y":0,"w":128,"h":128},
"rotated": false,
"trimmed": false,
"spriteSourceSize": {"x":0,"y":0,"w":128,"h":128},
"sourceSize": {"w":128,"h":128}
},
{
"filename": "T_X_Dpad_Right_Alt.png",
"frame": {"x":768,"y":0,"w":128,"h":128},
"rotated": false,
"trimmed": false,
"spriteSourceSize": {"x":0,"y":0,"w":128,"h":128},
"sourceSize": {"w":128,"h":128}
},
{
"filename": "T_X_Dpad_Up_Alt.png",
"frame": {"x":896,"y":0,"w":128,"h":128},
"rotated": false,
"trimmed": false,
"spriteSourceSize": {"x":0,"y":0,"w":128,"h":128},
"sourceSize": {"w":128,"h":128}
},
{
"filename": "T_X_LB_Alt.png",
"frame": {"x":1024,"y":0,"w":128,"h":128},
"rotated": false,
"trimmed": false,
"spriteSourceSize": {"x":0,"y":0,"w":128,"h":128},
"sourceSize": {"w":128,"h":128}
},
{
"filename": "T_X_RB_Alt.png",
"frame": {"x":1152,"y":0,"w":128,"h":128},
"rotated": false,
"trimmed": false,
"spriteSourceSize": {"x":0,"y":0,"w":128,"h":128},
"sourceSize": {"w":128,"h":128}
},
{
"filename": "T_X_X_White_Alt.png",
"frame": {"x":1280,"y":0,"w":128,"h":128},
"rotated": false,
"trimmed": false,
"spriteSourceSize": {"x":0,"y":0,"w":128,"h":128},
"sourceSize": {"w":128,"h":128}
},
{
"filename": "T_X_Y_White_Alt.png",
"frame": {"x":1408,"y":0,"w":128,"h":128},
"rotated": false,
"trimmed": false,
"spriteSourceSize": {"x":0,"y":0,"w":128,"h":128},
"sourceSize": {"w":128,"h":128}
}],
"meta": {
"app": "https://www.codeandweb.com/texturepacker",
"version": "1.0",
"image": "snes.png",
"format": "RGBA8888",
"size": {"w":1536,"h":128},
"scale": "1",
"smartupdate": "$TexturePacker:SmartUpdate:86d994650b80a3f876cc92e4d0928a65:60b6f706b30e87e11c3d01cec0eccf9c:7e443c950e063b6a235f0fd6295e2000$"
}
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.8 KiB

View File

@ -0,0 +1,348 @@
{"frames": {
"T_X_A_Color_Alt.png":
{
"frame": {"x":0,"y":0,"w":128,"h":128},
"rotated": false,
"trimmed": false,
"spriteSourceSize": {"x":0,"y":0,"w":128,"h":128},
"sourceSize": {"w":128,"h":128}
},
"T_X_A_White_Alt.png":
{
"frame": {"x":128,"y":0,"w":128,"h":128},
"rotated": false,
"trimmed": false,
"spriteSourceSize": {"x":0,"y":0,"w":128,"h":128},
"sourceSize": {"w":128,"h":128}
},
"T_X_B_Color_Alt.png":
{
"frame": {"x":256,"y":0,"w":128,"h":128},
"rotated": false,
"trimmed": false,
"spriteSourceSize": {"x":0,"y":0,"w":128,"h":128},
"sourceSize": {"w":128,"h":128}
},
"T_X_B_White_Alt.png":
{
"frame": {"x":384,"y":0,"w":128,"h":128},
"rotated": false,
"trimmed": false,
"spriteSourceSize": {"x":0,"y":0,"w":128,"h":128},
"sourceSize": {"w":128,"h":128}
},
"T_X_Dpad_Alt.png":
{
"frame": {"x":512,"y":0,"w":128,"h":128},
"rotated": false,
"trimmed": false,
"spriteSourceSize": {"x":0,"y":0,"w":128,"h":128},
"sourceSize": {"w":128,"h":128}
},
"T_X_Dpad_Down_Alt.png":
{
"frame": {"x":640,"y":0,"w":128,"h":128},
"rotated": false,
"trimmed": false,
"spriteSourceSize": {"x":0,"y":0,"w":128,"h":128},
"sourceSize": {"w":128,"h":128}
},
"T_X_Dpad_Left_Alt.png":
{
"frame": {"x":768,"y":0,"w":128,"h":128},
"rotated": false,
"trimmed": false,
"spriteSourceSize": {"x":0,"y":0,"w":128,"h":128},
"sourceSize": {"w":128,"h":128}
},
"T_X_Dpad_Right_Alt.png":
{
"frame": {"x":896,"y":0,"w":128,"h":128},
"rotated": false,
"trimmed": false,
"spriteSourceSize": {"x":0,"y":0,"w":128,"h":128},
"sourceSize": {"w":128,"h":128}
},
"T_X_Dpad_Up_Alt.png":
{
"frame": {"x":1024,"y":0,"w":128,"h":128},
"rotated": false,
"trimmed": false,
"spriteSourceSize": {"x":0,"y":0,"w":128,"h":128},
"sourceSize": {"w":128,"h":128}
},
"T_X_Dpad_X_Alt.png":
{
"frame": {"x":1152,"y":0,"w":128,"h":128},
"rotated": false,
"trimmed": false,
"spriteSourceSize": {"x":0,"y":0,"w":128,"h":128},
"sourceSize": {"w":128,"h":128}
},
"T_X_Dpad_Y_Alt.png":
{
"frame": {"x":1280,"y":0,"w":128,"h":128},
"rotated": false,
"trimmed": false,
"spriteSourceSize": {"x":0,"y":0,"w":128,"h":128},
"sourceSize": {"w":128,"h":128}
},
"T_X_L_2D_Alt.png":
{
"frame": {"x":1408,"y":0,"w":128,"h":128},
"rotated": false,
"trimmed": false,
"spriteSourceSize": {"x":0,"y":0,"w":128,"h":128},
"sourceSize": {"w":128,"h":128}
},
"T_X_L_Alt.png":
{
"frame": {"x":1536,"y":0,"w":128,"h":128},
"rotated": false,
"trimmed": false,
"spriteSourceSize": {"x":0,"y":0,"w":128,"h":128},
"sourceSize": {"w":128,"h":128}
},
"T_X_L_Down_Alt.png":
{
"frame": {"x":1664,"y":0,"w":128,"h":128},
"rotated": false,
"trimmed": false,
"spriteSourceSize": {"x":0,"y":0,"w":128,"h":128},
"sourceSize": {"w":128,"h":128}
},
"T_X_L_Left_Alt.png":
{
"frame": {"x":0,"y":128,"w":128,"h":128},
"rotated": false,
"trimmed": false,
"spriteSourceSize": {"x":0,"y":0,"w":128,"h":128},
"sourceSize": {"w":128,"h":128}
},
"T_X_L_Right_Alt.png":
{
"frame": {"x":128,"y":128,"w":128,"h":128},
"rotated": false,
"trimmed": false,
"spriteSourceSize": {"x":0,"y":0,"w":128,"h":128},
"sourceSize": {"w":128,"h":128}
},
"T_X_L_UP_Alt.png":
{
"frame": {"x":256,"y":128,"w":128,"h":128},
"rotated": false,
"trimmed": false,
"spriteSourceSize": {"x":0,"y":0,"w":128,"h":128},
"sourceSize": {"w":128,"h":128}
},
"T_X_L_X_Alt.png":
{
"frame": {"x":384,"y":128,"w":128,"h":128},
"rotated": false,
"trimmed": false,
"spriteSourceSize": {"x":0,"y":0,"w":128,"h":128},
"sourceSize": {"w":128,"h":128}
},
"T_X_L_Y_Alt.png":
{
"frame": {"x":512,"y":128,"w":128,"h":128},
"rotated": false,
"trimmed": false,
"spriteSourceSize": {"x":0,"y":0,"w":128,"h":128},
"sourceSize": {"w":128,"h":128}
},
"T_X_LB_Alt.png":
{
"frame": {"x":640,"y":128,"w":128,"h":128},
"rotated": false,
"trimmed": false,
"spriteSourceSize": {"x":0,"y":0,"w":128,"h":128},
"sourceSize": {"w":128,"h":128}
},
"T_X_Left_Stick_Click_Alt.png":
{
"frame": {"x":768,"y":128,"w":128,"h":128},
"rotated": false,
"trimmed": false,
"spriteSourceSize": {"x":0,"y":0,"w":128,"h":128},
"sourceSize": {"w":128,"h":128}
},
"T_X_Left_Stick_Click_Alt_Alt.png":
{
"frame": {"x":896,"y":128,"w":128,"h":128},
"rotated": false,
"trimmed": false,
"spriteSourceSize": {"x":0,"y":0,"w":128,"h":128},
"sourceSize": {"w":128,"h":128}
},
"T_X_LT_Alt.png":
{
"frame": {"x":1024,"y":128,"w":128,"h":128},
"rotated": false,
"trimmed": false,
"spriteSourceSize": {"x":0,"y":0,"w":128,"h":128},
"sourceSize": {"w":128,"h":128}
},
"T_X_R_2D_Alt.png":
{
"frame": {"x":1152,"y":128,"w":128,"h":128},
"rotated": false,
"trimmed": false,
"spriteSourceSize": {"x":0,"y":0,"w":128,"h":128},
"sourceSize": {"w":128,"h":128}
},
"T_X_R_Alt.png":
{
"frame": {"x":1280,"y":128,"w":128,"h":128},
"rotated": false,
"trimmed": false,
"spriteSourceSize": {"x":0,"y":0,"w":128,"h":128},
"sourceSize": {"w":128,"h":128}
},
"T_X_R_Down_Alt.png":
{
"frame": {"x":1408,"y":128,"w":128,"h":128},
"rotated": false,
"trimmed": false,
"spriteSourceSize": {"x":0,"y":0,"w":128,"h":128},
"sourceSize": {"w":128,"h":128}
},
"T_X_R_Left_Alt.png":
{
"frame": {"x":1536,"y":128,"w":128,"h":128},
"rotated": false,
"trimmed": false,
"spriteSourceSize": {"x":0,"y":0,"w":128,"h":128},
"sourceSize": {"w":128,"h":128}
},
"T_X_R_Right_Alt.png":
{
"frame": {"x":1664,"y":128,"w":128,"h":128},
"rotated": false,
"trimmed": false,
"spriteSourceSize": {"x":0,"y":0,"w":128,"h":128},
"sourceSize": {"w":128,"h":128}
},
"T_X_R_UP_Alt.png":
{
"frame": {"x":0,"y":256,"w":128,"h":128},
"rotated": false,
"trimmed": false,
"spriteSourceSize": {"x":0,"y":0,"w":128,"h":128},
"sourceSize": {"w":128,"h":128}
},
"T_X_R_X_Alt.png":
{
"frame": {"x":128,"y":256,"w":128,"h":128},
"rotated": false,
"trimmed": false,
"spriteSourceSize": {"x":0,"y":0,"w":128,"h":128},
"sourceSize": {"w":128,"h":128}
},
"T_X_R_Y_Alt.png":
{
"frame": {"x":256,"y":256,"w":128,"h":128},
"rotated": false,
"trimmed": false,
"spriteSourceSize": {"x":0,"y":0,"w":128,"h":128},
"sourceSize": {"w":128,"h":128}
},
"T_X_RB_Alt.png":
{
"frame": {"x":384,"y":256,"w":128,"h":128},
"rotated": false,
"trimmed": false,
"spriteSourceSize": {"x":0,"y":0,"w":128,"h":128},
"sourceSize": {"w":128,"h":128}
},
"T_X_Right_Stick_Click_Alt.png":
{
"frame": {"x":512,"y":256,"w":128,"h":128},
"rotated": false,
"trimmed": false,
"spriteSourceSize": {"x":0,"y":0,"w":128,"h":128},
"sourceSize": {"w":128,"h":128}
},
"T_X_Right_Stick_Click_Alt_Alt.png":
{
"frame": {"x":640,"y":256,"w":128,"h":128},
"rotated": false,
"trimmed": false,
"spriteSourceSize": {"x":0,"y":0,"w":128,"h":128},
"sourceSize": {"w":128,"h":128}
},
"T_X_RT_Alt.png":
{
"frame": {"x":768,"y":256,"w":128,"h":128},
"rotated": false,
"trimmed": false,
"spriteSourceSize": {"x":0,"y":0,"w":128,"h":128},
"sourceSize": {"w":128,"h":128}
},
"T_X_Share_Alt-1.png":
{
"frame": {"x":896,"y":256,"w":128,"h":128},
"rotated": false,
"trimmed": false,
"spriteSourceSize": {"x":0,"y":0,"w":128,"h":128},
"sourceSize": {"w":128,"h":128}
},
"T_X_Share_Alt.png":
{
"frame": {"x":1024,"y":256,"w":128,"h":128},
"rotated": false,
"trimmed": false,
"spriteSourceSize": {"x":0,"y":0,"w":128,"h":128},
"sourceSize": {"w":128,"h":128}
},
"T_X_X_Alt.png":
{
"frame": {"x":1152,"y":256,"w":128,"h":128},
"rotated": false,
"trimmed": false,
"spriteSourceSize": {"x":0,"y":0,"w":128,"h":128},
"sourceSize": {"w":128,"h":128}
},
"T_X_X_Color_Alt.png":
{
"frame": {"x":1280,"y":256,"w":128,"h":128},
"rotated": false,
"trimmed": false,
"spriteSourceSize": {"x":0,"y":0,"w":128,"h":128},
"sourceSize": {"w":128,"h":128}
},
"T_X_X_White_Alt.png":
{
"frame": {"x":1408,"y":256,"w":128,"h":128},
"rotated": false,
"trimmed": false,
"spriteSourceSize": {"x":0,"y":0,"w":128,"h":128},
"sourceSize": {"w":128,"h":128}
},
"T_X_Y_Color_Alt.png":
{
"frame": {"x":1536,"y":256,"w":128,"h":128},
"rotated": false,
"trimmed": false,
"spriteSourceSize": {"x":0,"y":0,"w":128,"h":128},
"sourceSize": {"w":128,"h":128}
},
"T_X_Y_White_Alt.png":
{
"frame": {"x":1664,"y":256,"w":128,"h":128},
"rotated": false,
"trimmed": false,
"spriteSourceSize": {"x":0,"y":0,"w":128,"h":128},
"sourceSize": {"w":128,"h":128}
}},
"meta": {
"app": "https://www.codeandweb.com/texturepacker",
"version": "1.0",
"image": "xbox.png",
"format": "RGBA8888",
"size": {"w":1792,"h":384},
"scale": "1",
"smartupdate": "$TexturePacker:SmartUpdate:4e419a6ed1d6fe68e572af3e46338b9b:30674cf3e9fcf41b5fb5ab36fa87043f:7ad6008cd8fa3f9f4bfb17e0cfcbbb64$"
}
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 66 KiB

View File

@ -33,9 +33,6 @@ import TrainerData from './system/trainer-data';
import SoundFade from 'phaser3-rex-plugins/plugins/soundfade';
import { pokemonPrevolutions } from './data/pokemon-evolutions';
import PokeballTray from './ui/pokeball-tray';
import { Setting, settingOptions } from './system/settings';
import SettingsUiHandler from './ui/settings-ui-handler';
import MessageUiHandler from './ui/message-ui-handler';
import { Species } from './data/enums/species';
import InvertPostFX from './pipelines/invert';
import { Achv, ModifierAchv, MoneyAchv, achvs } from './system/achv';
@ -119,7 +116,6 @@ export default class BattleScene extends SceneBase {
public fusionPaletteSwaps: boolean = true;
public enableTouchControls: boolean = false;
public enableVibration: boolean = false;
public abSwapped: boolean = false;
public disableMenu: boolean = false;

View File

@ -0,0 +1,291 @@
import {Button} from "#app/enums/buttons";
import {SettingKeyboard} from "#app/system/settings-keyboard";
const cfg_keyboard_azerty = {
padID: 'default',
padType: 'keyboard',
deviceMapping: {
KEY_A: Phaser.Input.Keyboard.KeyCodes.A,
KEY_B: Phaser.Input.Keyboard.KeyCodes.B,
KEY_C: Phaser.Input.Keyboard.KeyCodes.C,
KEY_D: Phaser.Input.Keyboard.KeyCodes.D,
KEY_E: Phaser.Input.Keyboard.KeyCodes.E,
KEY_F: Phaser.Input.Keyboard.KeyCodes.F,
KEY_G: Phaser.Input.Keyboard.KeyCodes.G,
KEY_H: Phaser.Input.Keyboard.KeyCodes.H,
KEY_I: Phaser.Input.Keyboard.KeyCodes.I,
KEY_J: Phaser.Input.Keyboard.KeyCodes.J,
KEY_K: Phaser.Input.Keyboard.KeyCodes.K,
KEY_L: Phaser.Input.Keyboard.KeyCodes.L,
KEY_M: Phaser.Input.Keyboard.KeyCodes.M,
KEY_N: Phaser.Input.Keyboard.KeyCodes.N,
KEY_O: Phaser.Input.Keyboard.KeyCodes.O,
KEY_P: Phaser.Input.Keyboard.KeyCodes.P,
KEY_Q: Phaser.Input.Keyboard.KeyCodes.Q,
KEY_R: Phaser.Input.Keyboard.KeyCodes.R,
KEY_S: Phaser.Input.Keyboard.KeyCodes.S,
KEY_T: Phaser.Input.Keyboard.KeyCodes.T,
KEY_U: Phaser.Input.Keyboard.KeyCodes.U,
KEY_V: Phaser.Input.Keyboard.KeyCodes.V,
KEY_W: Phaser.Input.Keyboard.KeyCodes.W,
KEY_X: Phaser.Input.Keyboard.KeyCodes.X,
KEY_Y: Phaser.Input.Keyboard.KeyCodes.Y,
KEY_Z: Phaser.Input.Keyboard.KeyCodes.Z,
KEY_0: Phaser.Input.Keyboard.KeyCodes.ZERO,
KEY_1: Phaser.Input.Keyboard.KeyCodes.ONE,
KEY_2: Phaser.Input.Keyboard.KeyCodes.TWO,
KEY_3: Phaser.Input.Keyboard.KeyCodes.THREE,
KEY_4: Phaser.Input.Keyboard.KeyCodes.FOUR,
KEY_5: Phaser.Input.Keyboard.KeyCodes.FIVE,
KEY_6: Phaser.Input.Keyboard.KeyCodes.SIX,
KEY_7: Phaser.Input.Keyboard.KeyCodes.SEVEN,
KEY_8: Phaser.Input.Keyboard.KeyCodes.EIGHT,
KEY_9: Phaser.Input.Keyboard.KeyCodes.NINE,
KEY_CTRL: Phaser.Input.Keyboard.KeyCodes.CTRL,
KEY_DEL: Phaser.Input.Keyboard.KeyCodes.DELETE,
KEY_END: Phaser.Input.Keyboard.KeyCodes.END,
KEY_ENTER: Phaser.Input.Keyboard.KeyCodes.ENTER,
KEY_ESC: Phaser.Input.Keyboard.KeyCodes.ESC,
KEY_F1: Phaser.Input.Keyboard.KeyCodes.F1,
KEY_F2: Phaser.Input.Keyboard.KeyCodes.F2,
KEY_F3: Phaser.Input.Keyboard.KeyCodes.F3,
KEY_F4: Phaser.Input.Keyboard.KeyCodes.F4,
KEY_F5: Phaser.Input.Keyboard.KeyCodes.F5,
KEY_F6: Phaser.Input.Keyboard.KeyCodes.F6,
KEY_F7: Phaser.Input.Keyboard.KeyCodes.F7,
KEY_F8: Phaser.Input.Keyboard.KeyCodes.F8,
KEY_F9: Phaser.Input.Keyboard.KeyCodes.F9,
KEY_F10: Phaser.Input.Keyboard.KeyCodes.F10,
KEY_F11: Phaser.Input.Keyboard.KeyCodes.F11,
KEY_F12: Phaser.Input.Keyboard.KeyCodes.F12,
KEY_HOME: Phaser.Input.Keyboard.KeyCodes.HOME,
KEY_INSERT: Phaser.Input.Keyboard.KeyCodes.INSERT,
KEY_PAGE_DOWN: Phaser.Input.Keyboard.KeyCodes.PAGE_DOWN,
KEY_PAGE_UP: Phaser.Input.Keyboard.KeyCodes.PAGE_UP,
KEY_PLUS: Phaser.Input.Keyboard.KeyCodes.NUMPAD_ADD, // Assuming numpad plus
KEY_MINUS: Phaser.Input.Keyboard.KeyCodes.NUMPAD_SUBTRACT, // Assuming numpad minus
KEY_QUOTATION: Phaser.Input.Keyboard.KeyCodes.QUOTES,
KEY_SHIFT: Phaser.Input.Keyboard.KeyCodes.SHIFT,
KEY_SPACE: Phaser.Input.Keyboard.KeyCodes.SPACE,
KEY_TAB: Phaser.Input.Keyboard.KeyCodes.TAB,
KEY_TILDE: Phaser.Input.Keyboard.KeyCodes.BACKTICK,
KEY_ARROW_UP: Phaser.Input.Keyboard.KeyCodes.UP,
KEY_ARROW_DOWN: Phaser.Input.Keyboard.KeyCodes.DOWN,
KEY_ARROW_LEFT: Phaser.Input.Keyboard.KeyCodes.LEFT,
KEY_ARROW_RIGHT: Phaser.Input.Keyboard.KeyCodes.RIGHT,
KEY_LEFT_BRACKET: Phaser.Input.Keyboard.KeyCodes.OPEN_BRACKET,
KEY_RIGHT_BRACKET: Phaser.Input.Keyboard.KeyCodes.CLOSED_BRACKET,
KEY_SEMICOLON: Phaser.Input.Keyboard.KeyCodes.SEMICOLON,
KEY_BACKSPACE: Phaser.Input.Keyboard.KeyCodes.BACKSPACE,
KEY_ALT: Phaser.Input.Keyboard.KeyCodes.ALT
},
icons: {
KEY_A: "T_A_Key_Dark.png",
KEY_B: "T_B_Key_Dark.png",
KEY_C: "T_C_Key_Dark.png",
KEY_D: "T_D_Key_Dark.png",
KEY_E: "T_E_Key_Dark.png",
KEY_F: "T_F_Key_Dark.png",
KEY_G: "T_G_Key_Dark.png",
KEY_H: "T_H_Key_Dark.png",
KEY_I: "T_I_Key_Dark.png",
KEY_J: "T_J_Key_Dark.png",
KEY_K: "T_K_Key_Dark.png",
KEY_L: "T_L_Key_Dark.png",
KEY_M: "T_M_Key_Dark.png",
KEY_N: "T_N_Key_Dark.png",
KEY_O: "T_O_Key_Dark.png",
KEY_P: "T_P_Key_Dark.png",
KEY_Q: "T_Q_Key_Dark.png",
KEY_R: "T_R_Key_Dark.png",
KEY_S: "T_S_Key_Dark.png",
KEY_T: "T_T_Key_Dark.png",
KEY_U: "T_U_Key_Dark.png",
KEY_V: "T_V_Key_Dark.png",
KEY_W: "T_W_Key_Dark.png",
KEY_X: "T_X_Key_Dark.png",
KEY_Y: "T_Y_Key_Dark.png",
KEY_Z: "T_Z_Key_Dark.png",
KEY_0: "T_0_Key_Dark.png",
KEY_1: "T_1_Key_Dark.png",
KEY_2: "T_2_Key_Dark.png",
KEY_3: "T_3_Key_Dark.png",
KEY_4: "T_4_Key_Dark.png",
KEY_5: "T_5_Key_Dark.png",
KEY_6: "T_6_Key_Dark.png",
KEY_7: "T_7_Key_Dark.png",
KEY_8: "T_8_Key_Dark.png",
KEY_9: "T_9_Key_Dark.png",
KEY_F1: "T_F1_Key_Dark.png",
KEY_F2: "T_F2_Key_Dark.png",
KEY_F3: "T_F3_Key_Dark.png",
KEY_F4: "T_F4_Key_Dark.png",
KEY_F5: "T_F5_Key_Dark.png",
KEY_F6: "T_F6_Key_Dark.png",
KEY_F7: "T_F7_Key_Dark.png",
KEY_F8: "T_F8_Key_Dark.png",
KEY_F9: "T_F9_Key_Dark.png",
KEY_F10: "T_F10_Key_Dark.png",
KEY_F11: "T_F11_Key_Dark.png",
KEY_F12: "T_F12_Key_Dark.png",
KEY_PAGE_DOWN: "T_PageDown_Key_Dark.png",
KEY_PAGE_UP: "T_PageUp_Key_Dark.png",
KEY_CTRL: "T_Crtl_Key_Dark.png",
KEY_DEL: "T_Del_Key_Dark.png",
KEY_END: "T_End_Key_Dark.png",
KEY_ENTER: "T_Enter_Alt_Key_Dark.png",
KEY_ESC: "T_Esc_Key_Dark.png",
KEY_HOME: "T_Home_Key_Dark.png",
KEY_INSERT: "T_Ins_Key_Dark.png",
KEY_PLUS: "T_Plus_Tall_Key_Dark.png",
KEY_MINUS: "T_Minus_Key_Dark.png",
KEY_QUOTATION: "T_Quotation_Key_Dark.png",
KEY_SHIFT: "T_Shift_Key_Dark.png",
KEY_SPACE: "T_Space_Key_Dark.png",
KEY_TAB: "T_Tab_Key_Dark.png",
KEY_TILDE: "T_Tilde_Key_Dark.png",
KEY_ARROW_UP: "T_Up_Key_Dark.png",
KEY_ARROW_DOWN: "T_Down_Key_Dark.png",
KEY_ARROW_LEFT: "T_Left_Key_Dark.png",
KEY_ARROW_RIGHT: "T_Right_Key_Dark.png",
KEY_LEFT_BRACKET: "T_Brackets_L_Key_Dark.png",
KEY_RIGHT_BRACKET: "T_Brackets_R_Key_Dark.png",
KEY_SEMICOLON: "T_Semicolon_Key_Dark.png",
KEY_BACKSPACE: "T_Backspace_Alt_Key_Dark.png",
KEY_ALT: "T_Alt_Key_Dark.png"
},
settings: {
[SettingKeyboard.Button_Up]: Button.UP,
[SettingKeyboard.Button_Down]: Button.DOWN,
[SettingKeyboard.Button_Left]: Button.LEFT,
[SettingKeyboard.Button_Right]: Button.RIGHT,
[SettingKeyboard.Button_Submit]: Button.SUBMIT,
[SettingKeyboard.Button_Action]: Button.ACTION,
[SettingKeyboard.Button_Cancel]: Button.CANCEL,
[SettingKeyboard.Button_Menu]: Button.MENU,
[SettingKeyboard.Button_Stats]: Button.STATS,
[SettingKeyboard.Button_Cycle_Shiny]: Button.CYCLE_SHINY,
[SettingKeyboard.Button_Cycle_Form]: Button.CYCLE_FORM,
[SettingKeyboard.Button_Cycle_Gender]: Button.CYCLE_GENDER,
[SettingKeyboard.Button_Cycle_Ability]: Button.CYCLE_ABILITY,
[SettingKeyboard.Button_Cycle_Nature]: Button.CYCLE_NATURE,
[SettingKeyboard.Button_Cycle_Variant]: Button.CYCLE_VARIANT,
[SettingKeyboard.Button_Speed_Up]: Button.SPEED_UP,
[SettingKeyboard.Button_Slow_Down]: Button.SLOW_DOWN,
[SettingKeyboard.Alt_Button_Up]: Button.UP,
[SettingKeyboard.Alt_Button_Down]: Button.DOWN,
[SettingKeyboard.Alt_Button_Left]: Button.LEFT,
[SettingKeyboard.Alt_Button_Right]: Button.RIGHT,
[SettingKeyboard.Alt_Button_Submit]: Button.SUBMIT,
[SettingKeyboard.Alt_Button_Action]: Button.ACTION,
[SettingKeyboard.Alt_Button_Cancel]: Button.CANCEL,
[SettingKeyboard.Alt_Button_Menu]: Button.MENU,
[SettingKeyboard.Alt_Button_Stats]: Button.STATS,
[SettingKeyboard.Alt_Button_Cycle_Shiny]: Button.CYCLE_SHINY,
[SettingKeyboard.Alt_Button_Cycle_Form]: Button.CYCLE_FORM,
[SettingKeyboard.Alt_Button_Cycle_Gender]: Button.CYCLE_GENDER,
[SettingKeyboard.Alt_Button_Cycle_Ability]: Button.CYCLE_ABILITY,
[SettingKeyboard.Alt_Button_Cycle_Nature]: Button.CYCLE_NATURE,
[SettingKeyboard.Alt_Button_Cycle_Variant]: Button.CYCLE_VARIANT,
[SettingKeyboard.Alt_Button_Speed_Up]: Button.SPEED_UP,
[SettingKeyboard.Alt_Button_Slow_Down]: Button.SLOW_DOWN,
},
default: {
KEY_ARROW_UP: SettingKeyboard.Button_Up,
KEY_ARROW_DOWN: SettingKeyboard.Button_Down,
KEY_ARROW_LEFT: SettingKeyboard.Button_Left,
KEY_ARROW_RIGHT: SettingKeyboard.Button_Right,
KEY_ENTER: SettingKeyboard.Button_Submit,
KEY_SPACE: SettingKeyboard.Button_Action,
KEY_BACKSPACE: SettingKeyboard.Button_Cancel,
KEY_ESC: SettingKeyboard.Button_Menu,
KEY_C: SettingKeyboard.Button_Stats,
KEY_R: SettingKeyboard.Button_Cycle_Shiny,
KEY_F: SettingKeyboard.Button_Cycle_Form,
KEY_G: SettingKeyboard.Button_Cycle_Gender,
KEY_E: SettingKeyboard.Button_Cycle_Ability,
KEY_N: SettingKeyboard.Button_Cycle_Nature,
KEY_V: SettingKeyboard.Button_Cycle_Variant,
KEY_PLUS: SettingKeyboard.Button_Speed_Up,
KEY_MINUS: SettingKeyboard.Button_Slow_Down,
KEY_A: -1,
KEY_B: -1,
KEY_D: SettingKeyboard.Alt_Button_Right,
KEY_H: -1,
KEY_I: SettingKeyboard.Alt_Button_Cycle_Nature,
KEY_J: -1,
KEY_K: SettingKeyboard.Alt_Button_Cycle_Variant,
KEY_L: SettingKeyboard.Alt_Button_Cycle_Ability,
KEY_M: SettingKeyboard.Alt_Button_Cycle_Form,
KEY_O: SettingKeyboard.Alt_Button_Cycle_Gender,
KEY_P: SettingKeyboard.Alt_Button_Cycle_Shiny,
KEY_Q: SettingKeyboard.Alt_Button_Left,
KEY_S: SettingKeyboard.Alt_Button_Down,
KEY_T: -1,
KEY_U: -1,
KEY_W: SettingKeyboard.Alt_Button_Action,
KEY_X: SettingKeyboard.Alt_Button_Cancel,
KEY_Y: -1,
KEY_Z: SettingKeyboard.Alt_Button_Up,
KEY_0: -1,
KEY_1: -1,
KEY_2: -1,
KEY_3: -1,
KEY_4: -1,
KEY_5: -1,
KEY_6: -1,
KEY_7: -1,
KEY_8: -1,
KEY_9: -1,
KEY_CTRL: SettingKeyboard.Alt_Button_Submit,
KEY_DEL: -1,
KEY_END: -1,
KEY_F1: -1,
KEY_F2: -1,
KEY_F3: -1,
KEY_F4: -1,
KEY_F5: -1,
KEY_F6: -1,
KEY_F7: -1,
KEY_F8: -1,
KEY_F9: -1,
KEY_F10: -1,
KEY_F11: -1,
KEY_F12: -1,
KEY_HOME: -1,
KEY_INSERT: -1,
KEY_PAGE_DOWN: SettingKeyboard.Alt_Button_Slow_Down,
KEY_PAGE_UP: SettingKeyboard.Alt_Button_Speed_Up,
KEY_QUOTATION: -1,
KEY_SHIFT: SettingKeyboard.Alt_Button_Stats,
KEY_TAB: SettingKeyboard.Alt_Button_Menu,
KEY_TILDE: -1,
KEY_LEFT_BRACKET: -1,
KEY_RIGHT_BRACKET: -1,
KEY_SEMICOLON: -1,
KEY_ALT: -1
},
blacklist: [
"KEY_ENTER",
"KEY_ESC",
"KEY_ARROW_UP",
"KEY_ARROW_DOWN",
"KEY_ARROW_LEFT",
"KEY_ARROW_RIGHT",
"KEY_DELETE",
"KEY_HOME",
]
};
export default cfg_keyboard_azerty;

View File

@ -0,0 +1,186 @@
import {Device} from "#app/enums/devices";
/**
* Retrieves the key associated with the specified keycode from the mapping.
*
* @param config - The configuration object containing the mapping.
* @param keycode - The keycode to search for.
* @returns The key associated with the specified keycode.
*/
export function getKeyWithKeycode(config, keycode) {
return Object.keys(config.deviceMapping).find(key => config.deviceMapping[key] === keycode);
}
/**
* Retrieves the setting name associated with the specified keycode.
*
* @param config - The configuration object containing custom settings.
* @param keycode - The keycode to search for.
* @returns The setting name associated with the specified keycode.
*/
export function getSettingNameWithKeycode(config, keycode) {
const key = getKeyWithKeycode(config, keycode);
return config.custom[key];
}
/**
* Retrieves the icon associated with the specified keycode.
*
* @param config - The configuration object containing icons.
* @param keycode - The keycode to search for.
* @returns The icon associated with the specified keycode.
*/
export function getIconWithKeycode(config, keycode) {
const key = getKeyWithKeycode(config, keycode);
return config.icons[key];
}
/**
* Retrieves the button associated with the specified keycode.
*
* @param config - The configuration object containing settings.
* @param keycode - The keycode to search for.
* @returns The button associated with the specified keycode.
*/
export function getButtonWithKeycode(config, keycode) {
const settingName = getSettingNameWithKeycode(config, keycode);
return config.settings[settingName];
}
/**
* Retrieves the key associated with the specified setting name.
*
* @param config - The configuration object containing custom settings.
* @param settingName - The setting name to search for.
* @returns The key associated with the specified setting name.
*/
export function getKeyWithSettingName(config, settingName) {
return Object.keys(config.custom).find(key => config.custom[key] === settingName);
}
/**
* Retrieves the setting name associated with the specified key.
*
* @param config - The configuration object containing custom settings.
* @param key - The key to search for.
* @returns The setting name associated with the specified key.
*/
export function getSettingNameWithKey(config, key) {
return config.custom[key];
}
/**
* Retrieves the icon associated with the specified key.
*
* @param config - The configuration object containing icons.
* @param key - The key to search for.
* @returns The icon associated with the specified key.
*/
export function getIconWithKey(config, key) {
return config.icons[key];
}
/**
* Retrieves the icon associated with the specified setting name.
*
* @param config - The configuration object containing icons.
* @param settingName - The setting name to search for.
* @returns The icon associated with the specified setting name.
*/
export function getIconWithSettingName(config, settingName) {
const key = getKeyWithSettingName(config, settingName);
return getIconWithKey(config, key);
}
export function getIconForLatestInput(configs, source, devices, settingName) {
let config;
if (source === 'gamepad') config = configs[devices[Device.GAMEPAD]];
else config = configs[devices[Device.KEYBOARD]];
const icon = getIconWithSettingName(config, settingName);
if (!icon) {
const isAlt = settingName.includes("ALT_");
let altSettingName;
if (isAlt)
altSettingName = settingName.split("ALT_").splice(1)[0];
else
altSettingName = `ALT_${settingName}`;
return getIconWithSettingName(config, altSettingName);
}
return icon;
}
export function assign(config, settingNameTarget, keycode): boolean {
// first, we need to check if this keycode is already used on another settingName
if (!canIAssignThisKey(config, getKeyWithKeycode(config, keycode)) || !canIOverrideThisSetting(config, settingNameTarget)) return false;
const previousSettingName = getSettingNameWithKeycode(config, keycode);
// if it was already bound, we delete the bind
if (previousSettingName) {
const previousKey = getKeyWithSettingName(config, previousSettingName);
config.custom[previousKey] = -1;
}
// then, we need to delete the current key for this settingName
const currentKey = getKeyWithSettingName(config, settingNameTarget);
config.custom[currentKey] = -1;
// then, the new key is assigned to the new settingName
const newKey = getKeyWithKeycode(config, keycode);
config.custom[newKey] = settingNameTarget;
return true;
}
export function swap(config, settingNameTarget, keycode) {
// only for gamepad
if (config.padType === 'keyboard') return false;
const prev_key = getKeyWithSettingName(config, settingNameTarget);
const prev_settingName = getSettingNameWithKey(config, prev_key);
const new_key = getKeyWithKeycode(config, keycode);
const new_settingName = getSettingNameWithKey(config, new_key);
config.custom[prev_key] = new_settingName;
config.custom[new_key] = prev_settingName;
return true;
}
/**
* Deletes the binding of the specified setting name.
*
* @param config - The configuration object containing custom settings.
* @param settingName - The setting name to delete.
*/
export function deleteBind(config, settingName) {
const key = getKeyWithSettingName(config, settingName);
if (config.blacklist.includes(key) || isTheLatestBind(config, settingName)) return false;
config.custom[key] = -1;
return true;
}
export function canIAssignThisKey(config, key) {
const settingName = getSettingNameWithKey(config, key);
if (config.blacklist?.includes(key)) return false;
if (settingName === -1) return true;
if (isTheLatestBind(config, settingName)) return false;
return true;
}
export function canIOverrideThisSetting(config, settingName) {
const key = getKeyWithSettingName(config, settingName);
if (config.blacklist?.includes(key) || isTheLatestBind(config, settingName)) return false;
return true;
}
export function canIDeleteThisKey(config, key) {
return canIAssignThisKey(config, key);
}
export function isTheLatestBind(config, settingName) {
if (config.padType !== 'keyboard') return false;
const isAlt = settingName.includes("ALT_");
let altSettingName;
if (isAlt)
altSettingName = settingName.split("ALT_").splice(1)[0];
else
altSettingName = `ALT_${settingName}`;
const secondButton = getKeyWithSettingName(config, altSettingName);
return secondButton === undefined;
}

View File

@ -1,10 +1,13 @@
import {SettingGamepad} from "../system/settings-gamepad";
import {Button} from "../enums/buttons";
/**
* Dualshock mapping
*/
const pad_dualshock = {
padID: 'Dualshock',
padType: 'Sony',
gamepadMapping: {
padType: 'dualshock',
deviceMapping: {
RC_S: 0,
RC_E: 1,
RC_W: 2,
@ -21,9 +24,65 @@ const pad_dualshock = {
LC_S: 13,
LC_W: 14,
LC_E: 15,
MENU: 16,
TOUCH: 17
},
icons: {
RC_S: "T_P4_Cross_Color_Default.png",
RC_E: "T_P4_Circle_Color_Default.png",
RC_W: "T_P4_Square_Color_Default.png",
RC_N: "T_P4_Triangle_Color_Default.png",
START: "T_P4_Options_Default.png",
SELECT: "T_P4_Share_Default.png",
LB: "T_P4_L1_Default.png",
RB: "T_P4_R1_Default.png",
LT: "T_P4_L2_Default.png",
RT: "T_P4_R2_Default.png",
LS: "T_P4_Left_Stick_Click_Default.png",
RS: "T_P4_Left_Stick_Click_Default-1.png",
LC_N: "T_P4_Dpad_UP_Default.png",
LC_S: "T_P4_Dpad_Down_Default.png",
LC_W: "T_P4_Dpad_Left_Default.png",
LC_E: "T_P4_Dpad_Right_Default.png",
TOUCH: "T_P4_Touch_Pad_Default.png"
},
settings: {
[SettingGamepad.Button_Up]: Button.UP,
[SettingGamepad.Button_Down]: Button.DOWN,
[SettingGamepad.Button_Left]: Button.LEFT,
[SettingGamepad.Button_Right]: Button.RIGHT,
[SettingGamepad.Button_Action]: Button.ACTION,
[SettingGamepad.Button_Cancel]: Button.CANCEL,
[SettingGamepad.Button_Cycle_Nature]: Button.CYCLE_NATURE,
[SettingGamepad.Button_Cycle_Variant]: Button.CYCLE_VARIANT,
[SettingGamepad.Button_Menu]: Button.MENU,
[SettingGamepad.Button_Stats]: Button.STATS,
[SettingGamepad.Button_Cycle_Form]: Button.CYCLE_FORM,
[SettingGamepad.Button_Cycle_Shiny]: Button.CYCLE_SHINY,
[SettingGamepad.Button_Cycle_Gender]: Button.CYCLE_GENDER,
[SettingGamepad.Button_Cycle_Ability]: Button.CYCLE_ABILITY,
[SettingGamepad.Button_Speed_Up]: Button.SPEED_UP,
[SettingGamepad.Button_Slow_Down]: Button.SLOW_DOWN,
[SettingGamepad.Button_Submit]: Button.SUBMIT
},
default: {
LC_N: SettingGamepad.Button_Up,
LC_S: SettingGamepad.Button_Down,
LC_W: SettingGamepad.Button_Left,
LC_E: SettingGamepad.Button_Right,
RC_S: SettingGamepad.Button_Action,
RC_E: SettingGamepad.Button_Cancel,
RC_W: SettingGamepad.Button_Cycle_Nature,
RC_N: SettingGamepad.Button_Cycle_Variant,
START: SettingGamepad.Button_Menu,
SELECT: SettingGamepad.Button_Stats,
LB: SettingGamepad.Button_Cycle_Form,
RB: SettingGamepad.Button_Cycle_Shiny,
LT: SettingGamepad.Button_Cycle_Gender,
RT: SettingGamepad.Button_Cycle_Ability,
LS: SettingGamepad.Button_Speed_Up,
RS: SettingGamepad.Button_Slow_Down,
TOUCH: SettingGamepad.Button_Submit,
},
};
export default pad_dualshock;

View File

@ -1,10 +1,13 @@
import {SettingGamepad} from "../system/settings-gamepad";
import {Button} from "../enums/buttons";
/**
* Generic pad mapping
*/
const pad_generic = {
padID: 'Generic',
padType: 'generic',
gamepadMapping: {
padType: 'xbox',
deviceMapping: {
RC_S: 0,
RC_E: 1,
RC_W: 2,
@ -22,6 +25,66 @@ const pad_generic = {
LC_W: 14,
LC_E: 15
},
icons: {
RC_S: "T_X_A_Color_Alt.png",
RC_E: "T_X_B_Color_Alt.png",
RC_W: "T_X_X_Color_Alt.png",
RC_N: "T_X_Y_Color_Alt.png",
START: "T_X_X_Alt.png",
SELECT: "T_X_Share_Alt.png",
LB: "T_X_LB_Alt.png",
RB: "T_X_RB_Alt.png",
LT: "T_X_LT_Alt.png",
RT: "T_X_RT_Alt.png",
LS: "T_X_Left_Stick_Click_Alt_Alt.png",
RS: "T_X_Right_Stick_Click_Alt_Alt.png",
LC_N: "T_X_Dpad_Up_Alt.png",
LC_S: "T_X_Dpad_Down_Alt.png",
LC_W: "T_X_Dpad_Left_Alt.png",
LC_E: "T_X_Dpad_Right_Alt.png",
},
settings: {
[SettingGamepad.Button_Up]: Button.UP,
[SettingGamepad.Button_Down]: Button.DOWN,
[SettingGamepad.Button_Left]: Button.LEFT,
[SettingGamepad.Button_Right]: Button.RIGHT,
[SettingGamepad.Button_Action]: Button.ACTION,
[SettingGamepad.Button_Cancel]: Button.CANCEL,
[SettingGamepad.Button_Cycle_Nature]: Button.CYCLE_NATURE,
[SettingGamepad.Button_Cycle_Variant]: Button.CYCLE_VARIANT,
[SettingGamepad.Button_Menu]: Button.MENU,
[SettingGamepad.Button_Stats]: Button.STATS,
[SettingGamepad.Button_Cycle_Form]: Button.CYCLE_FORM,
[SettingGamepad.Button_Cycle_Shiny]: Button.CYCLE_SHINY,
[SettingGamepad.Button_Cycle_Gender]: Button.CYCLE_GENDER,
[SettingGamepad.Button_Cycle_Ability]: Button.CYCLE_ABILITY,
[SettingGamepad.Button_Speed_Up]: Button.SPEED_UP,
[SettingGamepad.Button_Slow_Down]: Button.SLOW_DOWN
},
default: {
LC_N: SettingGamepad.Button_Up,
LC_S: SettingGamepad.Button_Down,
LC_W: SettingGamepad.Button_Left,
LC_E: SettingGamepad.Button_Right,
RC_S: SettingGamepad.Button_Action,
RC_E: SettingGamepad.Button_Cancel,
RC_W: SettingGamepad.Button_Cycle_Nature,
RC_N: SettingGamepad.Button_Cycle_Variant,
START: SettingGamepad.Button_Menu,
SELECT: SettingGamepad.Button_Stats,
LB: SettingGamepad.Button_Cycle_Form,
RB: SettingGamepad.Button_Cycle_Shiny,
LT: SettingGamepad.Button_Cycle_Gender,
RT: SettingGamepad.Button_Cycle_Ability,
LS: SettingGamepad.Button_Speed_Up,
RS: SettingGamepad.Button_Slow_Down
},
blacklist: [
"LC_N",
"LC_S",
"LC_W",
"LC_E",
]
};
export default pad_generic;

View File

@ -1,10 +1,13 @@
import {SettingGamepad} from "../system/settings-gamepad";
import {Button} from "../enums/buttons";
/**
* 081f-e401 - UnlicensedSNES
*/
const pad_unlicensedSNES = {
padID: '081f-e401',
padType: 'snes',
gamepadMapping : {
deviceMapping : {
RC_S: 2,
RC_E: 1,
RC_W: 3,
@ -17,7 +20,57 @@ const pad_unlicensedSNES = {
LC_S: 13,
LC_W: 14,
LC_E: 15
}
},
icons: {
RC_S: "T_X_B_White_Alt.png",
RC_E: "T_X_A_White_Alt.png",
RC_W: "T_X_Y_White_Alt.png",
RC_N: "T_X_X_White_Alt.png",
START: "start.png",
SELECT: "select.png",
LB: "T_X_LB_Alt.png",
RB: "T_X_RB_Alt.png",
LC_N: "T_X_Dpad_Up_Alt.png",
LC_S: "T_X_Dpad_Down_Alt.png",
LC_W: "T_X_Dpad_Left_Alt.png",
LC_E: "T_X_Dpad_Right_Alt.png",
},
settings: {
[SettingGamepad.Button_Up]: Button.UP,
[SettingGamepad.Button_Down]: Button.DOWN,
[SettingGamepad.Button_Left]: Button.LEFT,
[SettingGamepad.Button_Right]: Button.RIGHT,
[SettingGamepad.Button_Action]: Button.ACTION,
[SettingGamepad.Button_Cancel]: Button.CANCEL,
[SettingGamepad.Button_Cycle_Nature]: Button.CYCLE_NATURE,
[SettingGamepad.Button_Cycle_Variant]: Button.CYCLE_VARIANT,
[SettingGamepad.Button_Menu]: Button.MENU,
[SettingGamepad.Button_Stats]: Button.STATS,
[SettingGamepad.Button_Cycle_Form]: Button.CYCLE_FORM,
[SettingGamepad.Button_Cycle_Shiny]: Button.CYCLE_SHINY,
[SettingGamepad.Button_Cycle_Gender]: Button.CYCLE_GENDER,
[SettingGamepad.Button_Cycle_Ability]: Button.CYCLE_ABILITY,
[SettingGamepad.Button_Speed_Up]: Button.SPEED_UP,
[SettingGamepad.Button_Slow_Down]: Button.SLOW_DOWN
},
default: {
LC_N: SettingGamepad.Button_Up,
LC_S: SettingGamepad.Button_Down,
LC_W: SettingGamepad.Button_Left,
LC_E: SettingGamepad.Button_Right,
RC_S: SettingGamepad.Button_Action,
RC_E: SettingGamepad.Button_Cancel,
RC_W: SettingGamepad.Button_Cycle_Nature,
RC_N: SettingGamepad.Button_Cycle_Variant,
START: SettingGamepad.Button_Menu,
SELECT: SettingGamepad.Button_Stats,
LB: SettingGamepad.Button_Cycle_Form,
RB: SettingGamepad.Button_Cycle_Shiny,
LT: -1,
RT: -1,
LS: -1,
RS: -1
},
};
export default pad_unlicensedSNES;

View File

@ -1,10 +1,13 @@
import {SettingGamepad} from "../system/settings-gamepad";
import {Button} from "#app/enums/buttons";
/**
* Generic pad mapping
*/
const pad_xbox360 = {
padID: 'Xbox 360 controller (XInput STANDARD GAMEPAD)',
padType: 'xbox',
gamepadMapping: {
deviceMapping: {
RC_S: 0,
RC_E: 1,
RC_W: 2,
@ -20,8 +23,61 @@ const pad_xbox360 = {
LC_N: 12,
LC_S: 13,
LC_W: 14,
LC_E: 15,
MENU: 16
LC_E: 15
},
icons: {
RC_S: "T_X_A_Color_Alt.png",
RC_E: "T_X_B_Color_Alt.png",
RC_W: "T_X_X_Color_Alt.png",
RC_N: "T_X_Y_Color_Alt.png",
START: "T_X_X_Alt.png",
SELECT: "T_X_Share_Alt.png",
LB: "T_X_LB_Alt.png",
RB: "T_X_RB_Alt.png",
LT: "T_X_LT_Alt.png",
RT: "T_X_RT_Alt.png",
LS: "T_X_Left_Stick_Click_Alt_Alt.png",
RS: "T_X_Right_Stick_Click_Alt_Alt.png",
LC_N: "T_X_Dpad_Up_Alt.png",
LC_S: "T_X_Dpad_Down_Alt.png",
LC_W: "T_X_Dpad_Left_Alt.png",
LC_E: "T_X_Dpad_Right_Alt.png",
},
settings: {
[SettingGamepad.Button_Up]: Button.UP,
[SettingGamepad.Button_Down]: Button.DOWN,
[SettingGamepad.Button_Left]: Button.LEFT,
[SettingGamepad.Button_Right]: Button.RIGHT,
[SettingGamepad.Button_Action]: Button.ACTION,
[SettingGamepad.Button_Cancel]: Button.CANCEL,
[SettingGamepad.Button_Cycle_Nature]: Button.CYCLE_NATURE,
[SettingGamepad.Button_Cycle_Variant]: Button.CYCLE_VARIANT,
[SettingGamepad.Button_Menu]: Button.MENU,
[SettingGamepad.Button_Stats]: Button.STATS,
[SettingGamepad.Button_Cycle_Form]: Button.CYCLE_FORM,
[SettingGamepad.Button_Cycle_Shiny]: Button.CYCLE_SHINY,
[SettingGamepad.Button_Cycle_Gender]: Button.CYCLE_GENDER,
[SettingGamepad.Button_Cycle_Ability]: Button.CYCLE_ABILITY,
[SettingGamepad.Button_Speed_Up]: Button.SPEED_UP,
[SettingGamepad.Button_Slow_Down]: Button.SLOW_DOWN
},
default: {
LC_N: SettingGamepad.Button_Up,
LC_S: SettingGamepad.Button_Down,
LC_W: SettingGamepad.Button_Left,
LC_E: SettingGamepad.Button_Right,
RC_S: SettingGamepad.Button_Action,
RC_E: SettingGamepad.Button_Cancel,
RC_W: SettingGamepad.Button_Cycle_Nature,
RC_N: SettingGamepad.Button_Cycle_Variant,
START: SettingGamepad.Button_Menu,
SELECT: SettingGamepad.Button_Stats,
LB: SettingGamepad.Button_Cycle_Form,
RB: SettingGamepad.Button_Cycle_Shiny,
LT: SettingGamepad.Button_Cycle_Gender,
RT: SettingGamepad.Button_Cycle_Ability,
LS: SettingGamepad.Button_Speed_Up,
RS: SettingGamepad.Button_Slow_Down
},
};

4
src/enums/devices.ts Normal file
View File

@ -0,0 +1,4 @@
export enum Device {
GAMEPAD,
KEYBOARD,
}

View File

@ -1,26 +1,50 @@
import Phaser, {Time} from "phaser";
import * as Utils from "./utils";
import {deepCopy} from "./utils";
import {initTouchControls} from './touch-controls';
import pad_generic from "./configs/pad_generic";
import pad_unlicensedSNES from "./configs/pad_unlicensedSNES";
import pad_xbox360 from "./configs/pad_xbox360";
import pad_dualshock from "./configs/pad_dualshock";
import {Button} from "./enums/buttons";
import {Mode} from "./ui/ui";
import SettingsGamepadUiHandler from "./ui/settings/settings-gamepad-ui-handler";
import SettingsKeyboardUiHandler from "./ui/settings/settings-keyboard-ui-handler";
import cfg_keyboard_azerty from "./configs/cfg_keyboard_azerty";
import {Device} from "#app/enums/devices";
import {
assign,
getButtonWithKeycode,
getIconForLatestInput, swap,
} from "#app/configs/configHandler";
export interface GamepadMapping {
export interface DeviceMapping {
[key: string]: number;
}
export interface GamepadConfig {
padID: string;
padType: string;
gamepadMapping: GamepadMapping;
export interface IconsMapping {
[key: string]: string;
}
export interface ActionGamepadMapping {
export interface SettingMapping {
[key: string]: string;
}
export interface MappingLayout {
[key: string]: Button;
}
export interface InterfaceConfig {
padID: string;
padType: string;
deviceMapping: DeviceMapping;
icons: IconsMapping;
setting: SettingMapping;
default: MappingLayout;
custom: MappingLayout;
main: Array<string>;
alt: Array<string>;
}
const repeatInputDelayMillis = 250;
/**
@ -47,16 +71,25 @@ const repeatInputDelayMillis = 250;
*/
export class InputsController {
private buttonKeys: Phaser.Input.Keyboard.Key[][];
private gamepads: Array<string> = new Array();
private gamepads: Array<Phaser.Input.Gamepad.Gamepad> = new Array();
private scene: Phaser.Scene;
private events: Phaser.Events.EventEmitter;
private buttonLock: Button;
private buttonLock2: Button;
private interactions: Map<Button, Map<string, boolean>> = new Map();
private time: Time;
private player: Map<String, GamepadMapping> = new Map();
private time: Phaser.Time.Clock;
private configs: Map<string, InterfaceConfig> = new Map();
private gamepadSupport: boolean = true;
public selectedDevice;
private disconnectedGamepads: Array<String> = new Array();
private pauseUpdate: boolean = false;
public lastSource: string = 'keyboard';
private keys: Array<number> = [];
/**
* Initializes a new instance of the game control system, setting up initial state and configurations.
@ -69,10 +102,15 @@ export class InputsController {
* Specific buttons like MENU and STATS are set not to repeat their actions.
* It concludes by calling the `init` method to complete the setup.
*/
constructor(scene: Phaser.Scene) {
this.scene = scene;
this.time = this.scene.time;
this.buttonKeys = [];
this.selectedDevice = {
[Device.GAMEPAD]: null,
[Device.KEYBOARD]: 'default'
}
for (const b of Utils.getEnumValues(Button)) {
this.interactions[b] = {
@ -96,15 +134,22 @@ export class InputsController {
* Additionally, it manages the game's behavior when it loses focus to prevent unwanted game actions during this state.
*/
init(): void {
this.events = new Phaser.Events.EventEmitter();
this.events = this.scene.game.events;
this.scene.game.events.on(Phaser.Core.Events.BLUR, () => {
this.loseFocus()
})
if (typeof this.scene.input.gamepad !== 'undefined') {
this.scene.input.gamepad.on('connected', function (thisGamepad) {
if (!thisGamepad) return;
this.refreshGamepads();
this.setupGamepad(thisGamepad);
this.onReconnect(thisGamepad);
}, this);
this.scene.input.gamepad.on('disconnected', function (thisGamepad) {
this.onDisconnect(thisGamepad); // when a gamepad is disconnected
}, this);
// Check to see if the gamepad has already been setup by the browser
@ -118,10 +163,10 @@ export class InputsController {
this.scene.input.gamepad.on('down', this.gamepadButtonDown, this);
this.scene.input.gamepad.on('up', this.gamepadButtonUp, this);
this.scene.input.keyboard.on('keydown', this.keyboardKeyDown, this);
this.scene.input.keyboard.on('keyup', this.keyboardKeyUp, this);
}
// Keyboard
this.setupKeyboardControls();
initTouchControls(this.events);
}
/**
@ -147,35 +192,58 @@ export class InputsController {
this.gamepadSupport = true;
} else {
this.gamepadSupport = false;
// if we disable the gamepad, we want to release every key pressed
this.deactivatePressedKey();
}
}
/**
* Sets the currently chosen gamepad and initializes related settings.
* This method first deactivates any active key presses and then initializes the gamepad settings.
*
* @param gamepad - The identifier of the gamepad to set as chosen.
*/
setChosenGamepad(gamepad: String): void {
this.deactivatePressedKey();
this.initChosenGamepad(gamepad)
}
/**
* Sets the currently chosen keyboard layout and initializes related settings.
*
* @param layoutKeyboard - The identifier of the keyboard layout to set as chosen.
*/
setChosenKeyboardLayout(layoutKeyboard: String): void {
this.deactivatePressedKey();
this.initChosenLayoutKeyboard(layoutKeyboard)
}
/**
* Updates the interaction handling by processing input states.
* This method gives priority to certain buttons by reversing the order in which they are checked.
* This method loops through all button values, checks for valid and timely interactions, and conditionally processes
* or ignores them based on the current state of gamepad support and other criteria.
*
* @remarks
* The method iterates over all possible buttons, checking for specific conditions such as:
* - If the button is registered in the `interactions` dictionary.
* - If the button has been held down long enough.
* - If the button is currently pressed.
* It handles special conditions such as the absence of gamepad support or mismatches between the source of the input and
* the currently chosen gamepad. It also respects the paused state of updates to prevent unwanted input processing.
*
* Special handling is applied if gamepad support is disabled but a gamepad source is still triggering inputs,
* preventing potential infinite loops by removing the last processed movement time for the button.
* If an interaction is valid and should be processed, it emits an 'input_down' event with details of the interaction.
*/
update(): void {
for (const b of Utils.getEnumValues(Button).reverse()) {
if (
this.interactions.hasOwnProperty(b) &&
this.repeatInputDurationJustPassed(b) &&
this.repeatInputDurationJustPassed(b as Button) &&
this.interactions[b].isPressed
) {
// Prevents repeating button interactions when gamepad support is disabled.
if (!this.gamepadSupport && this.interactions[b].source === 'gamepad') {
if (
(!this.gamepadSupport && this.interactions[b].source === 'gamepad') ||
(this.interactions[b].source === 'gamepad' && this.interactions[b].sourceName && this.interactions[b].sourceName !== this.selectedDevice[Device.GAMEPAD]) ||
(this.interactions[b].source === 'keyboard' && this.interactions[b].sourceName && this.interactions[b].sourceName !== this.selectedDevice[Device.KEYBOARD]) ||
this.pauseUpdate
) {
// Deletes the last interaction for a button if gamepad is disabled.
this.delLastProcessedMovementTime(b);
this.delLastProcessedMovementTime(b as Button);
return;
}
// Emits an event for the button press.
@ -183,25 +251,101 @@ export class InputsController {
controller_type: this.interactions[b].source,
button: b,
});
this.setLastProcessedMovementTime(b, this.interactions[b].source);
this.setLastProcessedMovementTime(b as Button, this.interactions[b].source, this.interactions[b].sourceName);
}
}
}
/**
* Configures a gamepad for use based on its device ID.
* Retrieves the identifiers of all connected gamepads, excluding any that are currently marked as disconnected.
* @returns Array<String> An array of strings representing the IDs of the connected gamepads.
*/
getGamepadsName(): Array<String> {
return this.gamepads.filter(g => !this.disconnectedGamepads.includes(g.id)).map(g => g.id);
}
/**
* Initializes the chosen gamepad by setting its identifier in the local storage and updating the UI to reflect the chosen gamepad.
* If a gamepad name is provided, it uses that as the chosen gamepad; otherwise, it defaults to the currently chosen gamepad.
* @param gamepadName Optional parameter to specify the name of the gamepad to initialize as chosen.
*/
initChosenGamepad(gamepadName?: String): void {
if (gamepadName)
this.selectedDevice[Device.GAMEPAD] = gamepadName.toLowerCase();
const handler = this.scene.ui?.handlers[Mode.SETTINGS_GAMEPAD] as SettingsGamepadUiHandler;
handler && handler.updateChosenGamepadDisplay()
}
/**
* Initializes the chosen keyboard layout by setting its identifier in the local storage and updating the UI to reflect the chosen layout.
* If a layout name is provided, it uses that as the chosen layout; otherwise, it defaults to the currently chosen layout.
* @param layoutKeyboard Optional parameter to specify the name of the keyboard layout to initialize as chosen.
*/
initChosenLayoutKeyboard(layoutKeyboard?: String): void {
if (layoutKeyboard)
this.selectedDevice[Device.KEYBOARD] = layoutKeyboard.toLowerCase();
const handler = this.scene.ui?.handlers[Mode.SETTINGS_KEYBOARD] as SettingsKeyboardUiHandler;
handler && handler.updateChosenKeyboardDisplay()
}
/**
* Handles the disconnection of a gamepad by adding its identifier to a list of disconnected gamepads.
* This is necessary because Phaser retains memory of previously connected gamepads, and without tracking
* disconnections, it would be impossible to determine the connection status of gamepads. This method ensures
* that disconnected gamepads are recognized and can be appropriately hidden in the gamepad selection menu.
*
* @param thisGamepad - The gamepad to set up.
* @param thisGamepad The gamepad that has been disconnected.
*/
onDisconnect(thisGamepad: Phaser.Input.Gamepad.Gamepad): void {
this.disconnectedGamepads.push(thisGamepad.id);
}
/**
* Updates the tracking of disconnected gamepads when a gamepad is reconnected.
* It removes the reconnected gamepad's identifier from the `disconnectedGamepads` array,
* effectively updating its status to connected.
*
* @remarks
* This method initializes a gamepad by mapping its ID to a predefined configuration.
* It updates the player's gamepad mapping based on the identified configuration, ensuring
* that the gamepad controls are correctly mapped to in-game actions.
* @param thisGamepad The gamepad that has been reconnected.
*/
onReconnect(thisGamepad: Phaser.Input.Gamepad.Gamepad): void {
this.disconnectedGamepads = this.disconnectedGamepads.filter(g => g !== thisGamepad.id);
}
/**
* Initializes or updates configurations for connected gamepads.
* It retrieves the names of all connected gamepads, sets up their configurations according to stored or default settings,
* and ensures these configurations are saved. If the connected gamepad is the currently chosen one,
* it reinitializes the chosen gamepad settings.
*
* @param thisGamepad The gamepad that is being set up.
*/
setupGamepad(thisGamepad: Phaser.Input.Gamepad.Gamepad): void {
let gamepadID = thisGamepad.id.toLowerCase();
const mappedPad = this.mapGamepad(gamepadID);
this.player['mapping'] = mappedPad.gamepadMapping;
const allGamepads = this.getGamepadsName();
for (const gamepad of allGamepads) {
const gamepadID = gamepad.toLowerCase();
if (!this.selectedDevice[Device.GAMEPAD])
this.setChosenGamepad(gamepadID);
const config = deepCopy(this.getConfig(gamepadID));
config.custom = this.configs[gamepadID]?.custom || {...config.default};
this.configs[gamepadID] = config;
this.scene.gameData?.saveMappingConfigs(gamepadID, this.configs[gamepadID]);
}
this.lastSource = 'gamepad';
const handler = this.scene.ui?.handlers[Mode.SETTINGS_GAMEPAD] as SettingsGamepadUiHandler;
handler && handler.updateChosenGamepadDisplay()
}
/**
* Initializes or updates configurations for connected keyboards.
*/
setupKeyboard(): void {
for (const layout of ['default']) {
const config = deepCopy(this.getConfigKeyboard(layout));
config.custom = this.configs[layout]?.custom || {...config.default};
this.configs[layout] = config;
this.scene.gameData?.saveMappingConfigs(this.selectedDevice[Device.KEYBOARD], this.configs[layout]);
}
this.initChosenLayoutKeyboard(this.selectedDevice[Device.KEYBOARD])
}
/**
@ -224,83 +368,96 @@ export class InputsController {
}
/**
* Retrieves the current gamepad mapping for in-game actions.
*
* @returns An object mapping gamepad buttons to in-game actions based on the player's current gamepad configuration.
*
* @remarks
* This method constructs a mapping of gamepad buttons to in-game action buttons according to the player's
* current gamepad configuration. If no configuration is available, it returns an empty mapping.
* The mapping includes directional controls, action buttons, and system commands among others,
* adjusted for any custom settings such as swapped action buttons.
* Ensures the keyboard is initialized by checking if there is an active configuration for the keyboard.
* If not, it sets up the keyboard with default configurations.
*/
getActionGamepadMapping(): ActionGamepadMapping {
const gamepadMapping = {};
if (!this.player?.mapping) return gamepadMapping;
gamepadMapping[this.player.mapping.LC_N] = Button.UP;
gamepadMapping[this.player.mapping.LC_S] = Button.DOWN;
gamepadMapping[this.player.mapping.LC_W] = Button.LEFT;
gamepadMapping[this.player.mapping.LC_E] = Button.RIGHT;
gamepadMapping[this.player.mapping.TOUCH] = Button.SUBMIT;
gamepadMapping[this.player.mapping.RC_S] = this.scene.abSwapped ? Button.CANCEL : Button.ACTION;
gamepadMapping[this.player.mapping.RC_E] = this.scene.abSwapped ? Button.ACTION : Button.CANCEL;
gamepadMapping[this.player.mapping.SELECT] = Button.STATS;
gamepadMapping[this.player.mapping.START] = Button.MENU;
gamepadMapping[this.player.mapping.RB] = Button.CYCLE_SHINY;
gamepadMapping[this.player.mapping.LB] = Button.CYCLE_FORM;
gamepadMapping[this.player.mapping.LT] = Button.CYCLE_GENDER;
gamepadMapping[this.player.mapping.RT] = Button.CYCLE_ABILITY;
gamepadMapping[this.player.mapping.RC_W] = Button.CYCLE_NATURE;
gamepadMapping[this.player.mapping.RC_N] = Button.CYCLE_VARIANT;
gamepadMapping[this.player.mapping.LS] = Button.SPEED_UP;
gamepadMapping[this.player.mapping.RS] = Button.SLOW_DOWN;
return gamepadMapping;
ensureKeyboardIsInit(): void {
if (!this.getActiveConfig(Device.KEYBOARD)?.padID)
this.setupKeyboard();
}
/**
* Handles the 'down' event for gamepad buttons, emitting appropriate events and updating the interaction state.
* Handles the keydown event for the keyboard.
*
* @param pad - The gamepad on which the button press occurred.
* @param button - The button that was pressed.
* @param value - The value associated with the button press, typically indicating pressure or degree of activation.
* @param event The keyboard event.
*/
keyboardKeyDown(event): void {
this.lastSource = 'keyboard';
const keyDown = event.keyCode;
this.ensureKeyboardIsInit();
if (this.keys.includes(keyDown)) return;
this.keys.push(keyDown);
const buttonDown = getButtonWithKeycode(this.getActiveConfig(Device.KEYBOARD), keyDown);
if (buttonDown !== undefined) {
this.events.emit('input_down', {
controller_type: 'keyboard',
button: buttonDown,
});
this.setLastProcessedMovementTime(buttonDown, 'keyboard', this.selectedDevice[Device.KEYBOARD]);
}
}
/**
* Handles the keyup event for the keyboard.
*
* @remarks
* This method is triggered when a gamepad button is pressed. If gamepad support is enabled, it:
* - Retrieves the current gamepad action mapping.
* - Checks if the pressed button is mapped to a game action.
* - If mapped, emits an 'input_down' event with the controller type and button action, and updates the interaction of this button.
* @param event The keyboard event.
*/
keyboardKeyUp(event): void {
this.lastSource = 'keyboard';
const keyDown = event.keyCode;
this.keys = this.keys.filter(k => k !== keyDown);
this.ensureKeyboardIsInit()
const buttonUp = getButtonWithKeycode(this.getActiveConfig(Device.KEYBOARD), keyDown);
if (buttonUp !== undefined) {
this.events.emit('input_up', {
controller_type: 'keyboard',
button: buttonUp,
});
this.delLastProcessedMovementTime(buttonUp);
}
}
/**
* Handles button press events on a gamepad. This method sets the gamepad as chosen on the first input if no gamepad is currently chosen.
* It checks if gamepad support is enabled and if the event comes from the chosen gamepad. If so, it maps the button press to a specific
* action using a custom configuration, emits an event for the button press, and records the time of the action.
*
* @param pad The gamepad on which the button was pressed.
* @param button The specific button that was pressed.
* @param value The intensity or value of the button press, if applicable.
*/
gamepadButtonDown(pad: Phaser.Input.Gamepad.Gamepad, button: Phaser.Input.Gamepad.Button, value: number): void {
if (!this.gamepadSupport) return;
const actionMapping = this.getActionGamepadMapping();
const buttonDown = actionMapping.hasOwnProperty(button.index) && actionMapping[button.index];
if (!this.configs[this.selectedDevice[Device.KEYBOARD]]?.padID)
this.setupKeyboard();
if (!pad) return;
this.lastSource = 'gamepad';
if (!this.selectedDevice[Device.GAMEPAD])
this.setChosenGamepad(pad.id);
if (!this.gamepadSupport || pad.id.toLowerCase() !== this.selectedDevice[Device.GAMEPAD].toLowerCase()) return;
const buttonDown = getButtonWithKeycode(this.getActiveConfig(Device.GAMEPAD), button.index);
if (buttonDown !== undefined) {
this.events.emit('input_down', {
controller_type: 'gamepad',
button: buttonDown,
});
this.setLastProcessedMovementTime(buttonDown, 'gamepad');
this.setLastProcessedMovementTime(buttonDown, 'gamepad', pad.id);
}
}
/**
* Handles the 'up' event for gamepad buttons, emitting appropriate events and clearing the interaction state.
* Responds to a button release event on a gamepad by checking if the gamepad is supported and currently chosen.
* If conditions are met, it identifies the configured action for the button, emits an event signaling the button release,
* and clears the record of the button.
*
* @param pad - The gamepad on which the button release occurred.
* @param button - The button that was released.
* @param value - The value associated with the button release, typically indicating pressure or degree of deactivation.
*
* @remarks
* This method is triggered when a gamepad button is released. If gamepad support is enabled, it:
* - Retrieves the current gamepad action mapping.
* - Checks if the released button is mapped to a game action.
* - If mapped, emits an 'input_up' event with the controller type and button action, and clears the interaction for this button.
* @param pad The gamepad from which the button was released.
* @param button The specific button that was released.
* @param value The intensity or value of the button release, if applicable.
*/
gamepadButtonUp(pad: Phaser.Input.Gamepad.Gamepad, button: Phaser.Input.Gamepad.Button, value: number): void {
if (!this.gamepadSupport) return;
const actionMapping = this.getActionGamepadMapping();
const buttonUp = actionMapping.hasOwnProperty(button.index) && actionMapping[button.index];
if (!pad) return;
this.lastSource = 'gamepad';
if (!this.gamepadSupport || pad.id.toLowerCase() !== this.selectedDevice[Device.GAMEPAD]) return;
const buttonUp = getButtonWithKeycode(this.getActiveConfig(Device.GAMEPAD), button.index);
if (buttonUp !== undefined) {
this.events.emit('input_up', {
controller_type: 'gamepad',
@ -311,112 +468,14 @@ export class InputsController {
}
/**
* Configures keyboard controls for the game, mapping physical keys to game actions.
* Retrieves the configuration object for a gamepad based on its identifier. The method identifies specific gamepad models
* based on substrings in the identifier and returns predefined configurations for recognized models.
* If no specific configuration matches, it defaults to a generic gamepad configuration.
*
* @remarks
* This method sets up keyboard bindings for game controls using Phaser's `KeyCodes`. Each game action, represented
* by a button in the `Button` enum, is associated with one or more physical keys. For example, movement actions
* (up, down, left, right) are mapped to both arrow keys and WASD keys. Actions such as submit, cancel, and other
* game-specific functions are mapped to appropriate keys like Enter, Space, etc.
*
* The method does the following:
* - Defines a `keyConfig` object that associates each `Button` enum value with an array of `KeyCodes`.
* - Iterates over all values of the `Button` enum to set up these key bindings within the Phaser game scene.
* - For each button, it adds the respective keys to the game's input system and stores them in `this.buttonKeys`.
* - Additional configurations for mobile or alternative input schemes are stored in `mobileKeyConfig`.
*
* Post-setup, it initializes touch controls (if applicable) and starts listening for keyboard inputs using
* `listenInputKeyboard`, ensuring that all configured keys are actively monitored for player interactions.
* @param id The identifier string of the gamepad.
* @returns InterfaceConfig The configuration object corresponding to the identified gamepad type.
*/
setupKeyboardControls(): void {
const keyCodes = Phaser.Input.Keyboard.KeyCodes;
const keyConfig = {
[Button.UP]: [keyCodes.UP, keyCodes.W],
[Button.DOWN]: [keyCodes.DOWN, keyCodes.S],
[Button.LEFT]: [keyCodes.LEFT, keyCodes.A],
[Button.RIGHT]: [keyCodes.RIGHT, keyCodes.D],
[Button.SUBMIT]: [keyCodes.ENTER],
[Button.ACTION]: [keyCodes.SPACE, keyCodes.Z],
[Button.CANCEL]: [keyCodes.BACKSPACE, keyCodes.X],
[Button.MENU]: [keyCodes.ESC, keyCodes.M],
[Button.STATS]: [keyCodes.SHIFT, keyCodes.C],
[Button.CYCLE_SHINY]: [keyCodes.R],
[Button.CYCLE_FORM]: [keyCodes.F],
[Button.CYCLE_GENDER]: [keyCodes.G],
[Button.CYCLE_ABILITY]: [keyCodes.E],
[Button.CYCLE_NATURE]: [keyCodes.N],
[Button.CYCLE_VARIANT]: [keyCodes.V],
[Button.SPEED_UP]: [keyCodes.PLUS],
[Button.SLOW_DOWN]: [keyCodes.MINUS]
};
const mobileKeyConfig = {};
for (const b of Utils.getEnumValues(Button)) {
const keys: Phaser.Input.Keyboard.Key[] = [];
if (keyConfig.hasOwnProperty(b)) {
for (let k of keyConfig[b])
keys.push(this.scene.input.keyboard.addKey(k, false));
mobileKeyConfig[Button[b]] = keys[0];
}
this.buttonKeys[b] = keys;
}
initTouchControls(mobileKeyConfig);
this.listenInputKeyboard();
}
/**
* Sets up event listeners for keyboard inputs on all registered keys.
*
* @remarks
* This method iterates over an array of keyboard button rows (`this.buttonKeys`), adding 'down' and 'up'
* event listeners for each key. These listeners handle key press and release actions respectively.
*
* - **Key Down Event**: When a key is pressed down, the method emits an 'input_down' event with the button
* and the source ('keyboard'). It also records the time and state of the key press by calling
* `setLastProcessedMovementTime`.
*
* - **Key Up Event**: When a key is released, the method emits an 'input_up' event similarly, specifying the button
* and source. It then clears the recorded press time and state by calling
* `delLastProcessedMovementTime`.
*
* This setup ensures that each key on the keyboard is monitored for press and release events,
* and that these events are properly communicated within the system.
*/
listenInputKeyboard(): void {
this.buttonKeys.forEach((row, index) => {
for (const key of row) {
key.on('down', () => {
this.events.emit('input_down', {
controller_type: 'keyboard',
button: index,
});
this.setLastProcessedMovementTime(index, 'keyboard');
});
key.on('up', () => {
this.events.emit('input_up', {
controller_type: 'keyboard',
button: index,
});
this.delLastProcessedMovementTime(index);
});
}
});
}
/**
* Maps a gamepad ID to a specific gamepad configuration based on the ID's characteristics.
*
* @param id - The gamepad ID string, typically representing a unique identifier for a gamepad model or make.
* @returns A `GamepadConfig` object corresponding to the identified gamepad model.
*
* @remarks
* This function analyzes the provided gamepad ID and matches it to a predefined configuration based on known identifiers:
* - If the ID includes both '081f' and 'e401', it is identified as an unlicensed SNES gamepad.
* - If the ID contains 'xbox' and '360', it is identified as an Xbox 360 gamepad.
* - If the ID contains '054c', it is identified as a DualShock gamepad.
* If no specific identifiers are recognized, a generic gamepad configuration is returned.
*/
mapGamepad(id: string): GamepadConfig {
getConfig(id: string): InterfaceConfig {
id = id.toLowerCase();
if (id.includes('081f') && id.includes('e401')) {
@ -430,6 +489,19 @@ export class InputsController {
return pad_generic;
}
/**
* Retrieves the configuration object for a keyboard layout based on its identifier.
*
* @param id The identifier string of the keyboard layout.
* @returns InterfaceConfig The configuration object corresponding to the identified keyboard layout.
*/
getConfigKeyboard(id: string): InterfaceConfig {
if (id === 'default')
return cfg_keyboard_azerty;
return cfg_keyboard_azerty;
}
/**
* repeatInputDurationJustPassed returns true if @param button has been held down long
* enough to fire a repeated input. A button must claim the buttonLock before
@ -457,12 +529,13 @@ export class InputsController {
*
* Additionally, this method locks the button (by calling `setButtonLock`) to prevent it from being re-processed until it is released, ensuring that each press is handled distinctly.
*/
setLastProcessedMovementTime(button: Button, source: String = 'keyboard'): void {
setLastProcessedMovementTime(button: Button, source: String = 'keyboard', sourceName?: String): void {
if (!this.interactions.hasOwnProperty(button)) return;
this.setButtonLock(button);
this.interactions[button].pressTime = this.time.now;
this.interactions[button].isPressed = true;
this.interactions[button].source = source;
this.interactions[button].sourceName = sourceName.toLowerCase();
}
/**
@ -485,6 +558,7 @@ export class InputsController {
this.interactions[button].pressTime = null;
this.interactions[button].isPressed = false;
this.interactions[button].source = null;
this.interactions[button].sourceName = null;
}
/**
@ -506,6 +580,7 @@ export class InputsController {
* This method is typically called when needing to ensure that all inputs are neutralized.
*/
deactivatePressedKey(): void {
this.pauseUpdate = true;
this.releaseButtonLock(this.buttonLock);
this.releaseButtonLock(this.buttonLock2);
for (const b of Utils.getEnumValues(Button)) {
@ -513,8 +588,10 @@ export class InputsController {
this.interactions[b].pressTime = null;
this.interactions[b].isPressed = false;
this.interactions[b].source = null;
this.interactions[b].sourceName = null;
}
}
setTimeout(() => this.pauseUpdate = false, 500);
}
/**
@ -564,4 +641,71 @@ export class InputsController {
if (this.buttonLock === button) this.buttonLock = null;
else if (this.buttonLock2 === button) this.buttonLock2 = null;
}
/**
* Retrieves the active configuration for the currently chosen device.
* It checks if a specific device ID is stored in configurations and returns it.
*
* @returns InterfaceConfig The configuration object for the active gamepad, or null if not set.
*/
getActiveConfig(device: Device) {
if (this.configs[this.selectedDevice[device]]?.padID) return this.configs[this.selectedDevice[device]]
return null;
}
getIconForLatestInputRecorded(settingName) {
if (this.lastSource === 'keyboard') this.ensureKeyboardIsInit();
return getIconForLatestInput(this.configs, this.lastSource, this.selectedDevice, settingName);
}
getLastSourceDevice(): Device {
if (this.lastSource === 'gamepad') return Device.GAMEPAD;
else return Device.KEYBOARD;
}
getLastSourceConfig() {
const sourceDevice = this.getLastSourceDevice();
if (sourceDevice === Device.KEYBOARD)
this.ensureKeyboardIsInit();
return this.getActiveConfig(sourceDevice);
}
getLastSourceType() {
const config = this.getLastSourceConfig();
return config?.padType;
}
/**
* Injects a custom mapping configuration into the configuration for a specific gamepad.
* If the device does not have an existing configuration, it initializes one first.
*
* @param selectedDevice The identifier of the device to configure.
* @param mappingConfigs The mapping configuration to apply to the device.
*/
injectConfig(selectedDevice: string, mappingConfigs): void {
if (!this.configs[selectedDevice]) this.configs[selectedDevice] = {};
this.configs[selectedDevice].custom = mappingConfigs.custom;
}
resetConfigs(): void {
this.configs = new Map();
if (this.getGamepadsName()?.length)
this.setupGamepad(this.selectedDevice[Device.GAMEPAD]);
this.setupKeyboard();
}
/**
* Swaps a binding in the configuration.
*
* @param config The configuration object.
* @param settingName The name of the setting to swap.
* @param pressedButton The button that was pressed.
*/
assignBinding(config, settingName, pressedButton): boolean {
this.pauseUpdate = true;
setTimeout(() => this.pauseUpdate = false, 500);
if (config.padType === 'keyboard')
return assign(config, settingName, pressedButton);
else return swap(config, settingName, pressedButton);
}
}

View File

@ -218,6 +218,14 @@ export class LoadingScene extends SceneBase {
this.loadAtlas(`pokemon_icons_${i}v`, '');
}
// Free icons from:
// https://juliocacko.itch.io/free-input-prompts
this.loadAtlas('dualshock', 'inputs');
this.loadAtlas('nswitch', 'inputs');
this.loadAtlas('xbox', 'inputs');
this.loadAtlas('snes', 'inputs');
this.loadAtlas('keyboard', 'inputs');
this.loadSe('select');
this.loadSe('menu_open');
this.loadSe('hit');

View File

@ -30,6 +30,9 @@ import { allMoves } from "../data/move";
import { TrainerVariant } from "../field/trainer";
import { OutdatedPhase, ReloadSessionPhase } from "#app/phases";
import { Variant, variantData } from "#app/data/variant";
import {setSettingGamepad, SettingGamepad, settingGamepadDefaults} from "./settings-gamepad";
import {MappingLayout} from "#app/inputs-controller";
import {setSettingKeyboard, SettingKeyboard, settingKeyboardDefaults} from "#app/system/settings-keyboard";
const saveKey = 'x0i2O7WRiANTqPmZ'; // Temporary; secure encryption is not yet necessary
@ -241,6 +244,8 @@ export class GameData {
constructor(scene: BattleScene) {
this.scene = scene;
this.loadSettings();
this.loadGamepadSettings();
this.loadMappingConfigs();
this.trainerId = Utils.randInt(65536);
this.secretId = Utils.randInt(65536);
this.starterData = {};
@ -538,11 +543,123 @@ export class GameData {
settings[s] = valueIndex;
});
localStorage.setItem('settings', JSON.stringify(settings));
return true;
}
/**
* Saves the mapping configurations for a specified device.
*
* @param deviceName - The name of the device for which the configurations are being saved.
* @param config - The configuration object containing custom mapping details.
* @returns `true` if the configurations are successfully saved.
*/
public saveMappingConfigs(deviceName: string, config): boolean {
const key = deviceName.toLowerCase(); // Convert the gamepad name to lowercase to use as a key
let mappingConfigs: object = {}; // Initialize an empty object to hold the mapping configurations
if (localStorage.hasOwnProperty('mappingConfigs')) // Check if 'mappingConfigs' exists in localStorage
mappingConfigs = JSON.parse(localStorage.getItem('mappingConfigs')); // Parse the existing 'mappingConfigs' from localStorage
if (!mappingConfigs[key]) mappingConfigs[key] = {}; // If there is no configuration for the given key, create an empty object for it
mappingConfigs[key].custom = config.custom; // Assign the custom configuration to the mapping configuration for the given key
localStorage.setItem('mappingConfigs', JSON.stringify(mappingConfigs)); // Save the updated mapping configurations back to localStorage
return true; // Return true to indicate the operation was successful
}
/**
* Loads the mapping configurations from localStorage and injects them into the input controller.
*
* @returns `true` if the configurations are successfully loaded and injected; `false` if no configurations are found in localStorage.
*
* @remarks
* This method checks if the 'mappingConfigs' entry exists in localStorage. If it does not exist, the method returns `false`.
* If 'mappingConfigs' exists, it parses the configurations and injects each configuration into the input controller
* for the corresponding gamepad or device key. The method then returns `true` to indicate success.
*/
public loadMappingConfigs(): boolean {
if (!localStorage.hasOwnProperty('mappingConfigs')) // Check if 'mappingConfigs' exists in localStorage
return false; // If 'mappingConfigs' does not exist, return false
const mappingConfigs = JSON.parse(localStorage.getItem('mappingConfigs')); // Parse the existing 'mappingConfigs' from localStorage
for (const key of Object.keys(mappingConfigs)) // Iterate over the keys of the mapping configurations
this.scene.inputController.injectConfig(key, mappingConfigs[key]); // Inject each configuration into the input controller for the corresponding key
return true; // Return true to indicate the operation was successful
}
public resetMappingToFactory(): boolean {
if (!localStorage.hasOwnProperty('mappingConfigs')) // Check if 'mappingConfigs' exists in localStorage
return false; // If 'mappingConfigs' does not exist, return false
localStorage.removeItem('mappingConfigs');
this.scene.inputController.resetConfigs();
}
/**
* Saves a gamepad setting to localStorage.
*
* @param setting - The gamepad setting to save.
* @param valueIndex - The index of the value to set for the gamepad setting.
* @returns `true` if the setting is successfully saved.
*
* @remarks
* This method initializes an empty object for gamepad settings if none exist in localStorage.
* It then updates the setting in the current scene and iterates over the default gamepad settings
* to update the specified setting with the new value. Finally, it saves the updated settings back
* to localStorage and returns `true` to indicate success.
*/
public saveGamepadSetting(setting: SettingGamepad, valueIndex: integer): boolean {
let settingsGamepad: object = {}; // Initialize an empty object to hold the gamepad settings
if (localStorage.hasOwnProperty('settingsGamepad')) { // Check if 'settingsGamepad' exists in localStorage
settingsGamepad = JSON.parse(localStorage.getItem('settingsGamepad')); // Parse the existing 'settingsGamepad' from localStorage
}
setSettingGamepad(this.scene, setting as SettingGamepad, valueIndex); // Set the gamepad setting in the current scene
Object.keys(settingGamepadDefaults).forEach(s => { // Iterate over the default gamepad settings
if (s === setting) // If the current setting matches, update its value
settingsGamepad[s] = valueIndex;
});
localStorage.setItem('settingsGamepad', JSON.stringify(settingsGamepad)); // Save the updated gamepad settings back to localStorage
return true; // Return true to indicate the operation was successful
}
/**
* Saves a keyboard setting to localStorage.
*
* @param setting - The keyboard setting to save.
* @param valueIndex - The index of the value to set for the keyboard setting.
* @returns `true` if the setting is successfully saved.
*
* @remarks
* This method initializes an empty object for keyboard settings if none exist in localStorage.
* It then updates the setting in the current scene and iterates over the default keyboard settings
* to update the specified setting with the new value. Finally, it saves the updated settings back
* to localStorage and returns `true` to indicate success.
*/
public saveKeyboardSetting(setting: SettingKeyboard, valueIndex: integer): boolean {
let settingsKeyboard: object = {}; // Initialize an empty object to hold the keyboard settings
if (localStorage.hasOwnProperty('settingsKeyboard')) { // Check if 'settingsKeyboard' exists in localStorage
settingsKeyboard = JSON.parse(localStorage.getItem('settingsKeyboard')); // Parse the existing 'settingsKeyboard' from localStorage
}
setSettingKeyboard(this.scene, setting as SettingKeyboard, valueIndex); // Set the keyboard setting in the current scene
Object.keys(settingKeyboardDefaults).forEach(s => { // Iterate over the default keyboard settings
if (s === setting) // If the current setting matches, update its value
settingsKeyboard[s] = valueIndex;
});
localStorage.setItem('settingsKeyboard', JSON.stringify(settingsKeyboard)); // Save the updated keyboard settings back to localStorage
return true; // Return true to indicate the operation was successful
}
private loadSettings(): boolean {
Object.values(Setting).map(setting => setting as Setting).forEach(setting => setSetting(this.scene, setting, settingDefaults[setting]));
@ -555,6 +672,17 @@ export class GameData {
setSetting(this.scene, setting as Setting, settings[setting]);
}
private loadGamepadSettings(): boolean {
Object.values(SettingGamepad).map(setting => setting as SettingGamepad).forEach(setting => setSettingGamepad(this.scene, setting, settingGamepadDefaults[setting]));
if (!localStorage.hasOwnProperty('settingsGamepad'))
return false;
const settingsGamepad = JSON.parse(localStorage.getItem('settingsGamepad'));
for (let setting of Object.keys(settingsGamepad))
setSettingGamepad(this.scene, setting as SettingGamepad, settingsGamepad[setting]);
}
public saveTutorialFlag(tutorial: Tutorial, flag: boolean): boolean {
let tutorials: object = {};
if (localStorage.hasOwnProperty('tutorials'))

View File

@ -0,0 +1,146 @@
import BattleScene from "../battle-scene";
import {SettingDefaults, SettingOptions} from "./settings";
import SettingsGamepadUiHandler from "../ui/settings/settings-gamepad-ui-handler";
import {Mode} from "../ui/ui";
import {truncateString} from "../utils";
import {Button} from "../enums/buttons";
import {SettingKeyboard} from "#app/system/settings-keyboard";
export enum SettingGamepad {
Default_Controller = "DEFAULT_CONTROLLER",
Gamepad_Support = "GAMEPAD_SUPPORT",
Button_Up = "BUTTON_UP",
Button_Down = "BUTTON_DOWN",
Button_Left = "BUTTON_LEFT",
Button_Right = "BUTTON_RIGHT",
Button_Action = "BUTTON_ACTION",
Button_Cancel = "BUTTON_CANCEL",
Button_Menu = "BUTTON_MENU",
Button_Stats = "BUTTON_STATS",
Button_Cycle_Form = "BUTTON_CYCLE_FORM",
Button_Cycle_Shiny = "BUTTON_CYCLE_SHINY",
Button_Cycle_Gender = "BUTTON_CYCLE_GENDER",
Button_Cycle_Ability = "BUTTON_CYCLE_ABILITY",
Button_Cycle_Nature = "BUTTON_CYCLE_NATURE",
Button_Cycle_Variant = "BUTTON_CYCLE_VARIANT",
Button_Speed_Up = "BUTTON_SPEED_UP",
Button_Slow_Down = "BUTTON_SLOW_DOWN",
Button_Submit = "BUTTON_SUBMIT",
}
export const settingGamepadOptions: SettingOptions = {
[SettingGamepad.Default_Controller]: ['Default', 'Change'],
[SettingGamepad.Gamepad_Support]: ['Auto', 'Disabled'],
[SettingGamepad.Button_Up]: [`KEY ${Button.UP.toString()}`, 'Press action to assign'],
[SettingGamepad.Button_Down]: [`KEY ${Button.DOWN.toString()}`, 'Press action to assign'],
[SettingGamepad.Button_Left]: [`KEY ${Button.LEFT.toString()}`, 'Press action to assign'],
[SettingGamepad.Button_Right]: [`KEY ${Button.RIGHT.toString()}`, 'Press action to assign'],
[SettingGamepad.Button_Action]: [`KEY ${Button.ACTION.toString()}`, 'Press action to assign'],
[SettingGamepad.Button_Cancel]: [`KEY ${Button.CANCEL.toString()}`, 'Press action to assign'],
[SettingGamepad.Button_Menu]: [`KEY ${Button.MENU.toString()}`, 'Press action to assign'],
[SettingGamepad.Button_Stats]: [`KEY ${Button.STATS.toString()}`, 'Press action to assign'],
[SettingGamepad.Button_Cycle_Form]: [`KEY ${Button.CYCLE_FORM.toString()}`, 'Press action to assign'],
[SettingGamepad.Button_Cycle_Shiny]: [`KEY ${Button.CYCLE_SHINY.toString()}`, 'Press action to assign'],
[SettingGamepad.Button_Cycle_Gender]: [`KEY ${Button.CYCLE_GENDER.toString()}`, 'Press action to assign'],
[SettingGamepad.Button_Cycle_Ability]: [`KEY ${Button.CYCLE_ABILITY.toString()}`, 'Press action to assign'],
[SettingGamepad.Button_Cycle_Nature]: [`KEY ${Button.CYCLE_NATURE.toString()}`, 'Press action to assign'],
[SettingGamepad.Button_Cycle_Variant]: [`KEY ${Button.CYCLE_VARIANT.toString()}`, 'Press action to assign'],
[SettingGamepad.Button_Speed_Up]: [`KEY ${Button.SPEED_UP.toString()}`, 'Press action to assign'],
[SettingGamepad.Button_Slow_Down]: [`KEY ${Button.SLOW_DOWN.toString()}`, 'Press action to assign'],
[SettingGamepad.Button_Submit]: [`KEY ${Button.SUBMIT.toString()}`, 'Press action to assign'],
};
export const settingGamepadDefaults: SettingDefaults = {
[SettingGamepad.Default_Controller]: 0,
[SettingGamepad.Gamepad_Support]: 0,
[SettingGamepad.Button_Up]: 0,
[SettingGamepad.Button_Down]: 0,
[SettingGamepad.Button_Left]: 0,
[SettingGamepad.Button_Right]: 0,
[SettingGamepad.Button_Action]: 0,
[SettingGamepad.Button_Cancel]: 0,
[SettingGamepad.Button_Menu]: 0,
[SettingGamepad.Button_Stats]: 0,
[SettingGamepad.Button_Cycle_Form]: 0,
[SettingGamepad.Button_Cycle_Shiny]: 0,
[SettingGamepad.Button_Cycle_Gender]: 0,
[SettingGamepad.Button_Cycle_Ability]: 0,
[SettingGamepad.Button_Cycle_Nature]: 0,
[SettingGamepad.Button_Cycle_Variant]: 0,
[SettingGamepad.Button_Speed_Up]: 0,
[SettingGamepad.Button_Slow_Down]: 0,
[SettingGamepad.Button_Submit]: 0,
};
export const settingGamepadBlackList = [
SettingKeyboard.Button_Up,
SettingKeyboard.Button_Down,
SettingKeyboard.Button_Left,
SettingKeyboard.Button_Right,
];
export function setSettingGamepad(scene: BattleScene, setting: SettingGamepad, value: integer): boolean {
switch (setting) {
case SettingGamepad.Gamepad_Support:
// if we change the value of the gamepad support, we call a method in the inputController to
// activate or deactivate the controller listener
scene.inputController.setGamepadSupport(settingGamepadOptions[setting][value] !== 'Disabled');
break;
case SettingGamepad.Button_Action:
case SettingGamepad.Button_Cancel:
case SettingGamepad.Button_Menu:
case SettingGamepad.Button_Stats:
case SettingGamepad.Button_Cycle_Shiny:
case SettingGamepad.Button_Cycle_Form:
case SettingGamepad.Button_Cycle_Gender:
case SettingGamepad.Button_Cycle_Ability:
case SettingGamepad.Button_Cycle_Nature:
case SettingGamepad.Button_Cycle_Variant:
case SettingGamepad.Button_Speed_Up:
case SettingGamepad.Button_Slow_Down:
if (value) {
if (scene.ui) {
const cancelHandler = (success: boolean = false) : boolean => {
scene.ui.revertMode();
(scene.ui.getHandler() as SettingsGamepadUiHandler).updateBindings();
return success;
};
scene.ui.setOverlayMode(Mode.GAMEPAD_BINDING, {
target: setting,
cancelHandler: cancelHandler,
});
}
}
break;
case SettingGamepad.Default_Controller:
if (value) {
const gp = scene.inputController.getGamepadsName();
if (scene.ui && gp) {
const cancelHandler = () => {
scene.ui.revertMode();
(scene.ui.getHandler() as SettingsGamepadUiHandler).setOptionCursor(Object.values(SettingGamepad).indexOf(SettingGamepad.Default_Controller), 0, true);
(scene.ui.getHandler() as SettingsGamepadUiHandler).updateBindings();
return false;
};
const changeGamepadHandler = (gamepad: string) => {
scene.inputController.setChosenGamepad(gamepad);
cancelHandler();
return true;
};
scene.ui.setOverlayMode(Mode.OPTION_SELECT, {
options: [...gp.map((g) => ({
label: truncateString(g, 30), // Truncate the gamepad name for display
handler: () => changeGamepadHandler(g)
})), {
label: 'Cancel',
handler: cancelHandler,
}]
});
return false;
}
}
break;
}
return true;
}

View File

@ -0,0 +1,206 @@
import {SettingDefaults, SettingOptions} from "#app/system/settings";
import {Button} from "#app/enums/buttons";
import BattleScene from "#app/battle-scene";
import {Mode} from "#app/ui/ui";
import SettingsKeyboardUiHandler from "#app/ui/settings/settings-keyboard-ui-handler";
export enum SettingKeyboard {
// Default_Layout = "DEFAULT_LAYOUT",
Button_Up = "BUTTON_UP",
Alt_Button_Up = "ALT_BUTTON_UP",
Button_Down = "BUTTON_DOWN",
Alt_Button_Down = "ALT_BUTTON_DOWN",
Button_Left = "BUTTON_LEFT",
Alt_Button_Left = "ALT_BUTTON_LEFT",
Button_Right = "BUTTON_RIGHT",
Alt_Button_Right = "ALT_BUTTON_RIGHT",
Button_Action = "BUTTON_ACTION",
Alt_Button_Action = "ALT_BUTTON_ACTION",
Button_Cancel = "BUTTON_CANCEL",
Alt_Button_Cancel = "ALT_BUTTON_CANCEL",
Button_Menu = "BUTTON_MENU",
Alt_Button_Menu = "ALT_BUTTON_MENU",
Button_Stats = "BUTTON_STATS",
Alt_Button_Stats = "ALT_BUTTON_STATS",
Button_Cycle_Form = "BUTTON_CYCLE_FORM",
Alt_Button_Cycle_Form = "ALT_BUTTON_CYCLE_FORM",
Button_Cycle_Shiny = "BUTTON_CYCLE_SHINY",
Alt_Button_Cycle_Shiny = "ALT_BUTTON_CYCLE_SHINY",
Button_Cycle_Gender = "BUTTON_CYCLE_GENDER",
Alt_Button_Cycle_Gender = "ALT_BUTTON_CYCLE_GENDER",
Button_Cycle_Ability = "BUTTON_CYCLE_ABILITY",
Alt_Button_Cycle_Ability = "ALT_BUTTON_CYCLE_ABILITY",
Button_Cycle_Nature = "BUTTON_CYCLE_NATURE",
Alt_Button_Cycle_Nature = "ALT_BUTTON_CYCLE_NATURE",
Button_Cycle_Variant = "BUTTON_CYCLE_VARIANT",
Alt_Button_Cycle_Variant = "ALT_BUTTON_CYCLE_VARIANT",
Button_Speed_Up = "BUTTON_SPEED_UP",
Alt_Button_Speed_Up = "ALT_BUTTON_SPEED_UP",
Button_Slow_Down = "BUTTON_SLOW_DOWN",
Alt_Button_Slow_Down = "ALT_BUTTON_SLOW_DOWN",
Button_Submit = "BUTTON_SUBMIT",
Alt_Button_Submit = "ALT_BUTTON_SUBMIT",
}
export const settingKeyboardOptions: SettingOptions = {
// [SettingKeyboard.Default_Layout]: ['Default'],
[SettingKeyboard.Button_Up]: [`KEY ${Button.UP.toString()}`, 'Press action to assign'],
[SettingKeyboard.Button_Down]: [`KEY ${Button.DOWN.toString()}`, 'Press action to assign'],
[SettingKeyboard.Alt_Button_Up]: [`KEY ${Button.UP.toString()}`, 'Press action to assign'],
[SettingKeyboard.Button_Left]: [`KEY ${Button.LEFT.toString()}`, 'Press action to assign'],
[SettingKeyboard.Button_Right]: [`KEY ${Button.RIGHT.toString()}`, 'Press action to assign'],
[SettingKeyboard.Button_Action]: [`KEY ${Button.ACTION.toString()}`, 'Press action to assign'],
[SettingKeyboard.Button_Menu]: [`KEY ${Button.MENU.toString()}`, 'Press action to assign'],
[SettingKeyboard.Button_Submit]: [`KEY ${Button.SUBMIT.toString()}`, 'Press action to assign'],
[SettingKeyboard.Alt_Button_Down]: [`KEY ${Button.DOWN.toString()}`, 'Press action to assign'],
[SettingKeyboard.Alt_Button_Left]: [`KEY ${Button.LEFT.toString()}`, 'Press action to assign'],
[SettingKeyboard.Alt_Button_Right]: [`KEY ${Button.RIGHT.toString()}`, 'Press action to assign'],
[SettingKeyboard.Alt_Button_Action]: [`KEY ${Button.ACTION.toString()}`, 'Press action to assign'],
[SettingKeyboard.Button_Cancel]: [`KEY ${Button.CANCEL.toString()}`, 'Press action to assign'],
[SettingKeyboard.Alt_Button_Cancel]: [`KEY ${Button.CANCEL.toString()}`, 'Press action to assign'],
[SettingKeyboard.Alt_Button_Menu]: [`KEY ${Button.MENU.toString()}`, 'Press action to assign'],
[SettingKeyboard.Button_Stats]: [`KEY ${Button.STATS.toString()}`, 'Press action to assign'],
[SettingKeyboard.Alt_Button_Stats]: [`KEY ${Button.STATS.toString()}`, 'Press action to assign'],
[SettingKeyboard.Button_Cycle_Form]: [`KEY ${Button.CYCLE_FORM.toString()}`, 'Press action to assign'],
[SettingKeyboard.Alt_Button_Cycle_Form]: [`KEY ${Button.CYCLE_FORM.toString()}`, 'Press action to assign'],
[SettingKeyboard.Button_Cycle_Shiny]: [`KEY ${Button.CYCLE_SHINY.toString()}`, 'Press action to assign'],
[SettingKeyboard.Alt_Button_Cycle_Shiny]: [`KEY ${Button.CYCLE_SHINY.toString()}`, 'Press action to assign'],
[SettingKeyboard.Button_Cycle_Gender]: [`KEY ${Button.CYCLE_GENDER.toString()}`, 'Press action to assign'],
[SettingKeyboard.Alt_Button_Cycle_Gender]: [`KEY ${Button.CYCLE_GENDER.toString()}`, 'Press action to assign'],
[SettingKeyboard.Button_Cycle_Ability]: [`KEY ${Button.CYCLE_ABILITY.toString()}`, 'Press action to assign'],
[SettingKeyboard.Alt_Button_Cycle_Ability]: [`KEY ${Button.CYCLE_ABILITY.toString()}`, 'Press action to assign'],
[SettingKeyboard.Button_Cycle_Nature]: [`KEY ${Button.CYCLE_NATURE.toString()}`, 'Press action to assign'],
[SettingKeyboard.Alt_Button_Cycle_Nature]: [`KEY ${Button.CYCLE_NATURE.toString()}`, 'Press action to assign'],
[SettingKeyboard.Button_Cycle_Variant]: [`KEY ${Button.CYCLE_VARIANT.toString()}`, 'Press action to assign'],
[SettingKeyboard.Alt_Button_Cycle_Variant]: [`KEY ${Button.CYCLE_VARIANT.toString()}`, 'Press action to assign'],
[SettingKeyboard.Button_Speed_Up]: [`KEY ${Button.SPEED_UP.toString()}`, 'Press action to assign'],
[SettingKeyboard.Alt_Button_Speed_Up]: [`KEY ${Button.SPEED_UP.toString()}`, 'Press action to assign'],
[SettingKeyboard.Button_Slow_Down]: [`KEY ${Button.SLOW_DOWN.toString()}`, 'Press action to assign'],
[SettingKeyboard.Alt_Button_Slow_Down]: [`KEY ${Button.SLOW_DOWN.toString()}`, 'Press action to assign'],
[SettingKeyboard.Alt_Button_Submit]: [`KEY ${Button.SUBMIT.toString()}`, 'Press action to assign'],
};
export const settingKeyboardDefaults: SettingDefaults = {
// [SettingKeyboard.Default_Layout]: 0,
[SettingKeyboard.Button_Up]: 0,
[SettingKeyboard.Button_Down]: 0,
[SettingKeyboard.Button_Left]: 0,
[SettingKeyboard.Button_Right]: 0,
[SettingKeyboard.Button_Action]: 0,
[SettingKeyboard.Button_Menu]: 0,
[SettingKeyboard.Button_Submit]: 0,
[SettingKeyboard.Alt_Button_Up]: 0,
[SettingKeyboard.Alt_Button_Down]: 0,
[SettingKeyboard.Alt_Button_Left]: 0,
[SettingKeyboard.Alt_Button_Right]: 0,
[SettingKeyboard.Alt_Button_Action]: 0,
[SettingKeyboard.Button_Cancel]: 0,
[SettingKeyboard.Alt_Button_Cancel]: 0,
[SettingKeyboard.Alt_Button_Menu]: 0,
[SettingKeyboard.Button_Stats]: 0,
[SettingKeyboard.Alt_Button_Stats]: 0,
[SettingKeyboard.Button_Cycle_Form]: 0,
[SettingKeyboard.Alt_Button_Cycle_Form]: 0,
[SettingKeyboard.Button_Cycle_Shiny]: 0,
[SettingKeyboard.Alt_Button_Cycle_Shiny]: 0,
[SettingKeyboard.Button_Cycle_Gender]: 0,
[SettingKeyboard.Alt_Button_Cycle_Gender]: 0,
[SettingKeyboard.Button_Cycle_Ability]: 0,
[SettingKeyboard.Alt_Button_Cycle_Ability]: 0,
[SettingKeyboard.Button_Cycle_Nature]: 0,
[SettingKeyboard.Alt_Button_Cycle_Nature]: 0,
[SettingKeyboard.Button_Cycle_Variant]: 0,
[SettingKeyboard.Alt_Button_Cycle_Variant]: 0,
[SettingKeyboard.Button_Speed_Up]: 0,
[SettingKeyboard.Alt_Button_Speed_Up]: 0,
[SettingKeyboard.Button_Slow_Down]: 0,
[SettingKeyboard.Alt_Button_Slow_Down]: 0,
[SettingKeyboard.Alt_Button_Submit]: 0,
};
export const settingKeyboardBlackList = [
SettingKeyboard.Button_Submit,
SettingKeyboard.Button_Menu,
SettingKeyboard.Button_Action,
SettingKeyboard.Button_Up,
SettingKeyboard.Button_Down,
SettingKeyboard.Button_Left,
SettingKeyboard.Button_Right,
];
export function setSettingKeyboard(scene: BattleScene, setting: SettingKeyboard, value: integer): boolean {
switch (setting) {
case SettingKeyboard.Button_Up:
case SettingKeyboard.Button_Down:
case SettingKeyboard.Button_Left:
case SettingKeyboard.Button_Right:
case SettingKeyboard.Button_Action:
case SettingKeyboard.Button_Cancel:
case SettingKeyboard.Button_Menu:
case SettingKeyboard.Button_Stats:
case SettingKeyboard.Button_Cycle_Shiny:
case SettingKeyboard.Button_Cycle_Form:
case SettingKeyboard.Button_Cycle_Gender:
case SettingKeyboard.Button_Cycle_Ability:
case SettingKeyboard.Button_Cycle_Nature:
case SettingKeyboard.Button_Cycle_Variant:
case SettingKeyboard.Button_Speed_Up:
case SettingKeyboard.Button_Slow_Down:
case SettingKeyboard.Alt_Button_Up:
case SettingKeyboard.Alt_Button_Down:
case SettingKeyboard.Alt_Button_Left:
case SettingKeyboard.Alt_Button_Right:
case SettingKeyboard.Alt_Button_Action:
case SettingKeyboard.Alt_Button_Cancel:
case SettingKeyboard.Alt_Button_Menu:
case SettingKeyboard.Alt_Button_Stats:
case SettingKeyboard.Alt_Button_Cycle_Shiny:
case SettingKeyboard.Alt_Button_Cycle_Form:
case SettingKeyboard.Alt_Button_Cycle_Gender:
case SettingKeyboard.Alt_Button_Cycle_Ability:
case SettingKeyboard.Alt_Button_Cycle_Nature:
case SettingKeyboard.Alt_Button_Cycle_Variant:
case SettingKeyboard.Alt_Button_Speed_Up:
case SettingKeyboard.Alt_Button_Slow_Down:
if (value) {
if (scene.ui) {
const cancelHandler = (success: boolean = false) : boolean => {
scene.ui.revertMode();
(scene.ui.getHandler() as SettingsKeyboardUiHandler).updateBindings();
return success;
}
scene.ui.setOverlayMode(Mode.KEYBOARD_BINDING, {
target: setting,
cancelHandler: cancelHandler,
})
}
}
break;
// case SettingKeyboard.Default_Layout:
// if (value && scene.ui) {
// const cancelHandler = () => {
// scene.ui.revertMode();
// (scene.ui.getHandler() as SettingsKeyboardUiHandler).setOptionCursor(Object.values(SettingKeyboard).indexOf(SettingKeyboard.Default_Layout), 0, true);
// (scene.ui.getHandler() as SettingsKeyboardUiHandler).updateBindings();
// return false;
// };
// const changeKeyboardHandler = (keyboardLayout: string) => {
// scene.inputController.setChosenKeyboardLayout(keyboardLayout);
// cancelHandler();
// return true;
// };
// scene.ui.setOverlayMode(Mode.OPTION_SELECT, {
// options: [{
// label: 'Default',
// handler: changeKeyboardHandler,
// }]
// });
// return false;
// }
}
return true;
}

View File

@ -1,10 +1,10 @@
import SettingsUiHandler from "#app/ui/settings-ui-handler";
import { Mode } from "#app/ui/ui";
import i18next from "i18next";
import BattleScene from "../battle-scene";
import { hasTouchscreen } from "../touch-controls";
import { updateWindowType } from "../ui/ui-theme";
import { PlayerGender } from "./game-data";
import { Mode } from "../ui/ui";
import SettingsUiHandler from "../ui/settings/settings-ui-handler";
export enum Setting {
Game_Speed = "GAME_SPEED",
@ -25,8 +25,6 @@ export enum Setting {
HP_Bar_Speed = "HP_BAR_SPEED",
Fusion_Palette_Swaps = "FUSION_PALETTE_SWAPS",
Player_Gender = "PLAYER_GENDER",
Gamepad_Support = "GAMEPAD_SUPPORT",
Swap_A_and_B = "SWAP_A_B", // Swaps which gamepad button handles ACTION and CANCEL
Touch_Controls = "TOUCH_CONTROLS",
Vibration = "VIBRATION"
}
@ -58,8 +56,6 @@ export const settingOptions: SettingOptions = {
[Setting.HP_Bar_Speed]: ['Normal', 'Fast', 'Faster', 'Instant'],
[Setting.Fusion_Palette_Swaps]: ['Off', 'On'],
[Setting.Player_Gender]: ['Boy', 'Girl'],
[Setting.Gamepad_Support]: ['Auto', 'Disabled'],
[Setting.Swap_A_and_B]: ['Enabled', 'Disabled'],
[Setting.Touch_Controls]: ['Auto', 'Disabled'],
[Setting.Vibration]: ['Auto', 'Disabled']
};
@ -83,8 +79,6 @@ export const settingDefaults: SettingDefaults = {
[Setting.HP_Bar_Speed]: 0,
[Setting.Fusion_Palette_Swaps]: 1,
[Setting.Player_Gender]: 0,
[Setting.Gamepad_Support]: 0,
[Setting.Swap_A_and_B]: 1, // Set to 'Disabled' by default
[Setting.Touch_Controls]: 0,
[Setting.Vibration]: 0
};
@ -154,14 +148,6 @@ export function setSetting(scene: BattleScene, setting: Setting, value: integer)
} else
return false;
break;
case Setting.Gamepad_Support:
// if we change the value of the gamepad support, we call a method in the inputController to
// activate or deactivate the controller listener
scene.inputController.setGamepadSupport(settingOptions[setting][value] !== 'Disabled');
break;
case Setting.Swap_A_and_B:
scene.abSwapped = settingOptions[setting][value] !== 'Disabled';
break;
case Setting.Touch_Controls:
scene.enableTouchControls = settingOptions[setting][value] !== 'Disabled' && hasTouchscreen();
const touchControls = document.getElementById('touchControls');

View File

@ -0,0 +1,330 @@
import {Button} from "#app/enums/buttons";
export enum SettingInterface {
Default_Layout = "DEFAULT_LAYOUT",
Button_Up = "BUTTON_UP",
Alt_Button_Up = "ALT_BUTTON_UP",
Button_Down = "BUTTON_DOWN",
Alt_Button_Down = "ALT_BUTTON_DOWN",
Button_Left = "BUTTON_LEFT",
Alt_Button_Left = "ALT_BUTTON_LEFT",
Button_Right = "BUTTON_RIGHT",
Alt_Button_Right = "ALT_BUTTON_RIGHT",
Button_Action = "BUTTON_ACTION",
Alt_Button_Action = "ALT_BUTTON_ACTION",
Button_Cancel = "BUTTON_CANCEL",
Alt_Button_Cancel = "ALT_BUTTON_CANCEL",
Button_Menu = "BUTTON_MENU",
Alt_Button_Menu = "ALT_BUTTON_MENU",
Button_Stats = "BUTTON_STATS",
Alt_Button_Stats = "ALT_BUTTON_STATS",
Button_Cycle_Form = "BUTTON_CYCLE_FORM",
Alt_Button_Cycle_Form = "ALT_BUTTON_CYCLE_FORM",
Button_Cycle_Shiny = "BUTTON_CYCLE_SHINY",
Alt_Button_Cycle_Shiny = "ALT_BUTTON_CYCLE_SHINY",
Button_Cycle_Gender = "BUTTON_CYCLE_GENDER",
Alt_Button_Cycle_Gender = "ALT_BUTTON_CYCLE_GENDER",
Button_Cycle_Ability = "BUTTON_CYCLE_ABILITY",
Alt_Button_Cycle_Ability = "ALT_BUTTON_CYCLE_ABILITY",
Button_Cycle_Nature = "BUTTON_CYCLE_NATURE",
Alt_Button_Cycle_Nature = "ALT_BUTTON_CYCLE_NATURE",
Button_Cycle_Variant = "BUTTON_CYCLE_VARIANT",
Alt_Button_Cycle_Variant = "ALT_BUTTON_CYCLE_VARIANT",
Button_Speed_Up = "BUTTON_SPEED_UP",
Alt_Button_Speed_Up = "ALT_BUTTON_SPEED_UP",
Button_Slow_Down = "BUTTON_SLOW_DOWN",
Alt_Button_Slow_Down = "ALT_BUTTON_SLOW_DOWN",
Button_Submit = "BUTTON_SUBMIT",
Alt_Button_Submit = "ALT_BUTTON_SUBMIT",
}
const cfg_keyboard_azerty = {
padID: 'default',
padType: 'keyboard',
deviceMapping: {
KEY_A: Phaser.Input.Keyboard.KeyCodes.A,
KEY_B: Phaser.Input.Keyboard.KeyCodes.B,
KEY_C: Phaser.Input.Keyboard.KeyCodes.C,
KEY_D: Phaser.Input.Keyboard.KeyCodes.D,
KEY_E: Phaser.Input.Keyboard.KeyCodes.E,
KEY_F: Phaser.Input.Keyboard.KeyCodes.F,
KEY_G: Phaser.Input.Keyboard.KeyCodes.G,
KEY_H: Phaser.Input.Keyboard.KeyCodes.H,
KEY_I: Phaser.Input.Keyboard.KeyCodes.I,
KEY_J: Phaser.Input.Keyboard.KeyCodes.J,
KEY_K: Phaser.Input.Keyboard.KeyCodes.K,
KEY_L: Phaser.Input.Keyboard.KeyCodes.L,
KEY_M: Phaser.Input.Keyboard.KeyCodes.M,
KEY_N: Phaser.Input.Keyboard.KeyCodes.N,
KEY_O: Phaser.Input.Keyboard.KeyCodes.O,
KEY_P: Phaser.Input.Keyboard.KeyCodes.P,
KEY_Q: Phaser.Input.Keyboard.KeyCodes.Q,
KEY_R: Phaser.Input.Keyboard.KeyCodes.R,
KEY_S: Phaser.Input.Keyboard.KeyCodes.S,
KEY_T: Phaser.Input.Keyboard.KeyCodes.T,
KEY_U: Phaser.Input.Keyboard.KeyCodes.U,
KEY_V: Phaser.Input.Keyboard.KeyCodes.V,
KEY_W: Phaser.Input.Keyboard.KeyCodes.W,
KEY_X: Phaser.Input.Keyboard.KeyCodes.X,
KEY_Y: Phaser.Input.Keyboard.KeyCodes.Y,
KEY_Z: Phaser.Input.Keyboard.KeyCodes.Z,
KEY_0: Phaser.Input.Keyboard.KeyCodes.ZERO,
KEY_1: Phaser.Input.Keyboard.KeyCodes.ONE,
KEY_2: Phaser.Input.Keyboard.KeyCodes.TWO,
KEY_3: Phaser.Input.Keyboard.KeyCodes.THREE,
KEY_4: Phaser.Input.Keyboard.KeyCodes.FOUR,
KEY_5: Phaser.Input.Keyboard.KeyCodes.FIVE,
KEY_6: Phaser.Input.Keyboard.KeyCodes.SIX,
KEY_7: Phaser.Input.Keyboard.KeyCodes.SEVEN,
KEY_8: Phaser.Input.Keyboard.KeyCodes.EIGHT,
KEY_9: Phaser.Input.Keyboard.KeyCodes.NINE,
KEY_CTRL: Phaser.Input.Keyboard.KeyCodes.CTRL,
KEY_DEL: Phaser.Input.Keyboard.KeyCodes.DELETE,
KEY_END: Phaser.Input.Keyboard.KeyCodes.END,
KEY_ENTER: Phaser.Input.Keyboard.KeyCodes.ENTER,
KEY_ESC: Phaser.Input.Keyboard.KeyCodes.ESC,
KEY_F1: Phaser.Input.Keyboard.KeyCodes.F1,
KEY_F2: Phaser.Input.Keyboard.KeyCodes.F2,
KEY_F3: Phaser.Input.Keyboard.KeyCodes.F3,
KEY_F4: Phaser.Input.Keyboard.KeyCodes.F4,
KEY_F5: Phaser.Input.Keyboard.KeyCodes.F5,
KEY_F6: Phaser.Input.Keyboard.KeyCodes.F6,
KEY_F7: Phaser.Input.Keyboard.KeyCodes.F7,
KEY_F8: Phaser.Input.Keyboard.KeyCodes.F8,
KEY_F9: Phaser.Input.Keyboard.KeyCodes.F9,
KEY_F10: Phaser.Input.Keyboard.KeyCodes.F10,
KEY_F11: Phaser.Input.Keyboard.KeyCodes.F11,
KEY_F12: Phaser.Input.Keyboard.KeyCodes.F12,
KEY_HOME: Phaser.Input.Keyboard.KeyCodes.HOME,
KEY_INSERT: Phaser.Input.Keyboard.KeyCodes.INSERT,
KEY_PAGE_DOWN: Phaser.Input.Keyboard.KeyCodes.PAGE_DOWN,
KEY_PAGE_UP: Phaser.Input.Keyboard.KeyCodes.PAGE_UP,
KEY_PLUS: Phaser.Input.Keyboard.KeyCodes.NUMPAD_ADD, // Assuming numpad plus
KEY_MINUS: Phaser.Input.Keyboard.KeyCodes.NUMPAD_SUBTRACT, // Assuming numpad minus
KEY_QUOTATION: Phaser.Input.Keyboard.KeyCodes.QUOTES,
KEY_SHIFT: Phaser.Input.Keyboard.KeyCodes.SHIFT,
KEY_SPACE: Phaser.Input.Keyboard.KeyCodes.SPACE,
KEY_TAB: Phaser.Input.Keyboard.KeyCodes.TAB,
KEY_TILDE: Phaser.Input.Keyboard.KeyCodes.BACKTICK,
KEY_ARROW_UP: Phaser.Input.Keyboard.KeyCodes.UP,
KEY_ARROW_DOWN: Phaser.Input.Keyboard.KeyCodes.DOWN,
KEY_ARROW_LEFT: Phaser.Input.Keyboard.KeyCodes.LEFT,
KEY_ARROW_RIGHT: Phaser.Input.Keyboard.KeyCodes.RIGHT,
KEY_LEFT_BRACKET: Phaser.Input.Keyboard.KeyCodes.OPEN_BRACKET,
KEY_RIGHT_BRACKET: Phaser.Input.Keyboard.KeyCodes.CLOSED_BRACKET,
KEY_SEMICOLON: Phaser.Input.Keyboard.KeyCodes.SEMICOLON,
KEY_BACKSPACE: Phaser.Input.Keyboard.KeyCodes.BACKSPACE,
KEY_ALT: Phaser.Input.Keyboard.KeyCodes.ALT
},
icons: {
KEY_A: "T_A_Key_Dark.png",
KEY_B: "T_B_Key_Dark.png",
KEY_C: "T_C_Key_Dark.png",
KEY_D: "T_D_Key_Dark.png",
KEY_E: "T_E_Key_Dark.png",
KEY_F: "T_F_Key_Dark.png",
KEY_G: "T_G_Key_Dark.png",
KEY_H: "T_H_Key_Dark.png",
KEY_I: "T_I_Key_Dark.png",
KEY_J: "T_J_Key_Dark.png",
KEY_K: "T_K_Key_Dark.png",
KEY_L: "T_L_Key_Dark.png",
KEY_M: "T_M_Key_Dark.png",
KEY_N: "T_N_Key_Dark.png",
KEY_O: "T_O_Key_Dark.png",
KEY_P: "T_P_Key_Dark.png",
KEY_Q: "T_Q_Key_Dark.png",
KEY_R: "T_R_Key_Dark.png",
KEY_S: "T_S_Key_Dark.png",
KEY_T: "T_T_Key_Dark.png",
KEY_U: "T_U_Key_Dark.png",
KEY_V: "T_V_Key_Dark.png",
KEY_W: "T_W_Key_Dark.png",
KEY_X: "T_X_Key_Dark.png",
KEY_Y: "T_Y_Key_Dark.png",
KEY_Z: "T_Z_Key_Dark.png",
KEY_0: "T_0_Key_Dark.png",
KEY_1: "T_1_Key_Dark.png",
KEY_2: "T_2_Key_Dark.png",
KEY_3: "T_3_Key_Dark.png",
KEY_4: "T_4_Key_Dark.png",
KEY_5: "T_5_Key_Dark.png",
KEY_6: "T_6_Key_Dark.png",
KEY_7: "T_7_Key_Dark.png",
KEY_8: "T_8_Key_Dark.png",
KEY_9: "T_9_Key_Dark.png",
KEY_F1: "T_F1_Key_Dark.png",
KEY_F2: "T_F2_Key_Dark.png",
KEY_F3: "T_F3_Key_Dark.png",
KEY_F4: "T_F4_Key_Dark.png",
KEY_F5: "T_F5_Key_Dark.png",
KEY_F6: "T_F6_Key_Dark.png",
KEY_F7: "T_F7_Key_Dark.png",
KEY_F8: "T_F8_Key_Dark.png",
KEY_F9: "T_F9_Key_Dark.png",
KEY_F10: "T_F10_Key_Dark.png",
KEY_F11: "T_F11_Key_Dark.png",
KEY_F12: "T_F12_Key_Dark.png",
KEY_PAGE_DOWN: "T_PageDown_Key_Dark.png",
KEY_PAGE_UP: "T_PageUp_Key_Dark.png",
KEY_CTRL: "T_Crtl_Key_Dark.png",
KEY_DEL: "T_Del_Key_Dark.png",
KEY_END: "T_End_Key_Dark.png",
KEY_ENTER: "T_Enter_Alt_Key_Dark.png",
KEY_ESC: "T_Esc_Key_Dark.png",
KEY_HOME: "T_Home_Key_Dark.png",
KEY_INSERT: "T_Ins_Key_Dark.png",
KEY_PLUS: "T_Plus_Tall_Key_Dark.png",
KEY_MINUS: "T_Minus_Key_Dark.png",
KEY_QUOTATION: "T_Quotation_Key_Dark.png",
KEY_SHIFT: "T_Shift_Key_Dark.png",
KEY_SPACE: "T_Space_Key_Dark.png",
KEY_TAB: "T_Tab_Key_Dark.png",
KEY_TILDE: "T_Tilde_Key_Dark.png",
KEY_ARROW_UP: "T_Up_Key_Dark.png",
KEY_ARROW_DOWN: "T_Down_Key_Dark.png",
KEY_ARROW_LEFT: "T_Left_Key_Dark.png",
KEY_ARROW_RIGHT: "T_Right_Key_Dark.png",
KEY_LEFT_BRACKET: "T_Brackets_L_Key_Dark.png",
KEY_RIGHT_BRACKET: "T_Brackets_R_Key_Dark.png",
KEY_SEMICOLON: "T_Semicolon_Key_Dark.png",
KEY_BACKSPACE: "T_Backspace_Alt_Key_Dark.png",
KEY_ALT: "T_Alt_Key_Dark.png"
},
settings: {
[SettingInterface.Button_Up]: Button.UP,
[SettingInterface.Button_Down]: Button.DOWN,
[SettingInterface.Button_Left]: Button.LEFT,
[SettingInterface.Button_Right]: Button.RIGHT,
[SettingInterface.Button_Submit]: Button.SUBMIT,
[SettingInterface.Button_Action]: Button.ACTION,
[SettingInterface.Button_Cancel]: Button.CANCEL,
[SettingInterface.Button_Menu]: Button.MENU,
[SettingInterface.Button_Stats]: Button.STATS,
[SettingInterface.Button_Cycle_Shiny]: Button.CYCLE_SHINY,
[SettingInterface.Button_Cycle_Form]: Button.CYCLE_FORM,
[SettingInterface.Button_Cycle_Gender]: Button.CYCLE_GENDER,
[SettingInterface.Button_Cycle_Ability]: Button.CYCLE_ABILITY,
[SettingInterface.Button_Cycle_Nature]: Button.CYCLE_NATURE,
[SettingInterface.Button_Cycle_Variant]: Button.CYCLE_VARIANT,
[SettingInterface.Button_Speed_Up]: Button.SPEED_UP,
[SettingInterface.Button_Slow_Down]: Button.SLOW_DOWN,
[SettingInterface.Alt_Button_Up]: Button.UP,
[SettingInterface.Alt_Button_Down]: Button.DOWN,
[SettingInterface.Alt_Button_Left]: Button.LEFT,
[SettingInterface.Alt_Button_Right]: Button.RIGHT,
[SettingInterface.Alt_Button_Submit]: Button.SUBMIT,
[SettingInterface.Alt_Button_Action]: Button.ACTION,
[SettingInterface.Alt_Button_Cancel]: Button.CANCEL,
[SettingInterface.Alt_Button_Menu]: Button.MENU,
[SettingInterface.Alt_Button_Stats]: Button.STATS,
[SettingInterface.Alt_Button_Cycle_Shiny]: Button.CYCLE_SHINY,
[SettingInterface.Alt_Button_Cycle_Form]: Button.CYCLE_FORM,
[SettingInterface.Alt_Button_Cycle_Gender]: Button.CYCLE_GENDER,
[SettingInterface.Alt_Button_Cycle_Ability]: Button.CYCLE_ABILITY,
[SettingInterface.Alt_Button_Cycle_Nature]: Button.CYCLE_NATURE,
[SettingInterface.Alt_Button_Cycle_Variant]: Button.CYCLE_VARIANT,
[SettingInterface.Alt_Button_Speed_Up]: Button.SPEED_UP,
[SettingInterface.Alt_Button_Slow_Down]: Button.SLOW_DOWN,
},
default: {
KEY_ARROW_UP: SettingInterface.Button_Up,
KEY_ARROW_DOWN: SettingInterface.Button_Down,
KEY_ARROW_LEFT: SettingInterface.Button_Left,
KEY_ARROW_RIGHT: SettingInterface.Button_Right,
KEY_ENTER: SettingInterface.Button_Submit,
KEY_SPACE: SettingInterface.Button_Action,
KEY_BACKSPACE: SettingInterface.Button_Cancel,
KEY_ESC: SettingInterface.Button_Menu,
KEY_C: SettingInterface.Button_Stats,
KEY_R: SettingInterface.Button_Cycle_Shiny,
KEY_F: SettingInterface.Button_Cycle_Form,
KEY_G: SettingInterface.Button_Cycle_Gender,
KEY_E: SettingInterface.Button_Cycle_Ability,
KEY_N: SettingInterface.Button_Cycle_Nature,
KEY_V: SettingInterface.Button_Cycle_Variant,
KEY_PLUS: SettingInterface.Button_Speed_Up,
KEY_MINUS: SettingInterface.Button_Slow_Down,
KEY_A: -1,
KEY_B: -1,
KEY_D: SettingInterface.Alt_Button_Right,
KEY_H: -1,
KEY_I: SettingInterface.Alt_Button_Cycle_Nature,
KEY_J: -1,
KEY_K: SettingInterface.Alt_Button_Cycle_Variant,
KEY_L: SettingInterface.Alt_Button_Cycle_Ability,
KEY_M: SettingInterface.Alt_Button_Cycle_Form,
KEY_O: SettingInterface.Alt_Button_Cycle_Gender,
KEY_P: SettingInterface.Alt_Button_Cycle_Shiny,
KEY_Q: SettingInterface.Alt_Button_Left,
KEY_S: SettingInterface.Alt_Button_Down,
KEY_T: -1,
KEY_U: -1,
KEY_W: SettingInterface.Alt_Button_Action,
KEY_X: SettingInterface.Alt_Button_Cancel,
KEY_Y: -1,
KEY_Z: SettingInterface.Alt_Button_Up,
KEY_0: -1,
KEY_1: -1,
KEY_2: -1,
KEY_3: -1,
KEY_4: -1,
KEY_5: -1,
KEY_6: -1,
KEY_7: -1,
KEY_8: -1,
KEY_9: -1,
KEY_CTRL: SettingInterface.Alt_Button_Submit,
KEY_DEL: -1,
KEY_END: -1,
KEY_F1: -1,
KEY_F2: -1,
KEY_F3: -1,
KEY_F4: -1,
KEY_F5: -1,
KEY_F6: -1,
KEY_F7: -1,
KEY_F8: -1,
KEY_F9: -1,
KEY_F10: -1,
KEY_F11: -1,
KEY_F12: -1,
KEY_HOME: -1,
KEY_INSERT: -1,
KEY_PAGE_DOWN: SettingInterface.Alt_Button_Slow_Down,
KEY_PAGE_UP: SettingInterface.Alt_Button_Speed_Up,
KEY_QUOTATION: -1,
KEY_SHIFT: SettingInterface.Alt_Button_Stats,
KEY_TAB: SettingInterface.Alt_Button_Menu,
KEY_TILDE: -1,
KEY_LEFT_BRACKET: -1,
KEY_RIGHT_BRACKET: -1,
KEY_SEMICOLON: -1,
KEY_ALT: -1
},
main: [],
alt: [],
blacklist: [
"KEY_ENTER",
"KEY_ESC",
"KEY_ARROW_UP",
"KEY_ARROW_DOWN",
"KEY_ARROW_LEFT",
"KEY_ARROW_RIGHT",
"KEY_DEL",
"KEY_HOME",
]
};
export default cfg_keyboard_azerty;

View File

@ -0,0 +1,73 @@
import {
getIconForLatestInput,
getSettingNameWithKeycode
} from "#app/configs/configHandler";
import {expect} from "vitest";
import {SettingInterface} from "#app/test/cfg_keyboard.example";
export class InGameManip {
private config;
private keycode;
private settingName;
private icon;
private configs;
private latestSource;
private selectedDevice;
constructor(configs, config, selectedDevice) {
this.config = config;
this.configs = configs;
this.selectedDevice = selectedDevice;
this.keycode = null;
this.settingName = null;
this.icon = null;
this.latestSource = null;
}
whenWePressOnKeyboard(keycode) {
this.keycode = Phaser.Input.Keyboard.KeyCodes[keycode.toUpperCase()];
return this;
}
nothingShouldHappen() {
const settingName = getSettingNameWithKeycode(this.config, this.keycode);
expect(settingName).toEqual(-1);
return this;
}
forTheWantedBind(settingName) {
if (!settingName.includes("Button_")) settingName = "Button_" + settingName;
this.settingName = SettingInterface[settingName];
return this;
}
weShouldSeeTheIcon(icon) {
if (!icon.includes("KEY_")) icon = "KEY_" + icon;
this.icon = this.config.icons[icon];
expect(getIconForLatestInput(this.configs, this.latestSource, this.selectedDevice, this.settingName)).toEqual(this.icon);
return this;
}
forTheSource(source) {
this.latestSource = source;
return this;
}
normalizeSettingNameString(input) {
// Convert the input string to lower case
const lowerCasedInput = input.toLowerCase();
// Replace underscores with spaces, capitalize the first letter of each word, and join them back with underscores
const words = lowerCasedInput.split('_').map(word => word.charAt(0).toUpperCase() + word.slice(1));
const result = words.join('_');
return result;
}
weShouldTriggerTheButton(settingName) {
if (!settingName.includes("Button_")) settingName = "Button_" + settingName;
this.settingName = SettingInterface[this.normalizeSettingNameString(settingName)];
expect(getSettingNameWithKeycode(this.config, this.keycode)).toEqual(this.settingName);
return this;
}
}

View File

@ -0,0 +1,131 @@
import {SettingInterface} from "#app/test/cfg_keyboard.example";
import {expect} from "vitest";
import {Button} from "#app/enums/buttons";
import {
deleteBind,
getIconWithKeycode,
getIconWithSettingName,
getKeyWithKeycode,
getKeyWithSettingName,
assign,
getSettingNameWithKeycode, canIAssignThisKey, canIDeleteThisKey, canIOverrideThisSetting
} from "#app/configs/configHandler";
export class MenuManip {
private config;
private settingName;
private keycode;
private icon;
private iconDisplayed;
private specialCaseIcon;
constructor(config) {
this.config = config;
this.settingName = null;
this.icon = null;
this.iconDisplayed = null;
this.specialCaseIcon = null;
}
convertNameToButtonString(input) {
// Check if the input starts with "Alt_Button"
if (input.startsWith("Alt_Button")) {
// Return the last part in uppercase
return input.split('_').pop().toUpperCase();
}
// Split the input string by underscore
const parts = input.split('_');
// Skip the first part and join the rest with an underscore
const result = parts.slice(1).map(part => part.toUpperCase()).join('_');
return result;
}
whenCursorIsOnSetting(settingName) {
if (!settingName.includes("Button_")) settingName = "Button_" + settingName;
this.settingName = SettingInterface[settingName];
const isAlt = settingName.includes("ALT_");
const buttonName = isAlt ? settingName.toUpperCase().split("ALT_BUTTON_").splice(1)[0] : settingName.toUpperCase().split("BUTTON_").splice(1)[0];
expect(this.config.settings[this.settingName]).toEqual(Button[buttonName]);
return this;
}
iconDisplayedIs(icon) {
if (!(icon.toUpperCase().includes("KEY_"))) icon = "KEY_" + icon.toUpperCase();
this.iconDisplayed = this.config.icons[icon];
expect(getIconWithSettingName(this.config, this.settingName)).toEqual(this.iconDisplayed);
return this;
}
thereShouldBeNoIconAnymore() {
const icon = getIconWithSettingName(this.config, this.settingName);
expect(icon === undefined).toEqual(true);
return this;
}
thereShouldBeNoIcon() {
return this.thereShouldBeNoIconAnymore();
}
nothingShouldHappen() {
const settingName = getSettingNameWithKeycode(this.config, this.keycode);
expect(settingName).toEqual(-1);
return this;
}
weWantThisBindInstead(keycode) {
this.keycode = Phaser.Input.Keyboard.KeyCodes[keycode];
const icon = getIconWithKeycode(this.config, this.keycode);
const key = getKeyWithKeycode(this.config, this.keycode);
const _keys = key.toLowerCase().split("_");
const iconIdentifier = _keys[_keys.length-1];
expect(icon.toLowerCase().includes(iconIdentifier)).toEqual(true);
return this;
}
whenWeDelete(settingName?: string) {
this.settingName = SettingInterface[settingName] || this.settingName;
const key = getKeyWithSettingName(this.config, this.settingName);
deleteBind(this.config, this.settingName);
// expect(this.config.custom[key]).toEqual(-1);
return this;
}
whenWeTryToDelete(settingName?: string) {
this.settingName = SettingInterface[settingName] || this.settingName;
deleteBind(this.config, this.settingName);
return this;
}
confirmAssignment() {
assign(this.config, this.settingName, this.keycode);
}
butLetsForceIt() {
this.confirm();
}
confirm() {
assign(this.config, this.settingName, this.keycode);
}
weCantAssignThisKey() {
const key = getKeyWithKeycode(this.config, this.keycode);
expect(canIAssignThisKey(this.config, key)).toEqual(false);
return this;
}
weCantOverrideThisBind() {
expect(canIOverrideThisSetting(this.config, this.settingName)).toEqual(false);
return this;
}
weCantDelete() {
const key = getKeyWithSettingName(this.config, this.settingName);
expect(canIDeleteThisKey(this.config, key)).toEqual(false);
return this;
}
}

View File

@ -0,0 +1,417 @@
import {afterEach, beforeEach, describe, expect, it} from "vitest";
import cfg_keyboard_azerty from "#app/test/cfg_keyboard.example";
import {SettingInterface} from "#app/test/cfg_keyboard.example";
import {Button} from "#app/enums/buttons";
import {deepCopy} from "#app/utils";
import {
getKeyWithKeycode,
getKeyWithSettingName,
} from "#app/configs/configHandler";
import {MenuManip} from "#app/test/helpers/menuManip";
import {InGameManip} from "#app/test/helpers/inGameManip";
import {Device} from "#app/enums/devices";
import {InterfaceConfig} from "#app/inputs-controller";
describe('Test Rebinding', () => {
let config;
let inGame;
let inTheSettingMenu;
const configs: Map<string, InterfaceConfig> = new Map();
const selectedDevice = {
[Device.GAMEPAD]: null,
[Device.KEYBOARD]: 'default',
}
beforeEach(() => {
config = deepCopy(cfg_keyboard_azerty);
config.custom = {...config.default}
configs.default = config;
inGame = new InGameManip(configs, config, selectedDevice);
inTheSettingMenu = new MenuManip(config);
});
it('Check if config is loaded', () => {
expect(config).not.toBeNull();
});
it('Check button for setting name', () => {
const settingName = SettingInterface.Button_Left;
const button = config.settings[settingName];
expect(button).toEqual(Button.LEFT);
});
it('Check key for Keyboard KeyCode', () => {
const key = getKeyWithKeycode(config, Phaser.Input.Keyboard.KeyCodes.LEFT);
const settingName = config.custom[key];
const button = config.settings[settingName];
expect(button).toEqual(Button.LEFT);
});
it('Check key for currenly Assigned to action not alt', () => {
const key = getKeyWithKeycode(config, Phaser.Input.Keyboard.KeyCodes.Q);
const settingName = config.custom[key];
const button = config.settings[settingName];
expect(button).toEqual(Button.LEFT);
});
it('Check key for currenly Assigned to setting name', () => {
const settingName = SettingInterface.Button_Left;
const key = getKeyWithSettingName(config, settingName);
expect(key).toEqual('KEY_ARROW_LEFT');
});
it('Check key for currenly Assigned to setting name alt', () => {
const settingName = SettingInterface.Alt_Button_Left;
const key = getKeyWithSettingName(config, settingName);
expect(key).toEqual('KEY_Q');
});
it('Check key from key code', () => {
const keycode = Phaser.Input.Keyboard.KeyCodes.LEFT;
const key = getKeyWithKeycode(config, keycode);
expect(key).toEqual('KEY_ARROW_LEFT');
});
it('Check icon for currenly Assigned to key code', () => {
const keycode = Phaser.Input.Keyboard.KeyCodes.LEFT;
const key = getKeyWithKeycode(config, keycode);
const icon = config.icons[key];
expect(icon).toEqual('T_Left_Key_Dark.png');
});
it('Check icon for currenly Assigned to key code', () => {
const keycode = Phaser.Input.Keyboard.KeyCodes.Q;
const key = getKeyWithKeycode(config, keycode);
const icon = config.icons[key];
expect(icon).toEqual('T_Q_Key_Dark.png');
});
it('Check icon for currenly Assigned to setting name', () => {
const settingName = SettingInterface.Button_Left;
const key = getKeyWithSettingName(config, settingName);
const icon = config.icons[key];
expect(icon).toEqual('T_Left_Key_Dark.png');
});
it('Check icon for currenly Assigned to setting name alt', () => {
const settingName = SettingInterface.Alt_Button_Left;
const key = getKeyWithSettingName(config, settingName);
const icon = config.icons[key];
expect(icon).toEqual('T_Q_Key_Dark.png');
});
it('Check if is working', () => {
inTheSettingMenu.whenCursorIsOnSetting("Alt_Button_Left").iconDisplayedIs("Q")
inTheSettingMenu.whenCursorIsOnSetting("Alt_Button_Right").iconDisplayedIs("D")
inTheSettingMenu.whenCursorIsOnSetting("Alt_Button_Left").iconDisplayedIs("Q").weWantThisBindInstead("D").confirm();
inGame.whenWePressOnKeyboard("Q").nothingShouldHappen();
inGame.whenWePressOnKeyboard("D").weShouldTriggerTheButton("Alt_Button_Left");
});
it('Check prevent rebind indirectly the d-pad buttons', () => {
inTheSettingMenu.whenCursorIsOnSetting("Alt_Button_Left").iconDisplayedIs("Q")
inTheSettingMenu.whenCursorIsOnSetting("Alt_Button_Right").iconDisplayedIs("D")
inTheSettingMenu.whenCursorIsOnSetting("Alt_Button_Left").iconDisplayedIs("Q").weWantThisBindInstead("LEFT").weCantAssignThisKey().butLetsForceIt();
inGame.whenWePressOnKeyboard("LEFT").weShouldTriggerTheButton("Left");
inGame.whenWePressOnKeyboard("Q").weShouldTriggerTheButton("Alt_Button_Left");
inGame.whenWePressOnKeyboard("D").weShouldTriggerTheButton("Alt_Button_Right");
});
it('Swap alt with a d-pad main', () => {
inGame.whenWePressOnKeyboard("UP").weShouldTriggerTheButton("Button_Up");
inGame.whenWePressOnKeyboard("Z").weShouldTriggerTheButton("Alt_Button_Up");
inTheSettingMenu.whenCursorIsOnSetting("Button_Up").iconDisplayedIs("KEY_ARROW_UP").weWantThisBindInstead("Z").weCantOverrideThisBind().butLetsForceIt();
inGame.whenWePressOnKeyboard("UP").weShouldTriggerTheButton("Button_Up");
inGame.whenWePressOnKeyboard("Z").weShouldTriggerTheButton("Alt_Button_Up");
});
it('Check if double assign d-pad is blocked', () => {
inGame.whenWePressOnKeyboard("RIGHT").weShouldTriggerTheButton("Button_Right");
inGame.whenWePressOnKeyboard("UP").weShouldTriggerTheButton("Button_Up");
inTheSettingMenu.whenCursorIsOnSetting("Button_Left").iconDisplayedIs("KEY_ARROW_LEFT").weWantThisBindInstead("RIGHT").weCantOverrideThisBind().weCantAssignThisKey().butLetsForceIt();
inGame.whenWePressOnKeyboard("LEFT").weShouldTriggerTheButton("Button_Left");
inGame.whenWePressOnKeyboard("RIGHT").weShouldTriggerTheButton("Button_Right");
inGame.whenWePressOnKeyboard("UP").weShouldTriggerTheButton("Button_Up");
inTheSettingMenu.whenCursorIsOnSetting("Button_Left").iconDisplayedIs("KEY_ARROW_LEFT").weWantThisBindInstead("UP").weCantOverrideThisBind().weCantAssignThisKey().butLetsForceIt();
inGame.whenWePressOnKeyboard("LEFT").weShouldTriggerTheButton("Button_Left");
inGame.whenWePressOnKeyboard("RIGHT").weShouldTriggerTheButton("Button_Right");
inGame.whenWePressOnKeyboard("UP").weShouldTriggerTheButton("Button_Up");
inTheSettingMenu.whenCursorIsOnSetting("Button_Left").iconDisplayedIs("KEY_ARROW_LEFT").weWantThisBindInstead("RIGHT").weCantOverrideThisBind().weCantAssignThisKey().butLetsForceIt();
inGame.whenWePressOnKeyboard("LEFT").weShouldTriggerTheButton("Button_Left");
inGame.whenWePressOnKeyboard("RIGHT").weShouldTriggerTheButton("Button_Right");
inGame.whenWePressOnKeyboard("UP").weShouldTriggerTheButton("Button_Up");
});
it('Check if double assign is working', () => {
inGame.whenWePressOnKeyboard("Q").weShouldTriggerTheButton("Alt_Button_Left");
inGame.whenWePressOnKeyboard("D").weShouldTriggerTheButton("Alt_Button_Right");
inGame.whenWePressOnKeyboard("Z").weShouldTriggerTheButton("Alt_Button_Up");
inTheSettingMenu.whenCursorIsOnSetting("Alt_Button_Left").iconDisplayedIs("KEY_Q").weWantThisBindInstead("D").confirm();
inGame.whenWePressOnKeyboard("Q").nothingShouldHappen();
inGame.whenWePressOnKeyboard("D").weShouldTriggerTheButton("Alt_Button_Left");
inGame.whenWePressOnKeyboard("Z").weShouldTriggerTheButton("Alt_Button_Up");
inTheSettingMenu.whenCursorIsOnSetting("Alt_Button_Left").iconDisplayedIs("KEY_D").weWantThisBindInstead("Z").confirm();
inGame.whenWePressOnKeyboard("Q").nothingShouldHappen();
inGame.whenWePressOnKeyboard("D").nothingShouldHappen();
inGame.whenWePressOnKeyboard("Z").weShouldTriggerTheButton("Alt_Button_Left");
inTheSettingMenu.whenCursorIsOnSetting("Alt_Button_Left").iconDisplayedIs("KEY_Z").weWantThisBindInstead("D").confirm();
inGame.whenWePressOnKeyboard("Q").nothingShouldHappen();
inGame.whenWePressOnKeyboard("D").weShouldTriggerTheButton("Alt_Button_Left");
inGame.whenWePressOnKeyboard("Z").nothingShouldHappen();
});
it('Check if triple swap d-pad is prevented', () => {
inTheSettingMenu.whenCursorIsOnSetting("Button_Left").iconDisplayedIs("KEY_ARROW_LEFT").weWantThisBindInstead("RIGHT").weCantOverrideThisBind().weCantAssignThisKey().butLetsForceIt();
inGame.whenWePressOnKeyboard("LEFT").weShouldTriggerTheButton("Button_Left");
inGame.whenWePressOnKeyboard("RIGHT").weShouldTriggerTheButton("Button_Right");
inGame.whenWePressOnKeyboard("UP").weShouldTriggerTheButton("Button_Up");
inTheSettingMenu.whenCursorIsOnSetting("Button_Right").iconDisplayedIs("KEY_ARROW_RIGHT").weWantThisBindInstead("UP").weCantOverrideThisBind().weCantAssignThisKey().butLetsForceIt();
inGame.whenWePressOnKeyboard("LEFT").weShouldTriggerTheButton("Button_Left");
inGame.whenWePressOnKeyboard("RIGHT").weShouldTriggerTheButton("Button_Right");
inGame.whenWePressOnKeyboard("UP").weShouldTriggerTheButton("Button_Up");
inTheSettingMenu.whenCursorIsOnSetting("Button_Left").iconDisplayedIs("KEY_ARROW_LEFT").weWantThisBindInstead("LEFT").weCantOverrideThisBind().weCantAssignThisKey().butLetsForceIt();
inGame.whenWePressOnKeyboard("LEFT").weShouldTriggerTheButton("Button_Left");
inGame.whenWePressOnKeyboard("RIGHT").weShouldTriggerTheButton("Button_Right");
inGame.whenWePressOnKeyboard("UP").weShouldTriggerTheButton("Button_Up");
});
it('Check if triple swap is working', () => {
inGame.whenWePressOnKeyboard("Q").weShouldTriggerTheButton("Alt_Button_Left");
inGame.whenWePressOnKeyboard("D").weShouldTriggerTheButton("Alt_Button_Right");
inGame.whenWePressOnKeyboard("Z").weShouldTriggerTheButton("Alt_Button_Up");
inTheSettingMenu.whenCursorIsOnSetting("Alt_Button_Left").iconDisplayedIs("KEY_Q").weWantThisBindInstead("D").confirm();
inGame.whenWePressOnKeyboard("Q").nothingShouldHappen();
inGame.whenWePressOnKeyboard("D").weShouldTriggerTheButton("Alt_Button_Left");
inGame.whenWePressOnKeyboard("Z").weShouldTriggerTheButton("Alt_Button_Up");
inTheSettingMenu.whenCursorIsOnSetting("Alt_Button_Right").thereShouldBeNoIcon().weWantThisBindInstead("Z").confirm();
inGame.whenWePressOnKeyboard("Q").nothingShouldHappen();
inGame.whenWePressOnKeyboard("D").weShouldTriggerTheButton("Alt_Button_Left");
inGame.whenWePressOnKeyboard("Z").weShouldTriggerTheButton("Alt_Button_Right");
inTheSettingMenu.whenCursorIsOnSetting("Alt_Button_Left").iconDisplayedIs("KEY_D").weWantThisBindInstead("Q").confirm();
inGame.whenWePressOnKeyboard("Q").weShouldTriggerTheButton("Alt_Button_Left");
inGame.whenWePressOnKeyboard("D").nothingShouldHappen();
inGame.whenWePressOnKeyboard("Z").weShouldTriggerTheButton("Alt_Button_Right");
});
it('Swap alt with a main', () => {
inGame.whenWePressOnKeyboard("D").weShouldTriggerTheButton("Alt_Button_Right");
inGame.whenWePressOnKeyboard("R").weShouldTriggerTheButton("Cycle_Shiny");
inTheSettingMenu.whenCursorIsOnSetting("Cycle_Shiny").iconDisplayedIs("KEY_R").weWantThisBindInstead("D").confirm();
inGame.whenWePressOnKeyboard("D").weShouldTriggerTheButton("Cycle_Shiny");
inGame.whenWePressOnKeyboard("R").nothingShouldHappen();
});
it('multiple Swap alt with another main', () => {
inGame.whenWePressOnKeyboard("D").weShouldTriggerTheButton("Alt_Button_Right");
inGame.whenWePressOnKeyboard("R").weShouldTriggerTheButton("Button_Cycle_Shiny");
inGame.whenWePressOnKeyboard("Q").weShouldTriggerTheButton("Alt_Button_Left");
inGame.whenWePressOnKeyboard("F").weShouldTriggerTheButton("Button_Cycle_Form");
inTheSettingMenu.whenCursorIsOnSetting("Button_Cycle_Shiny").iconDisplayedIs("KEY_R").weWantThisBindInstead("D").confirm();
inGame.whenWePressOnKeyboard("D").weShouldTriggerTheButton("Button_Cycle_Shiny");
inGame.whenWePressOnKeyboard("R").nothingShouldHappen();
inGame.whenWePressOnKeyboard("Q").weShouldTriggerTheButton("Alt_Button_Left");
inGame.whenWePressOnKeyboard("F").weShouldTriggerTheButton("Button_Cycle_Form");
inTheSettingMenu.whenCursorIsOnSetting("Button_Cycle_Form").iconDisplayedIs("KEY_F").weWantThisBindInstead("R").confirm();
inGame.whenWePressOnKeyboard("D").weShouldTriggerTheButton("Button_Cycle_Shiny");
inGame.whenWePressOnKeyboard("R").weShouldTriggerTheButton("Button_Cycle_Form");
inGame.whenWePressOnKeyboard("Q").weShouldTriggerTheButton("Alt_Button_Left");
inGame.whenWePressOnKeyboard("F").nothingShouldHappen();
});
it('Swap alt with a key not binded yet', () => {
inGame.whenWePressOnKeyboard("Z").weShouldTriggerTheButton("Alt_Button_Up");
inGame.whenWePressOnKeyboard("B").nothingShouldHappen();
inTheSettingMenu.whenCursorIsOnSetting("Alt_Button_Up").iconDisplayedIs("KEY_Z").weWantThisBindInstead("B").confirm();
inGame.whenWePressOnKeyboard("Z").nothingShouldHappen();
inGame.whenWePressOnKeyboard("B").weShouldTriggerTheButton("Alt_Button_Up");
});
it('Delete blacklisted bind', () => {
inGame.whenWePressOnKeyboard("LEFT").weShouldTriggerTheButton("Button_Left");
inTheSettingMenu.whenWeDelete("Button_Left").weCantDelete().iconDisplayedIs("KEY_ARROW_LEFT");
inGame.whenWePressOnKeyboard("LEFT").weShouldTriggerTheButton("Button_Left");
});
it('Delete bind', () => {
inGame.whenWePressOnKeyboard("Q").weShouldTriggerTheButton("Alt_Button_Left");
inTheSettingMenu.whenWeDelete("Alt_Button_Left").thereShouldBeNoIconAnymore();
inGame.whenWePressOnKeyboard("Q").nothingShouldHappen();
});
it('Delete bind then assign a not yet binded button', () => {
inTheSettingMenu.whenWeDelete("Alt_Button_Left").thereShouldBeNoIconAnymore();
inGame.whenWePressOnKeyboard("Q").nothingShouldHappen();
inGame.whenWePressOnKeyboard("B").nothingShouldHappen();
inTheSettingMenu.whenCursorIsOnSetting("Alt_Button_Left").thereShouldBeNoIcon().weWantThisBindInstead("B").confirm();
inGame.whenWePressOnKeyboard("Q").nothingShouldHappen();
inGame.whenWePressOnKeyboard("B").weShouldTriggerTheButton("Alt_Button_Left");
})
it('swap 2 bind, than delete 1 bind than assign another bind', () => {
inGame.whenWePressOnKeyboard("R").weShouldTriggerTheButton("Button_Cycle_Shiny");
inGame.whenWePressOnKeyboard("F").weShouldTriggerTheButton("Button_Cycle_Form");
inGame.whenWePressOnKeyboard("Z").weShouldTriggerTheButton("Alt_Button_Up");
inGame.whenWePressOnKeyboard("D").weShouldTriggerTheButton("Alt_Button_Right");
inTheSettingMenu.whenCursorIsOnSetting("Button_Cycle_Shiny").iconDisplayedIs("KEY_R").weWantThisBindInstead("D").confirm();
inGame.whenWePressOnKeyboard("R").nothingShouldHappen();
inGame.whenWePressOnKeyboard("F").weShouldTriggerTheButton("Button_Cycle_Form");
inGame.whenWePressOnKeyboard("Z").weShouldTriggerTheButton("Alt_Button_Up");
inGame.whenWePressOnKeyboard("D").weShouldTriggerTheButton("Button_Cycle_Shiny");
inTheSettingMenu.whenCursorIsOnSetting("Button_Cycle_Form").iconDisplayedIs("KEY_F").weWantThisBindInstead("Z").confirm();
inGame.whenWePressOnKeyboard("R").nothingShouldHappen();
inGame.whenWePressOnKeyboard("F").nothingShouldHappen();
inGame.whenWePressOnKeyboard("Z").weShouldTriggerTheButton("Button_Cycle_Form");
inGame.whenWePressOnKeyboard("D").weShouldTriggerTheButton("Button_Cycle_Shiny");
inGame.whenWePressOnKeyboard("Q").weShouldTriggerTheButton("Alt_Button_Left");
inTheSettingMenu.whenWeDelete("Alt_Button_Left").thereShouldBeNoIconAnymore();
inGame.whenWePressOnKeyboard("R").nothingShouldHappen();
inGame.whenWePressOnKeyboard("F").nothingShouldHappen();
inGame.whenWePressOnKeyboard("Z").weShouldTriggerTheButton("Button_Cycle_Form");
inGame.whenWePressOnKeyboard("D").weShouldTriggerTheButton("Button_Cycle_Shiny");
inGame.whenWePressOnKeyboard("S").weShouldTriggerTheButton("Alt_Button_Down");
inGame.whenWePressOnKeyboard("Q").nothingShouldHappen();
inGame.whenWePressOnKeyboard("B").nothingShouldHappen();
inTheSettingMenu.whenCursorIsOnSetting("Alt_Button_Down").iconDisplayedIs("KEY_S").weWantThisBindInstead("B").confirm();
inGame.whenWePressOnKeyboard("R").nothingShouldHappen();
inGame.whenWePressOnKeyboard("F").nothingShouldHappen();
inGame.whenWePressOnKeyboard("Z").weShouldTriggerTheButton("Button_Cycle_Form");
inGame.whenWePressOnKeyboard("D").weShouldTriggerTheButton("Button_Cycle_Shiny");
inGame.whenWePressOnKeyboard("S").nothingShouldHappen();
inGame.whenWePressOnKeyboard("Q").nothingShouldHappen();
inGame.whenWePressOnKeyboard("B").weShouldTriggerTheButton("Alt_Button_Down");
});
it('Delete bind then assign not already existing button', () => {
inGame.whenWePressOnKeyboard("Q").weShouldTriggerTheButton("Alt_Button_Left");
inGame.whenWePressOnKeyboard("B").nothingShouldHappen();
inTheSettingMenu.whenWeDelete("Alt_Button_Left").thereShouldBeNoIconAnymore();
inGame.whenWePressOnKeyboard("Q").nothingShouldHappen();
inGame.whenWePressOnKeyboard("B").nothingShouldHappen();
inTheSettingMenu.whenCursorIsOnSetting("Alt_Button_Left").thereShouldBeNoIcon().weWantThisBindInstead("B").confirm();
inGame.whenWePressOnKeyboard("Q").nothingShouldHappen();
inGame.whenWePressOnKeyboard("B").weShouldTriggerTheButton("Alt_Button_Left");
});
it('change alt bind to not already existing button, than another one alt bind with another not already existing button', () => {
inGame.whenWePressOnKeyboard("Q").weShouldTriggerTheButton("Alt_Button_Left");
inGame.whenWePressOnKeyboard("D").weShouldTriggerTheButton("Alt_Button_Right");
inGame.whenWePressOnKeyboard("B").nothingShouldHappen();
inGame.whenWePressOnKeyboard("U").nothingShouldHappen();
inTheSettingMenu.whenCursorIsOnSetting("Alt_Button_Left").iconDisplayedIs("KEY_Q").weWantThisBindInstead("B").confirm();
inGame.whenWePressOnKeyboard("Q").nothingShouldHappen();
inGame.whenWePressOnKeyboard("D").weShouldTriggerTheButton("Alt_Button_Right");
inGame.whenWePressOnKeyboard("B").weShouldTriggerTheButton("Alt_Button_Left");
inGame.whenWePressOnKeyboard("U").nothingShouldHappen();
inTheSettingMenu.whenCursorIsOnSetting("Alt_Button_Right").iconDisplayedIs("KEY_D").weWantThisBindInstead("U").confirm();
inGame.whenWePressOnKeyboard("Q").nothingShouldHappen();
inGame.whenWePressOnKeyboard("D").nothingShouldHappen();
inGame.whenWePressOnKeyboard("B").weShouldTriggerTheButton("Alt_Button_Left");
inGame.whenWePressOnKeyboard("U").weShouldTriggerTheButton("Alt_Button_Right");
});
it('Swap multiple touch alt and main', () => {
inGame.whenWePressOnKeyboard("UP").weShouldTriggerTheButton("Button_Up");
inGame.whenWePressOnKeyboard("RIGHT").weShouldTriggerTheButton("Button_Right");
inGame.whenWePressOnKeyboard("Z").weShouldTriggerTheButton("Alt_Button_Up");
inGame.whenWePressOnKeyboard("D").weShouldTriggerTheButton("Alt_Button_Right");
inTheSettingMenu.whenCursorIsOnSetting("Button_Up").iconDisplayedIs("KEY_ARROW_UP").weWantThisBindInstead("RIGHT").weCantOverrideThisBind().weCantAssignThisKey().butLetsForceIt();
inGame.whenWePressOnKeyboard("UP").weShouldTriggerTheButton("Button_Up");
inGame.whenWePressOnKeyboard("RIGHT").weShouldTriggerTheButton("Button_Right");
inGame.whenWePressOnKeyboard("Z").weShouldTriggerTheButton("Alt_Button_Up");
inGame.whenWePressOnKeyboard("D").weShouldTriggerTheButton("Alt_Button_Right");
inTheSettingMenu.whenCursorIsOnSetting("Alt_Button_Up").iconDisplayedIs("KEY_Z").weWantThisBindInstead("D").confirm();
inGame.whenWePressOnKeyboard("UP").weShouldTriggerTheButton("Button_Up");
inGame.whenWePressOnKeyboard("RIGHT").weShouldTriggerTheButton("Button_Right");
inGame.whenWePressOnKeyboard("Z").nothingShouldHappen();
inGame.whenWePressOnKeyboard("D").weShouldTriggerTheButton("Alt_Button_Up");
inTheSettingMenu.whenCursorIsOnSetting("Alt_Button_Up").iconDisplayedIs("KEY_D").weWantThisBindInstead("Z").confirm();
inGame.whenWePressOnKeyboard("UP").weShouldTriggerTheButton("Button_Up");
inGame.whenWePressOnKeyboard("RIGHT").weShouldTriggerTheButton("Button_Right");
inGame.whenWePressOnKeyboard("Z").weShouldTriggerTheButton("Alt_Button_Up");
inGame.whenWePressOnKeyboard("D").nothingShouldHappen();
});
it('Delete 2 bind then reassign one of them', () => {
inGame.whenWePressOnKeyboard("Q").weShouldTriggerTheButton("Alt_Button_Left");
inGame.whenWePressOnKeyboard("D").weShouldTriggerTheButton("Alt_Button_Right");
inTheSettingMenu.whenWeDelete("Alt_Button_Left").thereShouldBeNoIconAnymore();
inGame.whenWePressOnKeyboard("Q").nothingShouldHappen();
inGame.whenWePressOnKeyboard("D").weShouldTriggerTheButton("Alt_Button_Right");
inTheSettingMenu.whenWeDelete("Alt_Button_Right").thereShouldBeNoIconAnymore();
inGame.whenWePressOnKeyboard("Q").nothingShouldHappen();
inGame.whenWePressOnKeyboard("D").nothingShouldHappen();
inTheSettingMenu.whenCursorIsOnSetting("Alt_Button_Left").thereShouldBeNoIcon().weWantThisBindInstead("Q").confirm();
inGame.whenWePressOnKeyboard("Q").weShouldTriggerTheButton("Alt_Button_Left");
inGame.whenWePressOnKeyboard("D").nothingShouldHappen();
});
it("test keyboard listener", () => {
const keyDown = Phaser.Input.Keyboard.KeyCodes.S;
const key = getKeyWithKeycode(config, keyDown);
const settingName = config.custom[key];
const buttonDown = config.settings[settingName];
expect(buttonDown).toEqual(Button.DOWN);
});
it("retrieve the correct icon for a given source", () => {
inTheSettingMenu.whenCursorIsOnSetting("Cycle_Shiny").iconDisplayedIs("KEY_R");
inTheSettingMenu.whenCursorIsOnSetting("Cycle_Form").iconDisplayedIs("KEY_F");
inGame.forTheSource("keyboard").forTheWantedBind("Cycle_Shiny").weShouldSeeTheIcon("R")
inGame.forTheSource("keyboard").forTheWantedBind("Cycle_Form").weShouldSeeTheIcon("F")
});
it("check the key displayed on confirm", () => {
inGame.whenWePressOnKeyboard("ENTER").weShouldTriggerTheButton("Button_Submit");
inGame.whenWePressOnKeyboard("UP").weShouldTriggerTheButton("Button_Up");
inGame.whenWePressOnKeyboard("DOWN").weShouldTriggerTheButton("Button_Down");
inGame.whenWePressOnKeyboard("LEFT").weShouldTriggerTheButton("Button_Left");
inGame.whenWePressOnKeyboard("RIGHT").weShouldTriggerTheButton("Button_Right");
inGame.whenWePressOnKeyboard("ESC").weShouldTriggerTheButton("Button_Menu");
inGame.whenWePressOnKeyboard("HOME").nothingShouldHappen();
inGame.whenWePressOnKeyboard("DELETE").nothingShouldHappen();
inTheSettingMenu.whenCursorIsOnSetting("Button_Submit").iconDisplayedIs("KEY_ENTER").whenWeDelete().iconDisplayedIs("KEY_ENTER")
inTheSettingMenu.whenCursorIsOnSetting("Button_Up").iconDisplayedIs("KEY_ARROW_UP").whenWeDelete().iconDisplayedIs("KEY_ARROW_UP")
inTheSettingMenu.whenCursorIsOnSetting("Button_Down").iconDisplayedIs("KEY_ARROW_DOWN").whenWeDelete().iconDisplayedIs("KEY_ARROW_DOWN")
inTheSettingMenu.whenCursorIsOnSetting("Button_Left").iconDisplayedIs("KEY_ARROW_LEFT").whenWeDelete().iconDisplayedIs("KEY_ARROW_LEFT")
inTheSettingMenu.whenCursorIsOnSetting("Button_Right").iconDisplayedIs("KEY_ARROW_RIGHT").whenWeDelete().iconDisplayedIs("KEY_ARROW_RIGHT")
inTheSettingMenu.whenCursorIsOnSetting("Button_Menu").iconDisplayedIs("KEY_ESC").whenWeDelete().iconDisplayedIs("KEY_ESC")
inTheSettingMenu.whenCursorIsOnSetting("Alt_Button_Up").iconDisplayedIs("KEY_Z").whenWeDelete().thereShouldBeNoIconAnymore();
inTheSettingMenu.whenCursorIsOnSetting("Alt_Button_Up").thereShouldBeNoIcon().weWantThisBindInstead("DELETE").weCantAssignThisKey().butLetsForceIt();
inTheSettingMenu.whenCursorIsOnSetting("Alt_Button_Up").thereShouldBeNoIcon().weWantThisBindInstead("HOME").weCantAssignThisKey().butLetsForceIt();
inGame.whenWePressOnKeyboard("DELETE").nothingShouldHappen();
inGame.whenWePressOnKeyboard("HOME").nothingShouldHappen();
inGame.whenWePressOnKeyboard("Z").nothingShouldHappen();
});
it("check to delete all the binds of an action", () => {
inGame.whenWePressOnKeyboard("V").weShouldTriggerTheButton("Button_Cycle_Variant");
inGame.whenWePressOnKeyboard("K").weShouldTriggerTheButton("Alt_Button_Cycle_Variant");
inTheSettingMenu.whenCursorIsOnSetting("Alt_Button_Cycle_Variant").iconDisplayedIs("KEY_K").whenWeDelete().thereShouldBeNoIconAnymore();
inTheSettingMenu.whenCursorIsOnSetting("Button_Cycle_Variant").iconDisplayedIs("KEY_V").whenWeDelete().iconDisplayedIs("KEY_V")
});
});

View File

@ -1,21 +1,43 @@
import {Button} from "./enums/buttons";
// Create a map to store key bindings
export const keys = new Map();
// Create a map to store keys that are currently pressed
export const keysDown = new Map();
// Variable to store the ID of the last touched element
let lastTouchedId;
export function initTouchControls(buttonMap) {
/**
* Initialize touch controls by binding keys to buttons.
*
* @param events - The event emitter for handling input events.
*/
export function initTouchControls(events) {
// Select all elements with the 'data-key' attribute and bind keys to them
for (const button of document.querySelectorAll('[data-key]')) {
// @ts-ignore
bindKey(button, button.dataset.key, buttonMap);
// @ts-ignore - Bind the key to the button using the dataset key
bindKey(button, button.dataset.key, events);
}
}
/**
* Check if the device has a touchscreen.
*
* @returns `true` if the device has a touchscreen, otherwise `false`.
*/
export function hasTouchscreen() {
return window.matchMedia('(hover: none), (pointer: coarse)').matches;
}
/**
* Check if the device is a mobile device.
*
* @returns `true` if the device is a mobile device, otherwise `false`.
*/
export function isMobile() {
let ret = false;
(function (a) {
// Check the user agent string against a regex for mobile devices
if (/(android|bb\d+|meego).+mobile|avantgo|bada\/|blackberry|blazer|compal|elaine|fennec|hiptop|iemobile|ip(hone|od)|iris|kindle|lge |maemo|midp|mmp|mobile.+firefox|netfront|opera m(ob|in)i|palm( os)?|phone|p(ixi|re)\/|plucker|pocket|psp|series(4|6)0|symbian|treo|up\.(browser|link)|vodafone|wap|windows ce|xda|xiino|android|ipad|playbook|silk/i.test(a)||/1207|6310|6590|3gso|4thp|50[1-6]i|770s|802s|a wa|abac|ac(er|oo|s\-)|ai(ko|rn)|al(av|ca|co)|amoi|an(ex|ny|yw)|aptu|ar(ch|go)|as(te|us)|attw|au(di|\-m|r |s )|avan|be(ck|ll|nq)|bi(lb|rd)|bl(ac|az)|br(e|v)w|bumb|bw\-(n|u)|c55\/|capi|ccwa|cdm\-|cell|chtm|cldc|cmd\-|co(mp|nd)|craw|da(it|ll|ng)|dbte|dc\-s|devi|dica|dmob|do(c|p)o|ds(12|\-d)|el(49|ai)|em(l2|ul)|er(ic|k0)|esl8|ez([4-7]0|os|wa|ze)|fetc|fly(\-|_)|g1 u|g560|gene|gf\-5|g\-mo|go(\.w|od)|gr(ad|un)|haie|hcit|hd\-(m|p|t)|hei\-|hi(pt|ta)|hp( i|ip)|hs\-c|ht(c(\-| |_|a|g|p|s|t)|tp)|hu(aw|tc)|i\-(20|go|ma)|i230|iac( |\-|\/)|ibro|idea|ig01|ikom|im1k|inno|ipaq|iris|ja(t|v)a|jbro|jemu|jigs|kddi|keji|kgt( |\/)|klon|kpt |kwc\-|kyo(c|k)|le(no|xi)|lg( g|\/(k|l|u)|50|54|\-[a-w])|libw|lynx|m1\-w|m3ga|m50\/|ma(te|ui|xo)|mc(01|21|ca)|m\-cr|me(rc|ri)|mi(o8|oa|ts)|mmef|mo(01|02|bi|de|do|t(\-| |o|v)|zz)|mt(50|p1|v )|mwbp|mywa|n10[0-2]|n20[2-3]|n30(0|2)|n50(0|2|5)|n7(0(0|1)|10)|ne((c|m)\-|on|tf|wf|wg|wt)|nok(6|i)|nzph|o2im|op(ti|wv)|oran|owg1|p800|pan(a|d|t)|pdxg|pg(13|\-([1-8]|c))|phil|pire|pl(ay|uc)|pn\-2|po(ck|rt|se)|prox|psio|pt\-g|qa\-a|qc(07|12|21|32|60|\-[2-7]|i\-)|qtek|r380|r600|raks|rim9|ro(ve|zo)|s55\/|sa(ge|ma|mm|ms|ny|va)|sc(01|h\-|oo|p\-)|sdk\/|se(c(\-|0|1)|47|mc|nd|ri)|sgh\-|shar|sie(\-|m)|sk\-0|sl(45|id)|sm(al|ar|b3|it|t5)|so(ft|ny)|sp(01|h\-|v\-|v )|sy(01|mb)|t2(18|50)|t6(00|10|18)|ta(gt|lk)|tcl\-|tdg\-|tel(i|m)|tim\-|t\-mo|to(pl|sh)|ts(70|m\-|m3|m5)|tx\-9|up(\.b|g1|si)|utst|v400|v750|veri|vi(rg|te)|vk(40|5[0-3]|\-v)|vm40|voda|vulc|vx(52|53|60|61|70|80|81|83|85|98)|w3c(\-| )|webc|whit|wi(g |nc|nw)|wmlb|wonu|x700|yas\-|your|zeto|zte\-/i.test(a.substr(0, 4)))
ret = true;
})(navigator.userAgent || navigator.vendor || window['opera']);
@ -23,51 +45,55 @@ export function isMobile() {
}
/**
* Simulate a keyboard event on the canvas
* Simulates a keyboard event on the canvas.
*
* @param {string} eventType Type of the keyboard event
* @param {string} button Button to simulate
* @param {object} buttonMap Map of buttons to key objects
* @param eventType - The type of the keyboard event ('keydown' or 'keyup').
* @param key - The key to simulate.
* @param events - The event emitter for handling input events.
*
* @remarks
* This function checks if the key exists in the Button enum. If it does, it retrieves the corresponding button
* and emits the appropriate event ('input_down' or 'input_up') based on the event type.
*/
function simulateKeyboardEvent(eventType, button, buttonMap) {
const key = buttonMap[button];
function simulateKeyboardEvent(eventType, key, events) {
if (!Button.hasOwnProperty(key)) return;
const button = Button[key];
switch (eventType) {
case 'keydown':
key.onDown({});
events.emit('input_down', {
controller_type: 'keyboard',
button: button,
});
break;
case 'keyup':
key.onUp({});
events.emit('input_up', {
controller_type: 'keyboard',
button: button,
});
break;
}
}
/**
* Simulate a keyboard input from 'keydown' to 'keyup'
* Binds a node to a specific key to simulate keyboard events on touch.
*
* @param {string} key Key to simulate
* @param {object} buttonMap Map of buttons to key objects
*/
function simulateKeyboardInput(key, buttonMap) {
simulateKeyboardEvent('keydown', key, buttonMap);
window.setTimeout(() => {
simulateKeyboardEvent('keyup', key, buttonMap);
}, 100);
}
/**
* Bind a node by a specific key to simulate on touch
* @param node - The DOM element to bind the key to.
* @param key - The key to simulate.
* @param events - The event emitter for handling input events.
*
* @param {*} node The node to bind a key to
* @param {string} key Key to simulate
* @param {object} buttonMap Map of buttons to key objects
* @remarks
* This function binds touch events to a node to simulate 'keydown' and 'keyup' keyboard events.
* It adds the key to the keys map and tracks the keydown state. When a touch starts, it simulates
* a 'keydown' event and adds an 'active' class to the node. When the touch ends, it simulates a 'keyup'
* event, removes the keydown state, and removes the 'active' class from the node and the last touched element.
*/
function bindKey(node, key, buttonMap) {
function bindKey(node, key, events) {
keys.set(node.id, key);
node.addEventListener('touchstart', event => {
event.preventDefault();
simulateKeyboardEvent('keydown', key, buttonMap);
simulateKeyboardEvent('keydown', key, events);
keysDown.set(event.target.id, node.id);
node.classList.add('active');
});
@ -78,7 +104,7 @@ function bindKey(node, key, buttonMap) {
const pressedKey = keysDown.get(event.target.id);
if (pressedKey && keys.has(pressedKey)) {
const key = keys.get(pressedKey);
simulateKeyboardEvent('keyup', key, buttonMap);
simulateKeyboardEvent('keyup', key, events);
}
keysDown.delete(event.target.id);
@ -88,28 +114,4 @@ function bindKey(node, key, buttonMap) {
document.getElementById(lastTouchedId).classList.remove('active');
}
});
// Inspired by https://github.com/pulsejet/mkxp-web/blob/262a2254b684567311c9f0e135ee29f6e8c3613e/extra/js/dpad.js
node.addEventListener('touchmove', event => {
const { target, clientX, clientY } = event.changedTouches[0];
const origTargetId = keysDown.get(target.id);
const nextTargetId = document.elementFromPoint(clientX, clientY).id;
if (origTargetId === nextTargetId)
return;
if (origTargetId) {
const key = keys.get(origTargetId);
simulateKeyboardEvent('keyup', key, buttonMap);
keysDown.delete(target.id);
document.getElementById(origTargetId).classList.remove('active');
}
if (keys.has(nextTargetId)) {
const key = keys.get(nextTargetId);
simulateKeyboardEvent('keydown', key, buttonMap);
keysDown.set(target.id, nextTargetId);
lastTouchedId = nextTargetId;
document.getElementById(nextTargetId).classList.add('active');
}
});
}

View File

@ -4,8 +4,10 @@ import {InputsController} from "./inputs-controller";
import MessageUiHandler from "./ui/message-ui-handler";
import StarterSelectUiHandler from "./ui/starter-select-ui-handler";
import {Setting, settingOptions} from "./system/settings";
import SettingsUiHandler from "./ui/settings-ui-handler";
import SettingsUiHandler from "./ui/settings/settings-ui-handler";
import {Button} from "./enums/buttons";
import SettingsGamepadUiHandler from "./ui/settings/settings-gamepad-ui-handler";
import SettingsKeyboardUiHandler from "#app/ui/settings/settings-keyboard-ui-handler";
export interface ActionKeys {
[key in Button]: () => void;
@ -130,7 +132,9 @@ export class UiInputs {
}
buttonCycleOption(button: Button): void {
if (this.scene.ui?.getHandler() instanceof StarterSelectUiHandler) {
const whitelist = [StarterSelectUiHandler, SettingsUiHandler, SettingsGamepadUiHandler, SettingsKeyboardUiHandler];
const uiHandler = this.scene.ui?.getHandler();
if (whitelist.some(handler => uiHandler instanceof handler)) {
this.scene.ui.processInput(button);
}
}

View File

@ -0,0 +1,255 @@
import UiHandler from "../ui-handler";
import BattleScene from "../../battle-scene";
import {Mode} from "../ui";
import {addWindow} from "../ui-theme";
import {addTextObject, TextStyle} from "../text";
import {Button} from "../../enums/buttons";
import {SettingKeyboard} from "#app/system/settings-keyboard";
/**
* Abstract class for handling UI elements related to button bindings.
*/
export default abstract class AbstractBindingUiHandler extends UiHandler {
// Containers for different segments of the UI.
protected optionSelectContainer: Phaser.GameObjects.Container;
protected actionsContainer: Phaser.GameObjects.Container;
// Background elements for titles and action areas.
protected titleBg: Phaser.GameObjects.NineSlice;
protected actionBg: Phaser.GameObjects.NineSlice;
protected optionSelectBg: Phaser.GameObjects.NineSlice;
// Text elements for displaying instructions and actions.
protected unlockText: Phaser.GameObjects.Text;
protected timerText: Phaser.GameObjects.Text;
protected swapText: Phaser.GameObjects.Text;
protected actionLabel: Phaser.GameObjects.Text;
protected cancelLabel: Phaser.GameObjects.Text;
protected listening: boolean = false;
protected buttonPressed: number | null = null;
// Icons for displaying current and new button assignments.
protected newButtonIcon: Phaser.GameObjects.Sprite;
protected targetButtonIcon: Phaser.GameObjects.Sprite;
// Function to call on cancel or completion of binding.
protected cancelFn: (boolean?) => boolean;
protected swapAction: () => boolean;
protected confirmText: string;
protected timeLeftAutoClose: number = 5;
protected countdownTimer;
// The specific setting being modified.
protected target;
/**
* Constructor for the AbstractBindingUiHandler.
*
* @param scene - The BattleScene instance.
* @param mode - The UI mode.
*/
constructor(scene: BattleScene, mode: Mode) {
super(scene, mode);
}
/**
* Setup UI elements.
*/
setup() {
const ui = this.getUi();
this.optionSelectContainer = this.scene.add.container(0, 0);
this.actionsContainer = this.scene.add.container(0, 0);
// Initially, containers are not visible.
this.optionSelectContainer.setVisible(false);
this.actionsContainer.setVisible(false);
// Add containers to the UI.
ui.add(this.optionSelectContainer);
ui.add(this.actionsContainer);
// Setup backgrounds and text objects for UI.
this.titleBg = addWindow(this.scene, (this.scene.game.canvas.width / 6) - this.getWindowWidth(), -(this.scene.game.canvas.height / 6) + 28 + 21, this.getWindowWidth(), 24);
this.titleBg.setOrigin(0.5);
this.optionSelectContainer.add(this.titleBg);
this.actionBg = addWindow(this.scene, (this.scene.game.canvas.width / 6) - this.getWindowWidth(), -(this.scene.game.canvas.height / 6) + this.getWindowHeight() + 28 + 21 + 21, this.getWindowWidth(), 24);
this.actionBg.setOrigin(0.5);
this.actionsContainer.add(this.actionBg);
// Text prompts and instructions for the user.
this.unlockText = addTextObject(this.scene, 0, 0, 'Press a button...', TextStyle.WINDOW);
this.unlockText.setOrigin(0, 0);
this.unlockText.setPositionRelative(this.titleBg, 36, 4);
this.optionSelectContainer.add(this.unlockText);
this.timerText = addTextObject(this.scene, 0, 0, '(5)', TextStyle.WINDOW);
this.timerText.setOrigin(0, 0);
this.timerText.setPositionRelative(this.unlockText, (this.unlockText.width/6) + 5, 0);
this.optionSelectContainer.add(this.timerText);
this.optionSelectBg = addWindow(this.scene, (this.scene.game.canvas.width / 6) - this.getWindowWidth(), -(this.scene.game.canvas.height / 6) + this.getWindowHeight() + 28, this.getWindowWidth(), this.getWindowHeight());
this.optionSelectBg.setOrigin(0.5);
this.optionSelectContainer.add(this.optionSelectBg);
this.cancelLabel = addTextObject(this.scene, 0, 0, 'Cancel', TextStyle.SETTINGS_LABEL);
this.cancelLabel.setOrigin(0, 0.5);
this.cancelLabel.setPositionRelative(this.actionBg, 10, this.actionBg.height / 2);
this.actionsContainer.add(this.cancelLabel);
}
manageAutoCloseTimer(){
clearTimeout(this.countdownTimer);
this.countdownTimer = setTimeout(() => {
this.timeLeftAutoClose -= 1;
this.timerText.setText(`(${this.timeLeftAutoClose})`);
if (this.timeLeftAutoClose >= 0)
this.manageAutoCloseTimer();
else
this.cancelFn();
}, 1000);
}
/**
* Show the UI with the provided arguments.
*
* @param args - Arguments to be passed to the show method.
* @returns `true` if successful.
*/
show(args: any[]): boolean {
super.show(args);
this.buttonPressed = null;
this.timeLeftAutoClose = 5;
this.cancelFn = args[0].cancelHandler;
this.target = args[0].target;
// Bring the option and action containers to the front of the UI.
this.getUi().bringToTop(this.optionSelectContainer);
this.getUi().bringToTop(this.actionsContainer);
this.optionSelectContainer.setVisible(true);
setTimeout(() => {
this.listening = true;
this.manageAutoCloseTimer();
}, 100);
return true;
}
/**
* Get the width of the window.
*
* @returns The window width.
*/
getWindowWidth(): number {
return 160;
}
/**
* Get the height of the window.
*
* @returns The window height.
*/
getWindowHeight(): number {
return 64;
}
/**
* Process the input for the given button.
*
* @param button - The button to process.
* @returns `true` if the input was processed successfully.
*/
processInput(button: Button): boolean {
if (this.buttonPressed === null) return;
const ui = this.getUi();
let success = false;
switch (button) {
case Button.LEFT:
case Button.RIGHT:
// Toggle between action and cancel options.
const cursor = this.cursor ? 0 : 1;
success = this.setCursor(cursor);
break
case Button.ACTION:
// Process actions based on current cursor position.
if (this.cursor === 0) {
this.cancelFn();
} else {
success = this.swapAction();
this.cancelFn(success);
}
break;
}
// Plays a select sound effect if an action was successfully processed.
if (success)
ui.playSelect();
else
ui.playError();
return success;
}
/**
* Set the cursor to the specified position.
*
* @param cursor - The cursor position to set.
* @returns `true` if the cursor was set successfully.
*/
setCursor(cursor: integer): boolean {
this.cursor = cursor;
if (cursor === 1) {
this.actionLabel.setColor(this.getTextColor(TextStyle.SETTINGS_SELECTED));
this.actionLabel.setShadowColor(this.getTextColor(TextStyle.SETTINGS_SELECTED, true));
this.cancelLabel.setColor(this.getTextColor(TextStyle.WINDOW));
this.cancelLabel.setShadowColor(this.getTextColor(TextStyle.WINDOW, true));
return true;
}
this.actionLabel.setColor(this.getTextColor(TextStyle.WINDOW));
this.actionLabel.setShadowColor(this.getTextColor(TextStyle.WINDOW, true));
this.cancelLabel.setColor(this.getTextColor(TextStyle.SETTINGS_SELECTED));
this.cancelLabel.setShadowColor(this.getTextColor(TextStyle.SETTINGS_SELECTED, true));
return true;
}
/**
* Clear the UI elements and state.
*/
clear() {
super.clear();
clearTimeout(this.countdownTimer);
this.timerText.setText('(5)');
this.timeLeftAutoClose = 5;
this.listening = false;
this.target = null;
this.cancelFn = null;
this.optionSelectContainer.setVisible(false);
this.actionsContainer.setVisible(false);
this.newButtonIcon.setVisible(false);
this.buttonPressed = null;
}
/**
* Handle input down events.
*
* @param buttonIcon - The icon of the button that was pressed.
* @param assignedButtonIcon - The icon of the button that is assigned.
* @param type - The type of button press.
*/
onInputDown(buttonIcon: string, assignedButtonIcon: string, type: string): void {
clearTimeout(this.countdownTimer);
this.timerText.setText("");
this.newButtonIcon.setTexture(type);
this.newButtonIcon.setFrame(buttonIcon);
if (assignedButtonIcon) {
this.targetButtonIcon.setTexture(type);
this.targetButtonIcon.setFrame(assignedButtonIcon);
this.targetButtonIcon.setVisible(true);
this.swapText.setVisible(true);
}
this.newButtonIcon.setVisible(true);
this.setCursor(0);
this.actionsContainer.setVisible(true);
}
}

View File

@ -0,0 +1,654 @@
import UiHandler from "../ui-handler";
import BattleScene from "../../battle-scene";
import {Mode} from "../ui";
import {InterfaceConfig} from "../../inputs-controller";
import {addWindow} from "../ui-theme";
import {addTextObject, TextStyle} from "../text";
import {Button} from "../../enums/buttons";
import {getIconWithSettingName, getKeyWithSettingName} from "#app/configs/configHandler";
import {setSettingKeyboard, SettingKeyboard} from "#app/system/settings-keyboard";
export interface InputsIcons {
[key: string]: Phaser.GameObjects.Sprite;
}
export interface LayoutConfig {
optionsContainer: Phaser.GameObjects.Container;
inputsIcons: InputsIcons;
settingLabels: Phaser.GameObjects.Text[];
optionValueLabels: Phaser.GameObjects.Text[][];
optionCursors: integer[];
keys: string[];
bindingSettings: Array<String>;
}
/**
* Abstract class for handling UI elements related to settings.
*/
export default abstract class AbstractSettingsUiUiHandler extends UiHandler {
protected settingsContainer: Phaser.GameObjects.Container;
protected optionsContainer: Phaser.GameObjects.Container;
protected scrollCursor: integer;
protected optionCursors: integer[];
protected cursorObj: Phaser.GameObjects.NineSlice;
protected headerBg: Phaser.GameObjects.NineSlice;
protected optionsBg: Phaser.GameObjects.NineSlice;
protected actionsBg: Phaser.GameObjects.NineSlice;
protected settingLabels: Phaser.GameObjects.Text[];
protected optionValueLabels: Phaser.GameObjects.Text[][];
// layout will contain the 3 Gamepad tab for each config - dualshock, xbox, snes
protected layout: Map<string, LayoutConfig> = new Map<string, LayoutConfig>();
// Will contain the input icons from the selected layout
protected inputsIcons: InputsIcons;
protected navigationIcons: InputsIcons;
// list all the setting keys used in the selected layout (because dualshock has more buttons than xbox)
protected keys: Array<String>;
// Store the specific settings related to key bindings for the current gamepad configuration.
protected bindingSettings: Array<String>;
protected settingDevice;
protected settingBlacklisted;
protected settingDeviceDefaults;
protected settingDeviceOptions;
protected configs;
protected commonSettingsCount;
protected textureOverride;
protected titleSelected;
protected localStoragePropertyName;
protected rowsToDisplay: number;
abstract getLocalStorageSetting(): object;
abstract navigateMenuLeft(): boolean;
abstract navigateMenuRight(): boolean;
abstract saveSettingToLocalStorage(setting, cursor): void;
abstract getActiveConfig(): InterfaceConfig;
abstract setSetting(scene: BattleScene, setting, value: integer): boolean;
/**
* Constructor for the AbstractSettingsUiUiHandler.
*
* @param scene - The BattleScene instance.
* @param mode - The UI mode.
*/
constructor(scene: BattleScene, mode?: Mode) {
super(scene, mode);
this.rowsToDisplay = 8;
}
/**
* Setup UI elements.
*/
setup() {
const ui = this.getUi();
this.settingsContainer = this.scene.add.container(1, -(this.scene.game.canvas.height / 6) + 1);
this.settingsContainer.setInteractive(new Phaser.Geom.Rectangle(0, 0, this.scene.game.canvas.width / 6, this.scene.game.canvas.height / 6), Phaser.Geom.Rectangle.Contains);
this.headerBg = addWindow(this.scene, 0, 0, (this.scene.game.canvas.width / 6) - 2, 24);
this.headerBg.setOrigin(0, 0);
this.navigationIcons = {};
const iconPreviousTab = this.scene.add.sprite(0, 0, 'keyboard');
iconPreviousTab.setScale(.1);
iconPreviousTab.setOrigin(0, -0.1);
iconPreviousTab.setPositionRelative(this.headerBg, 8, 4);
this.navigationIcons['BUTTON_CYCLE_FORM'] = iconPreviousTab;
const iconNextTab = this.scene.add.sprite(0, 0, 'keyboard');
iconNextTab.setScale(.1);
iconNextTab.setOrigin(0, -0.1);
iconNextTab.setPositionRelative(this.headerBg, this.headerBg.width - 20, 4);
this.navigationIcons['BUTTON_CYCLE_SHINY'] = iconNextTab;
const headerText = addTextObject(this.scene, 0, 0, 'General', TextStyle.SETTINGS_LABEL);
headerText.setOrigin(0, 0);
headerText.setPositionRelative(this.headerBg, 8 + iconPreviousTab.width/6 - 4, 4);
const gamepadText = addTextObject(this.scene, 0, 0, 'Gamepad', this.titleSelected === 'Gamepad' ? TextStyle.SETTINGS_SELECTED : TextStyle.SETTINGS_LABEL);
gamepadText.setOrigin(0, 0);
gamepadText.setPositionRelative(this.headerBg, 50 + iconPreviousTab.width/6 - 4, 4);
const keyboardText = addTextObject(this.scene, 0, 0, 'Keyboard', this.titleSelected === 'Keyboard' ? TextStyle.SETTINGS_SELECTED : TextStyle.SETTINGS_LABEL);
keyboardText.setOrigin(0, 0);
keyboardText.setPositionRelative(this.headerBg, 97 + iconPreviousTab.width/6 - 4, 4);
this.optionsBg = addWindow(this.scene, 0, this.headerBg.height, (this.scene.game.canvas.width / 6) - 2, (this.scene.game.canvas.height / 6) - 16 - this.headerBg.height - 2);
this.optionsBg.setOrigin(0, 0);
this.actionsBg = addWindow(this.scene, 0, (this.scene.game.canvas.height / 6) - this.headerBg.height, (this.scene.game.canvas.width / 6) - 2, 22);
this.actionsBg.setOrigin(0, 0);
const iconAction = this.scene.add.sprite(0, 0, 'keyboard');
iconAction.setScale(.1);
iconAction.setOrigin(0, -0.1);
iconAction.setPositionRelative(this.actionsBg, this.headerBg.width - 20, 4);
this.navigationIcons['BUTTON_ACTION'] = iconAction;
const actionText = addTextObject(this.scene, 0, 0, 'Action', TextStyle.SETTINGS_LABEL);
actionText.setOrigin(0, 0);
actionText.setPositionRelative(iconAction, 0, 2);
actionText.setPositionRelative(iconAction, -actionText.width/6, -(actionText.height/6)/2 - 6);
const iconCancel = this.scene.add.sprite(0, 0, 'keyboard');
iconCancel.setScale(.1);
iconCancel.setOrigin(0, -0.1);
iconCancel.setPositionRelative(this.actionsBg, this.headerBg.width - 100, 4);
this.navigationIcons['BUTTON_CANCEL'] = iconCancel;
const cancelText = addTextObject(this.scene, 0, 0, 'Cancel', TextStyle.SETTINGS_LABEL);
cancelText.setOrigin(0, 0);
cancelText.setPositionRelative(iconCancel, -cancelText.width/6, -(cancelText.height/6)/2 - 6);
const iconReset = this.scene.add.sprite(0, 0, 'keyboard');
iconReset.setScale(.1);
iconReset.setOrigin(0, -0.1);
iconReset.setPositionRelative(this.actionsBg, this.headerBg.width - 180, 4);
this.navigationIcons['BUTTON_HOME'] = iconReset;
const resetText = addTextObject(this.scene, 0, 0, 'Reset all', TextStyle.SETTINGS_LABEL);
resetText.setOrigin(0, 0);
resetText.setPositionRelative(iconReset, -resetText.width/6, -(resetText.height/6)/2 - 6);
this.settingsContainer.add(this.headerBg);
this.settingsContainer.add(headerText);
this.settingsContainer.add(gamepadText);
this.settingsContainer.add(keyboardText);
this.settingsContainer.add(this.optionsBg);
this.settingsContainer.add(iconNextTab)
this.settingsContainer.add(iconPreviousTab)
this.settingsContainer.add(this.actionsBg)
this.settingsContainer.add(iconAction)
this.settingsContainer.add(iconCancel)
this.settingsContainer.add(iconReset)
this.settingsContainer.add(actionText)
this.settingsContainer.add(cancelText)
this.settingsContainer.add(resetText)
/// Initialize a new configuration "screen" for each type of gamepad.
for (const config of this.configs) {
// Create a map to store layout settings based on the pad type.
this.layout[config.padType] = new Map();
// Create a container for gamepad options in the scene, initially hidden.
const optionsContainer = this.scene.add.container(0, 0);
optionsContainer.setVisible(false);
// Gather all binding settings from the configuration.
const bindingSettings = Object.keys(config.settings);
// Array to hold labels for different settings such as 'Default Controller', 'Gamepad Support', etc.
const settingLabels: Phaser.GameObjects.Text[] = [];
// Array to hold options for each setting, e.g., 'Auto', 'Disabled'.
const optionValueLabels: Phaser.GameObjects.Text[][] = [];
// Object to store sprites for each button configuration.
const inputsIcons: InputsIcons = {};
// Fetch common setting keys such as 'Default Controller' and 'Gamepad Support' from gamepad settings.
const commonSettingKeys = Object.keys(this.settingDevice).slice(0, this.commonSettingsCount).map(key => this.settingDevice[key]);
// Combine common and specific bindings into a single array.
const specificBindingKeys = [...commonSettingKeys, ...Object.keys(config.settings)];
// Fetch default values for these settings and prepare to highlight selected options.
const optionCursors = Object.values(Object.keys(this.settingDeviceDefaults).filter(s => specificBindingKeys.includes(s)).map(k => this.settingDeviceDefaults[k]));
// Filter out settings that are not relevant to the current gamepad configuration.
const settingFiltered = Object.keys(this.settingDevice).filter(_key => specificBindingKeys.includes(this.settingDevice[_key]))
// Loop through the filtered settings to manage display and options.
settingFiltered.forEach((setting, s) => {
// Convert the setting key from format 'Key_Name' to 'Key name' for display.
let settingName = setting.replace(/\_/g, ' ');
// Create and add a text object for the setting name to the scene.
const isLock = this.settingBlacklisted.includes(this.settingDevice[setting]);
const labelStyle = isLock ? TextStyle.SETTINGS_LOCKED : TextStyle.SETTINGS_LABEL
settingLabels[s] = addTextObject(this.scene, 8, 28 + s * 16, settingName, labelStyle);
settingLabels[s].setOrigin(0, 0);
optionsContainer.add(settingLabels[s]);
// Initialize an array to store the option labels for this setting.
const valueLabels: Phaser.GameObjects.Text[] = []
// Process each option for the current setting.
for (const [o, option] of this.settingDeviceOptions[this.settingDevice[setting]].entries()) {
// Check if the current setting is for binding keys.
if (bindingSettings.includes(this.settingDevice[setting])) {
// Create a label for non-null options, typically indicating actionable options like 'change'.
if (o) {
const valueLabel = addTextObject(this.scene, 0, 0, isLock ? '' : option, TextStyle.WINDOW);
valueLabel.setOrigin(0, 0);
optionsContainer.add(valueLabel);
valueLabels.push(valueLabel);
continue;
}
// For null options, add an icon for the key.
const icon = this.scene.add.sprite(0, 0, this.textureOverride ? this.textureOverride : config.padType);
icon.setScale(0.1);
icon.setOrigin(0, -0.1);
inputsIcons[this.settingDevice[setting]] = icon;
optionsContainer.add(icon);
valueLabels.push(icon);
continue;
}
// For regular settings like 'Gamepad support', create a label and determine if it is selected.
const valueLabel = addTextObject(this.scene, 0, 0, option, this.settingDeviceDefaults[this.settingDevice[setting]] === o ? TextStyle.SETTINGS_SELECTED : TextStyle.WINDOW);
valueLabel.setOrigin(0, 0);
optionsContainer.add(valueLabel);
//if a setting has 2 options, valueLabels will be an array of 2 elements
valueLabels.push(valueLabel);
}
// Collect all option labels for this setting into the main array.
optionValueLabels.push(valueLabels);
// Calculate the total width of all option labels within a specific setting
// This is achieved by summing the width of each option label
const totalWidth = optionValueLabels[s].map(o => o.width).reduce((total, width) => total += width, 0);
// Define the minimum width for a label, ensuring it's at least 78 pixels wide or the width of the setting label plus some padding
const labelWidth = Math.max(90, settingLabels[s].displayWidth + 8);
// Calculate the total available space for placing option labels next to their setting label
// We reserve space for the setting label and then distribute the remaining space evenly
const totalSpace = (300 - labelWidth) - totalWidth / 6;
// Calculate the spacing between options based on the available space divided by the number of gaps between labels
const optionSpacing = Math.floor(totalSpace / (optionValueLabels[s].length - 1));
// Initialize xOffset to zero, which will be used to position each option label horizontally
let xOffset = 0;
// Start positioning each option label one by one
for (let value of optionValueLabels[s]) {
// Set the option label's position right next to the setting label, adjusted by xOffset
value.setPositionRelative(settingLabels[s], labelWidth + xOffset, 0);
// Move the xOffset to the right for the next label, ensuring each label is spaced evenly
xOffset += value.width / 6 + optionSpacing;
}
});
// Assigning the newly created components to the layout map under the specific gamepad type.
this.layout[config.padType].optionsContainer = optionsContainer; // Container for this pad's options.
this.layout[config.padType].inputsIcons = inputsIcons; // Icons for each input specific to this pad.
this.layout[config.padType].settingLabels = settingLabels; // Text labels for each setting available on this pad.
this.layout[config.padType].optionValueLabels = optionValueLabels; // Labels for values corresponding to each setting.
this.layout[config.padType].optionCursors = optionCursors; // Cursors to navigate through the options.
this.layout[config.padType].keys = specificBindingKeys; // Keys that identify each setting specifically bound to this pad.
this.layout[config.padType].bindingSettings = bindingSettings; // Settings that define how the keys are bound.
// Add the options container to the overall settings container to be displayed in the UI.
this.settingsContainer.add(optionsContainer);
}
// Add the settings container to the UI.
ui.add(this.settingsContainer);
// Initially hide the settings container until needed (e.g., when a gamepad is connected or a button is pressed).
this.settingsContainer.setVisible(false);
}
/**
* Update the bindings for the current active device configuration.
*/
updateBindings(): void {
// Hide the options container for all layouts to reset the UI visibility.
Object.keys(this.layout).forEach((key) => this.layout[key].optionsContainer.setVisible(false));
// Fetch the active gamepad configuration from the input controller.
const activeConfig = this.getActiveConfig();
// Set the UI layout for the active configuration. If unsuccessful, exit the function early.
if (!this.setLayout(activeConfig)) return;
// Retrieve the gamepad settings from local storage or use an empty object if none exist.
const settings: object = this.getLocalStorageSetting();
// Update the cursor for each key based on the stored settings or default cursors.
this.keys.forEach((key, index) => {
this.setOptionCursor(index, settings.hasOwnProperty(key) ? settings[key] : this.optionCursors[index])
});
// If the active configuration has no custom bindings set, exit the function early.
// by default, if custom does not exists, a default is assigned to it
// it only means the gamepad is not yet initalized
if (!activeConfig.custom) return;
// For each element in the binding settings, update the icon according to the current assignment.
for (const elm of this.bindingSettings) {
const icon = getIconWithSettingName(activeConfig, elm);
if (icon) {
this.inputsIcons[elm].setFrame(icon);
this.inputsIcons[elm].alpha = 1;
} else {
this.inputsIcons[elm].alpha = 0;
}
}
// Set the cursor and scroll cursor to their initial positions.
this.setCursor(this.cursor);
this.setScrollCursor(this.scrollCursor);
}
updateNavigationDisplay() {
const specialIcons = {
'BUTTON_HOME': 'T_Home_Key_Dark.png',
'BUTTON_DELETE': 'T_Del_Key_Dark.png',
}
for (const settingName of Object.keys(this.navigationIcons)) {
if (Object.keys(specialIcons).includes(settingName)) {
this.navigationIcons[settingName].setTexture("keyboard");
this.navigationIcons[settingName].setFrame(specialIcons[settingName]);
this.navigationIcons[settingName].alpha = 1;
continue
}
const icon = this.scene.inputController?.getIconForLatestInputRecorded(settingName);
if (icon) {
const type = this.scene.inputController?.getLastSourceType();
this.navigationIcons[settingName].setTexture(type);
this.navigationIcons[settingName].setFrame(icon);
this.navigationIcons[settingName].alpha = 1;
} else {
this.navigationIcons[settingName].alpha = 0;
}
}
}
/**
* Show the UI with the provided arguments.
*
* @param args - Arguments to be passed to the show method.
* @returns `true` if successful.
*/
show(args: any[]): boolean {
super.show(args);
this.updateNavigationDisplay();
// Update the bindings for the current active gamepad configuration.
this.updateBindings();
// Make the settings container visible to the user.
this.settingsContainer.setVisible(true);
// Reset the scroll cursor to the top of the settings container.
this.resetScroll();
// Move the settings container to the end of the UI stack to ensure it is displayed on top.
this.getUi().moveTo(this.settingsContainer, this.getUi().length - 1);
// Hide any tooltips that might be visible before showing the settings container.
this.getUi().hideTooltip();
// Return true to indicate the UI was successfully shown.
return true;
}
/**
* Set the UI layout for the active device configuration.
*
* @param activeConfig - The active device configuration.
* @returns `true` if the layout was successfully applied, otherwise `false`.
*/
setLayout(activeConfig: InterfaceConfig): boolean {
// Check if there is no active configuration (e.g., no gamepad connected).
if (!activeConfig) {
// Retrieve the layout for when no gamepads are connected.
const layout = this.layout['noGamepads'];
// Make the options container visible to show message.
layout.optionsContainer.setVisible(true);
// Return false indicating the layout application was not successful due to lack of gamepad.
return false;
}
// Extract the type of the gamepad from the active configuration.
const configType = activeConfig.padType;
// Retrieve the layout settings based on the type of the gamepad.
const layout = this.layout[configType];
// Update the main controller with configuration details from the selected layout.
this.keys = layout.keys;
this.optionsContainer = layout.optionsContainer;
this.optionsContainer.setVisible(true);
this.settingLabels = layout.settingLabels;
this.optionValueLabels = layout.optionValueLabels;
this.optionCursors = layout.optionCursors;
this.inputsIcons = layout.inputsIcons;
this.bindingSettings = layout.bindingSettings;
// Return true indicating the layout was successfully applied.
return true;
}
/**
* Process the input for the given button.
*
* @param button - The button to process.
* @returns `true` if the input was processed successfully.
*/
processInput(button: Button): boolean {
const ui = this.getUi();
// Defines the maximum number of rows that can be displayed on the screen.
let success = false;
this.updateNavigationDisplay();
// Handle the input based on the button pressed.
if (button === Button.CANCEL) {
// Handle cancel button press, reverting UI mode to previous state.
success = true;
this.scene.ui.revertMode();
} else {
const cursor = this.cursor + this.scrollCursor; // Calculate the absolute cursor position.
const setting = this.settingDevice[Object.keys(this.settingDevice)[cursor]];
switch (button) {
case Button.ACTION:
if (!this.optionCursors || !this.optionValueLabels) return;
if (this.settingBlacklisted.includes(setting) || !setting.includes('BUTTON_')) success = false;
else
success = this.setSetting(this.scene, setting, 1);
break;
case Button.UP: // Move up in the menu.
if (!this.optionValueLabels) return false;
if (cursor) { // If not at the top, move the cursor up.
if (this.cursor)
success = this.setCursor(this.cursor - 1);
else // If at the top of the visible items, scroll up.
success = this.setScrollCursor(this.scrollCursor - 1);
} else {
// When at the top of the menu and pressing UP, move to the bottommost item.
// First, set the cursor to the last visible element, preparing for the scroll to the end.
const successA = this.setCursor(this.rowsToDisplay - 1);
// Then, adjust the scroll to display the bottommost elements of the menu.
const successB = this.setScrollCursor(this.optionValueLabels.length - this.rowsToDisplay);
success = successA && successB; // success is just there to play the little validation sound effect
}
break;
case Button.DOWN: // Move down in the menu.
if (!this.optionValueLabels) return false;
if (cursor < this.optionValueLabels.length - 1) {
if (this.cursor < this.rowsToDisplay - 1)
success = this.setCursor(this.cursor + 1);
else if (this.scrollCursor < this.optionValueLabels.length - this.rowsToDisplay)
success = this.setScrollCursor(this.scrollCursor + 1);
} else {
// When at the bottom of the menu and pressing DOWN, move to the topmost item.
// First, set the cursor to the first visible element, resetting the scroll to the top.
const successA = this.setCursor(0);
// Then, reset the scroll to start from the first element of the menu.
const successB = this.setScrollCursor(0);
success = successA && successB; // Indicates a successful cursor and scroll adjustment.
}
break;
case Button.LEFT: // Move selection left within the current option set.
if (!this.optionCursors || !this.optionValueLabels) return;
if (this.settingBlacklisted.includes(setting) || setting.includes('BUTTON_')) success = false;
else if (this.optionCursors[cursor]) {
success = this.setOptionCursor(cursor, this.optionCursors[cursor] - 1, true);
}
break;
case Button.RIGHT: // Move selection right within the current option set.
if (!this.optionCursors || !this.optionValueLabels) return;
if (this.settingBlacklisted.includes(setting) || setting.includes('BUTTON_')) success = false;
else if (this.optionCursors[cursor] < this.optionValueLabels[cursor].length - 1) {
success = this.setOptionCursor(cursor, this.optionCursors[cursor] + 1, true);
}
break;
case Button.CYCLE_FORM:
success = this.navigateMenuLeft();
break;
case Button.CYCLE_SHINY:
success = this.navigateMenuRight();
break;
}
}
// If a change occurred, play the selection sound.
if (success)
ui.playSelect();
return success; // Return whether the input resulted in a successful action.
}
resetScroll() {
this.cursorObj?.destroy();
this.cursorObj = null;
this.cursor = null;
this.setCursor(0);
this.setScrollCursor(0);
this.updateSettingsScroll();
}
/**
* Set the cursor to the specified position.
*
* @param cursor - The cursor position to set.
* @returns `true` if the cursor was set successfully.
*/
setCursor(cursor: integer): boolean {
const ret = super.setCursor(cursor);
// If the optionsContainer is not initialized, return the result from the parent class directly.
if (!this.optionsContainer) return ret;
// Check if the cursor object exists, if not, create it.
if (!this.cursorObj) {
this.cursorObj = this.scene.add.nineslice(0, 0, 'summary_moves_cursor', null, (this.scene.game.canvas.width / 6) - 10, 16, 1, 1, 1, 1);
this.cursorObj.setOrigin(0, 0); // Set the origin to the top-left corner.
this.optionsContainer.add(this.cursorObj); // Add the cursor to the options container.
}
// Update the position of the cursor object relative to the options background based on the current cursor and scroll positions.
this.cursorObj.setPositionRelative(this.optionsBg, 4, 4 + (this.cursor + this.scrollCursor) * 16);
return ret; // Return the result from the parent class's setCursor method.
}
/**
* Set the scroll cursor to the specified position.
*
* @param scrollCursor - The scroll cursor position to set.
* @returns `true` if the scroll cursor was set successfully.
*/
setScrollCursor(scrollCursor: integer): boolean {
// Check if the new scroll position is the same as the current one; if so, do not update.
if (scrollCursor === this.scrollCursor)
return false;
// Update the internal scroll cursor state
this.scrollCursor = scrollCursor;
// Apply the new scroll position to the settings UI.
this.updateSettingsScroll();
// Reset the cursor to its current position to adjust its visibility after scrolling.
this.setCursor(this.cursor);
return true; // Return true to indicate the scroll cursor was successfully updated.
}
/**
* Set the option cursor to the specified position.
*
* @param settingIndex - The index of the setting.
* @param cursor - The cursor position to set.
* @param save - Whether to save the setting to local storage.
* @returns `true` if the option cursor was set successfully.
*/
setOptionCursor(settingIndex: integer, cursor: integer, save?: boolean): boolean {
// Retrieve the specific setting using the settingIndex from the settingDevice enumeration.
const setting = this.settingDevice[Object.keys(this.settingDevice)[settingIndex]];
// Get the current cursor position for this setting.
const lastCursor = this.optionCursors[settingIndex];
// Check if the setting is not part of the bindings (i.e., it's a regular setting).
if (!this.bindingSettings.includes(setting) && !setting.includes('BUTTON_')) {
// Get the label of the last selected option and revert its color to the default.
const lastValueLabel = this.optionValueLabels[settingIndex][lastCursor];
lastValueLabel.setColor(this.getTextColor(TextStyle.WINDOW));
lastValueLabel.setShadowColor(this.getTextColor(TextStyle.WINDOW, true));
// Update the cursor for the setting to the new position.
this.optionCursors[settingIndex] = cursor;
// Change the color of the new selected option to indicate it's selected.
const newValueLabel = this.optionValueLabels[settingIndex][cursor];
newValueLabel.setColor(this.getTextColor(TextStyle.SETTINGS_SELECTED));
newValueLabel.setShadowColor(this.getTextColor(TextStyle.SETTINGS_SELECTED, true));
}
// If the save flag is set and the setting is not the default controller setting, save the setting to local storage
if (save) {
this.saveSettingToLocalStorage(setting, cursor);
}
return true; // Return true to indicate the cursor was successfully updated.
}
/**
* Update the scroll position of the settings UI.
*/
updateSettingsScroll(): void {
// Return immediately if the options container is not initialized.
if (!this.optionsContainer) return;
// Set the vertical position of the options container based on the current scroll cursor, multiplying by the item height.
this.optionsContainer.setY(-16 * this.scrollCursor);
// Iterate over all setting labels to update their visibility.
for (let s = 0; s < this.settingLabels.length; s++) {
// Determine if the current setting should be visible based on the scroll position.
const visible = s >= this.scrollCursor && s < this.scrollCursor + this.rowsToDisplay;
// Set the visibility of the setting label and its corresponding options.
this.settingLabels[s].setVisible(visible);
for (let option of this.optionValueLabels[s])
option.setVisible(visible);
}
}
/**
* Clear the UI elements and state.
*/
clear(): void {
super.clear();
// Hide the settings container to remove it from the view.
this.settingsContainer.setVisible(false);
// Remove the cursor from the UI.
this.eraseCursor();
}
/**
* Erase the cursor from the UI.
*/
eraseCursor(): void {
// Check if a cursor object exists.
if (this.cursorObj)
this.cursorObj.destroy(); // Destroy the cursor object to clean up resources.
// Set the cursor object reference to null to fully dereference it.
this.cursorObj = null;
}
}

View File

@ -0,0 +1,81 @@
import BattleScene from "../../battle-scene";
import AbstractBindingUiHandler from "../settings/abrast-binding-ui-handler";
import {Mode} from "../ui";
import {Device} from "#app/enums/devices";
import {getIconWithSettingName, getKeyWithKeycode} from "#app/configs/configHandler";
import {addTextObject, TextStyle} from "#app/ui/text";
export default class GamepadBindingUiHandler extends AbstractBindingUiHandler {
constructor(scene: BattleScene, mode: Mode) {
super(scene, mode);
this.scene.input.gamepad.on('down', this.gamepadButtonDown, this);
}
setup() {
super.setup();
// New button icon setup.
this.newButtonIcon = this.scene.add.sprite(0, 0, 'xbox');
this.newButtonIcon.setScale(0.15);
this.newButtonIcon.setPositionRelative(this.optionSelectBg, 78, 16);
this.newButtonIcon.setOrigin(0.5);
this.newButtonIcon.setVisible(false);
this.swapText = addTextObject(this.scene, 0, 0, 'will swap with', TextStyle.WINDOW);
this.swapText.setOrigin(0.5);
this.swapText.setPositionRelative(this.optionSelectBg, this.optionSelectBg.width / 2 - 2, this.optionSelectBg.height / 2 - 2);
this.swapText.setVisible(false);
this.targetButtonIcon = this.scene.add.sprite(0, 0, 'xbox');
this.targetButtonIcon.setScale(0.15);
this.targetButtonIcon.setPositionRelative(this.optionSelectBg, 78, 48);
this.targetButtonIcon.setOrigin(0.5);
this.targetButtonIcon.setVisible(false);
this.actionLabel = addTextObject(this.scene, 0, 0, "Confirm swap", TextStyle.SETTINGS_LABEL);
this.actionLabel.setOrigin(0, 0.5);
this.actionLabel.setPositionRelative(this.actionBg, this.actionBg.width - 75, this.actionBg.height / 2);
this.actionsContainer.add(this.actionLabel);
this.optionSelectContainer.add(this.newButtonIcon);
this.optionSelectContainer.add(this.swapText);
this.optionSelectContainer.add(this.targetButtonIcon);
}
getSelectedDevice() {
return this.scene.inputController?.selectedDevice[Device.GAMEPAD];
}
gamepadButtonDown(pad: Phaser.Input.Gamepad.Gamepad, button: Phaser.Input.Gamepad.Button, value: number): void {
const blacklist = [12, 13, 14, 15]; // d-pad buttons are blacklisted.
// Check conditions before processing the button press.
if (!this.listening || pad.id.toLowerCase() !== this.getSelectedDevice() || blacklist.includes(button.index) || this.buttonPressed !== null) return;
const activeConfig = this.scene.inputController.getActiveConfig(Device.GAMEPAD);
const type = activeConfig.padType
const key = getKeyWithKeycode(activeConfig, button.index);
const buttonIcon = activeConfig.icons[key];
if (!buttonIcon) return;
this.buttonPressed = button.index;
const assignedButtonIcon = getIconWithSettingName(activeConfig, this.target);
this.onInputDown(buttonIcon, assignedButtonIcon, type);
}
swapAction(): boolean {
const activeConfig = this.scene.inputController.getActiveConfig(Device.GAMEPAD);
if(this.scene.inputController.assignBinding(activeConfig, this.target, this.buttonPressed)) {
this.scene.gameData.saveMappingConfigs(this.getSelectedDevice(), activeConfig);
return true;
}
return false;
}
/**
* Clear the UI elements and state.
*/
clear() {
super.clear();
this.targetButtonIcon.setVisible(false);
this.swapText.setVisible(false);
}
}

View File

@ -0,0 +1,71 @@
import BattleScene from "../../battle-scene";
import AbstractBindingUiHandler from "../settings/abrast-binding-ui-handler";
import {Mode} from "../ui";
import { getIconWithSettingName, getKeyWithKeycode} from "#app/configs/configHandler";
import {Device} from "#app/enums/devices";
import {addTextObject, TextStyle} from "#app/ui/text";
export default class KeyboardBindingUiHandler extends AbstractBindingUiHandler {
constructor(scene: BattleScene, mode?: Mode) {
super(scene, mode);
// Listen to gamepad button down events to initiate binding.
scene.input.keyboard.on('keydown', this.onKeyDown, this);
this.confirmText = "Confirm";
}
setup() {
super.setup();
// New button icon setup.
this.newButtonIcon = this.scene.add.sprite(0, 0, 'keyboard');
this.newButtonIcon.setScale(0.15);
this.newButtonIcon.setPositionRelative(this.optionSelectBg, 78, 32);
this.newButtonIcon.setOrigin(0.5);
this.newButtonIcon.setVisible(false);
this.actionLabel = addTextObject(this.scene, 0, 0, "Assign button", TextStyle.SETTINGS_LABEL);
this.actionLabel.setOrigin(0, 0.5);
this.actionLabel.setPositionRelative(this.actionBg, this.actionBg.width - 80, this.actionBg.height / 2);
this.actionsContainer.add(this.actionLabel);
this.optionSelectContainer.add(this.newButtonIcon);
}
getSelectedDevice() {
return this.scene.inputController?.selectedDevice[Device.KEYBOARD];
}
onKeyDown(event): void {
const blacklist = [
Phaser.Input.Keyboard.KeyCodes.UP,
Phaser.Input.Keyboard.KeyCodes.DOWN,
Phaser.Input.Keyboard.KeyCodes.LEFT,
Phaser.Input.Keyboard.KeyCodes.RIGHT,
Phaser.Input.Keyboard.KeyCodes.HOME,
Phaser.Input.Keyboard.KeyCodes.ENTER,
Phaser.Input.Keyboard.KeyCodes.ESC,
Phaser.Input.Keyboard.KeyCodes.DELETE,
];
const key = event.keyCode;
// // Check conditions before processing the button press.
if (!this.listening || this.buttonPressed !== null || blacklist.includes(key)) return;
const activeConfig = this.scene.inputController.getActiveConfig(Device.KEYBOARD);
const _key = getKeyWithKeycode(activeConfig, key);
const buttonIcon = activeConfig.icons[_key];
if (!buttonIcon) return;
this.buttonPressed = key;
const assignedButtonIcon = getIconWithSettingName(activeConfig, this.target);
this.onInputDown(buttonIcon, null, 'keyboard');
}
swapAction(): boolean {
const activeConfig = this.scene.inputController.getActiveConfig(Device.KEYBOARD);
if (this.scene.inputController.assignBinding(activeConfig, this.target, this.buttonPressed)) {
this.scene.gameData.saveMappingConfigs(this.getSelectedDevice(), activeConfig);
return true;
}
return false;
}
}

View File

@ -1,6 +1,6 @@
import BattleScene from "../battle-scene";
import AbstractOptionSelectUiHandler from "./abstact-option-select-ui-handler";
import { Mode } from "./ui";
import BattleScene from "../../battle-scene";
import AbstractOptionSelectUiHandler from "../abstact-option-select-ui-handler";
import { Mode } from "../ui";
export default class OptionSelectUiHandler extends AbstractOptionSelectUiHandler {
constructor(scene: BattleScene, mode: Mode = Mode.OPTION_SELECT) {

View File

@ -0,0 +1,166 @@
import BattleScene from "../../battle-scene";
import {addTextObject, TextStyle} from "../text";
import {Mode} from "../ui";
import {
setSettingGamepad,
SettingGamepad,
settingGamepadBlackList,
settingGamepadDefaults,
settingGamepadOptions
} from "../../system/settings-gamepad";
import pad_xbox360 from "#app/configs/pad_xbox360";
import pad_dualshock from "#app/configs/pad_dualshock";
import pad_unlicensedSNES from "#app/configs/pad_unlicensedSNES";
import {InterfaceConfig} from "#app/inputs-controller";
import AbstractSettingsUiUiHandler from "#app/ui/settings/abstract-settings-ui-handler";
import {Device} from "#app/enums/devices";
import {truncateString} from "#app/utils";
import {setSettingKeyboard, SettingKeyboard} from "#app/system/settings-keyboard";
/**
* Class representing the settings UI handler for gamepads.
*
* @extends AbstractSettingsUiUiHandler
*/
export default class SettingsGamepadUiHandler extends AbstractSettingsUiUiHandler {
/**
* Creates an instance of SettingsGamepadUiHandler.
*
* @param scene - The BattleScene instance.
* @param mode - The UI mode, optional.
*/
constructor(scene: BattleScene, mode?: Mode) {
super(scene, mode);
this.titleSelected = 'Gamepad';
this.settingDevice = SettingGamepad;
this.settingDeviceDefaults = settingGamepadDefaults;
this.settingDeviceOptions = settingGamepadOptions;
this.configs = [pad_xbox360, pad_dualshock, pad_unlicensedSNES]
this.commonSettingsCount = 2;
this.localStoragePropertyName = 'settingsGamepad';
this.settingBlacklisted = settingGamepadBlackList;
}
setSetting(scene: BattleScene, setting, value: integer): boolean {
return setSettingGamepad(scene, setting, value);
}
/**
* Setup UI elements.
*/
setup() {
super.setup();
// If no gamepads are detected, set up a default UI prompt in the settings container.
this.layout['noGamepads'] = new Map();
const optionsContainer = this.scene.add.container(0, 0);
optionsContainer.setVisible(false); // Initially hide the container as no gamepads are connected.
const label = addTextObject(this.scene, 8, 28, 'Please plug a controller or press a button', TextStyle.SETTINGS_LABEL);
label.setOrigin(0, 0);
optionsContainer.add(label);
this.settingsContainer.add(optionsContainer);
// Map the 'noGamepads' layout options for easy access.
this.layout['noGamepads'].optionsContainer = optionsContainer;
this.layout['noGamepads'].label = label;
}
/**
* Get the active configuration.
*
* @returns The active gamepad configuration.
*/
getActiveConfig(): InterfaceConfig {
return this.scene.inputController.getActiveConfig(Device.GAMEPAD);
}
/**
* Get the gamepad settings from local storage.
*
* @returns The gamepad settings from local storage.
*/
getLocalStorageSetting(): object {
// Retrieve the gamepad settings from local storage or use an empty object if none exist.
const settings: object = localStorage.hasOwnProperty('settingsGamepad') ? JSON.parse(localStorage.getItem('settingsGamepad')) : {};
return settings;
}
/**
* Set the layout for the active configuration.
*
* @param activeConfig - The active gamepad configuration.
* @returns `true` if the layout was successfully applied, otherwise `false`.
*/
setLayout(activeConfig: InterfaceConfig): boolean {
// Check if there is no active configuration (e.g., no gamepad connected).
if (!activeConfig) {
// Retrieve the layout for when no gamepads are connected.
const layout = this.layout['noGamepads'];
// Make the options container visible to show message.
layout.optionsContainer.setVisible(true);
// Return false indicating the layout application was not successful due to lack of gamepad.
return false;
}
return super.setLayout(activeConfig);
}
/**
* Navigate to the left menu tab.
*
* @returns `true` indicating the navigation was successful.
*/
navigateMenuLeft(): boolean {
this.scene.ui.setMode(Mode.SETTINGS)
return true;
}
/**
* Navigate to the right menu tab.
*
* @returns `true` indicating the navigation was successful.
*/
navigateMenuRight(): boolean {
this.scene.ui.setMode(Mode.SETTINGS_KEYBOARD)
return true;
}
/**
* Update the display of the chosen gamepad.
*/
updateChosenGamepadDisplay(): void {
// Update any bindings that might have changed since the last update.
this.updateBindings();
this.resetScroll();
// Iterate over the keys in the settingDevice enumeration.
for (const [index, key] of Object.keys(this.settingDevice).entries()) {
const setting = this.settingDevice[key] // Get the actual setting value using the key.
// Check if the current setting corresponds to the default controller setting.
if (setting === this.settingDevice.Default_Controller) {
// Iterate over all layouts excluding the 'noGamepads' special case.
for (const _key of Object.keys(this.layout)) {
if (_key === 'noGamepads') continue; // Skip updating the no gamepad layout.
// Update the text of the first option label under the current setting to the name of the chosen gamepad,
// truncating the name to 30 characters if necessary.
this.layout[_key].optionValueLabels[index][0].setText(truncateString(this.scene.inputController.selectedDevice[Device.GAMEPAD], 30));
}
}
}
}
/**
* Save the setting to local storage.
*
* @param setting - The setting to save.
* @param cursor - The cursor position to save.
*/
saveSettingToLocalStorage(setting, cursor): void {
if (this.settingDevice[setting] !== this.settingDevice.Default_Controller)
this.scene.gameData.saveGamepadSetting(setting, cursor)
}
}

View File

@ -0,0 +1,215 @@
import BattleScene from "../../battle-scene";
import {Mode} from "../ui";
import cfg_keyboard_azerty from "#app/configs/cfg_keyboard_azerty";
import {
setSettingKeyboard,
SettingKeyboard,
settingKeyboardBlackList,
settingKeyboardDefaults,
settingKeyboardOptions
} from "#app/system/settings-keyboard";
import {reverseValueToKeySetting, truncateString} from "#app/utils";
import AbstractSettingsUiUiHandler from "#app/ui/settings/abstract-settings-ui-handler";
import {InterfaceConfig} from "#app/inputs-controller";
import {addTextObject, TextStyle} from "#app/ui/text";
import {deleteBind} from "#app/configs/configHandler";
import {Device} from "#app/enums/devices";
/**
* Class representing the settings UI handler for keyboards.
*
* @extends AbstractSettingsUiUiHandler
*/
export default class SettingsKeyboardUiHandler extends AbstractSettingsUiUiHandler {
/**
* Creates an instance of SettingsKeyboardUiHandler.
*
* @param scene - The BattleScene instance.
* @param mode - The UI mode, optional.
*/
constructor(scene: BattleScene, mode?: Mode) {
super(scene, mode);
this.titleSelected = 'Keyboard';
this.settingDevice = SettingKeyboard;
this.settingDeviceDefaults = settingKeyboardDefaults;
this.settingDeviceOptions = settingKeyboardOptions;
this.configs = [cfg_keyboard_azerty];
this.commonSettingsCount = 0;
this.textureOverride = 'keyboard';
this.localStoragePropertyName = 'settingsKeyboard';
this.settingBlacklisted = settingKeyboardBlackList;
const deleteEvent = scene.input.keyboard.addKey(Phaser.Input.Keyboard.KeyCodes.DELETE);
const restoreDefaultEvent = scene.input.keyboard.addKey(Phaser.Input.Keyboard.KeyCodes.HOME);
deleteEvent.on('up', this.onDeleteDown, this);
restoreDefaultEvent.on('up', this.onHomeDown, this);
}
setSetting(scene: BattleScene, setting, value: integer): boolean {
return setSettingKeyboard(scene, setting, value);
}
/**
* Setup UI elements.
*/
setup() {
super.setup();
// If no gamepads are detected, set up a default UI prompt in the settings container.
this.layout['noKeyboard'] = new Map();
const optionsContainer = this.scene.add.container(0, 0);
optionsContainer.setVisible(false); // Initially hide the container as no gamepads are connected.
const label = addTextObject(this.scene, 8, 28, 'Please press a key on your keyboard', TextStyle.SETTINGS_LABEL);
label.setOrigin(0, 0);
optionsContainer.add(label);
this.settingsContainer.add(optionsContainer);
const iconDelete = this.scene.add.sprite(0, 0, 'keyboard');
iconDelete.setScale(.1);
iconDelete.setOrigin(0, -0.1);
iconDelete.setPositionRelative(this.actionsBg, this.headerBg.width - 260, 4);
this.navigationIcons['BUTTON_DELETE'] = iconDelete;
const deleteText = addTextObject(this.scene, 0, 0, 'Delete', TextStyle.SETTINGS_LABEL);
deleteText.setOrigin(0, 0);
deleteText.setPositionRelative(iconDelete, -deleteText.width/6, -(deleteText.height/6)/2 - 6);
this.settingsContainer.add(iconDelete)
this.settingsContainer.add(deleteText)
// Map the 'noKeyboard' layout options for easy access.
this.layout['noKeyboard'].optionsContainer = optionsContainer;
this.layout['noKeyboard'].label = label;
}
/**
* Handle the home key press event.
*/
onHomeDown(): void {
if (![Mode.SETTINGS_KEYBOARD, Mode.SETTINGS_GAMEPAD].includes(this.scene.ui.getMode())) return;
this.scene.gameData.resetMappingToFactory();
}
/**
* Handle the delete key press event.
*/
onDeleteDown(): void {
if (this.scene.ui.getMode() !== Mode.SETTINGS_KEYBOARD) return;
const cursor = this.cursor + this.scrollCursor; // Calculate the absolute cursor position.
const selection = this.settingLabels[cursor].text;
const key = reverseValueToKeySetting(selection);
const settingName = SettingKeyboard[key];
const activeConfig = this.getActiveConfig();
const success = deleteBind(this.getActiveConfig(), settingName);
if (success) {
this.saveCustomKeyboardMappingToLocalStorage(activeConfig);
this.updateBindings();
}
}
/**
* Get the active configuration.
*
* @returns The active keyboard configuration.
*/
getActiveConfig(): InterfaceConfig {
return this.scene.inputController.getActiveConfig(Device.KEYBOARD);
}
/**
* Get the keyboard settings from local storage.
*
* @returns The keyboard settings from local storage.
*/
getLocalStorageSetting(): object {
// Retrieve the gamepad settings from local storage or use an empty object if none exist.
const settings: object = localStorage.hasOwnProperty('settingsKeyboard') ? JSON.parse(localStorage.getItem('settingsKeyboard')) : {};
return settings;
}
/**
* Set the layout for the active configuration.
*
* @param activeConfig - The active keyboard configuration.
* @returns `true` if the layout was successfully applied, otherwise `false`.
*/
setLayout(activeConfig: InterfaceConfig): boolean {
// Check if there is no active configuration (e.g., no gamepad connected).
if (!activeConfig) {
// Retrieve the layout for when no gamepads are connected.
const layout = this.layout['noKeyboard'];
// Make the options container visible to show message.
layout.optionsContainer.setVisible(true);
// Return false indicating the layout application was not successful due to lack of gamepad.
return false;
}
return super.setLayout(activeConfig);
}
/**
* Navigate to the left menu tab.
*
* @returns `true` indicating the navigation was successful.
*/
navigateMenuLeft(): boolean {
this.scene.ui.setMode(Mode.SETTINGS_GAMEPAD)
return true;
}
/**
* Navigate to the right menu tab.
*
* @returns `true` indicating the navigation was successful.
*/
navigateMenuRight(): boolean {
this.scene.ui.setMode(Mode.SETTINGS)
return true;
}
/**
* Update the display of the chosen keyboard layout.
*/
updateChosenKeyboardDisplay(): void {
// Update any bindings that might have changed since the last update.
this.updateBindings();
// Iterate over the keys in the settingDevice enumeration.
for (const [index, key] of Object.keys(this.settingDevice).entries()) {
const setting = this.settingDevice[key] // Get the actual setting value using the key.
// Check if the current setting corresponds to the default controller setting.
if (setting === this.settingDevice.Default_Layout) {
// Iterate over all layouts excluding the 'noGamepads' special case.
for (const _key of Object.keys(this.layout)) {
if (_key === 'noKeyboard') continue; // Skip updating the no gamepad layout.
// Update the text of the first option label under the current setting to the name of the chosen gamepad,
// truncating the name to 30 characters if necessary.
this.layout[_key].optionValueLabels[index][0].setText(truncateString(this.scene.inputController.selectedDevice[Device.KEYBOARD], 22));
}
}
}
}
/**
* Save the custom keyboard mapping to local storage.
*
* @param config - The configuration to save.
*/
saveCustomKeyboardMappingToLocalStorage(config): void {
this.scene.gameData.saveMappingConfigs(this.scene.inputController?.selectedDevice[Device.KEYBOARD], config);
}
/**
* Save the setting to local storage.
*
* @param settingName - The name of the setting to save.
* @param cursor - The cursor position to save.
*/
saveSettingToLocalStorage(settingName, cursor): void {
if (this.settingDevice[settingName] !== this.settingDevice.Default_Layout)
this.scene.gameData.saveKeyboardSetting(settingName, cursor)
}
}

View File

@ -1,11 +1,12 @@
import BattleScene from "../battle-scene";
import { Setting, reloadSettings, settingDefaults, settingOptions } from "../system/settings";
import { hasTouchscreen, isMobile } from "../touch-controls";
import { TextStyle, addTextObject } from "./text";
import { Mode } from "./ui";
import UiHandler from "./ui-handler";
import { addWindow } from "./ui-theme";
import {Button} from "../enums/buttons";
import BattleScene from "../../battle-scene";
import {Setting, reloadSettings, settingDefaults, settingOptions} from "../../system/settings";
import { hasTouchscreen, isMobile } from "../../touch-controls";
import { TextStyle, addTextObject } from "../text";
import { Mode } from "../ui";
import UiHandler from "../ui-handler";
import { addWindow } from "../ui-theme";
import {Button} from "../../enums/buttons";
import {InputsIcons} from "#app/ui/settings/abstract-settings-ui-handler";
export default class SettingsUiHandler extends UiHandler {
private settingsContainer: Phaser.GameObjects.Container;
@ -20,16 +21,20 @@ export default class SettingsUiHandler extends UiHandler {
private settingLabels: Phaser.GameObjects.Text[];
private optionValueLabels: Phaser.GameObjects.Text[][];
protected navigationIcons: InputsIcons;
private cursorObj: Phaser.GameObjects.NineSlice;
private reloadRequired: boolean;
private reloadI18n: boolean;
private rowsToDisplay: number;
constructor(scene: BattleScene, mode?: Mode) {
super(scene, mode);
this.reloadRequired = false;
this.reloadI18n = false;
this.rowsToDisplay = 8;
}
setup() {
@ -37,18 +42,64 @@ export default class SettingsUiHandler extends UiHandler {
this.settingsContainer = this.scene.add.container(1, -(this.scene.game.canvas.height / 6) + 1);
this.settingsContainer.setInteractive(new Phaser.Geom.Rectangle(0, 0, this.scene.game.canvas.width / 6, this.scene.game.canvas.height / 6), Phaser.Geom.Rectangle.Contains);
this.settingsContainer.setInteractive(new Phaser.Geom.Rectangle(0, 0, this.scene.game.canvas.width / 6, this.scene.game.canvas.height / 6) - 20, Phaser.Geom.Rectangle.Contains);
this.navigationIcons = {};
const headerBg = addWindow(this.scene, 0, 0, (this.scene.game.canvas.width / 6) - 2, 24);
headerBg.setOrigin(0, 0);
const headerText = addTextObject(this.scene, 0, 0, 'Options', TextStyle.SETTINGS_LABEL);
headerText.setOrigin(0, 0);
headerText.setPositionRelative(headerBg, 8, 4);
this.optionsBg = addWindow(this.scene, 0, headerBg.height, (this.scene.game.canvas.width / 6) - 2, (this.scene.game.canvas.height / 6) - headerBg.height - 2);
this.optionsBg = addWindow(this.scene, 0, headerBg.height, (this.scene.game.canvas.width / 6) - 2, (this.scene.game.canvas.height / 6) - 16 - headerBg.height - 2);
this.optionsBg.setOrigin(0, 0);
const actionsBg = addWindow(this.scene, 0, (this.scene.game.canvas.height / 6) - headerBg.height, (this.scene.game.canvas.width / 6) - 2, 22);
actionsBg.setOrigin(0, 0);
const iconPreviousTab = this.scene.add.sprite(0, 0, 'keyboard');
iconPreviousTab.setScale(.1);
iconPreviousTab.setOrigin(0, -0.1);
iconPreviousTab.setPositionRelative(headerBg, 8, 4);
this.navigationIcons['BUTTON_CYCLE_FORM'] = iconPreviousTab;
const iconNextTab = this.scene.add.sprite(0, 0, 'keyboard');
iconNextTab.setScale(.1);
iconNextTab.setOrigin(0, -0.1);
iconNextTab.setPositionRelative(headerBg, headerBg.width - 20, 4);
this.navigationIcons['BUTTON_CYCLE_SHINY'] = iconNextTab;
const iconAction = this.scene.add.sprite(0, 0, 'keyboard');
iconAction.setScale(.1);
iconAction.setOrigin(0, -0.1);
iconAction.setPositionRelative(actionsBg, headerBg.width - 20, 4);
this.navigationIcons['BUTTON_ACTION'] = iconAction;
const actionText = addTextObject(this.scene, 0, 0, 'Action', TextStyle.SETTINGS_LABEL);
actionText.setOrigin(0, 0);
actionText.setPositionRelative(iconAction, 0, 2);
actionText.setPositionRelative(iconAction, -actionText.width/6, -(actionText.height/6)/2 - 6);
const iconCancel = this.scene.add.sprite(0, 0, 'keyboard');
iconCancel.setScale(.1);
iconCancel.setOrigin(0, -0.1);
iconCancel.setPositionRelative(actionsBg, headerBg.width - 100, 4);
this.navigationIcons['BUTTON_CANCEL'] = iconCancel;
const cancelText = addTextObject(this.scene, 0, 0, 'Cancel', TextStyle.SETTINGS_LABEL);
cancelText.setOrigin(0, 0);
cancelText.setPositionRelative(iconCancel, -cancelText.width/6, -(cancelText.height/6)/2 - 6);
const headerText = addTextObject(this.scene, 0, 0, 'General', TextStyle.SETTINGS_SELECTED);
headerText.setOrigin(0, 0);
headerText.setPositionRelative(headerBg, 8 + iconPreviousTab.width/6 - 4, 4);
const gamepadText = addTextObject(this.scene, 0, 0, 'Gamepad', TextStyle.SETTINGS_LABEL);
gamepadText.setOrigin(0, 0);
gamepadText.setPositionRelative(headerBg, 50 + iconPreviousTab.width/6 - 4, 4);
const keyboardText = addTextObject(this.scene, 0, 0, 'Keyboard', TextStyle.SETTINGS_LABEL);
keyboardText.setOrigin(0, 0);
keyboardText.setPositionRelative(headerBg, 97 + iconPreviousTab.width/6 - 4, 4);
this.optionsContainer = this.scene.add.container(0, 0);
this.settingLabels = [];
@ -92,8 +143,17 @@ export default class SettingsUiHandler extends UiHandler {
this.settingsContainer.add(headerBg);
this.settingsContainer.add(headerText);
this.settingsContainer.add(gamepadText);
this.settingsContainer.add(keyboardText);
this.settingsContainer.add(this.optionsBg);
this.settingsContainer.add(actionsBg);
this.settingsContainer.add(this.optionsContainer);
this.settingsContainer.add(iconNextTab)
this.settingsContainer.add(iconAction)
this.settingsContainer.add(iconCancel)
this.settingsContainer.add(iconPreviousTab)
this.settingsContainer.add(actionText)
this.settingsContainer.add(cancelText)
ui.add(this.settingsContainer);
@ -103,8 +163,28 @@ export default class SettingsUiHandler extends UiHandler {
this.settingsContainer.setVisible(false);
}
updateBindings(): void {
for (const settingName of Object.keys(this.navigationIcons)) {
if (settingName === 'BUTTON_HOME') {
this.navigationIcons[settingName].setTexture("keyboard");
this.navigationIcons[settingName].setFrame("T_Home_Key_Dark.png");
this.navigationIcons[settingName].alpha = 1;
continue
}
const icon = this.scene.inputController?.getIconForLatestInputRecorded(settingName);
if (icon) {
const type = this.scene.inputController?.getLastSourceType();
this.navigationIcons[settingName].setTexture(type);
this.navigationIcons[settingName].setFrame(icon);
this.navigationIcons[settingName].alpha = 1;
} else
this.navigationIcons[settingName].alpha = 0;
}
}
show(args: any[]): boolean {
super.show(args);
this.updateBindings();
const settings: object = localStorage.hasOwnProperty('settings') ? JSON.parse(localStorage.getItem('settings')) : {};
@ -132,7 +212,6 @@ export default class SettingsUiHandler extends UiHandler {
processInput(button: Button): boolean {
const ui = this.getUi();
// Defines the maximum number of rows that can be displayed on the screen.
const rowsToDisplay = 9;
let success = false;
@ -152,17 +231,17 @@ export default class SettingsUiHandler extends UiHandler {
} else {
// When at the top of the menu and pressing UP, move to the bottommost item.
// First, set the cursor to the last visible element, preparing for the scroll to the end.
const successA = this.setCursor(rowsToDisplay - 1);
const successA = this.setCursor(this.rowsToDisplay - 1);
// Then, adjust the scroll to display the bottommost elements of the menu.
const successB = this.setScrollCursor(this.optionValueLabels.length - rowsToDisplay);
const successB = this.setScrollCursor(this.optionValueLabels.length - this.rowsToDisplay);
success = successA && successB; // success is just there to play the little validation sound effect
}
break;
case Button.DOWN:
if (cursor < this.optionValueLabels.length - 1) {
if (this.cursor < rowsToDisplay - 1) // if the visual cursor is in the frame of 0 to 8
if (this.cursor < this.rowsToDisplay - 1) // if the visual cursor is in the frame of 0 to 8
success = this.setCursor(this.cursor + 1);
else if (this.scrollCursor < this.optionValueLabels.length - rowsToDisplay)
else if (this.scrollCursor < this.optionValueLabels.length - this.rowsToDisplay)
success = this.setScrollCursor(this.scrollCursor + 1);
} else {
// When at the bottom of the menu and pressing DOWN, move to the topmost item.
@ -182,6 +261,14 @@ export default class SettingsUiHandler extends UiHandler {
if (this.optionCursors[cursor] < this.optionValueLabels[cursor].length - 1)
success = this.setOptionCursor(cursor, this.optionCursors[cursor] + 1, true);
break;
case Button.CYCLE_FORM: // to the left
this.scene.ui.setMode(Mode.SETTINGS_KEYBOARD)
success = true;
break;
case Button.CYCLE_SHINY: // to the right
this.scene.ui.setMode(Mode.SETTINGS_GAMEPAD)
success = true;
break;
}
}
@ -255,7 +342,7 @@ export default class SettingsUiHandler extends UiHandler {
this.optionsContainer.setY(-16 * this.scrollCursor);
for (let s = 0; s < this.settingLabels.length; s++) {
const visible = s >= this.scrollCursor && s < this.scrollCursor + 9;
const visible = s >= this.scrollCursor && s < this.scrollCursor + this.rowsToDisplay;
this.settingLabels[s].setVisible(visible);
for (let option of this.optionValueLabels[s])
option.setVisible(visible);

View File

@ -24,6 +24,7 @@ export enum TextStyle {
MONEY,
SETTINGS_LABEL,
SETTINGS_SELECTED,
SETTINGS_LOCKED,
TOOLTIP_TITLE,
TOOLTIP_CONTENT,
MOVE_INFO_CONTENT
@ -110,6 +111,7 @@ function getTextStyleOptions(style: TextStyle, uiTheme: UiTheme, extraStyleOptio
case TextStyle.WINDOW_ALT:
case TextStyle.MESSAGE:
case TextStyle.SETTINGS_LABEL:
case TextStyle.SETTINGS_LOCKED:
case TextStyle.SETTINGS_SELECTED:
styleOptions.fontSize = languageSettings[lang]?.summaryFontSize || '96px';
break;
@ -187,6 +189,7 @@ export function getTextColor(textStyle: TextStyle, shadow?: boolean, uiTheme: Ui
case TextStyle.SUMMARY_GOLD:
case TextStyle.MONEY:
return !shadow ? '#e8e8a8' : '#a0a060';
case TextStyle.SETTINGS_LOCKED:
case TextStyle.SUMMARY_GRAY:
return !shadow ? '#a0a0a0' : '#636363';
case TextStyle.SUMMARY_GREEN:

View File

@ -1,6 +1,6 @@
import BattleScene from "../battle-scene";
import { DailyRunScoreboard } from "./daily-run-scoreboard";
import OptionSelectUiHandler from "./option-select-ui-handler";
import OptionSelectUiHandler from "./settings/option-select-ui-handler";
import { Mode } from "./ui";
import * as Utils from "../utils";
import { TextStyle, addTextObject } from "./text";

View File

@ -12,12 +12,13 @@ import SummaryUiHandler from './summary-ui-handler';
import StarterSelectUiHandler from './starter-select-ui-handler';
import EvolutionSceneHandler from './evolution-scene-handler';
import TargetSelectUiHandler from './target-select-ui-handler';
import SettingsUiHandler from './settings-ui-handler';
import SettingsUiHandler from './settings/settings-ui-handler';
import SettingsGamepadUiHandler from "./settings/settings-gamepad-ui-handler";
import { TextStyle, addTextObject } from './text';
import AchvBar from './achv-bar';
import MenuUiHandler from './menu-ui-handler';
import AchvsUiHandler from './achvs-ui-handler';
import OptionSelectUiHandler from './option-select-ui-handler';
import OptionSelectUiHandler from './settings/option-select-ui-handler';
import EggHatchSceneHandler from './egg-hatch-scene-handler';
import EggListUiHandler from './egg-list-ui-handler';
import EggGachaUiHandler from './egg-gacha-ui-handler';
@ -36,6 +37,9 @@ import UnavailableModalUiHandler from './unavailable-modal-ui-handler';
import OutdatedModalUiHandler from './outdated-modal-ui-handler';
import SessionReloadModalUiHandler from './session-reload-modal-ui-handler';
import {Button} from "../enums/buttons";
import GamepadBindingUiHandler from "./settings/gamepad-binding-ui-handler";
import SettingsKeyboardUiHandler from "#app/ui/settings/settings-keyboard-ui-handler";
import KeyboardBindingUiHandler from "#app/ui/settings/keyboard-binding-ui-handler";
export enum Mode {
MESSAGE,
@ -56,6 +60,10 @@ export enum Mode {
MENU,
MENU_OPTION_SELECT,
SETTINGS,
SETTINGS_GAMEPAD,
GAMEPAD_BINDING,
SETTINGS_KEYBOARD,
KEYBOARD_BINDING,
ACHIEVEMENTS,
GAME_STATS,
VOUCHERS,
@ -86,7 +94,11 @@ const noTransitionModes = [
Mode.OPTION_SELECT,
Mode.MENU,
Mode.MENU_OPTION_SELECT,
Mode.GAMEPAD_BINDING,
Mode.KEYBOARD_BINDING,
Mode.SETTINGS,
Mode.SETTINGS_GAMEPAD,
Mode.SETTINGS_KEYBOARD,
Mode.ACHIEVEMENTS,
Mode.GAME_STATS,
Mode.VOUCHERS,
@ -137,6 +149,10 @@ export default class UI extends Phaser.GameObjects.Container {
new MenuUiHandler(scene),
new OptionSelectUiHandler(scene, Mode.MENU_OPTION_SELECT),
new SettingsUiHandler(scene),
new SettingsGamepadUiHandler(scene),
new GamepadBindingUiHandler(scene),
new SettingsKeyboardUiHandler(scene),
new KeyboardBindingUiHandler(scene),
new AchvsUiHandler(scene),
new GameStatsUiHandler(scene),
new VouchersUiHandler(scene),

View File

@ -337,3 +337,46 @@ export function rgbHexToRgba(hex: string) {
export function rgbaToInt(rgba: integer[]): integer {
return (rgba[0] << 24) + (rgba[1] << 16) + (rgba[2] << 8) + rgba[3];
}
/**
* Truncate a string to a specified maximum length and add an ellipsis if it exceeds that length.
*
* @param str - The string to be truncated.
* @param maxLength - The maximum length of the truncated string, defaults to 10.
* @returns The truncated string with an ellipsis if it was longer than maxLength.
*/
export function truncateString(str: String, maxLength: number = 10) {
// Check if the string length exceeds the maximum length
if (str.length > maxLength) {
// Truncate the string and add an ellipsis
return str.slice(0, maxLength - 3) + "..."; // Subtract 3 to accommodate the ellipsis
}
// Return the original string if it does not exceed the maximum length
return str;
}
/**
* Perform a deep copy of an object.
*
* @param values - The object to be deep copied.
* @returns A new object that is a deep copy of the input.
*/
export function deepCopy(values: object): object {
// Convert the object to a JSON string and parse it back to an object to perform a deep copy
return JSON.parse(JSON.stringify(values));
}
/**
* Convert a space-separated string into a capitalized and underscored string.
*
* @param input - The string to be converted.
* @returns The converted string with words capitalized and separated by underscores.
*/
export function reverseValueToKeySetting(input) {
// Split the input string into an array of words
const words = input.split(' ');
// Capitalize the first letter of each word and convert the rest to lowercase
const capitalizedWords = words.map(word => word.charAt(0).toUpperCase() + word.slice(1).toLowerCase());
// Join the capitalized words with underscores and return the result
return capitalizedWords.join('_');
}