You've already forked UnrealEngineUWP
mirror of
https://github.com/izzy2lost/UnrealEngineUWP.git
synced 2026-03-26 18:15:20 -07:00
Added HardwareTargeting module and tidied up project browser dialogs
Also removed tabs from the project browser dialogs when they're not necessary. Fixed up some incorrect icon sizes to work with the new layout. [CL 2290664 by Andrew Rodham in Main branch]
This commit is contained in:
@@ -31,7 +31,8 @@ public class GameProjectGeneration : ModuleRules
|
||||
"SourceControl",
|
||||
"TargetPlatform",
|
||||
"UnrealEd",
|
||||
"DesktopPlatform"
|
||||
"DesktopPlatform",
|
||||
"HardwareTargeting"
|
||||
}
|
||||
);
|
||||
|
||||
|
||||
@@ -318,7 +318,7 @@ bool GameProjectUtils::IsValidProjectFileForCreation(const FString& ProjectFile,
|
||||
{
|
||||
FFormatNamedArguments Args;
|
||||
Args.Add( TEXT("MaxProjectPathLength"), MaxProjectPathLength );
|
||||
OutFailReason = FText::Format( LOCTEXT( "ProjectPathTooLong", "A projects path must not be longer than {MaxProjectPathLength} characters." ), Args );
|
||||
OutFailReason = FText::Format( LOCTEXT( "ProjectPathTooLong", "A project's path must not be longer than {MaxProjectPathLength} characters." ), Args );
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -352,17 +352,13 @@ bool GameProjectUtils::IsValidProjectFileForCreation(const FString& ProjectFile,
|
||||
|
||||
if ( ProjectFileExists(ProjectFile) )
|
||||
{
|
||||
FFormatNamedArguments Args;
|
||||
Args.Add( TEXT("ProjectFile"), FText::FromString( ProjectFile ) );
|
||||
OutFailReason = FText::Format( LOCTEXT( "ProjectFileAlreadyExists", "{ProjectFile} already exists." ), Args );
|
||||
OutFailReason = LOCTEXT( "ProjectFileAlreadyExists", "This project file already exists." );
|
||||
return false;
|
||||
}
|
||||
|
||||
if ( FPaths::ConvertRelativePathToFull(FPaths::GetPath(ProjectFile)).StartsWith( FPaths::ConvertRelativePathToFull(FPaths::EngineDir())) )
|
||||
{
|
||||
FFormatNamedArguments Args;
|
||||
Args.Add( TEXT("ProjectFile"), FText::FromString( ProjectFile ) );
|
||||
OutFailReason = FText::Format( LOCTEXT( "ProjectFileCannotBeUnderEngineFolder", "{ProjectFile} cannot be saved under the Engine folder. Create the project in a different directory." ), Args );
|
||||
OutFailReason = LOCTEXT( "ProjectFileCannotBeUnderEngineFolder", "Project cannot be saved under the Engine folder. Please choose a different directory." );
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -370,8 +366,7 @@ bool GameProjectUtils::IsValidProjectFileForCreation(const FString& ProjectFile,
|
||||
{
|
||||
FFormatNamedArguments Args;
|
||||
Args.Add( TEXT("ProjectFileExtension"), FText::FromString( FProjectDescriptor::GetExtension() ) );
|
||||
Args.Add( TEXT("ProjectFilePath"), FText::FromString( FPaths::GetPath(ProjectFile) ) );
|
||||
OutFailReason = FText::Format( LOCTEXT( "AProjectFileAlreadyExistsAtLoction", "Another .{ProjectFileExtension} file already exists in {ProjectFilePath}" ), Args );
|
||||
OutFailReason = FText::Format( LOCTEXT( "AProjectFileAlreadyExistsAtLoction", "Another .{ProjectFileExtension} file already exists in the specified folder" ), Args );
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -404,7 +399,7 @@ bool GameProjectUtils::OpenProject(const FString& ProjectFile, FText& OutFailRea
|
||||
{
|
||||
FFormatNamedArguments Args;
|
||||
Args.Add( TEXT("MaxProjectPathLength"), MaxProjectPathLength );
|
||||
OutFailReason = FText::Format( LOCTEXT( "ProjectPathTooLong", "A projects path must not be longer than {MaxProjectPathLength} characters." ), Args );
|
||||
OutFailReason = FText::Format( LOCTEXT( "ProjectPathTooLong", "A project's path must not be longer than {MaxProjectPathLength} characters." ), Args );
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -556,9 +551,9 @@ bool GameProjectUtils::CopyStarterContent(const FString& DestProjectFolder, FTex
|
||||
}
|
||||
|
||||
|
||||
bool GameProjectUtils::CreateProject(const FString& NewProjectFile, const FString& TemplateFile, bool bShouldGenerateCode, bool bCopyStarterContent, FText& OutFailReason)
|
||||
bool GameProjectUtils::CreateProject(const FProjectInformation& InProjectInfo, FText& OutFailReason)
|
||||
{
|
||||
if ( !IsValidProjectFileForCreation(NewProjectFile, OutFailReason) )
|
||||
if ( !IsValidProjectFileForCreation(InProjectInfo.ProjectFilename, OutFailReason) )
|
||||
{
|
||||
return false;
|
||||
}
|
||||
@@ -568,22 +563,22 @@ bool GameProjectUtils::CreateProject(const FString& NewProjectFile, const FStrin
|
||||
|
||||
bool bProjectCreationSuccessful = false;
|
||||
FString TemplateName;
|
||||
if ( TemplateFile.IsEmpty() )
|
||||
if ( InProjectInfo.TemplateFile.IsEmpty() )
|
||||
{
|
||||
bProjectCreationSuccessful = GenerateProjectFromScratch(NewProjectFile, bShouldGenerateCode, bCopyStarterContent, OutFailReason);
|
||||
TemplateName = bShouldGenerateCode ? TEXT("Basic Code") : TEXT("Blank");
|
||||
bProjectCreationSuccessful = GenerateProjectFromScratch(InProjectInfo, OutFailReason);
|
||||
TemplateName = InProjectInfo.bShouldGenerateCode ? TEXT("Basic Code") : TEXT("Blank");
|
||||
}
|
||||
else
|
||||
{
|
||||
bProjectCreationSuccessful = CreateProjectFromTemplate(NewProjectFile, TemplateFile, bShouldGenerateCode, bCopyStarterContent, OutFailReason);
|
||||
TemplateName = FPaths::GetBaseFilename(TemplateFile);
|
||||
bProjectCreationSuccessful = CreateProjectFromTemplate(InProjectInfo, OutFailReason);
|
||||
TemplateName = FPaths::GetBaseFilename(InProjectInfo.TemplateFile);
|
||||
}
|
||||
|
||||
if( FEngineAnalytics::IsAvailable() )
|
||||
{
|
||||
TArray<FAnalyticsEventAttribute> EventAttributes;
|
||||
EventAttributes.Add(FAnalyticsEventAttribute(TEXT("Template"), TemplateName));
|
||||
EventAttributes.Add(FAnalyticsEventAttribute(TEXT("ProjectType"), bShouldGenerateCode ? TEXT("C++ Code") : TEXT("Content Only")));
|
||||
EventAttributes.Add(FAnalyticsEventAttribute(TEXT("ProjectType"), InProjectInfo.bShouldGenerateCode ? TEXT("C++ Code") : TEXT("Content Only")));
|
||||
EventAttributes.Add(FAnalyticsEventAttribute(TEXT("Outcome"), bProjectCreationSuccessful ? TEXT("Successful") : TEXT("Failed")));
|
||||
|
||||
FEngineAnalytics::GetProvider().RecordEvent( TEXT( "Editor.NewProject.ProjectCreated" ), EventAttributes );
|
||||
@@ -816,14 +811,14 @@ UTemplateProjectDefs* GameProjectUtils::LoadTemplateDefs(const FString& ProjectD
|
||||
return TemplateDefs;
|
||||
}
|
||||
|
||||
bool GameProjectUtils::GenerateProjectFromScratch(const FString& NewProjectFile, bool bShouldGenerateCode, bool bCopyStarterContent, FText& OutFailReason)
|
||||
bool GameProjectUtils::GenerateProjectFromScratch(const FProjectInformation& InProjectInfo, FText& OutFailReason)
|
||||
{
|
||||
const FString NewProjectFolder = FPaths::GetPath(NewProjectFile);
|
||||
const FString NewProjectName = FPaths::GetBaseFilename(NewProjectFile);
|
||||
const FString NewProjectFolder = FPaths::GetPath(InProjectInfo.ProjectFilename);
|
||||
const FString NewProjectName = FPaths::GetBaseFilename(InProjectInfo.ProjectFilename);
|
||||
TArray<FString> CreatedFiles;
|
||||
|
||||
// Generate config files
|
||||
if (!GenerateConfigFiles(NewProjectFolder, NewProjectName, bShouldGenerateCode, bCopyStarterContent, CreatedFiles, OutFailReason))
|
||||
if (!GenerateConfigFiles(InProjectInfo, CreatedFiles, OutFailReason))
|
||||
{
|
||||
DeleteCreatedFiles(NewProjectFolder, CreatedFiles);
|
||||
return false;
|
||||
@@ -841,7 +836,7 @@ bool GameProjectUtils::GenerateProjectFromScratch(const FString& NewProjectFile,
|
||||
}
|
||||
|
||||
TArray<FString> StartupModuleNames;
|
||||
if ( bShouldGenerateCode )
|
||||
if ( InProjectInfo.bShouldGenerateCode )
|
||||
{
|
||||
// Generate basic source code files
|
||||
if ( !GenerateBasicSourceCode(NewProjectFolder / TEXT("Source"), NewProjectName, StartupModuleNames, CreatedFiles, OutFailReason) )
|
||||
@@ -861,9 +856,9 @@ bool GameProjectUtils::GenerateProjectFromScratch(const FString& NewProjectFile,
|
||||
// Generate the project file
|
||||
{
|
||||
FText LocalFailReason;
|
||||
if (IProjectManager::Get().GenerateNewProjectFile(NewProjectFile, StartupModuleNames, FDesktopPlatformModule::Get()->GetCurrentEngineIdentifier(), LocalFailReason))
|
||||
if (IProjectManager::Get().GenerateNewProjectFile(InProjectInfo.ProjectFilename, StartupModuleNames, FDesktopPlatformModule::Get()->GetCurrentEngineIdentifier(), LocalFailReason))
|
||||
{
|
||||
CreatedFiles.Add(NewProjectFile);
|
||||
CreatedFiles.Add(InProjectInfo.ProjectFilename);
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -873,23 +868,23 @@ bool GameProjectUtils::GenerateProjectFromScratch(const FString& NewProjectFile,
|
||||
}
|
||||
}
|
||||
|
||||
if ( bShouldGenerateCode )
|
||||
if ( InProjectInfo.bShouldGenerateCode )
|
||||
{
|
||||
// Generate project files
|
||||
if ( !GenerateCodeProjectFiles(NewProjectFile, OutFailReason) )
|
||||
if ( !GenerateCodeProjectFiles(InProjectInfo.ProjectFilename, OutFailReason) )
|
||||
{
|
||||
DeleteGeneratedProjectFiles(NewProjectFile);
|
||||
DeleteGeneratedProjectFiles(InProjectInfo.ProjectFilename);
|
||||
DeleteCreatedFiles(NewProjectFolder, CreatedFiles);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
if (bCopyStarterContent)
|
||||
if (InProjectInfo.bCopyStarterContent)
|
||||
{
|
||||
// Copy the starter content
|
||||
if ( !CopyStarterContent(NewProjectFolder, OutFailReason) )
|
||||
{
|
||||
DeleteGeneratedProjectFiles(NewProjectFile);
|
||||
DeleteGeneratedProjectFiles(InProjectInfo.ProjectFilename);
|
||||
DeleteCreatedFiles(NewProjectFolder, CreatedFiles);
|
||||
return false;
|
||||
}
|
||||
@@ -899,17 +894,17 @@ bool GameProjectUtils::GenerateProjectFromScratch(const FString& NewProjectFile,
|
||||
return true;
|
||||
}
|
||||
|
||||
bool GameProjectUtils::CreateProjectFromTemplate(const FString& NewProjectFile, const FString& TemplateFile, bool bShouldGenerateCode, bool bCopyStarterContent, FText& OutFailReason)
|
||||
bool GameProjectUtils::CreateProjectFromTemplate(const FProjectInformation& InProjectInfo, FText& OutFailReason)
|
||||
{
|
||||
const FString ProjectName = FPaths::GetBaseFilename(NewProjectFile);
|
||||
const FString TemplateName = FPaths::GetBaseFilename(TemplateFile);
|
||||
const FString SrcFolder = FPaths::GetPath(TemplateFile);
|
||||
const FString DestFolder = FPaths::GetPath(NewProjectFile);
|
||||
const FString ProjectName = FPaths::GetBaseFilename(InProjectInfo.ProjectFilename);
|
||||
const FString TemplateName = FPaths::GetBaseFilename(InProjectInfo.TemplateFile);
|
||||
const FString SrcFolder = FPaths::GetPath(InProjectInfo.TemplateFile);
|
||||
const FString DestFolder = FPaths::GetPath(InProjectInfo.ProjectFilename);
|
||||
|
||||
if ( !FPlatformFileManager::Get().GetPlatformFile().FileExists(*TemplateFile) )
|
||||
if ( !FPlatformFileManager::Get().GetPlatformFile().FileExists(*InProjectInfo.TemplateFile) )
|
||||
{
|
||||
FFormatNamedArguments Args;
|
||||
Args.Add( TEXT("TemplateFile"), FText::FromString( TemplateFile ) );
|
||||
Args.Add( TEXT("TemplateFile"), FText::FromString( InProjectInfo.TemplateFile ) );
|
||||
OutFailReason = FText::Format( LOCTEXT("InvalidTemplate_MissingProject", "Template project \"{TemplateFile}\" does not exist."), Args );
|
||||
return false;
|
||||
}
|
||||
@@ -918,7 +913,7 @@ bool GameProjectUtils::CreateProjectFromTemplate(const FString& NewProjectFile,
|
||||
if ( TemplateDefs == NULL )
|
||||
{
|
||||
FFormatNamedArguments Args;
|
||||
Args.Add( TEXT("TemplateFile"), FText::FromString( FPaths::GetBaseFilename(TemplateFile) ) );
|
||||
Args.Add( TEXT("TemplateFile"), FText::FromString( FPaths::GetBaseFilename(InProjectInfo.TemplateFile) ) );
|
||||
Args.Add( TEXT("TemplateDefinesFile"), FText::FromString( GetTemplateDefsFilename() ) );
|
||||
OutFailReason = FText::Format( LOCTEXT("InvalidTemplate_MissingDefs", "Template project \"{TemplateFile}\" does not have definitions file: '{TemplateDefinesFile}'."), Args );
|
||||
return false;
|
||||
@@ -1080,9 +1075,28 @@ bool GameProjectUtils::CreateProjectFromTemplate(const FString& NewProjectFile,
|
||||
}
|
||||
}
|
||||
|
||||
const FString ProjectConfigPath = DestFolder / TEXT("Config");
|
||||
|
||||
// Write out the hardware class target settings chosen for this project
|
||||
{
|
||||
const FString DefaultEditorIniFilename = ProjectConfigPath / TEXT("DefaultEditor.ini");
|
||||
|
||||
FString FileContents;
|
||||
// Load the existing file - if it doesn't exist we create it
|
||||
FFileHelper::LoadFileToString(FileContents, *DefaultEditorIniFilename);
|
||||
|
||||
FileContents += LINE_TERMINATOR;
|
||||
FileContents += GetHardwareConfigString(InProjectInfo);
|
||||
|
||||
if ( !WriteOutputFile(DefaultEditorIniFilename, FileContents, OutFailReason) )
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// Fixup specific ini values
|
||||
TArray<FTemplateConfigValue> ConfigValuesToSet;
|
||||
TemplateDefs->AddConfigValues(ConfigValuesToSet, TemplateName, ProjectName, bShouldGenerateCode);
|
||||
TemplateDefs->AddConfigValues(ConfigValuesToSet, TemplateName, ProjectName, InProjectInfo.bShouldGenerateCode);
|
||||
new (ConfigValuesToSet) FTemplateConfigValue(TEXT("DefaultGame.ini"), TEXT("/Script/EngineSettings.GeneralProjectSettings"), TEXT("ProjectID"), FGuid::NewGuid().ToString(), /*InShouldReplaceExistingValue=*/true);
|
||||
|
||||
// Add all classname fixups
|
||||
@@ -1096,7 +1110,7 @@ bool GameProjectUtils::CreateProjectFromTemplate(const FString& NewProjectFile,
|
||||
for ( auto ConfigIt = ConfigValuesToSet.CreateConstIterator(); ConfigIt; ++ConfigIt )
|
||||
{
|
||||
const FTemplateConfigValue& ConfigValue = *ConfigIt;
|
||||
const FString IniFilename = DestFolder / TEXT("Config") / ConfigValue.ConfigFile;
|
||||
const FString IniFilename = ProjectConfigPath / ConfigValue.ConfigFile;
|
||||
bool bSuccessfullyProcessed = false;
|
||||
|
||||
TArray<FString> FileLines;
|
||||
@@ -1204,7 +1218,7 @@ bool GameProjectUtils::CreateProjectFromTemplate(const FString& NewProjectFile,
|
||||
{
|
||||
// Load the source project
|
||||
FProjectDescriptor Project;
|
||||
if(!Project.Load(TemplateFile, OutFailReason))
|
||||
if(!Project.Load(InProjectInfo.TemplateFile, OutFailReason))
|
||||
{
|
||||
DeleteCreatedFiles(DestFolder, CreatedFiles);
|
||||
return false;
|
||||
@@ -1215,8 +1229,8 @@ bool GameProjectUtils::CreateProjectFromTemplate(const FString& NewProjectFile,
|
||||
Project.EpicSampleNameHash = 0;
|
||||
|
||||
// Fix up module names
|
||||
const FString BaseSourceName = FPaths::GetBaseFilename(TemplateFile);
|
||||
const FString BaseNewName = FPaths::GetBaseFilename(NewProjectFile);
|
||||
const FString BaseSourceName = FPaths::GetBaseFilename(InProjectInfo.TemplateFile);
|
||||
const FString BaseNewName = FPaths::GetBaseFilename(InProjectInfo.ProjectFilename);
|
||||
for ( auto ModuleIt = Project.Modules.CreateIterator(); ModuleIt; ++ModuleIt )
|
||||
{
|
||||
FModuleDescriptor& ModuleInfo = *ModuleIt;
|
||||
@@ -1224,17 +1238,17 @@ bool GameProjectUtils::CreateProjectFromTemplate(const FString& NewProjectFile,
|
||||
}
|
||||
|
||||
// Save it to disk
|
||||
if(!Project.Save(NewProjectFile, OutFailReason))
|
||||
if(!Project.Save(InProjectInfo.ProjectFilename, OutFailReason))
|
||||
{
|
||||
DeleteCreatedFiles(DestFolder, CreatedFiles);
|
||||
return false;
|
||||
}
|
||||
|
||||
// Add it to the list of created files
|
||||
CreatedFiles.Add(NewProjectFile);
|
||||
CreatedFiles.Add(InProjectInfo.ProjectFilename);
|
||||
}
|
||||
|
||||
if ( bShouldGenerateCode )
|
||||
if ( InProjectInfo.bShouldGenerateCode )
|
||||
{
|
||||
// resource folder
|
||||
const FString GameModuleSourcePath = DestFolder / TEXT("Source") / ProjectName;
|
||||
@@ -1245,28 +1259,28 @@ bool GameProjectUtils::CreateProjectFromTemplate(const FString& NewProjectFile,
|
||||
}
|
||||
|
||||
// Generate project files
|
||||
if ( !GenerateCodeProjectFiles(NewProjectFile, OutFailReason) )
|
||||
if ( !GenerateCodeProjectFiles(InProjectInfo.ProjectFilename, OutFailReason) )
|
||||
{
|
||||
DeleteGeneratedProjectFiles(NewProjectFile);
|
||||
DeleteGeneratedProjectFiles(InProjectInfo.ProjectFilename);
|
||||
DeleteCreatedFiles(DestFolder, CreatedFiles);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
if (bCopyStarterContent)
|
||||
if (InProjectInfo.bCopyStarterContent)
|
||||
{
|
||||
// Copy the starter content
|
||||
if ( !CopyStarterContent(DestFolder, OutFailReason) )
|
||||
{
|
||||
DeleteGeneratedProjectFiles(NewProjectFile);
|
||||
DeleteGeneratedProjectFiles(InProjectInfo.ProjectFilename);
|
||||
DeleteCreatedFiles(DestFolder, CreatedFiles);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
if (!TemplateDefs->PostGenerateProject(DestFolder, SrcFolder, NewProjectFile, TemplateFile, bShouldGenerateCode, OutFailReason))
|
||||
if (!TemplateDefs->PostGenerateProject(DestFolder, SrcFolder, InProjectInfo.ProjectFilename, InProjectInfo.TemplateFile, InProjectInfo.bShouldGenerateCode, OutFailReason))
|
||||
{
|
||||
DeleteGeneratedProjectFiles(NewProjectFile);
|
||||
DeleteGeneratedProjectFiles(InProjectInfo.ProjectFilename);
|
||||
DeleteCreatedFiles(DestFolder, CreatedFiles);
|
||||
return false;
|
||||
}
|
||||
@@ -1395,9 +1409,24 @@ void GameProjectUtils::DeleteGeneratedBuildFiles(const FString& NewProjectFolder
|
||||
}
|
||||
}
|
||||
|
||||
bool GameProjectUtils::GenerateConfigFiles(const FString& NewProjectPath, const FString& NewProjectName, bool bShouldGenerateCode, bool bCopyStarterContent, TArray<FString>& OutCreatedFiles, FText& OutFailReason)
|
||||
FString GameProjectUtils::GetHardwareConfigString(const FProjectInformation& InProjectInfo)
|
||||
{
|
||||
FString ProjectConfigPath = NewProjectPath / TEXT("Config");
|
||||
FString HardwareTargeting;
|
||||
|
||||
HardwareTargeting += TEXT("[/Script/HardwareTargeting.HardwareTargetingSettings]") LINE_TERMINATOR;
|
||||
HardwareTargeting += FString::Printf(TEXT("TargetedHardwareClass=%d") LINE_TERMINATOR, int32(InProjectInfo.TargetedHardware));
|
||||
HardwareTargeting += FString::Printf(TEXT("DefaultGraphicsPerformance=%d") LINE_TERMINATOR, int32(InProjectInfo.DefaultGraphicsPerformance));
|
||||
HardwareTargeting += LINE_TERMINATOR;
|
||||
|
||||
return HardwareTargeting;
|
||||
}
|
||||
|
||||
bool GameProjectUtils::GenerateConfigFiles(const FProjectInformation& InProjectInfo, TArray<FString>& OutCreatedFiles, FText& OutFailReason)
|
||||
{
|
||||
const FString NewProjectFolder = FPaths::GetPath(InProjectInfo.ProjectFilename);
|
||||
const FString NewProjectName = FPaths::GetBaseFilename(InProjectInfo.ProjectFilename);
|
||||
|
||||
FString ProjectConfigPath = NewProjectFolder / TEXT("Config");
|
||||
|
||||
// DefaultEngine.ini
|
||||
{
|
||||
@@ -1407,8 +1436,8 @@ bool GameProjectUtils::GenerateConfigFiles(const FString& NewProjectPath, const
|
||||
FileContents += TEXT("[URL]") LINE_TERMINATOR;
|
||||
FileContents += FString::Printf(TEXT("GameName=%s") LINE_TERMINATOR, *NewProjectName);
|
||||
FileContents += LINE_TERMINATOR;
|
||||
|
||||
if (bCopyStarterContent)
|
||||
|
||||
if (InProjectInfo.bCopyStarterContent)
|
||||
{
|
||||
// for generated/blank projects with starter content, set startup map to be the starter content map
|
||||
// otherwise, we leave it to be what the template wants.
|
||||
@@ -1430,7 +1459,7 @@ bool GameProjectUtils::GenerateConfigFiles(const FString& NewProjectPath, const
|
||||
FileContents += TEXT("[/Script/EngineSettings.GameMapsSettings]") LINE_TERMINATOR;
|
||||
FileContents += FString::Printf(TEXT("EditorStartupMap=%s") LINE_TERMINATOR, *MapPackagePath);
|
||||
FileContents += FString::Printf(TEXT("GameDefaultMap=%s") LINE_TERMINATOR, *MapPackagePath);
|
||||
if (bShouldGenerateCode)
|
||||
if (InProjectInfo.bShouldGenerateCode)
|
||||
{
|
||||
FileContents += FString::Printf(TEXT("GlobalDefaultGameMode=\"/Script/%s.%sGameMode\"") LINE_TERMINATOR, *NewProjectName, *NewProjectName);
|
||||
}
|
||||
@@ -1447,24 +1476,6 @@ bool GameProjectUtils::GenerateConfigFiles(const FString& NewProjectPath, const
|
||||
}
|
||||
}
|
||||
|
||||
// DefaultGame.ini
|
||||
{
|
||||
const FString DefaultGameIniFilename = ProjectConfigPath / TEXT("DefaultGame.ini");
|
||||
FString FileContents;
|
||||
FileContents += TEXT("[/Script/EngineSettings.GeneralProjectSettings]") LINE_TERMINATOR;
|
||||
FileContents += FString::Printf( TEXT("ProjectID=%s") LINE_TERMINATOR, *FGuid::NewGuid().ToString() );
|
||||
FileContents += LINE_TERMINATOR;
|
||||
|
||||
if ( WriteOutputFile(DefaultGameIniFilename, FileContents, OutFailReason) )
|
||||
{
|
||||
OutCreatedFiles.Add(DefaultGameIniFilename);
|
||||
}
|
||||
else
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// DefaultEditor.ini
|
||||
{
|
||||
const FString DefaultEditorIniFilename = ProjectConfigPath / TEXT("DefaultEditor.ini");
|
||||
@@ -1474,6 +1485,8 @@ bool GameProjectUtils::GenerateConfigFiles(const FString& NewProjectPath, const
|
||||
FileContents += TEXT("bReplaceBlueprintWithClass=true") LINE_TERMINATOR;
|
||||
FileContents += TEXT("bDontLoadBlueprintOutsideEditor=true") LINE_TERMINATOR;
|
||||
FileContents += TEXT("bBlueprintIsNotBlueprintType=true") LINE_TERMINATOR;
|
||||
FileContents += LINE_TERMINATOR;
|
||||
FileContents += GetHardwareConfigString(InProjectInfo);
|
||||
|
||||
if (WriteOutputFile(DefaultEditorIniFilename, FileContents, OutFailReason))
|
||||
{
|
||||
|
||||
@@ -2,6 +2,29 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "HardwareTargetingModule.h"
|
||||
|
||||
struct FProjectInformation
|
||||
{
|
||||
FProjectInformation(FString InProjectFilename, bool bInGenerateCode, bool bInCopyStarterContent, FString InTemplateFile = FString())
|
||||
: ProjectFilename(MoveTemp(InProjectFilename))
|
||||
, TemplateFile(MoveTemp(InTemplateFile))
|
||||
, bShouldGenerateCode(bInGenerateCode)
|
||||
, bCopyStarterContent(bInCopyStarterContent)
|
||||
, TargetedHardware(EHardwareClass::Desktop)
|
||||
, DefaultGraphicsPerformance(EGraphicsPreset::Maximum)
|
||||
{
|
||||
}
|
||||
FString ProjectFilename;
|
||||
FString TemplateFile;
|
||||
|
||||
bool bShouldGenerateCode;
|
||||
bool bCopyStarterContent;
|
||||
|
||||
EHardwareClass::Type TargetedHardware;
|
||||
EGraphicsPreset::Type DefaultGraphicsPerformance;
|
||||
};
|
||||
|
||||
class GameProjectUtils
|
||||
{
|
||||
public:
|
||||
@@ -133,7 +156,7 @@ public:
|
||||
static bool OpenCodeIDE(const FString& ProjectFile, FText& OutFailReason);
|
||||
|
||||
/** Creates the specified project file and all required folders. If TemplateFile is non-empty, it will be used as the template for creation. On failure, OutFailReason will be populated. */
|
||||
static bool CreateProject(const FString& NewProjectFile, const FString& TemplateFile, bool bShouldGenerateCode, bool bCopyStarterContent, FText& OutFailReason);
|
||||
static bool CreateProject(const FProjectInformation& InProjectInfo, FText& OutFailReason);
|
||||
|
||||
/** Prompts the user to update his project file, if necessary. */
|
||||
static void CheckForOutOfDateGameProjectFile();
|
||||
@@ -238,11 +261,14 @@ public:
|
||||
static void ClearSupportedTargetPlatforms();
|
||||
|
||||
private:
|
||||
|
||||
static FString GetHardwareConfigString(const FProjectInformation& InProjectInfo);
|
||||
|
||||
/** Generates a new project without using a template project */
|
||||
static bool GenerateProjectFromScratch(const FString& NewProjectFile, bool bShouldGenerateCode, bool bCopyStarterContent, FText& OutFailReason);
|
||||
static bool GenerateProjectFromScratch(const FProjectInformation& InProjectInfo, FText& OutFailReason);
|
||||
|
||||
/** Generates a new project using a template project */
|
||||
static bool CreateProjectFromTemplate(const FString& NewProjectFile, const FString& TemplateFile, bool bShouldGenerateCode, bool bCopyStarterContent, FText& OutFailReason);
|
||||
static bool CreateProjectFromTemplate(const FProjectInformation& InProjectInfo, FText& OutFailReason);
|
||||
|
||||
/** Copies starter content into the specified project folder. */
|
||||
static bool CopyStarterContent(const FString& DestProjectFolder, FText& OutFailReason);
|
||||
@@ -278,7 +304,7 @@ private:
|
||||
static void DeleteGeneratedBuildFiles(const FString& NewProjectFolder);
|
||||
|
||||
/** Creates ini files for a new project. On failure, OutFailReason will be populated. */
|
||||
static bool GenerateConfigFiles(const FString& NewProjectPath, const FString& NewProjectName, bool bShouldGenerateCode, bool bCopyStarterContent, TArray<FString>& OutCreatedFiles, FText& OutFailReason);
|
||||
static bool GenerateConfigFiles(const FProjectInformation& InProjectInfo, TArray<FString>& OutCreatedFiles, FText& OutFailReason);
|
||||
|
||||
/** Creates the basic source code for a new project. On failure, OutFailReason will be populated. */
|
||||
static bool GenerateBasicSourceCode(const FString& NewProjectSourcePath, const FString& NewProjectName, TArray<FString>& OutGeneratedStartupModuleNames, TArray<FString>& OutCreatedFiles, FText& OutFailReason);
|
||||
|
||||
@@ -20,173 +20,156 @@ void SGameProjectDialog::Construct( const FArguments& InArgs )
|
||||
{
|
||||
bool bAtLeastOneVisibleRecentProject = false;
|
||||
|
||||
ProjectsTabVisibility = InArgs._AllowProjectOpening ? EVisibility::Visible : EVisibility::Collapsed;
|
||||
NewProjectTabVisibility = InArgs._AllowProjectCreate ? EVisibility::Visible : EVisibility::Collapsed;
|
||||
if (InArgs._AllowProjectCreate)
|
||||
{
|
||||
NewProjectWizard = SNew(SNewProjectWizard);
|
||||
}
|
||||
|
||||
ChildSlot
|
||||
[
|
||||
// Drop shadow border
|
||||
SNew(SBorder)
|
||||
.Padding(10.0f )
|
||||
.BorderImage(FEditorStyle::GetBrush("ContentBrowser.ThumbnailShadow"))
|
||||
if (InArgs._AllowProjectOpening)
|
||||
{
|
||||
ProjectBrowser = SNew(SProjectBrowser);
|
||||
}
|
||||
|
||||
TSharedPtr<SWidget> Content;
|
||||
|
||||
if (InArgs._AllowProjectCreate && InArgs._AllowProjectOpening)
|
||||
{
|
||||
// Create the Open Project tab button
|
||||
TSharedRef<SButton> ProjectsTabButton = SNew(SButton)
|
||||
.ForegroundColor(FCoreStyle::Get().GetSlateColor("Foreground"))
|
||||
.ButtonStyle(FEditorStyle::Get(), TEXT("NoBorder"))
|
||||
.OnClicked(this, &SGameProjectDialog::HandleProjectsTabButtonClicked)
|
||||
.ContentPadding(FMargin(40, 5))
|
||||
.Text(LOCTEXT("ProjectsTabTitle", "Projects"))
|
||||
.TextStyle(FEditorStyle::Get(), TEXT("ProjectBrowser.Tab.Text"));
|
||||
|
||||
// Create the New Project tab button
|
||||
TSharedRef<SButton> NewProjectTabButton = SNew(SButton)
|
||||
.ForegroundColor(FCoreStyle::Get().GetSlateColor("Foreground"))
|
||||
.ButtonStyle(FEditorStyle::Get(), "NoBorder")
|
||||
.OnClicked(this, &SGameProjectDialog::HandleNewProjectTabButtonClicked)
|
||||
.ContentPadding(FMargin(20, 5))
|
||||
.TextStyle(FEditorStyle::Get(), "ProjectBrowser.Tab.Text")
|
||||
.Text(LOCTEXT("NewProjectTabTitle", "New Project"))
|
||||
.ToolTip(IDocumentation::Get()->CreateToolTip(LOCTEXT("NewProjectTabTitle", "New Project"), nullptr, "Shared/LevelEditor", "NewProjectTab"));
|
||||
|
||||
// Allow creation and opening, so we need tabs here
|
||||
ChildSlot
|
||||
[
|
||||
|
||||
SNew(SBorder)
|
||||
.ColorAndOpacity(this, &SGameProjectDialog::HandleCustomContentColorAndOpacity)
|
||||
.BorderImage(FEditorStyle::GetBrush("Docking.Tab.ContentAreaBrush"))
|
||||
.Padding(0)
|
||||
[
|
||||
SNew(SBorder)
|
||||
.BorderImage(FEditorStyle::GetBrush( "Docking.Tab.ContentAreaBrush"))
|
||||
.Padding(10.0f)
|
||||
SNew(SVerticalBox)
|
||||
|
||||
+ SVerticalBox::Slot()
|
||||
.AutoHeight()
|
||||
.Padding(FMargin(6.f, 0, 0, 0))
|
||||
[
|
||||
SNew(SHorizontalBox)
|
||||
|
||||
// Open Project Tab
|
||||
+ SHorizontalBox::Slot()
|
||||
.AutoWidth()
|
||||
[
|
||||
SNew(SVerticalBox)
|
||||
SNew( SBorder )
|
||||
.BorderImage(this, &SGameProjectDialog::OnGetTabBorderImage, ProjectsTab)
|
||||
.Padding(0)
|
||||
[
|
||||
SNew(SOverlay)
|
||||
|
||||
+ SVerticalBox::Slot()
|
||||
.AutoHeight()
|
||||
+ SOverlay::Slot()
|
||||
.VAlign(VAlign_Top)
|
||||
[
|
||||
SNew(SHorizontalBox)
|
||||
|
||||
+ SHorizontalBox::Slot()
|
||||
.AutoWidth()
|
||||
[
|
||||
SNew( SBorder )
|
||||
.Visibility(ProjectsTabVisibility)
|
||||
.BorderImage(this, &SGameProjectDialog::HandleProjectsTabHeaderBorderImage)
|
||||
.Padding(0)
|
||||
[
|
||||
SNew(SOverlay)
|
||||
|
||||
+ SOverlay::Slot()
|
||||
.VAlign(VAlign_Top)
|
||||
[
|
||||
SNew(SBox)
|
||||
.HeightOverride(2.0f)
|
||||
[
|
||||
SNew(SImage)
|
||||
.Image(this, &SGameProjectDialog::HandleProjectsTabHeaderImage)
|
||||
.Visibility(EVisibility::HitTestInvisible)
|
||||
]
|
||||
]
|
||||
|
||||
+ SOverlay::Slot()
|
||||
[
|
||||
SAssignNew(ProjectsTabButton, SButton)
|
||||
.ForegroundColor(FCoreStyle::Get().GetSlateColor("Foreground"))
|
||||
.ButtonStyle(FEditorStyle::Get(), TEXT("NoBorder"))
|
||||
.OnClicked(this, &SGameProjectDialog::HandleProjectsTabButtonClicked)
|
||||
.ContentPadding(FMargin(40, 5))
|
||||
.Text(LOCTEXT("ProjectsTabTitle", "Projects"))
|
||||
.TextStyle(FEditorStyle::Get(), TEXT("ProjectBrowser.Tab.Text"))
|
||||
]
|
||||
]
|
||||
]
|
||||
|
||||
+ SHorizontalBox::Slot()
|
||||
.Padding(InArgs._AllowProjectOpening ? 10 : 0, 0)
|
||||
.AutoWidth()
|
||||
[
|
||||
SNew(SBorder)
|
||||
.Visibility(NewProjectTabVisibility)
|
||||
.BorderImage(this, &SGameProjectDialog::HandleNewProjectTabHeaderBorderImage)
|
||||
.Padding(0)
|
||||
[
|
||||
SNew(SOverlay)
|
||||
|
||||
+ SOverlay::Slot()
|
||||
.VAlign(VAlign_Top)
|
||||
[
|
||||
SNew(SBox)
|
||||
.HeightOverride(2.0f)
|
||||
[
|
||||
SNew(SImage)
|
||||
.Image(this, &SGameProjectDialog::HandleNewProjectTabHeaderImage)
|
||||
.Visibility(EVisibility::HitTestInvisible)
|
||||
]
|
||||
]
|
||||
|
||||
+ SOverlay::Slot()
|
||||
[
|
||||
SAssignNew(NewProjectTabButton, SButton)
|
||||
.ForegroundColor(FCoreStyle::Get().GetSlateColor("Foreground"))
|
||||
.ButtonStyle(FEditorStyle::Get(), "NoBorder")
|
||||
.OnClicked(this, &SGameProjectDialog::HandleNewProjectTabButtonClicked)
|
||||
.ContentPadding(FMargin(20, 5))
|
||||
.TextStyle(FEditorStyle::Get(), "ProjectBrowser.Tab.Text")
|
||||
.Text(LOCTEXT("NewProjectTabTitle", "New Project"))
|
||||
.ToolTip(IDocumentation::Get()->CreateToolTip(LOCTEXT("NewProjectTabTitle", "New Project"), nullptr, "Shared/LevelEditor", "NewProjectTab"))
|
||||
]
|
||||
]
|
||||
]
|
||||
|
||||
+ SHorizontalBox::Slot()
|
||||
.FillWidth(1.0f)
|
||||
.HAlign(HAlign_Right)
|
||||
.Padding(0,5)
|
||||
[
|
||||
SNew(SBorder)
|
||||
.BorderImage(FEditorStyle::Get().GetBrush( "ToolPanel.GroupBorder" ))
|
||||
.Padding(3)
|
||||
[
|
||||
SAssignNew(MarketplaceButton, SButton)
|
||||
.Visibility( FDesktopPlatformModule::Get()->CanOpenLauncher(true) ? EVisibility::Collapsed : EVisibility::Visible )
|
||||
.ForegroundColor(this, &SGameProjectDialog::HandleMarketplaceTabButtonForegroundColor)
|
||||
.ButtonStyle(FEditorStyle::Get(), "ToggleButton")
|
||||
.OnClicked(this, &SGameProjectDialog::HandleMarketplaceTabButtonClicked)
|
||||
.ContentPadding(FMargin(20, 0))
|
||||
.ToolTipText(LOCTEXT("MarketplaceToolTip", "Check out the Marketplace to find new projects!"))
|
||||
.HAlign(HAlign_Center)
|
||||
.VAlign(VAlign_Center)
|
||||
.Content()
|
||||
[
|
||||
SNew(SHorizontalBox)
|
||||
|
||||
+ SHorizontalBox::Slot()
|
||||
.Padding(2.0f)
|
||||
.AutoWidth()
|
||||
[
|
||||
SNew(SImage)
|
||||
.Image(FEditorStyle::GetBrush("LevelEditor.OpenMarketplace"))
|
||||
]
|
||||
|
||||
+ SHorizontalBox::Slot()
|
||||
.Padding( 2.0f )
|
||||
[
|
||||
SNew(STextBlock)
|
||||
.TextStyle(FEditorStyle::Get(), "ProjectBrowser.Tab.Text")
|
||||
.Text(LOCTEXT("Marketplace", "Marketplace"))
|
||||
]
|
||||
]
|
||||
]
|
||||
]
|
||||
SNew(SBox)
|
||||
.HeightOverride(2.0f)
|
||||
[
|
||||
SNew(SImage)
|
||||
.Image(this, &SGameProjectDialog::OnGetTabHeaderImage, ProjectsTab, ProjectsTabButton)
|
||||
.Visibility(EVisibility::HitTestInvisible)
|
||||
]
|
||||
]
|
||||
|
||||
+ SVerticalBox::Slot()
|
||||
+ SOverlay::Slot()
|
||||
[
|
||||
// custom content area
|
||||
SNew(SBorder)
|
||||
.ColorAndOpacity(this, &SGameProjectDialog::HandleCustomContentColorAndOpacity)
|
||||
.BorderImage(FEditorStyle::GetBrush("ProjectBrowser.Background"))
|
||||
.Padding(10.0f)
|
||||
[
|
||||
SAssignNew(ContentAreaSwitcher, SWidgetSwitcher)
|
||||
.WidgetIndex(InArgs._AllowProjectOpening ? 0 : 1)
|
||||
|
||||
+ SWidgetSwitcher::Slot()
|
||||
[
|
||||
// project browser
|
||||
SAssignNew(ProjectBrowser, SProjectBrowser)
|
||||
.AllowProjectCreate(InArgs._AllowProjectCreate)
|
||||
.OnNewProjectScreenRequested(this, &SGameProjectDialog::ShowNewProjectTab)
|
||||
]
|
||||
|
||||
+ SWidgetSwitcher::Slot()
|
||||
[
|
||||
// new project wizard
|
||||
SAssignNew(NewProjectWizard, SNewProjectWizard)
|
||||
]
|
||||
]
|
||||
ProjectsTabButton
|
||||
]
|
||||
]
|
||||
]
|
||||
]
|
||||
];
|
||||
|
||||
ActiveTab = InArgs._AllowProjectOpening ? SGameProjectDialog::ProjectsTab : SGameProjectDialog::NewProjectTab;
|
||||
ActiveTab = !ProjectBrowser->HasProjects() && InArgs._AllowProjectCreate ? SGameProjectDialog::NewProjectTab : ActiveTab;
|
||||
+ SHorizontalBox::Slot()
|
||||
.Padding(FMargin(6.f, 0, 0, 0))
|
||||
.AutoWidth()
|
||||
[
|
||||
SNew(SBorder)
|
||||
.BorderImage(this, &SGameProjectDialog::OnGetTabBorderImage, NewProjectTab)
|
||||
.Padding(0)
|
||||
[
|
||||
SNew(SOverlay)
|
||||
|
||||
+ SOverlay::Slot()
|
||||
.VAlign(VAlign_Top)
|
||||
[
|
||||
SNew(SBox)
|
||||
.HeightOverride(2.0f)
|
||||
[
|
||||
SNew(SImage)
|
||||
.Image(this, &SGameProjectDialog::OnGetTabHeaderImage, NewProjectTab, NewProjectTabButton)
|
||||
.Visibility(EVisibility::HitTestInvisible)
|
||||
]
|
||||
]
|
||||
|
||||
+ SOverlay::Slot()
|
||||
[
|
||||
NewProjectTabButton
|
||||
]
|
||||
]
|
||||
]
|
||||
]
|
||||
|
||||
+ SVerticalBox::Slot()
|
||||
[
|
||||
SAssignNew(ContentAreaSwitcher, SWidgetSwitcher)
|
||||
.WidgetIndex(0)
|
||||
|
||||
+ SWidgetSwitcher::Slot()
|
||||
[
|
||||
ProjectBrowser.ToSharedRef()
|
||||
]
|
||||
|
||||
+ SWidgetSwitcher::Slot()
|
||||
[
|
||||
NewProjectWizard.ToSharedRef()
|
||||
]
|
||||
]
|
||||
]
|
||||
];
|
||||
}
|
||||
else
|
||||
{
|
||||
TSharedPtr<SWidget> BorderContent;
|
||||
if (NewProjectWizard.IsValid())
|
||||
{
|
||||
BorderContent = NewProjectWizard;
|
||||
}
|
||||
else
|
||||
{
|
||||
BorderContent = ProjectBrowser;
|
||||
}
|
||||
|
||||
ChildSlot
|
||||
[
|
||||
BorderContent.ToSharedRef()
|
||||
];
|
||||
}
|
||||
|
||||
ActiveTab = InArgs._AllowProjectOpening ? ProjectsTab : NewProjectTab;
|
||||
if (ProjectBrowser.IsValid())
|
||||
{
|
||||
ActiveTab = !ProjectBrowser->HasProjects() && InArgs._AllowProjectCreate ? NewProjectTab : ActiveTab;
|
||||
}
|
||||
|
||||
if (ActiveTab == ProjectsTab)
|
||||
{
|
||||
@@ -278,60 +261,6 @@ FLinearColor SGameProjectDialog::HandleCustomContentColorAndOpacity( ) const
|
||||
}
|
||||
|
||||
|
||||
FReply SGameProjectDialog::HandleMarketplaceTabButtonClicked( )
|
||||
{
|
||||
IDesktopPlatform* DesktopPlatform = FDesktopPlatformModule::Get();
|
||||
|
||||
if (DesktopPlatform != nullptr)
|
||||
{
|
||||
TArray<FAnalyticsEventAttribute> EventAttributes;
|
||||
|
||||
if (DesktopPlatform->OpenLauncher(false, TEXT("-OpenMarket")))
|
||||
{
|
||||
EventAttributes.Add(FAnalyticsEventAttribute(TEXT("OpenSucceeded"), TEXT("TRUE")));
|
||||
}
|
||||
else
|
||||
{
|
||||
EventAttributes.Add(FAnalyticsEventAttribute(TEXT("OpenSucceeded"), TEXT("FALSE")));
|
||||
|
||||
if (EAppReturnType::Yes == FMessageDialog::Open(EAppMsgType::YesNo, LOCTEXT("InstallMarketplacePrompt", "The Marketplace requires the Unreal Engine Launcher, which does not seem to be installed on your computer. Would you like to install it now?")))
|
||||
{
|
||||
if (!DesktopPlatform->OpenLauncher(true, TEXT("-OpenMarket")))
|
||||
{
|
||||
EventAttributes.Add(FAnalyticsEventAttribute(TEXT("InstallSucceeded"), TEXT("FALSE")));
|
||||
FMessageDialog::Open(EAppMsgType::Ok, FText::FromString(TEXT("Sorry, there was a problem installing the Launcher.\nPlease try to install it manually!")));
|
||||
}
|
||||
else
|
||||
{
|
||||
EventAttributes.Add(FAnalyticsEventAttribute(TEXT("InstallSucceeded"), TEXT("TRUE")));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
EventAttributes.Add(FAnalyticsEventAttribute(TEXT("Source"), TEXT("ProjectBrowser")));
|
||||
if( FEngineAnalytics::IsAvailable() )
|
||||
{
|
||||
FEngineAnalytics::GetProvider().RecordEvent(TEXT("Editor.Usage.OpenMarketplace"), EventAttributes);
|
||||
}
|
||||
}
|
||||
|
||||
return FReply::Handled();
|
||||
}
|
||||
|
||||
|
||||
FSlateColor SGameProjectDialog::HandleMarketplaceTabButtonForegroundColor( ) const
|
||||
{
|
||||
//if (MarketplaceButton->IsHovered())
|
||||
//{
|
||||
// return FLinearColor::Black;
|
||||
//}
|
||||
//else
|
||||
//{
|
||||
return FSlateColor::UseForeground();
|
||||
//}
|
||||
}
|
||||
|
||||
|
||||
FReply SGameProjectDialog::HandleNewProjectTabButtonClicked( )
|
||||
{
|
||||
ShowNewProjectTab();
|
||||
@@ -340,25 +269,14 @@ FReply SGameProjectDialog::HandleNewProjectTabButtonClicked( )
|
||||
}
|
||||
|
||||
|
||||
const FSlateBrush* SGameProjectDialog::HandleNewProjectTabHeaderBorderImage( ) const
|
||||
const FSlateBrush* SGameProjectDialog::OnGetTabHeaderImage( ETab InTab, TSharedRef<SButton> TabButton ) const
|
||||
{
|
||||
if (ActiveTab == NewProjectTab)
|
||||
{
|
||||
return FEditorStyle::GetBrush("ProjectBrowser.Tab.ActiveBackground");
|
||||
}
|
||||
|
||||
return FEditorStyle::GetBrush("ProjectBrowser.Tab.Background");
|
||||
}
|
||||
|
||||
|
||||
const FSlateBrush* SGameProjectDialog::HandleNewProjectTabHeaderImage( ) const
|
||||
{
|
||||
if (NewProjectTabButton->IsPressed())
|
||||
if (TabButton->IsPressed())
|
||||
{
|
||||
return FEditorStyle::GetBrush("ProjectBrowser.Tab.PressedHighlight");
|
||||
}
|
||||
|
||||
if ((ActiveTab == NewProjectTab) || NewProjectTabButton->IsHovered())
|
||||
if ((ActiveTab == InTab) || TabButton->IsHovered())
|
||||
{
|
||||
return FEditorStyle::GetBrush("ProjectBrowser.Tab.ActiveHighlight");
|
||||
}
|
||||
@@ -374,10 +292,9 @@ FReply SGameProjectDialog::HandleProjectsTabButtonClicked( )
|
||||
return FReply::Handled();
|
||||
}
|
||||
|
||||
|
||||
const FSlateBrush* SGameProjectDialog::HandleProjectsTabHeaderBorderImage( ) const
|
||||
const FSlateBrush* SGameProjectDialog::OnGetTabBorderImage( ETab InTab ) const
|
||||
{
|
||||
if (ActiveTab == ProjectsTab)
|
||||
if (ActiveTab == InTab)
|
||||
{
|
||||
return FEditorStyle::GetBrush("ProjectBrowser.Tab.ActiveBackground");
|
||||
}
|
||||
@@ -386,20 +303,4 @@ const FSlateBrush* SGameProjectDialog::HandleProjectsTabHeaderBorderImage( ) con
|
||||
}
|
||||
|
||||
|
||||
const FSlateBrush* SGameProjectDialog::HandleProjectsTabHeaderImage( ) const
|
||||
{
|
||||
if (ProjectsTabButton->IsPressed())
|
||||
{
|
||||
return FEditorStyle::GetBrush("ProjectBrowser.Tab.PressedHighlight");
|
||||
}
|
||||
|
||||
if ((ActiveTab == ProjectsTab) || ProjectsTabButton->IsHovered())
|
||||
{
|
||||
return FEditorStyle::GetBrush("ProjectBrowser.Tab.ActiveHighlight");
|
||||
}
|
||||
|
||||
return FEditorStyle::GetBrush("ProjectBrowser.Tab.Highlight");
|
||||
}
|
||||
|
||||
|
||||
#undef LOCTEXT_NAMESPACE
|
||||
|
||||
@@ -66,29 +66,17 @@ private:
|
||||
// Callback for getting the color of the custom content area.
|
||||
FLinearColor HandleCustomContentColorAndOpacity() const;
|
||||
|
||||
// Callback for clicking the 'Marketplace' button.
|
||||
FReply HandleMarketplaceTabButtonClicked( );
|
||||
|
||||
// Callback for getting the foreground color of the 'Marketplace' button.
|
||||
FSlateColor HandleMarketplaceTabButtonForegroundColor( ) const;
|
||||
|
||||
// Callback for clicking the 'New Project' button.
|
||||
FReply HandleNewProjectTabButtonClicked( );
|
||||
|
||||
// Callback for getting the border image of the 'New Project' button.
|
||||
const FSlateBrush* HandleNewProjectTabHeaderBorderImage( ) const;
|
||||
|
||||
// Callback for getting the button image of the 'New Project' button.
|
||||
const FSlateBrush* HandleNewProjectTabHeaderImage( ) const;
|
||||
|
||||
// Callback for clicking the 'Projects' button.
|
||||
FReply HandleProjectsTabButtonClicked( );
|
||||
|
||||
// Callback for getting the border image of the 'Projects' button.
|
||||
const FSlateBrush* HandleProjectsTabHeaderBorderImage( ) const;
|
||||
// Callback for getting the border image of the specified tab.
|
||||
const FSlateBrush* OnGetTabBorderImage( ETab InTab ) const;
|
||||
|
||||
// Callback for getting the button image of the 'Projects' button.
|
||||
const FSlateBrush* HandleProjectsTabHeaderImage( ) const;
|
||||
// Callback for getting the header stripe image for the specified tab.
|
||||
const FSlateBrush* OnGetTabHeaderImage( ETab InTab, TSharedRef<SButton> TabButton ) const;
|
||||
|
||||
private:
|
||||
|
||||
@@ -102,12 +90,6 @@ private:
|
||||
TSharedPtr<SWidgetSwitcher> ContentAreaSwitcher;
|
||||
TSharedPtr<SProjectBrowser> ProjectBrowser;
|
||||
TSharedPtr<SNewProjectWizard> NewProjectWizard;
|
||||
TSharedPtr<SButton> ProjectsTabButton;
|
||||
TSharedPtr<SButton> NewProjectTabButton;
|
||||
TSharedPtr<SButton> MarketplaceButton;
|
||||
|
||||
ETab ActiveTab;
|
||||
|
||||
EVisibility ProjectsTabVisibility;
|
||||
EVisibility NewProjectTabVisibility;
|
||||
};
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -2,7 +2,6 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
|
||||
struct FTemplateItem;
|
||||
struct FTemplateCategory;
|
||||
|
||||
@@ -74,6 +73,9 @@ private:
|
||||
const FSlateBrush* GetSelectedTemplatePreviewImage() const;
|
||||
const FSlateBrush* GetSelectedTemplateTypeImage() const;
|
||||
|
||||
/** Get the visibility for the selected template preview image */
|
||||
EVisibility GetSelectedTemplatePreviewVisibility() const;
|
||||
|
||||
/** Gets the assembled project filename with path */
|
||||
FString GetProjectFilenameWithPath() const;
|
||||
|
||||
@@ -111,13 +113,22 @@ private:
|
||||
FText GetNameAndLocationErrorLabelText() const;
|
||||
|
||||
/** Handler for when the "copy starter content" checkbox changes state */
|
||||
void OnCopyStarterContentChanged(ESlateCheckBoxState::Type InNewState);
|
||||
FReply OnCopyStarterContentClicked();
|
||||
|
||||
/** Returns true if the "copy starter content" checkbox should be checked. */
|
||||
ESlateCheckBoxState::Type IsCopyStarterContentChecked() const;
|
||||
private:
|
||||
|
||||
/** Gets the visibility of the copy starter content option */
|
||||
EVisibility GetCopyStarterContentCheckboxVisibility() const;
|
||||
EHardwareClass::Type SelectedHardwareClassTarget;
|
||||
void SetHardwareClassTarget(EHardwareClass::Type InHardwareClass);
|
||||
EHardwareClass::Type GetHardwareClassTarget() const { return SelectedHardwareClassTarget; }
|
||||
|
||||
EGraphicsPreset::Type SelectedGraphicsPreset;
|
||||
void SetGraphicsPreset(EGraphicsPreset::Type InGraphicsPreset);
|
||||
EGraphicsPreset::Type GetGraphicsPreset() const { return SelectedGraphicsPreset; }
|
||||
|
||||
private:
|
||||
|
||||
FText GetStartContentText() const;
|
||||
const FSlateBrush* GetStartContentIcon() const;
|
||||
|
||||
private:
|
||||
|
||||
|
||||
@@ -97,11 +97,9 @@ SProjectBrowser::SProjectBrowser()
|
||||
BEGIN_SLATE_FUNCTION_BUILD_OPTIMIZATION
|
||||
void SProjectBrowser::Construct( const FArguments& InArgs )
|
||||
{
|
||||
NewProjectScreenRequestedDelegate = InArgs._OnNewProjectScreenRequested;
|
||||
bPreventSelectionChangeEvent = false;
|
||||
ThumbnailBorderPadding = 5;
|
||||
ThumbnailSize = 128.0f;
|
||||
bAllowProjectCreate = InArgs._AllowProjectCreate;
|
||||
|
||||
// Prepare the categories box
|
||||
CategoriesBox = SNew(SVerticalBox);
|
||||
@@ -129,66 +127,121 @@ void SProjectBrowser::Construct( const FArguments& InArgs )
|
||||
|
||||
ChildSlot
|
||||
[
|
||||
SNew(SVerticalBox)
|
||||
|
||||
// Page description
|
||||
+ SVerticalBox::Slot()
|
||||
.AutoHeight()
|
||||
.Padding(10.0f, 0.0f)
|
||||
SNew(SBorder)
|
||||
.BorderImage( FEditorStyle::GetBrush("ToolPanel.GroupBorder") )
|
||||
.Padding(8.f)
|
||||
[
|
||||
SNew(STextBlock)
|
||||
.Text(LOCTEXT("SelectProjectDescription", "Select an existing project from the list below."))
|
||||
]
|
||||
SNew(SVerticalBox)
|
||||
|
||||
// Categories
|
||||
+ SVerticalBox::Slot()
|
||||
.FillHeight(1.0f)
|
||||
[
|
||||
SNew(SBorder)
|
||||
.BorderImage( FEditorStyle::GetBrush("ToolPanel.GroupBorder") )
|
||||
.Padding(4)
|
||||
// Categories
|
||||
+ SVerticalBox::Slot()
|
||||
.Padding(8.f)
|
||||
.FillHeight(1.0f)
|
||||
[
|
||||
SNew(SVerticalBox)
|
||||
|
||||
+ SVerticalBox::Slot()
|
||||
.AutoHeight()
|
||||
.VAlign(VAlign_Top)
|
||||
.Padding(FMargin(5.f, 10.f))
|
||||
.HAlign(HAlign_Left)
|
||||
.Padding(FMargin(0, 0, 0, 5.f))
|
||||
[
|
||||
SNew(SHorizontalBox)
|
||||
|
||||
+SHorizontalBox::Slot()
|
||||
.AutoWidth()
|
||||
.Padding(FMargin(0,0,5,0))
|
||||
[
|
||||
SNew(SOverlay)
|
||||
|
||||
+SOverlay::Slot()
|
||||
SNew(SButton)
|
||||
.Visibility( FDesktopPlatformModule::Get()->CanOpenLauncher(true) ? EVisibility::Collapsed : EVisibility::Visible )
|
||||
.ButtonStyle(FEditorStyle::Get(), "ToggleButton")
|
||||
.OnClicked(this, &SProjectBrowser::HandleMarketplaceTabButtonClicked)
|
||||
.ForegroundColor(FSlateColor::UseForeground())
|
||||
.ToolTipText(LOCTEXT("MarketplaceToolTip", "Check out the Marketplace to find new projects!"))
|
||||
.HAlign(HAlign_Center)
|
||||
.VAlign(VAlign_Center)
|
||||
[
|
||||
SNew(SSearchBox)
|
||||
.HintText(LOCTEXT("FilterHint", "Filter Projects..."))
|
||||
.OnTextChanged(this, &SProjectBrowser::OnFilterTextChanged)
|
||||
]
|
||||
SNew(SHorizontalBox)
|
||||
|
||||
+SOverlay::Slot()
|
||||
[
|
||||
SNew(SBorder)
|
||||
.Visibility(this, &SProjectBrowser::GetFilterActiveOverlayVisibility)
|
||||
.BorderImage(FEditorStyle::Get().GetBrush("SearchBox.ActiveBorder"))
|
||||
+ SHorizontalBox::Slot()
|
||||
.Padding(2.0f)
|
||||
.VAlign(VAlign_Center)
|
||||
.AutoWidth()
|
||||
[
|
||||
SNew(SImage)
|
||||
.Image(FEditorStyle::GetBrush("LevelEditor.OpenMarketplace.Small"))
|
||||
]
|
||||
|
||||
+ SHorizontalBox::Slot()
|
||||
.VAlign(VAlign_Center)
|
||||
.Padding(2.0f)
|
||||
[
|
||||
SNew(STextBlock)
|
||||
.TextStyle(FEditorStyle::Get(), "ProjectBrowser.Toolbar.Text")
|
||||
.Text(LOCTEXT("Marketplace", "Marketplace"))
|
||||
]
|
||||
]
|
||||
]
|
||||
|
||||
+SHorizontalBox::Slot()
|
||||
.AutoWidth()
|
||||
.VAlign(VAlign_Center)
|
||||
[
|
||||
SNew(SButton)
|
||||
.ButtonStyle(FCoreStyle::Get(), "NoBorder")
|
||||
.ButtonStyle(FEditorStyle::Get(), "ToggleButton")
|
||||
.OnClicked(this, &SProjectBrowser::FindProjects)
|
||||
.ForegroundColor(FSlateColor::UseForeground())
|
||||
.ToolTipText(LOCTEXT("RefreshProjectList", "Refresh the project list"))
|
||||
.HAlign(HAlign_Center)
|
||||
.VAlign(VAlign_Center)
|
||||
[
|
||||
SNew(SImage).Image(FEditorStyle::Get().GetBrush("Icons.Refresh"))
|
||||
SNew(SHorizontalBox)
|
||||
|
||||
+ SHorizontalBox::Slot()
|
||||
.Padding(2.0f)
|
||||
.VAlign(VAlign_Center)
|
||||
.AutoWidth()
|
||||
[
|
||||
SNew(SImage)
|
||||
.Image(FEditorStyle::GetBrush("Icons.Refresh"))
|
||||
]
|
||||
|
||||
+ SHorizontalBox::Slot()
|
||||
.VAlign(VAlign_Center)
|
||||
.Padding(2.0f)
|
||||
[
|
||||
SNew(STextBlock)
|
||||
.TextStyle(FEditorStyle::Get(), "ProjectBrowser.Toolbar.Text")
|
||||
.Text(LOCTEXT("RefreshProjectsText", "Refresh"))
|
||||
]
|
||||
]
|
||||
]
|
||||
]
|
||||
|
||||
+ SVerticalBox::Slot()
|
||||
.AutoHeight()
|
||||
.VAlign(VAlign_Top)
|
||||
.Padding(FMargin(0, 5.f))
|
||||
[
|
||||
SNew(SOverlay)
|
||||
|
||||
+SOverlay::Slot()
|
||||
[
|
||||
SNew(SSearchBox)
|
||||
.HintText(LOCTEXT("FilterHint", "Filter Projects..."))
|
||||
.OnTextChanged(this, &SProjectBrowser::OnFilterTextChanged)
|
||||
]
|
||||
|
||||
+SOverlay::Slot()
|
||||
[
|
||||
SNew(SBorder)
|
||||
.Visibility(this, &SProjectBrowser::GetFilterActiveOverlayVisibility)
|
||||
.BorderImage(FEditorStyle::Get().GetBrush("SearchBox.ActiveBorder"))
|
||||
]
|
||||
]
|
||||
|
||||
+ SVerticalBox::Slot()
|
||||
.Padding(FMargin(0, 5.f))
|
||||
[
|
||||
SNew(SScrollBox)
|
||||
|
||||
@@ -198,48 +251,48 @@ void SProjectBrowser::Construct( const FArguments& InArgs )
|
||||
]
|
||||
]
|
||||
]
|
||||
]
|
||||
|
||||
+ SVerticalBox::Slot()
|
||||
.Padding( 0, 40, 0, 0 ) // Lots of vertical padding before the dialog buttons at the bottom
|
||||
.AutoHeight()
|
||||
[
|
||||
SNew( SHorizontalBox )
|
||||
|
||||
// Auto-load project
|
||||
+ SHorizontalBox::Slot()
|
||||
.FillWidth(1.0f)
|
||||
.Padding(4, 0)
|
||||
+ SVerticalBox::Slot()
|
||||
.Padding( 0, 40, 0, 0 ) // Lots of vertical padding before the dialog buttons at the bottom
|
||||
.AutoHeight()
|
||||
[
|
||||
SNew(SCheckBox)
|
||||
.IsChecked(GEditor->GetGameAgnosticSettings().bLoadTheMostRecentlyLoadedProjectAtStartup ? ESlateCheckBoxState::Checked : ESlateCheckBoxState::Unchecked)
|
||||
.OnCheckStateChanged(this, &SProjectBrowser::OnAutoloadLastProjectChanged)
|
||||
.Content()
|
||||
SNew( SHorizontalBox )
|
||||
|
||||
// Auto-load project
|
||||
+ SHorizontalBox::Slot()
|
||||
.FillWidth(1.0f)
|
||||
.VAlign(VAlign_Center)
|
||||
[
|
||||
SNew(STextBlock).Text(LOCTEXT("AutoloadOnStartupCheckbox", "Always load last project on startup"))
|
||||
SNew(SCheckBox)
|
||||
.IsChecked(GEditor->GetGameAgnosticSettings().bLoadTheMostRecentlyLoadedProjectAtStartup ? ESlateCheckBoxState::Checked : ESlateCheckBoxState::Unchecked)
|
||||
.OnCheckStateChanged(this, &SProjectBrowser::OnAutoloadLastProjectChanged)
|
||||
.Content()
|
||||
[
|
||||
SNew(STextBlock).Text(LOCTEXT("AutoloadOnStartupCheckbox", "Always load last project on startup"))
|
||||
]
|
||||
]
|
||||
]
|
||||
|
||||
// Browse Button
|
||||
+SHorizontalBox::Slot()
|
||||
.AutoWidth()
|
||||
.Padding(4, 0)
|
||||
[
|
||||
SNew(SButton)
|
||||
.Text(LOCTEXT("BrowseProjectButton", "Browse..."))
|
||||
.OnClicked(this, &SProjectBrowser::OnBrowseToProjectClicked)
|
||||
.ContentPadding( FCoreStyle::Get().GetMargin("StandardDialog.ContentPadding") )
|
||||
]
|
||||
// Browse Button
|
||||
+SHorizontalBox::Slot()
|
||||
.AutoWidth()
|
||||
.Padding(8.f, 0)
|
||||
[
|
||||
SNew(SButton)
|
||||
.Text(LOCTEXT("BrowseProjectButton", "Browse..."))
|
||||
.OnClicked(this, &SProjectBrowser::OnBrowseToProjectClicked)
|
||||
.ContentPadding( FCoreStyle::Get().GetMargin("StandardDialog.ContentPadding") )
|
||||
]
|
||||
|
||||
// Open Button
|
||||
+SHorizontalBox::Slot()
|
||||
.AutoWidth()
|
||||
[
|
||||
SNew(SButton)
|
||||
.Text(LOCTEXT("OpenProjectButton", "Open"))
|
||||
.OnClicked(this, &SProjectBrowser::HandleOpenProjectButtonClicked)
|
||||
.IsEnabled(this, &SProjectBrowser::HandleOpenProjectButtonIsEnabled)
|
||||
.ContentPadding( FCoreStyle::Get().GetMargin("StandardDialog.ContentPadding") )
|
||||
// Open Button
|
||||
+SHorizontalBox::Slot()
|
||||
.AutoWidth()
|
||||
[
|
||||
SNew(SButton)
|
||||
.Text(LOCTEXT("OpenProjectButton", "Open"))
|
||||
.OnClicked(this, &SProjectBrowser::HandleOpenProjectButtonClicked)
|
||||
.IsEnabled(this, &SProjectBrowser::HandleOpenProjectButtonIsEnabled)
|
||||
.ContentPadding( FCoreStyle::Get().GetMargin("StandardDialog.ContentPadding") )
|
||||
]
|
||||
]
|
||||
]
|
||||
];
|
||||
@@ -272,7 +325,6 @@ void SProjectBrowser::ConstructCategory( const TSharedRef<SVerticalBox>& InCateg
|
||||
{
|
||||
// Title
|
||||
InCategoriesBox->AddSlot()
|
||||
.Padding(FMargin(5.f, 0.f))
|
||||
.AutoHeight()
|
||||
[
|
||||
SNew(STextBlock)
|
||||
@@ -284,7 +336,7 @@ void SProjectBrowser::ConstructCategory( const TSharedRef<SVerticalBox>& InCateg
|
||||
// Separator
|
||||
InCategoriesBox->AddSlot()
|
||||
.AutoHeight()
|
||||
.Padding(5.0f, 2.0f, 5.0f, 8.0f)
|
||||
.Padding(0, 2.0f, 0, 8.0f)
|
||||
[
|
||||
SNew(SSeparator)
|
||||
.Visibility(this, &SProjectBrowser::GetProjectCategoryVisibility, Category)
|
||||
@@ -293,7 +345,7 @@ void SProjectBrowser::ConstructCategory( const TSharedRef<SVerticalBox>& InCateg
|
||||
// Project tile view
|
||||
InCategoriesBox->AddSlot()
|
||||
.AutoHeight()
|
||||
.Padding(5.0f, 0.0f, 5.0f, 40.0f)
|
||||
.Padding(0.f, 0.0f, 0.f, 40.0f)
|
||||
[
|
||||
SAssignNew(Category->ProjectTileView, STileView<TSharedPtr<FProjectItem> >)
|
||||
.Visibility(this, &SProjectBrowser::GetProjectCategoryVisibility, Category)
|
||||
@@ -1160,6 +1212,47 @@ void SProjectBrowser::HandleProjectViewSelectionChanged(TSharedPtr<FProjectItem>
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
FReply SProjectBrowser::HandleMarketplaceTabButtonClicked()
|
||||
{
|
||||
IDesktopPlatform* DesktopPlatform = FDesktopPlatformModule::Get();
|
||||
|
||||
if (DesktopPlatform != nullptr)
|
||||
{
|
||||
TArray<FAnalyticsEventAttribute> EventAttributes;
|
||||
|
||||
if (DesktopPlatform->OpenLauncher(false, TEXT("-OpenMarket")))
|
||||
{
|
||||
EventAttributes.Add(FAnalyticsEventAttribute(TEXT("OpenSucceeded"), TEXT("TRUE")));
|
||||
}
|
||||
else
|
||||
{
|
||||
EventAttributes.Add(FAnalyticsEventAttribute(TEXT("OpenSucceeded"), TEXT("FALSE")));
|
||||
|
||||
if (EAppReturnType::Yes == FMessageDialog::Open(EAppMsgType::YesNo, LOCTEXT("InstallMarketplacePrompt", "The Marketplace requires the Unreal Engine Launcher, which does not seem to be installed on your computer. Would you like to install it now?")))
|
||||
{
|
||||
if (!DesktopPlatform->OpenLauncher(true, TEXT("-OpenMarket")))
|
||||
{
|
||||
EventAttributes.Add(FAnalyticsEventAttribute(TEXT("InstallSucceeded"), TEXT("FALSE")));
|
||||
FMessageDialog::Open(EAppMsgType::Ok, FText::FromString(TEXT("Sorry, there was a problem installing the Launcher.\nPlease try to install it manually!")));
|
||||
}
|
||||
else
|
||||
{
|
||||
EventAttributes.Add(FAnalyticsEventAttribute(TEXT("InstallSucceeded"), TEXT("TRUE")));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
EventAttributes.Add(FAnalyticsEventAttribute(TEXT("Source"), TEXT("ProjectBrowser")));
|
||||
if( FEngineAnalytics::IsAvailable() )
|
||||
{
|
||||
FEngineAnalytics::GetProvider().RecordEvent(TEXT("Editor.Usage.OpenMarketplace"), EventAttributes);
|
||||
}
|
||||
}
|
||||
|
||||
return FReply::Handled();
|
||||
}
|
||||
|
||||
void SProjectBrowser::OnFilterTextChanged(const FText& InText)
|
||||
{
|
||||
ProjectItemFilter.SetRawFilterText(InText);
|
||||
|
||||
@@ -17,10 +17,6 @@ public:
|
||||
|
||||
SLATE_BEGIN_ARGS(SProjectBrowser) { }
|
||||
|
||||
SLATE_ARGUMENT(bool, AllowProjectCreate)
|
||||
|
||||
SLATE_EVENT(FNewProjectScreenRequested, OnNewProjectScreenRequested)
|
||||
|
||||
SLATE_END_ARGS()
|
||||
|
||||
public:
|
||||
@@ -109,6 +105,9 @@ private:
|
||||
/** Handler for when the selection changes in the project view */
|
||||
void HandleProjectViewSelectionChanged( TSharedPtr<FProjectItem> ProjectItem, ESelectInfo::Type SelectInfo, FText CategoryName );
|
||||
|
||||
/** Callback for clicking the 'Marketplace' button. */
|
||||
FReply HandleMarketplaceTabButtonClicked( );
|
||||
|
||||
/** Called when the text in the filter box is changed */
|
||||
void OnFilterTextChanged(const FText& InText);
|
||||
|
||||
@@ -149,9 +148,6 @@ private:
|
||||
TSharedPtr<SVerticalBox> CategoriesBox;
|
||||
|
||||
bool bHasProjectFiles;
|
||||
|
||||
/** True if this UI will enable the creation of new projects, false otherwise */
|
||||
bool bAllowProjectCreate;
|
||||
private:
|
||||
|
||||
// Holds a delegate that is executed when the new project screen is being requested.
|
||||
|
||||
@@ -116,7 +116,7 @@ bool FBuildPromotionNewProjectCreateTest::RunTest(const FString& Parameters)
|
||||
}
|
||||
|
||||
FText FailReason;
|
||||
if (GameProjectUtils::CreateProject(DesiredProjectFilename, TEXT(""), false, true, FailReason))
|
||||
if (GameProjectUtils::CreateProject(FProjectInformation(DesiredProjectFilename, false, true), FailReason))
|
||||
{
|
||||
UE_LOG(LogGameProjectGenerationTests, Display, TEXT("Generated a new project: %s"), *DesiredProjectFilename);
|
||||
UE_LOG(LogGameProjectGenerationTests, Display, TEXT("Test successful!"));
|
||||
|
||||
Reference in New Issue
Block a user