Files
UShaderLab/Source/UShaderLabEditor/Public/ShaderLabIntrinsicRegistry.h
2026-06-30 20:55:45 +08:00

91 lines
3.3 KiB
C++

// Copyright FlecsProj. All Rights Reserved.
#pragma once
#include "CoreMinimal.h"
class UMaterial;
class UMaterialExpression;
/** Shader stage an intrinsic is valid in (used to reject e.g. PixelDepth inside a Vertex body). */
enum class EShaderLabIntrinsicFrequency : uint8
{
Any,
PixelOnly,
VertexOnly,
};
/** One formal parameter of an intrinsic, used only to generate the IDE authoring stub signature. */
struct FShaderLabIntrinsicParam
{
/** HLSL type of the parameter, e.g. "int", "float". */
FString Type;
/** Parameter name shown in completion, e.g. "Index". */
FString Name;
/** Default-value literal for the stub (e.g. "1"); empty means the parameter is required. */
FString DefaultLiteral;
};
/**
* Describes one `UE::NodeName(...)` intrinsic: how to build the backing material expression node,
* which of its outputs to read, and what it requires of the material. The Custom-node input type is
* derived by the engine from the connected node's real output type, so no output type is declared here.
*
* The ReturnType/Params/Doc fields carry no runtime meaning — they exist so `ShaderLab.IDE.Prepare`
* can emit a `namespace UE { ... }` HLSL stub header from this single source of truth, giving the IDE
* member/signature completion for `UE::` calls without any drift from the real registration.
*/
struct FShaderLabIntrinsicDesc
{
FName Name;
/** Which output pin of the created node to connect (covers multi-output nodes like ObjectLocalBounds). */
int32 OutputIndex = 0;
/** Stage restriction; misuse is a build error. */
EShaderLabIntrinsicFrequency Frequency = EShaderLabIntrinsicFrequency::Any;
/** HLSL return type for the authoring stub, e.g. "float2"/"float3"/"float". Required (see Register). */
FString ReturnType;
/** Formal parameters for the authoring stub (empty for the common no-arg intrinsics). */
TArray<FShaderLabIntrinsicParam> Params;
/** Optional one-line doc surfaced as a comment above the stub. */
FString Doc;
/**
* Create the backing expression node and add it to `Material`'s expression collection. `ConstArgs`
* are the literal arguments parsed from the call (e.g. {"0","2.0"} for `UE::TextureCoordinate(0,2.0)`).
* Return nullptr and set `OutError` on a bad argument. Contract: this only runs in the editor/cook
* (graphs are editor-only); the cooked runtime never builds a graph.
*/
TFunction<UMaterialExpression*(UMaterial& /*Material*/, const TArray<FString>& /*ConstArgs*/, FString& /*OutError*/)> MakeNode;
};
/**
* Open registry mapping intrinsic names to descriptors. ShaderLab seeds its builtins on first use;
* other editor modules can register intrinsics for their own custom UMaterialExpression nodes from
* their StartupModule via Get().Register(...).
*/
class USHADERLABEDITOR_API FShaderLabIntrinsicRegistry
{
public:
static FShaderLabIntrinsicRegistry& Get();
/** Register (or override) an intrinsic. */
void Register(FShaderLabIntrinsicDesc Desc);
/** Lookup by name; nullptr if unknown. */
const FShaderLabIntrinsicDesc* Find(FName Name) const;
/** Visit every registered intrinsic (used by ShaderLab.IDE.Prepare to generate the UE:: stub header). */
void ForEach(TFunctionRef<void(const FShaderLabIntrinsicDesc&)> Fn) const;
private:
FShaderLabIntrinsicRegistry();
void RegisterBuiltins();
TMap<FName, FShaderLabIntrinsicDesc> Descs;
};