Forum rules - please read before posting.

Virtual Keyboard

Hi all!

Hope you are doing well -- so I'm hoping to get my game verified on steam deck, but there are some places where I need to enter input in my game.

Is it possible to call the virtual keyboard when this happens? Or does this happen automatically?
Any help is appreciated, thank you!

Comments

  • It's not automatic - you'll need to use the Steamworks API and open the keyboard when you intend.

    This could be automated when e.g. the user clicks/taps your UI Input field - something along these lines should do it:

    using UnityEngine;
    using Steamworks;
    using UnityEngine.UI;
    
    public class SteamDeckVirtualKeyboard : MonoBehaviour
    {
    
        public InputField nameInputField;
    
        private void Start()
        {
            if (SteamManager.Initialized)
            {
                nameInputField.onSelect.AddListener(ShowVirtualKeyboard);
            }
        }
    
        private void ShowVirtualKeyboard(string selected)
        {
            if (SteamUtils.IsSteamRunningOnSteamDeck())
            {
                SteamUtils.ShowFloatingTextInput(FloatingTextInputMode.k_EFloatingTextInputModeModeSingleLine, 0, 0, 300, 50);
                StartCoroutine (CheckForInput ());
            }
        }
    
        private System.Collections.IEnumerator CheckForInput()
        {
            while (SteamUtils.IsSteamRunningOnSteamDeck () && SteamInput.IsTextInputActive ())
            {
                string userInput = SteamUtils.GetEnteredGamepadTextInput ();
    
                if (!string.IsNullOrEmpty (userInput))
                {
                    nameInputField.text = userInput;
                }
    
                yield return null;
            }
        }
    
    }
    
  • I see! Thank you so much! :)

  • Would this only be possible on menus that are Unity UI prefabs and/or Unity UI in scene, or is this possible with menus that have AC as their source?

  • This adapted script should do the same thing for an AC-based Menu:

    using UnityEngine;
    using Steamworks;
    using AC;
    
    public class SteamDeckVirtualKeyboard : MonoBehaviour
    {
    
        public string menuName = "Menu";
        public string inputName = "Input";
    
        private void OnEnable () { EventManager.OnMenuElementClick += OnMenuElementClick; }
        private void OnDisable () { EventManager.OnMenuElementClick += OnMenuElementClick; }
    
        void OnMenuElementClick (Menu _menu, MenuElement _element, int _slot, int buttonPressed)
        {
            if (_menu.title == menuName && _element.title == inputName)
            {
                if (SteamManager.Initialized)
                {
                    nameInputField.onSelect.AddListener(ShowVirtualKeyboard);
                }
            }
        }
    
        private void ShowVirtualKeyboard(string selected)
        {
            if (SteamUtils.IsSteamRunningOnSteamDeck())
            {
                SteamUtils.ShowFloatingTextInput(FloatingTextInputMode.k_EFloatingTextInputModeModeSingleLine, 0, 0, 300, 50);
                StartCoroutine (CheckForInput ());
            }
        }
    
        private System.Collections.IEnumerator CheckForInput()
        {
            MenuInput menuInput = PlayerMenus.GetElementWithName (menuName, inputName) as MenuInput;
    
            while (SteamUtils.IsSteamRunningOnSteamDeck () && SteamInput.IsTextInputActive ())
            {
                string userInput = SteamUtils.GetEnteredGamepadTextInput ();
    
                if (!string.IsNullOrEmpty (userInput))
                {
                    menuInput.OverrideLabel (userInput);
                }
    
                yield return null;
            }
        }
    
    }
    
  • edited October 2024

    Thank you!
    Hm -- so it looks like I'm still having trouble with the getting the virtual keyboard to show up in the first place.

    If it helps, this is how I'm attaching the script component (on my TMP_InputField element in the AC menu prefab):

    https://drive.google.com/file/d/1NOsoSCQmKBpm-cVzTSz2AwUFe26Uh6ps/view?usp=sharing

    And this is the entire script:

    using UnityEngine;
    using TMPro;
    using Steamworks;
    using UnityEngine.InputSystem; // Ensure this is included
    
    public class UniversalControllerVirtualKeyboard : MonoBehaviour
    {
        public TMP_InputField inputField;
    
        private void Start()
        {
            inputField.onSelect.AddListener(ShowVirtualKeyboard);
        }
    
        private void ShowVirtualKeyboard(string selected)
        {
            if (Gamepad.current != null) // Checks if any controller is connected
            {
                if (Application.isMobilePlatform)
                {
                    TouchScreenKeyboard.Open("", TouchScreenKeyboardType.Default);
                }
                else if (SteamManager.Initialized && SteamUtils.IsSteamRunningOnSteamDeck())
                {
                    SteamUtils.ShowFloatingGamepadTextInput(
                        EFloatingGamepadTextInputMode.k_EFloatingGamepadTextInputModeModeSingleLine,
                        0, 0, 300, 50
                    );
                    StartCoroutine(CheckForSteamInput());
                }
                else
                {
    #if UNITY_PS4
                    Sony.PS4.Input.PS4Input.OpenOnScreenKeyboard(0, Sony.PS4.Input.PS4Input.OnScreenKeyboardType.Default, "");
    #elif UNITY_XBOXONE
                    UnityEngine.XboxOne.XboxOneInput.OpenVirtualKeyboard("");
    #else
                    Debug.Log("No virtual keyboard available for this platform.");
    #endif
                }
            }
            else
            {
                Debug.Log("No controller detected, keyboard input expected.");
            }
        }
    
        private System.Collections.IEnumerator CheckForSteamInput()
        {
            uint bufferSize = 1024;
            string userInput = "";
    
            while (SteamUtils.IsSteamRunningOnSteamDeck())
            {
                if (SteamUtils.GetEnteredGamepadTextInput(out userInput, bufferSize) && !string.IsNullOrEmpty(userInput))
                {
                    inputField.text = userInput;
                }
                yield return null;
            }
        }
    }
    

    I asked one of my testers on the steamdeck, along with someone else on an XBOX controller, to try this out. While the other controls in the controllers are ok, it looks like the virtual keyboard is never brought up.

    It also looks like it's able to detect the platform correctly, but no keyboard shows up?
    Is there any specific menu settings I need to have for the virtual keyboard to pop up?
    Thanks!

  • I'd recommend scaling back and just testing with the first script - add the extras afterwards once it's working.

    Try it in a fresh scene with just a regular InputField - no AC involvement.

    If it's not the right approach, you'll need to consult the Steamworks API documentation - I'm without a Steamdeck myself, so I can't guarantee the code will be exact.

  • Sounds good -- I rolled back but strangely it didn't work either :(

    Just in case, I readded the directives, but I went ahead and asked the Steamworks developer forums just in case, since it looks like the API functions are not throwing any errors -- rather, it's just the virtual keyboard that's not popping up.

    https://steamcommunity.com/groups/steamworks/discussions/27/4697910365481113732/

    Hopefully I can get some insight from others who are also doing this -- thank you so much for all your help above! :)

  • edited October 2024

    @ChrisIceBox

    So it looks like I might have to add an input mapping into unity. I think this is with the new input system. Where I'll have to define controller actions.

    I'm a bit confused as to how I can link / translate the AC default controls + things like "EndCutscene" + other custom inputs I defined (like Toggling Inventory) into this: https://docs.unity3d.com/Packages/com.unity.inputsystem@1.11/manual/index.html

    This is the mapping that one of my beta-testers sent me -- https://drive.google.com/file/d/1jV5tua1pV_Ub25RmA5y5d6DT2bX7S3C7/view?usp=sharing

    Additionally, would this input mapping need to be present anywhere in the scene / through a script? I'm not sure how I'd link this.

    For reference, I am selecting "both" instead of "new only" for my input manager, just because I want to preserve the old inputs, as I want the player to have the option to either play through the controller or the regular keyboard / mouse controls.

    Any guidance is appreciated, thank you!

  • If it helps, this is the asset file of my current input manager (the legacy input): https://drive.google.com/file/d/10wE3JG-JxG1jcKM3b1XIz8L-pfFTLk23/view?usp=drive_link

    And this is just a summary of the various functions according to the steam layout that my beta-tester defined (the image in the previous message should have more details):

    Menu / ESC - Open Settings
    A / LMB - Click through dialogue / walk / interact with objects
    B / RMB - Drop Inventory
    Y / O - Open Tasks
    A x 2 / LMB x 2 (double-click) - teleport
    Hover - Examine
    X / I - Open Inventory
    L1 / C - skip cutscenes
    R1 / H - highlight hotspots

  • AC has an integration for Input System, which you can find on the Downloads page.

    I recommend using one system or the other - you can still use regular mouse/keyboard controls with it, just defined in a separate control scheme. The integration comes with a sample set of schemes and inputs that you can work from.

  • edited October 2024

    Sorry I'm still a bit confused actually -- so do I need this package, or for that matter, the new input system, for Unity playmode to allow controller input?

    Or can I get away with Unity legacy input somehow?

  • edited November 2024

    I'm hoping to just generalize it to all gamepads, while still allowing users to use keyboard / moust input. -- I'm a bit confused as to how to integrate this plugin into AC.

    How would our custom inputs be able to be mapped (e.g: ToggleInventory, as I sent in this message: https://drive.google.com/file/d/10wE3JG-JxG1jcKM3b1XIz8L-pfFTLk23/view?usp=drive_link)?

    I took a look at the wiki, but it looks like not all the functionality is captured: https://adventure-creator.fandom.com/wiki/Input_System_integration

  • Sorry I'm still a bit confused actually -- so do I need this package, or for that matter, the new input system, for Unity playmode to allow controller input?

    Controller input is possible just fine with the old Input Manager - just define additional copies of your inputs, mapped to joystick buttons. The new system is more intuitive when it comes to working out what input goes where, but it's still possible with the old one.

    That's generally speaking, though. It may be different if you've come across a specific need to use the Input System API with e.g. a custom script.

    How would our custom inputs be able to be mapped (e.g: ToggleInventory, as I sent in this message:

    You can create an input with a Positive Button of e.g. "joystick button 0" to have it respond to the XBox A button. More can be found here.

    I took a look at the wiki, but it looks like not all the functionality is captured:

    That's outdated - the one on the Downloads is the one to use. It won't include all inputs (e.g. ToggleInventory) by default, but you can edit the Controls asset to include any inputs you need.

  • Got it, thank you!

    I went ahead and used the package + I set things up -- however, I noticed a few issues.

    It looks like I'm unable to hover over the input fields correctly, and it looks like while my cursor is moving, it doesn't follow the game cursor? It seems like I can still move it with mouse, but the cursor with my controller isn't doing the right thing.

    Unfortunately, I'm almost out of storage on G-drive, so I'm unable to upload screenshots of what I mean.

    Would it help if you have access to my repository? I can push my latest changes if it would help to reproduce.

  • For reference, it looks like the controller "cursor" and the mouse cursor are different things, but the "controller" cursor is invisible.

  • edited November 2024

    @ChrisIceBox
    Was also able to create a video, deleted a few things from drive so things could free up.

    The first part is me using the keyboard / mouse, where things are working as expected. The second part is where I'm using a controller, where this "invisible" cursor is moving around, although the "examine / use / talk" special cursors are rendering at the original position, where I last left my mouse. It does look like the player is also turning towards the new cursor, which is great, but I want the mouse / keyboard cursor to follow the controller cursor.

    here's what's happening:

    https://drive.google.com/file/d/1J2B1u1-5BQewsde6IeWQ16nvNIlvzLq_/view?usp=sharing

    I also DM'd you a link to my repository along with some general steps to reproduce, if that would help! We can carry the conversation there if that is better -- since I'm assuming there could be some specific settings I might need to check.

    Happy to continue it here as well -- whichever is better!

  • Updating this thread since I finally found a solution thanks to community support from here, Unity, and my beta-testers! :)

    So it turns out I needed to actually check for the input and do a callback, and I could easily get away with the old input system.

    Here is my script -- you will want to attach this to any TMP_InputField where the user needs to use the virtual keyboard:

    `using UnityEngine;
    using Steamworks;
    using TMPro;

    public class SteamDeckVirtualKeyboard : MonoBehaviour
    {
    public TMP_InputField inputField;
    public string promptText = "Please enter text";
    public int maxCharLimit = 300;

    private Callback<GamepadTextInputDismissed_t> gamepadTextInputDismissedCallback;
    
    private void Start()
    {
        if (SteamManager.Initialized)
        {
            inputField.onSelect.AddListener(ShowVirtualKeyboard);
            gamepadTextInputDismissedCallback = Callback<GamepadTextInputDismissed_t>.Create(OnGamepadTextInputDismissed);
        }
    }
    
    private void ShowVirtualKeyboard(string selected)
    {
        if (SteamUtils.IsSteamRunningOnSteamDeck())
        {
            Debug.Log("IS RUNNING ON STEAM DECK");
    
            bool isShowing = SteamUtils.ShowGamepadTextInput(
                EGamepadTextInputMode.k_EGamepadTextInputModeNormal,
                EGamepadTextInputLineMode.k_EGamepadTextInputLineModeSingleLine,
                promptText,
                (uint)maxCharLimit,
                inputField.text
            );
    
            if (isShowing)
            {
                Debug.Log("Virtual keyboard displayed");
            }
        }
        else
        {
            Debug.Log("NOT RUNNING ON STEAM DECK");
        }
    }
    
    private void OnGamepadTextInputDismissed(GamepadTextInputDismissed_t callbackData)
    {
        if (callbackData.m_bSubmitted == true)
        {
            string enteredText;
            uint bufferSize = (uint)maxCharLimit;
    
            bool success = SteamUtils.GetEnteredGamepadTextInput(out enteredText, bufferSize);
            if (success)
            {
                Debug.Log("ENTERED TEXT: " + enteredText);
                inputField.text = enteredText;
            }
            else
            {
                Debug.LogWarning("Failed to retrieve entered text from the virtual keyboard.");
            }
        }
        else
        {
            Debug.Log("User dismissed the keyboard without submitting.");
        }
    }
    

    }
    `

  • Thanks for sharing!

  • edited November 2024
    My pleasure, and thank you so much for your help! 😃
Sign In or Register to comment.

Howdy, Stranger!

It looks like you're new here. If you want to get involved, click one of these buttons!

Welcome to the official forum for Adventure Creator.