using System; using System.Collections.Generic; using System.Text; using System.Text.RegularExpressions; using UnityEngine; namespace UnityEditor.VFX.Block { [Flags] enum HLSLAccess { NONE = 0, IN = 1 << 0, OUT = 1 << 1, INOUT = IN | OUT, } interface IHLSMessage { string message { get; } VFXErrorType type { get; } } class HLSLAttributeError : IHLSMessage { private static readonly Dictionary s_ErrorMapping = new() { { VFXAttributeMode.Write, "writable" }, { VFXAttributeMode.Read, "readable" }, { VFXAttributeMode.ReadWrite, "readable and writable" }, { VFXAttributeMode.None, "found" }, }; public HLSLAttributeError(string name, VFXAttributeMode mode) { message = $"The attribute `{name}` is not {s_ErrorMapping[mode]}"; } public string message { get; } public VFXErrorType type => VFXErrorType.Error; } class HLSLVFXAttributeIsVariadic : IHLSMessage { private string attribute; public HLSLVFXAttributeIsVariadic(string attribute) { this.attribute = attribute; } public string message => $"Variadic attribute \"{attribute}\" is not supported in custom hlsl code, use {attribute}X, {attribute}Y or {attribute}Z"; public VFXErrorType type => VFXErrorType.Error; } class HLSLVFXAttributeAccessError : IHLSMessage { public string message => "Missing `inout` access modifier before the VFXAttributes type.\nNeeded because your code writes to at least one attribute."; public VFXErrorType type => VFXErrorType.Error; } class HLSLMissingVFXAttribute : IHLSMessage { public string message => "Missing `VFXAttributes attributes` as function's parameter"; public VFXErrorType type => VFXErrorType.Error; } class HLSLUnknownParameterType : IHLSMessage { public HLSLUnknownParameterType(string type) { message = $"Unknown parameter type '{type}'"; } public string message { get; } public VFXErrorType type => VFXErrorType.Error; } class HLSLUnsupportedAttributes : IHLSMessage { public HLSLUnsupportedAttributes(IEnumerable attributesName) { message = $"No VFXAttributes can be used here:\n\t{string.Join("\n\t", attributesName)}"; } public string message { get; } public VFXErrorType type => VFXErrorType.Error; } class HLSLVoidReturnTypeUnsupported : IHLSMessage { public HLSLVoidReturnTypeUnsupported(string functionName) { message = $"HLSL function '{functionName}' must return a value"; } public string message { get; } public VFXErrorType type => VFXErrorType.Error; } class HLSLVoidReturnTypeOnlyIsSupported : IHLSMessage { public HLSLVoidReturnTypeOnlyIsSupported(string functionName) { message = $"HLSL function '{functionName}' must return a 'void' type"; } public string message { get; } public VFXErrorType type => VFXErrorType.Error; } class HLSLSameFunctionName : IHLSMessage { public HLSLSameFunctionName(string name) { message = $"Multiple functions with same name '{name}' are declared, only the first one can be selected"; } public string message { get; } public VFXErrorType type => VFXErrorType.Warning; } class HLSLMissingFunction : IHLSMessage { public HLSLMissingFunction() { message = "No valid HLSL function has been provided. You should write at least one function that returns a value"; } public string message { get; } public VFXErrorType type => VFXErrorType.Error; } class HLSLOutParameterNotAllowed : IHLSMessage { public HLSLOutParameterNotAllowed(string parameterName) { message = $"Parameter {parameterName} has out or inout access which is not allowed for Custom HLSL block"; } public string message { get; } public VFXErrorType type => VFXErrorType.Error; } class HLSLMissingIncludeFile : IHLSMessage { public HLSLMissingIncludeFile(string filePath) { message = $"Couldn't open include file '{filePath}'."; } public string message { get; } public VFXErrorType type => VFXErrorType.Error; } class HLSLFunctionParameter { // Match inout/in/out accessor then any whitespace then the parameter type then optionally a template type any whitespace and then the parameter name static readonly Regex s_ParametersParser = new Regex(@"(?(inout|in|out)\b)?\s*(?\w+)(?:[<](?