Add Recent Blueprint Plugin
This commit is contained in:
parent
a5e8a8db13
commit
b62d7d75de
@ -68,6 +68,11 @@
|
||||
"Name": "AsyncLoadingScreen",
|
||||
"Enabled": true,
|
||||
"MarketplaceURL": "com.epicgames.launcher://ue/marketplace/product/01f39767dc6b4290877f38365787cbf8"
|
||||
},
|
||||
{
|
||||
"Name": "RecentBlueprintMenu",
|
||||
"Enabled": true,
|
||||
"MarketplaceURL": "com.epicgames.launcher://ue/marketplace/product/484f72297c144cf9b5c35fea3359500c"
|
||||
}
|
||||
]
|
||||
}
|
@ -0,0 +1,28 @@
|
||||
{
|
||||
"FileVersion": 3,
|
||||
"Version": 101,
|
||||
"VersionName": "1.01",
|
||||
"FriendlyName": "Recent Blueprints Menu",
|
||||
"Description": "A simple but time saving plugin that adds a \"Recent Blueprints\" menu to the blueprint editor. Giving you one click access to blueprints recently opened, and avoid having to constantly search for them.",
|
||||
"Category": "Blueprint Editor",
|
||||
"CreatedBy": "The Tool Shed",
|
||||
"CreatedByURL": "https://unrealengine.com/marketplace/en-US/profile/The%20Tool%20Shed",
|
||||
"DocsURL": "https://docs.google.com/presentation/d/10Gp1y-EPkBW8myvR-Lzd3viMDU5xovd0fSzJLOFm4NI/edit?usp=sharing",
|
||||
"MarketplaceURL": "com.epicgames.launcher://ue/marketplace/product/484f72297c144cf9b5c35fea3359500c",
|
||||
"SupportURL": "https://forums.unrealengine.com/t/support-recent-blueprints-menu/532808",
|
||||
"EngineVersion": "5.1.0",
|
||||
"CanContainContent": false,
|
||||
"Installed": true,
|
||||
"Modules": [
|
||||
{
|
||||
"Name": "RecentBlueprintMenu",
|
||||
"Type": "Editor",
|
||||
"LoadingPhase": "PostEngineInit",
|
||||
"PlatformAllowList": [
|
||||
"Win64",
|
||||
"Mac",
|
||||
"Linux"
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
BIN
EndlessVendetta/Plugins/RecentBlueprintMenu/Resources/Icon128.png
(Stored with Git LFS)
Normal file
BIN
EndlessVendetta/Plugins/RecentBlueprintMenu/Resources/Icon128.png
(Stored with Git LFS)
Normal file
Binary file not shown.
@ -0,0 +1,83 @@
|
||||
// Copyright 2022 The Tool Shed (Chris Garnier)
|
||||
|
||||
#include "RecentBlueprintMenu.h"
|
||||
#if ENGINE_MAJOR_VERSION == 4 && ENGINE_MINOR_VERSION < 24
|
||||
#include "Toolkits/AssetEditorManager.h"
|
||||
#endif
|
||||
#include "BlueprintEditor.h"
|
||||
#include "RecentBlueprintMenuUtils.h"
|
||||
#include "RecentBlueprintMenuSettings.h"
|
||||
#include "EditorStyleSet.h"
|
||||
#include "Framework/MultiBox/MultiBoxBuilder.h"
|
||||
#include "Engine/LevelScriptBlueprint.h"
|
||||
|
||||
#define LOCTEXT_NAMESPACE "FRecentBlueprintMenuModule"
|
||||
|
||||
void FRecentBlueprintMenuModule::StartupModule()
|
||||
{
|
||||
///ADD NEW BLUEPRINT MENU
|
||||
FBlueprintEditorModule& BlueprintEditorModule = FModuleManager::LoadModuleChecked<FBlueprintEditorModule>("Kismet");
|
||||
if (const TSharedPtr<FExtensibilityManager> MenuExtender = BlueprintEditorModule.GetMenuExtensibilityManager())
|
||||
{
|
||||
BlueprintMenuExtender = MakeShareable(new FExtender);
|
||||
BlueprintMenuExtender->AddMenuExtension("FileBlueprint",
|
||||
EExtensionHook::Before,
|
||||
nullptr,
|
||||
FMenuExtensionDelegate::CreateRaw(this, &FRecentBlueprintMenuModule::OnBuildBlueprintMenu));
|
||||
MenuExtender->AddExtender(BlueprintMenuExtender);
|
||||
}
|
||||
|
||||
//SUBSCRIBE TO BLUEPRINT OPEN EVENTS
|
||||
#if ENGINE_MAJOR_VERSION == 4 && ENGINE_MINOR_VERSION < 24
|
||||
FAssetEditorManager::Get().OnAssetEditorRequestedOpen().AddLambda([](UObject* Asset)
|
||||
#else
|
||||
GEditor->GetEditorSubsystem<UAssetEditorSubsystem>()->OnAssetEditorRequestedOpen().AddLambda([](UObject* Asset)
|
||||
#endif
|
||||
{
|
||||
if (Asset && Asset->GetClass() == UBlueprint::StaticClass() && Asset->GetClass() != ULevelScriptBlueprint::StaticClass())
|
||||
{
|
||||
FRecentBlueprintMenuUtils::OnBlueprintOpened(Asset->GetPathName());
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
void FRecentBlueprintMenuModule::ShutdownModule()
|
||||
{
|
||||
}
|
||||
|
||||
void FRecentBlueprintMenuModule::OnBuildBlueprintMenu(FMenuBuilder& MenuBuilder)
|
||||
{
|
||||
MenuBuilder.BeginSection("RecentBlueprintMenuSection", FText::FromString("Quick Access"));
|
||||
MenuBuilder.AddSubMenu(FText::FromString("Recent Blueprints..."),
|
||||
FText::FromString("Select a Blueprint to edit from a list of recently opened ones."),
|
||||
FNewMenuDelegate::CreateRaw(this, &FRecentBlueprintMenuModule::OnBuildRecentSubMenu),
|
||||
false,
|
||||
FSlateIcon(FEditorStyle::GetStyleSetName(),"GraphEditor.Timeline_16x"));
|
||||
MenuBuilder.EndSection();
|
||||
}
|
||||
|
||||
void FRecentBlueprintMenuModule::OnBuildRecentSubMenu(FMenuBuilder& MenuBuilder)
|
||||
{
|
||||
//purge first to ensure we have a list with no bad assets
|
||||
FRecentBlueprintMenuUtils::PurgeList();
|
||||
|
||||
TArray<FString> RecentList = GetDefault<URecentBlueprintMenuSettings>()->RecentBlueprints;
|
||||
for (FString Entry : RecentList)
|
||||
{
|
||||
MenuBuilder.AddMenuEntry(FText::FromString(FPackageName::ObjectPathToObjectName(Entry)),
|
||||
FText::FromString(FPackageName::ObjectPathToPackageName(Entry)),
|
||||
FSlateIcon(),
|
||||
FUIAction(FExecuteAction::CreateLambda([Entry]()
|
||||
{
|
||||
#if ENGINE_MAJOR_VERSION == 4 && ENGINE_MINOR_VERSION < 24
|
||||
FAssetEditorManager::Get().OpenEditorForAsset(Entry);
|
||||
#else
|
||||
GEditor->GetEditorSubsystem<UAssetEditorSubsystem>()->OpenEditorForAsset(Entry);
|
||||
#endif
|
||||
})));
|
||||
}
|
||||
}
|
||||
|
||||
#undef LOCTEXT_NAMESPACE
|
||||
|
||||
IMPLEMENT_MODULE(FRecentBlueprintMenuModule, RecentBlueprintMenu)
|
@ -0,0 +1,57 @@
|
||||
// Copyright 2022 The Tool Shed (Chris Garnier)
|
||||
|
||||
|
||||
#include "RecentBlueprintMenuUtils.h"
|
||||
#include "RecentBlueprintMenuSettings.h"
|
||||
|
||||
void FRecentBlueprintMenuUtils::OnBlueprintOpened(FString BlueprintPath)
|
||||
{
|
||||
|
||||
TArray<FString>& RecentList = GetMutableDefault<URecentBlueprintMenuSettings>()->RecentBlueprints;
|
||||
const int32 Index = RecentList.Find(BlueprintPath);
|
||||
if (Index != INDEX_NONE) //If it's already in the list we just need to move it to the top
|
||||
{
|
||||
if (Index == 0)
|
||||
{
|
||||
return; //already first
|
||||
}
|
||||
RecentList.RemoveAt(Index); //removes so we can re-add at the end
|
||||
}
|
||||
RecentList.EmplaceAt(0, BlueprintPath);
|
||||
|
||||
//Now that we've added, trim entries
|
||||
const uint8 MaxBP = GetDefault<URecentBlueprintMenuSettings>()->MaxRecentBP;
|
||||
if (RecentList.Num() > MaxBP)
|
||||
{
|
||||
TArray<FString> TrimmedList;
|
||||
for (int i=0; i < RecentList.Num(); i++)
|
||||
{
|
||||
if (i < MaxBP)
|
||||
{
|
||||
TrimmedList.Add(RecentList[i]);
|
||||
}
|
||||
}
|
||||
RecentList = TrimmedList;
|
||||
}
|
||||
|
||||
GetMutableDefault<URecentBlueprintMenuSettings>()->SaveConfig();
|
||||
|
||||
}
|
||||
|
||||
void FRecentBlueprintMenuUtils::PurgeList()
|
||||
{
|
||||
TArray<FString>& List = GetMutableDefault<URecentBlueprintMenuSettings>()->RecentBlueprints;
|
||||
|
||||
TArray<FString> NewList;
|
||||
|
||||
for (int32 i = 0; i < List.Num(); i++)
|
||||
{
|
||||
if (FPackageName::DoesPackageExist(List[i]))
|
||||
{
|
||||
NewList.Add(List[i]);
|
||||
}
|
||||
}
|
||||
|
||||
List = NewList;
|
||||
GetMutableDefault<URecentBlueprintMenuSettings>()->SaveConfig();
|
||||
}
|
@ -0,0 +1,28 @@
|
||||
// Copyright 2022 The Tool Shed (Chris Garnier)
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "CoreMinimal.h"
|
||||
#include "Modules/ModuleManager.h"
|
||||
|
||||
class FMenuBuilder;
|
||||
class FExtender;
|
||||
|
||||
class FRecentBlueprintMenuModule : public IModuleInterface
|
||||
{
|
||||
public:
|
||||
|
||||
/** IModuleInterface implementation */
|
||||
virtual void StartupModule() override;
|
||||
virtual void ShutdownModule() override;
|
||||
|
||||
private:
|
||||
//Delegate to generate new menu in BP
|
||||
void OnBuildBlueprintMenu(FMenuBuilder&);
|
||||
|
||||
//Delegate to generate new menu in BP
|
||||
void OnBuildRecentSubMenu(FMenuBuilder&);
|
||||
|
||||
//Pointer to the extender used for the new custom blueprint menu
|
||||
TSharedPtr<FExtender> BlueprintMenuExtender;
|
||||
};
|
@ -0,0 +1,25 @@
|
||||
// Copyright 2022 The Tool Shed (Chris Garnier)
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "CoreMinimal.h"
|
||||
#include "UObject/Object.h"
|
||||
#include "RecentBlueprintMenuSettings.generated.h"
|
||||
|
||||
/**
|
||||
* Settings class for RecentBlueprintMenu to save recent BPs and other info
|
||||
*/
|
||||
UCLASS(config=EditorPerProjectUserSettings)
|
||||
class RECENTBLUEPRINTMENU_API URecentBlueprintMenuSettings : public UObject
|
||||
{
|
||||
GENERATED_BODY()
|
||||
|
||||
public:
|
||||
//List of blueprints that were recently open to show in the Recent menu
|
||||
UPROPERTY(Config)
|
||||
TArray<FString> RecentBlueprints;
|
||||
|
||||
//How many Blueprints to remember max
|
||||
UPROPERTY(Config) //not presented in a menu but users can modify in ini
|
||||
uint8 MaxRecentBP = 15;
|
||||
};
|
@ -0,0 +1,23 @@
|
||||
// Copyright 2022 The Tool Shed (Chris Garnier)
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "CoreMinimal.h"
|
||||
|
||||
/**
|
||||
* RecentBlueprintMenu class containing functions to use by the menus
|
||||
*/
|
||||
|
||||
|
||||
class RECENTBLUEPRINTMENU_API FRecentBlueprintMenuUtils
|
||||
{
|
||||
friend class FRecentBlueprintMenuModule; //TODO: Only friend the necessary classes
|
||||
|
||||
private:
|
||||
//Called when a blueprint opens, so it can get saved to the recent list
|
||||
static void OnBlueprintOpened(FString BlueprintPath);
|
||||
|
||||
//Remove files that do not exist anymore
|
||||
static void PurgeList();
|
||||
|
||||
};
|
@ -0,0 +1,55 @@
|
||||
// Copyright 2022 The Tool Shed (Chris Garnier)
|
||||
|
||||
using UnrealBuildTool;
|
||||
|
||||
public class RecentBlueprintMenu : ModuleRules
|
||||
{
|
||||
public RecentBlueprintMenu(ReadOnlyTargetRules Target) : base(Target)
|
||||
{
|
||||
PCHUsage = ModuleRules.PCHUsageMode.UseExplicitOrSharedPCHs;
|
||||
|
||||
PublicIncludePaths.AddRange(
|
||||
new string[] {
|
||||
// ... add public include paths required here ...
|
||||
}
|
||||
);
|
||||
|
||||
|
||||
PrivateIncludePaths.AddRange(
|
||||
new string[] {
|
||||
// ... add other private include paths required here ...
|
||||
}
|
||||
);
|
||||
|
||||
|
||||
PublicDependencyModuleNames.AddRange(
|
||||
new string[]
|
||||
{
|
||||
"Core",
|
||||
// ... add other public dependencies that you statically link with here ...
|
||||
}
|
||||
);
|
||||
|
||||
|
||||
PrivateDependencyModuleNames.AddRange(
|
||||
new string[]
|
||||
{
|
||||
"CoreUObject",
|
||||
"Engine",
|
||||
"Slate",
|
||||
"SlateCore",
|
||||
"UnrealEd",
|
||||
"EditorStyle"
|
||||
// ... add private dependencies that you statically link with here ...
|
||||
}
|
||||
);
|
||||
|
||||
|
||||
DynamicallyLoadedModuleNames.AddRange(
|
||||
new string[]
|
||||
{
|
||||
// ... add any modules that your module loads dynamically here ...
|
||||
}
|
||||
);
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Block a user