using System.Collections.Generic; using System.Linq; using UnityEngine; using UnityEngine.VFX; using Type = System.Type; namespace UnityEditor.VFX { abstract class VFXBlock : VFXSlotContainerModel { public VFXBlock() { m_UICollapsed = false; } public static T CreateImplicitBlock(VFXData data) where T : VFXBlock { var block = ScriptableObject.CreateInstance(); block.m_TransientData = data; return block; } private VFXData m_TransientData = null; [SerializeField] protected bool m_Disabled = false; public bool enabled { get { return !m_Disabled; } set { m_Disabled = !value; Invalidate(InvalidationCause.kEnableChanged); } } public virtual bool isValid { get { if (GetParent() == null) return true; // a block is invalid only if added to incompatible context. if ((compatibleContexts & GetParent().contextType) != GetParent().contextType) return false; if (GetParent() is VFXBlockSubgraphContext subgraphContext) return (subgraphContext.compatibleContextType & compatibleContexts) == subgraphContext.compatibleContextType; return true; } } public bool isActive { get { return enabled && isValid; } } public abstract VFXContextType compatibleContexts { get; } public abstract VFXDataType compatibleData { get; } public virtual IEnumerable attributes { get { return Enumerable.Empty(); } } public virtual IEnumerable parameters { get { return GetExpressionsFromSlots(this); } } public virtual IEnumerable includes { get { return Enumerable.Empty(); } } public virtual string source { get { return null; } } public IEnumerable mergedAttributes { get { var attribs = new Dictionary(); foreach (var a in attributes) { VFXAttributeMode mode = VFXAttributeMode.None; attribs.TryGetValue(a.attrib, out mode); mode |= a.mode; attribs[a.attrib] = mode; } return attribs.Select(kvp => new VFXAttributeInfo(kvp.Key, kvp.Value)); } } public VFXData GetData() { if (GetParent() != null) return GetParent().GetData(); return m_TransientData; } public sealed override VFXCoordinateSpace GetOutputSpaceFromSlot(VFXSlot slot) { /* For block, space is directly inherited from parent context, this method should remains sealed */ if (GetParent() != null) return GetParent().space; return (VFXCoordinateSpace)int.MaxValue; } public VFXContext flattenedParent { get { return m_FlattenedParent != null ? m_FlattenedParent : GetParent(); } set { m_FlattenedParent = value; } } private VFXContext m_FlattenedParent; } }