void SBehaviorTreeBlackboardEditor::FillToolbar(FToolBarBuilder& ToolbarBuilder) const
{
	ToolbarBuilder.AddComboButton(
		FUIAction(
			FExecuteAction(),
			FCanExecuteAction::CreateSP(this, &SBehaviorTreeBlackboardEditor::CanCreateNewEntry)
			), 
		FOnGetContent::CreateSP(this, &SBehaviorTreeBlackboardEditor::HandleCreateNewEntryMenu),
		LOCTEXT( "New_Label", "New Key" ),
		LOCTEXT( "New_ToolTip", "Create a new blackboard entry" ),
		FSlateIcon(FEditorStyle::GetStyleSetName(), "BTEditor.Blackboard.NewEntry")
	);			
}
void FGameplayDebugger::CreateSettingSubMenu(FMenuBuilder& Builder)
{
#if !(UE_BUILD_SHIPPING || UE_BUILD_TEST)
	Builder.AddMenuEntry(
		LOCTEXT("Test_GameplayDebugger_Menu", "Test Gameplay Debugger Option"),
		LOCTEXT("Test_GameplayDebugger_Menu_Tooltip", "If Enabled, actors will snap to the nearest location on the constraint plane (NOTE: Only works correctly in perspective views right now!)"),
		FSlateIcon(),
		FUIAction(
		FExecuteAction()/*FExecuteAction::CreateRaw(PlanarPolicy.Get(), &FPlanarConstraintSnapPolicy::ToggleEnabled)*/,
		FCanExecuteAction(),
		FIsActionChecked()/*FIsActionChecked::CreateRaw(PlanarPolicy.Get(), &FPlanarConstraintSnapPolicy::IsEnabled)*/
		),
		NAME_None,
		EUserInterfaceActionType::Button,
		NAME_None);
#endif
}
	/**
	 * Takes the provided menu builder and adds elements representing various 
	 * profiles that the user can choose from (default, tutorial, etc.).
	 * 
	 * @param  MenuBuilder	The builder to modify and add entries to.
	 */
	static void BuildProfilesSubMenu(FMenuBuilder& MenuBuilder)
	{
		TArray<FString> AvailableProfiles;
	
		const UEditorPerProjectUserSettings* EditorPerProjectUserSettings = GetDefault<UEditorPerProjectUserSettings>();
		if (EditorPerProjectUserSettings->BlueprintFavorites != NULL)
		{
			static FString const ProfilesConfigKey("Profiles");
			GConfig->GetArray(*SBlueprintFavoritesPaletteUtils::ConfigSection, *ProfilesConfigKey, AvailableProfiles, GEditorIni);	
		}

		struct LocalUtils
		{
			static bool CanExecute()               { return true; }
			static bool CannotExecute()            { return false; }
			static void NavigateToURL(FString URL) { FPlatformProcess::LaunchURL(*URL, NULL, NULL); }
		};

		if (AvailableProfiles.Num() > 0)
		{
			for (FString const& Profile : AvailableProfiles)
			{
				FString ProfileName;
				FParse::Value(*Profile, TEXT("Name="), ProfileName);
				FString FriendlyProfileName;
				FParse::Value(*Profile, TEXT("FriendlyName="), FriendlyProfileName);
				FString ProfileToolTip;
				FParse::Value(*Profile, TEXT("ToolTip="), ProfileToolTip);
				FString ProfileURL;
				FParse::Value(*Profile, TEXT("URL="), ProfileURL);
				FString ProfileURLName;
				FParse::Value(*Profile, TEXT("URLText="), ProfileURLName);

				// @TODO how to best localize this?
				FText ToolTipText = FText::FromString(ProfileToolTip);
				if (ProfileURLName.IsEmpty())
				{
					ProfileURLName = ProfileURL;
				}
				if (FriendlyProfileName.IsEmpty())
				{
					FriendlyProfileName = ProfileName;
				}
				
				FUIAction ProfileAction;
				if (SBlueprintFavoritesPaletteUtils::CanLoadFavoritesProfile(ProfileName))
				{
					if (ToolTipText.IsEmpty())
					{
						ToolTipText = FText::Format(LOCTEXT("ProfileAvailableFmt", "Loads {0} node favorites"), FText::FromString(FriendlyProfileName));
					}

					ProfileAction = FUIAction(
						FExecuteAction::CreateStatic(&SBlueprintFavoritesPaletteUtils::LoadFavoritesProfile, ProfileName),
						FCanExecuteAction::CreateStatic(&LocalUtils::CanExecute)
					);
				}
				else 
				{
					if (ToolTipText.IsEmpty())
					{
						ToolTipText = LOCTEXT("ProfileLoaded", "Current profile");
					}

					ProfileAction = FUIAction(
						FExecuteAction(),
						FCanExecuteAction::CreateStatic(&LocalUtils::CannotExecute)
					);
				}

				// build the text that goes in the sub-menu
				TSharedRef<STextBlock> MenuTextEntry = SNew(STextBlock)
					.TextStyle(MenuBuilder.GetStyleSet(), FEditorStyle::Join("Menu", ".Label"))
					// @TODO how do we best localize this
					.Text(FText::FromString(FriendlyProfileName));

				FSlateFontInfo ToolTipFont(FPaths::EngineContentDir() / TEXT("Slate/Fonts/Roboto-Regular.ttf"), 8);

				TSharedPtr<SVerticalBox> ToolTipBox;
				// build the specialized tooltip
				TSharedRef<SToolTip> ToolTipWidget = SNew(SToolTip)
					[
						SAssignNew(ToolTipBox, SVerticalBox)
						+SVerticalBox::Slot()
						[
							SNew(STextBlock)
								.WrapTextAt(400)
								.Font(ToolTipFont)
								.Text(ToolTipText)
						]
					];

				// add the url if one was specified
				if (!ProfileURL.IsEmpty())
				{
					ToolTipBox->AddSlot()
						.AutoHeight()
						.HAlign(HAlign_Right)
					[
						SNew(SHyperlink)
							// @TODO how to best localize this?
							.Text(FText::FromString(ProfileURLName))
							.OnNavigate_Static(&LocalUtils::NavigateToURL, ProfileURL)
					];
				}

				// now build the actual menu widget
				TSharedRef<SWidget> MenuEntryWidget = SNew(SHorizontalBox)
						.ToolTip(ToolTipWidget)
						// so the tool tip shows up for the whole entry:
						.Visibility(EVisibility::Visible)
					+SHorizontalBox::Slot()
						// match the padding with normal sub-men entries
						.Padding(FMargin(18.f, 0.f, 6.f, 0.f))
						.FillWidth(1.0f)
					[
						MenuTextEntry
					];

				MenuBuilder.AddMenuEntry(ProfileAction, MenuEntryWidget);
			}
		}
		else 
		{
			FUIAction NullProfileAction(FExecuteAction(), FCanExecuteAction::CreateStatic(&LocalUtils::CannotExecute));
			MenuBuilder.AddMenuEntry(LOCTEXT("NoProfiles", "No profiles available"), FText::GetEmpty(), FSlateIcon(), NullProfileAction);
		}
	}
void FPathContextMenu::MakePathViewContextMenu(FMenuBuilder& MenuBuilder)
{
	int32 NumAssetPaths, NumClassPaths;
	ContentBrowserUtils::CountPathTypes(SelectedPaths, NumAssetPaths, NumClassPaths);

	// Only add something if at least one folder is selected
	if ( SelectedPaths.Num() > 0 )
	{
		const bool bHasAssetPaths = NumAssetPaths > 0;
		const bool bHasClassPaths = NumClassPaths > 0;

		// Common operations section //
		MenuBuilder.BeginSection("PathViewFolderOptions", LOCTEXT("PathViewOptionsMenuHeading", "Folder Options") );
		{
			if(bHasAssetPaths)
			{
				FText NewAssetToolTip;
				if(SelectedPaths.Num() == 1)
				{
					if(CanCreateAsset())
					{
						NewAssetToolTip = FText::Format(LOCTEXT("NewAssetTooltip_CreateIn", "Create a new asset in {0}."), FText::FromString(SelectedPaths[0]));
					}
					else
					{
						NewAssetToolTip = FText::Format(LOCTEXT("NewAssetTooltip_InvalidPath", "Cannot create new assets in {0}."), FText::FromString(SelectedPaths[0]));
					}
				}
				else
				{
					NewAssetToolTip = LOCTEXT("NewAssetTooltip_InvalidNumberOfPaths", "Can only create assets when there is a single path selected.");
				}

				// New Asset (submenu)
				MenuBuilder.AddSubMenu(
					LOCTEXT( "NewAssetLabel", "New Asset" ),
					NewAssetToolTip,
					FNewMenuDelegate::CreateRaw( this, &FPathContextMenu::MakeNewAssetSubMenu ),
					FUIAction(
						FExecuteAction(),
						FCanExecuteAction::CreateRaw( this, &FPathContextMenu::CanCreateAsset )
						),
					NAME_None,
					EUserInterfaceActionType::Button,
					false,
					FSlateIcon()
					);
			}

			if(bHasClassPaths)
			{
				FText NewClassToolTip;
				if(SelectedPaths.Num() == 1)
				{
					if(CanCreateClass())
					{
						NewClassToolTip = FText::Format(LOCTEXT("NewClassTooltip_CreateIn", "Create a new class in {0}."), FText::FromString(SelectedPaths[0]));
					}
					else
					{
						NewClassToolTip = FText::Format(LOCTEXT("NewClassTooltip_InvalidPath", "Cannot create new classes in {0}."), FText::FromString(SelectedPaths[0]));
					}
				}
				else
				{
					NewClassToolTip = LOCTEXT("NewClassTooltip_InvalidNumberOfPaths", "Can only create classes when there is a single path selected.");
				}

				// New Class
				MenuBuilder.AddMenuEntry(
					LOCTEXT("NewClassLabel", "New C++ Class..."),
					NewClassToolTip,
					FSlateIcon(FEditorStyle::GetStyleSetName(), "MainFrame.AddCodeToProject"),
					FUIAction(
						FExecuteAction::CreateRaw( this, &FPathContextMenu::ExecuteCreateClass ),
						FCanExecuteAction::CreateRaw( this, &FPathContextMenu::CanCreateClass )
						)
					);
			}

			// Explore
			MenuBuilder.AddMenuEntry(
				ContentBrowserUtils::GetExploreFolderText(),
				LOCTEXT("ExploreTooltip", "Finds this folder on disk."),
				FSlateIcon(),
				FUIAction( FExecuteAction::CreateSP( this, &FPathContextMenu::ExecuteExplore ) )
				);

			MenuBuilder.AddMenuEntry(FGenericCommands::Get().Rename, NAME_None,
				LOCTEXT("RenameFolder", "Rename"),
				LOCTEXT("RenameFolderTooltip", "Rename the selected folder.")
				);

			// If any colors have already been set, display color options as a sub menu
			if ( ContentBrowserUtils::HasCustomColors() )
			{
				// Set Color (submenu)
				MenuBuilder.AddSubMenu(
					LOCTEXT("SetColor", "Set Color"),
					LOCTEXT("SetColorTooltip", "Sets the color this folder should appear as."),
					FNewMenuDelegate::CreateRaw( this, &FPathContextMenu::MakeSetColorSubMenu ),
					false,
					FSlateIcon()
					);
			}
			else
			{
				// Set Color
				MenuBuilder.AddMenuEntry(
					LOCTEXT("SetColor", "Set Color"),
					LOCTEXT("SetColorTooltip", "Sets the color this folder should appear as."),
					FSlateIcon(),
					FUIAction( FExecuteAction::CreateSP( this, &FPathContextMenu::ExecutePickColor ) )
					);
			}			
		}
		MenuBuilder.EndSection();

		if(bHasAssetPaths)
		{
			// Bulk operations section //
			MenuBuilder.BeginSection("PathContextBulkOperations", LOCTEXT("AssetTreeBulkMenuHeading", "Bulk Operations") );
			{
				// Save
				MenuBuilder.AddMenuEntry(
					LOCTEXT("SaveFolder", "Save All"),
					LOCTEXT("SaveFolderTooltip", "Saves all modified assets in this folder."),
					FSlateIcon(),
					FUIAction( FExecuteAction::CreateSP( this, &FPathContextMenu::ExecuteSaveFolder ) )
					);
    
				// Delete
				MenuBuilder.AddMenuEntry(FGenericCommands::Get().Delete, NAME_None,
					LOCTEXT("DeleteFolder", "Delete"),
					LOCTEXT("DeleteFolderTooltip", "Removes this folder and all assets it contains."),
					FSlateIcon()
					);

				// Reference Viewer
				MenuBuilder.AddMenuEntry(
					LOCTEXT("ReferenceViewer", "Reference Viewer..."),
					LOCTEXT("ReferenceViewerOnFolderTooltip", "Shows a graph of references for this folder."),
					FSlateIcon(),
					FUIAction( FExecuteAction::CreateSP( this, &FPathContextMenu::ExecuteReferenceViewer ) )
					);
    
				// Size Map
				MenuBuilder.AddMenuEntry(
					LOCTEXT("SizeMap", "Size Map..."),
					LOCTEXT("SizeMapOnFolderTooltip", "Shows an interactive map of the approximate memory used by the assets in this folder and everything they reference."),
					FSlateIcon(),
					FUIAction( FExecuteAction::CreateSP( this, &FPathContextMenu::ExecuteSizeMap ) )
					);

				// Fix Up Redirectors in Folder
				MenuBuilder.AddMenuEntry(
					LOCTEXT("FixUpRedirectorsInFolder", "Fix Up Redirectors in Folder"),
					LOCTEXT("FixUpRedirectorsInFolderTooltip", "Finds referencers to all redirectors in the selected folders and resaves them if possible, then deletes any redirectors that had all their referencers fixed."),
					FSlateIcon(),
					FUIAction( FExecuteAction::CreateSP( this, &FPathContextMenu::ExecuteFixUpRedirectorsInFolder ) )
					);

				if ( NumAssetPaths == 1 && NumClassPaths == 0 )
				{
					// Migrate Folder
					MenuBuilder.AddMenuEntry(
						LOCTEXT("MigrateFolder", "Migrate..."),
						LOCTEXT("MigrateFolderTooltip", "Copies assets found in this folder and their dependencies to another game content folder."),
						FSlateIcon(),
						FUIAction( FExecuteAction::CreateSP( this, &FPathContextMenu::ExecuteMigrateFolder ) )
						);
				}
			}
			MenuBuilder.EndSection();

			// Source control section //
			MenuBuilder.BeginSection("PathContextSourceControl", LOCTEXT("AssetTreeSCCMenuHeading", "Source Control") );

			ISourceControlProvider& SourceControlProvider = ISourceControlModule::Get().GetProvider();
			if ( SourceControlProvider.IsEnabled() )
			{
				// Check out
				MenuBuilder.AddMenuEntry(
					LOCTEXT("FolderSCCCheckOut", "Check Out"),
					LOCTEXT("FolderSCCCheckOutTooltip", "Checks out all assets from source control which are in this folder."),
					FSlateIcon(),
					FUIAction(
						FExecuteAction::CreateSP( this, &FPathContextMenu::ExecuteSCCCheckOut ),
						FCanExecuteAction::CreateSP( this, &FPathContextMenu::CanExecuteSCCCheckOut )
						)
					);

				// Open for Add
				MenuBuilder.AddMenuEntry(
					LOCTEXT("FolderSCCOpenForAdd", "Mark For Add"),
					LOCTEXT("FolderSCCOpenForAddTooltip", "Adds all assets to source control that are in this folder and not already added."),
					FSlateIcon(),
					FUIAction(
						FExecuteAction::CreateSP( this, &FPathContextMenu::ExecuteSCCOpenForAdd ),
						FCanExecuteAction::CreateSP( this, &FPathContextMenu::CanExecuteSCCOpenForAdd )
						)
					);

				// Check in
				MenuBuilder.AddMenuEntry(
					LOCTEXT("FolderSCCCheckIn", "Check In"),
					LOCTEXT("FolderSCCCheckInTooltip", "Checks in all assets to source control which are in this folder."),
					FSlateIcon(),
					FUIAction(
						FExecuteAction::CreateSP( this, &FPathContextMenu::ExecuteSCCCheckIn ),
						FCanExecuteAction::CreateSP( this, &FPathContextMenu::CanExecuteSCCCheckIn )
						)
					);

				// Sync
				MenuBuilder.AddMenuEntry(
					LOCTEXT("FolderSCCSync", "Sync"),
					LOCTEXT("FolderSCCSyncTooltip", "Syncs all the assets in this folder to the latest version."),
					FSlateIcon(),
					FUIAction(
						FExecuteAction::CreateSP( this, &FPathContextMenu::ExecuteSCCSync ),
						FCanExecuteAction::CreateSP( this, &FPathContextMenu::CanExecuteSCCSync )
						)
					);
			}
			else
			{
				MenuBuilder.AddMenuEntry(
					LOCTEXT("FolderSCCConnect", "Connect To Source Control"),
					LOCTEXT("FolderSCCConnectTooltip", "Connect to source control to allow source control operations to be performed on content and levels."),
					FSlateIcon(),
					FUIAction(
						FExecuteAction::CreateSP( this, &FPathContextMenu::ExecuteSCCConnect ),
						FCanExecuteAction::CreateSP( this, &FPathContextMenu::CanExecuteSCCConnect )
						)
					);	
			}

			MenuBuilder.EndSection();
		}
	}
}
TSharedPtr<SWidget> FCollectionContextMenu::MakeCollectionTreeContextMenu(TSharedPtr< FUICommandList > InCommandList)
{
	// Get all menu extenders for this context menu from the content browser module
	FContentBrowserModule& ContentBrowserModule = FModuleManager::GetModuleChecked<FContentBrowserModule>( TEXT("ContentBrowser") );
	TArray<FContentBrowserMenuExtender> MenuExtenderDelegates = ContentBrowserModule.GetAllCollectionListContextMenuExtenders();

	TArray<TSharedPtr<FExtender>> Extenders;
	for (int32 i = 0; i < MenuExtenderDelegates.Num(); ++i)
	{
		if (MenuExtenderDelegates[i].IsBound())
		{
			Extenders.Add(MenuExtenderDelegates[i].Execute());
		}
	}
	TSharedPtr<FExtender> MenuExtender = FExtender::Combine(Extenders);

	FMenuBuilder MenuBuilder(/*bInShouldCloseWindowAfterMenuSelection=*/true, InCommandList, MenuExtender);

	UpdateProjectSourceControl();

	TArray<TSharedPtr<FCollectionItem>> SelectedCollections = CollectionView.Pin()->CollectionTreePtr->GetSelectedItems();

	bool bAnyManagedBySCC = false;
	bool bAnyNeedSCCUpdate = false;
	bool bAnyNeedSave = false;
		
	for (int32 CollectionIdx = 0; CollectionIdx < SelectedCollections.Num(); ++CollectionIdx)
	{
		bAnyManagedBySCC |= SelectedCollections[CollectionIdx]->CollectionType != ECollectionShareType::CST_Local;
		bAnyNeedSCCUpdate |= SelectedCollections[CollectionIdx]->CurrentStatus == ECollectionItemStatus::IsOutOfDate;
		bAnyNeedSave |= SelectedCollections[CollectionIdx]->CurrentStatus == ECollectionItemStatus::HasLocalChanges;

		if (bAnyManagedBySCC && bAnyNeedSCCUpdate && bAnyNeedSave)
		{
			// Found collections to turn all options on, break now
			break;
		}
	}

	MenuBuilder.BeginSection("CollectionOptions", LOCTEXT("CollectionListOptionsMenuHeading", "Collection Options"));
	{
		const bool bHasSingleSelectedCollection = SelectedCollections.Num() == 1;
		const bool bIsFirstSelectedCollectionStatic = SelectedCollections.Num() > 0 && SelectedCollections[0]->StorageMode == ECollectionStorageMode::Static;

		// New... (submenu)
		MenuBuilder.AddSubMenu(
			LOCTEXT("NewChildCollection", "New..."),
			LOCTEXT("NewChildCollectionTooltip", "Create child a collection."),
			FNewMenuDelegate::CreateRaw( this, &FCollectionContextMenu::MakeNewCollectionSubMenu, ECollectionStorageMode::Static, SCollectionView::FCreateCollectionPayload( FCollectionNameType( SelectedCollections[0]->CollectionName, SelectedCollections[0]->CollectionType ) ) ),
			FUIAction(
				FExecuteAction(),
				FCanExecuteAction::CreateLambda( [=]{ return bHasSingleSelectedCollection && bIsFirstSelectedCollectionStatic; } )
				),
			NAME_None,
			EUserInterfaceActionType::Button
			);

		// Rename
		MenuBuilder.AddMenuEntry( FGenericCommands::Get().Rename, NAME_None, LOCTEXT("RenameCollection", "Rename"), LOCTEXT("RenameCollectionTooltip", "Rename this collection."));

		// Set Share Type
		MenuBuilder.AddSubMenu(
			LOCTEXT("SetCollectionShareType", "Set Share Type"),
			LOCTEXT("SetCollectionShareTypeTooltip", "Change the share type of this collection."),
			FNewMenuDelegate::CreateRaw( this, &FCollectionContextMenu::MakeCollectionShareTypeSubMenu ),
			FUIAction(
				FExecuteAction(),
				FCanExecuteAction::CreateLambda( [=]{ return bHasSingleSelectedCollection; } )
				),
			NAME_None,
			EUserInterfaceActionType::Button
			);

		// If any colors have already been set, display color options as a sub menu
		if ( CollectionViewUtils::HasCustomColors() )
		{
			// Set Color (submenu)
			MenuBuilder.AddSubMenu(
				LOCTEXT("SetColor", "Set Color"),
				LOCTEXT("SetCollectionColorTooltip", "Sets the color this collection should appear as."),
				FNewMenuDelegate::CreateRaw( this, &FCollectionContextMenu::MakeSetColorSubMenu )
				);
		}
		else
		{
			// Set Color
			MenuBuilder.AddMenuEntry(
				LOCTEXT("SetColor", "Set Color"),
				LOCTEXT("SetCollectionColorTooltip", "Sets the color this collection should appear as."),
				FSlateIcon(),
				FUIAction( FExecuteAction::CreateSP( this, &FCollectionContextMenu::ExecutePickColor ) )
				);
		}
	}
	MenuBuilder.EndSection();

	if ( SelectedCollections.Num() > 0 )
	{
		MenuBuilder.BeginSection("CollectionBulkOperations", LOCTEXT("CollectionListBulkOperationsMenuHeading", "Bulk Operations"));
		{
			// Save
			MenuBuilder.AddMenuEntry(
				LOCTEXT("SaveCollection", "Save"),
				LOCTEXT("SaveCollectionTooltip", "Save this collection."),
				FSlateIcon(),
				FUIAction(
					FExecuteAction::CreateSP( this, &FCollectionContextMenu::ExecuteSaveCollection ),
					FCanExecuteAction::CreateLambda( [=]{ return bAnyNeedSave; } )
					)
				);

			// Delete
			MenuBuilder.AddMenuEntry(
				LOCTEXT("DestroyCollection", "Delete"),
				LOCTEXT("DestroyCollectionTooltip", "Delete this collection."),
				FSlateIcon(),
				FUIAction(
					FExecuteAction::CreateSP( this, &FCollectionContextMenu::ExecuteDestroyCollection ),
					FCanExecuteAction::CreateSP( this, &FCollectionContextMenu::CanExecuteDestroyCollection, bAnyManagedBySCC )
					)
				);

			// Update
			MenuBuilder.AddMenuEntry(
				LOCTEXT("UpdateCollection", "Update"),
				LOCTEXT("UpdateCollectionTooltip", "Update this collection to make sure it's using the latest version from source control."),
				FSlateIcon(),
				FUIAction(
					FExecuteAction::CreateSP( this, &FCollectionContextMenu::ExecuteUpdateCollection ),
					FCanExecuteAction::CreateLambda( [=]{ return bAnyNeedSCCUpdate; } )
					)
				);
		}
		MenuBuilder.EndSection();
	}
	
	return MenuBuilder.MakeWidget();
}