Update 2:
With the help of Joe from Microsoft, my colleague Tom, and some patches from the Unreal folks I think I’ve got a save feature working well enough for prototypes. Below is an attempt to document what worked. Hopefully I didn’t miss something.
Tested using UE4.27 and UXTools 0.12x-UE4.27
- note UE4.27 corrected some issue that prevents this from working in earlier versions
- This lets one use the built-in UE save function:
FFileHelper::SaveStringArrayToFile
- In the project
build.cs
file add the following
// Added to attempt to enable saving on the hololens
// https://docs.microsoft.com/en-us/windows/mixed-reality/develop/unreal/unreal-winRT?tabs=426
if (Target.Platform == UnrealTargetPlatform.Win64 || Target.Platform == UnrealTargetPlatform.HoloLens)
{
// These parameters are mandatory for winrt support
bEnableExceptions = true;
bUseUnity = false;
CppStandard = CppStandardVersion.Cpp17;
PublicSystemLibraries.AddRange(new string[] { "shlwapi.lib", "runtimeobject.lib" });
PrivateIncludePaths.Add(Path.Combine(Target.WindowsPlatform.WindowsSdkDir,
"Include",
Target.WindowsPlatform.WindowsSdkVersion,
"cppwinrt"));
}
- In the cpp file where the save file function is used add the following:
// start winrt headers
#if (PLATFORM_WINDOWS || PLATFORM_HOLOLENS)
//Before writing any code, you need to disable common warnings in WinRT headers
#pragma warning(disable : 5205 4265 4268 4946)
#include "Windows/AllowWindowsPlatformTypes.h"
#include "Windows/AllowWindowsPlatformAtomics.h"
#include "Windows/PreWindowsApi.h"
#include <unknwn.h>
#include <winrt/Windows.Foundation.h>
#include <winrt/Windows.Storage.h>
#include "Windows/PostWindowsApi.h"
#include "Windows/HideWindowsPlatformAtomics.h"
#include "Windows/HideWindowsPlatformTypes.h"
#endif
- The way I then set up my save function was as follows. For me this is a blueprint function that I use in my Blueprints. Note this function will work both on the computer, connected to the Hololens from the computer, and via packaged projects solely on the Hololens.
.h
file
UFUNCTION(BlueprintCallable, Category = "File Utilities")
static bool SaveStringArrayToFile(FString SaveDirectory, FString FileName, TArray<FString> SaveText, bool bAllowOverWriting = false, bool bAppend = false);
.cpp
file
bool UBPFL_FileUtilities::SaveStringArrayToFile(FString SaveDirectory, FString FileName, TArray<FString> SaveText, bool bAllowOverWriting, bool bAppend)
{
SaveDirectory += "\\" + FileName;
#if (PLATFORM_HOLOLENS)
try
{
std::string localPath = winrt::to_string(winrt::Windows::Storage::ApplicationData::Current().LocalFolder().Path());
auto localFolder = winrt::Windows::Storage::ApplicationData::Current().LocalFolder();
localFolder.CreateFolderAsync(L"SavedData");
// When saving to hololens grab only the actual filename and force save in the specified folder
int32 iName;
FileName.FindLastChar(TEXT('/'), iName);
FString savePathHL = UTF8_TO_TCHAR(localPath.c_str());
SaveDirectory = savePathHL + "\\SavedData\\" + FileName.RightChop(iName + 1);
}
catch (winrt::hresult_error const& ex)
{
UE_LOG(LogTemp, Warning, TEXT("error %s"), ex.message().c_str());
}
#endif
if (!bAppend)
{
if (!bAllowOverWriting)
{
if (FPlatformFileManager::Get().GetPlatformFile().FileExists(*SaveDirectory))
{
return false;
}
}
}
if (bAppend)
{
return FFileHelper::SaveStringArrayToFile(SaveText, *SaveDirectory, FFileHelper::EEncodingOptions::AutoDetect, &IFileManager::Get(), FILEWRITE_Append);
}
return FFileHelper::SaveStringArrayToFile(SaveText, *SaveDirectory);
}
Some notes:
-
localFolder.Path()
returns an hstring
(trying to call c_str()
on it just would return the first character… weird). Thus an issue I ran into was needing to convert that first to std::string
and then c_str
and then finally to FString
. The way that worked was to define localPath
and then use that rather than localFolder.Path()
directly. If I didn’t define a separate variable then I just got errors. IDK. shrug.
- There are a lot of restrictions on where you can save on the Hololens. The only way I could easily save files was to save it in the folder of the running app. Tried lots of things to save elsewhere but perhaps I just missed somethign. Anyways, this creates a folder and saved everything linked to this function in that “SavedData” folder. To access the location from the Windows Portal go the File Explorer and then navigate to
LocalAppData\YOURAPPPROJECT\LocalState\SavedData
- The part of
iName
and FileName
has to do with how I was formatting inputs. Letting users use relative directories on the computer but forcing a specific location on the Hololens.
I think that is it. Looking back it doesn’t look too terrible but that’s how things are. When you’re done they don’t seem so bad and you wonder why it took so long. Haha. Cheers!