private RecursionNode BeforeInvoke(ControlOutput output, RecursionNode recursionNode) { try { recursion?.Enter(recursionNode); } catch (StackOverflowException ex) { output.unit.HandleException(stack, ex); throw; } var connection = output.connection; var input = connection.destination; if (enableDebug) { var connectionEditorData = stack.GetElementDebugData <IUnitConnectionDebugData>(connection); var inputUnitEditorData = stack.GetElementDebugData <IUnitDebugData>(input.unit); connectionEditorData.lastInvokeFrame = EditorTimeBinding.frame; connectionEditorData.lastInvokeTime = EditorTimeBinding.time; inputUnitEditorData.lastInvokeFrame = EditorTimeBinding.frame; inputUnitEditorData.lastInvokeTime = EditorTimeBinding.time; } return(recursionNode); }
public void Invoke(ControlOutput output) { Ensure.That(nameof(output)).IsNotNull(output); var connection = output.connection; if (connection == null) { return; } var input = connection.destination; var recursionNode = new RecursionNode(output, stack); BeforeInvoke(output, recursionNode); try { var nextPort = InvokeDelegate(input); if (nextPort != null) { Invoke(nextPort); } } finally { AfterInvoke(output, recursionNode); } }
private IEnumerable InvokeCoroutine(ControlOutput output) { var connection = output.connection; if (connection == null) { yield break; } var input = connection.destination; var recursionNode = new RecursionNode(output, stack); BeforeInvoke(output, recursionNode); if (input.supportsCoroutine) { foreach (var instruction in InvokeCoroutineDelegate(input)) { if (instruction is ControlOutput) { foreach (var unwrappedInstruction in InvokeCoroutine((ControlOutput)instruction)) { yield return(unwrappedInstruction); } } else { yield return(instruction); } } } else { ControlOutput nextPort = InvokeDelegate(input); if (nextPort != null) { foreach (var instruction in InvokeCoroutine(nextPort)) { yield return(instruction); } } } AfterInvoke(output, recursionNode); }
private object GetValue(ValueOutput output) { if (locals.TryGetValue(output, out var local)) { return(local); } if (!output.supportsFetch) { throw new InvalidOperationException($"The value of '{output.key}' on '{output.unit}' cannot be fetched dynamically, it must be assigned."); } var recursionNode = new RecursionNode(output, stack); try { recursion?.Enter(recursionNode); } catch (StackOverflowException ex) { output.unit.HandleException(stack, ex); throw; } try { if (enableDebug) { var outputUnitEditorData = stack.GetElementDebugData <IUnitDebugData>(output.unit); outputUnitEditorData.lastInvokeFrame = EditorTimeBinding.frame; outputUnitEditorData.lastInvokeTime = EditorTimeBinding.time; } var value = GetValueDelegate(output); return(value); } finally { recursion?.Exit(recursionNode); } }
private bool CanPredict(ValueOutput output) { // Shortcircuit the expensive check if the port isn't marked as predictable if (!output.supportsPrediction) { return(false); } var recursionNode = new RecursionNode(output, stack); if (!recursion?.TryEnter(recursionNode) ?? false) { return(false); } // Check each value dependency foreach (var relation in output.unit.relations.WithDestination(output)) { if (relation.source is ValueInput) { var source = (ValueInput)relation.source; if (!CanPredict(source)) { recursion?.Exit(recursionNode); return(false); } } } var value = CanPredictDelegate(output); recursion?.Exit(recursionNode); return(value); }
private void AfterInvoke(ControlOutput output, RecursionNode recursionNode) { recursion?.Exit(recursionNode); }