From 5574e88adae3e8576b63c58900b9829f3cf24abd Mon Sep 17 00:00:00 2001 From: RobertBeekman Date: Tue, 27 Oct 2026 21:06:26 +0100 Subject: [PATCH] Core - Keep the last good outputs of a node that fails to evaluate A node that failed to evaluate reset its outputs to their default values, so a node breaking for a few frames made everything after it jump to defaults. It now keeps the outputs of its last successful run, like before #911, and still marks them as evaluated so it isn't evaluated again for every pin reading from it. --- src/Artemis.Core.Tests/VisualScripting/NodeTests.cs | 8 ++++---- src/Artemis.Core/VisualScripting/Nodes/Node.cs | 8 ++++---- src/Artemis.Core/VisualScripting/Pins/OutputPin.cs | 10 ---------- src/Artemis.Core/VisualScripting/Pins/Pin.cs | 7 ------- 4 files changed, 8 insertions(+), 25 deletions(-) diff --git a/src/Artemis.Core.Tests/VisualScripting/NodeTests.cs b/src/Artemis.Core.Tests/VisualScripting/NodeTests.cs index b1f89695b..6eaf6ffdf 100644 --- a/src/Artemis.Core.Tests/VisualScripting/NodeTests.cs +++ b/src/Artemis.Core.Tests/VisualScripting/NodeTests.cs @@ -218,9 +218,9 @@ public class NodeTests : ScriptTestBase } [Fact] - public void FailingNode_InAScript_SetsItsOutputsToTheirDefaultValues() + public void FailingNode_InAScript_KeepsTheOutputsOfItsLastSuccessfulRun() { - // Rather than letting the value from the last run that worked flow on + // So a node that fails for a few frames doesn't make the script jump to default values NodeScript script = CreateScript(); TestThrowingNode node = ScriptNodes.AddNode(script); script.GetExitNode().Input.ConnectTo(node.Output); @@ -231,7 +231,7 @@ public class NodeTests : ScriptTestBase node.FailsOn = TestThrowingNode.FailureMode.Evaluate; script.Run(); - script.Result.ShouldBe(new Numeric(0)); + script.Result.ShouldBe(new Numeric(5)); node.BrokenState.ShouldBe("Failed to evaluate"); script.GetExitNode().BrokenState.ShouldBeNull(); } @@ -239,7 +239,7 @@ public class NodeTests : ScriptTestBase [Fact] public void FailingNode_InAScript_IsEvaluatedOncePerRun() { - // A failing node sets its outputs to their default values, so the other pins reading from it don't try again + // A failing node still marks its outputs as evaluated, so the other pins reading from it don't try again NodeScript script = CreateScript(); TestNode failing = new() {OnEvaluate = _ => throw new InvalidOperationException()}; OutputPin output = failing.CreateOutputPin(); diff --git a/src/Artemis.Core/VisualScripting/Nodes/Node.cs b/src/Artemis.Core/VisualScripting/Nodes/Node.cs index 2c05b2060..f98e857e7 100644 --- a/src/Artemis.Core/VisualScripting/Nodes/Node.cs +++ b/src/Artemis.Core/VisualScripting/Nodes/Node.cs @@ -388,10 +388,10 @@ public abstract class Node : BreakableModel, INode if (TryOrBreak(Evaluate, "Failed to evaluate")) return; - // Don't let the values of the last successful run flow on, and don't try again for every pin that reads from this - // node. Setting a value marks the pin as evaluated until the next run - foreach (Pin pin in Pins.Concat(PinCollections.SelectMany(c => c)).OfType().Where(p => p.Direction == PinDirection.Output)) - pin.SetDefaultValue(); + // Keep the values of the last successful run so a brief failure goes unnoticed, and don't try again for every pin + // that reads from this node + foreach (IPin pin in Pins.Concat(PinCollections.SelectMany(c => c)).Where(p => p.Direction == PinDirection.Output)) + pin.IsEvaluated = true; } /// diff --git a/src/Artemis.Core/VisualScripting/Pins/OutputPin.cs b/src/Artemis.Core/VisualScripting/Pins/OutputPin.cs index 5ec32d1d1..8ff2d116f 100644 --- a/src/Artemis.Core/VisualScripting/Pins/OutputPin.cs +++ b/src/Artemis.Core/VisualScripting/Pins/OutputPin.cs @@ -29,11 +29,6 @@ public sealed class OutputPin : Pin /// public override PinDirection Direction => PinDirection.Output; - internal override void SetDefaultValue() - { - Value = default; - } - private T? _value; /// @@ -105,11 +100,6 @@ public sealed class OutputPin : Pin /// public override PinDirection Direction => PinDirection.Output; - internal override void SetDefaultValue() - { - Value = Type.GetDefault(); - } - private object? _value; private Type _type; diff --git a/src/Artemis.Core/VisualScripting/Pins/Pin.cs b/src/Artemis.Core/VisualScripting/Pins/Pin.cs index 222053542..f3d10d580 100644 --- a/src/Artemis.Core/VisualScripting/Pins/Pin.cs +++ b/src/Artemis.Core/VisualScripting/Pins/Pin.cs @@ -85,13 +85,6 @@ public abstract class Pin : CorePropertyChanged, IPin IsEvaluated = false; } - /// - /// Sets the value of an output pin to the default value of its type, used when its node fails to evaluate - /// - internal virtual void SetDefaultValue() - { - } - /// public void ConnectTo(IPin pin) {