diff --git a/src/XTMF2.GUI/Controls/ModelSystemCanvas/ModelSystemCanvas.Rendering.cs b/src/XTMF2.GUI/Controls/ModelSystemCanvas/ModelSystemCanvas.Rendering.cs index b94f7f9..c1ec14e 100644 --- a/src/XTMF2.GUI/Controls/ModelSystemCanvas/ModelSystemCanvas.Rendering.cs +++ b/src/XTMF2.GUI/Controls/ModelSystemCanvas/ModelSystemCanvas.Rendering.cs @@ -712,8 +712,11 @@ private void RenderLinks(DrawingContext ctx) else if (_isLight) { glowOuter = LinkGlowOuterPenL; glowInner = LinkGlowInnerPenL; } else { glowOuter = LinkGlowOuterPen; glowInner = LinkGlowInnerPen; } + bool passesExecution = link.UnderlyingLink.OriginHook.PassesExecution; + Point bp2, arrowFrom; Point shaftEnd; + Point labelFrom; if (link.UnderlyingLink.IsOrthogonal) { @@ -724,55 +727,72 @@ private void RenderLinks(DrawingContext ctx) var pts = ComputeOrthogonalPath(link, hasSharedSpine ? spineX : (double?)null); // pts = [p1, corner1, corner2, p2] (always 4 points) bp2 = pts[^1]; - arrowFrom = BorderArrivalFrom(link.Destination, bp2); - shaftEnd = DrawArrow(ctx, brush, arrowFrom, bp2); - - if (hasSharedSpine) + if (passesExecution) { - // For multi-link groups the trunk is identical for every sibling. - // Draw trunk glow + stroke only once to avoid stacking alpha. - if (_orthogonalTrunkDrawn.Add(link.UnderlyingLink)) + arrowFrom = BorderArrivalFrom(link.Destination, bp2); + shaftEnd = DrawArrow(ctx, brush, arrowFrom, bp2); + labelFrom = pts[^2]; + + if (hasSharedSpine) { - // Build the full-extent trunk from the precomputed range. - // The trunk is two segments that share the junction at (spineX, p1.Y): - // 1. Horizontal exit: p1 → (spineX, p1.Y) - // 2. Full vertical: (spineX, topY) → (spineX, bottomY) - // Drawing them as one polyline works when p1.Y is at one extreme; - // for the mixed case (branches above AND below) we draw two - // segments so the spine covers the complete range. - var p1Trunk = pts[0]; // hook anchor - var corner1 = pts[1]; // (spineX, p1.Y) - _orthogonalTrunkRange.TryGetValue(link.UnderlyingLink, out var range); - var spineTop = new Point(spineX, range.TopY); - var spineBot = new Point(spineX, range.BottomY); - - // Horizontal exit + vertical spine as a joined polyline. - // The vertical goes from spineTop down to spineBot; corner1 is - // somewhere along it, so we route: p1 → corner1 → spineTop - // then a separate segment corner1 → spineBot (the other direction). - // This draws the T/L shape correctly with a single extra segment. - var mainTrunkGeo = MakePolyGeo([p1Trunk, corner1, spineTop]); - var extGeo = MakeSegGeo(corner1, spineBot); - - foreach (var trunkPen in new[] { glowOuter, glowInner, pen }) + // For multi-link groups the trunk is identical for every sibling. + // Draw trunk glow + stroke only once to avoid stacking alpha. + if (_orthogonalTrunkDrawn.Add(link.UnderlyingLink)) { - ctx.DrawGeometry(null, trunkPen, mainTrunkGeo); - ctx.DrawGeometry(null, trunkPen, extGeo); + // Build the full-extent trunk from the precomputed range. + // The trunk is two segments that share the junction at (spineX, p1.Y): + // 1. Horizontal exit: p1 → (spineX, p1.Y) + // 2. Full vertical: (spineX, topY) → (spineX, bottomY) + // Drawing them as one polyline works when p1.Y is at one extreme; + // for the mixed case (branches above AND below) we draw two + // segments so the spine covers the complete range. + var p1Trunk = pts[0]; // hook anchor + var corner1 = pts[1]; // (spineX, p1.Y) + _orthogonalTrunkRange.TryGetValue(link.UnderlyingLink, out var range); + var spineTop = new Point(spineX, range.TopY); + var spineBot = new Point(spineX, range.BottomY); + + // Horizontal exit + vertical spine as a joined polyline. + // The vertical goes from spineTop down to spineBot; corner1 is + // somewhere along it, so we route: p1 → corner1 → spineTop + // then a separate segment corner1 → spineBot (the other direction). + // This draws the T/L shape correctly with a single extra segment. + var mainTrunkGeo = MakePolyGeo([p1Trunk, corner1, spineTop]); + var extGeo = MakeSegGeo(corner1, spineBot); + + foreach (var trunkPen in new[] { glowOuter, glowInner, pen }) + { + ctx.DrawGeometry(null, trunkPen, mainTrunkGeo); + ctx.DrawGeometry(null, trunkPen, extGeo); + } } - } - // Branch segment: corner2 → p2 (glow) and corner2 → shaftEnd (stroke). - var branchGlowGeo = MakeSegGeo(pts[^2], pts[^1]); // corner2 → bp2 - var branchShaftGeo = MakeSegGeo(pts[^2], shaftEnd); // corner2 → shaftEnd - ctx.DrawGeometry(null, glowOuter, branchGlowGeo); - ctx.DrawGeometry(null, glowInner, branchGlowGeo); - ctx.DrawGeometry(null, pen, branchShaftGeo); + // Branch segment: corner2 → p2 (glow) and corner2 → shaftEnd (stroke). + var branchGlowGeo = MakeSegGeo(pts[^2], pts[^1]); + var branchShaftGeo = MakeSegGeo(pts[^2], shaftEnd); + ctx.DrawGeometry(null, glowOuter, branchGlowGeo); + ctx.DrawGeometry(null, glowInner, branchGlowGeo); + ctx.DrawGeometry(null, pen, branchShaftGeo); + } + else + { + // Single-destination orthogonal link: draw the full path normally. + var glowGeo = MakePolyGeo(pts); + var shaftGeo = ReplacePolyGeoLastPoint(pts, shaftEnd); + ctx.DrawGeometry(null, glowOuter, glowGeo); + ctx.DrawGeometry(null, glowInner, glowGeo); + ctx.DrawGeometry(null, pen, shaftGeo); + } } else { - // Single-destination orthogonal link: draw the full path normally. - var glowGeo = MakePolyGeo(pts); - var shaftGeo = ReplacePolyGeoLastPoint(pts, shaftEnd); + var revPts = new[] { pts[^1], pts[^2], pts[1], pts[0] }; + arrowFrom = BorderArrivalFrom(link.Origin, revPts[^1]); + shaftEnd = DrawArrow(ctx, brush, arrowFrom, revPts[^1]); + labelFrom = revPts[1]; + + var glowGeo = MakePolyGeo(revPts); + var shaftGeo = ReplacePolyGeoLastPoint(revPts, shaftEnd); ctx.DrawGeometry(null, glowOuter, glowGeo); ctx.DrawGeometry(null, glowInner, glowGeo); ctx.DrawGeometry(null, pen, shaftGeo); @@ -784,9 +804,6 @@ private void RenderLinks(DrawingContext ctx) // links curve gently and long ones sweep broadly, with no elbow kinks. var (bp1, bc1, bc2, bp2c) = ComputeSCurve(link); bp2 = bp2c; - arrowFrom = BorderArrivalFrom(link.Destination, bp2); - shaftEnd = DrawArrow(ctx, brush, arrowFrom, bp2); - // Build the geometry once; reuse for glow and main stroke. static StreamGeometry MakeCurveGeo(Point p1, Point c1, Point c2, Point end) { @@ -798,12 +815,32 @@ static StreamGeometry MakeCurveGeo(Point p1, Point c1, Point c2, Point end) return g; } - var glowGeo = MakeCurveGeo(bp1, bc1, bc2, bp2); - var shaftGeo = MakeCurveGeo(bp1, bc1, bc2, shaftEnd); + if (passesExecution) + { + arrowFrom = BorderArrivalFrom(link.Destination, bp2); + shaftEnd = DrawArrow(ctx, brush, arrowFrom, bp2); + labelFrom = SampleCubicBezier(bp1, bc1, bc2, bp2, 0.97); + + var glowGeo = MakeCurveGeo(bp1, bc1, bc2, bp2); + var shaftGeo = MakeCurveGeo(bp1, bc1, bc2, shaftEnd); - ctx.DrawGeometry(null, glowOuter, glowGeo); - ctx.DrawGeometry(null, glowInner, glowGeo); - ctx.DrawGeometry(null, pen, shaftGeo); + ctx.DrawGeometry(null, glowOuter, glowGeo); + ctx.DrawGeometry(null, glowInner, glowGeo); + ctx.DrawGeometry(null, pen, shaftGeo); + } + else + { + arrowFrom = BorderArrivalFrom(link.Origin, bp1); + shaftEnd = DrawArrow(ctx, brush, arrowFrom, bp1); + labelFrom = SampleCubicBezier(bp2, bc2, bc1, bp1, 0.03); + + var glowGeo = MakeCurveGeo(bp2, bc2, bc1, bp1); + var shaftGeo = MakeCurveGeo(bp2, bc2, bc1, shaftEnd); + + ctx.DrawGeometry(null, glowOuter, glowGeo); + ctx.DrawGeometry(null, glowInner, glowGeo); + ctx.DrawGeometry(null, pen, shaftGeo); + } } // For multi-link destinations draw a small 1-based index number @@ -819,18 +856,44 @@ static StreamGeometry MakeCurveGeo(Point p1, Point c1, Point c2, Point end) if (idx >= 0) { var ft = MakeText((idx + 1).ToString(), LinkIndexFontSize, brush); - double adx = bp2.X - arrowFrom.X; - double ady = bp2.Y - arrowFrom.Y; + // Keep ordering badges outside the destination element regardless + // of curve direction by offsetting along the destination's outward normal. + // Also shift laterally (alternating above/below) so the badge does not + // sit on top of the arrow shaft near the destination. + var inward = BorderInwardNormal(link.Destination, bp2); + double ox = -inward.X; + double oy = -inward.Y; + + double adx = bp2.X - labelFrom.X; + double ady = bp2.Y - labelFrom.Y; double dlen = Math.Sqrt(adx * adx + ady * ady); + double ux, uy; if (dlen >= 1) { - double ux = adx / dlen, uy = ady / dlen; - double nx = -uy, ny = ux; // 90° CCW perpendicular unit vector - double offset = ft.Height * 0.5 + 3; - double lx = shaftEnd.X - ft.Width * 0.5 + nx * offset; - double ly = shaftEnd.Y - ft.Height * 0.5 + ny * offset; - ctx.DrawText(ft, new Point(lx, ly)); + ux = adx / dlen; + uy = ady / dlen; + } + else + { + // Fallback direction when the local segment is near-degenerate. + ux = ox; + uy = oy; } + + // Lateral offset direction (90° CCW from arrow direction). + double nx = -uy; + double ny = ux; + double sideSign = (idx & 1) == 0 ? 1.0 : -1.0; + + double outwardOffset = Math.Max(ft.Height * 0.6 + 6.0, ArrowSize + 4.0); + double lateralOffset = ft.Height * 0.5 + 3.0; + + double anchorX = bp2.X + ox * outwardOffset + nx * lateralOffset * sideSign; + double anchorY = bp2.Y + oy * outwardOffset + ny * lateralOffset * sideSign; + + double lx = anchorX - ft.Width * 0.5; + double ly = anchorY - ft.Height * 0.5; + ctx.DrawText(ft, new Point(lx, ly)); } } } diff --git a/src/XTMF2.GUI/Views/TypePickerDialog.axaml.cs b/src/XTMF2.GUI/Views/TypePickerDialog.axaml.cs index 358d2d7..b6191dc 100644 --- a/src/XTMF2.GUI/Views/TypePickerDialog.axaml.cs +++ b/src/XTMF2.GUI/Views/TypePickerDialog.axaml.cs @@ -25,6 +25,7 @@ You should have received a copy of the GNU General Public License using Avalonia.Controls; using Avalonia.Input; using Avalonia.Interactivity; +using Avalonia.Threading; using XTMF2.GUI.Controls; namespace XTMF2.GUI.Views; @@ -265,23 +266,29 @@ public TypePickerDialog( }, RoutingStrategies.Tunnel); UpdateFilter(); - // Focus the filter box and honour an initial selection once the window is shown. + // Focus the filter box and honour an initial selection once the list is loaded. Opened += (_, _) => { FilterBox.FocusSearchBox(); - if (_initialType is not null) + }; + + TypeListBox.Loaded += (_, _) => + { + Dispatcher.UIThread.Post(() => { - var idx = FilteredTypes.IndexOf(_initialType); - if (idx >= 0) + if (_initialType is not null) { - TypeListBox.SelectedIndex = idx; - TypeListBox.ScrollIntoView(TypeListBox.SelectedItem!); - // Explicitly call OnListSelectionChanged to ensure CanOK is updated. - // This is needed because if the item is already at the selected index, - // SelectionChanged won't fire. - OnListSelectionChanged(); + var idx = FilteredTypes.IndexOf(_initialType); + if (idx >= 0) + { + TypeListBox.SelectedIndex = idx; + TypeListBox.ScrollIntoView(TypeListBox.SelectedItem!); + } } - } + + // Ensure the OK binding reflects the realized ListBox selection. + OnListSelectionChanged(); + }); }; TypeListBox.DoubleTapped += (_, _) => diff --git a/src/XTMF2.Interfaces/SubModuleAttribute.cs b/src/XTMF2.Interfaces/SubModuleAttribute.cs index e543942..49117fb 100644 --- a/src/XTMF2.Interfaces/SubModuleAttribute.cs +++ b/src/XTMF2.Interfaces/SubModuleAttribute.cs @@ -31,12 +31,29 @@ public SubModuleAttribute() Index = -1; } + /// + /// The name of the submodule / Parameter. + /// public string? Name { get; set; } + /// + /// The description of the submodule / Parameter. + /// public string? Description { get; set; } + /// + /// Whether the submodule / Parameter is required. + /// public bool Required { get; set; } + /// + /// Whether the submodule / Parameter passes execution if false then the submodule is considered input, if true then we either pass execution to the submodule or it is output. + /// + public bool PassesExecution { get; set; } + + /// + /// The index of the submodule / Parameter within the module. This must be unique within the module. + /// public int Index { get; set; } } } diff --git a/src/XTMF2/ModelSystemConstruct/NodeHook.cs b/src/XTMF2/ModelSystemConstruct/NodeHook.cs index 37c3464..022d6a4 100644 --- a/src/XTMF2/ModelSystemConstruct/NodeHook.cs +++ b/src/XTMF2/ModelSystemConstruct/NodeHook.cs @@ -50,13 +50,19 @@ public abstract class NodeHook /// public string? DefaultValue; - public NodeHook(string name, HookCardinality cardinality, int index, bool isParameter, string? defaultValue) + /// + /// True when this hook passes execution context to its destination. + /// + public bool PassesExecution { get; private set; } + + public NodeHook(string name, HookCardinality cardinality, int index, bool isParameter, string? defaultValue, bool passesExecution = false) { Name = name; Cardinality = cardinality; Index = index; IsParameter = isParameter; DefaultValue = defaultValue; + PassesExecution = passesExecution; } protected static HookCardinality GetCardinality(Type type, bool required) @@ -115,8 +121,8 @@ public enum HookCardinality sealed class PropertyHook : NodeHook { readonly PropertyInfo Property; - public PropertyHook(string name, PropertyInfo property, bool required, int index, bool isParameter, string? defaultValue) - : base(name, GetCardinality(property, required), index, isParameter, defaultValue) + public PropertyHook(string name, PropertyInfo property, bool required, int index, bool isParameter, string? defaultValue, bool passesExecution = false) + : base(name, GetCardinality(property, required), index, isParameter, defaultValue, passesExecution) { Property = property; } @@ -200,8 +206,8 @@ internal override bool AnyInstalled(IModule module) sealed class FieldHook : NodeHook { readonly FieldInfo Field; - public FieldHook(string name, FieldInfo field, bool required, int index, bool isParameter, string? defaultValue) - : base(name, GetCardinality(field, required), index, isParameter, defaultValue) + public FieldHook(string name, FieldInfo field, bool required, int index, bool isParameter, string? defaultValue, bool passesExecution = false) + : base(name, GetCardinality(field, required), index, isParameter, defaultValue, passesExecution) { Field = field; } @@ -296,7 +302,7 @@ public sealed class FunctionParameterHook : NodeHook /// The function-parameter slot this hook exposes. /// Ordinal position among the template's FunctionParameters. public FunctionParameterHook(ModelSystemConstruct.FunctionParameter parameter, int index) - : base(parameter.Name, HookCardinality.SingleOptional, index, isParameter: false, defaultValue: null) + : base(parameter.Name, HookCardinality.SingleOptional, index, isParameter: false, defaultValue: null, passesExecution: false) { Parameter = parameter; } diff --git a/src/XTMF2/Repository/ModuleRepository.cs b/src/XTMF2/Repository/ModuleRepository.cs index c9ff79e..f06fbdc 100644 --- a/src/XTMF2/Repository/ModuleRepository.cs +++ b/src/XTMF2/Repository/ModuleRepository.cs @@ -379,7 +379,7 @@ private static void LoadFields(Type type, TypeInfo typeInfo, List hook throw new XTMFCodeStyleError(type, $"There is no index defined for sub module property {field.Name}!"); } // all parameters are required - hooks.Add(new FieldHook(parameter.Name!, field, true, parameter.Index, true, parameter.DefaultValue)); + hooks.Add(new FieldHook(parameter.Name!, field, true, parameter.Index, true, parameter.DefaultValue, parameter.PassesExecution)); } else if (attributes.First() is SubModuleAttribute subModule) { @@ -387,7 +387,7 @@ private static void LoadFields(Type type, TypeInfo typeInfo, List hook { throw new XTMFCodeStyleError(type, $"There is no index defined for sub module property {field.Name}!"); } - hooks.Add(new FieldHook(subModule.Name!, field, subModule.Required, subModule.Index, false, null)); + hooks.Add(new FieldHook(subModule.Name!, field, subModule.Required, subModule.Index, false, null, subModule.PassesExecution)); } else { @@ -448,7 +448,7 @@ private static void LoadProperties(Type type, TypeInfo typeInfo, List throw new XTMFCodeStyleError(type, $"There is no index defined for sub module property {property.Name}!"); } // all parameters are required - hooks.Add(new PropertyHook(parameter.Name!, property, true, parameter.Index, true, parameter.DefaultValue)); + hooks.Add(new PropertyHook(parameter.Name!, property, true, parameter.Index, true, parameter.DefaultValue, parameter.PassesExecution)); } else if (attributes.First() is SubModuleAttribute subModule) { @@ -456,7 +456,7 @@ private static void LoadProperties(Type type, TypeInfo typeInfo, List { throw new XTMFCodeStyleError(type, $"There is no index defined for sub module property {property.Name}!"); } - hooks.Add(new PropertyHook(subModule.Name!, property, subModule.Required, subModule.Index, false, null)); + hooks.Add(new PropertyHook(subModule.Name!, property, subModule.Required, subModule.Index, false, null, subModule.PassesExecution)); } else { diff --git a/src/XTMF2/RuntimeModules/Execute.cs b/src/XTMF2/RuntimeModules/Execute.cs index fedf84e..f5c4f65 100644 --- a/src/XTMF2/RuntimeModules/Execute.cs +++ b/src/XTMF2/RuntimeModules/Execute.cs @@ -33,10 +33,10 @@ public class Execute : BaseAction [Parameter(DefaultValue = "1", Name = "Iterations", Required = false, Index = 1)] public IFunction? Iterations; - [SubModule(Name = "Current Iteration", Required = false, Description = "Place to store the current iteration", Index = 2)] + [SubModule(Name = "Current Iteration", Required = false, Description = "Place to store the current iteration", Index = 2, PassesExecution = true)] public ISetableValue? CurrentIteration; - [SubModule(Name = "To Execute", Description = "The modules in order to execute", Index = 3)] + [SubModule(Name = "To Execute", Description = "The modules in order to execute", Index = 3, PassesExecution = true)] public IAction[]? ToInvoke; public override void Invoke() @@ -78,10 +78,10 @@ public class Execute : BaseAction [Parameter(DefaultValue = "1", Name = "Iterations", Required = false, Index = 1)] public IFunction? Iterations; - [SubModule(Name = "Current Iteration", Required = false, Description = "Place to store the current iteration", Index = 2)] + [SubModule(Name = "Current Iteration", Required = false, Description = "Place to store the current iteration", Index = 2, PassesExecution = true)] public ISetableValue? CurrentIteration; - [SubModule(Name = "To Execute", Description = "The modules in order to execute", Index = 3)] + [SubModule(Name = "To Execute", Description = "The modules in order to execute", Index = 3, PassesExecution = true)] public IAction[]? ToInvoke; public override void Invoke(Context context) diff --git a/src/XTMF2/RuntimeModules/ExecuteActionsThenFunction.cs b/src/XTMF2/RuntimeModules/ExecuteActionsThenFunction.cs index f32893f..25f9e85 100644 --- a/src/XTMF2/RuntimeModules/ExecuteActionsThenFunction.cs +++ b/src/XTMF2/RuntimeModules/ExecuteActionsThenFunction.cs @@ -27,13 +27,13 @@ namespace XTMF2.RuntimeModules Description = "Allows you to execute actions before calling a function. This allows you to ")] public class ExecuteActionsThenFunction : BaseFunction { - [SubModule(Index = 0, Name = "Invoke First", Description = "Actions to invoke before invoking the function.")] + [SubModule(Index = 0, Name = "Invoke First", Description = "Actions to invoke before invoking the function.", PassesExecution = true)] public IAction[]? InvokeFirst; [Parameter(Index = 1, Name = "Invoke Actions in Parallel", Description = "Should the actions be invoked in parallel?", DefaultValue = "false")] public IFunction? InvokeActionsInParallel; - [SubModule(Index = 2, Required = true, Name = "End With", Description = "The function to invoke and return the value of.")] + [SubModule(Index = 2, Required = true, Name = "End With", Description = "The function to invoke and return the value of.", PassesExecution = true)] public IFunction? EndWith; public override Return Invoke() diff --git a/src/XTMF2/RuntimeModules/ExecuteWithContext.cs b/src/XTMF2/RuntimeModules/ExecuteWithContext.cs index ae06523..d7a616a 100644 --- a/src/XTMF2/RuntimeModules/ExecuteWithContext.cs +++ b/src/XTMF2/RuntimeModules/ExecuteWithContext.cs @@ -26,7 +26,7 @@ public sealed class ExecuteWithContext : BaseAction [SubModule(Required = true, Name = "Get Context", Description = "The function to get the context to execute with.", Index = 0)] public IFunction GetContext = null!; - [SubModule(Required = true, Name = "To Execute", Description = "The actions to execute with the context.", Index = 1)] + [SubModule(Required = true, Name = "To Execute", Description = "The actions to execute with the context.", Index = 1, PassesExecution = true)] public IAction[] ToInvoke = null!; override public void Invoke() @@ -43,7 +43,7 @@ override public void Invoke() Description = "Provides a way to execute a series of actions using a context provided to it.")] public sealed class ExecuteWithForwardedContext : BaseAction { - [SubModule(Required = true, Name = "To Execute", Description = "The actions to execute with the context.", Index = 0)] + [SubModule(Required = true, Name = "To Execute", Description = "The actions to execute with the context.", Index = 0, PassesExecution = true)] public IAction[] ToInvoke = null!; override public void Invoke(Context context) diff --git a/src/XTMF2/RuntimeModules/If.cs b/src/XTMF2/RuntimeModules/If.cs index 839e4a0..9f81a06 100644 --- a/src/XTMF2/RuntimeModules/If.cs +++ b/src/XTMF2/RuntimeModules/If.cs @@ -30,10 +30,10 @@ public sealed class IfF : BaseFunction Description = "The condition to invoke to see if the true or false path is taken.", DefaultValue = "true", Index = 0)] public IFunction? Condition; - [SubModule(Required = true, Name = "If True", Description = "The logic to invoke if true", Index = 1)] + [SubModule(Required = true, Name = "If True", Description = "The logic to invoke if true", Index = 1, PassesExecution = true)] public IFunction? ToInvokeIfTrue; - [SubModule(Required = true, Name = "If False", Description = "The logic to invoke if false", Index = 2)] + [SubModule(Required = true, Name = "If False", Description = "The logic to invoke if false", Index = 2, PassesExecution = true)] public IFunction? ToInvokeIfFalse; public override Return Invoke() @@ -57,10 +57,10 @@ public sealed class IfF : BaseFunction Description = "The condition to invoke to see if the true or false path is taken.", DefaultValue = "true", Index = 0)] public IFunction? Condition; - [SubModule(Required = true, Name = "If True", Description = "The logic to invoke if true", Index = 1)] + [SubModule(Required = true, Name = "If True", Description = "The logic to invoke if true", Index = 1, PassesExecution = true)] public IFunction? ToInvokeIfTrue; - [SubModule(Required = true, Name = "If False", Description = "The logic to invoke if false", Index = 2)] + [SubModule(Required = true, Name = "If False", Description = "The logic to invoke if false", Index = 2, PassesExecution = true)] public IFunction? ToInvokeIfFalse; public override Return Invoke(Context context) @@ -84,10 +84,10 @@ public sealed class IfWithContextF : BaseFunction? Condition; - [SubModule(Required = true, Name = "If True", Description = "The logic to invoke if true", Index = 1)] + [SubModule(Required = true, Name = "If True", Description = "The logic to invoke if true", Index = 1, PassesExecution = true)] public IFunction? ToInvokeIfTrue; - [SubModule(Required = true, Name = "If False", Description = "The logic to invoke if false", Index = 2)] + [SubModule(Required = true, Name = "If False", Description = "The logic to invoke if false", Index = 2, PassesExecution = true)] public IFunction? ToInvokeIfFalse; public override Return Invoke(Context context) @@ -111,10 +111,10 @@ public sealed class IfA : BaseAction Description = "The condition to invoke to see if the true or false path is taken.", DefaultValue = "true", Index = 0)] public IFunction? Condition; - [SubModule(Required = false, Name = "If True", Description = "The logic to invoke if true", Index = 1)] + [SubModule(Required = false, Name = "If True", Description = "The logic to invoke if true", Index = 1, PassesExecution = true)] public IAction? ToInvokeIfTrue; - [SubModule(Required = false, Name = "If False", Description = "The logic to invoke if false", Index = 2)] + [SubModule(Required = false, Name = "If False", Description = "The logic to invoke if false", Index = 2, PassesExecution = true)] public IAction? ToInvokeIfFalse; public override void Invoke() @@ -138,10 +138,10 @@ public sealed class IfA : BaseAction Description = "The condition to invoke to see if the true or false path is taken.", DefaultValue = "true", Index = 0)] public IFunction? Condition; - [SubModule(Required = false, Name = "If True", Description = "The logic to invoke if true", Index = 1)] + [SubModule(Required = false, Name = "If True", Description = "The logic to invoke if true", Index = 1, PassesExecution = true)] public IAction? ToInvokeIfTrue; - [SubModule(Required = false, Name = "If False", Description = "The logic to invoke if false", Index = 2)] + [SubModule(Required = false, Name = "If False", Description = "The logic to invoke if false", Index = 2, PassesExecution = true)] public IAction? ToInvokeIfFalse; public override void Invoke(Context context) @@ -165,10 +165,10 @@ public sealed class IfWithContextA : BaseAction Description = "The condition to invoke to see if the true or false path is taken.", DefaultValue = "true", Index = 0)] public IFunction? Condition; - [SubModule(Required = false, Name = "If True", Description = "The logic to invoke if true", Index = 1)] + [SubModule(Required = false, Name = "If True", Description = "The logic to invoke if true", Index = 1, PassesExecution = true)] public IAction? ToInvokeIfTrue; - [SubModule(Required = false, Name = "If False", Description = "The logic to invoke if false", Index = 2)] + [SubModule(Required = false, Name = "If False", Description = "The logic to invoke if false", Index = 2, PassesExecution = true)] public IAction? ToInvokeIfFalse; public override void Invoke(Context context) diff --git a/src/XTMF2/RuntimeModules/Ignore.cs b/src/XTMF2/RuntimeModules/Ignore.cs index c68b0fc..b487a67 100644 --- a/src/XTMF2/RuntimeModules/Ignore.cs +++ b/src/XTMF2/RuntimeModules/Ignore.cs @@ -27,7 +27,7 @@ namespace XTMF2.RuntimeModules Description = "Ignore the result of a function call. This allows you to call functions from an action.")] public class IgnoreResult : BaseAction { - [SubModule(Description = "The module to ignore the results of.", Name = "To Ignore", Required = true, Index = 0)] + [SubModule(Description = "The module to ignore the results of.", Name = "To Ignore", Required = true, Index = 0, PassesExecution = true)] public IFunction? ToExecute; public override void Invoke() @@ -40,7 +40,7 @@ public override void Invoke() Description = "Ignore the result of a function call. This allows you to call functions from an action.")] public class IgnoreResult : BaseAction { - [SubModule(Description = "The module to ignore the results of.", Name = "To Ignore", Required = true, Index = 0)] + [SubModule(Description = "The module to ignore the results of.", Name = "To Ignore", Required = true, Index = 0, PassesExecution = true)] public IFunction? ToExecute; public override void Invoke(Context context) @@ -53,7 +53,7 @@ public override void Invoke(Context context) Description = "Ignore the context of a function call. This allows you to call functions that don't require a context.")] public class IgnoreContext : BaseAction { - [SubModule(Description = "The module to invoke ignoring context.", Name = "To Ignore", Required = true, Index = 0)] + [SubModule(Description = "The module to invoke ignoring context.", Name = "To Ignore", Required = true, Index = 0, PassesExecution = true)] public IAction? ToInvoke; public override void Invoke(Context context) @@ -66,7 +66,7 @@ public override void Invoke(Context context) Description = "Ignore the context of a function call. This allows you to call functions that don't require a context.")] public class IgnoreContext : BaseFunction { - [SubModule(Description = "The module to invoke ignoring context.", Name = "To Ignore", Required = true, Index = 0)] + [SubModule(Description = "The module to invoke ignoring context.", Name = "To Ignore", Required = true, Index = 0, PassesExecution = true)] public IFunction? ToInvoke; public override Return Invoke(Context context) diff --git a/src/XTMF2/RuntimeModules/ReportInvocation.cs b/src/XTMF2/RuntimeModules/ReportInvocation.cs index 8a163fd..6fcba20 100644 --- a/src/XTMF2/RuntimeModules/ReportInvocation.cs +++ b/src/XTMF2/RuntimeModules/ReportInvocation.cs @@ -37,7 +37,7 @@ public ReportFunctionInvocation(XTMFRuntime runtime) _runtime = runtime; } - [SubModule(Required = true, Name = "To Invoke", Description = "Invoke after signalling context", Index = 1)] + [SubModule(Required = true, Name = "To Invoke", Description = "Invoke after signalling context", Index = 1, PassesExecution = true)] public IFunction? ToInvoke; @@ -62,7 +62,7 @@ public ReportFunctionInvocation(XTMFRuntime runtime) _runtime = runtime; } - [SubModule(Required = true, Name = "To Invoke", Description = "Invoke after signalling context", Index = 1)] + [SubModule(Required = true, Name = "To Invoke", Description = "Invoke after signalling context", Index = 1, PassesExecution = true)] public IFunction? ToInvoke; public override Return Invoke(Context context) @@ -86,7 +86,7 @@ public ReportActionInvocation(XTMFRuntime runtime) _runtime = runtime; } - [SubModule(Required = true, Name = "To Invoke", Description = "Invoke after signalling context", Index = 1)] + [SubModule(Required = true, Name = "To Invoke", Description = "Invoke after signalling context", Index = 1, PassesExecution = true)] public IAction? ToInvoke; public override void Invoke() @@ -110,7 +110,7 @@ public ReportActionInvocation(XTMFRuntime runtime) _runtime = runtime; } - [SubModule(Required = true, Name = "To Invoke", Description = "Invoke after signalling context", Index = 1)] + [SubModule(Required = true, Name = "To Invoke", Description = "Invoke after signalling context", Index = 1, PassesExecution = true)] public IAction? ToInvoke; public override void Invoke(Context context) @@ -134,7 +134,7 @@ public ReportActionInvocationWithContext(XTMFRuntime runtime) _runtime = runtime; } - [SubModule(Required = true, Name = "To Invoke", Description = "Invoke after signalling context", Index = 1)] + [SubModule(Required = true, Name = "To Invoke", Description = "Invoke after signalling context", Index = 1, PassesExecution = true)] public IAction? ToInvoke; public override void Invoke(Context context) diff --git a/src/XTMF2/RuntimeModules/SetParameter.cs b/src/XTMF2/RuntimeModules/SetParameter.cs index f4f3042..0ac4aed 100644 --- a/src/XTMF2/RuntimeModules/SetParameter.cs +++ b/src/XTMF2/RuntimeModules/SetParameter.cs @@ -20,7 +20,7 @@ namespace XTMF2.RuntimeModules; DocumentationLink = "https://tmg.utoronto.ca/doc/2.0/xtmf2/modules/XTMF2/RuntimeModules/SetParameter.html")] public sealed class SetParameter : BaseAction { - [Parameter(Required = true, Name = "Value", Description = "The value to set the parameter to.", Index = 0)] + [Parameter(Required = true, Name = "Value", Description = "The value to set the parameter to.", Index = 0, PassesExecution = true)] public ISetableValue Value = null!; [Parameter(Required = true, Name = "New Value", Description = "The value to set the parameter to.", Index = 1)] diff --git a/src/XTMF2/RuntimeModules/StartModule.cs b/src/XTMF2/RuntimeModules/StartModule.cs index cf55f58..30be9d9 100644 --- a/src/XTMF2/RuntimeModules/StartModule.cs +++ b/src/XTMF2/RuntimeModules/StartModule.cs @@ -29,7 +29,7 @@ namespace XTMF2.RuntimeModules Description = "A starting point for a model system.")] public sealed class StartModule : BaseAction { - [SubModule(Name = "ToExecute", Description = "The node to invoke when executing this start.", Index = 0)] + [SubModule(Name = "ToExecute", Description = "The node to invoke when executing this start.", Index = 0, PassesExecution = true)] public IAction? ToExecute; public override void Invoke() diff --git a/src/XTMF2/RuntimeModules/WriteToLog.cs b/src/XTMF2/RuntimeModules/WriteToLog.cs index d46738d..8c16ef1 100644 --- a/src/XTMF2/RuntimeModules/WriteToLog.cs +++ b/src/XTMF2/RuntimeModules/WriteToLog.cs @@ -29,7 +29,7 @@ public sealed class WriteToLogF : BaseFunction [SubModule(Required = true, Name = "Log", Description = "The log that will be written to.", Index = 0)] public IFunction Log = null!; - [SubModule(Required = true, Name = "To Invoke", Description = "The function to execute after writing to the log.", Index = 1)] + [SubModule(Required = true, Name = "To Invoke", Description = "The function to execute after writing to the log.", Index = 1, PassesExecution = true)] public IFunction ToInvoke = null!; [Parameter(Required = true, Name = "Message", Description = "The message to write to the log.", DefaultValue = "", Index = 2)] @@ -50,7 +50,7 @@ public sealed class WriteToLogF : BaseFunction [SubModule(Required = true, Name = "Log", Description = "The log that will be written to.", Index = 0)] public IFunction Log = null!; - [SubModule(Required = true, Name = "To Invoke", Description = "The function to execute after writing to the log.", Index = 1)] + [SubModule(Required = true, Name = "To Invoke", Description = "The function to execute after writing to the log.", Index = 1, PassesExecution = true)] public IFunction ToInvoke = null!; [Parameter(Required = true, Name = "Message", Description = "The message to write to the log.", DefaultValue = "", Index = 2)] @@ -71,7 +71,7 @@ public sealed class WriteToLogBasedOnContextF : BaseFunction Log = null!; - [SubModule(Required = true, Name = "To Invoke", Description = "The function to execute after writing to the log.", Index = 1)] + [SubModule(Required = true, Name = "To Invoke", Description = "The function to execute after writing to the log.", Index = 1, PassesExecution = true)] public IFunction ToInvoke = null!; [Parameter(Required = true, Name = "Message", Description = "The message to write to the log.", DefaultValue = "", Index = 2)] @@ -92,7 +92,7 @@ public sealed class WriteToLogA : BaseAction [SubModule(Required = true, Name = "Log", Description = "The log that will be written to.", Index = 0)] public IFunction Log = null!; - [SubModule(Required = false, Name = "To Invoke", Description = "The function to execute after writing to the log.", Index = 1)] + [SubModule(Required = false, Name = "To Invoke", Description = "The function to execute after writing to the log.", Index = 1, PassesExecution = true)] public IAction? ToInvoke; [Parameter(Required = true, Name = "Message", Description = "The message to write to the log.", DefaultValue = "", Index = 2)] @@ -113,7 +113,7 @@ public sealed class WriteToLogA : BaseAction [SubModule(Required = true, Name = "Log", Description = "The log that will be written to.", Index = 0)] public IFunction Log = null!; - [SubModule(Required = false, Name = "To Invoke", Description = "The function to execute after writing to the log.", Index = 1)] + [SubModule(Required = false, Name = "To Invoke", Description = "The function to execute after writing to the log.", Index = 1, PassesExecution = true)] public IAction? ToInvoke; [Parameter(Required = true, Name = "Message", Description = "The message to write to the log.", DefaultValue = "", Index = 2)] @@ -134,7 +134,7 @@ public sealed class WriteToLogBasedOnContextA : BaseAction [SubModule(Required = true, Name = "Log", Description = "The log that will be written to.", Index = 0)] public IFunction Log = null!; - [SubModule(Required = true, Name = "To Invoke", Description = "The function to execute after writing to the log.", Index = 1)] + [SubModule(Required = true, Name = "To Invoke", Description = "The function to execute after writing to the log.", Index = 1, PassesExecution = true)] public IAction ToInvoke = null!; [Parameter(Required = true, Name = "Message", Description = "The message to write to the log.", DefaultValue = "", Index = 2)]