[UE4]Editor Extention and Programming
Keywords: UE4, Editor Extention and Programming
Documents
Documents - Fragments
UE4 - Easy example of How to create menus in the editor
http://www.danielmayor.com/ue4-simple-menus
Creating an Editor Module
https://wiki.unrealengine.com/Creating_an_Editor_Module
Customizing the editor’s toolbar buttons menu via custom plugin
https://answers.unrealengine.com/questions/25609/customizing-the-editors-toolbar-buttons-menu-via-c.html
UE4 Editor Toolbar Extention
https://blog.csdn.net/hui211314ddhui/article/details/79375548
batch operations with editor utility blueprints in UE4
https://www.youtube.com/watch?v=5Ty_rQp34PQ
Unreal’s Property Specifiers
https://benui.ca/unreal/uproperty/
Editor Programming Related
How to set display index / order of property in Editor
e.g.
UPROPERTY(EditAnywhere, BlueprintReadWrite, meta = (DisplayPriority = "1"))
int32 Value1 = -1;
UPROPERTY(EditAnywhere, BlueprintReadWrite, meta = (DisplayPriority = "2"))
int32 Value1 = -1;
Reference:
Metadata Specifiers
https://docs.unrealengine.com/en-US/Programming/UnrealArchitecture/Reference/Metadata/index.html
Editor Event
Properties changed event
#if WITH_EDITOR
virtual void PostEditChangeProperty(FPropertyChangedEvent& PropertyChangedEvent) override;
#endif
Actor moved event
#if WITH_EDITOR
/** Called after an actor has been moved in the editor */
virtual void PostEditMove(bool bFinished);
#endif
How to customize Transform of Actor in Editor
Header: Add VisibleAnywhere
on properties.
UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Category = CameraEvent)
UBoxComponent* BoxComp;
UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Category = CameraEvent)
UArrowComponent* DirectionComp;
Constructor:
BoxComp = CreateDefaultSubobject<UBoxComponent>(TEXT("BoxComp"));
BoxComp->SetupAttachment(GetDefaultAttachComponent());
DirectionComp = CreateDefaultSubobject<UArrowComponent>(TEXT("TriggerDirectionComp"));
DirectionComp->SetupAttachment(BoxComp);
In Bluerpint Editor:
In Level Editor:
In Bluerpint Editor, you can’t modify Location and Rotation of RootComponent, but you can modify them in Level Editor.
How to spawn actor in Editor (Level Editor)
example:
AActor* newActor = GEditor->AddActor(
GEditor->GetLevelViewportClients()[0]->GetWorld()->GetCurrentLevel(), AMyActorClass, MyTransform);
// modify properties on newActor
newActor->RerunConstructionScripts();
How to limit the lenght of array in Actor Blueprint editor.
Add EditFixedSize
in the property:
UPROPERTY(EditDefaultsOnly, BlueprintReadOnly, Category = "Config", EditFixedSize)
TArray<int32> IdList;
Then initilize array in constructor.
AMyActor::AMyActor()
{
IdList.Init(0, 5);
}
How to creat editor widget using C++
UE4 – C++ Editor Utility Widgets (4.22)
https://isaratech.com/ue4-c-editor-utility-widgets-4-22/
Issue:
Blueprint EditorUtilityWidget
Can’t inherit custom cpp class.
Solution:
Modify MyPlugin.uplugin
.
Origin:
"Modules": [
{
"Name": "MyExtender",
"Type": "Runtime",
"LoadingPhase": "Default"
}
]
New:
"Modules": [
{
"Name": "MyExtender",
"Type": "Editor",
"LoadingPhase": "PostEngineInit"
}
]
Then delete all intermediate files and re-generate project files.
How to open the Windows file explorer (open directory dialog) to select the file
Example:
void UMyUserWidget::OnTestBtnClicked()
{
TSharedPtr<SWindow> ParentWindow = FSlateApplication::Get().FindWidgetWindow(TakeWidget());
void* ParentWindowHandle = (ParentWindow.IsValid() && ParentWindow->GetNativeWindow().IsValid()) ? ParentWindow->GetNativeWindow()->GetOSWindowHandle() : nullptr;
IDesktopPlatform* DesktopPlatform = FDesktopPlatformModule::Get();
if (DesktopPlatform)
{
const FString ContentDireAbsolute = FPaths::ConvertRelativePathToFull(FPaths::ProjectConfigDir());
FString OutDire;
DesktopPlatform->OpenDirectoryDialog(ParentWindowHandle, TEXT("Choose Folder"), ContentDireAbsolute, OutDire);
GEngine->AddOnScreenDebugMessage(-1, 10.f, FColor::Cyan, OutDire);
}
}
Select files dialog:
/*
* Opens a file dialog for the specified data. Leave FileTypes empty to be able to select any files.
* Filetypes must be in the format of: <File type Description>|*.<actual extension>
* You can combine multiple extensions by placing ";" between them
* For example: Text Files|*.txt|Excel files|*.csv|Image Files|*.png;*.jpg;*.bmp will display 3 lines for 3 different type of files.
*/
TArray<FString> OutFileNames;
//Opening the file picker!
uint32 SelectionFlag = 0; //A value of 0 represents single file selection while a value of 1 represents multiple file selection
DesktopPlatform->OpenFileDialog(ParentWindowHandle, DialogTitle, DefaultPath, FString(""), FileTypes, SelectionFlag, OutFileNames);
Reference
https://www.orfeasel.com/creating-a-file-picker/
How to add customized tips bar in editor
Quoted from Engine\Source\Runtime\Engine\Private\ShaderCompiler\ShaderCompiler.cpp
FText StatusUpdate;
if ( MaterialName != NULL )
{
FFormatNamedArguments Args;
Args.Add( TEXT("MaterialName"), FText::FromString( MaterialName ) );
StatusUpdate = FText::Format( NSLOCTEXT("ShaderCompilingManager", "CompilingShadersForMaterialStatus", "Compiling shaders: {MaterialName}..."), Args );
}
else
{
StatusUpdate = NSLOCTEXT("ShaderCompilingManager", "CompilingShadersStatus", "Compiling shaders...");
}
FScopedSlowTask SlowTask(1, StatusUpdate, GIsEditor && !IsRunningCommandlet());
SlowTask.EnterProgressFrame(1);
How to add customized progress bar in editor
Begin:
FText Description = NSLOCTEXT("UnrealEd", "PerformingCSGOperation", "Performing CSG operation");
GWarn->BeginSlowTask( Description, true );
End:
GWarn->EndSlowTask();
References: UHCsgUtils::ComposeBrushCSG in HoudiniEngine
How to load asset data in a batch.
1st way: AssetRegistryModule
static const FName AssetRegistryName(TEXT("AssetRegistry"));
FAssetRegistryModule& AssetRegistryModule = FModuleManager::LoadModuleChecked<FAssetRegistryModule>(AssetRegistryName);
IAssetRegistry& AssetRegistry = AssetRegistryModule.Get();
AssetRegistry.GetAssetsByClass(UMaterial::StaticClass()->GetFName(), AssetDataArray, true);
AssetRegistry.GetAssetsByClass(UMaterialInstance::StaticClass()->GetFName(), AssetDataArray, true);
Example: SMaterialAnalyzer::BuildBasicMaterialTree()
2nd way: ObjectLibrary
const auto ObjectLibrary = UObjectLibrary::CreateLibrary(UMaterialInterface::StaticClass(), false, true);
ObjectLibrary->LoadAssetDataFromPath(TEXT("/Game/TestAssets"));
TArray<FAssetData> AssetDatas;
ObjectLibrary->GetAssetDataList(AssetDatas);
for(auto& Data : AssetDatas)
{
UObject* Obj = Data.GetAsset();
UClass* AssetClass = Data.GetClass();
if(const UMaterialInterface* Material = Cast<UMaterialInterface>(Obj))
{
}
}
How to draw debug line in Animation Editor’s viewport.
Example from FKawaiiPhysicsEditMode::Render():
void FKawaiiPhysicsEditMode::Render(const FSceneView* View, FViewport* Viewport, FPrimitiveDrawInterface* PDI)
{
const USkeletalMeshComponent* SkelMeshComp = GetAnimPreviewScene().GetPreviewMeshComponent();
#if ENGINE_MAJOR_VERSION == 5 && ENGINE_MINOR_VERSION >= 1
if (SkelMeshComp && SkelMeshComp->GetSkeletalMeshAsset() && SkelMeshComp->GetSkeletalMeshAsset()->GetSkeleton())
#else
if (SkelMeshComp && SkelMeshComp->SkeletalMesh && SkelMeshComp->SkeletalMesh->GetSkeleton())
#endif
{
RenderSphericalLimits(PDI);
RenderCapsuleLimit(PDI);
RenderPlanerLimit(PDI);
PDI->SetHitProxy(nullptr);
if (IsValidSelectCollision())
{
FCollisionLimitBase* Collision = GetSelectCollisionLimitRuntime();
if (Collision)
{
FTransform BoneTransform = FTransform::Identity;
if (Collision->DrivingBone.BoneIndex >= 0)
{
BoneTransform = RuntimeNode->ForwardedPose.GetComponentSpaceTransform(
Collision->DrivingBone.GetCompactPoseIndex(RuntimeNode->ForwardedPose.GetPose().GetBoneContainer()));
}
PDI->DrawPoint(BoneTransform.GetLocation(), FLinearColor::White, 10.0f, SDPG_Foreground);
DrawDashedLine(PDI, Collision->Location, BoneTransform.GetLocation(),
FLinearColor::White, 1, SDPG_Foreground);
DrawCoordinateSystem(PDI, BoneTransform.GetLocation(), Collision->Rotation.Rotator(), 20, SDPG_World + 1);
}
}
}
#if ENGINE_MAJOR_VERSION == 5
FAnimNodeEditMode::Render(View, Viewport, PDI);
#else
FKawaiiPhysicsEditModeBase::Render(View, Viewport, PDI);
#endif
}
How to write a C++ blueprint function with pass-by-reference paramters
Example:
// Use existing data, add some more
UFUNCTION(BlueprintCallable)
void UseAndFillDogInfo(
UPARAM(ref) FDogInfo& SearchParams);
Unreal’s UPARAM parameter
https://benui.ca/unreal/uparam/
Testing & Optimization
Testing Automation
Automation System Overview, Overview of the automation system used for unit testing, feature testing, and content stress testing.
https://docs.unrealengine.com/4.27/en-US/TestingAndOptimization/Automation/
静水流深(Still Water Runs Deep) ---拉丁谚语