diff --git a/OpenRA.Mods.Common/Traits/World/TilingPathTool.cs b/OpenRA.Mods.Common/Traits/World/TilingPathTool.cs index 7f587ada51..9506abfb2d 100644 --- a/OpenRA.Mods.Common/Traits/World/TilingPathTool.cs +++ b/OpenRA.Mods.Common/Traits/World/TilingPathTool.cs @@ -318,9 +318,12 @@ namespace OpenRA.Mods.Common.Traits public readonly World World; public WorldRenderer WorldRenderer = null; public readonly ImmutableArray SegmentedBrushes; - public readonly ImmutableArray StartTypes; + readonly ImmutableArray startTypes; public readonly ImmutableArray InnerTypes; - public readonly ImmutableArray EndTypes; + readonly ImmutableArray endTypes; + public Dictionary> StartTypesByInner = []; + public Dictionary> EndTypesByInner = []; + public PathPlan Plan { get; private set; } = null; public string StartType { get; private set; } = null; public string InnerType { get; private set; } = null; @@ -349,13 +352,6 @@ namespace OpenRA.Mods.Common.Traits if (!Available) return; - StartTypes = SegmentedBrushes - .Where(b => b.Segment != null) - .Select(b => string.Join(".", b.Segment.Start.Split('.').SkipLast(1))) - .Distinct() - .Order() - .ToImmutableArray(); - InnerTypes = SegmentedBrushes .Where(b => b.Segment != null) .SelectMany(b => @@ -366,19 +362,43 @@ namespace OpenRA.Mods.Common.Traits .Order() .ToImmutableArray(); - EndTypes = SegmentedBrushes - .Where(b => b.Segment != null) - .Select(b => string.Join(".", b.Segment.End.Split('.').SkipLast(1))) + foreach (var innerType in InnerTypes) + { + StartTypesByInner[innerType] = SegmentedBrushes + .Where(b => b.Segment != null + && b.Segment.Inner != null + ? b.Segment.Inner.Split('.')[0] == innerType : (b.Segment.Start.Split('.')[0] == innerType || b.Segment.End.Split('.')[0] == innerType)) + .Select(b => string.Join(".", b.Segment.Start.Split('.').SkipLast(1))) + .Distinct() + .Order() + .ToImmutableArray(); + + EndTypesByInner[innerType] = SegmentedBrushes + .Where(b => b.Segment != null + && b.Segment.Inner != null + ? b.Segment.Inner.Split('.')[0] == innerType : (b.Segment.Start.Split('.')[0] == innerType || b.Segment.End.Split('.')[0] == innerType)) + .Select(b => string.Join(".", b.Segment.End.Split('.').SkipLast(1))) + .Distinct() + .Order() + .ToImmutableArray(); + } + + startTypes = StartTypesByInner + .SelectMany(kvp => kvp.Value) + .Distinct() + .Order() + .ToImmutableArray(); + + endTypes = EndTypesByInner + .SelectMany(kvp => kvp.Value) .Distinct() .Order() .ToImmutableArray(); - StartType = info.DefaultStart - .FirstOrDefault(StartTypes.Contains, StartTypes[0]); InnerType = info.DefaultInner .FirstOrDefault(InnerTypes.Contains, InnerTypes[0]); - EndType = info.DefaultEnd - .FirstOrDefault(EndTypes.Contains, EndTypes[0]); + + VerifyTypes(InnerType); } public void WorldLoaded(World w, WorldRenderer wr) @@ -416,7 +436,7 @@ namespace OpenRA.Mods.Common.Traits (string Start, string End)[] terminalTypes = [(StartType, EndType)]; if (ClosedLoops && plan.Loop) { - terminalTypes = StartTypes.Concat(EndTypes) + terminalTypes = startTypes.Concat(endTypes) .Distinct() .Where(t => t.Split('.')[0] == InnerType) .Select(t => (t, t)) @@ -451,6 +471,24 @@ namespace OpenRA.Mods.Common.Traits return null; } + public void VerifyTypes(string innerType) + { + var startChoices = StartTypesByInner[innerType]; + if (startChoices.Length == 0) + StartType = ""; + else if (string.IsNullOrEmpty(StartType) || !startChoices.Contains(StartType)) + StartType = startChoices[0]; + + var endChoices = EndTypesByInner[innerType]; + if (endChoices.Length == 0) + EndType = ""; + else if (string.IsNullOrEmpty(EndType) || !endChoices.Contains(EndType)) + EndType = endChoices[0]; + + if (string.IsNullOrEmpty(innerType)) + InnerType = InnerTypes[0]; + } + void Update() { EditorBlitSource = TilePlan(Plan); @@ -471,6 +509,7 @@ namespace OpenRA.Mods.Common.Traits public void SetInnerType(string value) { InnerType = value; + VerifyTypes(value); Update(); } diff --git a/OpenRA.Mods.Common/Widgets/Logic/Editor/TilingPathToolLogic.cs b/OpenRA.Mods.Common/Widgets/Logic/Editor/TilingPathToolLogic.cs index 4ae5f0dbf4..3ecdc7920b 100644 --- a/OpenRA.Mods.Common/Widgets/Logic/Editor/TilingPathToolLogic.cs +++ b/OpenRA.Mods.Common/Widgets/Logic/Editor/TilingPathToolLogic.cs @@ -52,15 +52,11 @@ namespace OpenRA.Mods.Common.Widgets.Logic : new EditorTilingPathBrush(tool)); void SetupDropDown( - string name, + DropDownButtonWidget dropDown, ImmutableArray choices, Func read, Action write) { - var dropDown = widget - .Get(name) - .Get("DROPDOWN"); - dropDown.GetText = read; dropDown.OnMouseDown = _ => { ScrollItemWidget SetupItem(string choice, ScrollItemWidget template) @@ -76,9 +72,32 @@ namespace OpenRA.Mods.Common.Widgets.Logic }; } - SetupDropDown("START_TYPE", tool.StartTypes, () => tool.StartType, tool.SetStartType); - SetupDropDown("INNER_TYPE", tool.InnerTypes, () => tool.InnerType, tool.SetInnerType); - SetupDropDown("END_TYPE", tool.EndTypes, () => tool.EndType, tool.SetEndType); + var startDropdown = widget + .Get("START_TYPE") + .Get("DROPDOWN"); + startDropdown.GetText = () => tool.StartType; + + var endDropdown = widget + .Get("END_TYPE") + .Get("DROPDOWN"); + endDropdown.GetText = () => tool.EndType; + + var innerDropDown = widget + .Get("INNER_TYPE") + .Get("DROPDOWN"); + innerDropDown.GetText = () => tool.InnerType; + + SetupDropDown(startDropdown, tool.StartTypesByInner[tool.InnerType], () => tool.StartType, tool.SetStartType); + SetupDropDown(endDropdown, tool.EndTypesByInner[tool.InnerType], () => tool.EndType, tool.SetEndType); + + void PickInnerType(string choice) + { + tool.SetInnerType(choice); + SetupDropDown(startDropdown, tool.StartTypesByInner[choice], () => tool.StartType, tool.SetStartType); + SetupDropDown(endDropdown, tool.EndTypesByInner[choice], () => tool.EndType, tool.SetEndType); + } + + SetupDropDown(innerDropDown, tool.InnerTypes, () => tool.InnerType, PickInnerType); var deviationSlider = widget.Get("DEVIATION").Get("SLIDER"); deviationSlider.GetValue = () => tool.MaxDeviation;