diff options
| author | ivey <[email protected]> | 2020-06-15 15:54:16 -0400 |
|---|---|---|
| committer | ivey <[email protected]> | 2020-06-15 15:54:16 -0400 |
| commit | d5310c3455f9849243b7b950deb4e910aa1f24dd (patch) | |
| tree | 994a81eec10538d2a1efd9ed78469a249ff086f2 /Plugins/SimpleUGC/Source/SimpleUGCEditor/Private | |
| parent | Updated image paths. (diff) | |
| download | ugcexample-d5310c3455f9849243b7b950deb4e910aa1f24dd.tar.xz ugcexample-d5310c3455f9849243b7b950deb4e910aa1f24dd.zip | |
Initial commit of the UGCExample Project
Diffstat (limited to 'Plugins/SimpleUGC/Source/SimpleUGCEditor/Private')
6 files changed, 737 insertions, 0 deletions
diff --git a/Plugins/SimpleUGC/Source/SimpleUGCEditor/Private/SimpleUGCCreator.cpp b/Plugins/SimpleUGC/Source/SimpleUGCEditor/Private/SimpleUGCCreator.cpp new file mode 100644 index 0000000..d7403a9 --- /dev/null +++ b/Plugins/SimpleUGC/Source/SimpleUGCEditor/Private/SimpleUGCCreator.cpp @@ -0,0 +1,65 @@ +// Copyright Epic Games, Inc. All Rights Reserved. + +//#include "SimpleUGCEditorPrivatePCH.h" +#include "SimpleUGCCreator.h" + +#include "SimpleUGCPluginWizardDefinition.h" +#include "Widgets/Docking/SDockTab.h" + +// This depends on the Plugin Browser module to work correctly... +#include "IPluginBrowser.h" + + + +#define LOCTEXT_NAMESPACE "FSimpleUGCCreator" + +const FName FSimpleUGCCreator::SimpleUGCEditorPluginCreatorName("SimpleUGCPluginCreator"); + +FSimpleUGCCreator::FSimpleUGCCreator() +{ + RegisterTabSpawner(); +} + +FSimpleUGCCreator::~FSimpleUGCCreator() +{ + UnregisterTabSpawner(); +} + +void FSimpleUGCCreator::OpenNewPluginWizard(bool bSuppressErrors) const +{ + if (IPluginBrowser::IsAvailable()) + { + FGlobalTabmanager::Get()->InvokeTab(SimpleUGCEditorPluginCreatorName); + } + else if (!bSuppressErrors) + { + FMessageDialog::Open(EAppMsgType::Ok, + LOCTEXT("PluginBrowserDisabled", "Creating a game mod requires the use of the Plugin Browser, but it is currently disabled.")); + } +} + +void FSimpleUGCCreator::RegisterTabSpawner() +{ + FTabSpawnerEntry& Spawner = FGlobalTabmanager::Get()->RegisterNomadTabSpawner(SimpleUGCEditorPluginCreatorName, + FOnSpawnTab::CreateRaw(this, &FSimpleUGCCreator::HandleSpawnPluginTab)); + + // Set a default size for this tab + FVector2D DefaultSize(800.0f, 500.0f); + FTabManager::RegisterDefaultTabWindowSize(SimpleUGCEditorPluginCreatorName, DefaultSize); + + Spawner.SetDisplayName(LOCTEXT("NewUGCTabHeader", "Create New UGC Package")); + Spawner.SetMenuType(ETabSpawnerMenuType::Hidden); +} + +void FSimpleUGCCreator::UnregisterTabSpawner() +{ + FGlobalTabmanager::Get()->UnregisterNomadTabSpawner(SimpleUGCEditorPluginCreatorName); +} + +TSharedRef<SDockTab> FSimpleUGCCreator::HandleSpawnPluginTab(const FSpawnTabArgs& SpawnTabArgs) +{ + check(IPluginBrowser::IsAvailable()); + return IPluginBrowser::Get().SpawnPluginCreatorTab(SpawnTabArgs, MakeShared<FSimpleUGCPluginWizardDefinition>()); +} + +#undef LOCTEXT_NAMESPACE
\ No newline at end of file diff --git a/Plugins/SimpleUGC/Source/SimpleUGCEditor/Private/SimpleUGCEditor.cpp b/Plugins/SimpleUGC/Source/SimpleUGCEditor/Private/SimpleUGCEditor.cpp new file mode 100644 index 0000000..ce43dde --- /dev/null +++ b/Plugins/SimpleUGC/Source/SimpleUGCEditor/Private/SimpleUGCEditor.cpp @@ -0,0 +1,130 @@ +// Copyright Epic Games, Inc. All Rights Reserved. + +#include "SimpleUGCEditor.h" +#include "SimpleUGCEditorStyle.h" +#include "SimpleUGCEditorCommands.h" +#include "SimpleUGCCreator.h" +#include "Misc/MessageDialog.h" +#include "Framework/MultiBox/MultiBoxBuilder.h" + +#include "LevelEditor.h" + +static const FName SimpleUGCEditorTabName("SimpleUGCEditor"); + +#define LOCTEXT_NAMESPACE "FSimpleUGCEditorModule" + +void FSimpleUGCEditorModule::StartupModule() +{ + // This code will execute after your module is loaded into memory; the exact timing is specified in the .uplugin file per-module + + UGCCreator = MakeShared<FSimpleUGCCreator>(); + UGCPackager = MakeShared<FSimpleUGCPackager>(); + + FSimpleUGCEditorStyle::Initialize(); + FSimpleUGCEditorStyle::ReloadTextures(); + + FSimpleUGCEditorCommands::Register(); + + PluginCommands = MakeShareable(new FUICommandList); + + PluginCommands->MapAction( + FSimpleUGCEditorCommands::Get().CreateUGCAction, + FExecuteAction::CreateRaw(this, &FSimpleUGCEditorModule::CreateUGCButtonClicked), + FCanExecuteAction() + ); + + FLevelEditorModule& LevelEditorModule = FModuleManager::LoadModuleChecked<FLevelEditorModule>("LevelEditor"); + // Add commands + { + FName MenuSection = "FileProject"; + FName ToolbarSection = "Misc"; + + // Add creator button to the menu + { + TSharedPtr<FExtender> MenuExtender = MakeShareable(new FExtender()); + MenuExtender->AddMenuExtension(MenuSection, EExtensionHook::After, PluginCommands, FMenuExtensionDelegate::CreateRaw(this, &FSimpleUGCEditorModule::AddUGCCreatorMenuExtension)); + + LevelEditorModule.GetMenuExtensibilityManager()->AddExtender(MenuExtender); + } + + // Add creator button to the toolbar + { + TSharedPtr<FExtender> ToolbarExtender = MakeShareable(new FExtender); + ToolbarExtender->AddToolBarExtension(ToolbarSection, EExtensionHook::After, PluginCommands, FToolBarExtensionDelegate::CreateRaw(this, &FSimpleUGCEditorModule::AddUGCCreatorToolbarExtension)); + + LevelEditorModule.GetToolBarExtensibilityManager()->AddExtender(ToolbarExtender); + } + + // Add packager button to the menu + { + TSharedPtr<FExtender> MenuExtender = MakeShareable(new FExtender()); + MenuExtender->AddMenuExtension(MenuSection, EExtensionHook::After, PluginCommands, FMenuExtensionDelegate::CreateRaw(this, &FSimpleUGCEditorModule::AddUGCPackagerMenuExtension)); + + LevelEditorModule.GetMenuExtensibilityManager()->AddExtender(MenuExtender); + } + + // Add packager button to the toolbar + { + TSharedPtr<FExtender> ToolbarExtender = MakeShareable(new FExtender); + ToolbarExtender->AddToolBarExtension(ToolbarSection, EExtensionHook::After, PluginCommands, FToolBarExtensionDelegate::CreateRaw(this, &FSimpleUGCEditorModule::AddUGCPackagerToolbarExtension)); + + LevelEditorModule.GetToolBarExtensibilityManager()->AddExtender(ToolbarExtender); + } + } +} + +void FSimpleUGCEditorModule::ShutdownModule() +{ + // This function may be called during shutdown to clean up your module. For modules that support dynamic reloading, + // we call this function before unloading the module. + FSimpleUGCEditorStyle::Shutdown(); + + FSimpleUGCEditorCommands::Unregister(); + +} + +void FSimpleUGCEditorModule::CreateUGCButtonClicked() +{ + if (UGCCreator.IsValid()) + { + UGCCreator->OpenNewPluginWizard(); + } +} + +void FSimpleUGCEditorModule::AddUGCCreatorMenuExtension(FMenuBuilder& Builder) +{ + Builder.AddMenuEntry(FSimpleUGCEditorCommands::Get().CreateUGCAction); +} + +void FSimpleUGCEditorModule::AddUGCCreatorToolbarExtension(FToolBarBuilder& Builder) +{ + Builder.AddToolBarButton(FSimpleUGCEditorCommands::Get().CreateUGCAction); +} + +void FSimpleUGCEditorModule::AddUGCPackagerMenuExtension(FMenuBuilder& Builder) +{ + FSimpleUGCPackager* Packager = UGCPackager.Get(); + + Builder.AddSubMenu(LOCTEXT("PackageUGCMenu_Label", "Package UGC"), + LOCTEXT("PackageUGCMenu_Tooltip", "Share and distribute UGC"), + FNewMenuDelegate::CreateRaw(Packager, &FSimpleUGCPackager::GeneratePackagerMenuContent), + false, + FSlateIcon(FSimpleUGCEditorStyle::GetStyleSetName(), "SimpleUGCEditor.PackageUGCAction") + ); +} + +void FSimpleUGCEditorModule::AddUGCPackagerToolbarExtension(FToolBarBuilder& Builder) +{ + FSimpleUGCPackager* Packager = UGCPackager.Get(); + + Builder.AddComboButton(FUIAction(), + FOnGetContent::CreateSP(Packager, &FSimpleUGCPackager::GeneratePackagerComboButtonContent), + LOCTEXT("PackageUGC_Label", "Package UGC"), + LOCTEXT("PackageUGC_Tooltip", "Share and distribute UGC"), + FSlateIcon(FSimpleUGCEditorStyle::GetStyleSetName(), "SimpleUGCEditor.PackageUGCAction") + ); +} + +#undef LOCTEXT_NAMESPACE + +IMPLEMENT_MODULE(FSimpleUGCEditorModule, SimpleUGCEditor) diff --git a/Plugins/SimpleUGC/Source/SimpleUGCEditor/Private/SimpleUGCEditorCommands.cpp b/Plugins/SimpleUGC/Source/SimpleUGCEditor/Private/SimpleUGCEditorCommands.cpp new file mode 100644 index 0000000..846c5a3 --- /dev/null +++ b/Plugins/SimpleUGC/Source/SimpleUGCEditor/Private/SimpleUGCEditorCommands.cpp @@ -0,0 +1,51 @@ +// Copyright Epic Games, Inc. All Rights Reserved. + +#include "SimpleUGCEditorCommands.h" +#include "Interfaces/IPluginManager.h" + +#define LOCTEXT_NAMESPACE "FSimpleUGCEditorModule" + +void FSimpleUGCEditorCommands::RegisterCommands() +{ + UI_COMMAND(CreateUGCAction, "Create UGC", "Create a new UGC package in a mod plugin", EUserInterfaceActionType::Button, FInputGesture()); + UI_COMMAND(PackageUGCAction, "Package UGC", "Share and distribute your UGC", EUserInterfaceActionType::Button, FInputGesture()); +} + +TArray<TSharedPtr<FUICommandInfo>> FSimpleUGCEditorCommands::RegisterUGCCommands(const TArray<TSharedRef<class IPlugin>>& UGCList) const +{ + TArray<TSharedPtr<FUICommandInfo>> AvailableUGCActions; + AvailableUGCActions.Reserve(UGCList.Num()); + + FSimpleUGCEditorCommands* MutableThis = const_cast<FSimpleUGCEditorCommands*>(this); + + for (int32 Index = 0; Index < UGCList.Num(); ++Index) + { + AvailableUGCActions.Add(TSharedPtr<FUICommandInfo>()); + TSharedRef<IPlugin> UGC = UGCList[Index]; + + FString CommandName = "UGCEditorUGC_" + UGC->GetName(); + + FUICommandInfo::MakeCommandInfo(MutableThis->AsShared(), + AvailableUGCActions[Index], + FName(*CommandName), + FText::FromString(UGC->GetName()), + FText::FromString(UGC->GetBaseDir()), + FSlateIcon(), + EUserInterfaceActionType::Button, + FInputGesture()); + } + + return AvailableUGCActions; +} + +void FSimpleUGCEditorCommands::UnregisterUGCCommands(TArray<TSharedPtr<FUICommandInfo>>& UICommands) const +{ + FSimpleUGCEditorCommands* MutableThis = const_cast<FSimpleUGCEditorCommands*>(this); + + for (TSharedPtr<FUICommandInfo> Command : UICommands) + { + FUICommandInfo::UnregisterCommandInfo(MutableThis->AsShared(), Command.ToSharedRef()); + } +} + +#undef LOCTEXT_NAMESPACE
\ No newline at end of file diff --git a/Plugins/SimpleUGC/Source/SimpleUGCEditor/Private/SimpleUGCEditorStyle.cpp b/Plugins/SimpleUGC/Source/SimpleUGCEditor/Private/SimpleUGCEditorStyle.cpp new file mode 100644 index 0000000..309261a --- /dev/null +++ b/Plugins/SimpleUGC/Source/SimpleUGCEditor/Private/SimpleUGCEditorStyle.cpp @@ -0,0 +1,72 @@ +// Copyright Epic Games, Inc. All Rights Reserved. + +#include "SimpleUGCEditorStyle.h" +#include "SimpleUGCEditor.h" +#include "Framework/Application/SlateApplication.h" +#include "Styling/SlateStyleRegistry.h" +#include "Slate/SlateGameResources.h" +#include "Interfaces/IPluginManager.h" + +TSharedPtr< FSlateStyleSet > FSimpleUGCEditorStyle::StyleInstance = NULL; + +void FSimpleUGCEditorStyle::Initialize() +{ + if (!StyleInstance.IsValid()) + { + StyleInstance = Create(); + FSlateStyleRegistry::RegisterSlateStyle(*StyleInstance); + } +} + +void FSimpleUGCEditorStyle::Shutdown() +{ + FSlateStyleRegistry::UnRegisterSlateStyle(*StyleInstance); + ensure(StyleInstance.IsUnique()); + StyleInstance.Reset(); +} + +FName FSimpleUGCEditorStyle::GetStyleSetName() +{ + static FName StyleSetName(TEXT("SimpleUGCEditorStyle")); + return StyleSetName; +} + +#define IMAGE_BRUSH( RelativePath, ... ) FSlateImageBrush( Style->RootToContentDir( RelativePath, TEXT(".png") ), __VA_ARGS__ ) +#define BOX_BRUSH( RelativePath, ... ) FSlateBoxBrush( Style->RootToContentDir( RelativePath, TEXT(".png") ), __VA_ARGS__ ) +#define BORDER_BRUSH( RelativePath, ... ) FSlateBorderBrush( Style->RootToContentDir( RelativePath, TEXT(".png") ), __VA_ARGS__ ) +#define TTF_FONT( RelativePath, ... ) FSlateFontInfo( Style->RootToContentDir( RelativePath, TEXT(".ttf") ), __VA_ARGS__ ) +#define OTF_FONT( RelativePath, ... ) FSlateFontInfo( Style->RootToContentDir( RelativePath, TEXT(".otf") ), __VA_ARGS__ ) + +const FVector2D Icon16x16(16.0f, 16.0f); +const FVector2D Icon20x20(20.0f, 20.0f); +const FVector2D Icon40x40(40.0f, 40.0f); + +TSharedRef< FSlateStyleSet > FSimpleUGCEditorStyle::Create() +{ + TSharedRef< FSlateStyleSet > Style = MakeShareable(new FSlateStyleSet("SimpleUGCEditorStyle")); + Style->SetContentRoot(IPluginManager::Get().FindPlugin("SimpleUGC")->GetBaseDir() / TEXT("Resources")); + + Style->Set("SimpleUGCEditor.PackageUGCAction", new IMAGE_BRUSH(TEXT("PackageUGC_64x"), Icon40x40)); + Style->Set("SimpleUGCEditor.CreateUGCAction", new IMAGE_BRUSH(TEXT("CreateUGC_64x"), Icon40x40)); + + return Style; +} + +#undef IMAGE_BRUSH +#undef BOX_BRUSH +#undef BORDER_BRUSH +#undef TTF_FONT +#undef OTF_FONT + +void FSimpleUGCEditorStyle::ReloadTextures() +{ + if (FSlateApplication::IsInitialized()) + { + FSlateApplication::Get().GetRenderer()->ReloadTextureResources(); + } +} + +const ISlateStyle& FSimpleUGCEditorStyle::Get() +{ + return *StyleInstance; +} diff --git a/Plugins/SimpleUGC/Source/SimpleUGCEditor/Private/SimpleUGCPackager.cpp b/Plugins/SimpleUGC/Source/SimpleUGCEditor/Private/SimpleUGCPackager.cpp new file mode 100644 index 0000000..c7bc2db --- /dev/null +++ b/Plugins/SimpleUGC/Source/SimpleUGCEditor/Private/SimpleUGCPackager.cpp @@ -0,0 +1,205 @@ +// Copyright Epic Games, Inc. All Rights Reserved. + +#include "SimpleUGCPackager.h" +#include "SimpleUGCEditor.h" +#include "SimpleUGCEditorCommands.h" +#include "SimpleUGCEditorStyle.h" +#include "Editor.h" +#include "Widgets/SWindow.h" +#include "Widgets/SWidget.h" +#include "Interfaces/IPluginManager.h" +#include "Developer/DesktopPlatform/Public/DesktopPlatformModule.h" +#include "Editor/UATHelper/Public/IUATHelperModule.h" +#include "Editor/MainFrame/Public/Interfaces/IMainFrameModule.h" + +#include "FileHelpers.h" +#include "Misc/PackageName.h" + +#define LOCTEXT_NAMESPACE "SimpleUGCPackager" + +FSimpleUGCPackager::FSimpleUGCPackager() +{ +} + +FSimpleUGCPackager::~FSimpleUGCPackager() +{ +} + +void FSimpleUGCPackager::OpenPluginPackager(TSharedRef<IPlugin> Plugin) +{ + IDesktopPlatform* DesktopPlatform = FDesktopPlatformModule::Get(); + + FString DefaultDirectory = FPaths::ConvertRelativePathToFull(Plugin->GetBaseDir()); + FString OutputDirectory; + + // Prompt the user to save all dirty packages. We'll ensure that if any packages from the mod that the user wants to + // package are dirty that they will not be able to save them. + + if (!IsAllContentSaved(Plugin)) + { + FEditorFileUtils::SaveDirtyPackages( true, true, true); + } + + if (IsAllContentSaved(Plugin)) + { + void* ParentWindowWindowHandle = nullptr; + IMainFrameModule& MainFrameModule = FModuleManager::LoadModuleChecked<IMainFrameModule>(TEXT("MainFrame")); + const TSharedPtr<SWindow>& MainFrameParentWindow = MainFrameModule.GetParentWindow(); + if (MainFrameParentWindow.IsValid() && MainFrameParentWindow->GetNativeWindow().IsValid()) + { + ParentWindowWindowHandle = MainFrameParentWindow->GetNativeWindow()->GetOSWindowHandle(); + } + + if (DesktopPlatform->OpenDirectoryDialog(ParentWindowWindowHandle, LOCTEXT("SelectOutputFolderTitle", "Select UGC output directory:").ToString(), DefaultDirectory, OutputDirectory)) + { + PackagePlugin(Plugin, OutputDirectory); + } + } + else + { + FText PackageModError = FText::Format(LOCTEXT("PackageUGCError_UnsavedContent", "You must save all assets in {0} before you can share it."), + FText::FromString(Plugin->GetName())); + + FMessageDialog::Open(EAppMsgType::Ok, PackageModError); + } +} + +bool FSimpleUGCPackager::IsAllContentSaved(TSharedRef<IPlugin> Plugin) +{ + bool bAllContentSaved = true; + + TArray<UPackage*> UnsavedPackages; + FEditorFileUtils::GetDirtyContentPackages(UnsavedPackages); + FEditorFileUtils::GetDirtyWorldPackages(UnsavedPackages); + + if (UnsavedPackages.Num() > 0) + { + FString PluginBaseDir = Plugin->GetBaseDir(); + + for (UPackage* Package : UnsavedPackages) + { + FString PackageFilename; + if (FPackageName::TryConvertLongPackageNameToFilename(Package->GetName(), PackageFilename)) + { + if (PackageFilename.Find(PluginBaseDir) == 0) + { + bAllContentSaved = false; + break; + } + } + } + } + + return bAllContentSaved; +} + +void FSimpleUGCPackager::PackagePlugin(TSharedRef<class IPlugin> Plugin, const FString& OutputDirectory) +{ +#if PLATFORM_WINDOWS + FText PlatformName = LOCTEXT("PlatformName_Windows", "Windows"); +#elif PLATFORM_MAC + FText PlatformName = LOCTEXT("PlatformName_Mac", "Mac"); +#elif PLATFORM_LINUX + FText PlatformName = LOCTEXT("PlatformName_Linux", "Linux"); +#else + FText PlatformName = LOCTEXT("PlatformName_Desktop", "Desktop"); +#endif + + // Hard coded here for simplicity. You will probably want to read this from an ini file + FString ReleaseVersion = TEXT("UGCExampleGame_v1"); + + FString CommandLine = FString::Printf(TEXT("PackageUGC -Project=\"%s\" -PluginPath=\"%s\" -basedonreleaseversion=\"%s\" -StagingDirectory=\"%s\" -nocompile"), + *FPaths::ConvertRelativePathToFull(FPaths::GetProjectFilePath()), + *FPaths::ConvertRelativePathToFull(Plugin->GetDescriptorFileName()), + *ReleaseVersion, + *OutputDirectory); + + FText PackagingText = FText::Format(LOCTEXT("SimpleUGCEditor_PackagePluginTaskName", "Packaging {0}"), FText::FromString(Plugin->GetName())); + + FString FriendlyName = Plugin->GetDescriptor().FriendlyName; + IUATHelperModule::Get().CreateUatTask(CommandLine, PlatformName, PackagingText, + PackagingText, FSimpleUGCEditorStyle::Get().GetBrush(TEXT("SimpleUGCEditor.PackageUGCAction")), + [ReleaseVersion, PlatformName, FriendlyName](FString TaskResult, double TimeSec) {}); +} + +void FSimpleUGCPackager::FindAvailableGameMods(TArray<TSharedRef<IPlugin>>& OutAvailableGameMods) +{ + OutAvailableGameMods.Empty(); + + // Find available game mods from the list of discovered plugins + + for (TSharedRef<IPlugin> Plugin : IPluginManager::Get().GetDiscoveredPlugins()) + { + // All game project plugins that are marked as mods are valid + if (Plugin->GetLoadedFrom() == EPluginLoadedFrom::Project && Plugin->GetType() == EPluginType::Mod) + { + UE_LOG(LogTemp, Display, TEXT("Adding %s"), *Plugin->GetName()); + OutAvailableGameMods.AddUnique(Plugin); + } + } +} + +void FSimpleUGCPackager::GeneratePackagerMenuContent_Internal(class FMenuBuilder& MenuBuilder, const TArray<TSharedPtr<FUICommandInfo>>& Commands) +{ + for (TSharedPtr<FUICommandInfo> Command : Commands) + { + MenuBuilder.AddMenuEntry(Command, NAME_None, TAttribute<FText>(), TAttribute<FText>(), FSlateIcon(FSimpleUGCEditorStyle::GetStyleSetName(), "SimpleUGCEditor.Folder")); + } +} + +void FSimpleUGCPackager::GeneratePackagerMenuContent(class FMenuBuilder& MenuBuilder) +{ + TArray<TSharedRef<IPlugin>> AvailableGameMods; + FindAvailableGameMods(AvailableGameMods); + + TArray<TSharedPtr<FUICommandInfo>> Commands; + + GeneratePackagerMenuContent_Internal(MenuBuilder, UGCCommands); +} + +TSharedRef<SWidget> FSimpleUGCPackager::GeneratePackagerComboButtonContent() +{ + // Regenerate the game mod commands + TArray<TSharedRef<IPlugin>> AvailableGameMods; + FindAvailableGameMods(AvailableGameMods); + + GetAvailableUGCCommands(AvailableGameMods); + + // Regenerate the action list + TSharedPtr<FUICommandList> GameModActionsList = MakeShareable(new FUICommandList); + + for (int32 Index = 0; Index < UGCCommands.Num(); ++Index) + { + GameModActionsList->MapAction( + UGCCommands[Index], + FExecuteAction::CreateRaw(this, &FSimpleUGCPackager::OpenPluginPackager, AvailableGameMods[Index]), + FCanExecuteAction() + ); + } + + // Show the drop down menu + const bool bShouldCloseWindowAfterMenuSelection = true; + FMenuBuilder MenuBuilder(bShouldCloseWindowAfterMenuSelection, GameModActionsList); + + MenuBuilder.BeginSection(NAME_None, LOCTEXT("PackageUGC", "Share...")); + { + GeneratePackagerMenuContent_Internal(MenuBuilder, UGCCommands); + } + MenuBuilder.EndSection(); + + return MenuBuilder.MakeWidget(); +} + +void FSimpleUGCPackager::GetAvailableUGCCommands(const TArray<TSharedRef<IPlugin>>& AvailableUGC) +{ + if (UGCCommands.Num() > 0) + { + // Unregister UI Commands + FSimpleUGCEditorCommands::Get().UnregisterUGCCommands(UGCCommands); + } + UGCCommands.Empty(AvailableUGC.Num()); + + UGCCommands = FSimpleUGCEditorCommands::Get().RegisterUGCCommands(AvailableUGC); +} + +#undef LOCTEXT_NAMESPACE
\ No newline at end of file diff --git a/Plugins/SimpleUGC/Source/SimpleUGCEditor/Private/SimpleUGCPluginWizardDefinition.cpp b/Plugins/SimpleUGC/Source/SimpleUGCEditor/Private/SimpleUGCPluginWizardDefinition.cpp new file mode 100644 index 0000000..53abeb4 --- /dev/null +++ b/Plugins/SimpleUGC/Source/SimpleUGCEditor/Private/SimpleUGCPluginWizardDefinition.cpp @@ -0,0 +1,214 @@ +// Copyright Epic Games, Inc. All Rights Reserved. + +#include "SimpleUGCPluginWizardDefinition.h" +#include "ContentBrowserModule.h" +#include "EngineAnalytics.h" +#include "Interfaces/IPluginManager.h" +#include "IContentBrowserSingleton.h" +#include "Algo/Transform.h" +#include "SlateBasics.h" +#include "SourceCodeNavigation.h" + +#define LOCTEXT_NAMESPACE "SimpleUGCPluginWizard" + +FSimpleUGCPluginWizardDefinition::FSimpleUGCPluginWizardDefinition() +{ + PluginBaseDir = IPluginManager::Get().FindPlugin(TEXT("SimpleUGC"))->GetBaseDir(); + // Find the Content Only Template that ships with the plugin. + // Download the Robo Recall Mod Kit and check the Plugins/OdinEditor code for how to build and use your own UGC templates from your game content + BackingTemplate = MakeShareable(new FPluginTemplateDescription(FText(), FText(), TEXT("BaseTemplate"), true, EHostType::Runtime)); + BackingTemplatePath = PluginBaseDir / TEXT("Templates") / BackingTemplate->OnDiskPath; +} + +const TArray<TSharedRef<FPluginTemplateDescription>>& FSimpleUGCPluginWizardDefinition::GetTemplatesSource() const +{ + return TemplateDefinitions; +} + +void FSimpleUGCPluginWizardDefinition::OnTemplateSelectionChanged(TArray<TSharedRef<FPluginTemplateDescription>> InSelectedItems, ESelectInfo::Type SelectInfo) +{ + SelectedTemplates = InSelectedItems; +} + +TArray<TSharedPtr<FPluginTemplateDescription>> FSimpleUGCPluginWizardDefinition::GetSelectedTemplates() const +{ + TArray<TSharedPtr<FPluginTemplateDescription>> SelectedTemplatePtrs; + + for (TSharedRef<FPluginTemplateDescription> Ref : SelectedTemplates) + { + SelectedTemplatePtrs.Add(Ref); + } + + return SelectedTemplatePtrs; +} + +void FSimpleUGCPluginWizardDefinition::ClearTemplateSelection() +{ + SelectedTemplates.Empty(); +} + +bool FSimpleUGCPluginWizardDefinition::HasValidTemplateSelection() const +{ + // A mod should be created even if no templates are actually selected + return true; +} + +bool FSimpleUGCPluginWizardDefinition::CanContainContent() const +{ + bool bHasContent = SelectedTemplates.Num() == 0; // if no templates are selected, by default it is a content mod + + if (!bHasContent) + { + for (TSharedPtr<FPluginTemplateDescription> Template : SelectedTemplates) + { + // If at least one module can contain content, it's a content mod. Otherwise, it's a pure code mod. + if (Template->bCanContainContent) + { + bHasContent = true; + break; + } + } + } + + return bHasContent; +} + +bool FSimpleUGCPluginWizardDefinition::HasModules() const +{ + bool bHasModules = false; + + for (TSharedPtr<FPluginTemplateDescription> Template : SelectedTemplates) + { + if (FPaths::DirectoryExists(PluginBaseDir / TEXT("Templates") / Template->OnDiskPath / TEXT("Source"))) + { + bHasModules = true; + break; + } + } + + return bHasModules; +} + +bool FSimpleUGCPluginWizardDefinition::IsMod() const +{ + return true; +} + +void FSimpleUGCPluginWizardDefinition::OnShowOnStartupCheckboxChanged(ECheckBoxState CheckBoxState) +{ +} + +ECheckBoxState FSimpleUGCPluginWizardDefinition::GetShowOnStartupCheckBoxState() const +{ + return ECheckBoxState(); +} + +FText FSimpleUGCPluginWizardDefinition::GetInstructions() const +{ + return LOCTEXT("CreateNewUGCPanel", "Give your new UGC package a name and Click 'Create Mod' to make a new content only UGC package."); +} + +TSharedPtr<SWidget> FSimpleUGCPluginWizardDefinition::GetCustomHeaderWidget() +{ + if ( !CustomHeaderWidget.IsValid() ) + { + FString IconPath; + GetPluginIconPath(IconPath); + + const FName BrushName(*IconPath); + const FIntPoint Size = FSlateApplication::Get().GetRenderer()->GenerateDynamicImageResource(BrushName); + if ((Size.X > 0) && (Size.Y > 0)) + { + IconBrush = MakeShareable(new FSlateDynamicImageBrush(BrushName, FVector2D(Size.X, Size.Y))); + } + + CustomHeaderWidget = SNew(SHorizontalBox) + // Header image + + SHorizontalBox::Slot() + .AutoWidth() + .Padding(4.0f) + [ + SNew(SBox) + .WidthOverride(80.0f) + .HeightOverride(80.0f) + [ + SNew(SImage) + .Image(IconBrush.IsValid() ? IconBrush.Get() : nullptr) + ] + ]; + } + + return CustomHeaderWidget; +} + +bool FSimpleUGCPluginWizardDefinition::GetPluginIconPath(FString& OutIconPath) const +{ + // Replace this file with your own 128x128 image if desired. + OutIconPath = BackingTemplatePath / TEXT("Resources/Icon128.png"); + return false; +} + +bool FSimpleUGCPluginWizardDefinition::GetTemplateIconPath(TSharedRef<FPluginTemplateDescription> InTemplate, FString& OutIconPath) const +{ + FString TemplateName = InTemplate->Name.ToString(); + + OutIconPath = PluginBaseDir / TEXT("Resources"); + + if (TemplateToIconMap.Contains(TemplateName)) + { + OutIconPath /= TemplateToIconMap[TemplateName]; + } + else + { + // Couldn't find a suitable icon to use for this template, so use the default one instead + OutIconPath /= TEXT("Icon128.png"); + } + + return false; +} + +FString FSimpleUGCPluginWizardDefinition::GetPluginFolderPath() const +{ + return BackingTemplatePath; +} + +EHostType::Type FSimpleUGCPluginWizardDefinition::GetPluginModuleDescriptor() const +{ + return BackingTemplate->ModuleDescriptorType; +} + +ELoadingPhase::Type FSimpleUGCPluginWizardDefinition::GetPluginLoadingPhase() const +{ + return BackingTemplate->LoadingPhase; +} + +TArray<FString> FSimpleUGCPluginWizardDefinition::GetFoldersForSelection() const +{ + TArray<FString> SelectedFolders; + SelectedFolders.Add(BackingTemplatePath); // This will always be a part of the mod plugin + + for (TSharedPtr<FPluginTemplateDescription> Template : SelectedTemplates) + { + SelectedFolders.AddUnique(PluginBaseDir / TEXT("Templates") / Template->OnDiskPath); + } + + return SelectedFolders; +} + +void FSimpleUGCPluginWizardDefinition::PluginCreated(const FString& PluginName, bool bWasSuccessful) const +{ + // Override Category to UGC + if (bWasSuccessful) + { + TSharedPtr<IPlugin> Plugin = IPluginManager::Get().FindPlugin(PluginName); + if (Plugin != nullptr) + { + FPluginDescriptor Desc = Plugin->GetDescriptor(); + Desc.Category = "UGC"; + FText UpdateFailureText; + Plugin->UpdateDescriptor(Desc, UpdateFailureText); + } + } +} + +#undef LOCTEXT_NAMESPACE |