diff --git a/OpenRA.Mods.Cnc/Widgets/Logic/ProductionTabsLogic.cs b/OpenRA.Mods.Cnc/Widgets/Logic/ProductionTabsLogic.cs index 4c5a63fd09..fe93861cc0 100644 --- a/OpenRA.Mods.Cnc/Widgets/Logic/ProductionTabsLogic.cs +++ b/OpenRA.Mods.Cnc/Widgets/Logic/ProductionTabsLogic.cs @@ -30,6 +30,8 @@ namespace OpenRA.Mods.Cnc.Widgets.Logic tabs.SelectNextTab(reverse); else tabs.QueueGroup = button.ProductionGroup; + + tabs.PickUpCompletedBuilding(); }; Func getKey = _ => Hotkey.Invalid; diff --git a/OpenRA.Mods.Common/Widgets/Logic/Ingame/ClassicProductionLogic.cs b/OpenRA.Mods.Common/Widgets/Logic/Ingame/ClassicProductionLogic.cs index b862eb7fc5..fa4ebc8de4 100644 --- a/OpenRA.Mods.Common/Widgets/Logic/Ingame/ClassicProductionLogic.cs +++ b/OpenRA.Mods.Common/Widgets/Logic/Ingame/ClassicProductionLogic.cs @@ -38,6 +38,9 @@ namespace OpenRA.Mods.Common.Widgets.Logic // When a tab is selected, scroll to the top because the current row position may be invalid for the new tab palette.ScrollToTop(); + + // Attempt to pick up a completed building (if there is one) so it can be placed + palette.PickUpCompletedBuilding(); }; Func getKey = _ => Hotkey.Invalid; diff --git a/OpenRA.Mods.Common/Widgets/ProductionPaletteWidget.cs b/OpenRA.Mods.Common/Widgets/ProductionPaletteWidget.cs index f9ccf48e7b..fb21df5db9 100644 --- a/OpenRA.Mods.Common/Widgets/ProductionPaletteWidget.cs +++ b/OpenRA.Mods.Common/Widgets/ProductionPaletteWidget.cs @@ -182,63 +182,94 @@ namespace OpenRA.Mods.Common.Widgets return HandleEvent(icon, mi.Button == MouseButton.Left, mi.Modifiers.HasModifier(Modifiers.Shift)); } - bool HandleEvent(ProductionIcon icon, bool isLeftClick, bool handleMultiple) + protected bool PickUpCompletedBuildingIcon(ProductionIcon icon, ProductionItem item) { var actor = World.Map.Rules.Actors[icon.Name]; - var first = icon.Queued.FirstOrDefault(); - if (isLeftClick) + if (item != null && item.Done && actor.Traits.Contains()) { - // Pick up a completed building - if (first != null && first.Done && actor.Traits.Contains()) - { - Sound.Play(TabClick); - World.OrderGenerator = new PlaceBuildingOrderGenerator(CurrentQueue, icon.Name); - } - else if (first != null && first.Paused) - { - // Resume a paused item - Sound.Play(TabClick); - World.IssueOrder(Order.PauseProduction(CurrentQueue.Actor, icon.Name, false)); - } - else if (CurrentQueue.BuildableItems().Any(a => a.Name == icon.Name)) - { - // Queue a new item - Sound.Play(TabClick); - Sound.PlayNotification(World.Map.Rules, World.LocalPlayer, "Speech", CurrentQueue.Info.QueuedAudio, World.LocalPlayer.Country.Race); - World.IssueOrder(Order.StartProduction(CurrentQueue.Actor, icon.Name, - handleMultiple ? 5 : 1)); - } - else - Sound.Play(DisabledTabClick); + World.OrderGenerator = new PlaceBuildingOrderGenerator(CurrentQueue, icon.Name); + return true; + } + + return false; + } + + public void PickUpCompletedBuilding() + { + foreach (var icon in icons.Values) + { + var item = icon.Queued.FirstOrDefault(); + if (PickUpCompletedBuildingIcon(icon, item)) + break; + } + } + + bool HandleLeftClick(ProductionItem item, ProductionIcon icon, bool handleMultiple) + { + if (PickUpCompletedBuildingIcon(icon, item)) + { + Sound.Play(TabClick); + return true; + } + + if (item != null && item.Paused) + { + // Resume a paused item + Sound.Play(TabClick); + World.IssueOrder(Order.PauseProduction(CurrentQueue.Actor, icon.Name, false)); + return true; + } + + if (CurrentQueue.BuildableItems().Any(a => a.Name == icon.Name)) + { + // Queue a new item + Sound.Play(TabClick); + Sound.PlayNotification(World.Map.Rules, World.LocalPlayer, "Speech", CurrentQueue.Info.QueuedAudio, World.LocalPlayer.Country.Race); + World.IssueOrder(Order.StartProduction(CurrentQueue.Actor, icon.Name, + handleMultiple ? 5 : 1)); + return true; + } + + return false; + } + + bool HandleRightClick(ProductionItem item, ProductionIcon icon, bool handleMultiple) + { + if (item == null) + return false; + + Sound.Play(TabClick); + + if (item.Paused || item.Done || item.TotalCost == item.RemainingCost) + { + // Instant cancel of things we have not started yet and things that are finished + Sound.PlayNotification(World.Map.Rules, World.LocalPlayer, "Speech", CurrentQueue.Info.CancelledAudio, World.LocalPlayer.Country.Race); + World.IssueOrder(Order.CancelProduction(CurrentQueue.Actor, icon.Name, + handleMultiple ? 5 : 1)); } else { - // Hold/Cancel an existing item - if (first != null) - { - Sound.Play(TabClick); - - // instant cancel of things we havent started yet and things that are finished - if (first.Paused || first.Done || first.TotalCost == first.RemainingCost) - { - Sound.PlayNotification(World.Map.Rules, World.LocalPlayer, "Speech", CurrentQueue.Info.CancelledAudio, World.LocalPlayer.Country.Race); - World.IssueOrder(Order.CancelProduction(CurrentQueue.Actor, icon.Name, - handleMultiple ? 5 : 1)); - } - else - { - Sound.PlayNotification(World.Map.Rules, World.LocalPlayer, "Speech", CurrentQueue.Info.OnHoldAudio, World.LocalPlayer.Country.Race); - World.IssueOrder(Order.PauseProduction(CurrentQueue.Actor, icon.Name, true)); - } - } - else - Sound.Play(DisabledTabClick); + // Pause an existing item + Sound.PlayNotification(World.Map.Rules, World.LocalPlayer, "Speech", CurrentQueue.Info.OnHoldAudio, World.LocalPlayer.Country.Race); + World.IssueOrder(Order.PauseProduction(CurrentQueue.Actor, icon.Name, true)); } return true; } + bool HandleEvent(ProductionIcon icon, bool isLeftClick, bool handleMultiple) + { + var item = icon.Queued.FirstOrDefault(); + var handled = isLeftClick ? HandleLeftClick(item, icon, handleMultiple) + : HandleRightClick(item, icon, handleMultiple); + + if (!handled) + Sound.Play(DisabledTabClick); + + return true; + } + public override bool HandleKeyPress(KeyInput e) { if (e.Event == KeyInputEvent.Up || CurrentQueue == null) diff --git a/OpenRA.Mods.Common/Widgets/ProductionTabsWidget.cs b/OpenRA.Mods.Common/Widgets/ProductionTabsWidget.cs index 513577f42f..14ea5e9943 100644 --- a/OpenRA.Mods.Common/Widgets/ProductionTabsWidget.cs +++ b/OpenRA.Mods.Common/Widgets/ProductionTabsWidget.cs @@ -110,6 +110,12 @@ namespace OpenRA.Mods.Common.Widgets return true; } + public void PickUpCompletedBuilding() + { + // This is called from ProductionTabsLogic + paletteWidget.Value.PickUpCompletedBuilding(); + } + public string QueueGroup { get