You've already forked UnrealEngineUWP
mirror of
https://github.com/izzy2lost/UnrealEngineUWP.git
synced 2026-03-26 18:15:20 -07:00
#lockdown Nick.Penwarden
#rb None
============================
MAJOR FEATURES & CHANGES
============================
Change 3600639 by Nick.Shin
HTML5 remove old emscripten toolchain
forgot to remove this (was checked out in another changelist)
#jira UE-47813
Change 3600641 by Nick.Shin
HTML5 TM-Core crash fixes
new PhysX HTML5 libs
#jira UE-47813 Index Out Of Bounds crash running "GC and Level Load Stress Test" in TM-Core on Firefox
Change 3600644 by Nick.Shin
HTML5 TM-Core crash fixes
emscripten doesn't seem to know how to look at <PxRigidActor> from the PxActor class...
#jira UE-47813 Index Out Of Bounds crash running "GC and Level Load Stress Test" in TM-Core on Firefox
Change 3600647 by Nick.Shin
HTML5 UInterpTrackInst::GetGroupActor()
pre-null check
#jira UE-47485 ( Pri:1 - 4.18 ) Crash running Stat Command test in TM-Core on Firefox
Change 3601439 by Dmitriy.Dyomin
Fixed: Protostar leads to device reboot in Galaxy S7 Adreno device. (SM-G930V)
#jira UE-48323
Change 3601440 by Dmitriy.Dyomin
Fixed: Texture streaming after world origin was rebased
Change 3601456 by Dmitriy.Dyomin
Added: Async loading bytecode from shader library
- Shader library will be packed into single file
- Shader library will be created only when packaging project by the book
#jira UEMOB-381
Change 3601624 by Jack.Porter
Fix landscape crash on HTML5 Exception !IsInRenderingThread() failed.
#jira UE-48527
Change 3603890 by Dmitriy.Dyomin
GitHub 3905 : Engine crash in LandscapeComponent when streaming levels
#3905
#jira UE-48422
Change 3603933 by Dmitriy.Dyomin
Fixed: Crash after Splash Screen on Android (ETC2) when Adding r.UseShaderCaching and r.UseShaderPredraw
- Added r.SaveShaderCache command to save current cache on demand
- Removed support for caching multiple platfroms at the same time, each platform now uses separate cache/file
- Significantly reduced size of draw log on disk
- Mobile platfroms support only basic caching, logging shaders and bound shader states without full gfx state
#jira UE-47553
Change 3604050 by Sorin.Gradinaru
#jira UE-47428 Android virtual keyboard polishing
Done:
Multiline should be disabled when not needed
Hide suggestions and autocorrect
"Done" / back button behavior to make it feel natural - Done/Enter and the Back key event sent to the engine
If the keyboard is up and you click on the same control you're currently inputting into, it will hide the keyboard.
Look into animation - not critical.
S6 with Swiftkey. The numbers don't show up in our textedit but the string is updated (we see dots in the Slate control) with the password entry
Could not reproduce/test:
Make sure we don't use negative coords for the input box if the keyboard is at the top of the screen
Change 3604081 by Allan.Bentham
Reduce redundant log spam from SustainedPerformanceMode on android.
Change 3604152 by Allan.Bentham
Improved vulkanRHI availability and selection reporting.
Change 3604186 by Dmitriy.Dyomin
Vulkan: Write to buffers directly on UMA devices (no staging)
Change 3604396 by Nick.Shin
HTML5 - stats and multi-threading checks
more null & multi-threading - and some functions flat out disabled for HTML5 platform
the big "don't use on HTML5" is TLockFreeFixedSizeAllocator_TLSCacheBase's manual TLS.PartialBundle memory handler... i'm not sure it's working properly... switched on USE_NIEVE_TLockFreeFixedSizeAllocator_TLSCacheBase sections of code (i.e. basic malloc and free) for PLATFORM_HTML5
- it seems only the stats function was exacerbating the memory bug ... but, shutting this completely out for HTML5... don't know if it's an emscripten compiler/corruption that's causing this...
- will send this to emscripten makers as another test case for them to help see what's going on...
#jira UE-47485 ( Pri:1 - 4.18 ) Crash running Stat Command test in TM-Core on Firefox
Change 3604752 by Allan.Bentham
Reduce battery status log spam.
Change 3604825 by Nick.Shin
HTML5 emscripten 1.37.19 updated license file
#jira UE-47813
Change 3606486 by Jack.Porter
Enabled refraction on tvOS
#jira UE-47229
Change 3606546 by Dmitriy.Dyomin
Vulkan: Missed null check from CL# 3601439
Change 3606654 by Allan.Bentham
mobile post process shaders will not attempt depth buffer fetch, instead they will always read from the depth texture.
#jira UE-41919
Change 3606672 by Dmitriy.Dyomin
Fixed: Vulkan mode crashes without error on Tegra K1 Nvidia Shield due to OOM
- fixed r.MobileReduceLoadedMips has no effect
- added r.MobileMaxLoadedMips to set a limit to a number of mips
- reduced size of vulkan allocation pages on android
#jira UE-42838
Change 3607204 by Allan.Bentham
Do not attempt getprocaddress for GL_EXT_DEBUG_LABEL functions when the extension is not declared.
Change 3607214 by Nick.Shin
HTML5 - stats font crash fix
#jira UE-47485 ( Pri:1 - 4.18 ) Crash running Stat Command test in TM-Core on Firefox
Change 3609164 by Chris.Babcock
More informative Android SDK license requirements and errors
#jra UE-48837
#ue4
#android
Change 3609175 by Chris.Babcock
Linux build fix
#jira none
Change 3609516 by Dmitriy.Dyomin
Fixed: Decals in TM-ShaderModels appearing and disappearing when viewed at certain angles on Android
#jira UE-45342
Change 3609618 by Dmitriy.Dyomin
Back out changelist 3603933, to help merge from main
Change 3610979 by Peter.Sauerbrei
addition of asset catalogs for icons on Xcode 9 for iOS 11
Change 3612145 by Dmitriy.Dyomin
Resubmitting CL #3603933 (shader cache fixes)
Change 3613981 by Chris.Babcock
Fix issue with Android password keyboard input
#jira WEX-7343
#ue4
#android
Change 3614375 by Sorin.Gradinaru
#jira UE-44656 StrategyGame Crashes on launch on KindleFire 5th Gen.
Kindle Fire HD7 5th (CPU Mali 450) seems to have problems with thread rendering, crashing when returning to the main thread.
Added new device profile [Android_Mali_4xx_KindleFire] with a new cvar r.AndroidDisableThreadedRenderingFirstLoad=1, disabling movie player rendering on the intial screen. For subsequent loading screens, the (same) code apparently runs Ok.
A warning "Initial loading screen disabled from BaseDeviceProfiles.ini: r.AndroidDisableThreadedRenderingFirstLoad=1" should appear when the thread rendering is disabled
Change 3614971 by Cosmin.Sulea
UE-46769 - GitHub 3745 : bForcePVRTC4 was ignored.
#jira UE-46769
Change 3616431 by Peter.Sauerbrei
PR3657,3658 - fixes for InApp purchase bugs courtesy of nverenik
Change 3617306 by Jack.Porter
Fix issue where undocked tabs had no way to be made visible again when hidden
#jira UE-12044
Change 3617312 by Jack.Porter
Find a new best MobileDirectionalLights[channel] when then current one is removed from the world (eg by a level streaming operation)
#jira UE-47135
#3785
Change 3617383 by Dmitriy.Dyomin
Vk - only dynamic buffers in HostVisible on UMA devices
Change 3617437 by Dmitriy.Dyomin
Vk - SRV allocates one BufferView for each buffer in FVulkanResourceMultiBuffer, so they can be reused (contributed by Samsung)
Change 3617474 by Dmitriy.Dyomin
Vk - Don't use fences on image acquire on Android
Change 3617483 by Dmitriy.Dyomin
Vk - Remove redundant dynamic state setup (viewport, scissor, stencilref) (contributed by Samsung)
Change 3617521 by Dmitriy.Dyomin
Fix CIS warnings
Change 3617574 by Dmitriy.Dyomin
Vk - Optimized RenderPass pool and Framebuffer pool (reduced vkObject count) (contributed by Samsung)
ProtoStar: Framebuffer count : 133 -> 108, Renderpass count : 21 -> 18
Change 3617585 by Dmitriy.Dyomin
compile fix for CL# 3617574
Change 3617849 by Allan.Bentham
Log UnsatisfiedLinkError's content when loadlibrary fails.
Change 3617945 by Chris.Babcock
Allow UPL variable expansion in addPermission, addFeature, and addLibrary
#jira UE-47421
#ue4
#android
Change 3618097 by Allan.Bentham
Fix Y axis switch with android GLES when rendering triangles to canvas.
#jira UE-44510
Change 3618733 by Peter.Sauerbrei
fix from Dev-Rendering for tvOS shader compilation
Change 3618761 by Peter.Sauerbrei
fix for shader crash on startup on iOS
Change 3618769 by Peter.Sauerbrei
bump metal shader guid to force a rebuild of shaders
Change 3620061 by Peter.Sauerbrei
fix for resource directory on Asset catalogs
#jira UE-49074
Change 3620520 by Peter.Sauerbrei
remove the texture warning, the logic was incorrect and in the end we don't need the warning
#jira UE-49057
Change 3621811 by Allan.Bentham
Add mipindex and array slice index to framebuffer hashing code.
#jira UE-49171
Change 3624410 by Jack.Porter
Fix issue where the Shared Material Native Libraries checkbox causes packaging for Android to fail
#jira UE-49105
Change 3627361 by Jack.Porter
Fixing case on iOS files
#jira None
Change 3627362 by Jack.Porter
Fixed case on IOS files
#jira None
[CL 3627373 by Jack Porter in Main branch]
867 lines
36 KiB
C++
867 lines
36 KiB
C++
// Copyright 1998-2017 Epic Games, Inc. All Rights Reserved.
|
|
|
|
#include "AndroidTargetSettingsCustomization.h"
|
|
#include "Misc/Paths.h"
|
|
#include "Layout/Margin.h"
|
|
#include "Widgets/DeclarativeSyntaxSupport.h"
|
|
#include "Engine/GameViewportClient.h"
|
|
#include "Widgets/SBoxPanel.h"
|
|
#include "Engine/GameEngine.h"
|
|
#include "Framework/Text/SlateHyperlinkRun.h"
|
|
#include "Widgets/Layout/SBorder.h"
|
|
#include "Widgets/Text/STextBlock.h"
|
|
#include "Widgets/Text/SRichTextBlock.h"
|
|
#include "Widgets/Layout/SBox.h"
|
|
#include "Widgets/Input/SButton.h"
|
|
#include "EditorStyleSet.h"
|
|
#include "AndroidRuntimeSettings.h"
|
|
#include "PropertyHandle.h"
|
|
#include "DetailLayoutBuilder.h"
|
|
#include "DetailWidgetRow.h"
|
|
#include "IDetailPropertyRow.h"
|
|
#include "DetailCategoryBuilder.h"
|
|
|
|
#include "SExternalImageReference.h"
|
|
#include "SHyperlinkLaunchURL.h"
|
|
#include "SPlatformSetupMessage.h"
|
|
#include "PlatformIconInfo.h"
|
|
#include "SourceControlHelpers.h"
|
|
#include "ManifestUpdateHelper.h"
|
|
#include "Framework/Notifications/NotificationManager.h"
|
|
#include "Widgets/Notifications/SNotificationList.h"
|
|
#include "Misc/EngineBuildSettings.h"
|
|
#include "InstalledPlatformInfo.h"
|
|
|
|
#include "AndroidLicenseDialog.h"
|
|
#include "Interfaces/IMainFrameModule.h"
|
|
#include "Framework/Application/SlateApplication.h"
|
|
|
|
#define LOCTEXT_NAMESPACE "AndroidRuntimeSettings"
|
|
|
|
//////////////////////////////////////////////////////////////////////////
|
|
// FAndroidTargetSettingsCustomization
|
|
namespace FAndroidTargetSettingsCustomizationConstants
|
|
{
|
|
const FText DisabledTip = LOCTEXT("GitHubSourceRequiredToolTip", "This requires GitHub source.");
|
|
}
|
|
|
|
TSharedRef<IDetailCustomization> FAndroidTargetSettingsCustomization::MakeInstance()
|
|
{
|
|
return MakeShareable(new FAndroidTargetSettingsCustomization);
|
|
}
|
|
|
|
FAndroidTargetSettingsCustomization::FAndroidTargetSettingsCustomization()
|
|
: LastLicenseChecktime(-1.0)
|
|
, AndroidRelativePath(TEXT(""))
|
|
, EngineAndroidPath(FPaths::EngineDir() + TEXT("Build/Android/Java"))
|
|
, GameAndroidPath(FPaths::ProjectDir() + TEXT("Build/Android"))
|
|
, EngineGooglePlayAppIDPath(EngineAndroidPath / TEXT("res") / TEXT("values") / TEXT("GooglePlayAppID.xml"))
|
|
, GameGooglePlayAppIDPath(GameAndroidPath / TEXT("res") / TEXT("values") / TEXT("GooglePlayAppID.xml"))
|
|
, EngineProguardPath(EngineAndroidPath / TEXT("proguard-project.txt"))
|
|
, GameProguardPath(GameAndroidPath / TEXT("proguard-project.txt"))
|
|
, EngineProjectPropertiesPath(EngineAndroidPath / TEXT("project.properties"))
|
|
, GameProjectPropertiesPath(GameAndroidPath / TEXT("project.properties"))
|
|
{
|
|
new (IconNames) FPlatformIconInfo(TEXT("res/drawable/icon.png"), LOCTEXT("SettingsIcon", "Icon"), FText::GetEmpty(), 48, 48, FPlatformIconInfo::Required);
|
|
new (IconNames) FPlatformIconInfo(TEXT("res/drawable-ldpi/icon.png"), LOCTEXT("SettingsIcon_LDPI", "LDPI Icon"), FText::GetEmpty(), 36, 36, FPlatformIconInfo::Required);
|
|
new (IconNames) FPlatformIconInfo(TEXT("res/drawable-mdpi/icon.png"), LOCTEXT("SettingsIcon_MDPI", "MDPI Icon"), FText::GetEmpty(), 48, 48, FPlatformIconInfo::Required);
|
|
new (IconNames) FPlatformIconInfo(TEXT("res/drawable-hdpi/icon.png"), LOCTEXT("SettingsIcon_HDPI", "HDPI Icon"), FText::GetEmpty(), 72, 72, FPlatformIconInfo::Required);
|
|
new (IconNames) FPlatformIconInfo(TEXT("res/drawable-xhdpi/icon.png"), LOCTEXT("SettingsIcon_XHDPI", "XHDPI Icon"), FText::GetEmpty(), 96, 96, FPlatformIconInfo::Required);
|
|
|
|
new (LaunchImageNames)FPlatformIconInfo(TEXT("res/drawable/downloadimagev.png"), LOCTEXT("SettingsIcon_DownloadImageV", "Download Background Vertical Image"), FText::GetEmpty(), 720, 1280, FPlatformIconInfo::Required);
|
|
new (LaunchImageNames)FPlatformIconInfo(TEXT("res/drawable/downloadimageh.png"), LOCTEXT("SettingsIcon_DownloadImageH", "Download Background Horizontal Image"), FText::GetEmpty(), 1280, 720, FPlatformIconInfo::Required);
|
|
new (LaunchImageNames)FPlatformIconInfo(TEXT("res/drawable/splashscreen_portrait.png"), LOCTEXT("LaunchImage_Portrait", "Launch Portrait"), FText::GetEmpty(), 360, 640, FPlatformIconInfo::Required);
|
|
new (LaunchImageNames)FPlatformIconInfo(TEXT("res/drawable/splashscreen_landscape.png"), LOCTEXT("LaunchImage_Landscape", "Launch Landscape"), FText::GetEmpty(), 640, 360, FPlatformIconInfo::Required);
|
|
|
|
new (DaydreamAppTileImageNames) FPlatformIconInfo(TEXT("res/drawable-nodpi/vr_icon.png"), LOCTEXT("AppTile_Icon", "App Tile Icon"), FText::GetEmpty(), 512, 512, FPlatformIconInfo::Optional);
|
|
new (DaydreamAppTileImageNames) FPlatformIconInfo(TEXT("res/drawable-nodpi/vr_icon_background.png"), LOCTEXT("AppTile_Icon_Background", "App Tile Icon Background"), FText::GetEmpty(), 512, 512, FPlatformIconInfo::Optional);
|
|
}
|
|
|
|
void FAndroidTargetSettingsCustomization::CustomizeDetails(IDetailLayoutBuilder& DetailLayout)
|
|
{
|
|
SavedLayoutBuilder = &DetailLayout;
|
|
|
|
BuildAppManifestSection(DetailLayout);
|
|
BuildIconSection(DetailLayout);
|
|
BuildLaunchImageSection(DetailLayout);
|
|
BuildDaydreamAppTileImageSection(DetailLayout);
|
|
BuildGraphicsDebuggerSection(DetailLayout);
|
|
AudioPluginWidgetManager.BuildAudioCategory(DetailLayout, EAudioPlatform::Android);
|
|
}
|
|
|
|
static void OnBrowserLinkClicked(const FSlateHyperlinkRun::FMetadata& Metadata)
|
|
{
|
|
const FString* URL = Metadata.Find(TEXT("href"));
|
|
|
|
if(URL)
|
|
{
|
|
FPlatformProcess::LaunchURL(**URL, nullptr, nullptr);
|
|
}
|
|
}
|
|
|
|
|
|
void FAndroidTargetSettingsCustomization::BuildAppManifestSection(IDetailLayoutBuilder& DetailLayout)
|
|
{
|
|
// Cache some categories
|
|
IDetailCategoryBuilder& APKPackagingCategory = DetailLayout.EditCategory(TEXT("APKPackaging"));
|
|
IDetailCategoryBuilder& BuildCategory = DetailLayout.EditCategory(TEXT("Build"));
|
|
IDetailCategoryBuilder& AdvancedBuildCategory = DetailLayout.EditCategory(TEXT("AdvancedBuild"));
|
|
AdvancedBuildCategory.InitiallyCollapsed(true);
|
|
|
|
IDetailCategoryBuilder& SigningCategory = DetailLayout.EditCategory(TEXT("DistributionSigning"));
|
|
|
|
TSharedRef<SPlatformSetupMessage> PlatformSetupMessage = SNew(SPlatformSetupMessage, GameProjectPropertiesPath)
|
|
.PlatformName(LOCTEXT("AndroidPlatformName", "Android"))
|
|
.OnSetupClicked(this, &FAndroidTargetSettingsCustomization::CopySetupFilesIntoProject);
|
|
|
|
SetupForPlatformAttribute = PlatformSetupMessage->GetReadyToGoAttribute();
|
|
|
|
APKPackagingCategory.AddCustomRow(LOCTEXT("Warning", "Warning"), false)
|
|
.WholeRowWidget
|
|
[
|
|
PlatformSetupMessage
|
|
];
|
|
|
|
APKPackagingCategory.AddCustomRow(LOCTEXT("UpgradeInfo", "Upgrade Info"), false)
|
|
.WholeRowWidget
|
|
[
|
|
SNew(SBorder)
|
|
.Padding(1)
|
|
[
|
|
SNew(SHorizontalBox)
|
|
+ SHorizontalBox::Slot()
|
|
.Padding(FMargin(10, 10, 10, 10))
|
|
.FillWidth(1.0f)
|
|
[
|
|
SNew(SRichTextBlock)
|
|
.Text(LOCTEXT("UpgradeInfoMessage", "<RichTextBlock.TextHighlight>Note to users from 4.6 or earlier</>: We now <RichTextBlock.TextHighlight>GENERATE</> an AndroidManifest.xml when building, so if you have customized your .xml file, you will need to put all of your changes into the below settings. Note that we don't touch your AndroidManifest.xml that is in your project directory.\nAdditionally, we no longer use SigningConfig.xml, the settings are now set in the Distribution Signing section.\n\n<RichTextBlock.TextHighlight>NOTE</>: You must accept the SDK license agreement (click on button below) to use Gradle if it isn't grayed out."))
|
|
.TextStyle(FEditorStyle::Get(), "MessageLog")
|
|
.DecoratorStyleSet(&FEditorStyle::Get())
|
|
.AutoWrapText(true)
|
|
+ SRichTextBlock::HyperlinkDecorator(TEXT("browser"), FSlateHyperlinkRun::FOnClick::CreateStatic(&OnBrowserLinkClicked))
|
|
]
|
|
]
|
|
];
|
|
|
|
APKPackagingCategory.AddCustomRow(LOCTEXT("AndroidSDKLicenses", "Android SDK Licenses"), false)
|
|
.WholeRowWidget
|
|
[
|
|
SNew(SHorizontalBox)
|
|
+ SHorizontalBox::Slot()
|
|
.Padding(FMargin(0, 5, 5, 5))
|
|
.AutoWidth()
|
|
[
|
|
SNew(SButton)
|
|
.HAlign(HAlign_Center)
|
|
.VAlign(VAlign_Center)
|
|
.OnClicked(this, &FAndroidTargetSettingsCustomization::OnAcceptSDKLicenseClicked)
|
|
.IsEnabled(this, &FAndroidTargetSettingsCustomization::IsLicenseInvalid)
|
|
[
|
|
SNew(STextBlock)
|
|
.Text(LOCTEXT("AcceptSDKLicense", "Accept SDK License"))
|
|
]
|
|
]
|
|
];
|
|
|
|
APKPackagingCategory.AddCustomRow(LOCTEXT("BuildFolderLabel", "Build Folder"), false)
|
|
.IsEnabled(SetupForPlatformAttribute)
|
|
.NameContent()
|
|
[
|
|
SNew(SHorizontalBox)
|
|
+ SHorizontalBox::Slot()
|
|
.Padding(FMargin(0, 1, 0, 1))
|
|
.FillWidth(1.0f)
|
|
[
|
|
SNew(STextBlock)
|
|
.Text(LOCTEXT("BuildFolderLabel", "Build Folder"))
|
|
.Font(DetailLayout.GetDetailFont())
|
|
]
|
|
]
|
|
.ValueContent()
|
|
[
|
|
SNew(SHorizontalBox)
|
|
+SHorizontalBox::Slot()
|
|
.AutoWidth()
|
|
[
|
|
SNew(SButton)
|
|
.Text(LOCTEXT("OpenBuildFolderButton", "Open Build Folder"))
|
|
.ToolTipText(LOCTEXT("OpenManifestFolderButton_Tooltip", "Opens the folder containing the build files in Explorer or Finder (it's recommended you check these in to source control to share with your team)"))
|
|
.OnClicked(this, &FAndroidTargetSettingsCustomization::OpenBuildFolder)
|
|
]
|
|
];
|
|
|
|
// Signing category
|
|
SigningCategory.AddCustomRow(LOCTEXT("SigningHyperlink", "Signing Hyperlink"), false)
|
|
.WholeRowWidget
|
|
[
|
|
SNew(SBox)
|
|
.HAlign(HAlign_Center)
|
|
[
|
|
SNew(SHyperlinkLaunchURL, TEXT("http://developer.android.com/tools/publishing/app-signing.html#releasemode"))
|
|
.Text(LOCTEXT("AndroidDeveloperSigningPage", "Android Developer page on Signing for Distribution"))
|
|
.ToolTipText(LOCTEXT("AndroidDeveloperSigningPageTooltip", "Opens a page that discusses the signing using keytool"))
|
|
]
|
|
];
|
|
|
|
// Google Play category
|
|
IDetailCategoryBuilder& GooglePlayCategory = DetailLayout.EditCategory(TEXT("GooglePlayServices"));
|
|
|
|
TSharedRef<SPlatformSetupMessage> GooglePlaySetupMessage = SNew(SPlatformSetupMessage, GameGooglePlayAppIDPath)
|
|
.PlatformName(LOCTEXT("GooglePlayPlatformName", "Google Play services"))
|
|
.OnSetupClicked(this, &FAndroidTargetSettingsCustomization::CopyGooglePlayAppIDFileIntoProject);
|
|
|
|
SetupForGooglePlayAttribute = GooglePlaySetupMessage->GetReadyToGoAttribute();
|
|
|
|
GooglePlayCategory.AddCustomRow(LOCTEXT("Warning", "Warning"), false)
|
|
.WholeRowWidget
|
|
[
|
|
GooglePlaySetupMessage
|
|
];
|
|
|
|
GooglePlayCategory.AddCustomRow(LOCTEXT("AppIDHyperlink", "App ID Hyperlink"), false)
|
|
.WholeRowWidget
|
|
[
|
|
SNew(SBox)
|
|
.HAlign(HAlign_Center)
|
|
[
|
|
SNew(SHyperlinkLaunchURL, TEXT("http://developer.android.com/google/index.html"))
|
|
.Text(LOCTEXT("GooglePlayDeveloperPage", "Android Developer Page on Google Play services"))
|
|
.ToolTipText(LOCTEXT("GooglePlayDeveloperPageTooltip", "Opens a page that discusses Google Play services"))
|
|
]
|
|
];
|
|
|
|
TSharedRef<IPropertyHandle> EnabledProperty = DetailLayout.GetProperty(GET_MEMBER_NAME_CHECKED(UAndroidRuntimeSettings, bEnableGooglePlaySupport));
|
|
GooglePlayCategory.AddProperty(EnabledProperty)
|
|
.EditCondition(SetupForGooglePlayAttribute, NULL);
|
|
|
|
TSharedRef<IPropertyHandle> AppIDProperty = DetailLayout.GetProperty(GET_MEMBER_NAME_CHECKED(UAndroidRuntimeSettings, GamesAppID));
|
|
AppIDProperty->SetOnPropertyValueChanged(FSimpleDelegate::CreateRaw(this, &FAndroidTargetSettingsCustomization::OnAppIDModified));
|
|
GooglePlayCategory.AddProperty(AppIDProperty)
|
|
.EditCondition(SetupForGooglePlayAttribute, NULL);
|
|
|
|
TSharedRef<IPropertyHandle> AdMobAdUnitIDProperty = DetailLayout.GetProperty(GET_MEMBER_NAME_CHECKED(UAndroidRuntimeSettings, AdMobAdUnitID));
|
|
AdMobAdUnitIDProperty->MarkHiddenByCustomization();
|
|
|
|
TSharedRef<IPropertyHandle> AdMobAdUnitIDsProperty = DetailLayout.GetProperty(GET_MEMBER_NAME_CHECKED(UAndroidRuntimeSettings, AdMobAdUnitIDs));
|
|
GooglePlayCategory.AddProperty(AdMobAdUnitIDsProperty)
|
|
.EditCondition(SetupForGooglePlayAttribute, NULL);
|
|
|
|
TSharedRef<IPropertyHandle> GooglePlayLicenseKeyProperty = DetailLayout.GetProperty(GET_MEMBER_NAME_CHECKED(UAndroidRuntimeSettings, GooglePlayLicenseKey));
|
|
GooglePlayCategory.AddProperty(GooglePlayLicenseKeyProperty)
|
|
.EditCondition(SetupForGooglePlayAttribute, NULL);
|
|
|
|
#define SETUP_ANDROIDARCH_PROP(ArchFragment, PropName, Category, Tip) \
|
|
{ \
|
|
TSharedRef<IPropertyHandle> PropertyHandle = DetailLayout.GetProperty(GET_MEMBER_NAME_CHECKED(UAndroidRuntimeSettings, PropName)); \
|
|
Category.AddProperty(PropertyHandle) \
|
|
.IsEnabled(FInstalledPlatformInfo::Get().IsValidPlatformArchitecture(TEXT("Android"), ArchFragment)) \
|
|
.ToolTip(FInstalledPlatformInfo::Get().IsValidPlatformArchitecture(TEXT("Android"), ArchFragment) ? Tip : FAndroidTargetSettingsCustomizationConstants::DisabledTip); \
|
|
}
|
|
|
|
#define SETUP_SOURCEONLY_PROP(PropName, Category, Tip) \
|
|
{ \
|
|
TSharedRef<IPropertyHandle> PropertyHandle = DetailLayout.GetProperty(GET_MEMBER_NAME_CHECKED(UAndroidRuntimeSettings, PropName)); \
|
|
Category.AddProperty(PropertyHandle) \
|
|
.IsEnabled(FEngineBuildSettings::IsSourceDistribution()) \
|
|
.ToolTip(FEngineBuildSettings::IsSourceDistribution() ? Tip : FAndroidTargetSettingsCustomizationConstants::DisabledTip); \
|
|
}
|
|
SETUP_ANDROIDARCH_PROP(TEXT("-armv7"), bBuildForArmV7, BuildCategory, LOCTEXT("BuildForArmV7ToolTip", "Enable ArmV7 CPU architecture support? (this will be used if all CPU architecture types are unchecked)"));
|
|
SETUP_ANDROIDARCH_PROP(TEXT("-arm64"), bBuildForArm64, BuildCategory, LOCTEXT("BuildForArm64ToolTip", "Enable Arm64 CPU architecture support? (use at least NDK r11c, requires Lollipop (android-21) minimum)"));
|
|
SETUP_ANDROIDARCH_PROP(TEXT("-x86"), bBuildForX86, BuildCategory, LOCTEXT("BuildForX86ToolTip", "Enable X86 CPU architecture support?"));
|
|
SETUP_ANDROIDARCH_PROP(TEXT("-x64"), bBuildForX8664, BuildCategory, LOCTEXT("BuildForX8664ToolTip", "Enable X86-64 CPU architecture support?"));
|
|
SETUP_ANDROIDARCH_PROP(TEXT("-es2"), bBuildForES2, BuildCategory, LOCTEXT("BuildForES2ToolTip", "Enable OpenGL ES2 rendering support? (this will be used if rendering types are unchecked)"));
|
|
SETUP_ANDROIDARCH_PROP(TEXT("-esdeferred"), bBuildForESDeferred, BuildCategory, LOCTEXT("BuildForESDeferredToolTip", "Enable the Deferred Shading Renderer using OpenGL ES 3.1+AEP (Android Extension Pack)? This setting is not recommended for general use and is supported only on Nvidia K1 and X1 devices."));
|
|
|
|
// @todo android fat binary: Put back in when we expose those
|
|
// SETUP_SOURCEONLY_PROP(bSplitIntoSeparateApks, BuildCategory, LOCTEXT("SplitIntoSeparateAPKsToolTip", "If checked, CPU architectures and rendering types will be split into separate .apk files"));
|
|
|
|
// check for Gradle change
|
|
TSharedRef<IPropertyHandle> EnableGradleProperty = DetailLayout.GetProperty(GET_MEMBER_NAME_CHECKED(UAndroidRuntimeSettings, bEnableGradle));
|
|
FSimpleDelegate EnableGradleChange = FSimpleDelegate::CreateSP(this, &FAndroidTargetSettingsCustomization::OnEnableGradleChange);
|
|
EnableGradleProperty->SetOnPropertyValueChanged(EnableGradleChange);
|
|
}
|
|
|
|
bool FAndroidTargetSettingsCustomization::IsLicenseInvalid() const
|
|
{
|
|
static bool bInvalid = true;
|
|
|
|
// only check every 30 seconds after first time
|
|
double CurrentTime = FApp::GetCurrentTime();
|
|
if (LastLicenseChecktime < 0.0 || CurrentTime - LastLicenseChecktime >= 30.0)
|
|
{
|
|
const_cast<FAndroidTargetSettingsCustomization *>(this)->LastLicenseChecktime = CurrentTime;
|
|
|
|
TSharedPtr<SAndroidLicenseDialog> LicenseDialog = SNew(SAndroidLicenseDialog);
|
|
bInvalid = !LicenseDialog->HasLicense();
|
|
}
|
|
|
|
return bInvalid;
|
|
}
|
|
|
|
void FAndroidTargetSettingsCustomization::OnLicenseAccepted()
|
|
{
|
|
LastLicenseChecktime = -1.0;
|
|
}
|
|
|
|
FReply FAndroidTargetSettingsCustomization::OnAcceptSDKLicenseClicked()
|
|
{
|
|
// only show if don't have a valid license
|
|
TSharedPtr<SAndroidLicenseDialog> LicenseDialog = SNew(SAndroidLicenseDialog);
|
|
if (!LicenseDialog->HasLicense())
|
|
{
|
|
FSimpleDelegate LicenseAcceptedCallback = FSimpleDelegate::CreateSP(this, &FAndroidTargetSettingsCustomization::OnLicenseAccepted);
|
|
LicenseDialog->SetLicenseAcceptedCallback(LicenseAcceptedCallback);
|
|
|
|
const FText AndroidLicenseWindowTitle = LOCTEXT("AndroidLicenseUnrealEditor", "Android SDK License");
|
|
|
|
TSharedPtr<SWindow> AndroidLicenseWindow =
|
|
SNew(SWindow)
|
|
.Title(AndroidLicenseWindowTitle)
|
|
.ClientSize(FVector2D(600.f, 700.f))
|
|
.SupportsMaximize(false)
|
|
.SupportsMinimize(false)
|
|
.SizingRule(ESizingRule::FixedSize)
|
|
[
|
|
LicenseDialog.ToSharedRef()
|
|
];
|
|
|
|
IMainFrameModule& MainFrame = FModuleManager::LoadModuleChecked<IMainFrameModule>("MainFrame");
|
|
TSharedPtr<SWindow> ParentWindow = MainFrame.GetParentWindow();
|
|
|
|
if (ParentWindow.IsValid())
|
|
{
|
|
FSlateApplication::Get().AddModalWindow(AndroidLicenseWindow.ToSharedRef(), ParentWindow.ToSharedRef());
|
|
}
|
|
else
|
|
{
|
|
FSlateApplication::Get().AddWindow(AndroidLicenseWindow.ToSharedRef());
|
|
}
|
|
}
|
|
|
|
LastLicenseChecktime = -1.0;
|
|
|
|
return FReply::Handled();
|
|
}
|
|
|
|
void FAndroidTargetSettingsCustomization::OnEnableGradleChange()
|
|
{
|
|
// only need to do this if enabling
|
|
if (!GetDefault<UAndroidRuntimeSettings>()->bEnableGradle)
|
|
{
|
|
return;
|
|
}
|
|
|
|
// only show if don't have a valid license
|
|
TSharedPtr<SAndroidLicenseDialog> LicenseDialog = SNew(SAndroidLicenseDialog);
|
|
if (!LicenseDialog->HasLicense())
|
|
{
|
|
FSimpleDelegate LicenseAcceptedCallback = FSimpleDelegate::CreateSP(this, &FAndroidTargetSettingsCustomization::OnLicenseAccepted);
|
|
LicenseDialog->SetLicenseAcceptedCallback(LicenseAcceptedCallback);
|
|
|
|
const FText AndroidLicenseWindowTitle = LOCTEXT("AndroidLicenseUnrealEditor", "Android SDK License");
|
|
|
|
TSharedPtr<SWindow> AndroidLicenseWindow =
|
|
SNew(SWindow)
|
|
.Title(AndroidLicenseWindowTitle)
|
|
.ClientSize(FVector2D(600.f, 700.f))
|
|
.HasCloseButton(false)
|
|
.SupportsMaximize(false)
|
|
.SupportsMinimize(false)
|
|
.SizingRule(ESizingRule::FixedSize)
|
|
[
|
|
LicenseDialog.ToSharedRef()
|
|
];
|
|
|
|
IMainFrameModule& MainFrame = FModuleManager::LoadModuleChecked<IMainFrameModule>("MainFrame");
|
|
TSharedPtr<SWindow> ParentWindow = MainFrame.GetParentWindow();
|
|
|
|
if (ParentWindow.IsValid())
|
|
{
|
|
FSlateApplication::Get().AddModalWindow(AndroidLicenseWindow.ToSharedRef(), ParentWindow.ToSharedRef());
|
|
}
|
|
else
|
|
{
|
|
FSlateApplication::Get().AddWindow(AndroidLicenseWindow.ToSharedRef());
|
|
}
|
|
}
|
|
}
|
|
|
|
void FAndroidTargetSettingsCustomization::BuildIconSection(IDetailLayoutBuilder& DetailLayout)
|
|
{
|
|
// Icon category
|
|
IDetailCategoryBuilder& IconCategory = DetailLayout.EditCategory(TEXT("Icons"));
|
|
|
|
IconCategory.AddCustomRow(LOCTEXT("IconsHyperlink", "Icons Hyperlink"), false)
|
|
.WholeRowWidget
|
|
[
|
|
SNew(SBox)
|
|
.HAlign(HAlign_Center)
|
|
[
|
|
SNew(SHyperlinkLaunchURL, TEXT("http://developer.android.com/design/style/iconography.html"))
|
|
.Text(LOCTEXT("AndroidDeveloperIconographyPage", "Android Developer Page on Iconography"))
|
|
.ToolTipText(LOCTEXT("AndroidDeveloperIconographyPageTooltip", "Opens a page on Android Iconography"))
|
|
]
|
|
];
|
|
|
|
for (const FPlatformIconInfo& Info : IconNames)
|
|
{
|
|
const FString AutomaticImagePath = EngineAndroidPath / Info.IconPath;
|
|
const FString TargetImagePath = GameAndroidPath / Info.IconPath;
|
|
|
|
IconCategory.AddCustomRow(Info.IconName)
|
|
.NameContent()
|
|
[
|
|
SNew(SHorizontalBox)
|
|
+SHorizontalBox::Slot()
|
|
.Padding( FMargin( 0, 1, 0, 1 ) )
|
|
.FillWidth(1.0f)
|
|
[
|
|
SNew(STextBlock)
|
|
.Text(Info.IconName)
|
|
.Font(DetailLayout.GetDetailFont())
|
|
]
|
|
]
|
|
.ValueContent()
|
|
.MaxDesiredWidth(400.0f)
|
|
.MinDesiredWidth(100.0f)
|
|
[
|
|
SNew(SHorizontalBox)
|
|
+SHorizontalBox::Slot()
|
|
.FillWidth(1.0f)
|
|
.VAlign(VAlign_Center)
|
|
[
|
|
SNew(SExternalImageReference, AutomaticImagePath, TargetImagePath)
|
|
.FileDescription(Info.IconDescription)
|
|
.RequiredSize(Info.IconRequiredSize)
|
|
.MaxDisplaySize(FVector2D(FMath::Min(96, Info.IconRequiredSize.X), FMath::Min(96, Info.IconRequiredSize.Y)))
|
|
]
|
|
];
|
|
}
|
|
}
|
|
|
|
void FAndroidTargetSettingsCustomization::BuildLaunchImageSection(IDetailLayoutBuilder& DetailLayout)
|
|
{
|
|
// Add the launch images
|
|
IDetailCategoryBuilder& LaunchImageCategory = DetailLayout.EditCategory(TEXT("LaunchImages"));
|
|
LaunchImageCategory.AddCustomRow(LOCTEXT("LaunchImageInfo", "Launch Image Info"), false)
|
|
.WholeRowWidget
|
|
[
|
|
SNew(SBorder)
|
|
.Padding(1)
|
|
[
|
|
SNew(SHorizontalBox)
|
|
+ SHorizontalBox::Slot()
|
|
.Padding(FMargin(10, 10, 10, 10))
|
|
.FillWidth(1.0f)
|
|
[
|
|
SNew(SRichTextBlock)
|
|
.Text(LOCTEXT("LaunchImageInfoMessage", "The <RichTextBlock.TextHighlight>Download Background</> image is used as the background for OBB downloading. The <RichTextBlock.TextHighlight>Launch Portrait</> image is used as a splash screen for applications with Portrait, Reverse Portrait, Sensor Portrait, Sensor, or Full Sensor orientation. The <RichTextBlock.TextHighlight>Launch Landscape</> image is used as a splash screen for applications with Landscape, Sensor Landscape, Reverse Landscape, Sensor, or Full Sensor orientation.\n\nThe launch images will be scaled to fit the device in the active orientation. Additional optional launch images may be provided as overrides for LDPI, MDPI, HDPI, and XHDPI by placing them in the project's corresponding Build/Android/res/drawable-* directory."))
|
|
.TextStyle(FEditorStyle::Get(), "MessageLog")
|
|
.DecoratorStyleSet(&FEditorStyle::Get())
|
|
.AutoWrapText(true)
|
|
+ SRichTextBlock::HyperlinkDecorator(TEXT("browser"), FSlateHyperlinkRun::FOnClick::CreateStatic(&OnBrowserLinkClicked))
|
|
]
|
|
]
|
|
];
|
|
|
|
const FVector2D LaunchImageMaxSize(150.0f, 150.0f);
|
|
|
|
for (const FPlatformIconInfo& Info : LaunchImageNames)
|
|
{
|
|
const FString AutomaticImagePath = EngineAndroidPath / Info.IconPath;
|
|
const FString TargetImagePath = GameAndroidPath / Info.IconPath;
|
|
|
|
LaunchImageCategory.AddCustomRow(Info.IconName)
|
|
.NameContent()
|
|
[
|
|
SNew(SHorizontalBox)
|
|
+ SHorizontalBox::Slot()
|
|
.Padding(FMargin(0, 1, 0, 1))
|
|
.FillWidth(1.0f)
|
|
[
|
|
SNew(STextBlock)
|
|
.Text(Info.IconName)
|
|
.Font(DetailLayout.GetDetailFont())
|
|
]
|
|
]
|
|
.ValueContent()
|
|
.MaxDesiredWidth(400.0f)
|
|
.MinDesiredWidth(100.0f)
|
|
[
|
|
SNew(SHorizontalBox)
|
|
+ SHorizontalBox::Slot()
|
|
.FillWidth(1.0f)
|
|
.VAlign(VAlign_Center)
|
|
[
|
|
SNew(SExternalImageReference, AutomaticImagePath, TargetImagePath)
|
|
.FileDescription(Info.IconDescription)
|
|
// .RequiredSize(Info.IconRequiredSize)
|
|
.MaxDisplaySize(LaunchImageMaxSize)
|
|
]
|
|
];
|
|
}
|
|
}
|
|
|
|
void FAndroidTargetSettingsCustomization::BuildDaydreamAppTileImageSection(IDetailLayoutBuilder& DetailLayout)
|
|
{
|
|
// Daydream App Tile Category
|
|
IDetailCategoryBuilder& DaydreamAppTileCategory = DetailLayout.EditCategory(TEXT("DaydreamAppTile"));
|
|
|
|
for (const FPlatformIconInfo& Info : DaydreamAppTileImageNames)
|
|
{
|
|
const FString AutomaticImagePath = EngineAndroidPath / Info.IconPath;
|
|
const FString TargetImagePath = GameAndroidPath / Info.IconPath;
|
|
|
|
DaydreamAppTileCategory.AddCustomRow(Info.IconName)
|
|
.NameContent()
|
|
[
|
|
SNew(SHorizontalBox)
|
|
+SHorizontalBox::Slot()
|
|
.Padding( FMargin( 0, 1, 0, 1 ) )
|
|
.FillWidth(1.0f)
|
|
[
|
|
SNew(STextBlock)
|
|
.Text(Info.IconName)
|
|
.Font(DetailLayout.GetDetailFont())
|
|
]
|
|
]
|
|
.ValueContent()
|
|
.MaxDesiredWidth(400.0f)
|
|
.MinDesiredWidth(100.0f)
|
|
[
|
|
SNew(SHorizontalBox)
|
|
+SHorizontalBox::Slot()
|
|
.FillWidth(1.0f)
|
|
.VAlign(VAlign_Center)
|
|
[
|
|
SNew(SExternalImageReference, AutomaticImagePath, TargetImagePath)
|
|
.FileDescription(Info.IconDescription)
|
|
.RequiredSize(Info.IconRequiredSize)
|
|
.MaxDisplaySize(FVector2D(FMath::Min(96, Info.IconRequiredSize.X), FMath::Min(96, Info.IconRequiredSize.Y)))
|
|
]
|
|
];
|
|
}
|
|
}
|
|
|
|
FReply FAndroidTargetSettingsCustomization::OpenBuildFolder()
|
|
{
|
|
const FString BuildFolder = FPaths::ConvertRelativePathToFull(FPaths::GetPath(GameProjectPropertiesPath));
|
|
FPlatformProcess::ExploreFolder(*BuildFolder);
|
|
|
|
return FReply::Handled();
|
|
}
|
|
|
|
void FAndroidTargetSettingsCustomization::CopySetupFilesIntoProject()
|
|
{
|
|
// First copy the manifest, it must get copied
|
|
FText ErrorMessage;
|
|
if (!SourceControlHelpers::CopyFileUnderSourceControl(GameProjectPropertiesPath, EngineProjectPropertiesPath, LOCTEXT("ProjectProperties", "Project Properties"), /*out*/ ErrorMessage))
|
|
{
|
|
FNotificationInfo Info(ErrorMessage);
|
|
Info.ExpireDuration = 3.0f;
|
|
FSlateNotificationManager::Get().AddNotification(Info);
|
|
}
|
|
else
|
|
{
|
|
// Now try to copy all of the icons, etc... (these can be ignored if the file already exists)
|
|
for (const FPlatformIconInfo& Info : IconNames)
|
|
{
|
|
const FString EngineImagePath = EngineAndroidPath / Info.IconPath;
|
|
const FString ProjectImagePath = GameAndroidPath / Info.IconPath;
|
|
|
|
if (!FPaths::FileExists(ProjectImagePath))
|
|
{
|
|
SourceControlHelpers::CopyFileUnderSourceControl(ProjectImagePath, EngineImagePath, Info.IconName, /*out*/ ErrorMessage);
|
|
}
|
|
}
|
|
|
|
// Now try to copy all of the launch images... (these can be ignored if the file already exists)
|
|
for (const FPlatformIconInfo& Info : LaunchImageNames)
|
|
{
|
|
const FString EngineImagePath = EngineAndroidPath / Info.IconPath;
|
|
const FString ProjectImagePath = GameAndroidPath / Info.IconPath;
|
|
|
|
if (!FPaths::FileExists(ProjectImagePath))
|
|
{
|
|
SourceControlHelpers::CopyFileUnderSourceControl(ProjectImagePath, EngineImagePath, Info.IconName, /*out*/ ErrorMessage);
|
|
}
|
|
}
|
|
|
|
// Now try to copy all of the launch images... (these can be ignored if the file already exists)
|
|
for (const FPlatformIconInfo& Info : DaydreamAppTileImageNames)
|
|
{
|
|
const FString EngineImagePath = EngineAndroidPath / Info.IconPath;
|
|
const FString ProjectImagePath = GameAndroidPath / Info.IconPath;
|
|
|
|
if (!FPaths::FileExists(ProjectImagePath))
|
|
{
|
|
SourceControlHelpers::CopyFileUnderSourceControl(ProjectImagePath, EngineImagePath, Info.IconName, /*out*/ ErrorMessage);
|
|
}
|
|
}
|
|
|
|
// and copy the other files (aren't required)
|
|
//SourceControlHelpers::CopyFileUnderSourceControl(GameProguardPath, EngineProguardPath, LOCTEXT("Proguard", "Proguard Settings"), /*out*/ ErrorMessage);
|
|
}
|
|
|
|
SavedLayoutBuilder->ForceRefreshDetails();
|
|
}
|
|
|
|
void FAndroidTargetSettingsCustomization::CopyGooglePlayAppIDFileIntoProject()
|
|
{
|
|
FText ErrorMessage;
|
|
if (!SourceControlHelpers::CopyFileUnderSourceControl(GameGooglePlayAppIDPath, EngineGooglePlayAppIDPath, LOCTEXT("GooglePlayAppID", "GooglePlayAppID.xml"), /*out*/ ErrorMessage))
|
|
{
|
|
FNotificationInfo Info(ErrorMessage);
|
|
Info.ExpireDuration = 3.0f;
|
|
FSlateNotificationManager::Get().AddNotification(Info);
|
|
}
|
|
|
|
SavedLayoutBuilder->ForceRefreshDetails();
|
|
}
|
|
|
|
void FAndroidTargetSettingsCustomization::OnAppIDModified()
|
|
{
|
|
const FString NewIDString = GetDefault<UAndroidRuntimeSettings>()->GamesAppID;
|
|
|
|
if (NewIDString.Len() > 0 && !FCString::IsNumeric(*NewIDString))
|
|
{
|
|
FNotificationInfo Info(LOCTEXT("InvalidGamesAppID", "The Games App ID you provided is invalid"));
|
|
Info.ExpireDuration = 3.0f;
|
|
FSlateNotificationManager::Get().AddNotification(Info);
|
|
|
|
return;
|
|
}
|
|
|
|
if (FPaths::FileExists(GameGooglePlayAppIDPath))
|
|
{
|
|
FManifestUpdateHelper Updater(GameGooglePlayAppIDPath);
|
|
|
|
const FString AppIDTag(TEXT("name=\"app_id\">"));
|
|
const FString ClosingTag(TEXT("</string>"));
|
|
Updater.ReplaceKey(AppIDTag, ClosingTag, NewIDString);
|
|
|
|
Updater.Finalize(GameGooglePlayAppIDPath);
|
|
}
|
|
}
|
|
|
|
static EVisibility GraphicsDebuggerSettingsVisibility(EAndroidGraphicsDebugger::Type DebuggerType, TSharedPtr<IPropertyHandle> AndroidGraphicsDebuggerProperty)
|
|
{
|
|
uint8 ValueAsByte = 0;
|
|
FPropertyAccess::Result Result = AndroidGraphicsDebuggerProperty->GetValue(ValueAsByte);
|
|
if (Result == FPropertyAccess::Success && ValueAsByte == static_cast<uint8>(DebuggerType))
|
|
{
|
|
return EVisibility::Visible;
|
|
}
|
|
|
|
return EVisibility::Hidden;
|
|
}
|
|
|
|
static FText GetMaliGraphicsDebuggerHelpText()
|
|
{
|
|
const static FText InstallText(LOCTEXT("MGDInstallText", "Run the following command from a host command line from the target/unrooted directory located in the installation directory of the MGD tool, to install the MGD Daemon application on your device."));
|
|
const static FString InstallCommand(TEXT("adb install -r MGD.apk"));
|
|
const static FText RunText1(LOCTEXT("MGDIRunText1", "Run the following command from your host to establish a tunnel between your PC and the MGD Daemon. This needs to be done each time you connect your device by USB."));
|
|
const static FString RunCommand(TEXT("adb forward tcp:5002 tcp:5002"));
|
|
const static FText RunText2(LOCTEXT("MGDIRunText2", "Next, ensure you are running the daemon. Run the MGD Daemon application and switch it to the \"ON\" state"));
|
|
|
|
FFormatOrderedArguments Args;
|
|
Args.Add(InstallText);
|
|
Args.Add(FText::FromString(InstallCommand));
|
|
Args.Add(RunText1);
|
|
Args.Add(FText::FromString(RunCommand));
|
|
Args.Add(RunText2);
|
|
|
|
return FText::Format(LOCTEXT("MaliGraphicsDebuggerHelpText","<RichTextBlock.TextHighlight>Installation</>\n{0}\n{1}\n\n<RichTextBlock.TextHighlight>Run</>\n{2}\n{3}\n{4}"),
|
|
Args);
|
|
}
|
|
|
|
static FText GetAdrenoProfilerHelpText()
|
|
{
|
|
const static FText RunText(LOCTEXT("AdrenoRunText", "Before profiling, and after rebooting your Android device, you must enable debug mode by setting the following property from the command line:"));
|
|
const static FString RunCommand(TEXT("adb shell setprop debug.egl.profiler 1"));
|
|
|
|
FFormatOrderedArguments Args;
|
|
Args.Add(RunText);
|
|
Args.Add(FText::FromString(RunCommand));
|
|
|
|
return FText::Format(LOCTEXT("AdrenoHelpText","{0}\n{1}"), Args);
|
|
}
|
|
|
|
static FText GetRenderDocHelpText()
|
|
{
|
|
const static FText InstallText(LOCTEXT("RDOCInstallText", "Run the following command from a host command line from the android/apk/32 directory located in the installation directory of the RenderDoc tool, to install the RenderDocCmd application on your device."));
|
|
const static FString InstallCommand(TEXT("adb install -r RenderDocCmd.apk"));
|
|
|
|
const static FText RunText0(LOCTEXT("RDOCRunText0", "Open RenderDoc on the host"));
|
|
const static FText RunText1(LOCTEXT("RDOCRunText1", "1. In Tools -> Options -> Android, set the path to your adb executable."));
|
|
const static FText RunText2(LOCTEXT("RDOCRunText2", "2. Start the Remote Server using Tools -> Start Android Remote Server."));
|
|
const static FText RunText3(LOCTEXT("RDOCRunText3", "3. Check your device screen and 'Allow' RenderDocCmd to access files on your device."));
|
|
const static FText RunText4(LOCTEXT("RDOCRunText4", "4. Change your current Replay Context to your device using the bottom left menu, which should now show your device as Online."));
|
|
const static FText RunText5(LOCTEXT("RDOCRunText5", "5. In the capture executable tab, there is a button on the right of Executable Path that lets you select an installed Android package for capture."));
|
|
const static FText RunText6(LOCTEXT("RDOCRunText6", "6. Select your package and press the Launch button in the bottom right of the tab to start the package on the device."));
|
|
const static FText RunText7(LOCTEXT("RDOCRunText7", "7. If everything went well, a new tab will open with a button to Trigger captures."));
|
|
|
|
const static FText NoteText(LOCTEXT("RDOCNoteText", "If the latest RenderDoc release does not have Android functionality, download the latest nightly build."));
|
|
|
|
FFormatOrderedArguments Args;
|
|
Args.Add(InstallText);
|
|
Args.Add(FText::FromString(InstallCommand));
|
|
Args.Add(RunText0);
|
|
Args.Add(RunText1);
|
|
Args.Add(RunText2);
|
|
Args.Add(RunText3);
|
|
Args.Add(RunText4);
|
|
Args.Add(RunText5);
|
|
Args.Add(RunText6);
|
|
Args.Add(RunText7);
|
|
Args.Add(NoteText);
|
|
|
|
return FText::Format(LOCTEXT("RDOCHelpText","<RichTextBlock.TextHighlight>Installation</>\n{0}\n{1}\n\n<RichTextBlock.TextHighlight>Run</>\n{2}\n{3}\n{4}\n{5}\n{6}\n{7}\n{8}\n{9}\n\n<RichTextBlock.TextHighlight>Note</>\n{10}"),
|
|
Args);
|
|
}
|
|
|
|
void FAndroidTargetSettingsCustomization::BuildGraphicsDebuggerSection(IDetailLayoutBuilder& DetailLayout)
|
|
{
|
|
IDetailCategoryBuilder& GraphicsDebuggerCategory = DetailLayout.EditCategory(TEXT("GraphicsDebugger"));
|
|
|
|
TSharedPtr<IPropertyHandle> AndroidGraphicsDebuggerProperty = DetailLayout.GetProperty(GET_MEMBER_NAME_CHECKED(UAndroidRuntimeSettings, AndroidGraphicsDebugger));
|
|
GraphicsDebuggerCategory.AddProperty(AndroidGraphicsDebuggerProperty);
|
|
|
|
// Mali Graphics Debugger settings
|
|
{
|
|
TAttribute<EVisibility> MaliSettingsVisibility(
|
|
TAttribute<EVisibility>::Create(TAttribute<EVisibility>::FGetter::CreateStatic(GraphicsDebuggerSettingsVisibility, EAndroidGraphicsDebugger::Mali, AndroidGraphicsDebuggerProperty))
|
|
);
|
|
|
|
TSharedPtr<IPropertyHandle> MaliGraphicsDebuggerPathProperty = DetailLayout.GetProperty(GET_MEMBER_NAME_CHECKED(UAndroidRuntimeSettings, MaliGraphicsDebuggerPath));
|
|
DetailLayout.HideProperty(MaliGraphicsDebuggerPathProperty);
|
|
GraphicsDebuggerCategory.AddProperty(MaliGraphicsDebuggerPathProperty).Visibility(MaliSettingsVisibility);
|
|
|
|
FText MGDHelpText = GetMaliGraphicsDebuggerHelpText();
|
|
|
|
GraphicsDebuggerCategory.AddCustomRow(LOCTEXT("MaliGraphicsDebuggerInfo", "Mali Graphics Debugger Info"), false)
|
|
.Visibility(MaliSettingsVisibility)
|
|
.WholeRowWidget
|
|
[
|
|
SNew(SBorder)
|
|
.Padding(1)
|
|
[
|
|
SNew(SVerticalBox)
|
|
+ SVerticalBox::Slot()
|
|
.Padding(FMargin(10, 10, 10, 10))
|
|
.AutoHeight()
|
|
[
|
|
SNew(SRichTextBlock)
|
|
.Text(MGDHelpText)
|
|
.TextStyle(FEditorStyle::Get(), "MessageLog")
|
|
.DecoratorStyleSet(&FEditorStyle::Get())
|
|
.AutoWrapText(true)
|
|
]
|
|
+ SVerticalBox::Slot()
|
|
.AutoHeight()
|
|
.Padding(FMargin(10, 10, 10, 10))
|
|
[
|
|
SNew(SBox)
|
|
.HAlign(HAlign_Left)
|
|
[
|
|
SNew(SHyperlinkLaunchURL, TEXT("http://malideveloper.arm.com/resources/tools/mali-graphics-debugger/"))
|
|
.Text(LOCTEXT("MaliGraphicsDebuggerPage", "Mali Graphics Debugger home page"))
|
|
.ToolTipText(LOCTEXT("MaliGraphicsDebuggerPageTooltip", "Opens the Mali Graphics Debugger home page on ARM's website"))
|
|
]
|
|
]
|
|
]
|
|
];
|
|
}
|
|
// Adreno Profiler settings
|
|
{
|
|
TAttribute<EVisibility> AdrenoSettingsVisibility(
|
|
TAttribute<EVisibility>::Create(TAttribute<EVisibility>::FGetter::CreateStatic(GraphicsDebuggerSettingsVisibility, EAndroidGraphicsDebugger::Adreno, AndroidGraphicsDebuggerProperty))
|
|
);
|
|
|
|
FText AdrenoHelpText = GetAdrenoProfilerHelpText();
|
|
|
|
GraphicsDebuggerCategory.AddCustomRow(LOCTEXT("AdrenoProfilerInfo", "Adreno Profiler Info"), false)
|
|
.Visibility(AdrenoSettingsVisibility)
|
|
.WholeRowWidget
|
|
[
|
|
SNew(SBorder)
|
|
.Padding(1)
|
|
[
|
|
SNew(SVerticalBox)
|
|
+ SVerticalBox::Slot()
|
|
.Padding(FMargin(10, 10, 10, 10))
|
|
.AutoHeight()
|
|
[
|
|
SNew(SRichTextBlock)
|
|
.Text(AdrenoHelpText)
|
|
.TextStyle(FEditorStyle::Get(), "MessageLog")
|
|
.DecoratorStyleSet(&FEditorStyle::Get())
|
|
.AutoWrapText(true)
|
|
]
|
|
+ SVerticalBox::Slot()
|
|
.AutoHeight()
|
|
.Padding(FMargin(10, 10, 10, 10))
|
|
[
|
|
SNew(SBox)
|
|
.HAlign(HAlign_Left)
|
|
[
|
|
SNew(SHyperlinkLaunchURL, TEXT("https://developer.qualcomm.com/software/adreno-gpu-profiler"))
|
|
.Text(LOCTEXT("AdrenoProfilerPage", "Adreno Profiler home page"))
|
|
.ToolTipText(LOCTEXT("AdrenoProfilerPageTooltip", "Opens the Adreno Profiler home page on the Qualcomm website"))
|
|
]
|
|
]
|
|
]
|
|
];
|
|
}
|
|
|
|
// RenderDoc settings
|
|
{
|
|
TAttribute<EVisibility> RenderDocSettingsVisibility(
|
|
TAttribute<EVisibility>::Create(TAttribute<EVisibility>::FGetter::CreateStatic(GraphicsDebuggerSettingsVisibility, EAndroidGraphicsDebugger::RenderDoc, AndroidGraphicsDebuggerProperty))
|
|
);
|
|
|
|
TSharedPtr<IPropertyHandle> RenderDocPathProperty = DetailLayout.GetProperty(GET_MEMBER_NAME_CHECKED(UAndroidRuntimeSettings, RenderDocPath));
|
|
DetailLayout.HideProperty(RenderDocPathProperty);
|
|
GraphicsDebuggerCategory.AddProperty(RenderDocPathProperty).Visibility(RenderDocSettingsVisibility);
|
|
|
|
FText RenderDocHelpText = GetRenderDocHelpText();
|
|
|
|
GraphicsDebuggerCategory.AddCustomRow(LOCTEXT("RenderDocInfo", "RenderDoc Info"), false)
|
|
.Visibility(RenderDocSettingsVisibility)
|
|
.WholeRowWidget
|
|
[
|
|
SNew(SBorder)
|
|
.Padding(1)
|
|
[
|
|
SNew(SVerticalBox)
|
|
+ SVerticalBox::Slot()
|
|
.Padding(FMargin(10, 10, 10, 10))
|
|
.AutoHeight()
|
|
[
|
|
SNew(SRichTextBlock)
|
|
.Text(RenderDocHelpText)
|
|
.TextStyle(FEditorStyle::Get(), "MessageLog")
|
|
.DecoratorStyleSet(&FEditorStyle::Get())
|
|
.AutoWrapText(true)
|
|
]
|
|
+ SVerticalBox::Slot()
|
|
.AutoHeight()
|
|
.Padding(FMargin(10, 10, 10, 10))
|
|
[
|
|
SNew(SBox)
|
|
.HAlign(HAlign_Left)
|
|
[
|
|
SNew(SHyperlinkLaunchURL, TEXT("https://renderdoc.org/"))
|
|
.Text(LOCTEXT("RenderDocPage", "RenderDoc home page"))
|
|
.ToolTipText(LOCTEXT("RenderDocPageTooltip", "Opens the RenderDoc home page"))
|
|
]
|
|
]
|
|
]
|
|
];
|
|
}
|
|
}
|
|
|
|
//////////////////////////////////////////////////////////////////////////
|
|
|
|
#undef LOCTEXT_NAMESPACE
|