UE4 switch材质节点

2024-3-26修改:

        经网友提醒,在将float返回值连接到if的输入节点时会报错,提示输入类型不是float类型,检查后发现,输入参数类型只检测了MCT_Float1-4,但是输入参数会识别为MCT_Float导致判断类型错误返回了INDEX_NONE,加入MCT_Float判断后解决

在实际项目中,很多次遇到在材质中需要根据index选择输出对应的数据,一个两个用if节点去连问题不大,但是数据量多了之后连起来就满眼的连线,乱的一塌糊涂,所以有了封装一个switch的想法,本质上还是if的嵌套实现,但是由代码层面去创建hlsl代码,不用在材质编辑器中连的乱七八糟了

注:这里只做了float1,float2,float3,float4的选择实现,其它的需要可以自行扩展,

     defResult为各种类别的0项,因为本质是做了循环的加法

     defResult的初始化不能省略,因为if判断里面对类别进行了判断,如果类别不符合会返回index_none

最终效果

materialSwitch

1.创建个插件,空白的就好,用来放我们的自定义节点相关的内容

2.创建switch的节点实现

MaterialExpressionSwitch.h

// Copyright 2022-2023 Ace Software. All Rights Reserved. Unauthorized copying of this file, via any medium is strictly prohibited

#pragma once

#include "CoreMinimal.h"
#include "Materials/MaterialExpression.h"
#include "MaterialExpressionIO.h"
#if WITH_EDITOR

#include "MaterialCompiler.h"
#include "MaterialGraph/MaterialGraphNode_Comment.h"
#include "MaterialGraph/MaterialGraphNode.h"
#endif //WITH_EDITOR
#include "MaterialExpressionSwitch.generated.h"

struct FPropertyChangedEvent;

/**
 * 
 */
UCLASS(collapsecategories, hidecategories=Object)
class ACEMATERIAL_API UMaterialExpressionSwitch : public UMaterialExpression
{
	GENERATED_UCLASS_BODY()
	UPROPERTY(EditAnywhere, Category=AceMaterial)
	TArray<FExpressionInput> Layers;
	
	UPROPERTY(EditAnywhere, Category=AceMaterial, meta=(OverridingInputProperty = "Index"))
	FExpressionInput Index;
	//~ Begin UMaterialExpression Interface
	#if WITH_EDITOR
	virtual void PostEditChangeProperty(FPropertyChangedEvent& PropertyChangedEvent) override;
	virtual int32 Compile(class FMaterialCompiler* Compiler, int32 OutputIndex) override;
	virtual void GetCaption(TArray<FString>& OutCaptions) const override;
	virtual const TArray<FExpressionInput*> GetInputs() override;
	virtual FName GetInputName(int32 InputIndex) const override;
	virtual FExpressionInput* GetInput(int32 InputIndex) override;
#endif // WITH_EDITOR
	//~ End UMaterialExpression Interface
};

MaterialExpressionSwitch.cpp

// Copyright 2022-2023 Ace Software. All Rights Reserved. Unauthorized copying of this file, via any medium is strictly prohibited


#include "MaterialExpressionSwitch.h"

#define LOCTEXT_NAMESPACE "MaterialExpression"

UMaterialExpressionSwitch::UMaterialExpressionSwitch(const FObjectInitializer& ObjectInitializer)
	: Super(ObjectInitializer)
{
	// Structure to hold one-time initialization
	struct FConstructorStatics
	{
		FText NAME_Math;
		FConstructorStatics()
			: NAME_Math(LOCTEXT("Switch", "Switch"))
		{
		}
	};
	static FConstructorStatics ConstructorStatics;
 
#if WITH_EDITORONLY_DATA
	MenuCategories.Add(ConstructorStatics.NAME_Math);
#endif
}
#if WITH_EDITOR

void UMaterialExpressionSwitch::GetCaption(TArray<FString>& OutCaptions) const
{
	OutCaptions.Add(TEXT("Switch"));
}

const TArray<FExpressionInput*> UMaterialExpressionSwitch::GetInputs()
{
	TArray<FExpressionInput*> Result;	
	for (int32 LayerIdx = 0; LayerIdx<Layers.Num(); LayerIdx++)
	{
		Result.Add(&Layers[LayerIdx]);
	}
	Result.Add(&Index);
	return Result;
}

FName UMaterialExpressionSwitch::GetInputName(int32 InputIndex) const
{
	if(InputIndex<Layers.Num())
	{
		return *FString::Printf(TEXT("Layer%d"), InputIndex);
	}
	return TEXT("Index");
}

FExpressionInput* UMaterialExpressionSwitch::GetInput(int32 InputIndex)
{
	if(InputIndex<Layers.Num())
		return &Layers[InputIndex];
	return  &Index;
}

void UMaterialExpressionSwitch::PostEditChangeProperty(FPropertyChangedEvent& PropertyChangedEvent)
{
	

	Super::PostEditChangeProperty(PropertyChangedEvent);
	if (UMaterialGraphNode* MatGraphNode = Cast<UMaterialGraphNode>(GraphNode))
	{
		MatGraphNode->RecreateAndLinkNode();
	}
	
}

int32 UMaterialExpressionSwitch::Compile(FMaterialCompiler* Compiler, int32 OutputIndex)
{
	int32 Result = Compiler->Constant(0);
	if(!Index.Expression)
	{
		return  Compiler->Errorf(TEXT("请输入选择的下标!!!"));
	}
	int32 indexCode=Index.Compile(Compiler);
	if(Compiler->GetType(indexCode)!=MCT_Float)
	{
		return  Compiler->Errorf(TEXT("value值需要输入数值,会向下取整!!!"));
	}
	if(Layers.Num()==0)
	{
		return  INDEX_NONE;
		//Result=Compiler->Errorf(TEXT("请添加需要选择的数据!!!"));
	}
	indexCode=Compiler->Floor(indexCode);
	int32 defResult;
	switch (Compiler->GetType(Layers[0].Compile(Compiler)))
	{
    case MCT_Float:
	case MCT_Float1:
		defResult=Compiler->Constant(0);
		break;
	case MCT_Float2:
		defResult=Compiler->Constant2(0,0);
		break;
	case MCT_Float3:
		defResult=Compiler->Constant3(0,0,0);
		break;
	case MCT_Float4:
		defResult=Compiler->Constant4(0,0,0,0);
		break;
	default:return  INDEX_NONE;
	}
	int thCode=Compiler->Constant(0.0001f);
	for (int32 i=0;i<Layers.Num();i++)
	{
		int32 tmpCode=Compiler->Floor(Compiler->Constant(i)) ;
		int32 layerCode=Layers[i].Compile(Compiler);
		int32 ifCode=Compiler->If(indexCode,tmpCode,defResult, layerCode,defResult,thCode);
		Result=Compiler->Add(Result, ifCode);
	}
	return Result;
}
 

#endif

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 4
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值