namespace Unity.VisualScripting { /// /// Toggles between two values with on and off triggers. /// [UnitCategory("Control")] [UnitOrder(19)] [UnitFooterPorts(ControlInputs = true, ControlOutputs = true)] public sealed class ToggleValue : 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; /// /// Trigger to turn on the toggle. /// [DoNotSerialize] [PortLabel("On")] public ControlInput turnOn { get; private set; } /// /// Trigger to turn off the toggle. /// [DoNotSerialize] [PortLabel("Off")] public ControlInput turnOff { get; private set; } /// /// Trigger to toggle the state of the toggle. /// [DoNotSerialize] public ControlInput toggle { get; private set; } /// /// The value to return if the toggle is on. /// [DoNotSerialize] public ValueInput onValue { get; private set; } /// /// The value to return if the toggle is off. /// [DoNotSerialize] public ValueInput offValue { 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; } /// /// The value of the toggle selected depending on the state. /// [DoNotSerialize] public ValueOutput value { get; private set; } protected override void Definition() { turnOn = ControlInput(nameof(turnOn), TurnOn); turnOff = ControlInput(nameof(turnOff), TurnOff); toggle = ControlInput(nameof(toggle), Toggle); onValue = ValueInput(nameof(onValue)); offValue = ValueInput(nameof(offValue)); turnedOn = ControlOutput(nameof(turnedOn)); turnedOff = ControlOutput(nameof(turnedOff)); isOn = ValueOutput(nameof(isOn), IsOn); value = ValueOutput(nameof(value), Value); Requirement(onValue, value); Requirement(offValue, value); 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 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; } private object Value(Flow flow) { var data = flow.stack.GetElementData(this); return flow.GetValue(data.isOn ? onValue : offValue); } } }