namespace Unity.VisualScripting { /// /// Toggles the control flow with on and off triggers. /// [UnitCategory("Control")] [UnitOrder(18)] [UnitFooterPorts(ControlInputs = true, ControlOutputs = true)] public sealed class ToggleFlow : Unit, IGraphElementWithData { public class Data : IGraphElementData { public bool isOn; } /// /// Whether the toggle should start in the on state. /// [Serialize] [Inspectable] [UnitHeaderInspectable("Start On")] [InspectorToggleLeft] public bool startOn { get; set; } = true; /// /// Entry point to the toggle. /// [DoNotSerialize] [PortLabelHidden] public ControlInput enter { get; private set; } /// /// Trigger to turn on the flow through the toggle. /// [DoNotSerialize] [PortLabel("On")] public ControlInput turnOn { get; private set; } /// /// Trigger to turn off the flow through the toggle. /// [DoNotSerialize] [PortLabel("Off")] public ControlInput turnOff { get; private set; } /// /// Trigger to toggle the flow through the toggle. /// [DoNotSerialize] public ControlInput toggle { get; private set; } /// /// Triggered on entry if the flow is on. /// [DoNotSerialize] [PortLabel("On")] public ControlOutput exitOn { get; private set; } /// /// Triggered on entry if the flow is off. /// [DoNotSerialize] [PortLabel("Off")] public ControlOutput exitOff { get; private set; } /// /// Triggered when the flow gets turned on. /// [DoNotSerialize] public ControlOutput turnedOn { get; private set; } /// /// Triggered when the flow gets turned off. /// [DoNotSerialize] public ControlOutput turnedOff { get; private set; } /// /// Whether the flow is currently on. /// [DoNotSerialize] public ValueOutput isOn { get; private set; } protected override void Definition() { enter = ControlInput(nameof(enter), Enter); turnOn = ControlInput(nameof(turnOn), TurnOn); turnOff = ControlInput(nameof(turnOff), TurnOff); toggle = ControlInput(nameof(toggle), Toggle); exitOn = ControlOutput(nameof(exitOn)); exitOff = ControlOutput(nameof(exitOff)); turnedOn = ControlOutput(nameof(turnedOn)); turnedOff = ControlOutput(nameof(turnedOff)); isOn = ValueOutput(nameof(isOn), IsOn); Succession(enter, exitOn); Succession(enter, exitOff); Succession(turnOn, turnedOn); Succession(turnOff, turnedOff); Succession(toggle, turnedOn); Succession(toggle, turnedOff); } public IGraphElementData CreateData() { return new Data() { isOn = startOn }; } private bool IsOn(Flow flow) { return flow.stack.GetElementData(this).isOn; } private ControlOutput Enter(Flow flow) { return IsOn(flow) ? exitOn : exitOff; } private ControlOutput TurnOn(Flow flow) { var data = flow.stack.GetElementData(this); if (data.isOn) { return null; } data.isOn = true; return turnedOn; } private ControlOutput TurnOff(Flow flow) { var data = flow.stack.GetElementData(this); if (!data.isOn) { return null; } data.isOn = false; return turnedOff; } private ControlOutput Toggle(Flow flow) { var data = flow.stack.GetElementData(this); data.isOn = !data.isOn; return data.isOn ? turnedOn : turnedOff; } } }