#pragma once #include "CoreMinimal.h" #include "MCPHandler.h" #include "MCPAssetFinder.h" #include "MCPUtils.h" #include "Materials/Material.h" #include "MaterialDomain.h" #include "Factories/MaterialFactoryNew.h" #include "AssetToolsModule.h" #include "IAssetTools.h" #include "Material_Create.generated.h" // --------------------------------------------------------------------------- // --------------------------------------------------------------------------- // --------------------------------------------------------------------------- UCLASS() class UMCP_Material_Create : public UObject, public IMCPHandler { GENERATED_BODY() public: UPROPERTY(meta=(Description="Name for the new material asset")) FString Name; UPROPERTY(meta=(Description="Package path where the asset will be created (must start with /Game)")) FString PackagePath; UPROPERTY(meta=(Optional, Description="Material domain: Surface, DeferredDecal, LightFunction, Volume, PostProcess, UI")) FString Domain; UPROPERTY(meta=(Optional, Description="Blend mode: Opaque, Masked, Translucent, Additive, Modulate")) FString BlendMode; UPROPERTY(meta=(Optional, Description="Whether the material is two-sided")) bool TwoSided = false; virtual FString GetDescription() const override { return TEXT("Create a new UMaterial asset with optional domain, blend mode, and two-sided settings."); } virtual void Handle(const FJsonObject* Json, FStringBuilderBase& Result) override { if (!PackagePath.StartsWith(TEXT("/Game"))) { Result.Append(TEXT("ERROR: PackagePath must start with '/Game'\n")); return; } // Parse optional enum properties before creating the asset. EMaterialDomain ParsedDomain = MD_Surface; if (!Domain.IsEmpty()) { if (!MCPUtils::StringToEnum(Domain, ParsedDomain, Result, TEXT("MD_"))) return; } EBlendMode ParsedBlendMode = BLEND_Opaque; if (!BlendMode.IsEmpty()) { if (!MCPUtils::StringToEnum(BlendMode, ParsedBlendMode, Result, TEXT("BLEND_"))) return; } // Check if an asset with this name already exists. MCPAssets ExistCheck; if (!ExistCheck.Exact(Name).Errors(Result).EAny().Info()) return; // Create via IAssetTools + factory. IAssetTools& AssetTools = FModuleManager::LoadModuleChecked("AssetTools").Get(); UMaterialFactoryNew* Factory = NewObject(); UObject* NewAsset = AssetTools.CreateAsset(Name, PackagePath, UMaterial::StaticClass(), Factory); UMaterial* MaterialObj = Cast(NewAsset); if (!MaterialObj) { Result.Appendf(TEXT("ERROR: Failed to create Material '%s' in '%s'\n"), *Name, *PackagePath); return; } // Apply optional properties. bool bHasTwoSided = Json->HasField(TEXT("twoSided")); TArray Chain = { MaterialObj }; MCPUtils::PreEdit(Chain); if (!Domain.IsEmpty()) MaterialObj->MaterialDomain = ParsedDomain; if (!BlendMode.IsEmpty()) MaterialObj->BlendMode = ParsedBlendMode; if (bHasTwoSided) MaterialObj->TwoSided = TwoSided; MCPUtils::PostEdit(Chain); bool bSaved = MCPUtils::SaveMaterialPackage(MaterialObj); Result.Appendf(TEXT("Created %s\n"), *MaterialObj->GetPathName()); Result.Appendf(TEXT("Domain: %s\n"), *MCPUtils::EnumToString(MaterialObj->MaterialDomain, TEXT("MD_"))); Result.Appendf(TEXT("BlendMode: %s\n"), *MCPUtils::EnumToString(MaterialObj->BlendMode, TEXT("BLEND_"))); Result.Appendf(TEXT("TwoSided: %s\n"), MaterialObj->TwoSided ? TEXT("true") : TEXT("false")); if (!bSaved) Result.Append(TEXT("WARNING: Package save failed\n")); } };