pull/685/merge
Greenlamp2 2024-05-15 23:15:14 +00:00 committed by GitHub
commit 6e842aa3b9
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
43 changed files with 5008 additions and 290 deletions

View File

@ -146,7 +146,9 @@ body {
margin-left: 10%; 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; 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 SoundFade from 'phaser3-rex-plugins/plugins/soundfade';
import { pokemonPrevolutions } from './data/pokemon-evolutions'; import { pokemonPrevolutions } from './data/pokemon-evolutions';
import PokeballTray from './ui/pokeball-tray'; 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 { Species } from './data/enums/species';
import InvertPostFX from './pipelines/invert'; import InvertPostFX from './pipelines/invert';
import { Achv, ModifierAchv, MoneyAchv, achvs } from './system/achv'; import { Achv, ModifierAchv, MoneyAchv, achvs } from './system/achv';
@ -119,7 +116,6 @@ export default class BattleScene extends SceneBase {
public fusionPaletteSwaps: boolean = true; public fusionPaletteSwaps: boolean = true;
public enableTouchControls: boolean = false; public enableTouchControls: boolean = false;
public enableVibration: boolean = false; public enableVibration: boolean = false;
public abSwapped: boolean = false;
public disableMenu: boolean = false; public disableMenu: boolean = false;

View File

@ -0,0 +1,283 @@
import {Button} from "#app/enums/buttons";
import {SettingKeyboard} from "#app/system/settings-keyboard";
const cfg_keyboard_azerty = {
padID: 'keyboard',
padType: 'default',
gamepadMapping: {
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
},
main: [],
alt: [],
};
export default cfg_keyboard_azerty;

View File

@ -0,0 +1,136 @@
export function getKeyWithKeycode(config, keycode) {
return Object.keys(config.gamepadMapping).find(key => config.gamepadMapping[key] === keycode);
}
export function getSettingNameWithKeycode(config, keycode) {
const key = getKeyWithKeycode(config, keycode);
return config.custom[key];
}
export function getIconWithKeycode(config, keycode) {
const key = getKeyWithKeycode(config, keycode);
return config.icons[key];
}
export function getButtonWithKeycode(config, keycode) {
const settingName = getSettingNameWithKeycode(config, keycode);
return config.settings[settingName];
}
export function getKeycodeWithKey(config, key) {
return config.gamepadMapping[key]
}
export function getKeyWithSettingName(config, settingName) {
return Object.keys(config.custom).find(key => config.custom[key] === settingName);
}
export function getSettingNameWithKey(config, key) {
return config.custom[key]
}
export function getIconWithKey(config, key) {
return config.icons[key]
}
export function getIconSpecialCase(config, keycode, settingName) {
const potentialKey = isAlreadyBinded(config, keycode, settingName);
if (potentialKey) return getIconWithKey(config, potentialKey);
return null;
}
export function getButtonWithSettingName(config, settingName) {
return config.settings[settingName];
}
export function getButtonWithKey(config, key) {
const settingName = config.custom[key];
return getButtonWithSettingName(config, settingName);
}
export function getIconWithSettingName(config, settingName) {
const key = getKeyWithSettingName(config, settingName);
return getIconWithKey(config, key);
}
export function getKeycodeWithSettingName(config, settingName) {
const key = getKeyWithSettingName(config, settingName);
return getKeycodeWithKey(config, key);
}
export function getSettingNameWithButton(config, button, alt= false) {
return Object.keys(config.settings).find(k => {
const a = !alt && !k.includes("ALT_");
const b = alt && k.includes("ALT_");
const c = config.settings[k] === button;
return (a || b) && c;
});
}
export function getKeyWithButton(config, button, alt= false) {
const settingName = getSettingNameWithButton(config, button, alt);
return getKeyWithSettingName(config, settingName);
}
export function getKeycodeWithButton(config, button, alt= false) {
const key = getKeyWithButton(config, button, alt);
return getKeycodeWithKey(config, key);
}
export function getIconWithButton(config, button, alt= false) {
const key = getKeyWithButton(config, button, alt);
return getIconWithKey(config, key);
}
export function isAlreadyBinded(config, keycode, settingNameTarget) {
const key = getKeyWithKeycode(config, keycode);
const isMain = config.main.includes(key);
const isTargetMain = !settingNameTarget.includes("ALT_");
const potentialExistingButton = getButtonWithSettingName(config, settingNameTarget);
const potentialExistingKey = getKeyWithButton(config, potentialExistingButton, !isMain);
if (potentialExistingKey && isMain !== isTargetMain) return potentialExistingKey;
return null;
}
export function swap(config, settingNameTarget, keycode) {
// 2 alt can't do the same thing
// 2 main can't do the same thing
// can't swap an alt if another alt is already doing the same
// can't swap a main if another main is already doing the same
const isDeleted = !getKeyWithSettingName(config, settingNameTarget);
if (isDeleted) {
const new_key = getKeyWithKeycode(config, keycode);
config.custom[new_key] = settingNameTarget;
return;
}
const potentialExistingKey = isAlreadyBinded(config, keycode, settingNameTarget);
const prev_key = potentialExistingKey || 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;
regenerateIdentifiers(config);
}
export function deleteBind(config, settingName) {
const key = getKeyWithSettingName(config, settingName);
config.custom[key] = -1;
regenerateIdentifiers(config);
}
export function regenerateIdentifiers(config) {
config.main = Object.keys(config.custom).filter(key => {
const value = config.custom[key]
return value !== -1 && !value.includes("ALT_");
});
config.alt = Object.keys(config.custom).filter(key => {
const value = config.custom[key]
return value !== -1 && value.includes("ALT_");
});
}

View File

@ -1,9 +1,12 @@
import {SettingGamepad} from "../system/settings-gamepad";
import {Button} from "../enums/buttons";
/** /**
* Dualshock mapping * Dualshock mapping
*/ */
const pad_dualshock = { const pad_dualshock = {
padID: 'Dualshock', padID: 'Dualshock',
padType: 'Sony', padType: 'dualshock',
gamepadMapping: { gamepadMapping: {
RC_S: 0, RC_S: 0,
RC_E: 1, RC_E: 1,
@ -21,9 +24,67 @@ const pad_dualshock = {
LC_S: 13, LC_S: 13,
LC_W: 14, LC_W: 14,
LC_E: 15, LC_E: 15,
MENU: 16,
TOUCH: 17 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,
},
main: [],
alt: [],
}; };
export default pad_dualshock; export default pad_dualshock;

View File

@ -1,9 +1,12 @@
import {SettingGamepad} from "../system/settings-gamepad";
import {Button} from "../enums/buttons";
/** /**
* Generic pad mapping * Generic pad mapping
*/ */
const pad_generic = { const pad_generic = {
padID: 'Generic', padID: 'Generic',
padType: 'generic', padType: 'xbox',
gamepadMapping: { gamepadMapping: {
RC_S: 0, RC_S: 0,
RC_E: 1, RC_E: 1,
@ -22,6 +25,62 @@ const pad_generic = {
LC_W: 14, LC_W: 14,
LC_E: 15 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
},
main: [],
alt: [],
}; };
export default pad_generic; export default pad_generic;

View File

@ -1,3 +1,6 @@
import {SettingGamepad} from "../system/settings-gamepad";
import {Button} from "../enums/buttons";
/** /**
* 081f-e401 - UnlicensedSNES * 081f-e401 - UnlicensedSNES
*/ */
@ -17,7 +20,59 @@ const pad_unlicensedSNES = {
LC_S: 13, LC_S: 13,
LC_W: 14, LC_W: 14,
LC_E: 15 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
},
main: [],
alt: [],
}; };
export default pad_unlicensedSNES; export default pad_unlicensedSNES;

View File

@ -1,3 +1,6 @@
import {SettingGamepad} from "../system/settings-gamepad";
import {Button} from "#app/enums/buttons";
/** /**
* Generic pad mapping * Generic pad mapping
*/ */
@ -20,9 +23,64 @@ const pad_xbox360 = {
LC_N: 12, LC_N: 12,
LC_S: 13, LC_S: 13,
LC_W: 14, LC_W: 14,
LC_E: 15, LC_E: 15
MENU: 16
}, },
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
},
main: [],
alt: [],
}; };
export default pad_xbox360; export default pad_xbox360;

View File

@ -8,8 +8,8 @@ export enum Button {
CANCEL, CANCEL,
MENU, MENU,
STATS, STATS,
CYCLE_SHINY, CYCLE_SHINY, // CYCLE_SHINY
CYCLE_FORM, CYCLE_FORM, // CYCLE_FORM
CYCLE_GENDER, CYCLE_GENDER,
CYCLE_ABILITY, CYCLE_ABILITY,
CYCLE_NATURE, CYCLE_NATURE,

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

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

View File

@ -1,24 +1,43 @@
import Phaser, {Time} from "phaser";
import * as Utils from "./utils"; import * as Utils from "./utils";
import {deepCopy} from "./utils";
import {initTouchControls} from './touch-controls'; import {initTouchControls} from './touch-controls';
import pad_generic from "./configs/pad_generic"; import pad_generic from "./configs/pad_generic";
import pad_unlicensedSNES from "./configs/pad_unlicensedSNES"; import pad_unlicensedSNES from "./configs/pad_unlicensedSNES";
import pad_xbox360 from "./configs/pad_xbox360"; import pad_xbox360 from "./configs/pad_xbox360";
import pad_dualshock from "./configs/pad_dualshock"; import pad_dualshock from "./configs/pad_dualshock";
import {Button} from "./enums/buttons"; 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 {getButtonWithKeycode, regenerateIdentifiers, swap} from "#app/configs/configHandler";
export interface GamepadMapping { export interface GamepadMapping {
[key: string]: number; [key: string]: number;
} }
export interface GamepadConfig { export interface IconsMapping {
[key: string]: string;
}
export interface SettingMapping {
[key: string]: string;
}
export interface MappingLayout {
[key: string]: Button;
}
export interface InterfaceConfig {
padID: string; padID: string;
padType: string; padType: string;
gamepadMapping: GamepadMapping; gamepadMapping: GamepadMapping;
} ogIcons: IconsMapping;
icons: IconsMapping;
export interface ActionGamepadMapping { setting: SettingMapping;
[key: string]: Button; default: MappingLayout;
custom: MappingLayout;
} }
const repeatInputDelayMillis = 250; const repeatInputDelayMillis = 250;
@ -47,16 +66,25 @@ const repeatInputDelayMillis = 250;
*/ */
export class InputsController { export class InputsController {
private buttonKeys: Phaser.Input.Keyboard.Key[][]; 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 scene: Phaser.Scene;
private events: Phaser.Events.EventEmitter;
private buttonLock: Button; private buttonLock: Button;
private buttonLock2: Button; private buttonLock2: Button;
private interactions: Map<Button, Map<string, boolean>> = new Map(); private interactions: Map<Button, Map<string, boolean>> = new Map();
private time: Time; private time: Phaser.Time.Clock;
private player: Map<String, GamepadMapping> = new Map(); private configs: Map<string, InterfaceConfig> = new Map();
private gamepadSupport: boolean = true; 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. * Initializes a new instance of the game control system, setting up initial state and configurations.
@ -69,10 +97,15 @@ export class InputsController {
* Specific buttons like MENU and STATS are set not to repeat their actions. * Specific buttons like MENU and STATS are set not to repeat their actions.
* It concludes by calling the `init` method to complete the setup. * It concludes by calling the `init` method to complete the setup.
*/ */
constructor(scene: Phaser.Scene) { constructor(scene: Phaser.Scene) {
this.scene = scene; this.scene = scene;
this.time = this.scene.time; this.time = this.scene.time;
this.buttonKeys = []; this.buttonKeys = [];
this.selectedDevice = {
[Device.GAMEPAD]: null,
[Device.KEYBOARD]: 'default'
}
for (const b of Utils.getEnumValues(Button)) { for (const b of Utils.getEnumValues(Button)) {
this.interactions[b] = { this.interactions[b] = {
@ -96,15 +129,25 @@ export class InputsController {
* Additionally, it manages the game's behavior when it loses focus to prevent unwanted game actions during this state. * Additionally, it manages the game's behavior when it loses focus to prevent unwanted game actions during this state.
*/ */
init(): void { init(): void {
this.events = new Phaser.Events.EventEmitter(); this.events = this.scene.game.events;
if (localStorage.hasOwnProperty('selectedDevice')) {
this.selectedDevice = JSON.parse(localStorage.getItem('selectedDevice'));
}
this.scene.game.events.on(Phaser.Core.Events.BLUR, () => { this.scene.game.events.on(Phaser.Core.Events.BLUR, () => {
this.loseFocus() this.loseFocus()
}) })
if (typeof this.scene.input.gamepad !== 'undefined') { if (typeof this.scene.input.gamepad !== 'undefined') {
this.scene.input.gamepad.on('connected', function (thisGamepad) { this.scene.input.gamepad.on('connected', function (thisGamepad) {
if (!thisGamepad) return;
this.refreshGamepads(); this.refreshGamepads();
this.setupGamepad(thisGamepad); this.setupGamepad(thisGamepad);
this.onReconnect(thisGamepad);
}, this);
this.scene.input.gamepad.on('disconnected', function (thisGamepad) {
this.onDisconnect(thisGamepad); // when a gamepad is disconnected
}, this); }, this);
// Check to see if the gamepad has already been setup by the browser // Check to see if the gamepad has already been setup by the browser
@ -118,10 +161,12 @@ export class InputsController {
this.scene.input.gamepad.on('down', this.gamepadButtonDown, this); this.scene.input.gamepad.on('down', this.gamepadButtonDown, this);
this.scene.input.gamepad.on('up', this.gamepadButtonUp, 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);
} }
initTouchControls(this.events);
// Keyboard // Keyboard
this.setupKeyboardControls(); // this.setupKeyboardControls();
} }
/** /**
@ -152,30 +197,49 @@ export class InputsController {
} }
} }
/**
* 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)
}
setChosenKeyboardLayout(layoutKeyboard: String): void {
this.deactivatePressedKey();
this.initChosenLayoutKeyboard(layoutKeyboard)
}
/** /**
* Updates the interaction handling by processing input states. * 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 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 * It handles special conditions such as the absence of gamepad support or mismatches between the source of the input and
* The method iterates over all possible buttons, checking for specific conditions such as: * the currently chosen gamepad. It also respects the paused state of updates to prevent unwanted input processing.
* - If the button is registered in the `interactions` dictionary.
* - If the button has been held down long enough.
* - If the button is currently pressed.
* *
* Special handling is applied if gamepad support is disabled but a gamepad source is still triggering inputs, * If an interaction is valid and should be processed, it emits an 'input_down' event with details of the interaction.
* preventing potential infinite loops by removing the last processed movement time for the button.
*/ */
update(): void { update(): void {
for (const b of Utils.getEnumValues(Button).reverse()) { for (const b of Utils.getEnumValues(Button).reverse()) {
if ( if (
this.interactions.hasOwnProperty(b) && this.interactions.hasOwnProperty(b) &&
this.repeatInputDurationJustPassed(b) && this.repeatInputDurationJustPassed(b as Button) &&
this.interactions[b].isPressed this.interactions[b].isPressed
) { ) {
// Prevents repeating button interactions when gamepad support is disabled. // 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. // Deletes the last interaction for a button if gamepad is disabled.
this.delLastProcessedMovementTime(b); this.delLastProcessedMovementTime(b as Button);
return; return;
} }
// Emits an event for the button press. // Emits an event for the button press.
@ -183,25 +247,93 @@ export class InputsController {
controller_type: this.interactions[b].source, controller_type: this.interactions[b].source,
button: b, 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();
localStorage.setItem('selectedDevice', JSON.stringify(this.selectedDevice));
const handler = this.scene.ui?.handlers[Mode.SETTINGS_GAMEPAD] as SettingsGamepadUiHandler;
handler && handler.updateChosenGamepadDisplay()
}
initChosenLayoutKeyboard(layoutKeyboard?: String): void {
if (layoutKeyboard)
this.selectedDevice[Device.KEYBOARD] = layoutKeyboard.toLowerCase();
localStorage.setItem('selectedDevice', JSON.stringify(this.selectedDevice));
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 * @param thisGamepad The gamepad that has been reconnected.
* 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 onReconnect(thisGamepad: Phaser.Input.Gamepad.Gamepad): void {
* that the gamepad controls are correctly mapped to in-game actions. 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 { setupGamepad(thisGamepad: Phaser.Input.Gamepad.Gamepad): void {
let gamepadID = thisGamepad.id.toLowerCase(); const allGamepads = this.getGamepadsName();
const mappedPad = this.mapGamepad(gamepadID); for (const gamepad of allGamepads) {
this.player['mapping'] = mappedPad.gamepadMapping; 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.initChosenGamepad(this.selectedDevice[Device.GAMEPAD])
}
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])
} }
/** /**
@ -223,84 +355,81 @@ export class InputsController {
} }
} }
/** checkIfKeyboardIsInit(): void {
* Retrieves the current gamepad mapping for in-game actions. if (!this.getActiveConfig(Device.KEYBOARD)?.padID)
* this.setupKeyboard();
* @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.
*/
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; keyboardKeyDown(event): void {
const keyDown = event.keyCode;
this.checkIfKeyboardIsInit();
if (this.keys.includes(keyDown)) return;
this.keys.push(keyDown);
const buttonDown = getButtonWithKeycode(this.getActiveConfig(Device.KEYBOARD), keyDown);
this.lastSource = 'keyboard';
if (buttonDown !== undefined) {
this.events.emit('input_down', {
controller_type: 'keyboard',
button: buttonDown,
});
this.setLastProcessedMovementTime(buttonDown, 'keyboard', this.selectedDevice[Device.KEYBOARD]);
}
}
keyboardKeyUp(event): void {
const keyDown = event.keyCode;
this.keys = this.keys.filter(k => k !== keyDown);
this.checkIfKeyboardIsInit()
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 the 'down' event for gamepad buttons, emitting appropriate events and updating the interaction state. * 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 press occurred. * @param pad The gamepad on which the button was pressed.
* @param button - The button that was pressed. * @param button The specific button that was pressed.
* @param value - The value associated with the button press, typically indicating pressure or degree of activation. * @param value The intensity or value of the button press, if applicable.
*
* @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.
*/ */
gamepadButtonDown(pad: Phaser.Input.Gamepad.Gamepad, button: Phaser.Input.Gamepad.Button, value: number): void { gamepadButtonDown(pad: Phaser.Input.Gamepad.Gamepad, button: Phaser.Input.Gamepad.Button, value: number): void {
if (!this.gamepadSupport) return; if (!this.configs[this.selectedDevice[Device.KEYBOARD]]?.padID)
const actionMapping = this.getActionGamepadMapping(); this.setupKeyboard();
const buttonDown = actionMapping.hasOwnProperty(button.index) && actionMapping[button.index]; if (!pad) return;
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);
this.lastSource = 'gamepad';
if (buttonDown !== undefined) { if (buttonDown !== undefined) {
this.events.emit('input_down', { this.events.emit('input_down', {
controller_type: 'gamepad', controller_type: 'gamepad',
button: buttonDown, 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 pad The gamepad from which the button was released.
* @param button - The button that was released. * @param button The specific button that was released.
* @param value - The value associated with the button release, typically indicating pressure or degree of deactivation. * @param value The intensity or value of the button release, if applicable.
*
* @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.
*/ */
gamepadButtonUp(pad: Phaser.Input.Gamepad.Gamepad, button: Phaser.Input.Gamepad.Button, value: number): void { gamepadButtonUp(pad: Phaser.Input.Gamepad.Gamepad, button: Phaser.Input.Gamepad.Button, value: number): void {
if (!this.gamepadSupport) return; if (!pad) return;
const actionMapping = this.getActionGamepadMapping(); if (!this.gamepadSupport || pad.id.toLowerCase() !== this.selectedDevice[Device.GAMEPAD]) return;
const buttonUp = actionMapping.hasOwnProperty(button.index) && actionMapping[button.index]; const buttonUp = getButtonWithKeycode(this.getActiveConfig(Device.GAMEPAD), button.index);
if (buttonUp !== undefined) { if (buttonUp !== undefined) {
this.events.emit('input_up', { this.events.emit('input_up', {
controller_type: 'gamepad', controller_type: 'gamepad',
@ -311,112 +440,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 * @param id The identifier string of the gamepad.
* This method sets up keyboard bindings for game controls using Phaser's `KeyCodes`. Each game action, represented * @returns InterfaceConfig The configuration object corresponding to the identified gamepad type.
* 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.
*/ */
setupKeyboardControls(): void { getConfig(id: string): InterfaceConfig {
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 {
id = id.toLowerCase(); id = id.toLowerCase();
if (id.includes('081f') && id.includes('e401')) { if (id.includes('081f') && id.includes('e401')) {
@ -430,6 +461,13 @@ export class InputsController {
return pad_generic; return pad_generic;
} }
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 * repeatInputDurationJustPassed returns true if @param button has been held down long
* enough to fire a repeated input. A button must claim the buttonLock before * enough to fire a repeated input. A button must claim the buttonLock before
@ -457,12 +495,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. * 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; if (!this.interactions.hasOwnProperty(button)) return;
this.setButtonLock(button); this.setButtonLock(button);
this.interactions[button].pressTime = this.time.now; this.interactions[button].pressTime = this.time.now;
this.interactions[button].isPressed = true; this.interactions[button].isPressed = true;
this.interactions[button].source = source; this.interactions[button].source = source;
this.interactions[button].sourceName = sourceName.toLowerCase();
} }
/** /**
@ -485,6 +524,7 @@ export class InputsController {
this.interactions[button].pressTime = null; this.interactions[button].pressTime = null;
this.interactions[button].isPressed = false; this.interactions[button].isPressed = false;
this.interactions[button].source = null; this.interactions[button].source = null;
this.interactions[button].sourceName = null;
} }
/** /**
@ -506,6 +546,7 @@ export class InputsController {
* This method is typically called when needing to ensure that all inputs are neutralized. * This method is typically called when needing to ensure that all inputs are neutralized.
*/ */
deactivatePressedKey(): void { deactivatePressedKey(): void {
this.pauseUpdate = true;
this.releaseButtonLock(this.buttonLock); this.releaseButtonLock(this.buttonLock);
this.releaseButtonLock(this.buttonLock2); this.releaseButtonLock(this.buttonLock2);
for (const b of Utils.getEnumValues(Button)) { for (const b of Utils.getEnumValues(Button)) {
@ -513,8 +554,10 @@ export class InputsController {
this.interactions[b].pressTime = null; this.interactions[b].pressTime = null;
this.interactions[b].isPressed = false; this.interactions[b].isPressed = false;
this.interactions[b].source = null; this.interactions[b].source = null;
this.interactions[b].sourceName = null;
} }
} }
setTimeout(() => this.pauseUpdate = false, 500);
} }
/** /**
@ -564,4 +607,36 @@ export class InputsController {
if (this.buttonLock === button) this.buttonLock = null; if (this.buttonLock === button) this.buttonLock = null;
else if (this.buttonLock2 === button) this.buttonLock2 = 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;
}
/**
* Injects a custom mapping configuration into the gamepad configuration for a specific gamepad.
* If the gamepad does not have an existing configuration, it initializes one first.
*
* @param gamepadName The identifier of the gamepad to configure.
* @param customMappings The custom mapping configuration to apply to the gamepad.
*/
injectConfig(selectedDevice: string, mappingConfigs): void {
if (!this.configs[selectedDevice]) this.configs[selectedDevice] = {};
this.configs[selectedDevice].custom = mappingConfigs.custom;
this.configs[selectedDevice].main = mappingConfigs.main;
this.configs[selectedDevice].alt = mappingConfigs.alt;
regenerateIdentifiers(this.configs[selectedDevice]);
}
swapBinding(config, settingName, pressedButton): void {
this.pauseUpdate = true;
swap(config, settingName, pressedButton);
setTimeout(() => this.pauseUpdate = false, 500);
}
} }

View File

@ -215,6 +215,14 @@ export class LoadingScene extends SceneBase {
this.loadAtlas(`pokemon_icons_${i}v`, ''); 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('select');
this.loadSe('menu_open'); this.loadSe('menu_open');
this.loadSe('hit'); this.loadSe('hit');

View File

@ -30,6 +30,9 @@ import { allMoves } from "../data/move";
import { TrainerVariant } from "../field/trainer"; import { TrainerVariant } from "../field/trainer";
import { OutdatedPhase, ReloadSessionPhase } from "#app/phases"; import { OutdatedPhase, ReloadSessionPhase } from "#app/phases";
import { Variant, variantData } from "#app/data/variant"; 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 const saveKey = 'x0i2O7WRiANTqPmZ'; // Temporary; secure encryption is not yet necessary
@ -241,6 +244,8 @@ export class GameData {
constructor(scene: BattleScene) { constructor(scene: BattleScene) {
this.scene = scene; this.scene = scene;
this.loadSettings(); this.loadSettings();
this.loadGamepadSettings();
this.loadMappingConfigs();
this.trainerId = Utils.randInt(65536); this.trainerId = Utils.randInt(65536);
this.secretId = Utils.randInt(65536); this.secretId = Utils.randInt(65536);
this.starterData = {}; this.starterData = {};
@ -538,11 +543,60 @@ export class GameData {
settings[s] = valueIndex; settings[s] = valueIndex;
}); });
localStorage.setItem('settings', JSON.stringify(settings)); localStorage.setItem('settings', JSON.stringify(settings));
return true; return true;
} }
public saveMappingConfigs(gamepadName: string, config): boolean {
const key = gamepadName.toLowerCase();
let mappingConfigs: object = {};
if (localStorage.hasOwnProperty('mappingConfigs'))
mappingConfigs = JSON.parse(localStorage.getItem('mappingConfigs'));
if (!mappingConfigs[key]) mappingConfigs[key] = {};
mappingConfigs[key].custom = config.custom;
localStorage.setItem('mappingConfigs', JSON.stringify(mappingConfigs));
return true;
}
public loadMappingConfigs(): boolean {
if (!localStorage.hasOwnProperty('mappingConfigs'))
return false;
const mappingConfigs = JSON.parse(localStorage.getItem('mappingConfigs'));
for (const key of Object.keys(mappingConfigs))
this.scene.inputController.injectConfig(key, mappingConfigs[key]);
}
public saveGamepadSetting(setting: SettingGamepad, valueIndex: integer): boolean {
let settingsGamepad: object = {};
if (localStorage.hasOwnProperty('settingsGamepad'))
settingsGamepad = JSON.parse(localStorage.getItem('settingsGamepad'));
setSettingGamepad(this.scene, setting as SettingGamepad, valueIndex);
Object.keys(settingGamepadDefaults).forEach(s => {
if (s === setting)
settingsGamepad[s] = valueIndex;
});
localStorage.setItem('settingsGamepad', JSON.stringify(settingsGamepad));
return true;
}
public saveKeyboardSetting(setting: SettingKeyboard, valueIndex: integer): boolean {
let settingsKeyboard: object = {};
if (localStorage.hasOwnProperty('settingsKeyboard'))
settingsKeyboard = JSON.parse(localStorage.getItem('settingsKeyboard'));
setSettingKeyboard(this.scene, setting as SettingKeyboard, valueIndex);
Object.keys(settingKeyboardDefaults).forEach(s => {
if (s === setting)
settingsKeyboard[s] = valueIndex;
});
localStorage.setItem('settingsKeyboard', JSON.stringify(settingsKeyboard));
return true;
}
private loadSettings(): boolean { private loadSettings(): boolean {
Object.values(Setting).map(setting => setting as Setting).forEach(setting => setSetting(this.scene, setting, settingDefaults[setting])); Object.values(Setting).map(setting => setting as Setting).forEach(setting => setSetting(this.scene, setting, settingDefaults[setting]));
@ -555,6 +609,17 @@ export class GameData {
setSetting(this.scene, setting as Setting, settings[setting]); 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 { public saveTutorialFlag(tutorial: Tutorial, flag: boolean): boolean {
let tutorials: object = {}; let tutorials: object = {};
if (localStorage.hasOwnProperty('tutorials')) if (localStorage.hasOwnProperty('tutorials'))

View File

@ -0,0 +1,138 @@
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";
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()}`, 'Change'],
[SettingGamepad.Button_Down]: [`KEY ${Button.DOWN.toString()}`, 'Change'],
[SettingGamepad.Button_Left]: [`KEY ${Button.LEFT.toString()}`, 'Change'],
[SettingGamepad.Button_Right]: [`KEY ${Button.RIGHT.toString()}`, 'Change'],
[SettingGamepad.Button_Action]: [`KEY ${Button.ACTION.toString()}`, 'Change'],
[SettingGamepad.Button_Cancel]: [`KEY ${Button.CANCEL.toString()}`, 'Change'],
[SettingGamepad.Button_Menu]: [`KEY ${Button.MENU.toString()}`, 'Change'],
[SettingGamepad.Button_Stats]: [`KEY ${Button.STATS.toString()}`, 'Change'],
[SettingGamepad.Button_Cycle_Form]: [`KEY ${Button.CYCLE_FORM.toString()}`, 'Change'],
[SettingGamepad.Button_Cycle_Shiny]: [`KEY ${Button.CYCLE_SHINY.toString()}`, 'Change'],
[SettingGamepad.Button_Cycle_Gender]: [`KEY ${Button.CYCLE_GENDER.toString()}`, 'Change'],
[SettingGamepad.Button_Cycle_Ability]: [`KEY ${Button.CYCLE_ABILITY.toString()}`, 'Change'],
[SettingGamepad.Button_Cycle_Nature]: [`KEY ${Button.CYCLE_NATURE.toString()}`, 'Change'],
[SettingGamepad.Button_Cycle_Variant]: [`KEY ${Button.CYCLE_VARIANT.toString()}`, 'Change'],
[SettingGamepad.Button_Speed_Up]: [`KEY ${Button.SPEED_UP.toString()}`, 'Change'],
[SettingGamepad.Button_Slow_Down]: [`KEY ${Button.SLOW_DOWN.toString()}`, 'Change'],
[SettingGamepad.Button_Submit]: [`KEY ${Button.SUBMIT.toString()}`, 'Change']
};
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 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),
handler: () => changeGamepadHandler(g)
})), {
label: 'Cancel',
handler: cancelHandler,
}]
});
return false;
}
}
break;
}
return true;
}

View File

@ -0,0 +1,194 @@
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()}`, 'Change'],
[SettingKeyboard.Alt_Button_Up]: [`KEY ${Button.UP.toString()}`, 'Change'],
[SettingKeyboard.Button_Down]: [`KEY ${Button.DOWN.toString()}`, 'Change'],
[SettingKeyboard.Alt_Button_Down]: [`KEY ${Button.DOWN.toString()}`, 'Change'],
[SettingKeyboard.Button_Left]: [`KEY ${Button.LEFT.toString()}`, 'Change'],
[SettingKeyboard.Alt_Button_Left]: [`KEY ${Button.LEFT.toString()}`, 'Change'],
[SettingKeyboard.Button_Right]: [`KEY ${Button.RIGHT.toString()}`, 'Change'],
[SettingKeyboard.Alt_Button_Right]: [`KEY ${Button.RIGHT.toString()}`, 'Change'],
[SettingKeyboard.Button_Action]: [`KEY ${Button.ACTION.toString()}`, 'Change'],
[SettingKeyboard.Alt_Button_Action]: [`KEY ${Button.ACTION.toString()}`, 'Change'],
[SettingKeyboard.Button_Cancel]: [`KEY ${Button.CANCEL.toString()}`, 'Change'],
[SettingKeyboard.Alt_Button_Cancel]: [`KEY ${Button.CANCEL.toString()}`, 'Change'],
[SettingKeyboard.Button_Menu]: [`KEY ${Button.MENU.toString()}`, 'Change'],
[SettingKeyboard.Alt_Button_Menu]: [`KEY ${Button.MENU.toString()}`, 'Change'],
[SettingKeyboard.Button_Stats]: [`KEY ${Button.STATS.toString()}`, 'Change'],
[SettingKeyboard.Alt_Button_Stats]: [`KEY ${Button.STATS.toString()}`, 'Change'],
[SettingKeyboard.Button_Cycle_Form]: [`KEY ${Button.CYCLE_FORM.toString()}`, 'Change'],
[SettingKeyboard.Alt_Button_Cycle_Form]: [`KEY ${Button.CYCLE_FORM.toString()}`, 'Change'],
[SettingKeyboard.Button_Cycle_Shiny]: [`KEY ${Button.CYCLE_SHINY.toString()}`, 'Change'],
[SettingKeyboard.Alt_Button_Cycle_Shiny]: [`KEY ${Button.CYCLE_SHINY.toString()}`, 'Change'],
[SettingKeyboard.Button_Cycle_Gender]: [`KEY ${Button.CYCLE_GENDER.toString()}`, 'Change'],
[SettingKeyboard.Alt_Button_Cycle_Gender]: [`KEY ${Button.CYCLE_GENDER.toString()}`, 'Change'],
[SettingKeyboard.Button_Cycle_Ability]: [`KEY ${Button.CYCLE_ABILITY.toString()}`, 'Change'],
[SettingKeyboard.Alt_Button_Cycle_Ability]: [`KEY ${Button.CYCLE_ABILITY.toString()}`, 'Change'],
[SettingKeyboard.Button_Cycle_Nature]: [`KEY ${Button.CYCLE_NATURE.toString()}`, 'Change'],
[SettingKeyboard.Alt_Button_Cycle_Nature]: [`KEY ${Button.CYCLE_NATURE.toString()}`, 'Change'],
[SettingKeyboard.Button_Cycle_Variant]: [`KEY ${Button.CYCLE_VARIANT.toString()}`, 'Change'],
[SettingKeyboard.Alt_Button_Cycle_Variant]: [`KEY ${Button.CYCLE_VARIANT.toString()}`, 'Change'],
[SettingKeyboard.Button_Speed_Up]: [`KEY ${Button.SPEED_UP.toString()}`, 'Change'],
[SettingKeyboard.Alt_Button_Speed_Up]: [`KEY ${Button.SPEED_UP.toString()}`, 'Change'],
[SettingKeyboard.Button_Slow_Down]: [`KEY ${Button.SLOW_DOWN.toString()}`, 'Change'],
[SettingKeyboard.Alt_Button_Slow_Down]: [`KEY ${Button.SLOW_DOWN.toString()}`, 'Change'],
[SettingKeyboard.Button_Submit]: [`KEY ${Button.SUBMIT.toString()}`, 'Change'],
[SettingKeyboard.Alt_Button_Submit]: [`KEY ${Button.SUBMIT.toString()}`, 'Change']
};
export const settingKeyboardDefaults: SettingDefaults = {
[SettingKeyboard.Default_Layout]: 0,
[SettingKeyboard.Button_Up]: 0,
[SettingKeyboard.Alt_Button_Up]: 0,
[SettingKeyboard.Button_Down]: 0,
[SettingKeyboard.Alt_Button_Down]: 0,
[SettingKeyboard.Button_Left]: 0,
[SettingKeyboard.Alt_Button_Left]: 0,
[SettingKeyboard.Button_Right]: 0,
[SettingKeyboard.Alt_Button_Right]: 0,
[SettingKeyboard.Button_Action]: 0,
[SettingKeyboard.Alt_Button_Action]: 0,
[SettingKeyboard.Button_Cancel]: 0,
[SettingKeyboard.Alt_Button_Cancel]: 0,
[SettingKeyboard.Button_Menu]: 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.Button_Submit]: 0,
[SettingKeyboard.Alt_Button_Submit]: 0,
};
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 i18next from "i18next";
import BattleScene from "../battle-scene"; import BattleScene from "../battle-scene";
import { hasTouchscreen } from "../touch-controls"; import { hasTouchscreen } from "../touch-controls";
import { updateWindowType } from "../ui/ui-theme"; import { updateWindowType } from "../ui/ui-theme";
import { PlayerGender } from "./game-data"; import { PlayerGender } from "./game-data";
import { Mode } from "../ui/ui";
import SettingsUiHandler from "../ui/settings/settings-ui-handler";
export enum Setting { export enum Setting {
Game_Speed = "GAME_SPEED", Game_Speed = "GAME_SPEED",
@ -25,8 +25,6 @@ export enum Setting {
HP_Bar_Speed = "HP_BAR_SPEED", HP_Bar_Speed = "HP_BAR_SPEED",
Fusion_Palette_Swaps = "FUSION_PALETTE_SWAPS", Fusion_Palette_Swaps = "FUSION_PALETTE_SWAPS",
Player_Gender = "PLAYER_GENDER", 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", Touch_Controls = "TOUCH_CONTROLS",
Vibration = "VIBRATION" Vibration = "VIBRATION"
} }
@ -58,8 +56,6 @@ export const settingOptions: SettingOptions = {
[Setting.HP_Bar_Speed]: ['Normal', 'Fast', 'Faster', 'Instant'], [Setting.HP_Bar_Speed]: ['Normal', 'Fast', 'Faster', 'Instant'],
[Setting.Fusion_Palette_Swaps]: ['Off', 'On'], [Setting.Fusion_Palette_Swaps]: ['Off', 'On'],
[Setting.Player_Gender]: ['Boy', 'Girl'], [Setting.Player_Gender]: ['Boy', 'Girl'],
[Setting.Gamepad_Support]: ['Auto', 'Disabled'],
[Setting.Swap_A_and_B]: ['Enabled', 'Disabled'],
[Setting.Touch_Controls]: ['Auto', 'Disabled'], [Setting.Touch_Controls]: ['Auto', 'Disabled'],
[Setting.Vibration]: ['Auto', 'Disabled'] [Setting.Vibration]: ['Auto', 'Disabled']
}; };
@ -83,8 +79,6 @@ export const settingDefaults: SettingDefaults = {
[Setting.HP_Bar_Speed]: 0, [Setting.HP_Bar_Speed]: 0,
[Setting.Fusion_Palette_Swaps]: 1, [Setting.Fusion_Palette_Swaps]: 1,
[Setting.Player_Gender]: 0, [Setting.Player_Gender]: 0,
[Setting.Gamepad_Support]: 0,
[Setting.Swap_A_and_B]: 1, // Set to 'Disabled' by default
[Setting.Touch_Controls]: 0, [Setting.Touch_Controls]: 0,
[Setting.Vibration]: 0 [Setting.Vibration]: 0
}; };
@ -154,14 +148,6 @@ export function setSetting(scene: BattleScene, setting: Setting, value: integer)
} else } else
return false; return false;
break; 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: case Setting.Touch_Controls:
scene.enableTouchControls = settingOptions[setting][value] !== 'Disabled' && hasTouchscreen(); scene.enableTouchControls = settingOptions[setting][value] !== 'Disabled' && hasTouchscreen();
const touchControls = document.getElementById('touchControls'); const touchControls = document.getElementById('touchControls');

View File

@ -0,0 +1,320 @@
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: 'keyboard',
padType: 'default',
gamepadMapping: {
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: [],
};
export default cfg_keyboard_azerty;

View File

@ -0,0 +1,44 @@
import {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;
constructor(config) {
this.config = config;
this.keycode = null;
this.settingName = null;
this.icon = 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;
}
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) {
this.settingName = SettingInterface[this.normalizeSettingNameString(settingName)];
expect(getSettingNameWithKeycode(this.config, this.keycode)).toEqual(this.settingName);
return this;
}
}

View File

@ -0,0 +1,96 @@
import {SettingInterface} from "#app/test/cfg_keyboard.example";
import {expect} from "vitest";
import {Button} from "#app/enums/buttons";
import {
deleteBind,
getIconWithKey,
getIconWithKeycode,
getIconWithSettingName,
getKeyWithKeycode, getKeyWithSettingName, isAlreadyBinded, swap
} 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) {
this.settingName = SettingInterface[settingName];
const buttonName = this.convertNameToButtonString(settingName);
expect(this.config.settings[this.settingName]).toEqual(Button[buttonName]);
return this;
}
iconDisplayedIs(icon) {
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();
}
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;
}
OopsSpecialCaseIcon(icon) {
this.specialCaseIcon = this.config.icons[icon];
const potentialExistingKey = isAlreadyBinded(this.config, this.keycode, this.settingName);
const prev_key = potentialExistingKey || getKeyWithSettingName(this.config, this.settingName);
expect(getIconWithKey(this.config, prev_key)).toEqual(this.specialCaseIcon);
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;
}
confirm() {
swap(this.config, this.settingName, this.keycode);
}
}

View File

@ -0,0 +1,311 @@
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 {
getButtonWithSettingName,
getIconWithSettingName,
getKeyWithKeycode,
getKeyWithSettingName,
getSettingNameWithKeycode,
regenerateIdentifiers,
swap
} from "#app/configs/configHandler";
import {MenuManip} from "#app/test/helpers/menuManip";
import {InGameManip} from "#app/test/helpers/inGameManip";
describe('Test Rebinding', () => {
let config;
let inGame;
let inTheSettingMenu;
beforeEach(() => {
config = deepCopy(cfg_keyboard_azerty);
config.custom = {...config.default}
regenerateIdentifiers(config);
inGame = new InGameManip(config);
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', () => {
const settingNameA = SettingInterface.Button_Left;
const settingNameB = SettingInterface.Button_Right;
swap(config, SettingInterface.Button_Left, Phaser.Input.Keyboard.KeyCodes.RIGHT);
expect(getButtonWithSettingName(config, settingNameA)).toEqual(Button.LEFT);
expect(getSettingNameWithKeycode(config, Phaser.Input.Keyboard.KeyCodes.RIGHT)).toEqual(SettingInterface.Button_Left)
expect(getButtonWithSettingName(config, settingNameB)).toEqual(Button.RIGHT);
expect(getSettingNameWithKeycode(config, Phaser.Input.Keyboard.KeyCodes.LEFT)).toEqual(SettingInterface.Button_Right)
expect(getIconWithSettingName(config, settingNameA)).toEqual(config.icons.KEY_ARROW_RIGHT);
expect(getIconWithSettingName(config, settingNameB)).toEqual(config.icons.KEY_ARROW_LEFT);
});
it('Check if double swap is working', () => {
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").confirm();
inGame.whenWePressOnKeyboard("LEFT").weShouldTriggerTheButton("Button_Right");
inGame.whenWePressOnKeyboard("RIGHT").weShouldTriggerTheButton("Button_Left");
inGame.whenWePressOnKeyboard("UP").weShouldTriggerTheButton("Button_Up");
inTheSettingMenu.whenCursorIsOnSetting("Button_Left").iconDisplayedIs("KEY_ARROW_RIGHT").weWantThisBindInstead("UP").confirm();
inGame.whenWePressOnKeyboard("LEFT").weShouldTriggerTheButton("Button_Right");
inGame.whenWePressOnKeyboard("RIGHT").weShouldTriggerTheButton("Button_Up");
inGame.whenWePressOnKeyboard("UP").weShouldTriggerTheButton("Button_Left");
inTheSettingMenu.whenCursorIsOnSetting("Button_Left").iconDisplayedIs("KEY_ARROW_UP").weWantThisBindInstead("RIGHT").confirm();
inGame.whenWePressOnKeyboard("LEFT").weShouldTriggerTheButton("Button_Right");
inGame.whenWePressOnKeyboard("RIGHT").weShouldTriggerTheButton("Button_Left");
inGame.whenWePressOnKeyboard("UP").weShouldTriggerTheButton("Button_Up");
});
it('Check if triple swap is working', () => {
inTheSettingMenu.whenCursorIsOnSetting("Button_Left").iconDisplayedIs("KEY_ARROW_LEFT").weWantThisBindInstead("RIGHT").confirm();
inGame.whenWePressOnKeyboard("LEFT").weShouldTriggerTheButton("Button_Right");
inGame.whenWePressOnKeyboard("RIGHT").weShouldTriggerTheButton("Button_Left");
inGame.whenWePressOnKeyboard("UP").weShouldTriggerTheButton("Button_Up");
inTheSettingMenu.whenCursorIsOnSetting("Button_Right").iconDisplayedIs("KEY_ARROW_LEFT").weWantThisBindInstead("UP").confirm();
inGame.whenWePressOnKeyboard("LEFT").weShouldTriggerTheButton("Button_Up");
inGame.whenWePressOnKeyboard("RIGHT").weShouldTriggerTheButton("Button_Left");
inGame.whenWePressOnKeyboard("UP").weShouldTriggerTheButton("Button_Right");
inTheSettingMenu.whenCursorIsOnSetting("Button_Left").iconDisplayedIs("KEY_ARROW_RIGHT").weWantThisBindInstead("LEFT").confirm();
inGame.whenWePressOnKeyboard("LEFT").weShouldTriggerTheButton("Button_Left");
inGame.whenWePressOnKeyboard("RIGHT").weShouldTriggerTheButton("Button_Up");
inGame.whenWePressOnKeyboard("UP").weShouldTriggerTheButton("Button_Right");
});
it('Swap alt with another main', () => {
inGame.whenWePressOnKeyboard("D").weShouldTriggerTheButton("Alt_Button_Right");
inGame.whenWePressOnKeyboard("LEFT").weShouldTriggerTheButton("Button_Left");
inGame.whenWePressOnKeyboard("Q").weShouldTriggerTheButton("Alt_Button_Left");
inTheSettingMenu.whenCursorIsOnSetting("Button_Left").iconDisplayedIs("KEY_ARROW_LEFT").weWantThisBindInstead("D").OopsSpecialCaseIcon("KEY_Q").confirm();
inGame.whenWePressOnKeyboard("D").weShouldTriggerTheButton("Alt_Button_Left");
inGame.whenWePressOnKeyboard("LEFT").weShouldTriggerTheButton("Button_Left");
inGame.whenWePressOnKeyboard("Q").weShouldTriggerTheButton("Alt_Button_Right");
});
it('multiple Swap alt with another main', () => {
inGame.whenWePressOnKeyboard("D").weShouldTriggerTheButton("Alt_Button_Right");
inGame.whenWePressOnKeyboard("LEFT").weShouldTriggerTheButton("Button_Left");
inGame.whenWePressOnKeyboard("LEFT").weShouldTriggerTheButton("Button_Left");
inGame.whenWePressOnKeyboard("UP").weShouldTriggerTheButton("Button_Up");
inTheSettingMenu.whenCursorIsOnSetting("Button_Left").iconDisplayedIs("KEY_ARROW_LEFT").weWantThisBindInstead("D").OopsSpecialCaseIcon("KEY_Q").confirm();
inGame.whenWePressOnKeyboard("D").weShouldTriggerTheButton("Alt_Button_Left");
inGame.whenWePressOnKeyboard("LEFT").weShouldTriggerTheButton("Button_Left");
inGame.whenWePressOnKeyboard("Q").weShouldTriggerTheButton("Alt_Button_Right");
inGame.whenWePressOnKeyboard("UP").weShouldTriggerTheButton("Button_Up");
inTheSettingMenu.whenCursorIsOnSetting("Button_Up").iconDisplayedIs("KEY_ARROW_UP").weWantThisBindInstead("LEFT").confirm();
inGame.whenWePressOnKeyboard("D").weShouldTriggerTheButton("Alt_Button_Left");
inGame.whenWePressOnKeyboard("LEFT").weShouldTriggerTheButton("Button_Up");
inGame.whenWePressOnKeyboard("Q").weShouldTriggerTheButton("Alt_Button_Right");
inGame.whenWePressOnKeyboard("UP").weShouldTriggerTheButton("Button_Left");
});
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 bind', () => {
inGame.whenWePressOnKeyboard("LEFT").weShouldTriggerTheButton("Button_Left");
inTheSettingMenu.whenWeDelete("Button_Left").thereShouldBeNoIconAnymore();
inGame.whenWePressOnKeyboard("LEFT").nothingShouldHappen();
});
it('Delete bind then assign a not yet binded button', () => {
inGame.whenWePressOnKeyboard("LEFT").weShouldTriggerTheButton("Button_Left");
inGame.whenWePressOnKeyboard("Q").weShouldTriggerTheButton("Alt_Button_Left");
inGame.whenWePressOnKeyboard("B").nothingShouldHappen();
inTheSettingMenu.whenWeDelete("Button_Left").thereShouldBeNoIconAnymore();
inGame.whenWePressOnKeyboard("LEFT").nothingShouldHappen();
inGame.whenWePressOnKeyboard("Q").weShouldTriggerTheButton("Alt_Button_Left");
inGame.whenWePressOnKeyboard("B").nothingShouldHappen();
inTheSettingMenu.whenCursorIsOnSetting("Button_Left").thereShouldBeNoIcon().weWantThisBindInstead("B").confirm();
inGame.whenWePressOnKeyboard("B").weShouldTriggerTheButton("Button_Left");
inGame.whenWePressOnKeyboard("LEFT").nothingShouldHappen();
inGame.whenWePressOnKeyboard("Q").weShouldTriggerTheButton("Alt_Button_Left");
})
it('Delete bind then assign a not yet binded button', () => {
inGame.whenWePressOnKeyboard("LEFT").weShouldTriggerTheButton("Button_Left");
inGame.whenWePressOnKeyboard("Q").weShouldTriggerTheButton("Alt_Button_Left");
inGame.whenWePressOnKeyboard("B").nothingShouldHappen();
inTheSettingMenu.whenWeDelete("Button_Left").thereShouldBeNoIconAnymore();
inGame.whenWePressOnKeyboard("LEFT").nothingShouldHappen();
inGame.whenWePressOnKeyboard("RIGHT").weShouldTriggerTheButton("Button_Right");
inTheSettingMenu.whenCursorIsOnSetting("Button_Left").thereShouldBeNoIcon().weWantThisBindInstead("RIGHT").confirm();
inGame.whenWePressOnKeyboard("LEFT").nothingShouldHappen();
inGame.whenWePressOnKeyboard("RIGHT").weShouldTriggerTheButton("Button_Left");
});
it('swap 2 bind, than delete 1 bind than assign another bind', () => {
inGame.whenWePressOnKeyboard("LEFT").weShouldTriggerTheButton("Button_Left");
inGame.whenWePressOnKeyboard("RIGHT").weShouldTriggerTheButton("Button_Right");
inTheSettingMenu.whenCursorIsOnSetting("Button_Left").iconDisplayedIs("KEY_ARROW_LEFT").weWantThisBindInstead("RIGHT").confirm();
inGame.whenWePressOnKeyboard("LEFT").weShouldTriggerTheButton("Button_Right");
inGame.whenWePressOnKeyboard("RIGHT").weShouldTriggerTheButton("Button_Left");
inTheSettingMenu.whenCursorIsOnSetting("Button_Left").whenWeDelete().thereShouldBeNoIconAnymore();
inGame.whenWePressOnKeyboard("LEFT").weShouldTriggerTheButton("Button_Right");
inGame.whenWePressOnKeyboard("RIGHT").nothingShouldHappen();
inTheSettingMenu.whenCursorIsOnSetting("Alt_Button_Up").iconDisplayedIs("KEY_Z").weWantThisBindInstead("B").confirm();
inGame.whenWePressOnKeyboard("LEFT").weShouldTriggerTheButton("Button_Right");
inGame.whenWePressOnKeyboard("RIGHT").nothingShouldHappen();
inGame.whenWePressOnKeyboard("B").weShouldTriggerTheButton("Alt_Button_Up");
});
it('Delete bind then assign not already existing button', () => {
inGame.whenWePressOnKeyboard("LEFT").weShouldTriggerTheButton("Button_Left");
inGame.whenWePressOnKeyboard("Q").weShouldTriggerTheButton("Alt_Button_Left");
inGame.whenWePressOnKeyboard("B").nothingShouldHappen();
inTheSettingMenu.whenWeDelete("Button_Left").thereShouldBeNoIconAnymore();
inGame.whenWePressOnKeyboard("LEFT").nothingShouldHappen();
inGame.whenWePressOnKeyboard("RIGHT").weShouldTriggerTheButton("Button_Right");
inTheSettingMenu.whenCursorIsOnSetting("Button_Left").thereShouldBeNoIcon().weWantThisBindInstead("L").confirm();
inGame.whenWePressOnKeyboard("L").weShouldTriggerTheButton("Button_Left");
});
it('change alt bind to not already existing button, than another one alt bind with another not already existing button', () => {
inGame.whenWePressOnKeyboard("Z").weShouldTriggerTheButton("Alt_Button_Up");
inGame.whenWePressOnKeyboard("S").weShouldTriggerTheButton("Alt_Button_Down");
inGame.whenWePressOnKeyboard("T").nothingShouldHappen();
inTheSettingMenu.whenCursorIsOnSetting("Alt_Button_Up").iconDisplayedIs("KEY_Z").weWantThisBindInstead("T").confirm();
inGame.whenWePressOnKeyboard("T").weShouldTriggerTheButton("Alt_Button_Up");
inGame.whenWePressOnKeyboard("Z").nothingShouldHappen();
inGame.whenWePressOnKeyboard("U").nothingShouldHappen();
inGame.whenWePressOnKeyboard("S").weShouldTriggerTheButton("Alt_Button_Down");
inTheSettingMenu.whenCursorIsOnSetting("Alt_Button_Down").iconDisplayedIs("KEY_S").weWantThisBindInstead("U").confirm();
inGame.whenWePressOnKeyboard("T").weShouldTriggerTheButton("Alt_Button_Up");
inGame.whenWePressOnKeyboard("Z").nothingShouldHappen();
inGame.whenWePressOnKeyboard("U").weShouldTriggerTheButton("Alt_Button_Down");
inGame.whenWePressOnKeyboard("S").nothingShouldHappen();
});
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").confirm();
inGame.whenWePressOnKeyboard("UP").weShouldTriggerTheButton("Button_Right");
inGame.whenWePressOnKeyboard("RIGHT").weShouldTriggerTheButton("Button_Up");
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_Right");
inGame.whenWePressOnKeyboard("RIGHT").weShouldTriggerTheButton("Button_Up");
inGame.whenWePressOnKeyboard("Z").weShouldTriggerTheButton("Alt_Button_Right");
inGame.whenWePressOnKeyboard("D").weShouldTriggerTheButton("Alt_Button_Up");
inTheSettingMenu.whenCursorIsOnSetting("Alt_Button_Up").iconDisplayedIs("KEY_D").weWantThisBindInstead("Z").confirm();
inGame.whenWePressOnKeyboard("UP").weShouldTriggerTheButton("Button_Right");
inGame.whenWePressOnKeyboard("RIGHT").weShouldTriggerTheButton("Button_Up");
inGame.whenWePressOnKeyboard("Z").weShouldTriggerTheButton("Alt_Button_Up");
inGame.whenWePressOnKeyboard("D").weShouldTriggerTheButton("Alt_Button_Right");
})
it('Delete 2 bind then reassign one of them', () => {
inGame.whenWePressOnKeyboard("LEFT").weShouldTriggerTheButton("Button_Left");
inGame.whenWePressOnKeyboard("Q").weShouldTriggerTheButton("Alt_Button_Left");
inGame.whenWePressOnKeyboard("B").nothingShouldHappen();
inTheSettingMenu.whenWeDelete("Button_Left").thereShouldBeNoIconAnymore();
inGame.whenWePressOnKeyboard("LEFT").nothingShouldHappen();
inGame.whenWePressOnKeyboard("Q").weShouldTriggerTheButton("Alt_Button_Left");
inGame.whenWePressOnKeyboard("B").nothingShouldHappen();
inTheSettingMenu.whenWeDelete("Alt_Button_Left").thereShouldBeNoIconAnymore();
inGame.whenWePressOnKeyboard("LEFT").nothingShouldHappen();
inGame.whenWePressOnKeyboard("Q").nothingShouldHappen();
inGame.whenWePressOnKeyboard("B").nothingShouldHappen();
inTheSettingMenu.whenCursorIsOnSetting("Alt_Button_Left").thereShouldBeNoIcon().weWantThisBindInstead("Q").confirm();
inGame.whenWePressOnKeyboard("LEFT").nothingShouldHappen();
inGame.whenWePressOnKeyboard("Q").weShouldTriggerTheButton("Alt_Button_Left");
inGame.whenWePressOnKeyboard("B").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);
});
});

View File

@ -1,11 +1,13 @@
import {Button} from "./enums/buttons";
export const keys = new Map(); export const keys = new Map();
export const keysDown = new Map(); export const keysDown = new Map();
let lastTouchedId; let lastTouchedId;
export function initTouchControls(buttonMap) { export function initTouchControls(events) {
for (const button of document.querySelectorAll('[data-key]')) { for (const button of document.querySelectorAll('[data-key]')) {
// @ts-ignore // @ts-ignore
bindKey(button, button.dataset.key, buttonMap); bindKey(button, button.dataset.key, events);
} }
} }
@ -27,34 +29,27 @@ export function isMobile() {
* *
* @param {string} eventType Type of the keyboard event * @param {string} eventType Type of the keyboard event
* @param {string} button Button to simulate * @param {string} button Button to simulate
* @param {object} buttonMap Map of buttons to key objects
*/ */
function simulateKeyboardEvent(eventType, button, buttonMap) { function simulateKeyboardEvent(eventType, key, events) {
const key = buttonMap[button]; if (!Button.hasOwnProperty(key)) return;
const button = Button[key];
switch (eventType) { switch (eventType) {
case 'keydown': case 'keydown':
key.onDown({}); events.emit('input_down', {
controller_type: 'touch',
button: button,
});
break; break;
case 'keyup': case 'keyup':
key.onUp({}); events.emit('input_up', {
controller_type: 'touch',
button: button,
});
break; break;
} }
} }
/**
* Simulate a keyboard input from 'keydown' to 'keyup'
*
* @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 * Bind a node by a specific key to simulate on touch
* *
@ -62,12 +57,12 @@ function simulateKeyboardInput(key, buttonMap) {
* @param {string} key Key to simulate * @param {string} key Key to simulate
* @param {object} buttonMap Map of buttons to key objects * @param {object} buttonMap Map of buttons to key objects
*/ */
function bindKey(node, key, buttonMap) { function bindKey(node, key, events) {
keys.set(node.id, key); keys.set(node.id, key);
node.addEventListener('touchstart', event => { node.addEventListener('touchstart', event => {
event.preventDefault(); event.preventDefault();
simulateKeyboardEvent('keydown', key, buttonMap); simulateKeyboardEvent('keydown', key, events);
keysDown.set(event.target.id, node.id); keysDown.set(event.target.id, node.id);
node.classList.add('active'); node.classList.add('active');
}); });
@ -78,7 +73,7 @@ function bindKey(node, key, buttonMap) {
const pressedKey = keysDown.get(event.target.id); const pressedKey = keysDown.get(event.target.id);
if (pressedKey && keys.has(pressedKey)) { if (pressedKey && keys.has(pressedKey)) {
const key = keys.get(pressedKey); const key = keys.get(pressedKey);
simulateKeyboardEvent('keyup', key, buttonMap); simulateKeyboardEvent('keyup', key, events);
} }
keysDown.delete(event.target.id); keysDown.delete(event.target.id);
@ -88,28 +83,4 @@ function bindKey(node, key, buttonMap) {
document.getElementById(lastTouchedId).classList.remove('active'); 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 MessageUiHandler from "./ui/message-ui-handler";
import StarterSelectUiHandler from "./ui/starter-select-ui-handler"; import StarterSelectUiHandler from "./ui/starter-select-ui-handler";
import {Setting, settingOptions} from "./system/settings"; 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 {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 { export interface ActionKeys {
[key in Button]: () => void; [key in Button]: () => void;
@ -130,7 +132,9 @@ export class UiInputs {
} }
buttonCycleOption(button: Button): void { 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); this.scene.ui.processInput(button);
} }
} }

View File

@ -0,0 +1,201 @@
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";
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 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;
// The specific setting being modified.
protected target;
constructor(scene: BattleScene, mode: Mode) {
super(scene, mode);
}
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.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);
// New button icon setup.
this.newButtonIcon = this.scene.add.sprite(0, 0, 'keyboard');
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, 'keyboard');
this.targetButtonIcon.setScale(0.15);
this.targetButtonIcon.setPositionRelative(this.optionSelectBg, 78, 48);
this.targetButtonIcon.setOrigin(0.5);
this.targetButtonIcon.setVisible(false);
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.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);
// Add swap and cancel labels to the containers.
this.optionSelectContainer.add(this.newButtonIcon);
this.optionSelectContainer.add(this.swapText);
this.optionSelectContainer.add(this.targetButtonIcon);
this.actionsContainer.add(this.actionLabel);
this.actionsContainer.add(this.cancelLabel);
}
show(args: any[]): boolean {
super.show(args);
this.buttonPressed = null;
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, 100);
return true;
}
getWindowWidth(): number {
return 160;
}
getWindowHeight(): number {
return 64;
}
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;
}
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() {
super.clear();
this.listening = false;
this.target = null;
this.cancelFn = null;
this.optionSelectContainer.setVisible(false);
this.actionsContainer.setVisible(false);
this.newButtonIcon.setVisible(false);
this.targetButtonIcon.setVisible(false);
this.swapText.setVisible(false);
this.buttonPressed = null;
}
onInputDown(buttonIcon: string, assignedButtonIcon: string, type: string): void {
this.newButtonIcon.setTexture(type);
this.newButtonIcon.setFrame(buttonIcon);
this.targetButtonIcon.setTexture(type);
this.targetButtonIcon.setFrame(assignedButtonIcon);
this.newButtonIcon.setVisible(true);
this.targetButtonIcon.setVisible(true);
this.swapText.setVisible(true);
this.setCursor(0);
this.actionsContainer.setVisible(true);
}
}

View File

@ -0,0 +1,492 @@
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";
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>;
}
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 optionsBg: 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;
// 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 settingDeviceDefaults;
protected settingDeviceOptions;
protected configs;
protected commonSettingsCount;
protected textureOverride;
protected titleSelected;
protected localStoragePropertyName;
abstract getLocalStorageSetting(): object;
abstract navigateMenuLeft(): boolean;
abstract navigateMenuRight(): boolean;
abstract saveSettingToLocalStorage(setting, cursor): void;
abstract getActiveConfig(): InterfaceConfig;
constructor(scene: BattleScene, mode?: Mode) {
super(scene, mode);
}
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);
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, 'General', TextStyle.SETTINGS_LABEL);
headerText.setOrigin(0, 0);
headerText.setPositionRelative(headerBg, 8, 4);
const gamepadText = addTextObject(this.scene, 0, 0, 'Gamepad', this.titleSelected === 'Gamepad' ? TextStyle.SETTINGS_SELECTED : TextStyle.SETTINGS_LABEL);
gamepadText.setOrigin(0, 0);
gamepadText.setPositionRelative(headerBg, 50, 4);
const keyboardText = addTextObject(this.scene, 0, 0, 'Keyboard', this.titleSelected === 'Keyboard' ? TextStyle.SETTINGS_SELECTED : TextStyle.SETTINGS_LABEL);
keyboardText.setOrigin(0, 0);
keyboardText.setPositionRelative(headerBg, 97, 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.setOrigin(0, 0);
this.settingsContainer.add(headerBg);
this.settingsContainer.add(headerText);
this.settingsContainer.add(gamepadText);
this.settingsContainer.add(keyboardText);
this.settingsContainer.add(this.optionsBg);
/// 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 gamepad 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.
settingLabels[s] = addTextObject(this.scene, 8, 28 + s * 16, settingName, TextStyle.SETTINGS_LABEL);
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.
const aaa = this.settingDeviceOptions;
const bbb = this.settingDevice;
const ccc = this.settingDevice[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, 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(78, 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);
}
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 {
if (!this.inputsIcons[elm]) debugger;
this.inputsIcons[elm].alpha = 0;
}
}
// Set the cursor and scroll cursor to their initial positions.
this.setCursor(0);
this.setScrollCursor(0);
}
show(args: any[]): boolean {
super.show(args);
// 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.setScrollCursor(0);
// 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;
}
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;
// If a cursor object exists, destroy it to clean up previous UI states.
this.cursorObj?.destroy();
// Reset the cursor object and scroll cursor to ensure they are re-initialized correctly.
this.cursorObj = null;
this.scrollCursor = null;
// 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;
}
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;
// 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.
switch (button) {
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(rowsToDisplay - 1);
// Then, adjust the scroll to display the bottommost elements of the menu.
const successB = this.setScrollCursor(this.optionValueLabels.length - 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 < rowsToDisplay - 1)
success = this.setCursor(this.cursor + 1);
else if (this.scrollCursor < this.optionValueLabels.length - 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.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.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.
}
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.
}
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.
}
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.
}
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 + 9;
// 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(): 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();
}
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,41 @@
import BattleScene from "../../battle-scene";
import AbstractBindingUiHandler from "../settings/abrast-binding-ui-handler";
import {Mode} from "../ui";
import {Device} from "#app/enums/devices";
import {getIconSpecialCase, getIconWithSettingName, getKeyWithKeycode} from "#app/configs/configHandler";
export default class GamepadBindingUiHandler extends AbstractBindingUiHandler {
constructor(scene: BattleScene, mode: Mode) {
super(scene, mode);
// Listen to gamepad button down events to initiate binding.
scene.input.gamepad.on('down', this.gamepadButtonDown, this);
}
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 specialCaseIcon = getIconSpecialCase(activeConfig, button.index, this.target);
const assignedButtonIcon = getIconWithSettingName(activeConfig, this.target);
this.onInputDown(buttonIcon, specialCaseIcon || assignedButtonIcon, type);
}
swapAction() {
const activeConfig = this.scene.inputController.getActiveConfig(Device.GAMEPAD);
this.scene.inputController.swapBinding(activeConfig, this.target, this.buttonPressed)
this.scene.gameData.saveMappingConfigs(this.getSelectedDevice(), activeConfig);
return true;
}
}

View File

@ -0,0 +1,41 @@
import BattleScene from "../../battle-scene";
import AbstractBindingUiHandler from "../settings/abrast-binding-ui-handler";
import {Mode} from "../ui";
import {getIconSpecialCase, getIconWithSettingName, getKeyWithKeycode} from "#app/configs/configHandler";
import {Device} from "#app/enums/devices";
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);
}
getSelectedDevice() {
return this.scene.inputController?.selectedDevice[Device.KEYBOARD];
}
onKeyDown(event): void {
const key = event.keyCode;
// // Check conditions before processing the button press.
if (!this.listening || this.buttonPressed !== null) 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 specialCaseIcon = getIconSpecialCase(activeConfig, key, this.target);
const assignedButtonIcon = getIconWithSettingName(activeConfig, this.target);
this.onInputDown(buttonIcon, specialCaseIcon || assignedButtonIcon, 'keyboard');
}
swapAction() {
const activeConfig = this.scene.inputController.getActiveConfig(Device.KEYBOARD);
this.scene.inputController.swapBinding(activeConfig, this.target, this.buttonPressed)
this.scene.gameData.saveMappingConfigs(this.getSelectedDevice(), activeConfig);
return true;
}
}

View File

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

View File

@ -0,0 +1,102 @@
import BattleScene from "../../battle-scene";
import {addTextObject, TextStyle} from "../text";
import {Mode} from "../ui";
import {SettingGamepad, 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";
export default class SettingsGamepadUiHandler extends AbstractSettingsUiUiHandler {
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';
}
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;
}
getActiveConfig(): InterfaceConfig {
return this.scene.inputController.getActiveConfig(Device.GAMEPAD);
}
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;
}
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);
}
navigateMenuLeft(): boolean {
this.scene.ui.setMode(Mode.SETTINGS)
return true;
}
navigateMenuRight(): boolean {
this.scene.ui.setMode(Mode.SETTINGS_KEYBOARD)
return true;
}
updateChosenGamepadDisplay(): 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_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(this.scene.inputController.selectedDevice[Device.GAMEPAD], 30);
}
}
}
}
saveSettingToLocalStorage(setting, cursor): void {
if (this.settingDevice[setting] !== this.settingDevice.Default_Controller)
this.scene.gameData.saveGamepadSetting(setting, cursor)
}
}

View File

@ -0,0 +1,120 @@
import BattleScene from "../../battle-scene";
import {Mode} from "../ui";
import cfg_keyboard_azerty from "#app/configs/cfg_keyboard_azerty";
import {SettingKeyboard, 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";
export default class SettingsKeyboardUiHandler extends AbstractSettingsUiUiHandler {
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 = 1;
this.textureOverride = 'keyboard';
this.localStoragePropertyName = 'settingsKeyboard';
const deleteEvent = scene.input.keyboard.addKey(Phaser.Input.Keyboard.KeyCodes.DELETE);
deleteEvent.on('up', this.onDeleteDown, this);
}
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);
// Map the 'noKeyboard' layout options for easy access.
this.layout['noKeyboard'].optionsContainer = optionsContainer;
this.layout['noKeyboard'].label = label;
}
onDeleteDown(): void {
const cursor = this.cursor + this.scrollCursor; // Calculate the absolute cursor position.
const selection = this.settingLabels[cursor].text;
const key = reverseValueToKeySetting(selection);
const setting = SettingKeyboard[key];
const activeConfig = this.getActiveConfig();
deleteBind(this.getActiveConfig(), setting);
this.saveCustomKeyboardMappingToLocalStorage(activeConfig);
this.updateBindings();
}
getActiveConfig(): InterfaceConfig {
return this.scene.inputController.getActiveConfig(Device.KEYBOARD);
}
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;
}
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);
}
navigateMenuLeft(): boolean {
this.scene.ui.setMode(Mode.SETTINGS_GAMEPAD)
return true;
}
navigateMenuRight(): boolean {
this.scene.ui.setMode(Mode.SETTINGS)
return true;
}
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], 30));
}
}
}
}
saveCustomKeyboardMappingToLocalStorage(config): void {
this.scene.gameData.saveMappingConfigs(this.scene.inputController?.selectedDevice[Device.KEYBOARD], config);
}
saveSettingToLocalStorage(settingName, cursor): void {
if (this.settingDevice[settingName] !== this.settingDevice.Default_Layout)
this.scene.gameData.saveKeyboardSetting(settingName, cursor)
}
}

View File

@ -1,11 +1,11 @@
import BattleScene from "../battle-scene"; import BattleScene from "../../battle-scene";
import { Setting, reloadSettings, settingDefaults, settingOptions } from "../system/settings"; import { Setting, reloadSettings, settingDefaults, settingOptions } from "../../system/settings";
import { hasTouchscreen, isMobile } from "../touch-controls"; import { hasTouchscreen, isMobile } from "../../touch-controls";
import { TextStyle, addTextObject } from "./text"; import { TextStyle, addTextObject } from "../text";
import { Mode } from "./ui"; import { Mode } from "../ui";
import UiHandler from "./ui-handler"; import UiHandler from "../ui-handler";
import { addWindow } from "./ui-theme"; import { addWindow } from "../ui-theme";
import {Button} from "../enums/buttons"; import {Button} from "../../enums/buttons";
export default class SettingsUiHandler extends UiHandler { export default class SettingsUiHandler extends UiHandler {
private settingsContainer: Phaser.GameObjects.Container; private settingsContainer: Phaser.GameObjects.Container;
@ -42,10 +42,18 @@ export default class SettingsUiHandler extends UiHandler {
const headerBg = addWindow(this.scene, 0, 0, (this.scene.game.canvas.width / 6) - 2, 24); const headerBg = addWindow(this.scene, 0, 0, (this.scene.game.canvas.width / 6) - 2, 24);
headerBg.setOrigin(0, 0); headerBg.setOrigin(0, 0);
const headerText = addTextObject(this.scene, 0, 0, 'Options', TextStyle.SETTINGS_LABEL); const headerText = addTextObject(this.scene, 0, 0, 'General', TextStyle.SETTINGS_SELECTED);
headerText.setOrigin(0, 0); headerText.setOrigin(0, 0);
headerText.setPositionRelative(headerBg, 8, 4); headerText.setPositionRelative(headerBg, 8, 4);
const gamepadText = addTextObject(this.scene, 0, 0, 'Gamepad', TextStyle.SETTINGS_LABEL);
gamepadText.setOrigin(0, 0);
gamepadText.setPositionRelative(headerBg, 50, 4);
const keyboardText = addTextObject(this.scene, 0, 0, 'Keyboard', TextStyle.SETTINGS_LABEL);
keyboardText.setOrigin(0, 0);
keyboardText.setPositionRelative(headerBg, 97, 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) - headerBg.height - 2);
this.optionsBg.setOrigin(0, 0); this.optionsBg.setOrigin(0, 0);
@ -92,6 +100,8 @@ export default class SettingsUiHandler extends UiHandler {
this.settingsContainer.add(headerBg); this.settingsContainer.add(headerBg);
this.settingsContainer.add(headerText); this.settingsContainer.add(headerText);
this.settingsContainer.add(gamepadText);
this.settingsContainer.add(keyboardText);
this.settingsContainer.add(this.optionsBg); this.settingsContainer.add(this.optionsBg);
this.settingsContainer.add(this.optionsContainer); this.settingsContainer.add(this.optionsContainer);
@ -182,6 +192,14 @@ export default class SettingsUiHandler extends UiHandler {
if (this.optionCursors[cursor] < this.optionValueLabels[cursor].length - 1) if (this.optionCursors[cursor] < this.optionValueLabels[cursor].length - 1)
success = this.setOptionCursor(cursor, this.optionCursors[cursor] + 1, true); success = this.setOptionCursor(cursor, this.optionCursors[cursor] + 1, true);
break; 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;
} }
} }

View File

@ -1,6 +1,6 @@
import BattleScene from "../battle-scene"; import BattleScene from "../battle-scene";
import { DailyRunScoreboard } from "./daily-run-scoreboard"; 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 { Mode } from "./ui";
import * as Utils from "../utils"; import * as Utils from "../utils";
import { TextStyle, addTextObject } from "./text"; 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 StarterSelectUiHandler from './starter-select-ui-handler';
import EvolutionSceneHandler from './evolution-scene-handler'; import EvolutionSceneHandler from './evolution-scene-handler';
import TargetSelectUiHandler from './target-select-ui-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 { TextStyle, addTextObject } from './text';
import AchvBar from './achv-bar'; import AchvBar from './achv-bar';
import MenuUiHandler from './menu-ui-handler'; import MenuUiHandler from './menu-ui-handler';
import AchvsUiHandler from './achvs-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 EggHatchSceneHandler from './egg-hatch-scene-handler';
import EggListUiHandler from './egg-list-ui-handler'; import EggListUiHandler from './egg-list-ui-handler';
import EggGachaUiHandler from './egg-gacha-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 OutdatedModalUiHandler from './outdated-modal-ui-handler';
import SessionReloadModalUiHandler from './session-reload-modal-ui-handler'; import SessionReloadModalUiHandler from './session-reload-modal-ui-handler';
import {Button} from "../enums/buttons"; 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 { export enum Mode {
MESSAGE, MESSAGE,
@ -56,6 +60,10 @@ export enum Mode {
MENU, MENU,
MENU_OPTION_SELECT, MENU_OPTION_SELECT,
SETTINGS, SETTINGS,
SETTINGS_GAMEPAD,
GAMEPAD_BINDING,
SETTINGS_KEYBOARD,
KEYBOARD_BINDING,
ACHIEVEMENTS, ACHIEVEMENTS,
GAME_STATS, GAME_STATS,
VOUCHERS, VOUCHERS,
@ -86,7 +94,11 @@ const noTransitionModes = [
Mode.OPTION_SELECT, Mode.OPTION_SELECT,
Mode.MENU, Mode.MENU,
Mode.MENU_OPTION_SELECT, Mode.MENU_OPTION_SELECT,
Mode.GAMEPAD_BINDING,
Mode.KEYBOARD_BINDING,
Mode.SETTINGS, Mode.SETTINGS,
Mode.SETTINGS_GAMEPAD,
Mode.SETTINGS_KEYBOARD,
Mode.ACHIEVEMENTS, Mode.ACHIEVEMENTS,
Mode.GAME_STATS, Mode.GAME_STATS,
Mode.VOUCHERS, Mode.VOUCHERS,
@ -137,6 +149,10 @@ export default class UI extends Phaser.GameObjects.Container {
new MenuUiHandler(scene), new MenuUiHandler(scene),
new OptionSelectUiHandler(scene, Mode.MENU_OPTION_SELECT), new OptionSelectUiHandler(scene, Mode.MENU_OPTION_SELECT),
new SettingsUiHandler(scene), new SettingsUiHandler(scene),
new SettingsGamepadUiHandler(scene),
new GamepadBindingUiHandler(scene),
new SettingsKeyboardUiHandler(scene),
new KeyboardBindingUiHandler(scene),
new AchvsUiHandler(scene), new AchvsUiHandler(scene),
new GameStatsUiHandler(scene), new GameStatsUiHandler(scene),
new VouchersUiHandler(scene), new VouchersUiHandler(scene),

View File

@ -336,4 +336,21 @@ export function rgbHexToRgba(hex: string) {
export function rgbaToInt(rgba: integer[]): integer { export function rgbaToInt(rgba: integer[]): integer {
return (rgba[0] << 24) + (rgba[1] << 16) + (rgba[2] << 8) + rgba[3]; return (rgba[0] << 24) + (rgba[1] << 16) + (rgba[2] << 8) + rgba[3];
}
export function truncateString(str: String, maxLength: number = 10) {
if (str.length > maxLength) {
return str.slice(0, maxLength - 3) + "..."; // Subtract 3 to accommodate the ellipsis
}
return str;
}
export function deepCopy(values: object): object {
return JSON.parse(JSON.stringify(values));
}
export function reverseValueToKeySetting(input) {
const words = input.split(' ');
const capitalizedWords = words.map(word => word.charAt(0).toUpperCase() + word.slice(1).toLowerCase());
return capitalizedWords.join('_');
} }