96 lines
2.9 KiB
C++
96 lines
2.9 KiB
C++
#pragma once
|
|
|
|
#include "CoreMinimal.h"
|
|
#include "MCPHandler.h"
|
|
#include "MCPAssets.h"
|
|
#include "MCPUtils.h"
|
|
#include "Materials/Material.h"
|
|
#include "Materials/MaterialInterface.h"
|
|
#include "Materials/MaterialInstanceConstant.h"
|
|
#include "Material_ReparentInstance.generated.h"
|
|
|
|
|
|
// ---------------------------------------------------------------------------
|
|
// ---------------------------------------------------------------------------
|
|
// ---------------------------------------------------------------------------
|
|
|
|
UCLASS()
|
|
class UMCP_Material_ReparentInstance : public UObject, public IMCPHandler
|
|
{
|
|
GENERATED_BODY()
|
|
|
|
public:
|
|
UPROPERTY(meta=(Description="Material Instance name or path to reparent"))
|
|
FString MaterialInstance;
|
|
|
|
UPROPERTY(meta=(Description="New parent material name or path (Material or Material Instance)"))
|
|
FString NewParent;
|
|
|
|
UPROPERTY(meta=(Optional, Description="If true, validate without applying changes"))
|
|
bool DryRun = false;
|
|
|
|
virtual FString GetDescription() const override
|
|
{
|
|
return TEXT("Change the parent material of a Material Instance. "
|
|
"Validates against circular parent chains.");
|
|
}
|
|
|
|
virtual void Handle(const FJsonObject* Json, FStringBuilderBase& Result) override
|
|
{
|
|
// Load the Material Instance
|
|
MCPAssets<UMaterialInstanceConstant> Assets;
|
|
if (!Assets.Exact(MaterialInstance).Errors(Result).ENone().ETwo().Load()) return;
|
|
UMaterialInstanceConstant* MI = Assets.Object();
|
|
|
|
// Load new parent (Material or MaterialInstance)
|
|
MCPAssets<UMaterialInterface> ParentAssets;
|
|
ParentAssets.NoScans();
|
|
ParentAssets.Scan<UMaterial>();
|
|
ParentAssets.Scan<UMaterialInstanceConstant>();
|
|
if (!ParentAssets.Exact(NewParent).Errors(Result).ENone().ETwo().Load()) return;
|
|
UMaterialInterface* NewParentObj = ParentAssets.Object();
|
|
|
|
// Prevent circular parenting
|
|
UMaterialInterface* Check = NewParentObj;
|
|
while (Check)
|
|
{
|
|
if (Check == MI)
|
|
{
|
|
Result.Appendf(TEXT("ERROR: Reparenting to '%s' would create a circular parent chain.\n"),
|
|
*NameOf(NewParentObj));
|
|
return;
|
|
}
|
|
UMaterialInstanceConstant* CheckMI = Cast<UMaterialInstanceConstant>(Check);
|
|
if (!CheckMI) break;
|
|
Check = CheckMI->Parent;
|
|
}
|
|
|
|
FString OldParentName = MI->Parent ? NameOf(MI->Parent) : TEXT("None");
|
|
|
|
if (DryRun)
|
|
{
|
|
Result.Appendf(TEXT("[DRY RUN] Would reparent %s: %s -> %s\n"),
|
|
*MCPUtils::FormatName(MI), *OldParentName, *NameOf(NewParentObj));
|
|
return;
|
|
}
|
|
|
|
MCPUtils::PreEdit({MI});
|
|
MI->Parent = NewParentObj;
|
|
MCPUtils::PostEdit({MI});
|
|
MCPUtils::SaveGenericPackage(MI);
|
|
|
|
Result.Appendf(TEXT("Reparented %s: %s -> %s\n"),
|
|
*MCPUtils::FormatName(MI), *OldParentName, *NameOf(NewParentObj));
|
|
}
|
|
|
|
private:
|
|
FString NameOf(UMaterialInterface* Obj)
|
|
{
|
|
if (UMaterial* M = Cast<UMaterial>(Obj))
|
|
return MCPUtils::FormatName(M);
|
|
if (UMaterialInstance* MI = Cast<UMaterialInstance>(Obj))
|
|
return MCPUtils::FormatName(MI);
|
|
return Obj->GetPathName();
|
|
}
|
|
};
|