I downloaded the latest Steamworks SDK and I had to make a new native class:
class SteamUtilsWrapper extends Object native;
var protected array<Object> ObjectsWaitingForCallback;
var string GamepadTextInput;
var bool TextInputWasCanceled;
// native function bool BOverlayNeedsPresent(); // No need to ever call this manually
native function int GetAppID();
native function byte GetCurrentBatteryPower();
native function int GetSecondsSinceAppActive();
native function int GetSecondsSinceComputerActive();
native function bool IsOverlayEnabled();
native function bool IsSteamChinaLauncher();
native function bool IsSteamInBigPictureMode();
native function bool IsSteamRunningOnSteamDeck();
native function SetOverlayNotificationInset(int nHorizontalInset, int nVerticalInset);
native function SetOverlayNotificationPosition(byte byteNotificationPosition);
native function bool ShowGamepadTextInput(byte eInputMode, byte eLineInputMode, string Description, int MaxChar, string ExistingText);
// native function bool ShowFloatingGamepadTextInput(byte eKeyboardMode, int nTextFieldXPosition, int nTextFieldYPosition, int nTextFieldWidth, int nTextFieldHeight); // only useful on Steam Deck
// native function WrapperRunCallbacks(); // The game engine runs this automatically. No need to call it manually.
function bool WaitingForCallback()
{
return ObjectsWaitingForCallback.Length > 0 ? true : false;
}
function AddToWaitForCallback(Object ObjectWaitingForCallback)
{
if(TextInputDismissedInterface(ObjectWaitingForCallback) != none)
{
ObjectsWaitingForCallback.AddItem(ObjectWaitingForCallback);
}
}
event NotifyTextInputCallbacks()
{
local Object ObjectWaitingForCallback;
foreach ObjectsWaitingForCallback(ObjectWaitingForCallback)
{
if(TextInputDismissedInterface(ObjectWaitingForCallback) != none)
{
TextInputDismissedInterface(ObjectWaitingForCallback).OnTextInputDismissed(self);
}
}
ObjectsWaitingForCallback.Length = 0;
}
cpptext
{
#include "isteamutils.h" // ************************************************ Remember to cut/paste this to the top of RPGTacGameClasses.h
#include "steam_api_common.h" // ************************************************ Remember to cut/paste this to the top of RPGTacGameClasses.h
#include "steamclientpublic.h" // ************************************************ Remember to cut/paste this to the top of RPGTacGameClasses.h
private:
STEAM_CALLBACK( USteamUtilsWrapper, OnGamepadTextInputDismissed_t, GamepadTextInputDismissed_t );
}
Make that UScript class, build UScript which will make new header files, then move the #include statements to the top of the header (there’s a way to set up the Unreal Build Tool so that it automatically creates your headers with the #includes in the right place, but I never figured that out), then fill in your functions in the cpp file, and build the C++.
It took me a while to do all of that, mostly because I never learned C++. Now that I’ve done it all and I have working code, I think the code looks pretty simple. I don’t have any of the functionality you mentioned–I only really needed the text input window–but I think I could add more SteamUtils functions if I needed them.
Everything is working perfectly, except instantiating my SteamUtils object crashes the game when you’re running the 32 bit exe. I never figured out a way to know directly from UScript whether the game is 32 or 64 bit. So I added an option to my startup command (?win32=true) to tell the game whether I intended to run the 32 bit exe, and I look for that option before creating SteamUtils.
My 32-bit players just have to do without SteamUtils for now.