From 39bec379237713eeb650d1d62dacab0886267f38 Mon Sep 17 00:00:00 2001 From: sfan5 Date: Wed, 16 Aug 2017 14:11:17 +0200 Subject: [PATCH] Implement text input on iOS --- build/iOS/MultiCraft/MultiCraft/ioswrap.h | 2 ++ build/iOS/MultiCraft/MultiCraft/ioswrap.m | 42 +++++++++++++++++++++++ src/client/clientlauncher.cpp | 9 ++++- src/game.cpp | 10 +++--- src/guiEngine.cpp | 2 +- src/guiFormSpecMenu.cpp | 6 ++-- src/guiFormSpecMenu.h | 4 +-- src/porting_ios.cpp | 21 ++++++++++++ src/porting_ios.h | 6 ++++ src/touchscreengui.cpp | 6 ++++ 10 files changed, 94 insertions(+), 14 deletions(-) diff --git a/build/iOS/MultiCraft/MultiCraft/ioswrap.h b/build/iOS/MultiCraft/MultiCraft/ioswrap.h index 0db8cd1fb..58879e103 100644 --- a/build/iOS/MultiCraft/MultiCraft/ioswrap.h +++ b/build/iOS/MultiCraft/MultiCraft/ioswrap.h @@ -15,6 +15,8 @@ void ioswrap_log(const char *message); void ioswrap_paths(int type, char *dest, size_t destlen); void ioswrap_assets(void); // extracts assets.zip to PATH_LIBRARY_SUPPORT void ioswrap_size(unsigned int *dest); +void ioswrap_show_dialog(void *uiviewcontroller, const char *accept, const char *hint, const char *current, int type); +int ioswrap_get_dialog(const char **text); #ifdef __cplusplus } diff --git a/build/iOS/MultiCraft/MultiCraft/ioswrap.m b/build/iOS/MultiCraft/MultiCraft/ioswrap.m index 1a74ff217..c7a26cea1 100644 --- a/build/iOS/MultiCraft/MultiCraft/ioswrap.m +++ b/build/iOS/MultiCraft/MultiCraft/ioswrap.m @@ -131,3 +131,45 @@ void ioswrap_size(unsigned int *dest) dest[0] = bounds.width * scale; dest[1] = bounds.height * scale; } + +/********/ + +static int dialog_state; +static char dialog_text[512]; + +#define DIALOG_MULTILINE 1 +#define DIALOG_SINGLELINE 2 +#define DIALOG_PASSWORD 3 + +void ioswrap_show_dialog(void *uiviewcontroller, const char *accept, const char *hint, const char *current, int type) +{ + UIViewController *viewc = (__bridge UIViewController*) uiviewcontroller; + NSString *accept_ = [NSString stringWithUTF8String:accept]; + (void) hint; // unused + + UIAlertController *alert = [UIAlertController alertControllerWithTitle:@"Text Input" message:nil preferredStyle:UIAlertControllerStyleAlert]; + [alert addTextFieldWithConfigurationHandler:^(UITextField *textField) { + textField.text = [NSString stringWithUTF8String:current]; + if(type == DIALOG_PASSWORD) + textField.secureTextEntry = YES; + }]; + [alert addAction:[UIAlertAction actionWithTitle:accept_ style:UIAlertActionStyleDefault handler:^(UIAlertAction *action) { + dialog_state = 0; + strncpy(dialog_text, alert.textFields[0].text.UTF8String, sizeof(dialog_text)); + }]]; + + dialog_state = -1; + dialog_text[0] = 0; + [viewc presentViewController:alert animated:YES completion:nil]; +} + +int ioswrap_get_dialog(const char **text) +{ + int ret = dialog_state; + if(text) { + *text = dialog_text; + dialog_state = -1; // reset + } + + return ret; +} diff --git a/src/client/clientlauncher.cpp b/src/client/clientlauncher.cpp index 46a2f1c83..721b6058c 100644 --- a/src/client/clientlauncher.cpp +++ b/src/client/clientlauncher.cpp @@ -39,6 +39,9 @@ with this program; if not, write to the Free Software Foundation, Inc., #if 0 // toggle to 1 for ads #define ADS #include "ads.h" +#endif + +#ifdef __IOS__ namespace irr { class CIrrDeviceiOS : public IrrlichtDevice { public: @@ -596,10 +599,14 @@ bool ClientLauncher::create_engine_device() if (device) porting::initIrrlicht(device); -#ifdef ADS + +#ifdef __IOS__ if (device) { CIrrDeviceiOS* dev = (CIrrDeviceiOS*) device; + porting::setViewController(dev->getViewController()); +#ifdef ADS ads_startup(dev->getViewController()); +#endif } #endif diff --git a/src/game.cpp b/src/game.cpp index 95df678b8..641acac5e 100644 --- a/src/game.cpp +++ b/src/game.cpp @@ -1353,7 +1353,7 @@ protected: return input->wasKeyDown(keycache.key[k]) || input->joystick.wasKeyDown(k); } -#ifdef __ANDROID__ +#if defined(__ANDROID__) || defined(__IOS__) void handleAndroidChatInput(); #endif @@ -1463,8 +1463,6 @@ private: #if defined(__ANDROID__) || defined(__IOS__) bool show_minimap; bool m_cache_hold_aux1; -#endif -#ifdef __ANDROID__ bool m_android_chat_open; #endif }; @@ -2547,7 +2545,7 @@ void Game::processUserInput(f32 dtime) // Input handler step() (used by the random input generator) input->step(dtime); -#ifdef __ANDROID__ +#if defined(__ANDROID__) || defined(__IOS__) if (current_formspec != NULL) current_formspec->getAndroidUIInput(); else @@ -2758,7 +2756,7 @@ void Game::openConsole(float scale, const wchar_t *line) { assert(scale > 0.0f && scale <= 1.0f); -#ifdef __ANDROID__ +#if defined(__ANDROID__) || defined(__IOS__) porting::showInputDialog(gettext("ok"), "", "", 2); m_android_chat_open = true; #else @@ -2772,7 +2770,7 @@ void Game::openConsole(float scale, const wchar_t *line) #endif } -#ifdef __ANDROID__ +#if defined(__ANDROID__) || defined(__IOS__) void Game::handleAndroidChatInput() { if (m_android_chat_open && porting::getInputDialogState() == 0) { diff --git a/src/guiEngine.cpp b/src/guiEngine.cpp index 084395d20..bccc58d57 100644 --- a/src/guiEngine.cpp +++ b/src/guiEngine.cpp @@ -309,7 +309,7 @@ void GUIEngine::run() m_script->step(); -#ifdef __ANDROID__ +#if defined(__ANDROID__) || defined(__IOS__) m_menu->getAndroidUIInput(); #endif } diff --git a/src/guiFormSpecMenu.cpp b/src/guiFormSpecMenu.cpp index 7d47fb376..90608deef 100644 --- a/src/guiFormSpecMenu.cpp +++ b/src/guiFormSpecMenu.cpp @@ -106,7 +106,7 @@ GUIFormSpecMenu::GUIFormSpecMenu(irr::IrrlichtDevice* dev, current_field_enter_pending(""), m_font(NULL), m_remap_dbl_click(remap_dbl_click) -#ifdef __ANDROID__ +#if defined(__ANDROID__) || defined(__IOS__) , m_JavaDialogFieldName("") #endif { @@ -2227,7 +2227,7 @@ void GUIFormSpecMenu::regenerateGui(v2u32 screensize) skin->setFont(old_font); } -#ifdef __ANDROID__ +#if defined(__ANDROID__) || defined(__IOS__) bool GUIFormSpecMenu::getAndroidUIInput() { /* no dialog shown */ @@ -3051,7 +3051,7 @@ bool GUIFormSpecMenu::preprocessEvent(const SEvent& event) } } - #ifdef __ANDROID__ +#if defined(__ANDROID__) || defined(__IOS__) // display software keyboard when clicking edit boxes if (event.EventType == EET_MOUSE_INPUT_EVENT && event.MouseInput.Event == EMIE_LMOUSE_PRESSED_DOWN) { diff --git a/src/guiFormSpecMenu.h b/src/guiFormSpecMenu.h index 7d93eb42f..1098d91fb 100644 --- a/src/guiFormSpecMenu.h +++ b/src/guiFormSpecMenu.h @@ -365,7 +365,7 @@ public: GUITable* getTable(const std::string &tablename); std::vector* getDropDownValues(const std::string &name); -#ifdef __ANDROID__ +#if defined(__ANDROID__) || defined(__IOS__) bool getAndroidUIInput(); #endif @@ -541,8 +541,6 @@ private: std::string getNameByID(s32 id); #if defined(__ANDROID__) || defined(__IOS__) v2s32 m_down_pos; -#endif -#ifdef __ANDROID__ std::string m_JavaDialogFieldName; #endif diff --git a/src/porting_ios.cpp b/src/porting_ios.cpp index 94fb8db0e..a849d1651 100644 --- a/src/porting_ios.cpp +++ b/src/porting_ios.cpp @@ -4,6 +4,7 @@ #include "config.h" #include "ioswrap.h" +static void *uiviewcontroller; namespace porting { void initializePathsiOS() { @@ -40,6 +41,26 @@ namespace porting { return retval; } + + void setViewController(void *v) { + uiviewcontroller = v; + } + + void showInputDialog(const std::string &acceptButton, const std::string &hint, + const std::string ¤t, int editType) + { + ioswrap_show_dialog(uiviewcontroller, acceptButton.c_str(), hint.c_str(), current.c_str(), editType); + } + + int getInputDialogState() { + return ioswrap_get_dialog(NULL); + } + + std::string getInputDialogValue() { + const char *str; + ioswrap_get_dialog(&str); + return std::string(str); + } } diff --git a/src/porting_ios.h b/src/porting_ios.h index 906c9f8f0..99292ed00 100644 --- a/src/porting_ios.h +++ b/src/porting_ios.h @@ -8,6 +8,12 @@ namespace porting { void initializePathsiOS(); void copyAssets(); + void setViewController(void *v); + + void showInputDialog(const std::string &acceptButton, const std::string &hint, + const std::string ¤t, int editType); + int getInputDialogState(); + std::string getInputDialogValue(); } #endif diff --git a/src/touchscreengui.cpp b/src/touchscreengui.cpp index ec4abe9be..3818a605d 100644 --- a/src/touchscreengui.cpp +++ b/src/touchscreengui.cpp @@ -364,6 +364,12 @@ void TouchScreenGUI::init(ISimpleTextureSource* tsrc) m_screensize.X / 2 + (button_size * 0.75), (button_size * 0.75)), L"far", false, SLOW_BUTTON_REPEAT); + /* init chat button */ + initButton(chat_id, + rect(m_screensize.X / 2 + (button_size * 0.75), 0, + m_screensize.X / 2 + (button_size * 1.5), + (button_size * 0.75)), + L"Chat", false, SLOW_BUTTON_REPEAT); #else // Android and Windows bar