├── .gitattributes ├── .gitignore ├── Config ├── DefaultEditor.ini ├── DefaultEngine.ini ├── DefaultGame.ini └── HoloLens │ └── HoloLensEngine.ini ├── Content ├── Blueprint │ └── NewFolder1 │ │ ├── BP_Used_1.uasset │ │ └── BP_Used_2.uasset ├── Map │ ├── ToolTestMap.umap │ └── ToolTestMap_BuiltData.uasset ├── TestDeleting │ ├── BP_Used.uasset │ ├── NewBlueprint_6.uasset │ ├── NewBlueprint_7.uasset │ ├── NewBlueprint_8.uasset │ ├── NewBlueprint_9.uasset │ ├── NewFolder1 │ │ ├── NewBlueprint_7.uasset │ │ └── NewBlueprint_8.uasset │ └── NewFolder2 │ │ ├── NewBlueprint_8.uasset │ │ └── NewBlueprint_9.uasset └── TestTextures │ ├── MI_.uasset │ ├── MI_metal_grate_rusty_diff_2k.uasset │ ├── M_castle_brick_02_red_diff_2k.uasset │ ├── M_metal_grate_rusty_diff_2k.uasset │ ├── NewBlueprint.uasset │ ├── castle_brick_02_red_ao_2k.uasset │ ├── castle_brick_02_red_arm_2k.uasset │ ├── castle_brick_02_red_diff_2k.uasset │ ├── castle_brick_02_red_nor_gl_2k.uasset │ ├── castle_brick_02_red_rough_2k.uasset │ ├── metal_grate_rusty_ao_2k.uasset │ ├── metal_grate_rusty_arm_2k.uasset │ ├── metal_grate_rusty_diff_2k.uasset │ ├── metal_grate_rusty_metal_2k.uasset │ ├── metal_grate_rusty_nor_gl_2k.uasset │ └── metal_grate_rusty_rough_2k.uasset ├── ExtendEditor.uproject ├── LICENSE ├── Plugins └── SuperManager │ ├── Content │ ├── WBP_QuickActorActions.uasset │ └── WBP_QuickMaterialCreation.uasset │ ├── Resources │ ├── AdvanceDeletion.png │ ├── DeleteEmptyFolders.png │ ├── DeleteUnusedAsset.png │ ├── Icon128.png │ ├── SelectionLock.png │ └── SelectionUnlock.png │ ├── Source │ └── SuperManager │ │ ├── Private │ │ ├── ActorActions │ │ │ └── QuickActorActionsWidget.cpp │ │ ├── AssetActions │ │ │ ├── QuickAssetAction.cpp │ │ │ └── QuickMaterialCreationWidget.cpp │ │ ├── CustomOutlinerColumn │ │ │ └── OutlinerSelectionLockColumn.cpp │ │ ├── CustomStyle │ │ │ └── SuperManagerStyle.cpp │ │ ├── CustomUICommands │ │ │ └── SuperManagerUICommands.cpp │ │ ├── SlateWidgets │ │ │ └── AdvanceDeletionWidget.cpp │ │ └── SuperManager.cpp │ │ ├── Public │ │ ├── ActorActions │ │ │ └── QuickActorActionsWidget.h │ │ ├── AssetActions │ │ │ ├── QuickAssetAction.h │ │ │ └── QuickMaterialCreationWidget.h │ │ ├── CustomOutlinerColumn │ │ │ └── OutlinerSelectionLockColumn.h │ │ ├── CustomStyle │ │ │ └── SuperManagerStyle.h │ │ ├── CustomUICommands │ │ │ └── SuperManagerUICommands.h │ │ ├── DebugHeader.h │ │ ├── SlateWidgets │ │ │ └── AdvanceDeletionWidget.h │ │ └── SuperManager.h │ │ └── SuperManager.Build.cs │ └── SuperManager.uplugin ├── README.md └── Source ├── ExtendEditor.Target.cs ├── ExtendEditor ├── ExtendEditor.Build.cs ├── ExtendEditor.cpp ├── ExtendEditor.h ├── ExtendEditorGameModeBase.cpp └── ExtendEditorGameModeBase.h └── ExtendEditorEditor.Target.cs /.gitattributes: -------------------------------------------------------------------------------- 1 | Content/** filter=lfs diff=lfs merge=lfs -text 2 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | Binaries 2 | DerivedDataCache 3 | Intermediate 4 | Saved 5 | StarterContent 6 | .vscode 7 | .vs 8 | *.VC.db 9 | *.opensdf 10 | *.opendb 11 | *.sdf 12 | *.sln 13 | *.suo 14 | *.xcodeproj 15 | *.xcworkspace 16 | -------------------------------------------------------------------------------- /Config/DefaultEditor.ini: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vinceright3/ExtendingEditorCourseSourceCode/20b0bffcd01db51743adcec1171fa6a4798e196c/Config/DefaultEditor.ini -------------------------------------------------------------------------------- /Config/DefaultEngine.ini: -------------------------------------------------------------------------------- 1 | 2 | 3 | [/Script/EngineSettings.GameMapsSettings] 4 | GameDefaultMap=/Engine/Maps/Templates/OpenWorld 5 | EditorStartupMap=/Game/Map/ToolTestMap.ToolTestMap 6 | 7 | [/Script/HardwareTargeting.HardwareTargetingSettings] 8 | TargetedHardwareClass=Desktop 9 | AppliedTargetedHardwareClass=Desktop 10 | DefaultGraphicsPerformance=Maximum 11 | AppliedDefaultGraphicsPerformance=Maximum 12 | 13 | [/Script/WindowsTargetPlatform.WindowsTargetSettings] 14 | DefaultGraphicsRHI=DefaultGraphicsRHI_DX12 15 | 16 | [/Script/Engine.RendererSettings] 17 | r.GenerateMeshDistanceFields=True 18 | r.DynamicGlobalIlluminationMethod=1 19 | r.ReflectionMethod=1 20 | r.Shadow.Virtual.Enable=1 21 | 22 | [/Script/WorldPartitionEditor.WorldPartitionEditorSettings] 23 | CommandletClass=Class'/Script/UnrealEd.WorldPartitionConvertCommandlet' 24 | 25 | [/Script/Engine.Engine] 26 | +ActiveGameNameRedirects=(OldGameName="TP_Blank",NewGameName="/Script/ExtendEditor") 27 | +ActiveGameNameRedirects=(OldGameName="/Script/TP_Blank",NewGameName="/Script/ExtendEditor") 28 | +ActiveClassRedirects=(OldClassName="TP_BlankGameModeBase",NewClassName="ExtendEditorGameModeBase") 29 | 30 | [/Script/AndroidFileServerEditor.AndroidFileServerRuntimeSettings] 31 | bEnablePlugin=True 32 | bAllowNetworkConnection=True 33 | SecurityToken=D2F243744D33357DD1F0069893626319 34 | bIncludeInShipping=False 35 | bAllowExternalStartInShipping=False 36 | bCompileAFSProject=False 37 | bUseCompression=False 38 | bLogFiles=False 39 | bReportStats=False 40 | ConnectionType=USBOnly 41 | bUseManualIPAddress=False 42 | ManualIPAddress= 43 | 44 | -------------------------------------------------------------------------------- /Config/DefaultGame.ini: -------------------------------------------------------------------------------- 1 | 2 | [/Script/EngineSettings.GeneralProjectSettings] 3 | ProjectID=3C9234CE4ECCC2D82652AFACC335C029 4 | CopyrightNotice=Vince Petrelli All Rights Reserverd 5 | LicensingTerms=Educational purposes only 6 | 7 | -------------------------------------------------------------------------------- /Config/HoloLens/HoloLensEngine.ini: -------------------------------------------------------------------------------- 1 | 2 | 3 | [/Script/HoloLensPlatformEditor.HoloLensTargetSettings] 4 | bBuildForEmulation=False 5 | bBuildForDevice=True 6 | bUseNameForLogo=True 7 | bBuildForRetailWindowsStore=False 8 | bAutoIncrementVersion=False 9 | bShouldCreateAppInstaller=False 10 | AppInstallerInstallationURL= 11 | HoursBetweenUpdateChecks=0 12 | bEnablePIXProfiling=False 13 | TileBackgroundColor=(B=64,G=0,R=0,A=255) 14 | SplashScreenBackgroundColor=(B=64,G=0,R=0,A=255) 15 | +PerCultureResources=(CultureId="",Strings=(PackageDisplayName="",PublisherDisplayName="",PackageDescription="",ApplicationDisplayName="",ApplicationDescription=""),Images=()) 16 | TargetDeviceFamily=Windows.Holographic 17 | MinimumPlatformVersion= 18 | MaximumPlatformVersionTested=10.0.18362.0 19 | MaxTrianglesPerCubicMeter=500.000000 20 | SpatialMeshingVolumeSize=20.000000 21 | CompilerVersion=Default 22 | Windows10SDKVersion=10.0.18362.0 23 | +CapabilityList=internetClientServer 24 | +CapabilityList=privateNetworkClientServer 25 | +Uap2CapabilityList=spatialPerception 26 | bSetDefaultCapabilities=False 27 | SpatializationPlugin= 28 | ReverbPlugin= 29 | OcclusionPlugin= 30 | SoundCueCookQualityIndex=-1 31 | 32 | -------------------------------------------------------------------------------- /Content/Blueprint/NewFolder1/BP_Used_1.uasset: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:28f89b1f7b3b3816facf2c96836c17f295b1cd255f9cb290af1999d3f2fee965 3 | size 26022 4 | -------------------------------------------------------------------------------- /Content/Blueprint/NewFolder1/BP_Used_2.uasset: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:adfe340f9d96e4df69147eb1b4dd68984393d6ebd75fb3e186357aedeeed7736 3 | size 26022 4 | -------------------------------------------------------------------------------- /Content/Map/ToolTestMap.umap: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:35dccca6f60f5f30267e230b0b7e756c702d5f32c428214fd0f9f4da6b48203c 3 | size 189867 4 | -------------------------------------------------------------------------------- /Content/Map/ToolTestMap_BuiltData.uasset: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vinceright3/ExtendingEditorCourseSourceCode/20b0bffcd01db51743adcec1171fa6a4798e196c/Content/Map/ToolTestMap_BuiltData.uasset -------------------------------------------------------------------------------- /Content/TestDeleting/BP_Used.uasset: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:427c409500ab8a094544d997dd8c7b834fa2c59198ba3656726558becdeac189 3 | size 26694 4 | -------------------------------------------------------------------------------- /Content/TestDeleting/NewBlueprint_6.uasset: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:94961696953c82ccb533ce330d34273f1808eb3057d60c308c81b889d1e026af 3 | size 22490 4 | -------------------------------------------------------------------------------- /Content/TestDeleting/NewBlueprint_7.uasset: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:3f3bd9742862d65be9edb7aca5aee8ff8f8c71e3f781937b7bd1b0dd51fc2745 3 | size 22490 4 | -------------------------------------------------------------------------------- /Content/TestDeleting/NewBlueprint_8.uasset: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:d02ebcfb78db3fd94fdf49796ef3ca82fb6a6c324e01e173c5668988babefef0 3 | size 22490 4 | -------------------------------------------------------------------------------- /Content/TestDeleting/NewBlueprint_9.uasset: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:f8db2b4594071f41e8497b4682771bf42fe72335e2523183c42b3372f9f653dd 3 | size 22490 4 | -------------------------------------------------------------------------------- /Content/TestDeleting/NewFolder1/NewBlueprint_7.uasset: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:6e814cbea69d594be815e48b7e30ea0284a5d5329d6fc4e2e35512b0f375967d 3 | size 20990 4 | -------------------------------------------------------------------------------- /Content/TestDeleting/NewFolder1/NewBlueprint_8.uasset: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:9d639445126dc0d804da581284fdffcdf77d665b420b1fa4a07c66c0ccd31e3a 3 | size 20990 4 | -------------------------------------------------------------------------------- /Content/TestDeleting/NewFolder2/NewBlueprint_8.uasset: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:4e968f0750188b6651f59f5b821488f84b6541097b98a3fb7ea7d866db3d50f2 3 | size 20990 4 | -------------------------------------------------------------------------------- /Content/TestDeleting/NewFolder2/NewBlueprint_9.uasset: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:b76bbcc4a1f234c9c27454824ffab99896d8748e6f5e7a30735e3d610a0c3df7 3 | size 20990 4 | -------------------------------------------------------------------------------- /Content/TestTextures/MI_.uasset: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:a9a037d860be68b7b81ef57bc39825fabece0dd8f16a5f793c69a23da800b9e9 3 | size 15986 4 | -------------------------------------------------------------------------------- /Content/TestTextures/MI_metal_grate_rusty_diff_2k.uasset: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:5449b45bc5945ccc02092b29fff558d9cce69b818476030cb60876e3dfec57dd 3 | size 12790 4 | -------------------------------------------------------------------------------- /Content/TestTextures/M_castle_brick_02_red_diff_2k.uasset: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:4bbf0cb74029df9c6ab2938f8d58c26c5709fef12a2394740a5c9b641e759b4d 3 | size 17011 4 | -------------------------------------------------------------------------------- /Content/TestTextures/M_metal_grate_rusty_diff_2k.uasset: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:ec707e3238a02ffa9e28d84aee5886e49609b02578558460a9db262f58992caa 3 | size 13673 4 | -------------------------------------------------------------------------------- /Content/TestTextures/NewBlueprint.uasset: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:5b0b7fe91d17f471d6c6de59e8962fcc909aed5d5870bdc29449ba124bc18f48 3 | size 20841 4 | -------------------------------------------------------------------------------- /Content/TestTextures/castle_brick_02_red_ao_2k.uasset: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:c3c62415f7da72d2e6ca5d699d540ce0c351daa403bf4234f03bc525103b9982 3 | size 2054511 4 | -------------------------------------------------------------------------------- /Content/TestTextures/castle_brick_02_red_arm_2k.uasset: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:6151724837a070e637e0d8bdb4319d79700ad8959f9c26cd0639bf83c08f2944 3 | size 894123 4 | -------------------------------------------------------------------------------- /Content/TestTextures/castle_brick_02_red_diff_2k.uasset: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:71a78c87af05cd98e9a66b379a50bc3a09d65898140bda149fdfc3845c6b84f0 3 | size 2714223 4 | -------------------------------------------------------------------------------- /Content/TestTextures/castle_brick_02_red_nor_gl_2k.uasset: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:5ed00de8cd20d543739c9f6b534c4303c0acda3ed63ab11315dc17574df31333 3 | size 4297141 4 | -------------------------------------------------------------------------------- /Content/TestTextures/castle_brick_02_red_rough_2k.uasset: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:9ea857ce00cddabd32f5572dd5d9c6933a42cbf3c9ef74ff3ac7eceb7142c92a 3 | size 906391 4 | -------------------------------------------------------------------------------- /Content/TestTextures/metal_grate_rusty_ao_2k.uasset: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:1f8a7029c675c6041c1de5906148e1ef65797625d1327812cccbbe588e65f4ba 3 | size 6078243 4 | -------------------------------------------------------------------------------- /Content/TestTextures/metal_grate_rusty_arm_2k.uasset: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:1893ebf16ddc4c3af8541f54e95f58b2ff150fe204b4a3f0687e047be34498cd 3 | size 23872355 4 | -------------------------------------------------------------------------------- /Content/TestTextures/metal_grate_rusty_diff_2k.uasset: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:38da616ee66efddc78fb08bbc0dbf8073eee7b75b026cdf6b97dc9a6754d813f 3 | size 3846138 4 | -------------------------------------------------------------------------------- /Content/TestTextures/metal_grate_rusty_metal_2k.uasset: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:103806646186652554c528562190221b1dba9509f95176a53aa322b5162ea4ca 3 | size 14222574 4 | -------------------------------------------------------------------------------- /Content/TestTextures/metal_grate_rusty_nor_gl_2k.uasset: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:370d472e369018983497122182b844d24d47d9aedf56e6d9a968994d1851cd11 3 | size 22529709 4 | -------------------------------------------------------------------------------- /Content/TestTextures/metal_grate_rusty_rough_2k.uasset: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:35211fd7cede7f778538c593612a8004a54ad3581ff854e05e5a46f0fd2dd62a 3 | size 15499312 4 | -------------------------------------------------------------------------------- /ExtendEditor.uproject: -------------------------------------------------------------------------------- 1 | { 2 | "FileVersion": 3, 3 | "EngineAssociation": "5.0", 4 | "Category": "", 5 | "Description": "", 6 | "Modules": [ 7 | { 8 | "Name": "ExtendEditor", 9 | "Type": "Runtime", 10 | "LoadingPhase": "Default" 11 | } 12 | ], 13 | "Plugins": [ 14 | { 15 | "Name": "ModelingToolsEditorMode", 16 | "Enabled": true, 17 | "TargetAllowList": [ 18 | "Editor" 19 | ] 20 | } 21 | ] 22 | } -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | 2 | All licenses in this repository are copyrighted by Vince Petrelli. 3 | 4 | All code should only be used for informational purposes 5 | 6 | ------------------------------------------------------------------------------ 7 | 8 | Informational Purposes Only 9 | 10 | Vince Petrelli is the author of the work and reserves all rights to the work worldwide under 11 | copyright law, including all related and neighboring rights, 12 | to the extent allowed by law. 13 | 14 | The code under this repo can only be used for informational purposes and not for commercial use of any kind. 15 | 16 | Other Information: 17 | 18 | * Whoever wants to use the code for commercial purposes must contact the author Vince Petrelli for permission to use 19 | 20 | * When citing the work, you should imply endorsement 21 | by the author Vince Petrelli. 22 | 23 | -------------------------------------------------------------------------------- /Plugins/SuperManager/Content/WBP_QuickActorActions.uasset: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vinceright3/ExtendingEditorCourseSourceCode/20b0bffcd01db51743adcec1171fa6a4798e196c/Plugins/SuperManager/Content/WBP_QuickActorActions.uasset -------------------------------------------------------------------------------- /Plugins/SuperManager/Content/WBP_QuickMaterialCreation.uasset: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vinceright3/ExtendingEditorCourseSourceCode/20b0bffcd01db51743adcec1171fa6a4798e196c/Plugins/SuperManager/Content/WBP_QuickMaterialCreation.uasset -------------------------------------------------------------------------------- /Plugins/SuperManager/Resources/AdvanceDeletion.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vinceright3/ExtendingEditorCourseSourceCode/20b0bffcd01db51743adcec1171fa6a4798e196c/Plugins/SuperManager/Resources/AdvanceDeletion.png -------------------------------------------------------------------------------- /Plugins/SuperManager/Resources/DeleteEmptyFolders.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vinceright3/ExtendingEditorCourseSourceCode/20b0bffcd01db51743adcec1171fa6a4798e196c/Plugins/SuperManager/Resources/DeleteEmptyFolders.png -------------------------------------------------------------------------------- /Plugins/SuperManager/Resources/DeleteUnusedAsset.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vinceright3/ExtendingEditorCourseSourceCode/20b0bffcd01db51743adcec1171fa6a4798e196c/Plugins/SuperManager/Resources/DeleteUnusedAsset.png -------------------------------------------------------------------------------- /Plugins/SuperManager/Resources/Icon128.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vinceright3/ExtendingEditorCourseSourceCode/20b0bffcd01db51743adcec1171fa6a4798e196c/Plugins/SuperManager/Resources/Icon128.png -------------------------------------------------------------------------------- /Plugins/SuperManager/Resources/SelectionLock.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vinceright3/ExtendingEditorCourseSourceCode/20b0bffcd01db51743adcec1171fa6a4798e196c/Plugins/SuperManager/Resources/SelectionLock.png -------------------------------------------------------------------------------- /Plugins/SuperManager/Resources/SelectionUnlock.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vinceright3/ExtendingEditorCourseSourceCode/20b0bffcd01db51743adcec1171fa6a4798e196c/Plugins/SuperManager/Resources/SelectionUnlock.png -------------------------------------------------------------------------------- /Plugins/SuperManager/Source/SuperManager/Private/ActorActions/QuickActorActionsWidget.cpp: -------------------------------------------------------------------------------- 1 | // Copyright Vince Petrelli. Published in 2022.All rights reserved. 2 | 3 | #include "ActorActions/QuickActorActionsWidget.h" 4 | #include "Subsystems/EditorActorSubsystem.h" 5 | #include "DebugHeader.h" 6 | 7 | void UQuickActorActionsWidget::SelectAllActorsWithSimilarName() 8 | { 9 | if(!GetEditorActorSubsystem()) return; 10 | 11 | TArray SelectedActors = EditorActorSubsystem->GetSelectedLevelActors(); 12 | uint32 SelectionCounter = 0; 13 | 14 | if(SelectedActors.Num()==0) 15 | { 16 | DebugHeader::ShowNotifyInfo(TEXT("No actor selected")); 17 | return; 18 | } 19 | 20 | if(SelectedActors.Num()>1) 21 | { 22 | DebugHeader::ShowNotifyInfo(TEXT("You can only select one actor")); 23 | return; 24 | } 25 | 26 | FString SelectedActorName = SelectedActors[0]->GetActorLabel(); 27 | const FString NameToSearch = SelectedActorName.LeftChop(4); 28 | 29 | TArray AllLeveActors = EditorActorSubsystem->GetAllLevelActors(); 30 | 31 | for(AActor* ActorInLevel:AllLeveActors) 32 | { 33 | if(!ActorInLevel) continue; 34 | 35 | if(ActorInLevel->GetActorLabel().Contains(NameToSearch,SearchCase)) 36 | { 37 | EditorActorSubsystem->SetActorSelectionState(ActorInLevel,true); 38 | SelectionCounter++; 39 | } 40 | } 41 | 42 | if(SelectionCounter>0) 43 | { 44 | DebugHeader::ShowNotifyInfo(TEXT("Successfully selected ") + 45 | FString::FromInt(SelectionCounter) + TEXT(" actors")); 46 | } 47 | else 48 | { 49 | DebugHeader::ShowNotifyInfo(TEXT("No actor with similar name found")); 50 | } 51 | } 52 | 53 | void UQuickActorActionsWidget::DuplicateActors() 54 | { 55 | if(!GetEditorActorSubsystem()) return; 56 | 57 | TArray SelectedActors = EditorActorSubsystem->GetSelectedLevelActors(); 58 | uint32 Counter = 0; 59 | 60 | if(SelectedActors.Num()==0) 61 | { 62 | DebugHeader::ShowNotifyInfo(TEXT("No actor selected")); 63 | return; 64 | } 65 | 66 | if(NumberOfDuplicates <=0 || OffsetDist == 0) 67 | { 68 | DebugHeader::ShowNotifyInfo(TEXT("Did not specify a number of duplications or an offset distance")); 69 | return; 70 | } 71 | 72 | for(AActor* SelectedActor:SelectedActors) 73 | { 74 | if(!SelectedActor) continue; 75 | 76 | for(int32 i = 0; iDuplicateActor(SelectedActor,SelectedActor->GetWorld()); 80 | 81 | if(!DuplicatedActor) continue; 82 | 83 | const float DuplicationOffsetDist = (i+1)*OffsetDist; 84 | 85 | switch(AxisForDuplication) 86 | { 87 | case E_DuplicationAxis::EDA_XAxis: 88 | 89 | DuplicatedActor->AddActorWorldOffset(FVector(DuplicationOffsetDist,0.f,0.f)); 90 | break; 91 | 92 | case E_DuplicationAxis::EDA_YAxis: 93 | 94 | DuplicatedActor->AddActorWorldOffset(FVector(0.f,DuplicationOffsetDist,0.f)); 95 | break; 96 | 97 | case E_DuplicationAxis::EDA_ZAxis: 98 | 99 | DuplicatedActor->AddActorWorldOffset(FVector(0.f,0.f,DuplicationOffsetDist)); 100 | break; 101 | 102 | case E_DuplicationAxis::EDA_MAX: 103 | break; 104 | 105 | default: 106 | break; 107 | } 108 | 109 | EditorActorSubsystem->SetActorSelectionState(DuplicatedActor,true); 110 | Counter++; 111 | } 112 | } 113 | 114 | if(Counter>0) 115 | { 116 | DebugHeader::ShowNotifyInfo(TEXT("Successfully duplicated ")+ 117 | FString::FromInt(Counter)+TEXT(" actors")); 118 | } 119 | } 120 | 121 | void UQuickActorActionsWidget::RandomizeActorTransform() 122 | { 123 | const bool bConditionNotSet = 124 | !RandomActorRotation.bRandomizeRotYaw && 125 | !RandomActorRotation.bRandomizeRotPitch && 126 | !RandomActorRotation.bRandomizeRotRoll && 127 | !bRandomizeScale && 128 | !bRandomizeOffset; 129 | 130 | if(bConditionNotSet) 131 | { 132 | DebugHeader::ShowNotifyInfo(TEXT("No variation condition specified")); 133 | return; 134 | } 135 | 136 | if(!GetEditorActorSubsystem()) return; 137 | 138 | TArray SelectedActors = EditorActorSubsystem->GetSelectedLevelActors(); 139 | uint32 Counter = 0; 140 | 141 | if(SelectedActors.Num()==0) 142 | { 143 | DebugHeader::ShowNotifyInfo(TEXT("No actor selected")); 144 | return; 145 | } 146 | 147 | for(AActor* SelectedActor:SelectedActors) 148 | { 149 | if(!SelectedActor) continue; 150 | 151 | if(RandomActorRotation.bRandomizeRotYaw) 152 | { 153 | const float RandomRotYawValue = FMath::RandRange(RandomActorRotation.RotYawMin,RandomActorRotation.RotYawMax); 154 | 155 | SelectedActor->AddActorWorldRotation(FRotator(0.f,RandomRotYawValue,0.f)); 156 | } 157 | 158 | if(RandomActorRotation.bRandomizeRotPitch) 159 | { 160 | const float RandomRotPitchValue = FMath::RandRange(RandomActorRotation.RotPitchMin,RandomActorRotation.RotPitchMax); 161 | 162 | SelectedActor->AddActorWorldRotation(FRotator(RandomRotPitchValue,0.f,0.f)); 163 | } 164 | 165 | if(RandomActorRotation.bRandomizeRotRoll) 166 | { 167 | const float RandomRotRollValue = FMath::RandRange(RandomActorRotation.RotRollMin,RandomActorRotation.RotRollMax); 168 | 169 | SelectedActor->AddActorWorldRotation(FRotator(0.f,0.f,RandomRotRollValue)); 170 | } 171 | 172 | if(bRandomizeScale) 173 | { 174 | SelectedActor->SetActorScale3D(FVector(FMath::RandRange(ScaleMin,ScaleMax))); 175 | } 176 | 177 | if(bRandomizeOffset) 178 | { 179 | const float RandomOffsetValue = FMath::RandRange(OffsetMin,OffsetMax); 180 | 181 | SelectedActor->AddActorWorldOffset(FVector(RandomOffsetValue,RandomOffsetValue,0.f)); 182 | } 183 | 184 | Counter++; 185 | } 186 | 187 | if(Counter>0) 188 | { 189 | DebugHeader::ShowNotifyInfo(TEXT("Successfully set ")+ 190 | FString::FromInt(Counter)+TEXT(" actors")); 191 | } 192 | 193 | } 194 | 195 | bool UQuickActorActionsWidget::GetEditorActorSubsystem() 196 | { 197 | if(!EditorActorSubsystem) 198 | { 199 | EditorActorSubsystem = GEditor->GetEditorSubsystem(); 200 | } 201 | 202 | return EditorActorSubsystem != nullptr; 203 | } -------------------------------------------------------------------------------- /Plugins/SuperManager/Source/SuperManager/Private/AssetActions/QuickAssetAction.cpp: -------------------------------------------------------------------------------- 1 | // Copyright Vince Petrelli. Published in 2022.All rights reserved. 2 | 3 | 4 | #include "AssetActions/QuickAssetAction.h" 5 | #include "DebugHeader.h" 6 | #include "EditorUtilityLibrary.h" 7 | #include "EditorAssetLibrary.h" 8 | #include "ObjectTools.h" 9 | #include "AssetRegistryModule.h" 10 | #include "AssetToolsModule.h" 11 | 12 | void UQuickAssetAction::DuplicateAssets(int32 NumOfDuplicates) 13 | { 14 | if(NumOfDuplicates<=0) 15 | { 16 | DebugHeader::ShowMsgDialog(EAppMsgType::Ok,TEXT("Please enter a VALID number")); 17 | return; 18 | } 19 | 20 | TArray SelectedAssetsData = UEditorUtilityLibrary::GetSelectedAssetData(); 21 | uint32 Counter = 0; 22 | 23 | for(const FAssetData& SelectedAssetData:SelectedAssetsData) 24 | { 25 | for(int32 i = 0; i0) 40 | { 41 | DebugHeader::ShowNotifyInfo(TEXT("Successfully duplicated " + FString::FromInt(Counter) + " files")); 42 | /*Print(TEXT("Successfully duplicated " + FString::FromInt(Counter) + " files"),FColor::Green);*/ 43 | } 44 | } 45 | 46 | void UQuickAssetAction::AddPrefixes() 47 | { 48 | TArraySelectedObjects = UEditorUtilityLibrary::GetSelectedAssets(); 49 | uint32 Counter = 0; 50 | 51 | for(UObject* SelectedObject:SelectedObjects) 52 | { 53 | if(!SelectedObject) continue; 54 | 55 | FString* PrefixFound = PrefixMap.Find(SelectedObject->GetClass()); 56 | 57 | if(!PrefixFound||PrefixFound->IsEmpty()) 58 | { 59 | DebugHeader::Print(TEXT("Failed to find prefix for class ") + SelectedObject->GetClass()->GetName(),FColor::Red); 60 | continue; 61 | } 62 | 63 | FString OldName = SelectedObject->GetName(); 64 | 65 | if(OldName.StartsWith(*PrefixFound)) 66 | { 67 | DebugHeader::Print(OldName + TEXT(" already has prefix added"),FColor::Red); 68 | continue; 69 | } 70 | 71 | if(SelectedObject->IsA()) 72 | { 73 | OldName.RemoveFromStart(TEXT("M_")); 74 | OldName.RemoveFromEnd(TEXT("_Inst")); 75 | } 76 | 77 | const FString NewNameWithPrefix = *PrefixFound + OldName; 78 | 79 | UEditorUtilityLibrary::RenameAsset(SelectedObject,NewNameWithPrefix); 80 | 81 | ++Counter; 82 | } 83 | 84 | if(Counter>0) 85 | { 86 | DebugHeader::ShowNotifyInfo(TEXT("Successfully renamed "+FString::FromInt(Counter)+" assets")); 87 | } 88 | } 89 | 90 | void UQuickAssetAction::RemoveUnusedAssets() 91 | { 92 | TArray SelectedAssetsData = UEditorUtilityLibrary::GetSelectedAssetData(); 93 | TArray UnusedAssetsData; 94 | 95 | FixUpRedirectors(); 96 | 97 | for(const FAssetData& SelectedAssetData:SelectedAssetsData) 98 | { 99 | TArray AssetRefrencers = 100 | UEditorAssetLibrary::FindPackageReferencersForAsset(SelectedAssetData.ObjectPath.ToString()); 101 | 102 | if(AssetRefrencers.Num()==0) 103 | { 104 | UnusedAssetsData.Add(SelectedAssetData); 105 | } 106 | } 107 | 108 | if(UnusedAssetsData.Num()==0) 109 | { 110 | DebugHeader::ShowMsgDialog(EAppMsgType::Ok,TEXT("No unused asset found among selected assets"),false); 111 | return; 112 | } 113 | 114 | const int32 NumOfAssetsDeleted = ObjectTools::DeleteAssets(UnusedAssetsData); 115 | 116 | if(NumOfAssetsDeleted == 0) return; 117 | 118 | DebugHeader::ShowNotifyInfo(TEXT("Successfully deleted " + FString::FromInt(NumOfAssetsDeleted) + TEXT(" unused assets"))); 119 | } 120 | 121 | void UQuickAssetAction::FixUpRedirectors() 122 | { 123 | TArray RedirectorsToFixArray; 124 | 125 | FAssetRegistryModule& AssetRegistryModule = 126 | FModuleManager::Get().LoadModuleChecked(TEXT("AssetRegistry")); 127 | 128 | FARFilter Filter; 129 | Filter.bRecursivePaths = true; 130 | Filter.PackagePaths.Emplace("/Game"); 131 | Filter.ClassNames.Emplace("ObjectRedirector"); 132 | 133 | TArray OutRedirectors; 134 | 135 | AssetRegistryModule.Get().GetAssets(Filter,OutRedirectors); 136 | 137 | for(const FAssetData& RedirectorData:OutRedirectors) 138 | { 139 | if(UObjectRedirector* RedirectorToFix = Cast(RedirectorData.GetAsset())) 140 | { 141 | RedirectorsToFixArray.Add(RedirectorToFix); 142 | } 143 | } 144 | 145 | FAssetToolsModule& AssetToolsModule = 146 | FModuleManager::LoadModuleChecked(TEXT("AssetTools")); 147 | 148 | AssetToolsModule.Get().FixupReferencers(RedirectorsToFixArray); 149 | } -------------------------------------------------------------------------------- /Plugins/SuperManager/Source/SuperManager/Private/AssetActions/QuickMaterialCreationWidget.cpp: -------------------------------------------------------------------------------- 1 | // Copyright Vince Petrelli. Published in 2022.All rights reserved. 2 | 3 | 4 | #include "AssetActions/QuickMaterialCreationWidget.h" 5 | #include "DebugHeader.h" 6 | #include "EditorUtilityLibrary.h" 7 | #include "EditorAssetLibrary.h" 8 | #include "AssetToolsModule.h" 9 | #include "Factories/MaterialFactoryNew.h" 10 | #include "Materials/MaterialInstanceConstant.h" 11 | #include "Factories/MaterialInstanceConstantFactoryNew.h" 12 | 13 | #pragma region QuickMaterialCreationCore 14 | 15 | void UQuickMaterialCreationWidget::CreateMaterialFromSelectedTextures() 16 | { 17 | if(bCustomMaterialName) 18 | { 19 | if(MaterialName.IsEmpty() || MaterialName.Equals(TEXT("M_"))) 20 | { 21 | DebugHeader::ShowMsgDialog(EAppMsgType::Ok,TEXT("Please enter a valid name")); 22 | return; 23 | } 24 | } 25 | 26 | TArray SelectedAssetsData = UEditorUtilityLibrary::GetSelectedAssetData(); 27 | TArray SelectedTexturesArray; 28 | FString SelectedTextureFolderPath; 29 | uint32 PinsConnectedCounter = 0; 30 | 31 | if(!ProcessSelectedData(SelectedAssetsData, SelectedTexturesArray, SelectedTextureFolderPath)) {MaterialName = TEXT("M_"); return;} 32 | 33 | if(CheckIsNameUsed(SelectedTextureFolderPath, MaterialName)) {MaterialName = TEXT("M_"); return;} 34 | 35 | UMaterial* CreatedMaterial = CreateMaterialAsset(MaterialName,SelectedTextureFolderPath); 36 | 37 | if(!CreatedMaterial) 38 | { 39 | DebugHeader::ShowMsgDialog(EAppMsgType::Ok,TEXT("Failed to create material")); 40 | return; 41 | } 42 | 43 | for(UTexture2D* SelectedTexture:SelectedTexturesArray) 44 | { 45 | if(!SelectedTexture) continue; 46 | 47 | switch(ChannelPackingType) 48 | { 49 | case E_ChannelPackingType::ECPT_NoChannelPacking: 50 | 51 | Default_CreateMaterialNodes(CreatedMaterial,SelectedTexture,PinsConnectedCounter); 52 | break; 53 | 54 | case E_ChannelPackingType::ECPT_ORM: 55 | 56 | ORM_CreateMaterialNodes(CreatedMaterial,SelectedTexture,PinsConnectedCounter); 57 | break; 58 | 59 | case E_ChannelPackingType::ECPT_MAX: 60 | break; 61 | 62 | default: 63 | break; 64 | } 65 | } 66 | 67 | if(PinsConnectedCounter>0) 68 | { 69 | DebugHeader::ShowNotifyInfo(TEXT("Successfully connected ") 70 | + FString::FromInt(PinsConnectedCounter) + (TEXT(" pins"))); 71 | } 72 | 73 | if(bCreateMaterialInstance) 74 | { 75 | CreateMaterialInstanceAsset(CreatedMaterial,MaterialName,SelectedTextureFolderPath); 76 | } 77 | 78 | MaterialName = TEXT("M_"); 79 | } 80 | 81 | //Process the selected data, will filter out textures,and return false if non-texture selected 82 | bool UQuickMaterialCreationWidget::ProcessSelectedData(const TArray& SelectedDataToProccess, 83 | TArray& OutSelectedTexturesArray, FString& OutSelectedTexturePackagePath) 84 | { 85 | if(SelectedDataToProccess.Num()==0) 86 | { 87 | DebugHeader::ShowMsgDialog(EAppMsgType::Ok,TEXT("No texture selected")); 88 | return false; 89 | } 90 | 91 | bool bMaterialNameSet = false; 92 | 93 | for(const FAssetData& SelectedData:SelectedDataToProccess) 94 | { 95 | UObject* SelectedAsset = SelectedData.GetAsset(); 96 | 97 | if(!SelectedAsset) continue; 98 | 99 | UTexture2D* SelectedTexture = Cast(SelectedAsset); 100 | 101 | if(!SelectedTexture) 102 | { 103 | DebugHeader::ShowMsgDialog(EAppMsgType::Ok,TEXT("Please select only textures\n") + 104 | SelectedAsset->GetName() + TEXT(" is not a texture")); 105 | 106 | return false; 107 | } 108 | 109 | OutSelectedTexturesArray.Add(SelectedTexture); 110 | 111 | if(OutSelectedTexturePackagePath.IsEmpty()) 112 | { 113 | OutSelectedTexturePackagePath = SelectedData.PackagePath.ToString(); 114 | } 115 | 116 | if(!bCustomMaterialName && !bMaterialNameSet) 117 | { 118 | MaterialName = SelectedAsset->GetName(); 119 | MaterialName.RemoveFromStart(TEXT("T_")); 120 | MaterialName.InsertAt(0,TEXT("M_")); 121 | 122 | bMaterialNameSet = true; 123 | } 124 | } 125 | 126 | return true; 127 | } 128 | 129 | //Will return true if the material name is used by asset under the specified folder 130 | bool UQuickMaterialCreationWidget::CheckIsNameUsed(const FString& FolderPathToCheck, 131 | const FString& MaterialNameToCheck) 132 | { 133 | TArray ExistingAssetsPaths = UEditorAssetLibrary::ListAssets(FolderPathToCheck,false); 134 | 135 | for(const FString& ExistingAssetPath:ExistingAssetsPaths) 136 | { 137 | const FString ExistingAssetName = FPaths::GetBaseFilename(ExistingAssetPath); 138 | 139 | if(ExistingAssetName.Equals(MaterialNameToCheck)) 140 | { 141 | DebugHeader::ShowMsgDialog(EAppMsgType::Ok,MaterialNameToCheck + 142 | TEXT(" is already used by asset")); 143 | 144 | return true; 145 | } 146 | } 147 | 148 | return false; 149 | 150 | } 151 | 152 | UMaterial * UQuickMaterialCreationWidget::CreateMaterialAsset(const FString & NameOfTheMaterial, const FString & PathToPutMaterial) 153 | { 154 | FAssetToolsModule& AssetToolsModule = FModuleManager::LoadModuleChecked(TEXT("AssetTools")); 155 | 156 | UMaterialFactoryNew* MaterialFactory = NewObject(); 157 | 158 | UObject* CreatedObject = AssetToolsModule.Get().CreateAsset(NameOfTheMaterial,PathToPutMaterial, 159 | UMaterial::StaticClass(),MaterialFactory); 160 | 161 | return Cast(CreatedObject); 162 | } 163 | 164 | void UQuickMaterialCreationWidget::Default_CreateMaterialNodes(UMaterial* CreatedMaterial, 165 | UTexture2D * SelectedTexture, uint32 & PinsConnectedCounter) 166 | { 167 | UMaterialExpressionTextureSample* TextureSampleNode = 168 | NewObject(CreatedMaterial); 169 | 170 | if(!TextureSampleNode) return; 171 | 172 | if(!CreatedMaterial->BaseColor.IsConnected()) 173 | { 174 | if(TryConnectBaseColor(TextureSampleNode,SelectedTexture,CreatedMaterial)) 175 | { 176 | PinsConnectedCounter++; 177 | return; 178 | } 179 | } 180 | 181 | if(!CreatedMaterial->Metallic.IsConnected()) 182 | { 183 | if(TryConnectMetalic(TextureSampleNode, SelectedTexture, CreatedMaterial)) 184 | { 185 | PinsConnectedCounter++; 186 | return; 187 | } 188 | } 189 | 190 | if(!CreatedMaterial->Roughness.IsConnected()) 191 | { 192 | if(TryConnectRoughness(TextureSampleNode, SelectedTexture, CreatedMaterial)) 193 | { 194 | PinsConnectedCounter++; 195 | return; 196 | } 197 | } 198 | 199 | if(!CreatedMaterial->Normal.IsConnected()) 200 | { 201 | if(TryConnectNormal(TextureSampleNode, SelectedTexture, CreatedMaterial)) 202 | { 203 | PinsConnectedCounter++; 204 | return; 205 | } 206 | } 207 | 208 | if(!CreatedMaterial->AmbientOcclusion.IsConnected()) 209 | { 210 | if(TryConnectAO(TextureSampleNode, SelectedTexture, CreatedMaterial)) 211 | { 212 | PinsConnectedCounter++; 213 | return; 214 | } 215 | } 216 | 217 | DebugHeader::Print(TEXT("Failed to connect the texture: ") + SelectedTexture->GetName(),FColor::Red); 218 | } 219 | 220 | void UQuickMaterialCreationWidget::ORM_CreateMaterialNodes(UMaterial* CreatedMaterial, 221 | UTexture2D * SelectedTexture, uint32 & PinsConnectedCounter) 222 | { 223 | UMaterialExpressionTextureSample* TextureSampleNode = 224 | NewObject(CreatedMaterial); 225 | 226 | if(!TextureSampleNode) return; 227 | 228 | if(!CreatedMaterial->BaseColor.IsConnected()) 229 | { 230 | if(TryConnectBaseColor(TextureSampleNode,SelectedTexture,CreatedMaterial)) 231 | { 232 | PinsConnectedCounter++; 233 | return; 234 | } 235 | } 236 | 237 | if(!CreatedMaterial->Normal.IsConnected()) 238 | { 239 | if(TryConnectNormal(TextureSampleNode, SelectedTexture, CreatedMaterial)) 240 | { 241 | PinsConnectedCounter++; 242 | return; 243 | } 244 | } 245 | 246 | if(!CreatedMaterial->Roughness.IsConnected()) 247 | { 248 | if(TryConnectORM(TextureSampleNode, SelectedTexture, CreatedMaterial)) 249 | { 250 | PinsConnectedCounter+=3; 251 | return; 252 | } 253 | } 254 | } 255 | 256 | #pragma endregion 257 | 258 | #pragma region CreateMaterialNodesConnectPins 259 | 260 | bool UQuickMaterialCreationWidget::TryConnectBaseColor(UMaterialExpressionTextureSample * TextureSampleNode, 261 | UTexture2D * SelectedTexture, UMaterial * CreatedMaterial) 262 | { 263 | for(const FString& BaseColorName:BaseColorArray) 264 | { 265 | if(SelectedTexture->GetName().Contains(BaseColorName)) 266 | { 267 | //Connect pins to base color socket here 268 | TextureSampleNode->Texture = SelectedTexture; 269 | 270 | CreatedMaterial->Expressions.Add(TextureSampleNode); 271 | CreatedMaterial->BaseColor.Expression = TextureSampleNode; 272 | CreatedMaterial->PostEditChange(); 273 | 274 | TextureSampleNode->MaterialExpressionEditorX -=600; 275 | 276 | return true; 277 | } 278 | } 279 | 280 | return false; 281 | } 282 | 283 | bool UQuickMaterialCreationWidget::TryConnectMetalic(UMaterialExpressionTextureSample * TextureSampleNode, 284 | UTexture2D * SelectedTexture, UMaterial * CreatedMaterial) 285 | { 286 | for(const FString& MetalicName:MetallicArray) 287 | { 288 | if(SelectedTexture->GetName().Contains(MetalicName)) 289 | { 290 | SelectedTexture->CompressionSettings = TextureCompressionSettings::TC_Default; 291 | SelectedTexture->SRGB = false; 292 | SelectedTexture->PostEditChange(); 293 | 294 | TextureSampleNode->Texture = SelectedTexture; 295 | TextureSampleNode->SamplerType = EMaterialSamplerType::SAMPLERTYPE_LinearColor; 296 | 297 | CreatedMaterial->Expressions.Add(TextureSampleNode); 298 | CreatedMaterial->Metallic.Expression = TextureSampleNode; 299 | CreatedMaterial->PostEditChange(); 300 | 301 | TextureSampleNode->MaterialExpressionEditorX -=600; 302 | TextureSampleNode->MaterialExpressionEditorY +=240; 303 | 304 | return true; 305 | } 306 | } 307 | 308 | return false; 309 | } 310 | 311 | bool UQuickMaterialCreationWidget::TryConnectRoughness(UMaterialExpressionTextureSample * TextureSampleNode, UTexture2D * SelectedTexture, UMaterial * CreatedMaterial) 312 | { 313 | for(const FString& RoughnessName:RoughnessArray) 314 | { 315 | if(SelectedTexture->GetName().Contains(RoughnessName)) 316 | { 317 | SelectedTexture->CompressionSettings = TextureCompressionSettings::TC_Default; 318 | SelectedTexture->SRGB = false; 319 | SelectedTexture->PostEditChange(); 320 | 321 | TextureSampleNode->Texture = SelectedTexture; 322 | TextureSampleNode->SamplerType = EMaterialSamplerType::SAMPLERTYPE_LinearColor; 323 | 324 | CreatedMaterial->Expressions.Add(TextureSampleNode); 325 | CreatedMaterial->Roughness.Expression = TextureSampleNode; 326 | CreatedMaterial->PostEditChange(); 327 | 328 | TextureSampleNode->MaterialExpressionEditorX -=600; 329 | TextureSampleNode->MaterialExpressionEditorY +=480; 330 | 331 | return true; 332 | } 333 | } 334 | 335 | return false; 336 | } 337 | 338 | bool UQuickMaterialCreationWidget::TryConnectNormal(UMaterialExpressionTextureSample * TextureSampleNode, UTexture2D * SelectedTexture, UMaterial * CreatedMaterial) 339 | { 340 | for(const FString& NormalName:NormalArray) 341 | { 342 | if(SelectedTexture->GetName().Contains(NormalName)) 343 | { 344 | TextureSampleNode->Texture = SelectedTexture; 345 | TextureSampleNode->SamplerType = EMaterialSamplerType::SAMPLERTYPE_Normal; 346 | 347 | CreatedMaterial->Expressions.Add(TextureSampleNode); 348 | CreatedMaterial->Normal.Expression = TextureSampleNode; 349 | CreatedMaterial->PostEditChange(); 350 | 351 | TextureSampleNode->MaterialExpressionEditorX -= 600; 352 | TextureSampleNode->MaterialExpressionEditorY += 720; 353 | 354 | return true; 355 | } 356 | } 357 | 358 | return false; 359 | } 360 | 361 | bool UQuickMaterialCreationWidget::TryConnectAO(UMaterialExpressionTextureSample * TextureSampleNode, UTexture2D * SelectedTexture, UMaterial * CreatedMaterial) 362 | { 363 | for(const FString& AOName:AmbientOcclusionArray) 364 | { 365 | if(SelectedTexture->GetName().Contains(AOName)) 366 | { 367 | SelectedTexture->CompressionSettings = TextureCompressionSettings::TC_Default; 368 | SelectedTexture->SRGB = false; 369 | SelectedTexture->PostEditChange(); 370 | 371 | TextureSampleNode->Texture = SelectedTexture; 372 | TextureSampleNode->SamplerType = EMaterialSamplerType::SAMPLERTYPE_LinearColor; 373 | 374 | CreatedMaterial->Expressions.Add(TextureSampleNode); 375 | CreatedMaterial->AmbientOcclusion.Expression = TextureSampleNode; 376 | CreatedMaterial->PostEditChange(); 377 | 378 | 379 | TextureSampleNode->MaterialExpressionEditorX -= 600; 380 | TextureSampleNode->MaterialExpressionEditorY += 960; 381 | 382 | return true; 383 | } 384 | } 385 | 386 | return false; 387 | } 388 | 389 | bool UQuickMaterialCreationWidget::TryConnectORM(UMaterialExpressionTextureSample * TextureSampleNode, UTexture2D * SelectedTexture, UMaterial * CreatedMaterial) 390 | { 391 | for(const FString& ORM_Name:ORMArray) 392 | { 393 | if(SelectedTexture->GetName().Contains(ORM_Name)) 394 | { 395 | SelectedTexture->CompressionSettings = TextureCompressionSettings::TC_Masks; 396 | SelectedTexture->SRGB = false; 397 | SelectedTexture->PostEditChange(); 398 | 399 | TextureSampleNode->Texture = SelectedTexture; 400 | TextureSampleNode->SamplerType = EMaterialSamplerType::SAMPLERTYPE_Masks; 401 | 402 | CreatedMaterial->Expressions.Add(TextureSampleNode); 403 | CreatedMaterial->AmbientOcclusion.Connect(1,TextureSampleNode); 404 | CreatedMaterial->Roughness.Connect(2,TextureSampleNode); 405 | CreatedMaterial->Metallic.Connect(3,TextureSampleNode); 406 | CreatedMaterial->PostEditChange(); 407 | 408 | TextureSampleNode->MaterialExpressionEditorX -= 600; 409 | TextureSampleNode->MaterialExpressionEditorY += 960; 410 | 411 | return true; 412 | } 413 | } 414 | return false; 415 | } 416 | 417 | #pragma endregion 418 | 419 | UMaterialInstanceConstant* UQuickMaterialCreationWidget::CreateMaterialInstanceAsset(UMaterial * CreatedMaterial, 420 | FString NameOfMaterialInstance, const FString & PathToPutMI) 421 | { 422 | NameOfMaterialInstance.RemoveFromStart(TEXT("M_")); 423 | NameOfMaterialInstance.InsertAt(0,TEXT("MI_")); 424 | 425 | UMaterialInstanceConstantFactoryNew* MIFactoryNew = NewObject(); 426 | 427 | FAssetToolsModule& AssetToolsModule = FModuleManager::LoadModuleChecked(TEXT("AssetTools")); 428 | 429 | UObject* CreatedObject = AssetToolsModule.Get().CreateAsset(NameOfMaterialInstance,PathToPutMI, 430 | UMaterialInstanceConstant::StaticClass(),MIFactoryNew); 431 | 432 | if(UMaterialInstanceConstant* CreatedMI = Cast(CreatedObject)) 433 | { 434 | CreatedMI->SetParentEditorOnly(CreatedMaterial); 435 | 436 | CreatedMI->PostEditChange(); 437 | CreatedMaterial->PostEditChange(); 438 | 439 | return CreatedMI; 440 | } 441 | 442 | return nullptr; 443 | } 444 | -------------------------------------------------------------------------------- /Plugins/SuperManager/Source/SuperManager/Private/CustomOutlinerColumn/OutlinerSelectionLockColumn.cpp: -------------------------------------------------------------------------------- 1 | // Copyright Vince Petrelli. Published in 2022.All rights reserved. 2 | 3 | 4 | #include "CustomOutlinerColumn/OutlinerSelectionLockColumn.h" 5 | #include "CustomStyle/SuperManagerStyle.h" 6 | #include "ActorTreeItem.h" 7 | #include "SuperManager.h" 8 | 9 | SHeaderRow::FColumn::FArguments FOutlinerSelectionLockColumn::ConstructHeaderRowColumn() 10 | { 11 | SHeaderRow::FColumn::FArguments ConstructedHeaderRow = 12 | SHeaderRow::Column(GetColumnID()) 13 | .FixedWidth(24.f) 14 | .HAlignHeader(HAlign_Center) 15 | .VAlignHeader(VAlign_Center) 16 | .HAlignCell(HAlign_Center) 17 | .VAlignCell(VAlign_Center) 18 | .DefaultTooltip(FText::FromString(TEXT("Actor Selection Lock - Press icon to lock actor selection"))) 19 | [ 20 | SNew(SImage) 21 | .ColorAndOpacity(FSlateColor::UseForeground()) 22 | .Image(FSuperManagerStyle::GetCreatedSlateStyleSet()->GetBrush(FName("LevelEditor.LockSelection"))) 23 | ]; 24 | 25 | return ConstructedHeaderRow; 26 | } 27 | 28 | const TSharedRef FOutlinerSelectionLockColumn::ConstructRowWidget(FSceneOutlinerTreeItemRef TreeItem, 29 | const STableRow& Row) 30 | { 31 | FActorTreeItem* ActorTreeItem = TreeItem->CastTo(); 32 | 33 | if(!ActorTreeItem || !ActorTreeItem->IsValid()) return SNullWidget::NullWidget; 34 | 35 | FSuperManagerModule& SuperManagerModule = 36 | FModuleManager::LoadModuleChecked(TEXT("SuperManager")); 37 | 38 | const bool bIsActorSelectionLocked = 39 | SuperManagerModule.CheckIsActorSelectionLocked(ActorTreeItem->Actor.Get()); 40 | 41 | const FCheckBoxStyle& ToggleButtonStyle = FSuperManagerStyle::GetCreatedSlateStyleSet()-> 42 | GetWidgetStyle(FName("SceneOutliner.SelectionLock")); 43 | 44 | TSharedRef ConstructedRowWidgetCheckBox = 45 | SNew(SCheckBox) 46 | .Visibility(EVisibility::Visible) 47 | .Type(ESlateCheckBoxType::ToggleButton) 48 | .Style(&ToggleButtonStyle) 49 | .HAlign(HAlign_Center) 50 | .IsChecked(bIsActorSelectionLocked? ECheckBoxState::Checked : ECheckBoxState::Unchecked) 51 | .OnCheckStateChanged(this,&FOutlinerSelectionLockColumn::OnRowWdigetCheckStateChanged,ActorTreeItem->Actor); 52 | 53 | return ConstructedRowWidgetCheckBox; 54 | } 55 | 56 | void FOutlinerSelectionLockColumn::OnRowWdigetCheckStateChanged(ECheckBoxState NewState, 57 | TWeakObjectPtr CorrespondingActor) 58 | { 59 | FSuperManagerModule& SuperManagerModule = 60 | FModuleManager::LoadModuleChecked(TEXT("SuperManager")); 61 | 62 | switch(NewState) 63 | { 64 | case ECheckBoxState::Unchecked: 65 | 66 | SuperManagerModule.ProcessLockingForOutliner(CorrespondingActor.Get(),false); 67 | break; 68 | 69 | case ECheckBoxState::Checked: 70 | 71 | SuperManagerModule.ProcessLockingForOutliner(CorrespondingActor.Get(),true); 72 | break; 73 | 74 | case ECheckBoxState::Undetermined: 75 | break; 76 | default: 77 | break; 78 | } 79 | } 80 | 81 | -------------------------------------------------------------------------------- /Plugins/SuperManager/Source/SuperManager/Private/CustomStyle/SuperManagerStyle.cpp: -------------------------------------------------------------------------------- 1 | // Copyright Vince Petrelli. Published in 2022.All rights reserved. 2 | 3 | 4 | #include "CustomStyle/SuperManagerStyle.h" 5 | #include "Interfaces/IPluginManager.h" 6 | #include "Styling/SlateStyleRegistry.h" 7 | #include "Styling/StyleColors.h" 8 | 9 | FName FSuperManagerStyle::StyleSetName = FName("SuperManagerStyle"); 10 | TSharedPtr FSuperManagerStyle::CreatedSlateStyleSet = nullptr; 11 | 12 | void FSuperManagerStyle::InitializeIcons() 13 | { 14 | if(!CreatedSlateStyleSet.IsValid()) 15 | { 16 | CreatedSlateStyleSet = CreateSlateStyleSet(); 17 | FSlateStyleRegistry::RegisterSlateStyle(*CreatedSlateStyleSet); 18 | } 19 | 20 | } 21 | 22 | TSharedRef FSuperManagerStyle::CreateSlateStyleSet() 23 | { 24 | TSharedRef CustomStyleSet = MakeShareable(new FSlateStyleSet(StyleSetName)); 25 | 26 | const FString IconDirectory = 27 | IPluginManager::Get().FindPlugin(TEXT("SuperManager"))->GetBaseDir() /"Resources"; 28 | 29 | CustomStyleSet->SetContentRoot(IconDirectory); 30 | 31 | const FVector2D Icon16x16 (16.f,16.f); 32 | 33 | CustomStyleSet->Set("ContentBrowser.DeleteUnusedAssets", 34 | new FSlateImageBrush(IconDirectory/"DeleteUnusedAsset.png",Icon16x16)); 35 | 36 | CustomStyleSet->Set("ContentBrowser.DeleteEmptyFolders", 37 | new FSlateImageBrush(IconDirectory/"DeleteEmptyFolders.png",Icon16x16)); 38 | 39 | CustomStyleSet->Set("ContentBrowser.AdvanceDeletion", 40 | new FSlateImageBrush(IconDirectory/"AdvanceDeletion.png",Icon16x16)); 41 | 42 | CustomStyleSet->Set("LevelEditor.LockSelection", 43 | new FSlateImageBrush(IconDirectory/"SelectionLock.png",Icon16x16)); 44 | 45 | CustomStyleSet->Set("LevelEditor.UnlockSelection", 46 | new FSlateImageBrush(IconDirectory/"SelectionUnlock.png",Icon16x16)); 47 | 48 | const FCheckBoxStyle SelectionLockToggleButtonStyle = FCheckBoxStyle() 49 | .SetCheckBoxType(ESlateCheckBoxType::ToggleButton) 50 | .SetPadding(FMargin(10.f)) 51 | 52 | //Uncheck images 53 | .SetUncheckedImage(FSlateImageBrush(IconDirectory/"SelectionLock.png",Icon16x16,FStyleColors::White25)) 54 | .SetUncheckedHoveredImage(FSlateImageBrush(IconDirectory/"SelectionLock.png",Icon16x16,FStyleColors::AccentBlue)) 55 | .SetUncheckedPressedImage(FSlateImageBrush(IconDirectory/"SelectionLock.png",Icon16x16,FStyleColors::Foreground)) 56 | 57 | //Checked images 58 | .SetCheckedImage(FSlateImageBrush(IconDirectory/"SelectionLock.png",Icon16x16,FStyleColors::Foreground)) 59 | .SetCheckedHoveredImage(FSlateImageBrush(IconDirectory/"SelectionLock.png",Icon16x16,FStyleColors::AccentBlack)) 60 | .SetCheckedPressedImage(FSlateImageBrush(IconDirectory/"SelectionLock.png",Icon16x16,FStyleColors::AccentGray)); 61 | 62 | CustomStyleSet->Set("SceneOutliner.SelectionLock",SelectionLockToggleButtonStyle); 63 | 64 | return CustomStyleSet; 65 | } 66 | 67 | void FSuperManagerStyle::ShutDown() 68 | { 69 | if(CreatedSlateStyleSet.IsValid()) 70 | { 71 | FSlateStyleRegistry::UnRegisterSlateStyle(*CreatedSlateStyleSet); 72 | CreatedSlateStyleSet.Reset(); 73 | } 74 | } 75 | -------------------------------------------------------------------------------- /Plugins/SuperManager/Source/SuperManager/Private/CustomUICommands/SuperManagerUICommands.cpp: -------------------------------------------------------------------------------- 1 | // Copyright Vince Petrelli. Published in 2022.All rights reserved. 2 | 3 | 4 | #include "CustomUICommands/SuperManagerUICommands.h" 5 | 6 | #define LOCTEXT_NAMESPACE "FSuperManagerModule" 7 | 8 | void FSuperManagerUICommands::RegisterCommands() 9 | { 10 | UI_COMMAND( 11 | LockActorSelection, 12 | "Lock Actor Selection", 13 | "Lock actor selection in level, once triggered, actor can no longer be selected", 14 | EUserInterfaceActionType::Button, 15 | FInputChord(EKeys::W,EModifierKey::Alt) 16 | ); 17 | 18 | UI_COMMAND( 19 | UnlockActorSelection, 20 | "Unlock Actor Selection", 21 | "Remove selection lock on all actors", 22 | EUserInterfaceActionType::Button, 23 | FInputChord(EKeys::W,EModifierKey::Alt | EModifierKey::Shift) 24 | ); 25 | } 26 | 27 | #undef LOCTEXT_NAMESPACE 28 | -------------------------------------------------------------------------------- /Plugins/SuperManager/Source/SuperManager/Private/SlateWidgets/AdvanceDeletionWidget.cpp: -------------------------------------------------------------------------------- 1 | // Copyright Vince Petrelli. Published in 2022.All rights reserved. 2 | 3 | #include "SlateWidgets/AdvanceDeletionWidget.h" 4 | #include "SlateBasics.h" 5 | #include "DebugHeader.h" 6 | #include "SuperManager.h" 7 | 8 | #define ListAll TEXT("List All Available Assets") 9 | #define ListUnused TEXT("List Unused Assets") 10 | #define ListSameName TEXT("List Assets With Same Name ") 11 | 12 | void SAdvanceDeletionTab::Construct(const FArguments & InArgs) 13 | { 14 | bCanSupportFocus = true; 15 | 16 | StoredAssetsData = InArgs._AssetsDataToStore; 17 | DisplayedAssetsData = StoredAssetsData; 18 | 19 | CheckBoxesArray.Empty(); 20 | AssetsDataToDeleteArray.Empty(); 21 | ComboBoxSourceItems.Empty(); 22 | 23 | ComboBoxSourceItems.Add(MakeShared(ListAll)); 24 | ComboBoxSourceItems.Add(MakeShared(ListUnused)); 25 | ComboBoxSourceItems.Add(MakeShared(ListSameName)); 26 | 27 | FSlateFontInfo TitleTextFont = GetEmboseedTextFont(); 28 | TitleTextFont.Size = 30; 29 | 30 | ChildSlot 31 | [ //Main vertical box 32 | SNew(SVerticalBox) 33 | 34 | //First vertical slot for title text 35 | +SVerticalBox::Slot() 36 | .AutoHeight() 37 | [ 38 | SNew(STextBlock) 39 | .Text(FText::FromString(TEXT("Advance Deletion"))) 40 | .Font(TitleTextFont) 41 | .Justification(ETextJustify::Center) 42 | .ColorAndOpacity(FColor::White) 43 | ] 44 | 45 | //SecondSlot for drop down to specify the listing condition and help text 46 | +SVerticalBox::Slot() 47 | .AutoHeight() 48 | [ 49 | SNew(SHorizontalBox) 50 | 51 | //Combox Box Slot 52 | +SHorizontalBox::Slot() 53 | .AutoWidth() 54 | [ 55 | ConstructComboBox() 56 | ] 57 | 58 | //Help text for combo box slot 59 | +SHorizontalBox::Slot() 60 | .FillWidth(.6f) 61 | [ 62 | ConstructComboHelpTexts(TEXT("Specify the listing condition in the drop down. Left mouse click to go to where asset is located"), 63 | ETextJustify::Center) 64 | ] 65 | 66 | //Help text for folder path 67 | +SHorizontalBox::Slot() 68 | .FillWidth(.1f) 69 | [ 70 | ConstructComboHelpTexts(TEXT("Current Folder:\n") + InArgs._CurrentSelectedFolder,ETextJustify::Right) 71 | ] 72 | ] 73 | 74 | //Third slot for the asset list 75 | +SVerticalBox::Slot() 76 | .VAlign(VAlign_Fill) 77 | [ 78 | SNew(SScrollBox) 79 | 80 | +SScrollBox::Slot() 81 | [ 82 | ConstructAssetListView() 83 | ] 84 | ] 85 | 86 | //Fourth slot for 3 buttons 87 | +SVerticalBox::Slot() 88 | .AutoHeight() 89 | [ 90 | SNew(SHorizontalBox) 91 | 92 | //Button1 slot 93 | +SHorizontalBox::Slot() 94 | .FillWidth(10.f) 95 | .Padding(5.f) 96 | [ 97 | ConstructDeleteAllButton() 98 | ] 99 | 100 | //Button2 slot 101 | +SHorizontalBox::Slot() 102 | .FillWidth(10.f) 103 | .Padding(5.f) 104 | [ 105 | ConstructSelectAllButton() 106 | ] 107 | 108 | //Button3 slot 109 | +SHorizontalBox::Slot() 110 | .FillWidth(10.f) 111 | .Padding(5.f) 112 | [ 113 | ConstructDeselectAllButton() 114 | ] 115 | ] 116 | ]; 117 | } 118 | 119 | TSharedRef>> SAdvanceDeletionTab::ConstructAssetListView() 120 | { 121 | ConstructedAssetListView = SNew(SListView< TSharedPtr >) 122 | .ItemHeight(24.f) 123 | .ListItemsSource(&DisplayedAssetsData) 124 | .OnGenerateRow(this,&SAdvanceDeletionTab::OnGenerateRowForList) 125 | .OnMouseButtonClick(this,&SAdvanceDeletionTab::OnRowWidgetMoustButtonClicked); 126 | 127 | return ConstructedAssetListView.ToSharedRef(); 128 | } 129 | 130 | void SAdvanceDeletionTab::RefreshAssetListView() 131 | { 132 | CheckBoxesArray.Empty(); 133 | AssetsDataToDeleteArray.Empty(); 134 | 135 | if(ConstructedAssetListView.IsValid()) 136 | { 137 | ConstructedAssetListView->RebuildList(); 138 | } 139 | } 140 | 141 | #pragma region ComboBoxForListingCondition 142 | 143 | TSharedRef>> SAdvanceDeletionTab::ConstructComboBox() 144 | { 145 | TSharedRef< SComboBox < TSharedPtr > > ConstructedComboBox = 146 | SNew(SComboBox < TSharedPtr >) 147 | .OptionsSource(&ComboBoxSourceItems) 148 | .OnGenerateWidget(this,&SAdvanceDeletionTab::OnGenerateComboContent) 149 | .OnSelectionChanged(this,&SAdvanceDeletionTab::OnComboSelectionChanged) 150 | [ 151 | SAssignNew(ComboDiplayTextBlock,STextBlock) 152 | .Text(FText::FromString(TEXT("List Assets Option"))) 153 | ]; 154 | 155 | return ConstructedComboBox; 156 | } 157 | 158 | TSharedRef SAdvanceDeletionTab::OnGenerateComboContent(TSharedPtr SourceItem) 159 | { 160 | TSharedRef ContructedComboText = SNew(STextBlock) 161 | .Text(FText::FromString(*SourceItem.Get())); 162 | 163 | return ContructedComboText; 164 | } 165 | 166 | void SAdvanceDeletionTab::OnComboSelectionChanged(TSharedPtr SelectedOption, 167 | ESelectInfo::Type InSelectInfo) 168 | { 169 | DebugHeader::Print(*SelectedOption.Get(),FColor::Cyan); 170 | 171 | ComboDiplayTextBlock->SetText(FText::FromString(*SelectedOption.Get())); 172 | 173 | FSuperManagerModule& SuperManagerModule = 174 | FModuleManager::LoadModuleChecked(TEXT("SuperManager")); 175 | 176 | //Pass data for our module to filter based on the selected option 177 | if(*SelectedOption.Get() == ListAll) 178 | { 179 | //List all stored asset data 180 | DisplayedAssetsData = StoredAssetsData; 181 | RefreshAssetListView(); 182 | } 183 | else if(*SelectedOption.Get() == ListUnused) 184 | { 185 | //List all unused assets 186 | SuperManagerModule.ListUnusedAssetsForAssetList(StoredAssetsData,DisplayedAssetsData); 187 | RefreshAssetListView(); 188 | } 189 | else if(*SelectedOption.Get() == ListSameName) 190 | { 191 | //List out all assets with same name 192 | SuperManagerModule.ListSameNameAssetsForAssetList(StoredAssetsData,DisplayedAssetsData); 193 | RefreshAssetListView(); 194 | } 195 | } 196 | 197 | TSharedRef SAdvanceDeletionTab::ConstructComboHelpTexts(const FString & TextContent, 198 | ETextJustify::Type TextJustify) 199 | { 200 | TSharedRef ConstructedHelpText = 201 | SNew(STextBlock) 202 | .Text(FText::FromString(TextContent)) 203 | .Justification(TextJustify) 204 | .AutoWrapText(true); 205 | 206 | return ConstructedHelpText; 207 | } 208 | 209 | #pragma endregion 210 | 211 | #pragma region RowWidgetForAssetListView 212 | 213 | TSharedRef SAdvanceDeletionTab::OnGenerateRowForList(TSharedPtr AssetDataToDisplay, const TSharedRef& OwnerTable) 214 | { 215 | if(!AssetDataToDisplay.IsValid()) return SNew(STableRow < TSharedPtr >,OwnerTable); 216 | 217 | const FString DisplayAssetClassName = AssetDataToDisplay->AssetClass.ToString(); 218 | const FString DisplayAssetName = AssetDataToDisplay->AssetName.ToString(); 219 | 220 | FSlateFontInfo AssetClassNameFont = GetEmboseedTextFont(); 221 | AssetClassNameFont.Size = 10; 222 | 223 | FSlateFontInfo AssetNameFont = GetEmboseedTextFont(); 224 | AssetNameFont.Size = 15; 225 | 226 | TSharedRef< STableRow < TSharedPtr > > ListViewRowWidget = 227 | SNew(STableRow < TSharedPtr >,OwnerTable).Padding(FMargin(5.f)) 228 | [ 229 | SNew(SHorizontalBox) 230 | 231 | //First slot for check box 232 | +SHorizontalBox::Slot() 233 | .HAlign(HAlign_Left) 234 | .VAlign(VAlign_Center) 235 | .FillWidth(.05f) 236 | [ 237 | ConstructCheckBox(AssetDataToDisplay) 238 | ] 239 | 240 | //Second slot for displaying asset class name 241 | +SHorizontalBox::Slot() 242 | .HAlign(HAlign_Center) 243 | .VAlign(VAlign_Fill) 244 | .FillWidth(.5f) 245 | [ 246 | ConstructTextForRowWidget(DisplayAssetClassName,AssetClassNameFont) 247 | ] 248 | 249 | //Third slot for displaying asset name 250 | +SHorizontalBox::Slot() 251 | .HAlign(HAlign_Left) 252 | .VAlign(VAlign_Fill) 253 | [ 254 | ConstructTextForRowWidget(DisplayAssetName,AssetNameFont) 255 | ] 256 | 257 | //Fourth slot for a button 258 | +SHorizontalBox::Slot() 259 | .HAlign(HAlign_Right) 260 | .VAlign(VAlign_Fill) 261 | [ 262 | ConstructButtonForRowWidget(AssetDataToDisplay) 263 | ] 264 | 265 | ]; 266 | 267 | return ListViewRowWidget; 268 | } 269 | 270 | void SAdvanceDeletionTab::OnRowWidgetMoustButtonClicked(TSharedPtr ClickedData) 271 | { 272 | FSuperManagerModule& SuperManagerModule = 273 | FModuleManager::LoadModuleChecked(TEXT("SuperManager")); 274 | 275 | SuperManagerModule.SyncCBToClickedAssetForAssetList(ClickedData->ObjectPath.ToString()); 276 | } 277 | 278 | TSharedRef SAdvanceDeletionTab::ConstructCheckBox(const TSharedPtr& AssetDataToDisplay) 279 | { 280 | TSharedRef ConstructedCheckBox = SNew(SCheckBox) 281 | .Type(ESlateCheckBoxType::CheckBox) 282 | .OnCheckStateChanged(this,&SAdvanceDeletionTab::OnCheckBoxStateChanged,AssetDataToDisplay) 283 | .Visibility(EVisibility::Visible); 284 | 285 | CheckBoxesArray.Add(ConstructedCheckBox); 286 | 287 | return ConstructedCheckBox; 288 | } 289 | 290 | void SAdvanceDeletionTab::OnCheckBoxStateChanged(ECheckBoxState NewState, TSharedPtr AssetData) 291 | { 292 | switch(NewState) 293 | { 294 | case ECheckBoxState::Unchecked: 295 | 296 | if(AssetsDataToDeleteArray.Contains(AssetData)) 297 | { 298 | AssetsDataToDeleteArray.Remove(AssetData); 299 | } 300 | 301 | break; 302 | 303 | case ECheckBoxState::Checked: 304 | 305 | AssetsDataToDeleteArray.AddUnique(AssetData); 306 | 307 | break; 308 | 309 | case ECheckBoxState::Undetermined: 310 | break; 311 | 312 | default: 313 | break; 314 | } 315 | 316 | } 317 | 318 | TSharedRef SAdvanceDeletionTab::ConstructTextForRowWidget(const FString & TextContent, 319 | const FSlateFontInfo & FontToUse) 320 | { 321 | TSharedRef ConstructedTextBlock = SNew(STextBlock) 322 | .Text(FText::FromString(TextContent)) 323 | .Font(FontToUse) 324 | .ColorAndOpacity(FColor::White); 325 | 326 | return ConstructedTextBlock; 327 | } 328 | 329 | TSharedRef SAdvanceDeletionTab::ConstructButtonForRowWidget(const TSharedPtr& AssetDataToDisplay) 330 | { 331 | TSharedRef ConstructedButton = SNew(SButton) 332 | .Text(FText::FromString(TEXT("Delete"))) 333 | .OnClicked(this,&SAdvanceDeletionTab::OnDeleteButtonClicked,AssetDataToDisplay); 334 | 335 | return ConstructedButton; 336 | } 337 | 338 | FReply SAdvanceDeletionTab::OnDeleteButtonClicked(TSharedPtr ClickedAssetData) 339 | { 340 | FSuperManagerModule& SuperManagerModule = 341 | FModuleManager::LoadModuleChecked(TEXT("SuperManager")); 342 | 343 | const bool bAssetDeleted = SuperManagerModule.DeleteSingleAssetForAssetList(*ClickedAssetData.Get()); 344 | 345 | if(bAssetDeleted) 346 | { 347 | //Updating the list source items 348 | if(StoredAssetsData.Contains(ClickedAssetData)) 349 | { 350 | StoredAssetsData.Remove(ClickedAssetData); 351 | } 352 | 353 | if(DisplayedAssetsData.Contains(ClickedAssetData)) 354 | { 355 | DisplayedAssetsData.Remove(ClickedAssetData); 356 | } 357 | 358 | //Refresh the list 359 | RefreshAssetListView(); 360 | } 361 | 362 | return FReply::Handled(); 363 | } 364 | 365 | #pragma endregion 366 | 367 | #pragma region TabButtons 368 | 369 | TSharedRef SAdvanceDeletionTab::ConstructDeleteAllButton() 370 | { 371 | TSharedRef DeleteAllButton = SNew(SButton) 372 | .ContentPadding(FMargin(5.f)) 373 | .OnClicked(this,&SAdvanceDeletionTab::OnDeleteAllButtonClicked); 374 | 375 | DeleteAllButton->SetContent(ConstructTextForTabButtons(TEXT("Delete All"))); 376 | 377 | return DeleteAllButton; 378 | } 379 | 380 | FReply SAdvanceDeletionTab::OnDeleteAllButtonClicked() 381 | { 382 | if(AssetsDataToDeleteArray.Num()==0) 383 | { 384 | DebugHeader::ShowMsgDialog(EAppMsgType::Ok,TEXT("No asset currently selected")); 385 | return FReply::Handled(); 386 | } 387 | 388 | TArray AssetDataToDelete; 389 | 390 | for(const TSharedPtr& Data:AssetsDataToDeleteArray) 391 | { 392 | AssetDataToDelete.Add(*Data.Get()); 393 | } 394 | 395 | FSuperManagerModule& SuperManagerModule = 396 | FModuleManager::LoadModuleChecked(TEXT("SuperManager")); 397 | 398 | const bool bAssetsDeleted = SuperManagerModule.DeleteMultipleAssetsForAssetList(AssetDataToDelete); 399 | 400 | if(bAssetsDeleted) 401 | { 402 | for(const TSharedPtr& DeletedData:AssetsDataToDeleteArray) 403 | { 404 | //Updating the stored assets data 405 | if(StoredAssetsData.Contains(DeletedData)) 406 | { 407 | StoredAssetsData.Remove(DeletedData); 408 | } 409 | 410 | if(DisplayedAssetsData.Contains(DeletedData)) 411 | { 412 | DisplayedAssetsData.Remove(DeletedData); 413 | } 414 | } 415 | 416 | RefreshAssetListView(); 417 | } 418 | 419 | //Pass data to our module for deletion 420 | return FReply::Handled(); 421 | } 422 | 423 | TSharedRef SAdvanceDeletionTab::ConstructSelectAllButton() 424 | { 425 | TSharedRef SelectAllButton = SNew(SButton) 426 | .ContentPadding(FMargin(5.f)) 427 | .OnClicked(this,&SAdvanceDeletionTab::OnSelectAllButtonClicked); 428 | 429 | SelectAllButton->SetContent(ConstructTextForTabButtons(TEXT("Select All"))); 430 | 431 | return SelectAllButton; 432 | } 433 | 434 | FReply SAdvanceDeletionTab::OnSelectAllButtonClicked() 435 | { 436 | if(CheckBoxesArray.Num()==0) return FReply::Handled(); 437 | 438 | for(const TSharedRef& CheckBox:CheckBoxesArray) 439 | { 440 | if(!CheckBox->IsChecked()) 441 | { 442 | CheckBox->ToggleCheckedState(); 443 | } 444 | } 445 | 446 | return FReply::Handled(); 447 | } 448 | 449 | TSharedRef SAdvanceDeletionTab::ConstructDeselectAllButton() 450 | { 451 | TSharedRef DeselectAllButton = SNew(SButton) 452 | .ContentPadding(FMargin(5.f)) 453 | .OnClicked(this,&SAdvanceDeletionTab::OnDeselectAllButtonClicked); 454 | 455 | DeselectAllButton->SetContent(ConstructTextForTabButtons(TEXT("Deselect All"))); 456 | 457 | return DeselectAllButton; 458 | } 459 | 460 | FReply SAdvanceDeletionTab::OnDeselectAllButtonClicked() 461 | { 462 | if(CheckBoxesArray.Num()==0) return FReply::Handled(); 463 | 464 | for(const TSharedRef& CheckBox:CheckBoxesArray) 465 | { 466 | if(CheckBox->IsChecked()) 467 | { 468 | CheckBox->ToggleCheckedState(); 469 | } 470 | } 471 | 472 | return FReply::Handled(); 473 | } 474 | 475 | TSharedRef SAdvanceDeletionTab::ConstructTextForTabButtons(const FString & TextContent) 476 | { 477 | FSlateFontInfo ButtonTextFont = GetEmboseedTextFont(); 478 | ButtonTextFont.Size = 15; 479 | 480 | TSharedRef ConstructedTextBlock = SNew(STextBlock) 481 | .Text(FText::FromString(TextContent)) 482 | .Font(ButtonTextFont) 483 | .Justification(ETextJustify::Center); 484 | 485 | return ConstructedTextBlock; 486 | } 487 | 488 | #pragma endregion -------------------------------------------------------------------------------- /Plugins/SuperManager/Source/SuperManager/Private/SuperManager.cpp: -------------------------------------------------------------------------------- 1 | // Copyright Vince Petrelli. Published in 2022.All rights reserved. 2 | 3 | #include "SuperManager.h" 4 | #include "ContentBrowserModule.h" 5 | #include "DebugHeader.h" 6 | #include "EditorAssetLibrary.h" 7 | #include "ObjectTools.h" 8 | #include "AssetRegistryModule.h" 9 | #include "AssetToolsModule.h" 10 | #include "SlateWidgets/AdvanceDeletionWidget.h" 11 | #include "CustomStyle/SuperManagerStyle.h" 12 | #include "LevelEditor.h" 13 | #include "Engine/Selection.h" 14 | #include "Subsystems/EditorActorSubsystem.h" 15 | #include "CustomUICommands/SuperManagerUICommands.h" 16 | #include "SceneOutlinerModule.h" 17 | #include "CustomOutlinerColumn/OutlinerSelectionLockColumn.h" 18 | 19 | #define LOCTEXT_NAMESPACE "FSuperManagerModule" 20 | 21 | void FSuperManagerModule::StartupModule() 22 | { 23 | FSuperManagerStyle::InitializeIcons(); 24 | 25 | InitCBMenuExtention(); 26 | 27 | RegisterAdvanceDeletionTab(); 28 | 29 | FSuperManagerUICommands::Register(); 30 | 31 | InitCustomUICommands(); 32 | 33 | InitLevelEditorExtention(); 34 | 35 | InitCustomSelectionEvent(); 36 | 37 | InitSceneOutlinerColumnExtension(); 38 | } 39 | 40 | #pragma region ContentBrowserMenuExtention 41 | 42 | void FSuperManagerModule::InitCBMenuExtention() 43 | { 44 | FContentBrowserModule& ContentBrowserModule = 45 | FModuleManager::LoadModuleChecked(TEXT("ContentBrowser")); 46 | 47 | //Get hold of all the menu extenders 48 | TArray& ContentBrowserModuleMenuExtenders = 49 | ContentBrowserModule.GetAllPathViewContextMenuExtenders(); 50 | 51 | /*FContentBrowserMenuExtender_SelectedPaths CustomCBMenuDelegate; 52 | CustomCBMenuDelegate.BindRaw(this,&FSuperManagerModule::CustomCBMenuExtender); 53 | 54 | ContentBrowserModuleMenuExtenders.Add(CustomCBMenuDelegate);*/ 55 | 56 | //We add custom delegate to all the existing delegate 57 | ContentBrowserModuleMenuExtenders.Add(FContentBrowserMenuExtender_SelectedPaths:: 58 | CreateRaw(this,&FSuperManagerModule::CustomCBMenuExtender)); 59 | } 60 | 61 | //To define the positio for inserting menu entry 62 | TSharedRef FSuperManagerModule::CustomCBMenuExtender(const TArray& SelectedPaths) 63 | { 64 | TSharedRef MenuExtender (new FExtender()); 65 | 66 | if(SelectedPaths.Num()>0) 67 | { 68 | MenuExtender->AddMenuExtension(FName("Delete"), //Extend hook, position to insert 69 | EExtensionHook::After, //Insert before or after 70 | TSharedPtr(), //Custom hot keys 71 | FMenuExtensionDelegate::CreateRaw(this,&FSuperManagerModule::AddCBMenuEntry)); //Second binding, will define details for this menu entry 72 | 73 | FolderPathsSelected = SelectedPaths; 74 | } 75 | 76 | return MenuExtender; 77 | } 78 | 79 | //Define details for the custom menu entry 80 | void FSuperManagerModule::AddCBMenuEntry(FMenuBuilder & MenuBuilder) 81 | { 82 | MenuBuilder.AddMenuEntry 83 | ( 84 | FText::FromString(TEXT("Delete Unused Assets")), //Title text for menu entry 85 | FText::FromString(TEXT("Safely delete all unused assets under folder")), //Tooltip text 86 | FSlateIcon(FSuperManagerStyle::GetStyleSetName(),"ContentBrowser.DeleteUnusedAssets"), //Custom icon 87 | FExecuteAction::CreateRaw(this,&FSuperManagerModule::OnDeleteUnsuedAssetButtonClicked) //The actual function to excute 88 | ); 89 | 90 | MenuBuilder.AddMenuEntry 91 | ( 92 | FText::FromString(TEXT("Delete Empty Folders")), //Title text for menu entry 93 | FText::FromString(TEXT("Safely delete all empty folders")), //Tooltip text 94 | FSlateIcon(FSuperManagerStyle::GetStyleSetName(),"ContentBrowser.DeleteEmptyFolders"), //Custom icon 95 | FExecuteAction::CreateRaw(this,&FSuperManagerModule::OnDeleteEmptyFoldersButtonClicked) //The actual function to excute 96 | ); 97 | 98 | MenuBuilder.AddMenuEntry 99 | ( 100 | FText::FromString(TEXT("Advance Deletion")), //Title text for menu entry 101 | FText::FromString(TEXT("List assets by specific condition in a tab for deleting")), //Tooltip text 102 | FSlateIcon(FSuperManagerStyle::GetStyleSetName(),"ContentBrowser.AdvanceDeletion"), //Custom icon 103 | FExecuteAction::CreateRaw(this,&FSuperManagerModule::OnAdvanceDeletionButtonClicked) //The actual function to excute 104 | ); 105 | } 106 | 107 | void FSuperManagerModule::OnDeleteUnsuedAssetButtonClicked() 108 | { 109 | if(ConstructedDockTab.IsValid()) 110 | { 111 | DebugHeader::ShowMsgDialog(EAppMsgType::Ok,TEXT("Please close advance deletion tab before this operation")); 112 | return; 113 | } 114 | 115 | if(FolderPathsSelected.Num()>1) 116 | { 117 | DebugHeader::ShowMsgDialog(EAppMsgType::Ok,TEXT("You can only do this to one folder")); 118 | return; 119 | } 120 | 121 | TArray AssetsPathNames = UEditorAssetLibrary::ListAssets(FolderPathsSelected[0]); 122 | 123 | //Whether there are assets under selected folder 124 | if(AssetsPathNames.Num()==0) 125 | { 126 | DebugHeader::ShowMsgDialog(EAppMsgType::Ok,TEXT("No asset found under selected folder"),false); 127 | return; 128 | } 129 | 130 | EAppReturnType::Type ConfirmResult = 131 | DebugHeader::ShowMsgDialog(EAppMsgType::YesNo,TEXT("A total of ") + FString::FromInt(AssetsPathNames.Num()) 132 | + TEXT(" assets need to be checked.\nWould you like to procceed?"),false); 133 | 134 | if(ConfirmResult == EAppReturnType::No) return; 135 | 136 | FixUpRedirectors(); 137 | 138 | TArray UnusedAssetsDataArray; 139 | 140 | for(const FString& AssetPathName:AssetsPathNames) 141 | { 142 | //Don't touch root folder 143 | if(AssetPathName.Contains(TEXT("Developers"))|| 144 | AssetPathName.Contains(TEXT("Collections")) || 145 | AssetPathName.Contains(TEXT("__ExternalActors__")) || 146 | AssetPathName.Contains(TEXT("__ExternalObjects__"))) 147 | { 148 | continue; 149 | } 150 | 151 | if(!UEditorAssetLibrary::DoesAssetExist(AssetPathName)) continue; 152 | 153 | TArray AssetReferencers = 154 | UEditorAssetLibrary::FindPackageReferencersForAsset(AssetPathName); 155 | 156 | if(AssetReferencers.Num()==0) 157 | { 158 | const FAssetData UnusedAssetData = UEditorAssetLibrary::FindAssetData(AssetPathName); 159 | UnusedAssetsDataArray.Add(UnusedAssetData); 160 | } 161 | } 162 | 163 | if(UnusedAssetsDataArray.Num()>0) 164 | { 165 | ObjectTools::DeleteAssets(UnusedAssetsDataArray); 166 | } 167 | else 168 | { 169 | DebugHeader::ShowMsgDialog(EAppMsgType::Ok,TEXT("No unused asset found under selected folder"),false); 170 | } 171 | } 172 | 173 | void FSuperManagerModule::OnDeleteEmptyFoldersButtonClicked() 174 | { 175 | if(ConstructedDockTab.IsValid()) 176 | { 177 | DebugHeader::ShowMsgDialog(EAppMsgType::Ok,TEXT("Please close advance deletion tab before this operation")); 178 | return; 179 | } 180 | 181 | FixUpRedirectors(); 182 | 183 | TArray FolderPathsArray = UEditorAssetLibrary::ListAssets(FolderPathsSelected[0],true,true); 184 | uint32 Counter = 0; 185 | 186 | FString EmptyFolderPathsNames; 187 | TArray EmptyFoldersPathsArray; 188 | 189 | for(const FString& FolderPath:FolderPathsArray) 190 | { 191 | if(FolderPath.Contains(TEXT("Developers"))|| 192 | FolderPath.Contains(TEXT("Collections")) || 193 | FolderPath.Contains(TEXT("__ExternalActors__")) || 194 | FolderPath.Contains(TEXT("__ExternalObjects__"))) 195 | { 196 | continue; 197 | } 198 | 199 | if(!UEditorAssetLibrary::DoesDirectoryExist(FolderPath)) continue; 200 | 201 | if(!UEditorAssetLibrary::DoesDirectoryHaveAssets(FolderPath)) 202 | { 203 | EmptyFolderPathsNames.Append(FolderPath); 204 | EmptyFolderPathsNames.Append(TEXT("\n")); 205 | 206 | EmptyFoldersPathsArray.Add(FolderPath); 207 | } 208 | } 209 | 210 | if(EmptyFoldersPathsArray.Num()==0) 211 | { 212 | DebugHeader::ShowMsgDialog(EAppMsgType::Ok,TEXT("No empty folder found under selected folder"),false); 213 | return; 214 | } 215 | 216 | EAppReturnType::Type ConfirmResult = DebugHeader::ShowMsgDialog(EAppMsgType::OkCancel, 217 | TEXT("Empty folders found in:\n") + EmptyFolderPathsNames +TEXT("\nWould you like to delete all?"),false); 218 | 219 | if(ConfirmResult==EAppReturnType::Cancel) return; 220 | 221 | for(const FString& EmptyFolderPath:EmptyFoldersPathsArray) 222 | { 223 | UEditorAssetLibrary::DeleteDirectory(EmptyFolderPath)? 224 | ++Counter : DebugHeader::Print(TEXT("Failed to delete " + EmptyFolderPath),FColor::Red); 225 | } 226 | 227 | if(Counter>0) 228 | { 229 | DebugHeader::ShowNotifyInfo(TEXT("Successfully deleted ") + FString::FromInt(Counter) + TEXT(" folders")); 230 | } 231 | 232 | } 233 | 234 | void FSuperManagerModule::OnAdvanceDeletionButtonClicked() 235 | { 236 | FixUpRedirectors(); 237 | 238 | FGlobalTabmanager::Get()->TryInvokeTab(FName("AdvanceDeletion")); 239 | } 240 | 241 | void FSuperManagerModule::FixUpRedirectors() 242 | { 243 | TArray RedirectorsToFixArray; 244 | 245 | FAssetRegistryModule& AssetRegistryModule = 246 | FModuleManager::Get().LoadModuleChecked(TEXT("AssetRegistry")); 247 | 248 | FARFilter Filter; 249 | Filter.bRecursivePaths = true; 250 | Filter.PackagePaths.Emplace("/Game"); 251 | Filter.ClassNames.Emplace("ObjectRedirector"); 252 | 253 | TArray OutRedirectors; 254 | AssetRegistryModule.Get().GetAssets(Filter,OutRedirectors); 255 | 256 | for(const FAssetData& RedirectorData:OutRedirectors) 257 | { 258 | if(UObjectRedirector* RedirectorToFix = Cast(RedirectorData.GetAsset())) 259 | { 260 | RedirectorsToFixArray.Add(RedirectorToFix); 261 | } 262 | } 263 | 264 | FAssetToolsModule& AssetToolsModule = 265 | FModuleManager::LoadModuleChecked(TEXT("AssetTools")); 266 | 267 | AssetToolsModule.Get().FixupReferencers(RedirectorsToFixArray); 268 | } 269 | 270 | #pragma endregion 271 | 272 | #pragma region CustomEditorTab 273 | 274 | void FSuperManagerModule::RegisterAdvanceDeletionTab() 275 | { 276 | FGlobalTabmanager::Get()->RegisterNomadTabSpawner(FName("AdvanceDeletion"), 277 | FOnSpawnTab::CreateRaw(this,&FSuperManagerModule::OnSpawnAdvanceDeletionTab)) 278 | .SetDisplayName(FText::FromString(TEXT("Advance Deletion"))) 279 | .SetIcon(FSlateIcon(FSuperManagerStyle::GetStyleSetName(),"ContentBrowser.AdvanceDeletion")); 280 | } 281 | 282 | TSharedRef FSuperManagerModule::OnSpawnAdvanceDeletionTab(const FSpawnTabArgs &SpawnTabArgs) 283 | { 284 | if(FolderPathsSelected.Num()==0) return SNew(SDockTab).TabRole(ETabRole::NomadTab); 285 | 286 | ConstructedDockTab = 287 | SNew(SDockTab).TabRole(ETabRole::NomadTab) 288 | [ 289 | SNew(SAdvanceDeletionTab) 290 | .AssetsDataToStore(GetAllAssetDataUnderSelectedFolder()) 291 | .CurrentSelectedFolder(FolderPathsSelected[0]) 292 | ]; 293 | 294 | ConstructedDockTab->SetOnTabClosed( 295 | SDockTab::FOnTabClosedCallback::CreateRaw(this,&FSuperManagerModule::OnAdvanceDeletionTabClosed)); 296 | 297 | return ConstructedDockTab.ToSharedRef(); 298 | } 299 | 300 | TArray> FSuperManagerModule::GetAllAssetDataUnderSelectedFolder() 301 | { 302 | TArray< TSharedPtr > AvaiableAssetsData; 303 | 304 | TArray AssetsPathNames = UEditorAssetLibrary::ListAssets(FolderPathsSelected[0]); 305 | 306 | for(const FString& AssetPathName:AssetsPathNames) 307 | { 308 | //Don't touch root folder 309 | if(AssetPathName.Contains(TEXT("Developers"))|| 310 | AssetPathName.Contains(TEXT("Collections")) || 311 | AssetPathName.Contains(TEXT("__ExternalActors__")) || 312 | AssetPathName.Contains(TEXT("__ExternalObjects__"))) 313 | { 314 | continue; 315 | } 316 | 317 | if(!UEditorAssetLibrary::DoesAssetExist(AssetPathName)) continue; 318 | 319 | const FAssetData Data = UEditorAssetLibrary::FindAssetData(AssetPathName); 320 | 321 | AvaiableAssetsData.Add(MakeShared(Data)); 322 | } 323 | 324 | return AvaiableAssetsData; 325 | } 326 | 327 | void FSuperManagerModule::OnAdvanceDeletionTabClosed(TSharedRef TabToClose) 328 | { 329 | if(ConstructedDockTab.IsValid()) 330 | { 331 | ConstructedDockTab.Reset(); 332 | FolderPathsSelected.Empty(); 333 | } 334 | } 335 | 336 | #pragma endregion 337 | 338 | #pragma region ProccessDataForAdvanceDeletionTab 339 | 340 | bool FSuperManagerModule::DeleteSingleAssetForAssetList(const FAssetData & AssetDataToDelete) 341 | { 342 | TArray AssetDataForDeletion; 343 | AssetDataForDeletion.Add(AssetDataToDelete); 344 | 345 | if(ObjectTools::DeleteAssets(AssetDataForDeletion)>0) 346 | { 347 | return true; 348 | } 349 | 350 | return false; 351 | } 352 | 353 | bool FSuperManagerModule::DeleteMultipleAssetsForAssetList(const TArray& AssetsToDelete) 354 | { 355 | if(ObjectTools::DeleteAssets(AssetsToDelete)>0) 356 | { 357 | return true; 358 | } 359 | 360 | return false; 361 | } 362 | 363 | void FSuperManagerModule::ListUnusedAssetsForAssetList(const TArray>& AssetsDataToFilter, 364 | TArray>& OutUnusedAssetsData) 365 | { 366 | OutUnusedAssetsData.Empty(); 367 | 368 | for(const TSharedPtr& DataSharedPtr:AssetsDataToFilter) 369 | { 370 | TArray AssetReferencers = 371 | UEditorAssetLibrary::FindPackageReferencersForAsset(DataSharedPtr->ObjectPath.ToString()); 372 | 373 | if(AssetReferencers.Num()==0) 374 | { 375 | OutUnusedAssetsData.Add(DataSharedPtr); 376 | } 377 | } 378 | } 379 | 380 | void FSuperManagerModule::ListSameNameAssetsForAssetList(const TArray>& AssetsDataToFilter, 381 | TArray>& OutSameNameAssetsData) 382 | { 383 | OutSameNameAssetsData.Empty(); 384 | 385 | //Multimap for supporting finding assets with same name 386 | TMultiMap > AssetsInfoMultiMap; 387 | 388 | for(const TSharedPtr& DataSharedPtr:AssetsDataToFilter) 389 | { 390 | AssetsInfoMultiMap.Emplace(DataSharedPtr->AssetName.ToString(), DataSharedPtr); 391 | } 392 | 393 | for(const TSharedPtr& DataSharedPtr:AssetsDataToFilter) 394 | { 395 | TArray< TSharedPtr > OutAssetsData; 396 | AssetsInfoMultiMap.MultiFind(DataSharedPtr->AssetName.ToString(), OutAssetsData); 397 | 398 | if(OutAssetsData.Num()<=1) continue; 399 | 400 | for(const TSharedPtr& SameNameData:OutAssetsData) 401 | { 402 | if(SameNameData.IsValid()) 403 | { 404 | OutSameNameAssetsData.AddUnique(SameNameData); 405 | } 406 | } 407 | } 408 | } 409 | 410 | void FSuperManagerModule::SyncCBToClickedAssetForAssetList(const FString & AssetPathToSync) 411 | { 412 | TArray AssetsPathToSync; 413 | AssetsPathToSync.Add(AssetPathToSync); 414 | 415 | UEditorAssetLibrary::SyncBrowserToObjects(AssetsPathToSync); 416 | } 417 | #pragma endregion 418 | 419 | #pragma region LevelEditorMenuExtension 420 | 421 | void FSuperManagerModule::InitLevelEditorExtention() 422 | { 423 | FLevelEditorModule& LevelEditorModule = 424 | FModuleManager::LoadModuleChecked(TEXT("LevelEditor")); 425 | 426 | TSharedRef ExistingLevelCommands = LevelEditorModule.GetGlobalLevelEditorActions(); 427 | ExistingLevelCommands->Append(CustomUICommands.ToSharedRef()); 428 | 429 | TArray& LevelEditorMenuExtenders = 430 | LevelEditorModule.GetAllLevelViewportContextMenuExtenders(); 431 | 432 | LevelEditorMenuExtenders.Add(FLevelEditorModule::FLevelViewportMenuExtender_SelectedActors:: 433 | CreateRaw(this,&FSuperManagerModule::CustomLevelEditorMenuExtender)); 434 | } 435 | 436 | TSharedRef FSuperManagerModule::CustomLevelEditorMenuExtender(const TSharedRef UICommandList, 437 | const TArray SelectedActors) 438 | { 439 | TSharedRef MenuExtender = MakeShareable(new FExtender()); 440 | 441 | if(SelectedActors.Num()>0) 442 | { 443 | MenuExtender->AddMenuExtension( 444 | FName("ActorOptions"), 445 | EExtensionHook::Before, 446 | UICommandList, 447 | FMenuExtensionDelegate::CreateRaw(this,&FSuperManagerModule::AddLevelEditorMenuEntry) 448 | ); 449 | } 450 | 451 | return MenuExtender; 452 | } 453 | 454 | void FSuperManagerModule::AddLevelEditorMenuEntry(FMenuBuilder & MenuBuilder) 455 | { 456 | MenuBuilder.AddMenuEntry 457 | ( 458 | FText::FromString(TEXT("Lock Actor Selection")), 459 | FText::FromString(TEXT("Prevent actor from being selected")), 460 | FSlateIcon(FSuperManagerStyle::GetStyleSetName(),"LevelEditor.LockSelection"), 461 | FExecuteAction::CreateRaw(this,&FSuperManagerModule::OnLockActorSelectionButtonClicked) 462 | ); 463 | 464 | MenuBuilder.AddMenuEntry 465 | ( 466 | FText::FromString(TEXT("Unlock All Actor Selection")), 467 | FText::FromString(TEXT("Remove the selection constraint on all actor")), 468 | FSlateIcon(FSuperManagerStyle::GetStyleSetName(),"LevelEditor.UnlockSelection"), 469 | FExecuteAction::CreateRaw(this,&FSuperManagerModule::OnUnlockActorSelectionButtonClicked) 470 | ); 471 | } 472 | 473 | void FSuperManagerModule::OnLockActorSelectionButtonClicked() 474 | { 475 | if(!GetEditorActorSubsystem()) return; 476 | 477 | TArray SelectedActors = WeakEditorActorSubsystem->GetSelectedLevelActors(); 478 | 479 | if(SelectedActors.Num()==0) 480 | { 481 | DebugHeader::ShowNotifyInfo(TEXT("No actor selected")); 482 | return; 483 | } 484 | 485 | FString CurrentLockedActorNames = TEXT("Locked selection for:"); 486 | 487 | for(AActor* SelectedActor:SelectedActors) 488 | { 489 | if(!SelectedActor) continue; 490 | 491 | LockActorSelection(SelectedActor); 492 | 493 | WeakEditorActorSubsystem->SetActorSelectionState(SelectedActor,false); 494 | 495 | CurrentLockedActorNames.Append(TEXT("\n")); 496 | CurrentLockedActorNames.Append(SelectedActor->GetActorLabel()); 497 | } 498 | 499 | RefreshSceneOutliner(); 500 | 501 | DebugHeader::ShowNotifyInfo(CurrentLockedActorNames); 502 | } 503 | 504 | void FSuperManagerModule::OnUnlockActorSelectionButtonClicked() 505 | { 506 | if(!GetEditorActorSubsystem()) return; 507 | 508 | TArray AllActorsInLevel = WeakEditorActorSubsystem->GetAllLevelActors(); 509 | TArray AllLockedActors; 510 | 511 | for(AActor* ActorInLevel:AllActorsInLevel) 512 | { 513 | if(!ActorInLevel) continue; 514 | 515 | if(CheckIsActorSelectionLocked(ActorInLevel)) 516 | { 517 | AllLockedActors.Add(ActorInLevel); 518 | } 519 | } 520 | 521 | if(AllLockedActors.Num()==0) 522 | { 523 | DebugHeader::ShowNotifyInfo(TEXT("No selection locked actor currently")); 524 | return; 525 | } 526 | 527 | FString UnlockedActorNames = TEXT("Lifted selection constraint for:"); 528 | 529 | for(AActor* LockedActor:AllLockedActors) 530 | { 531 | UnlockActorSelection(LockedActor); 532 | 533 | UnlockedActorNames.Append(TEXT("\n")); 534 | UnlockedActorNames.Append(LockedActor->GetActorLabel()); 535 | } 536 | 537 | RefreshSceneOutliner(); 538 | 539 | DebugHeader::ShowNotifyInfo(UnlockedActorNames); 540 | } 541 | 542 | #pragma endregion 543 | 544 | #pragma region SelectionLock 545 | 546 | void FSuperManagerModule::InitCustomSelectionEvent() 547 | { 548 | USelection* UserSelection = GEditor->GetSelectedActors(); 549 | 550 | UserSelection->SelectObjectEvent.AddRaw(this,&FSuperManagerModule::OnActorSelected); 551 | } 552 | 553 | void FSuperManagerModule::OnActorSelected(UObject * SelectedObject) 554 | { 555 | if(!GetEditorActorSubsystem()) return; 556 | 557 | if(AActor* SelectedActor = Cast(SelectedObject)) 558 | { 559 | if(CheckIsActorSelectionLocked(SelectedActor)) 560 | { 561 | //Deselect actor right away 562 | WeakEditorActorSubsystem->SetActorSelectionState(SelectedActor,false); 563 | } 564 | } 565 | } 566 | 567 | void FSuperManagerModule::LockActorSelection(AActor * ActorToProcess) 568 | { 569 | if(!ActorToProcess) return; 570 | 571 | if(!ActorToProcess->ActorHasTag(FName("Locked"))) 572 | { 573 | ActorToProcess->Tags.Add(FName("Locked")); 574 | } 575 | } 576 | 577 | void FSuperManagerModule::UnlockActorSelection(AActor * ActorToProcess) 578 | { 579 | if(!ActorToProcess) return; 580 | 581 | if(ActorToProcess->ActorHasTag(FName("Locked"))) 582 | { 583 | ActorToProcess->Tags.Remove(FName("Locked")); 584 | } 585 | } 586 | 587 | bool FSuperManagerModule::CheckIsActorSelectionLocked(AActor * ActorToProcess) 588 | { 589 | if(!ActorToProcess) return false; 590 | 591 | return ActorToProcess->ActorHasTag(FName("Locked")); 592 | } 593 | 594 | void FSuperManagerModule::RefreshSceneOutliner() 595 | { 596 | FLevelEditorModule& LevelEditorModule = 597 | FModuleManager::LoadModuleChecked(TEXT("LevelEditor")); 598 | 599 | TSharedPtr SceneOutliner = LevelEditorModule.GetFirstLevelEditor()->GetSceneOutliner(); 600 | 601 | if(SceneOutliner.IsValid()) 602 | { 603 | SceneOutliner->FullRefresh(); 604 | } 605 | } 606 | 607 | #pragma endregion 608 | 609 | #pragma region CustomEditorUICommands 610 | 611 | void FSuperManagerModule::InitCustomUICommands() 612 | { 613 | CustomUICommands = MakeShareable(new FUICommandList()); 614 | 615 | CustomUICommands->MapAction( 616 | FSuperManagerUICommands::Get().LockActorSelection, 617 | FExecuteAction::CreateRaw(this,&FSuperManagerModule::OnSelectionLockHotKeyPressed) 618 | ); 619 | 620 | CustomUICommands->MapAction( 621 | FSuperManagerUICommands::Get().UnlockActorSelection, 622 | FExecuteAction::CreateRaw(this,&FSuperManagerModule::OnUnlockActorSelectionHotKeyPressed) 623 | ); 624 | } 625 | 626 | void FSuperManagerModule::OnSelectionLockHotKeyPressed() 627 | { 628 | OnLockActorSelectionButtonClicked(); 629 | } 630 | 631 | void FSuperManagerModule::OnUnlockActorSelectionHotKeyPressed() 632 | { 633 | OnUnlockActorSelectionButtonClicked(); 634 | } 635 | 636 | #pragma endregion 637 | 638 | #pragma region SceneOutlinerExtension 639 | 640 | void FSuperManagerModule::InitSceneOutlinerColumnExtension() 641 | { 642 | FSceneOutlinerModule& SceneOutlinerModule = 643 | FModuleManager::LoadModuleChecked(TEXT("SceneOutliner")); 644 | 645 | FSceneOutlinerColumnInfo SelectionLockColumnInfo( 646 | ESceneOutlinerColumnVisibility::Visible, 647 | 1, 648 | FCreateSceneOutlinerColumn::CreateRaw(this,&FSuperManagerModule::OnCreateSelectionLockColumn) 649 | ); 650 | 651 | SceneOutlinerModule.RegisterDefaultColumnType(SelectionLockColumnInfo); 652 | } 653 | 654 | TSharedRef FSuperManagerModule::OnCreateSelectionLockColumn(ISceneOutliner & SceneOutliner) 655 | { 656 | return MakeShareable(new FOutlinerSelectionLockColumn(SceneOutliner)); 657 | } 658 | 659 | void FSuperManagerModule::UnRegisterSceneOutlinerColumnExtension() 660 | { 661 | FSceneOutlinerModule& SceneOutlinerModule = 662 | FModuleManager::LoadModuleChecked(TEXT("SceneOutliner")); 663 | 664 | SceneOutlinerModule.UnRegisterColumnType(); 665 | } 666 | 667 | #pragma endregion 668 | 669 | void FSuperManagerModule::ProcessLockingForOutliner(AActor * ActorToProcess, bool bShouldLock) 670 | { 671 | if(!GetEditorActorSubsystem()) return; 672 | 673 | if(bShouldLock) 674 | { 675 | LockActorSelection(ActorToProcess); 676 | 677 | WeakEditorActorSubsystem->SetActorSelectionState(ActorToProcess,false); 678 | 679 | DebugHeader::ShowNotifyInfo(TEXT("Locked selection for:\n") + ActorToProcess->GetActorLabel()); 680 | } 681 | else 682 | { 683 | UnlockActorSelection(ActorToProcess); 684 | 685 | DebugHeader::ShowNotifyInfo(TEXT("Removed selection lock for:\n") + ActorToProcess->GetActorLabel()); 686 | } 687 | } 688 | 689 | bool FSuperManagerModule::GetEditorActorSubsystem() 690 | { 691 | if(!WeakEditorActorSubsystem.IsValid()) 692 | { 693 | WeakEditorActorSubsystem = GEditor->GetEditorSubsystem(); 694 | } 695 | 696 | return WeakEditorActorSubsystem.IsValid(); 697 | } 698 | 699 | void FSuperManagerModule::ShutdownModule() 700 | { 701 | // This function may be called during shutdown to clean up your module. For modules that support dynamic reloading, 702 | // we call this function before unloading the module. 703 | FGlobalTabmanager::Get()->UnregisterNomadTabSpawner(FName("AdvanceDeletion")); 704 | 705 | FSuperManagerStyle::ShutDown(); 706 | 707 | FSuperManagerUICommands::Unregister(); 708 | 709 | UnRegisterSceneOutlinerColumnExtension(); 710 | } 711 | 712 | #undef LOCTEXT_NAMESPACE 713 | 714 | IMPLEMENT_MODULE(FSuperManagerModule, SuperManager) -------------------------------------------------------------------------------- /Plugins/SuperManager/Source/SuperManager/Public/ActorActions/QuickActorActionsWidget.h: -------------------------------------------------------------------------------- 1 | // Copyright Vince Petrelli. Published in 2022.All rights reserved. 2 | 3 | #pragma once 4 | 5 | #include "CoreMinimal.h" 6 | #include "EditorUtilityWidget.h" 7 | #include "QuickActorActionsWidget.generated.h" 8 | 9 | UENUM(BlueprintType) 10 | enum class E_DuplicationAxis : uint8 11 | { 12 | EDA_XAxis UMETA (DisplayName = "X Axis"), 13 | EDA_YAxis UMETA (DisplayName = "Y Axis"), 14 | EDA_ZAxis UMETA (DisplayName = "Z Axis"), 15 | EDA_MAX UMETA (DisplayName = "Default Max") 16 | }; 17 | 18 | USTRUCT(BlueprintType) 19 | struct FRandomActorRotation 20 | { 21 | GENERATED_BODY() 22 | 23 | UPROPERTY(EditAnywhere,BlueprintReadWrite) 24 | bool bRandomizeRotYaw = false; 25 | 26 | UPROPERTY(EditAnywhere,BlueprintReadWrite, meta = (EditCondition = "bRandomizeRotYaw")) 27 | float RotYawMin = -45.f; 28 | 29 | UPROPERTY(EditAnywhere,BlueprintReadWrite, meta = (EditCondition = "bRandomizeRotYaw")) 30 | float RotYawMax = 45.f; 31 | 32 | UPROPERTY(EditAnywhere,BlueprintReadWrite) 33 | bool bRandomizeRotPitch = false; 34 | 35 | UPROPERTY(EditAnywhere,BlueprintReadWrite, meta = (EditCondition = "bRandomizeRotPitch")) 36 | float RotPitchMin = -45.f; 37 | 38 | UPROPERTY(EditAnywhere,BlueprintReadWrite, meta = (EditCondition = "bRandomizeRotPitch")) 39 | float RotPitchMax = 45.f; 40 | 41 | UPROPERTY(EditAnywhere,BlueprintReadWrite) 42 | bool bRandomizeRotRoll = false; 43 | 44 | UPROPERTY(EditAnywhere,BlueprintReadWrite, meta = (EditCondition = "bRandomizeRotRoll")) 45 | float RotRollMin = -45.f; 46 | 47 | UPROPERTY(EditAnywhere,BlueprintReadWrite, meta = (EditCondition = "bRandomizeRotRoll")) 48 | float RotRollMax = 45.f; 49 | 50 | }; 51 | /** 52 | * 53 | */ 54 | UCLASS() 55 | class SUPERMANAGER_API UQuickActorActionsWidget : public UEditorUtilityWidget 56 | { 57 | GENERATED_BODY() 58 | 59 | public: 60 | 61 | #pragma region ActorBatchSelection 62 | 63 | UFUNCTION(BlueprintCallable) 64 | void SelectAllActorsWithSimilarName(); 65 | 66 | UPROPERTY(EditAnywhere,BlueprintReadWrite,Category = "ActorBatchSelection") 67 | TEnumAsByte SearchCase = ESearchCase::IgnoreCase; 68 | 69 | #pragma endregion 70 | 71 | #pragma region ActorBatchDuplication 72 | 73 | UFUNCTION(BlueprintCallable) 74 | void DuplicateActors(); 75 | 76 | UPROPERTY(EditAnywhere,BlueprintReadWrite,Category = "ActorBatchDuplication") 77 | E_DuplicationAxis AxisForDuplication = E_DuplicationAxis::EDA_XAxis; 78 | 79 | UPROPERTY(EditAnywhere,BlueprintReadWrite,Category = "ActorBatchDuplication") 80 | int32 NumberOfDuplicates = 5; 81 | 82 | UPROPERTY(EditAnywhere,BlueprintReadWrite,Category = "ActorBatchDuplication") 83 | float OffsetDist = 300.f; 84 | 85 | #pragma endregion 86 | 87 | #pragma region RandomizeActorTransform 88 | 89 | UFUNCTION(BlueprintCallable) 90 | void RandomizeActorTransform(); 91 | 92 | UPROPERTY(EditAnywhere,BlueprintReadWrite,Category = "RandomizeActorTransform") 93 | FRandomActorRotation RandomActorRotation; 94 | 95 | UPROPERTY(EditAnywhere,BlueprintReadWrite,Category = "RandomizeActorTransform") 96 | bool bRandomizeScale = false; 97 | 98 | UPROPERTY(EditAnywhere,BlueprintReadWrite,Category = "RandomizeActorTransform",meta = (EditCondition = "bRandomizeScale")) 99 | float ScaleMin = .8f; 100 | 101 | UPROPERTY(EditAnywhere,BlueprintReadWrite,Category = "RandomizeActorTransform",meta = (EditCondition = "bRandomizeScale")) 102 | float ScaleMax = 1.2f; 103 | 104 | UPROPERTY(EditAnywhere,BlueprintReadWrite,Category = "RandomizeActorTransform") 105 | bool bRandomizeOffset = false; 106 | 107 | UPROPERTY(EditAnywhere,BlueprintReadWrite,Category = "RandomizeActorTransform",meta = (EditCondition = "bRandomizeOffset")) 108 | float OffsetMin = -50.f; 109 | 110 | UPROPERTY(EditAnywhere,BlueprintReadWrite,Category = "RandomizeActorTransform",meta = (EditCondition = "bRandomizeOffset")) 111 | float OffsetMax = 50.f; 112 | 113 | #pragma endregion 114 | 115 | private: 116 | UPROPERTY() 117 | class UEditorActorSubsystem* EditorActorSubsystem; 118 | 119 | bool GetEditorActorSubsystem(); 120 | }; 121 | -------------------------------------------------------------------------------- /Plugins/SuperManager/Source/SuperManager/Public/AssetActions/QuickAssetAction.h: -------------------------------------------------------------------------------- 1 | // Copyright Vince Petrelli. Published in 2022.All rights reserved. 2 | 3 | #pragma once 4 | 5 | #include "CoreMinimal.h" 6 | #include "AssetActionUtility.h" 7 | 8 | #include "Materials/Material.h" 9 | #include "Materials/MaterialInstanceConstant.h" 10 | #include "Particles/ParticleSystem.h" 11 | #include "Sound/SoundCue.h" 12 | #include "Sound/SoundWave.h" 13 | #include "Engine/Texture.h" 14 | #include "Blueprint/UserWidget.h" 15 | #include "Components/SkeletalMeshComponent.h" 16 | #include "NiagaraSystem.h" 17 | #include "NiagaraEmitter.h" 18 | 19 | #include "QuickAssetAction.generated.h" 20 | 21 | /** 22 | * 23 | */ 24 | UCLASS() 25 | class SUPERMANAGER_API UQuickAssetAction : public UAssetActionUtility 26 | { 27 | GENERATED_BODY() 28 | 29 | public: 30 | UFUNCTION(CallInEditor) 31 | void DuplicateAssets(int32 NumOfDuplicates); 32 | 33 | UFUNCTION(CallInEditor) 34 | void AddPrefixes(); 35 | 36 | UFUNCTION(CallInEditor) 37 | void RemoveUnusedAssets(); 38 | 39 | private: 40 | TMapPrefixMap = 41 | { 42 | {UBlueprint::StaticClass(),TEXT("BP_")}, 43 | {UStaticMesh::StaticClass(),TEXT("SM_")}, 44 | {UMaterial::StaticClass(), TEXT("M_")}, 45 | {UMaterialInstanceConstant::StaticClass(),TEXT("MI_")}, 46 | {UMaterialFunctionInterface::StaticClass(), TEXT("MF_")}, 47 | {UParticleSystem::StaticClass(), TEXT("PS_")}, 48 | {USoundCue::StaticClass(), TEXT("SC_")}, 49 | {USoundWave::StaticClass(), TEXT("SW_")}, 50 | {UTexture::StaticClass(), TEXT("T_")}, 51 | {UTexture2D::StaticClass(), TEXT("T_")}, 52 | {UUserWidget::StaticClass(), TEXT("WBP_")}, 53 | {USkeletalMeshComponent::StaticClass(), TEXT("SK_")}, 54 | {UNiagaraSystem::StaticClass(), TEXT("NS_")}, 55 | {UNiagaraEmitter::StaticClass(), TEXT("NE_")} 56 | }; 57 | 58 | void FixUpRedirectors(); 59 | 60 | }; 61 | -------------------------------------------------------------------------------- /Plugins/SuperManager/Source/SuperManager/Public/AssetActions/QuickMaterialCreationWidget.h: -------------------------------------------------------------------------------- 1 | // Copyright Vince Petrelli. Published in 2022.All rights reserved. 2 | 3 | #pragma once 4 | 5 | #include "CoreMinimal.h" 6 | #include "EditorUtilityWidget.h" 7 | #include "QuickMaterialCreationWidget.generated.h" 8 | 9 | UENUM(BlueprintType) 10 | enum class E_ChannelPackingType : uint8 11 | { 12 | ECPT_NoChannelPacking UMETA (DisplayName = "No Channel Packing"), 13 | 14 | ECPT_ORM UMETA (DisplayName = "OcclusionRoughnessMetallic"), 15 | 16 | ECPT_MAX UMETA (DisplayName = "DefaultMAX") 17 | }; 18 | /** 19 | * 20 | */ 21 | UCLASS() 22 | class SUPERMANAGER_API UQuickMaterialCreationWidget : public UEditorUtilityWidget 23 | { 24 | GENERATED_BODY() 25 | 26 | public: 27 | 28 | #pragma region QuickMaterialCreation 29 | 30 | UFUNCTION(BlueprintCallable) 31 | void CreateMaterialFromSelectedTextures(); 32 | 33 | UPROPERTY(EditAnywhere,BlueprintReadWrite,Category = "CreateMaterialFromSelectedTextures") 34 | E_ChannelPackingType ChannelPackingType = E_ChannelPackingType::ECPT_NoChannelPacking; 35 | 36 | UPROPERTY(EditAnywhere,BlueprintReadWrite,Category = "CreateMaterialFromSelectedTextures") 37 | bool bCustomMaterialName = true; 38 | 39 | UPROPERTY(EditAnywhere,BlueprintReadWrite,Category = "CreateMaterialFromSelectedTextures",meta = (EditCondition = "bCustomMaterialName")) 40 | FString MaterialName = TEXT("M_"); 41 | 42 | UPROPERTY(EditAnywhere,BlueprintReadWrite,Category = "CreateMaterialFromSelectedTextures") 43 | bool bCreateMaterialInstance = false; 44 | 45 | #pragma endregion 46 | 47 | #pragma region SupportedTextureNames 48 | 49 | UPROPERTY(EditAnywhere,BlueprintReadWrite,Category = "Supported Texture Names") 50 | TArray BaseColorArray = { 51 | TEXT("_BaseColor"), 52 | TEXT("_Albedo"), 53 | TEXT("_Diffuse"), 54 | TEXT("_diff") 55 | }; 56 | 57 | UPROPERTY(EditAnywhere,BlueprintReadWrite,Category = "Supported Texture Names") 58 | TArray MetallicArray = { 59 | TEXT("_Metallic"), 60 | TEXT("_metal") 61 | }; 62 | 63 | UPROPERTY(EditAnywhere,BlueprintReadWrite,Category = "Supported Texture Names") 64 | TArray RoughnessArray = { 65 | TEXT("_Roughness"), 66 | TEXT("_RoughnessMap"), 67 | TEXT("_rough") 68 | }; 69 | 70 | UPROPERTY(EditAnywhere,BlueprintReadWrite,Category = "Supported Texture Names") 71 | TArray NormalArray = { 72 | TEXT("_Normal"), 73 | TEXT("_NormalMap"), 74 | TEXT("_nor") 75 | }; 76 | 77 | UPROPERTY(EditAnywhere,BlueprintReadWrite,Category = "Supported Texture Names") 78 | TArray AmbientOcclusionArray = { 79 | TEXT("_AmbientOcclusion"), 80 | TEXT("_AmbientOcclusionMap"), 81 | TEXT("_AO") 82 | }; 83 | 84 | UPROPERTY(EditAnywhere,BlueprintReadWrite,Category = "Supported Texture Names") 85 | TArray ORMArray = { 86 | TEXT("_arm"), 87 | TEXT("_OcclusionRoughnessMetallic"), 88 | TEXT("_ORM") 89 | }; 90 | 91 | #pragma endregion 92 | 93 | private: 94 | 95 | #pragma region QuickMaterialCreationCore 96 | 97 | bool ProcessSelectedData(const TArray& SelectedDataToProccess, TArray& OutSelectedTexturesArray,FString& OutSelectedTexturePackagePath); 98 | bool CheckIsNameUsed(const FString& FolderPathToCheck, const FString& MaterialNameToCheck); 99 | UMaterial* CreateMaterialAsset(const FString& NameOfTheMaterial, const FString& PathToPutMaterial); 100 | void Default_CreateMaterialNodes(UMaterial* CreatedMaterial,UTexture2D* SelectedTexture,uint32& PinsConnectedCounter); 101 | void ORM_CreateMaterialNodes(UMaterial* CreatedMaterial,UTexture2D* SelectedTexture,uint32& PinsConnectedCounter); 102 | 103 | #pragma endregion 104 | 105 | #pragma region CreateMaterialNodesConnectPins 106 | 107 | bool TryConnectBaseColor(UMaterialExpressionTextureSample* TextureSampleNode,UTexture2D* SelectedTexture,UMaterial* CreatedMaterial); 108 | bool TryConnectMetalic(UMaterialExpressionTextureSample* TextureSampleNode,UTexture2D* SelectedTexture,UMaterial* CreatedMaterial); 109 | bool TryConnectRoughness(UMaterialExpressionTextureSample* TextureSampleNode,UTexture2D* SelectedTexture,UMaterial* CreatedMaterial); 110 | bool TryConnectNormal(UMaterialExpressionTextureSample* TextureSampleNode,UTexture2D* SelectedTexture,UMaterial* CreatedMaterial); 111 | bool TryConnectAO(UMaterialExpressionTextureSample* TextureSampleNode,UTexture2D* SelectedTexture,UMaterial* CreatedMaterial); 112 | bool TryConnectORM(UMaterialExpressionTextureSample* TextureSampleNode,UTexture2D* SelectedTexture,UMaterial* CreatedMaterial); 113 | 114 | #pragma endregion 115 | 116 | class UMaterialInstanceConstant* CreateMaterialInstanceAsset(UMaterial* CreatedMaterial,FString NameOfMaterialInstance,const FString& PathToPutMI); 117 | }; 118 | -------------------------------------------------------------------------------- /Plugins/SuperManager/Source/SuperManager/Public/CustomOutlinerColumn/OutlinerSelectionLockColumn.h: -------------------------------------------------------------------------------- 1 | // Copyright Vince Petrelli. Published in 2022.All rights reserved. 2 | 3 | #pragma once 4 | 5 | #include "ISceneOutlinerColumn.h" 6 | 7 | class FOutlinerSelectionLockColumn : public ISceneOutlinerColumn 8 | { 9 | public: 10 | FOutlinerSelectionLockColumn(ISceneOutliner& SceneOutliner){} 11 | 12 | virtual FName GetColumnID() override {return FName("SelectionLock");} 13 | 14 | static FName GetID() {return FName("SelectionLock");} 15 | 16 | virtual SHeaderRow::FColumn::FArguments ConstructHeaderRowColumn() override; 17 | 18 | virtual const TSharedRef< SWidget > ConstructRowWidget(FSceneOutlinerTreeItemRef TreeItem, const STableRow& Row) override; 19 | 20 | private: 21 | void OnRowWdigetCheckStateChanged(ECheckBoxState NewState, TWeakObjectPtr CorrespondingActor); 22 | }; -------------------------------------------------------------------------------- /Plugins/SuperManager/Source/SuperManager/Public/CustomStyle/SuperManagerStyle.h: -------------------------------------------------------------------------------- 1 | // Copyright Vince Petrelli. Published in 2022.All rights reserved. 2 | 3 | #pragma once 4 | 5 | #include "Styling/SlateStyle.h" 6 | 7 | 8 | class FSuperManagerStyle 9 | { 10 | public: 11 | static void InitializeIcons(); 12 | static void ShutDown(); 13 | 14 | private: 15 | static FName StyleSetName; 16 | 17 | static TSharedRef CreateSlateStyleSet(); 18 | static TSharedPtr CreatedSlateStyleSet; 19 | 20 | public: 21 | static FName GetStyleSetName(){return StyleSetName;} 22 | 23 | static TSharedRef GetCreatedSlateStyleSet() {return CreatedSlateStyleSet.ToSharedRef(); } 24 | }; -------------------------------------------------------------------------------- /Plugins/SuperManager/Source/SuperManager/Public/CustomUICommands/SuperManagerUICommands.h: -------------------------------------------------------------------------------- 1 | // Copyright Vince Petrelli. Published in 2022.All rights reserved. 2 | 3 | #pragma once 4 | 5 | #include "Framework/Commands/Commands.h" 6 | 7 | 8 | class FSuperManagerUICommands : public TCommands 9 | { 10 | public: 11 | FSuperManagerUICommands() : TCommands( 12 | TEXT("SuperManager"), 13 | FText::FromString(TEXT("Super Manager UI Commands")), 14 | NAME_None, 15 | TEXT("SuperManager") 16 | ) {} 17 | 18 | virtual void RegisterCommands() override; 19 | 20 | TSharedPtr LockActorSelection; 21 | TSharedPtr UnlockActorSelection; 22 | }; 23 | -------------------------------------------------------------------------------- /Plugins/SuperManager/Source/SuperManager/Public/DebugHeader.h: -------------------------------------------------------------------------------- 1 | // Copyright Vince Petrelli. Published in 2022.All rights reserved. 2 | #pragma once 3 | 4 | #include "Misc/MessageDialog.h" 5 | #include "Widgets/Notifications/SNotificationList.h" 6 | #include "Framework/Notifications/NotificationManager.h" 7 | 8 | namespace DebugHeader 9 | { 10 | static void Print(const FString& Message, const FColor& Color) 11 | { 12 | if(GEngine) 13 | { 14 | GEngine->AddOnScreenDebugMessage(-1, 8.f, Color, Message); 15 | } 16 | } 17 | 18 | static void PrintLog(const FString& Message) 19 | { 20 | UE_LOG(LogTemp, Warning, TEXT("%s"), *Message); 21 | } 22 | 23 | static EAppReturnType::Type ShowMsgDialog(EAppMsgType::Type MsgType, const FString& Message, 24 | bool bShowMsgAsWarning = true) 25 | { 26 | if(bShowMsgAsWarning) 27 | { 28 | FText MsgTitle = FText::FromString(TEXT("Warning")); 29 | 30 | return FMessageDialog::Open(MsgType, FText::FromString(Message), &MsgTitle); 31 | } 32 | else 33 | { 34 | return FMessageDialog::Open(MsgType, FText::FromString(Message)); 35 | } 36 | } 37 | 38 | static void ShowNotifyInfo(const FString& Message) 39 | { 40 | FNotificationInfo NotifyInfo(FText::FromString(Message)); 41 | NotifyInfo.bUseLargeFont = true; 42 | NotifyInfo.FadeOutDuration = 7.f; 43 | 44 | FSlateNotificationManager::Get().AddNotification(NotifyInfo); 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /Plugins/SuperManager/Source/SuperManager/Public/SlateWidgets/AdvanceDeletionWidget.h: -------------------------------------------------------------------------------- 1 | // Copyright Vince Petrelli. Published in 2022.All rights reserved. 2 | 3 | #pragma once 4 | 5 | #include "Widgets/SCompoundWidget.h" 6 | 7 | class SAdvanceDeletionTab : public SCompoundWidget 8 | { 9 | SLATE_BEGIN_ARGS(SAdvanceDeletionTab) {} 10 | 11 | SLATE_ARGUMENT(TArray< TSharedPtr >,AssetsDataToStore) 12 | 13 | SLATE_ARGUMENT(FString,CurrentSelectedFolder) 14 | 15 | SLATE_END_ARGS() 16 | 17 | public: 18 | void Construct(const FArguments& InArgs); 19 | 20 | private: 21 | TArray< TSharedPtr > StoredAssetsData; 22 | TArray< TSharedPtr > DisplayedAssetsData; 23 | TArray< TSharedRef > CheckBoxesArray; 24 | TArray< TSharedPtr < FAssetData> > AssetsDataToDeleteArray; 25 | 26 | TSharedRef< SListView< TSharedPtr > > ConstructAssetListView(); 27 | TSharedPtr< SListView< TSharedPtr > > ConstructedAssetListView; 28 | void RefreshAssetListView(); 29 | 30 | #pragma region ComboBoxForListingCondition 31 | 32 | TSharedRef< SComboBox < TSharedPtr > > ConstructComboBox(); 33 | 34 | TArray< TSharedPtr > ComboBoxSourceItems; 35 | 36 | TSharedRef OnGenerateComboContent(TSharedPtr SourceItem); 37 | 38 | void OnComboSelectionChanged(TSharedPtr SelectedOption,ESelectInfo::Type InSelectInfo); 39 | 40 | TSharedPtr ComboDiplayTextBlock; 41 | 42 | TSharedRef ConstructComboHelpTexts(const FString& TextContent, ETextJustify::Type TextJustify); 43 | 44 | #pragma endregion 45 | 46 | 47 | #pragma region RowWidgetForAssetListView 48 | 49 | TSharedRef OnGenerateRowForList(TSharedPtr AssetDataToDisplay,const TSharedRef& OwnerTable); 50 | 51 | void OnRowWidgetMoustButtonClicked(TSharedPtr ClickedData); 52 | 53 | TSharedRef ConstructCheckBox(const TSharedPtr& AssetDataToDisplay); 54 | void OnCheckBoxStateChanged(ECheckBoxState NewState, TSharedPtr AssetData); 55 | 56 | TSharedRef ConstructTextForRowWidget(const FString& TextContent, const FSlateFontInfo& FontToUse); 57 | 58 | TSharedRef ConstructButtonForRowWidget(const TSharedPtr& AssetDataToDisplay); 59 | FReply OnDeleteButtonClicked(TSharedPtr ClickedAssetData); 60 | 61 | #pragma endregion 62 | 63 | #pragma region TabButtons 64 | 65 | TSharedRef ConstructDeleteAllButton(); 66 | TSharedRef ConstructSelectAllButton(); 67 | TSharedRef ConstructDeselectAllButton(); 68 | 69 | FReply OnDeleteAllButtonClicked(); 70 | FReply OnSelectAllButtonClicked(); 71 | FReply OnDeselectAllButtonClicked(); 72 | 73 | TSharedRef ConstructTextForTabButtons(const FString& TextContent); 74 | 75 | #pragma endregion 76 | 77 | 78 | 79 | FSlateFontInfo GetEmboseedTextFont() const {return FCoreStyle::Get().GetFontStyle(FName("EmbossedText"));} 80 | }; 81 | -------------------------------------------------------------------------------- /Plugins/SuperManager/Source/SuperManager/Public/SuperManager.h: -------------------------------------------------------------------------------- 1 | // Copyright Vince Petrelli. Published in 2022.All rights reserved. 2 | 3 | #pragma once 4 | 5 | #include "CoreMinimal.h" 6 | #include "Modules/ModuleManager.h" 7 | 8 | class FSuperManagerModule : public IModuleInterface 9 | { 10 | public: 11 | 12 | /** IModuleInterface implementation */ 13 | virtual void StartupModule() override; 14 | virtual void ShutdownModule() override; 15 | 16 | private: 17 | 18 | #pragma region ContentBrowserMenuExtention 19 | 20 | void InitCBMenuExtention(); 21 | 22 | TArray FolderPathsSelected; 23 | 24 | TSharedRef CustomCBMenuExtender(const TArray& SelectedPaths); 25 | 26 | void AddCBMenuEntry(class FMenuBuilder& MenuBuilder); 27 | 28 | void OnDeleteUnsuedAssetButtonClicked(); 29 | void OnDeleteEmptyFoldersButtonClicked(); 30 | void OnAdvanceDeletionButtonClicked(); 31 | 32 | void FixUpRedirectors(); 33 | 34 | #pragma endregion 35 | 36 | #pragma region CustomEditorTab 37 | 38 | void RegisterAdvanceDeletionTab(); 39 | 40 | TSharedRef OnSpawnAdvanceDeletionTab(const FSpawnTabArgs& SpawnTabArgs); 41 | TSharedPtr ConstructedDockTab; 42 | 43 | TArray< TSharedPtr > GetAllAssetDataUnderSelectedFolder(); 44 | 45 | void OnAdvanceDeletionTabClosed(TSharedRef TabToClose); 46 | 47 | #pragma endregion 48 | 49 | #pragma region LevelEditorMenuExtension 50 | 51 | void InitLevelEditorExtention(); 52 | 53 | TSharedRef CustomLevelEditorMenuExtender(const TSharedRef UICommandList, const TArray SelectedActors); 54 | 55 | void AddLevelEditorMenuEntry(class FMenuBuilder& MenuBuilder); 56 | 57 | void OnLockActorSelectionButtonClicked(); 58 | void OnUnlockActorSelectionButtonClicked(); 59 | 60 | #pragma endregion 61 | 62 | #pragma region SelectionLock 63 | 64 | void InitCustomSelectionEvent(); 65 | 66 | void OnActorSelected(UObject* SelectedObject); 67 | 68 | void LockActorSelection(AActor* ActorToProcess); 69 | void UnlockActorSelection(AActor* ActorToProcess); 70 | 71 | void RefreshSceneOutliner(); 72 | 73 | #pragma endregion 74 | 75 | #pragma region CustomEditorUICommands 76 | 77 | TSharedPtr CustomUICommands; 78 | 79 | void InitCustomUICommands(); 80 | 81 | void OnSelectionLockHotKeyPressed(); 82 | void OnUnlockActorSelectionHotKeyPressed(); 83 | 84 | #pragma endregion 85 | 86 | #pragma region SceneOutlinerExtension 87 | 88 | void InitSceneOutlinerColumnExtension(); 89 | 90 | TSharedRef OnCreateSelectionLockColumn(class ISceneOutliner& SceneOutliner); 91 | 92 | void UnRegisterSceneOutlinerColumnExtension(); 93 | 94 | #pragma endregion 95 | 96 | TWeakObjectPtr WeakEditorActorSubsystem; 97 | 98 | bool GetEditorActorSubsystem(); 99 | 100 | public: 101 | 102 | #pragma region ProccessDataForAdvanceDeletionTab 103 | 104 | bool DeleteSingleAssetForAssetList(const FAssetData& AssetDataToDelete); 105 | bool DeleteMultipleAssetsForAssetList(const TArray& AssetsToDelete); 106 | void ListUnusedAssetsForAssetList(const TArray< TSharedPtr >& AssetsDataToFilter,TArray< TSharedPtr >& OutUnusedAssetsData); 107 | void ListSameNameAssetsForAssetList(const TArray< TSharedPtr >& AssetsDataToFilter, TArray< TSharedPtr >& OutSameNameAssetsData); 108 | void SyncCBToClickedAssetForAssetList(const FString& AssetPathToSync); 109 | 110 | #pragma endregion 111 | 112 | bool CheckIsActorSelectionLocked(AActor* ActorToProcess); 113 | void ProcessLockingForOutliner(AActor* ActorToProcess,bool bShouldLock); 114 | 115 | }; 116 | -------------------------------------------------------------------------------- /Plugins/SuperManager/Source/SuperManager/SuperManager.Build.cs: -------------------------------------------------------------------------------- 1 | // Copyright Epic Games, Inc. All Rights Reserved. 2 | 3 | using UnrealBuildTool; 4 | 5 | public class SuperManager : ModuleRules 6 | { 7 | public SuperManager(ReadOnlyTargetRules Target) : base(Target) 8 | { 9 | PCHUsage = ModuleRules.PCHUsageMode.UseExplicitOrSharedPCHs; 10 | 11 | PublicIncludePaths.AddRange( 12 | new string[] { 13 | // ... add public include paths required here ... 14 | } 15 | ); 16 | 17 | 18 | PrivateIncludePaths.AddRange( 19 | new string[] { 20 | System.IO.Path.GetFullPath(Target.RelativeEnginePath) + "/Source/Editor/Blutility/Private" 21 | } 22 | ); 23 | 24 | 25 | PublicDependencyModuleNames.AddRange( 26 | new string[] 27 | { 28 | "Core","Blutility","EditorScriptingUtilities","UMG","Niagara","UnrealEd","AssetTools", 29 | "ContentBrowser","InputCore","Projects","SceneOutliner" 30 | // ... add other public dependencies that you statically link with here ... 31 | } 32 | ); 33 | 34 | 35 | PrivateDependencyModuleNames.AddRange( 36 | new string[] 37 | { 38 | "CoreUObject", 39 | "Engine", 40 | "Slate", 41 | "SlateCore", 42 | // ... add private dependencies that you statically link with here ... 43 | } 44 | ); 45 | 46 | 47 | DynamicallyLoadedModuleNames.AddRange( 48 | new string[] 49 | { 50 | // ... add any modules that your module loads dynamically here ... 51 | } 52 | ); 53 | } 54 | } 55 | -------------------------------------------------------------------------------- /Plugins/SuperManager/SuperManager.uplugin: -------------------------------------------------------------------------------- 1 | { 2 | "FileVersion": 3, 3 | "Version": 1, 4 | "VersionName": "1.0", 5 | "FriendlyName": "SuperManager", 6 | "Description": "", 7 | "Category": "Other", 8 | "CreatedBy": "", 9 | "CreatedByURL": "", 10 | "DocsURL": "", 11 | "MarketplaceURL": "", 12 | "SupportURL": "", 13 | "CanContainContent": true, 14 | "IsBetaVersion": false, 15 | "IsExperimentalVersion": false, 16 | "Installed": false, 17 | "Modules": [ 18 | { 19 | "Name": "SuperManager", 20 | "Type": "Editor", 21 | "LoadingPhase": "PreDefault" 22 | } 23 | ] 24 | } -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # ExtendEditor 2 | 3 | Developed with Unreal Engine 5 4 | 5 | Copyright by Vince Petrelli All rights reserved 6 | 7 | All licenses in this repository are copyrighted by their respective author Vince Petrelli. 8 | No code should be used commercially without fees or permission by the author Vince Petrelli. See `LICENSE` for details. 9 | -------------------------------------------------------------------------------- /Source/ExtendEditor.Target.cs: -------------------------------------------------------------------------------- 1 | // Copyright Epic Games, Inc. All Rights Reserved. 2 | 3 | using UnrealBuildTool; 4 | using System.Collections.Generic; 5 | 6 | public class ExtendEditorTarget : TargetRules 7 | { 8 | public ExtendEditorTarget( TargetInfo Target) : base(Target) 9 | { 10 | Type = TargetType.Game; 11 | DefaultBuildSettings = BuildSettingsVersion.V2; 12 | ExtraModuleNames.AddRange( new string[] { "ExtendEditor" } ); 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /Source/ExtendEditor/ExtendEditor.Build.cs: -------------------------------------------------------------------------------- 1 | // Copyright Epic Games, Inc. All Rights Reserved. 2 | 3 | using UnrealBuildTool; 4 | 5 | public class ExtendEditor : ModuleRules 6 | { 7 | public ExtendEditor(ReadOnlyTargetRules Target) : base(Target) 8 | { 9 | PCHUsage = PCHUsageMode.UseExplicitOrSharedPCHs; 10 | 11 | PublicDependencyModuleNames.AddRange(new string[] { "Core", "CoreUObject", "Engine", "InputCore" }); 12 | 13 | PrivateDependencyModuleNames.AddRange(new string[] { }); 14 | 15 | // Uncomment if you are using Slate UI 16 | // PrivateDependencyModuleNames.AddRange(new string[] { "Slate", "SlateCore" }); 17 | 18 | // Uncomment if you are using online features 19 | // PrivateDependencyModuleNames.Add("OnlineSubsystem"); 20 | 21 | // To include OnlineSubsystemSteam, add it to the plugins section in your uproject file with the Enabled attribute set to true 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /Source/ExtendEditor/ExtendEditor.cpp: -------------------------------------------------------------------------------- 1 | // Copyright Epic Games, Inc. All Rights Reserved. 2 | 3 | #include "ExtendEditor.h" 4 | #include "Modules/ModuleManager.h" 5 | 6 | IMPLEMENT_PRIMARY_GAME_MODULE( FDefaultGameModuleImpl, ExtendEditor, "ExtendEditor" ); 7 | -------------------------------------------------------------------------------- /Source/ExtendEditor/ExtendEditor.h: -------------------------------------------------------------------------------- 1 | // Copyright Epic Games, Inc. All Rights Reserved. 2 | 3 | #pragma once 4 | 5 | #include "CoreMinimal.h" 6 | 7 | -------------------------------------------------------------------------------- /Source/ExtendEditor/ExtendEditorGameModeBase.cpp: -------------------------------------------------------------------------------- 1 | // Copyright Epic Games, Inc. All Rights Reserved. 2 | 3 | 4 | #include "ExtendEditorGameModeBase.h" 5 | 6 | -------------------------------------------------------------------------------- /Source/ExtendEditor/ExtendEditorGameModeBase.h: -------------------------------------------------------------------------------- 1 | // Copyright Epic Games, Inc. All Rights Reserved. 2 | 3 | #pragma once 4 | 5 | #include "CoreMinimal.h" 6 | #include "GameFramework/GameModeBase.h" 7 | #include "ExtendEditorGameModeBase.generated.h" 8 | 9 | /** 10 | * 11 | */ 12 | UCLASS() 13 | class EXTENDEDITOR_API AExtendEditorGameModeBase : public AGameModeBase 14 | { 15 | GENERATED_BODY() 16 | 17 | }; 18 | -------------------------------------------------------------------------------- /Source/ExtendEditorEditor.Target.cs: -------------------------------------------------------------------------------- 1 | // Copyright Epic Games, Inc. All Rights Reserved. 2 | 3 | using UnrealBuildTool; 4 | using System.Collections.Generic; 5 | 6 | public class ExtendEditorEditorTarget : TargetRules 7 | { 8 | public ExtendEditorEditorTarget( TargetInfo Target) : base(Target) 9 | { 10 | Type = TargetType.Editor; 11 | DefaultBuildSettings = BuildSettingsVersion.V2; 12 | ExtraModuleNames.AddRange( new string[] { "ExtendEditor" } ); 13 | } 14 | } 15 | --------------------------------------------------------------------------------