Initial Commit
This commit is contained in:
parent
53eb92e9af
commit
270ab7d11f
15341 changed files with 700234 additions and 0 deletions
|
@ -0,0 +1,234 @@
|
|||
using System;
|
||||
using UnityEngine;
|
||||
|
||||
namespace Unity.VisualScripting
|
||||
{
|
||||
/// <summary>
|
||||
/// Runs a cooldown timer to throttle flow and outputs remaining measurements.
|
||||
/// </summary>
|
||||
[UnitCategory("Time")]
|
||||
[TypeIcon(typeof(Timer))]
|
||||
[UnitOrder(8)]
|
||||
public sealed class Cooldown : Unit, IGraphElementWithData, IGraphEventListener
|
||||
{
|
||||
public sealed class Data : IGraphElementData
|
||||
{
|
||||
public float remaining;
|
||||
|
||||
public float duration;
|
||||
|
||||
public bool unscaled;
|
||||
|
||||
public bool isReady => remaining <= 0;
|
||||
|
||||
public Delegate update;
|
||||
|
||||
public bool isListening;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// The moment at which to try using the cooldown.
|
||||
/// </summary>
|
||||
[DoNotSerialize]
|
||||
[PortLabelHidden]
|
||||
public ControlInput enter { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// Trigger to force reset the cooldown.
|
||||
/// </summary>
|
||||
[DoNotSerialize]
|
||||
public ControlInput reset { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// The total duration of the cooldown.
|
||||
/// </summary>
|
||||
[DoNotSerialize]
|
||||
public ValueInput duration { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// Whether to ignore the time scale.
|
||||
/// </summary>
|
||||
[DoNotSerialize]
|
||||
[PortLabel("Unscaled")]
|
||||
public ValueInput unscaledTime { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// Called upon entry when the cooldown is ready.
|
||||
/// </summary>
|
||||
[DoNotSerialize]
|
||||
[PortLabel("Ready")]
|
||||
public ControlOutput exitReady { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// Called upon entry when the cooldown is not yet ready.
|
||||
/// </summary>
|
||||
[DoNotSerialize]
|
||||
[PortLabel("Not Ready")]
|
||||
public ControlOutput exitNotReady { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// Called each frame while the cooldown timer is active.
|
||||
/// </summary>
|
||||
[DoNotSerialize]
|
||||
public ControlOutput tick { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// Called when the cooldown timer reaches zero.
|
||||
/// </summary>
|
||||
[DoNotSerialize]
|
||||
[PortLabel("Completed")]
|
||||
public ControlOutput becameReady { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// The number of seconds remaining until the cooldown is ready.
|
||||
/// </summary>
|
||||
[DoNotSerialize]
|
||||
[PortLabel("Remaining")]
|
||||
public ValueOutput remainingSeconds { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// The proportion of the duration remaining until the cooldown is ready (0-1).
|
||||
/// </summary>
|
||||
[DoNotSerialize]
|
||||
[PortLabel("Remaining %")]
|
||||
public ValueOutput remainingRatio { get; private set; }
|
||||
|
||||
protected override void Definition()
|
||||
{
|
||||
enter = ControlInput(nameof(enter), Enter);
|
||||
reset = ControlInput(nameof(reset), Reset);
|
||||
|
||||
duration = ValueInput(nameof(duration), 1f);
|
||||
unscaledTime = ValueInput(nameof(unscaledTime), false);
|
||||
|
||||
exitReady = ControlOutput(nameof(exitReady));
|
||||
exitNotReady = ControlOutput(nameof(exitNotReady));
|
||||
tick = ControlOutput(nameof(tick));
|
||||
becameReady = ControlOutput(nameof(becameReady));
|
||||
|
||||
remainingSeconds = ValueOutput<float>(nameof(remainingSeconds));
|
||||
remainingRatio = ValueOutput<float>(nameof(remainingRatio));
|
||||
|
||||
Requirement(duration, enter);
|
||||
Requirement(unscaledTime, enter);
|
||||
Succession(enter, exitReady);
|
||||
Succession(enter, exitNotReady);
|
||||
Succession(enter, tick);
|
||||
Succession(enter, becameReady);
|
||||
Assignment(enter, remainingSeconds);
|
||||
Assignment(enter, remainingRatio);
|
||||
}
|
||||
|
||||
public IGraphElementData CreateData()
|
||||
{
|
||||
return new Data();
|
||||
}
|
||||
|
||||
public void StartListening(GraphStack stack)
|
||||
{
|
||||
var data = stack.GetElementData<Data>(this);
|
||||
|
||||
if (data.isListening)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
var reference = stack.ToReference();
|
||||
var hook = new EventHook(EventHooks.Update, stack.machine);
|
||||
Action<EmptyEventArgs> update = args => TriggerUpdate(reference);
|
||||
EventBus.Register(hook, update);
|
||||
data.update = update;
|
||||
data.isListening = true;
|
||||
}
|
||||
|
||||
public void StopListening(GraphStack stack)
|
||||
{
|
||||
var data = stack.GetElementData<Data>(this);
|
||||
|
||||
if (!data.isListening)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
var hook = new EventHook(EventHooks.Update, stack.machine);
|
||||
EventBus.Unregister(hook, data.update);
|
||||
data.update = null;
|
||||
data.isListening = false;
|
||||
}
|
||||
|
||||
public bool IsListening(GraphPointer pointer)
|
||||
{
|
||||
return pointer.GetElementData<Data>(this).isListening;
|
||||
}
|
||||
|
||||
private void TriggerUpdate(GraphReference reference)
|
||||
{
|
||||
using (var flow = Flow.New(reference))
|
||||
{
|
||||
Update(flow);
|
||||
}
|
||||
}
|
||||
|
||||
private ControlOutput Enter(Flow flow)
|
||||
{
|
||||
var data = flow.stack.GetElementData<Data>(this);
|
||||
|
||||
if (data.isReady)
|
||||
{
|
||||
Reset(flow);
|
||||
|
||||
return exitReady;
|
||||
}
|
||||
else
|
||||
{
|
||||
return exitNotReady;
|
||||
}
|
||||
}
|
||||
|
||||
private ControlOutput Reset(Flow flow)
|
||||
{
|
||||
var data = flow.stack.GetElementData<Data>(this);
|
||||
|
||||
data.duration = flow.GetValue<float>(duration);
|
||||
data.remaining = data.duration;
|
||||
data.unscaled = flow.GetValue<bool>(unscaledTime);
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
private void AssignMetrics(Flow flow, Data data)
|
||||
{
|
||||
flow.SetValue(remainingSeconds, data.remaining);
|
||||
flow.SetValue(remainingRatio, Mathf.Clamp01(data.remaining / data.duration));
|
||||
}
|
||||
|
||||
public void Update(Flow flow)
|
||||
{
|
||||
var data = flow.stack.GetElementData<Data>(this);
|
||||
|
||||
if (data.isReady)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
data.remaining -= data.unscaled ? Time.unscaledDeltaTime : Time.deltaTime;
|
||||
|
||||
data.remaining = Mathf.Max(0f, data.remaining);
|
||||
|
||||
AssignMetrics(flow, data);
|
||||
|
||||
var stack = flow.PreserveStack();
|
||||
|
||||
flow.Invoke(tick);
|
||||
|
||||
if (data.isReady)
|
||||
{
|
||||
flow.RestoreStack(stack);
|
||||
|
||||
flow.Invoke(becameReady);
|
||||
}
|
||||
|
||||
flow.DisposePreservedStack(stack);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,11 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 962d2c1de100b4bee951cc5d53693b9f
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
|
@ -0,0 +1,280 @@
|
|||
using System;
|
||||
using UnityEngine;
|
||||
|
||||
namespace Unity.VisualScripting
|
||||
{
|
||||
/// <summary>
|
||||
/// Runs a timer and outputs elapsed and remaining measurements.
|
||||
/// </summary>
|
||||
[UnitCategory("Time")]
|
||||
[UnitOrder(7)]
|
||||
public sealed class Timer : Unit, IGraphElementWithData, IGraphEventListener
|
||||
{
|
||||
public sealed class Data : IGraphElementData
|
||||
{
|
||||
public float elapsed;
|
||||
|
||||
public float duration;
|
||||
|
||||
public bool active;
|
||||
|
||||
public bool paused;
|
||||
|
||||
public bool unscaled;
|
||||
|
||||
public Delegate update;
|
||||
|
||||
public bool isListening;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// The moment at which to start the timer.
|
||||
/// If the timer is already started, this will reset it.
|
||||
/// If the timer is paused, this will resume it.
|
||||
/// </summary>
|
||||
[DoNotSerialize]
|
||||
public ControlInput start { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// Trigger to pause the timer.
|
||||
/// </summary>
|
||||
[DoNotSerialize]
|
||||
public ControlInput pause { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// Trigger to resume the timer.
|
||||
/// </summary>
|
||||
[DoNotSerialize]
|
||||
public ControlInput resume { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// Trigger to toggle the timer.
|
||||
/// If it is idle, it will start.
|
||||
/// If it is active, it will pause.
|
||||
/// If it is paused, it will resume.
|
||||
/// </summary>
|
||||
[DoNotSerialize]
|
||||
public ControlInput toggle { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// The total duration of the timer.
|
||||
/// </summary>
|
||||
[DoNotSerialize]
|
||||
public ValueInput duration { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// Whether to ignore the time scale.
|
||||
/// </summary>
|
||||
[DoNotSerialize]
|
||||
[PortLabel("Unscaled")]
|
||||
public ValueInput unscaledTime { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// Called when the timer is started.co
|
||||
/// </summary>
|
||||
[DoNotSerialize]
|
||||
public ControlOutput started { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// Called each frame while the timer is active.
|
||||
/// </summary>
|
||||
[DoNotSerialize]
|
||||
public ControlOutput tick { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// Called when the timer completes.
|
||||
/// </summary>
|
||||
[DoNotSerialize]
|
||||
public ControlOutput completed { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// The number of seconds elapsed since the timer started.
|
||||
/// </summary>
|
||||
[DoNotSerialize]
|
||||
[PortLabel("Elapsed")]
|
||||
public ValueOutput elapsedSeconds { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// The proportion of the duration that has elapsed (0-1).
|
||||
/// </summary>
|
||||
[DoNotSerialize]
|
||||
[PortLabel("Elapsed %")]
|
||||
public ValueOutput elapsedRatio { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// The number of seconds remaining until the timer is elapsed.
|
||||
/// </summary>
|
||||
[DoNotSerialize]
|
||||
[PortLabel("Remaining")]
|
||||
public ValueOutput remainingSeconds { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// The proportion of the duration remaining until the timer is elapsed (0-1).
|
||||
/// </summary>
|
||||
[DoNotSerialize]
|
||||
[PortLabel("Remaining %")]
|
||||
public ValueOutput remainingRatio { get; private set; }
|
||||
|
||||
protected override void Definition()
|
||||
{
|
||||
isControlRoot = true;
|
||||
|
||||
start = ControlInput(nameof(start), Start);
|
||||
pause = ControlInput(nameof(pause), Pause);
|
||||
resume = ControlInput(nameof(resume), Resume);
|
||||
toggle = ControlInput(nameof(toggle), Toggle);
|
||||
|
||||
duration = ValueInput(nameof(duration), 1f);
|
||||
unscaledTime = ValueInput(nameof(unscaledTime), false);
|
||||
|
||||
started = ControlOutput(nameof(started));
|
||||
tick = ControlOutput(nameof(tick));
|
||||
completed = ControlOutput(nameof(completed));
|
||||
|
||||
elapsedSeconds = ValueOutput<float>(nameof(elapsedSeconds));
|
||||
elapsedRatio = ValueOutput<float>(nameof(elapsedRatio));
|
||||
|
||||
remainingSeconds = ValueOutput<float>(nameof(remainingSeconds));
|
||||
remainingRatio = ValueOutput<float>(nameof(remainingRatio));
|
||||
}
|
||||
|
||||
public IGraphElementData CreateData()
|
||||
{
|
||||
return new Data();
|
||||
}
|
||||
|
||||
public void StartListening(GraphStack stack)
|
||||
{
|
||||
var data = stack.GetElementData<Data>(this);
|
||||
|
||||
if (data.isListening)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
var reference = stack.ToReference();
|
||||
var hook = new EventHook(EventHooks.Update, stack.machine);
|
||||
Action<EmptyEventArgs> update = args => TriggerUpdate(reference);
|
||||
EventBus.Register(hook, update);
|
||||
data.update = update;
|
||||
data.isListening = true;
|
||||
}
|
||||
|
||||
public void StopListening(GraphStack stack)
|
||||
{
|
||||
var data = stack.GetElementData<Data>(this);
|
||||
|
||||
if (!data.isListening)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
var hook = new EventHook(EventHooks.Update, stack.machine);
|
||||
EventBus.Unregister(hook, data.update);
|
||||
data.update = null;
|
||||
data.isListening = false;
|
||||
}
|
||||
|
||||
public bool IsListening(GraphPointer pointer)
|
||||
{
|
||||
return pointer.GetElementData<Data>(this).isListening;
|
||||
}
|
||||
|
||||
private void TriggerUpdate(GraphReference reference)
|
||||
{
|
||||
using (var flow = Flow.New(reference))
|
||||
{
|
||||
Update(flow);
|
||||
}
|
||||
}
|
||||
|
||||
private ControlOutput Start(Flow flow)
|
||||
{
|
||||
var data = flow.stack.GetElementData<Data>(this);
|
||||
|
||||
data.elapsed = 0;
|
||||
data.duration = flow.GetValue<float>(duration);
|
||||
data.active = true;
|
||||
data.paused = false;
|
||||
data.unscaled = flow.GetValue<bool>(unscaledTime);
|
||||
|
||||
AssignMetrics(flow, data);
|
||||
|
||||
return started;
|
||||
}
|
||||
|
||||
private ControlOutput Pause(Flow flow)
|
||||
{
|
||||
var data = flow.stack.GetElementData<Data>(this);
|
||||
|
||||
data.paused = true;
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
private ControlOutput Resume(Flow flow)
|
||||
{
|
||||
var data = flow.stack.GetElementData<Data>(this);
|
||||
|
||||
data.paused = false;
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
private ControlOutput Toggle(Flow flow)
|
||||
{
|
||||
var data = flow.stack.GetElementData<Data>(this);
|
||||
|
||||
if (!data.active)
|
||||
{
|
||||
return Start(flow);
|
||||
}
|
||||
else
|
||||
{
|
||||
data.paused = !data.paused;
|
||||
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
private void AssignMetrics(Flow flow, Data data)
|
||||
{
|
||||
flow.SetValue(elapsedSeconds, data.elapsed);
|
||||
flow.SetValue(elapsedRatio, Mathf.Clamp01(data.elapsed / data.duration));
|
||||
|
||||
flow.SetValue(remainingSeconds, Mathf.Max(0, data.duration - data.elapsed));
|
||||
flow.SetValue(remainingRatio, Mathf.Clamp01((data.duration - data.elapsed) / data.duration));
|
||||
}
|
||||
|
||||
public void Update(Flow flow)
|
||||
{
|
||||
var data = flow.stack.GetElementData<Data>(this);
|
||||
|
||||
if (!data.active || data.paused)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
data.elapsed += data.unscaled ? Time.unscaledDeltaTime : Time.deltaTime;
|
||||
|
||||
data.elapsed = Mathf.Min(data.elapsed, data.duration);
|
||||
|
||||
AssignMetrics(flow, data);
|
||||
|
||||
var stack = flow.PreserveStack();
|
||||
|
||||
flow.Invoke(tick);
|
||||
|
||||
if (data.elapsed >= data.duration)
|
||||
{
|
||||
data.active = false;
|
||||
|
||||
flow.RestoreStack(stack);
|
||||
|
||||
flow.Invoke(completed);
|
||||
}
|
||||
|
||||
flow.DisposePreservedStack(stack);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,11 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 97745dc9f2f4640559e8bd02331d9feb
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
|
@ -0,0 +1,21 @@
|
|||
using System.Collections;
|
||||
using UnityEngine;
|
||||
|
||||
namespace Unity.VisualScripting
|
||||
{
|
||||
/// <summary>
|
||||
/// Delays flow by waiting until the end of the frame.
|
||||
/// </summary>
|
||||
[UnitTitle("Wait For End of Frame")]
|
||||
[UnitShortTitle("End of Frame")]
|
||||
[UnitOrder(5)]
|
||||
public class WaitForEndOfFrameUnit : WaitUnit
|
||||
{
|
||||
protected override IEnumerator Await(Flow flow)
|
||||
{
|
||||
yield return new WaitForEndOfFrame();
|
||||
|
||||
yield return exit;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,11 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 08418bca4bc8e4506aeb510a5267664a
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
|
@ -0,0 +1,162 @@
|
|||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using System.Collections.ObjectModel;
|
||||
using UnityEngine;
|
||||
|
||||
namespace Unity.VisualScripting
|
||||
{
|
||||
/// <summary>
|
||||
/// Delays flow by waiting until multiple input flows have been executed.
|
||||
/// </summary>
|
||||
[UnitCategory("Time")]
|
||||
[UnitOrder(6)]
|
||||
[TypeIcon(typeof(WaitUnit))]
|
||||
public sealed class WaitForFlow : Unit, IGraphElementWithData
|
||||
{
|
||||
public sealed class Data : IGraphElementData
|
||||
{
|
||||
public bool[] inputsActivated;
|
||||
public bool isWaitingCoroutine;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Whether the activation status should be reset on exit.
|
||||
/// </summary>
|
||||
[Serialize]
|
||||
[Inspectable]
|
||||
public bool resetOnExit { get; set; }
|
||||
|
||||
[SerializeAs(nameof(inputCount))]
|
||||
private int _inputCount = 2;
|
||||
|
||||
[DoNotSerialize]
|
||||
[Inspectable, UnitHeaderInspectable("Inputs")]
|
||||
public int inputCount
|
||||
{
|
||||
get => _inputCount;
|
||||
set => _inputCount = Mathf.Clamp(value, 2, 10);
|
||||
}
|
||||
|
||||
[DoNotSerialize]
|
||||
public ReadOnlyCollection<ControlInput> awaitedInputs { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// Trigger to reset the activation status.
|
||||
/// </summary>
|
||||
[DoNotSerialize]
|
||||
public ControlInput reset { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// Triggered after all inputs have been entered at least once.
|
||||
/// </summary>
|
||||
[DoNotSerialize]
|
||||
[PortLabelHidden]
|
||||
public ControlOutput exit { get; private set; }
|
||||
|
||||
protected override void Definition()
|
||||
{
|
||||
var _awaitedInputs = new List<ControlInput>();
|
||||
|
||||
awaitedInputs = _awaitedInputs.AsReadOnly();
|
||||
|
||||
exit = ControlOutput(nameof(exit));
|
||||
|
||||
for (var i = 0; i < inputCount; i++)
|
||||
{
|
||||
var _i = i; // Cache outside closure
|
||||
|
||||
var awaitedInput = ControlInputCoroutine(_i.ToString(), (flow) => Enter(flow, _i), (flow) => EnterCoroutine(flow, _i));
|
||||
|
||||
_awaitedInputs.Add(awaitedInput);
|
||||
|
||||
Succession(awaitedInput, exit);
|
||||
}
|
||||
|
||||
reset = ControlInput(nameof(reset), Reset);
|
||||
}
|
||||
|
||||
public IGraphElementData CreateData()
|
||||
{
|
||||
return new Data() { inputsActivated = new bool[inputCount] };
|
||||
}
|
||||
|
||||
private ControlOutput Enter(Flow flow, int index)
|
||||
{
|
||||
var data = flow.stack.GetElementData<Data>(this);
|
||||
|
||||
data.inputsActivated[index] = true;
|
||||
|
||||
if (CheckActivated(flow))
|
||||
{
|
||||
if (resetOnExit)
|
||||
{
|
||||
Reset(flow);
|
||||
}
|
||||
|
||||
return exit;
|
||||
}
|
||||
else
|
||||
{
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
private bool CheckActivated(Flow flow)
|
||||
{
|
||||
var data = flow.stack.GetElementData<Data>(this);
|
||||
|
||||
for (int i = 0; i < data.inputsActivated.Length; i++)
|
||||
{
|
||||
if (!data.inputsActivated[i])
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
private IEnumerator EnterCoroutine(Flow flow, int index)
|
||||
{
|
||||
var data = flow.stack.GetElementData<Data>(this);
|
||||
|
||||
data.inputsActivated[index] = true;
|
||||
|
||||
if (data.isWaitingCoroutine)
|
||||
{
|
||||
// Another input started an async wait,
|
||||
// we'll let that flow be responsible for
|
||||
// triggering the exit.
|
||||
yield break;
|
||||
}
|
||||
|
||||
if (!CheckActivated(flow))
|
||||
{
|
||||
data.isWaitingCoroutine = true;
|
||||
|
||||
yield return new WaitUntil(() => CheckActivated(flow));
|
||||
|
||||
data.isWaitingCoroutine = false;
|
||||
}
|
||||
|
||||
if (resetOnExit)
|
||||
{
|
||||
Reset(flow);
|
||||
}
|
||||
|
||||
yield return exit;
|
||||
}
|
||||
|
||||
private ControlOutput Reset(Flow flow)
|
||||
{
|
||||
var data = flow.stack.GetElementData<Data>(this);
|
||||
|
||||
for (int i = 0; i < data.inputsActivated.Length; i++)
|
||||
{
|
||||
data.inputsActivated[i] = false;
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,11 @@
|
|||
fileFormatVersion: 2
|
||||
guid: f1ce51feaceca405daca97b5a2789be9
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
|
@ -0,0 +1,20 @@
|
|||
using System.Collections;
|
||||
|
||||
namespace Unity.VisualScripting
|
||||
{
|
||||
/// <summary>
|
||||
/// Delays flow by waiting until the next frame.
|
||||
/// </summary>
|
||||
[UnitTitle("Wait For Next Frame")]
|
||||
[UnitShortTitle("Next Frame")]
|
||||
[UnitOrder(4)]
|
||||
public class WaitForNextFrameUnit : WaitUnit
|
||||
{
|
||||
protected override IEnumerator Await(Flow flow)
|
||||
{
|
||||
yield return null;
|
||||
|
||||
yield return exit;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,11 @@
|
|||
fileFormatVersion: 2
|
||||
guid: e479a8edc294743d0850fde55adafead
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
|
@ -0,0 +1,55 @@
|
|||
using System.Collections;
|
||||
using UnityEngine;
|
||||
|
||||
namespace Unity.VisualScripting
|
||||
{
|
||||
/// <summary>
|
||||
/// Delays flow by waiting a specified number of seconds.
|
||||
/// </summary>
|
||||
[UnitTitle("Wait For Seconds")]
|
||||
[UnitShortTitle("Wait")]
|
||||
[UnitOrder(1)]
|
||||
public class WaitForSecondsUnit : WaitUnit
|
||||
{
|
||||
/// <summary>
|
||||
/// The number of seconds to await.
|
||||
/// </summary>
|
||||
[DoNotSerialize]
|
||||
[PortLabel("Delay")]
|
||||
public ValueInput seconds { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// Whether to ignore the time scale.
|
||||
/// </summary>
|
||||
[DoNotSerialize]
|
||||
[PortLabel("Unscaled")]
|
||||
public ValueInput unscaledTime { get; private set; }
|
||||
|
||||
protected override void Definition()
|
||||
{
|
||||
base.Definition();
|
||||
|
||||
seconds = ValueInput(nameof(seconds), 0f);
|
||||
unscaledTime = ValueInput(nameof(unscaledTime), false);
|
||||
|
||||
Requirement(seconds, enter);
|
||||
Requirement(unscaledTime, enter);
|
||||
}
|
||||
|
||||
protected override IEnumerator Await(Flow flow)
|
||||
{
|
||||
var seconds = flow.GetValue<float>(this.seconds);
|
||||
|
||||
if (flow.GetValue<bool>(unscaledTime))
|
||||
{
|
||||
yield return new WaitForSecondsRealtime(seconds);
|
||||
}
|
||||
else
|
||||
{
|
||||
yield return new WaitForSeconds(seconds);
|
||||
}
|
||||
|
||||
yield return exit;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,11 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 864067c09f11046dba76f5cacba7cbba
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
|
@ -0,0 +1,31 @@
|
|||
using System.Collections;
|
||||
|
||||
namespace Unity.VisualScripting
|
||||
{
|
||||
[UnitCategory("Time")]
|
||||
public abstract class WaitUnit : Unit
|
||||
{
|
||||
/// <summary>
|
||||
/// The moment at which to start the delay.
|
||||
/// </summary>
|
||||
[DoNotSerialize]
|
||||
[PortLabelHidden]
|
||||
public ControlInput enter { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// The action to execute after the delay has elapsed.
|
||||
/// </summary>
|
||||
[DoNotSerialize]
|
||||
[PortLabelHidden]
|
||||
public ControlOutput exit { get; private set; }
|
||||
|
||||
protected override void Definition()
|
||||
{
|
||||
enter = ControlInputCoroutine(nameof(enter), Await);
|
||||
exit = ControlOutput(nameof(exit));
|
||||
Succession(enter, exit);
|
||||
}
|
||||
|
||||
protected abstract IEnumerator Await(Flow flow);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,11 @@
|
|||
fileFormatVersion: 2
|
||||
guid: cc6b78093d57e40f883de7672944949a
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
|
@ -0,0 +1,35 @@
|
|||
using System.Collections;
|
||||
using UnityEngine;
|
||||
|
||||
namespace Unity.VisualScripting
|
||||
{
|
||||
/// <summary>
|
||||
/// Delays flow by waiting until a condition becomes true.
|
||||
/// </summary>
|
||||
[UnitTitle("Wait Until")]
|
||||
[UnitShortTitle("Wait Until")]
|
||||
[UnitOrder(2)]
|
||||
public class WaitUntilUnit : WaitUnit
|
||||
{
|
||||
/// <summary>
|
||||
/// The condition to await.
|
||||
/// </summary>
|
||||
[DoNotSerialize]
|
||||
public ValueInput condition { get; private set; }
|
||||
|
||||
protected override void Definition()
|
||||
{
|
||||
base.Definition();
|
||||
|
||||
condition = ValueInput<bool>(nameof(condition));
|
||||
Requirement(condition, enter);
|
||||
}
|
||||
|
||||
protected override IEnumerator Await(Flow flow)
|
||||
{
|
||||
yield return new WaitUntil(() => flow.GetValue<bool>(condition));
|
||||
|
||||
yield return exit;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,11 @@
|
|||
fileFormatVersion: 2
|
||||
guid: edb411d5c9d5e4a40a66972455d3f334
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
|
@ -0,0 +1,35 @@
|
|||
using System.Collections;
|
||||
using UnityEngine;
|
||||
|
||||
namespace Unity.VisualScripting
|
||||
{
|
||||
/// <summary>
|
||||
/// Delays flow by waiting while a condition is true.
|
||||
/// </summary>
|
||||
[UnitTitle("Wait While")]
|
||||
[UnitShortTitle("Wait While")]
|
||||
[UnitOrder(3)]
|
||||
public class WaitWhileUnit : WaitUnit
|
||||
{
|
||||
/// <summary>
|
||||
/// The condition to check.
|
||||
/// </summary>
|
||||
[DoNotSerialize]
|
||||
public ValueInput condition { get; private set; }
|
||||
|
||||
protected override void Definition()
|
||||
{
|
||||
base.Definition();
|
||||
|
||||
condition = ValueInput<bool>(nameof(condition));
|
||||
Requirement(condition, enter);
|
||||
}
|
||||
|
||||
protected override IEnumerator Await(Flow flow)
|
||||
{
|
||||
yield return new WaitWhile(() => flow.GetValue<bool>(condition));
|
||||
|
||||
yield return exit;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,11 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 1a5a5df0e4f7041b691dcef865c9c428
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
Loading…
Add table
Add a link
Reference in a new issue