diff --git a/CMake/ctr/n3ds_defs.cmake b/CMake/ctr/n3ds_defs.cmake index b006c7397..4fe187f5e 100644 --- a/CMake/ctr/n3ds_defs.cmake +++ b/CMake/ctr/n3ds_defs.cmake @@ -1,6 +1,7 @@ #General compilation options set(NONET ON) set(USE_SDL1 ON) +set(PREFILL_PLAYER_NAME ON) #3DS libraries list(APPEND CMAKE_MODULE_PATH "${DevilutionX_SOURCE_DIR}/CMake/ctr/modules") diff --git a/Source/DiabloUI/diabloui.cpp b/Source/DiabloUI/diabloui.cpp index 331cd5cd9..55b6dfd8d 100644 --- a/Source/DiabloUI/diabloui.cpp +++ b/Source/DiabloUI/diabloui.cpp @@ -30,6 +30,10 @@ // for virtual keyboard on Vita #include "platform/vita/keyboard.h" #endif +#ifdef __3DS__ +// for virtual keyboard on 3DS +#include "platform/ctr/keyboard.h" +#endif namespace devilution { @@ -101,9 +105,11 @@ void UiInitList(int count, void (*fnFocus)(int value), void (*fnSelect)(int valu SDL_SetTextInputRect(&item->m_rect); textInputActive = true; #ifdef __SWITCH__ - switch_start_text_input("", pItemUIEdit->m_value, pItemUIEdit->m_max_length, /*multiline=*/0); + switch_start_text_input(pItemUIEdit->m_hint, pItemUIEdit->m_value, pItemUIEdit->m_max_length, /*multiline=*/0); #elif defined(__vita__) - vita_start_text_input("", pItemUIEdit->m_value, pItemUIEdit->m_max_length); + vita_start_text_input(pItemUIEdit->m_hint, pItemUIEdit->m_value, pItemUIEdit->m_max_length); +#elif defined(__3DS__) + ctr_vkbdInput(pItemUIEdit->m_hint, pItemUIEdit->m_value, pItemUIEdit->m_value, pItemUIEdit->m_max_length); #else SDL_StartTextInput(); #endif @@ -692,6 +698,12 @@ void UiPollAndRender() // Must happen after the very first UiFadeIn, which sets the cursor. if (IsHardwareCursor()) SetHardwareCursorVisible(!sgbControllerActive); + +#ifdef __3DS__ + // Keyboard blocks until input is finished + // so defer until after render and fade-in + ctr_vkbdFlush(); +#endif } namespace { diff --git a/Source/DiabloUI/selgame.cpp b/Source/DiabloUI/selgame.cpp index 6af7b07d5..f28ef53d9 100644 --- a/Source/DiabloUI/selgame.cpp +++ b/Source/DiabloUI/selgame.cpp @@ -182,7 +182,7 @@ void selgame_GameSelection_Select(int value) vecSelGameDialog.push_back(new UiArtText(_("Enter address"), rect4, UIS_CENTER | UIS_BIG)); SDL_Rect rect5 = { (Sint16)(PANEL_LEFT + 305), (Sint16)(UI_OFFSET_Y + 314), 285, 33 }; - vecSelGameDialog.push_back(new UiEdit(selgame_Ip, 128, rect5, UIS_MED | UIS_GOLD)); + vecSelGameDialog.push_back(new UiEdit(_("Enter address"), selgame_Ip, 128, rect5, UIS_MED | UIS_GOLD)); SDL_Rect rect6 = { (Sint16)(PANEL_LEFT + 299), (Sint16)(UI_OFFSET_Y + 427), 140, 35 }; vecSelGameDialog.push_back(new UiArtTextButton(_("OK"), &UiFocusNavigationSelect, rect6, UIS_CENTER | UIS_VCENTER | UIS_BIG | UIS_GOLD)); @@ -388,7 +388,7 @@ void selgame_Password_Init(int value) vecSelGameDialog.push_back(new UiArtText(_("Enter Password"), rect4, UIS_CENTER | UIS_BIG)); SDL_Rect rect5 = { (Sint16)(PANEL_LEFT + 305), (Sint16)(UI_OFFSET_Y + 314), 285, 33 }; - vecSelGameDialog.push_back(new UiEdit(selgame_Password, 15, rect5, UIS_MED | UIS_GOLD)); + vecSelGameDialog.push_back(new UiEdit(_("Enter Password"), selgame_Password, 15, rect5, UIS_MED | UIS_GOLD)); SDL_Rect rect6 = { (Sint16)(PANEL_LEFT + 299), (Sint16)(UI_OFFSET_Y + 427), 140, 35 }; vecSelGameDialog.push_back(new UiArtTextButton(_("OK"), &UiFocusNavigationSelect, rect6, UIS_CENTER | UIS_VCENTER | UIS_BIG | UIS_GOLD)); diff --git a/Source/DiabloUI/selhero.cpp b/Source/DiabloUI/selhero.cpp index e06f1b55b..9802c966e 100644 --- a/Source/DiabloUI/selhero.cpp +++ b/Source/DiabloUI/selhero.cpp @@ -17,10 +17,6 @@ #include "pfile.h" #include "utils/language.h" -#ifdef __3DS__ -#include "platform/ctr/keyboard.h" -#endif - namespace devilution { bool selhero_endMenu; @@ -272,9 +268,7 @@ void SelheroClassSelectorFocus(int value) bool ShouldPrefillHeroName() { -#if defined __3DS__ - return false; -#elif defined(PREFILL_PLAYER_NAME) +#if defined(PREFILL_PLAYER_NAME) return true; #else return sgbControllerActive; @@ -297,9 +291,6 @@ void SelheroClassSelectorSelect(int value) strncpy(title, _("New Multi Player Hero"), sizeof(title) - 1); } memset(selhero_heroInfo.name, '\0', sizeof(selhero_heroInfo.name)); -#if defined __3DS__ - ctr_vkbdInput(_("Enter Name"), SelheroGenerateName(selhero_heroInfo.heroclass), selhero_heroInfo.name); -#endif if (ShouldPrefillHeroName()) strncpy(selhero_heroInfo.name, SelheroGenerateName(selhero_heroInfo.heroclass), sizeof(selhero_heroInfo.name) - 1); SelheroFreeDlgItems(); @@ -307,7 +298,7 @@ void SelheroClassSelectorSelect(int value) vecSelDlgItems.push_back(new UiArtText(_("Enter Name"), rect1, UIS_CENTER | UIS_BIG)); SDL_Rect rect2 = { (Sint16)(PANEL_LEFT + 265), (Sint16)(UI_OFFSET_Y + 317), 320, 33 }; - vecSelDlgItems.push_back(new UiEdit(selhero_heroInfo.name, 15, rect2, UIS_MED | UIS_GOLD)); + vecSelDlgItems.push_back(new UiEdit(_("Enter Name"), selhero_heroInfo.name, 15, rect2, UIS_MED | UIS_GOLD)); SDL_Rect rect3 = { (Sint16)(PANEL_LEFT + 279), (Sint16)(UI_OFFSET_Y + 429), 140, 35 }; vecSelDlgItems.push_back(new UiArtTextButton(_("OK"), &UiFocusNavigationSelect, rect3, UIS_CENTER | UIS_BIG | UIS_GOLD)); diff --git a/Source/DiabloUI/ui_item.h b/Source/DiabloUI/ui_item.h index c5beaf1b9..1b029f2f8 100644 --- a/Source/DiabloUI/ui_item.h +++ b/Source/DiabloUI/ui_item.h @@ -185,15 +185,17 @@ public: class UiEdit : public UiItemBase { public: - UiEdit(char *value, std::size_t max_length, SDL_Rect rect, int flags = 0) + UiEdit(const char *hint, char *value, std::size_t max_length, SDL_Rect rect, int flags = 0) : UiItemBase(rect, flags) { m_type = UI_EDIT; + m_hint = hint; m_value = value; m_max_length = max_length; } //private: + const char *m_hint; char *m_value; std::size_t m_max_length; }; diff --git a/Source/platform/ctr/keyboard.cpp b/Source/platform/ctr/keyboard.cpp index f3004b517..c272dc580 100644 --- a/Source/platform/ctr/keyboard.cpp +++ b/Source/platform/ctr/keyboard.cpp @@ -3,24 +3,53 @@ #include "platform/ctr/keyboard.h" -const char *ctr_vkbdInput(const char *hintText, const char *inText, char *outText) +constexpr size_t MAX_TEXT_LENGTH = 255; + +struct vkbdEvent { + const char *hintText; + const char *inText; + char *outText; + int maxLength; +}; + +static vkbdEvent events[16]; +static int eventCount = 0; + +void ctr_vkbdInput(const char *hintText, const char *inText, char *outText, int maxLength) +{ + if (eventCount >= sizeof(events)) + return; + + vkbdEvent &event = events[eventCount]; + event.hintText = hintText; + event.inText = inText; + event.outText = outText; + event.maxLength = maxLength; + eventCount++; +} + +void ctr_vkbdFlush() { - SwkbdState swkbd; + for (int i = 0; i < eventCount; i++) { + vkbdEvent &event = events[i]; + SwkbdState swkbd; + + char mybuf[MAX_TEXT_LENGTH + 1]; - char mybuf[16]; + swkbdInit(&swkbd, SWKBD_TYPE_WESTERN, 2, MAX_TEXT_LENGTH); + swkbdSetValidation(&swkbd, SWKBD_NOTEMPTY_NOTBLANK, 0, 0); + swkbdSetInitialText(&swkbd, event.inText); + swkbdSetHintText(&swkbd, event.hintText); - swkbdInit(&swkbd, SWKBD_TYPE_WESTERN, 2, 15); - swkbdSetValidation(&swkbd, SWKBD_NOTEMPTY_NOTBLANK, 0, 0); - swkbdSetInitialText(&swkbd, inText); - swkbdSetHintText(&swkbd, hintText); + SwkbdButton button = swkbdInputText(&swkbd, mybuf, sizeof(mybuf)); - SwkbdButton button = swkbdInputText(&swkbd, mybuf, sizeof(mybuf)); + if (button == SWKBD_BUTTON_CONFIRM) { + strncpy(event.outText, mybuf, event.maxLength); + continue; + } - if (button == SWKBD_BUTTON_CONFIRM) { - strcpy(outText, mybuf); - return 0; + strncpy(event.outText, event.inText, event.maxLength); } - strcpy(outText, inText); - return 0; + eventCount = 0; } diff --git a/Source/platform/ctr/keyboard.h b/Source/platform/ctr/keyboard.h index 5a930f606..669118857 100644 --- a/Source/platform/ctr/keyboard.h +++ b/Source/platform/ctr/keyboard.h @@ -1,3 +1,4 @@ #include <3ds.h> -const char *ctr_vkbdInput(const char *title, const char *inText, char *outText); +void ctr_vkbdInput(const char *title, const char *inText, char *outText, int maxLength); +void ctr_vkbdFlush();