using System; using System.Collections.Generic; namespace Unity.VisualScripting { public class OverrideStack { public OverrideStack(T defaultValue) { _value = defaultValue; getValue = () => _value; setValue = (value) => _value = value; } public OverrideStack(Func getValue, Action setValue) { Ensure.That(nameof(getValue)).IsNotNull(getValue); Ensure.That(nameof(setValue)).IsNotNull(setValue); this.getValue = getValue; this.setValue = setValue; } public OverrideStack(Func getValue, Action setValue, Action clearValue) : this(getValue, setValue) { Ensure.That(nameof(clearValue)).IsNotNull(clearValue); this.clearValue = clearValue; } private readonly Func getValue; private readonly Action setValue; private readonly Action clearValue; private T _value; private readonly Stack previous = new Stack(); public T value { get { return getValue(); } internal set { setValue(value); } } public OverrideLayer Override(T item) { return new OverrideLayer(this, item); } public void BeginOverride(T item) { previous.Push(value); value = item; } public void EndOverride() { if (previous.Count == 0) { throw new InvalidOperationException(); } value = previous.Pop(); if (previous.Count == 0) { clearValue?.Invoke(); } } public static implicit operator T(OverrideStack stack) { Ensure.That(nameof(stack)).IsNotNull(stack); return stack.value; } } public struct OverrideLayer : IDisposable { public OverrideStack stack { get; } internal OverrideLayer(OverrideStack stack, T item) { Ensure.That(nameof(stack)).IsNotNull(stack); this.stack = stack; stack.BeginOverride(item); } public void Dispose() { stack.EndOverride(); } } }