Merge pull request #7227 from sinaptik/bleed
add scroll buttons that appear in the production palette when icons exceed available space
This commit is contained in:
@@ -48,13 +48,17 @@ namespace OpenRA.Mods.Common.Widgets
|
|||||||
[Translate] public readonly string ReadyText = "";
|
[Translate] public readonly string ReadyText = "";
|
||||||
[Translate] public readonly string HoldText = "";
|
[Translate] public readonly string HoldText = "";
|
||||||
|
|
||||||
public int IconCount { get; private set; }
|
public int DisplayedIconCount { get; private set; }
|
||||||
|
public int TotalIconCount { get; private set; }
|
||||||
public event Action<int, int> OnIconCountChanged = (a, b) => { };
|
public event Action<int, int> OnIconCountChanged = (a, b) => { };
|
||||||
|
|
||||||
public ProductionIcon TooltipIcon { get; private set; }
|
public ProductionIcon TooltipIcon { get; private set; }
|
||||||
public readonly World World;
|
public readonly World World;
|
||||||
readonly OrderManager orderManager;
|
readonly OrderManager orderManager;
|
||||||
|
|
||||||
|
public int IconRowOffset = 0;
|
||||||
|
public int MaxIconRowOffset = int.MaxValue;
|
||||||
|
|
||||||
Lazy<TooltipContainerWidget> tooltipContainer;
|
Lazy<TooltipContainerWidget> tooltipContainer;
|
||||||
ProductionQueue currentQueue;
|
ProductionQueue currentQueue;
|
||||||
|
|
||||||
@@ -86,8 +90,53 @@ namespace OpenRA.Mods.Common.Widgets
|
|||||||
clock = new Animation(world, "clock");
|
clock = new Animation(world, "clock");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void ScrollDown()
|
||||||
|
{
|
||||||
|
if (CanScrollDown)
|
||||||
|
IconRowOffset++;
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool CanScrollDown
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
var totalRows = (TotalIconCount + Columns - 1) / Columns;
|
||||||
|
|
||||||
|
return IconRowOffset < totalRows - MaxIconRowOffset;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void ScrollUp()
|
||||||
|
{
|
||||||
|
if (CanScrollUp)
|
||||||
|
IconRowOffset--;
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool CanScrollUp
|
||||||
|
{
|
||||||
|
get { return IconRowOffset > 0; }
|
||||||
|
}
|
||||||
|
|
||||||
|
public void ScrollToTop()
|
||||||
|
{
|
||||||
|
IconRowOffset = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
public IEnumerable<ActorInfo> AllBuildables
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
if (CurrentQueue == null)
|
||||||
|
return Enumerable.Empty<ActorInfo>();
|
||||||
|
|
||||||
|
return CurrentQueue.AllItems().OrderBy(a => a.Traits.Get<BuildableInfo>().BuildPaletteOrder);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public override void Tick()
|
public override void Tick()
|
||||||
{
|
{
|
||||||
|
TotalIconCount = AllBuildables.Count();
|
||||||
|
|
||||||
if (CurrentQueue != null && !CurrentQueue.Actor.IsInWorld)
|
if (CurrentQueue != null && !CurrentQueue.Actor.IsInWorld)
|
||||||
CurrentQueue = null;
|
CurrentQueue = null;
|
||||||
|
|
||||||
@@ -202,26 +251,25 @@ namespace OpenRA.Mods.Common.Widgets
|
|||||||
icons = new Dictionary<Rectangle, ProductionIcon>();
|
icons = new Dictionary<Rectangle, ProductionIcon>();
|
||||||
if (CurrentQueue == null)
|
if (CurrentQueue == null)
|
||||||
{
|
{
|
||||||
if (IconCount != 0)
|
if (DisplayedIconCount != 0)
|
||||||
{
|
{
|
||||||
OnIconCountChanged(IconCount, 0);
|
OnIconCountChanged(DisplayedIconCount, 0);
|
||||||
IconCount = 0;
|
DisplayedIconCount = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
var allBuildables = CurrentQueue.AllItems().OrderBy(a => a.Traits.Get<BuildableInfo>().BuildPaletteOrder);
|
var oldIconCount = DisplayedIconCount;
|
||||||
|
DisplayedIconCount = 0;
|
||||||
var oldIconCount = IconCount;
|
|
||||||
IconCount = 0;
|
|
||||||
|
|
||||||
var ks = Game.Settings.Keys;
|
var ks = Game.Settings.Keys;
|
||||||
var rb = RenderBounds;
|
var rb = RenderBounds;
|
||||||
foreach (var item in allBuildables)
|
|
||||||
|
foreach (var item in AllBuildables.Skip(IconRowOffset * Columns).Take(MaxIconRowOffset * Columns))
|
||||||
{
|
{
|
||||||
var x = IconCount % Columns;
|
var x = DisplayedIconCount % Columns;
|
||||||
var y = IconCount / Columns;
|
var y = DisplayedIconCount / Columns;
|
||||||
var rect = new Rectangle(rb.X + x * (IconSize.X + IconMargin.X), rb.Y + y * (IconSize.Y + IconMargin.Y), IconSize.X, IconSize.Y);
|
var rect = new Rectangle(rb.X + x * (IconSize.X + IconMargin.X), rb.Y + y * (IconSize.Y + IconMargin.Y), IconSize.X, IconSize.Y);
|
||||||
var icon = new Animation(World, RenderSimple.GetImage(item));
|
var icon = new Animation(World, RenderSimple.GetImage(item));
|
||||||
icon.Play(item.Traits.Get<TooltipInfo>().Icon);
|
icon.Play(item.Traits.Get<TooltipInfo>().Icon);
|
||||||
@@ -230,20 +278,20 @@ namespace OpenRA.Mods.Common.Widgets
|
|||||||
{
|
{
|
||||||
Actor = item,
|
Actor = item,
|
||||||
Name = item.Name,
|
Name = item.Name,
|
||||||
Hotkey = ks.GetProductionHotkey(IconCount),
|
Hotkey = ks.GetProductionHotkey(DisplayedIconCount),
|
||||||
Sprite = icon.Image,
|
Sprite = icon.Image,
|
||||||
Pos = new float2(rect.Location),
|
Pos = new float2(rect.Location),
|
||||||
Queued = CurrentQueue.AllQueued().Where(a => a.Item == item.Name).ToList(),
|
Queued = CurrentQueue.AllQueued().Where(a => a.Item == item.Name).ToList(),
|
||||||
};
|
};
|
||||||
|
|
||||||
icons.Add(rect, pi);
|
icons.Add(rect, pi);
|
||||||
IconCount++;
|
DisplayedIconCount++;
|
||||||
}
|
}
|
||||||
|
|
||||||
eventBounds = icons.Any() ? icons.Keys.Aggregate(Rectangle.Union) : Rectangle.Empty;
|
eventBounds = icons.Any() ? icons.Keys.Aggregate(Rectangle.Union) : Rectangle.Empty;
|
||||||
|
|
||||||
if (oldIconCount != IconCount)
|
if (oldIconCount != DisplayedIconCount)
|
||||||
OnIconCountChanged(oldIconCount, IconCount);
|
OnIconCountChanged(oldIconCount, DisplayedIconCount);
|
||||||
}
|
}
|
||||||
|
|
||||||
public override void Draw()
|
public override void Draw()
|
||||||
|
|||||||
@@ -36,6 +36,9 @@ namespace OpenRA.Mods.RA.Widgets.Logic
|
|||||||
Action<bool> selectTab = reverse =>
|
Action<bool> selectTab = reverse =>
|
||||||
{
|
{
|
||||||
palette.CurrentQueue = queues.FirstOrDefault(q => q.Enabled);
|
palette.CurrentQueue = queues.FirstOrDefault(q => q.Enabled);
|
||||||
|
|
||||||
|
// When a tab is selected, scroll to the top because the current row position may be invalid for the new tab
|
||||||
|
palette.ScrollToTop();
|
||||||
};
|
};
|
||||||
|
|
||||||
Func<ButtonWidget, Hotkey> getKey = _ => Hotkey.Invalid;
|
Func<ButtonWidget, Hotkey> getKey = _ => Hotkey.Invalid;
|
||||||
@@ -134,7 +137,7 @@ namespace OpenRA.Mods.RA.Widgets.Logic
|
|||||||
var ticker = widget.Get<LogicTickerWidget>("PRODUCTION_TICKER");
|
var ticker = widget.Get<LogicTickerWidget>("PRODUCTION_TICKER");
|
||||||
ticker.OnTick = () =>
|
ticker.OnTick = () =>
|
||||||
{
|
{
|
||||||
if (palette.CurrentQueue == null || palette.IconCount == 0)
|
if (palette.CurrentQueue == null || palette.DisplayedIconCount == 0)
|
||||||
{
|
{
|
||||||
// Select the first active tab
|
// Select the first active tab
|
||||||
foreach (var b in typesContainer.Children)
|
foreach (var b in typesContainer.Children)
|
||||||
@@ -148,6 +151,45 @@ namespace OpenRA.Mods.RA.Widgets.Logic
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// Hook up scroll up and down buttons on the palette
|
||||||
|
var scrollDown = widget.GetOrNull<ButtonWidget>("SCROLL_DOWN_BUTTON");
|
||||||
|
|
||||||
|
if (scrollDown != null)
|
||||||
|
{
|
||||||
|
scrollDown.OnClick = palette.ScrollDown;
|
||||||
|
scrollDown.IsVisible = () => palette.TotalIconCount > (palette.MaxIconRowOffset * palette.Columns);
|
||||||
|
scrollDown.IsDisabled = () => !palette.CanScrollDown;
|
||||||
|
}
|
||||||
|
|
||||||
|
var scrollUp = widget.GetOrNull<ButtonWidget>("SCROLL_UP_BUTTON");
|
||||||
|
|
||||||
|
if (scrollUp != null)
|
||||||
|
{
|
||||||
|
scrollUp.OnClick = palette.ScrollUp;
|
||||||
|
scrollUp.IsVisible = () => palette.TotalIconCount > (palette.MaxIconRowOffset * palette.Columns);
|
||||||
|
scrollUp.IsDisabled = () => !palette.CanScrollUp;
|
||||||
|
}
|
||||||
|
|
||||||
|
SetMaximumVisibleRows(palette);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void SetMaximumVisibleRows(ProductionPaletteWidget productionPalette)
|
||||||
|
{
|
||||||
|
var screenHeight = Game.Renderer.Resolution.Height;
|
||||||
|
|
||||||
|
// Get height of currently displayed icons
|
||||||
|
var containerWidget = Ui.Root.GetOrNull<ContainerWidget>("SIDEBAR_PRODUCTION");
|
||||||
|
|
||||||
|
if (containerWidget == null)
|
||||||
|
return;
|
||||||
|
|
||||||
|
var sidebarProductionHeight = containerWidget.Bounds.Y;
|
||||||
|
|
||||||
|
// Check if icon heights exceed y resolution
|
||||||
|
var maxItemsHeight = screenHeight - sidebarProductionHeight;
|
||||||
|
|
||||||
|
productionPalette.MaxIconRowOffset = (maxItemsHeight / productionPalette.IconSize.Y) - 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -5,21 +5,85 @@ sidebar-allies: chrome.png
|
|||||||
background-supportoverlay: 184,118,64,48
|
background-supportoverlay: 184,118,64,48
|
||||||
|
|
||||||
sidebar-button-allies: chrome.png
|
sidebar-button-allies: chrome.png
|
||||||
background: 56,28,28,28
|
background: 59,31,22,22
|
||||||
|
border-r: 81,31,3,22
|
||||||
|
border-l: 56,31,3,22
|
||||||
|
border-b: 59,53,22,3
|
||||||
|
border-t: 59,28,22,3
|
||||||
|
corner-tl: 56,28,3,3
|
||||||
|
corner-tr: 81,28,3,3
|
||||||
|
corner-bl: 56,53,3,3
|
||||||
|
corner-br: 81,53,3,3
|
||||||
sidebar-button-allies-hover: chrome.png
|
sidebar-button-allies-hover: chrome.png
|
||||||
background: 56,0,28,28
|
background: 59,3,22,22
|
||||||
|
border-r: 81,3,3,22
|
||||||
|
border-l: 56,3,3,22
|
||||||
|
border-b: 59,25,22,3
|
||||||
|
border-t: 59,0,22,3
|
||||||
|
corner-tl: 56,0,3,3
|
||||||
|
corner-tr: 81,0,3,3
|
||||||
|
corner-bl: 56,25,3,3
|
||||||
|
corner-br: 81,25,3,3
|
||||||
sidebar-button-allies-pressed: chrome.png
|
sidebar-button-allies-pressed: chrome.png
|
||||||
background: 56,28,28,28
|
background: 59,31,22,22
|
||||||
|
border-r: 81,31,3,22
|
||||||
|
border-l: 56,31,3,22
|
||||||
|
border-b: 59,53,22,3
|
||||||
|
border-t: 59,28,22,3
|
||||||
|
corner-tl: 56,28,3,3
|
||||||
|
corner-tr: 81,28,3,3
|
||||||
|
corner-bl: 56,53,3,3
|
||||||
|
corner-br: 81,53,3,3
|
||||||
sidebar-button-allies-highlighted: chrome.png
|
sidebar-button-allies-highlighted: chrome.png
|
||||||
background: 84,28,28,28
|
background: 87,31,22,22
|
||||||
|
border-r: 109,31,3,22
|
||||||
|
border-l: 84,31,3,22
|
||||||
|
border-b: 87,53,22,3
|
||||||
|
border-t: 87,28,22,3
|
||||||
|
corner-tl: 84,28,3,3
|
||||||
|
corner-tr: 109,28,3,3
|
||||||
|
corner-bl: 84,53,3,3
|
||||||
|
corner-br: 109,53,3,3
|
||||||
sidebar-button-allies-highlighted-hover: chrome.png
|
sidebar-button-allies-highlighted-hover: chrome.png
|
||||||
background: 84,0,28,28
|
background: 87,3,22,22
|
||||||
|
border-r: 109,3,3,22
|
||||||
|
border-l: 84,3,3,22
|
||||||
|
border-b: 87,25,22,3
|
||||||
|
border-t: 87,0,22,3
|
||||||
|
corner-tl: 84,0,3,3
|
||||||
|
corner-tr: 109,0,3,3
|
||||||
|
corner-bl: 84,25,3,3
|
||||||
|
corner-br: 109,25,3,3
|
||||||
sidebar-button-allies-highlighted-pressed: chrome.png
|
sidebar-button-allies-highlighted-pressed: chrome.png
|
||||||
background: 84,28,28,28
|
background: 87,31,22,22
|
||||||
|
border-r: 109,31,3,22
|
||||||
|
border-l: 84,31,3,22
|
||||||
|
border-b: 87,53,22,3
|
||||||
|
border-t: 87,28,22,3
|
||||||
|
corner-tl: 84,28,3,3
|
||||||
|
corner-tr: 109,28,3,3
|
||||||
|
corner-bl: 84,53,3,3
|
||||||
|
corner-br: 109,53,3,3
|
||||||
sidebar-button-allies-disabled: chrome.png
|
sidebar-button-allies-disabled: chrome.png
|
||||||
background: 168,0,28,28
|
background: 171,3,22,22
|
||||||
|
border-r: 193,3,3,22
|
||||||
|
border-l: 168,3,3,22
|
||||||
|
border-b: 171,25,22,3
|
||||||
|
border-t: 171,0,22,3
|
||||||
|
corner-tl: 168,0,3,3
|
||||||
|
corner-tr: 193,0,3,3
|
||||||
|
corner-bl: 168,25,3,3
|
||||||
|
corner-br: 193,25,3,3
|
||||||
sidebar-button-allies-highlighted-disabled: chrome.png
|
sidebar-button-allies-highlighted-disabled: chrome.png
|
||||||
background: 168,0,28,28
|
background: 171,3,22,22
|
||||||
|
border-r: 193,3,3,22
|
||||||
|
border-l: 168,3,3,22
|
||||||
|
border-b: 171,25,22,3
|
||||||
|
border-t: 171,0,22,3
|
||||||
|
corner-tl: 168,0,3,3
|
||||||
|
corner-tr: 193,0,3,3
|
||||||
|
corner-bl: 168,25,3,3
|
||||||
|
corner-br: 193,25,3,3
|
||||||
|
|
||||||
sidebar-soviet: chrome.png
|
sidebar-soviet: chrome.png
|
||||||
background-top: 274,167,238,290
|
background-top: 274,167,238,290
|
||||||
@@ -28,21 +92,85 @@ sidebar-soviet: chrome.png
|
|||||||
background-supportoverlay: 249,118,64,48
|
background-supportoverlay: 249,118,64,48
|
||||||
|
|
||||||
sidebar-button-soviet: chrome.png
|
sidebar-button-soviet: chrome.png
|
||||||
background: 0,28,28,28
|
background: 3,31,22,22
|
||||||
|
border-r: 25,31,3,22
|
||||||
|
border-l: 0,31,3,22
|
||||||
|
border-b: 3,53,22,3
|
||||||
|
border-t: 3,28,22,3
|
||||||
|
corner-tl: 0,28,3,3
|
||||||
|
corner-tr: 25,28,3,3
|
||||||
|
corner-bl: 0,53,3,3
|
||||||
|
corner-br: 25,53,3,3
|
||||||
sidebar-button-soviet-hover: chrome.png
|
sidebar-button-soviet-hover: chrome.png
|
||||||
background: 0,0,28,28
|
background: 3,3,22,22
|
||||||
|
border-r: 25,3,3,22
|
||||||
|
border-l: 0,3,3,22
|
||||||
|
border-b: 3,25,22,3
|
||||||
|
border-t: 3,0,22,3
|
||||||
|
corner-tl: 0,0,3,3
|
||||||
|
corner-tr: 25,0,3,3
|
||||||
|
corner-bl: 0,25,3,3
|
||||||
|
corner-br: 25,25,3,3
|
||||||
sidebar-button-soviet-pressed: chrome.png
|
sidebar-button-soviet-pressed: chrome.png
|
||||||
background: 0,28,28,28
|
background: 3,31,22,22
|
||||||
|
border-r: 25,31,3,22
|
||||||
|
border-l: 0,31,3,22
|
||||||
|
border-b: 3,53,22,3
|
||||||
|
border-t: 3,28,22,3
|
||||||
|
corner-tl: 0,28,3,3
|
||||||
|
corner-tr: 25,28,3,3
|
||||||
|
corner-bl: 0,53,3,3
|
||||||
|
corner-br: 25,53,3,3
|
||||||
sidebar-button-soviet-highlighted: chrome.png
|
sidebar-button-soviet-highlighted: chrome.png
|
||||||
background: 28,28,28,28
|
background: 31,31,22,22
|
||||||
|
border-r: 53,31,3,22
|
||||||
|
border-l: 28,31,3,22
|
||||||
|
border-b: 31,53,22,3
|
||||||
|
border-t: 31,28,22,3
|
||||||
|
corner-tl: 28,28,3,3
|
||||||
|
corner-tr: 53,28,3,3
|
||||||
|
corner-bl: 28,53,3,3
|
||||||
|
corner-br: 53,53,3,3
|
||||||
sidebar-button-soviet-highlighted-hover: chrome.png
|
sidebar-button-soviet-highlighted-hover: chrome.png
|
||||||
background: 28,0,28,28
|
background: 31,3,22,22
|
||||||
|
border-r: 53,3,3,22
|
||||||
|
border-l: 28,3,3,22
|
||||||
|
border-b: 31,25,22,3
|
||||||
|
border-t: 31,0,22,3
|
||||||
|
corner-tl: 25,0,3,3
|
||||||
|
corner-tr: 53,0,3,3
|
||||||
|
corner-bl: 25,25,3,3
|
||||||
|
corner-br: 53,25,3,3
|
||||||
sidebar-button-soviet-highlighted-pressed: chrome.png
|
sidebar-button-soviet-highlighted-pressed: chrome.png
|
||||||
background: 28,28,28,28
|
background: 31,31,22,22
|
||||||
|
border-r: 53,31,3,22
|
||||||
|
border-l: 28,31,3,22
|
||||||
|
border-b: 31,53,22,3
|
||||||
|
border-t: 31,28,22,3
|
||||||
|
corner-tl: 25,28,3,3
|
||||||
|
corner-tr: 53,28,3,3
|
||||||
|
corner-bl: 25,53,3,3
|
||||||
|
corner-br: 53,53,3,3
|
||||||
sidebar-button-soviet-disabled: chrome.png
|
sidebar-button-soviet-disabled: chrome.png
|
||||||
background: 168,0,28,28
|
background: 115,3,22,22
|
||||||
|
border-r: 137,3,3,22
|
||||||
|
border-l: 112,3,3,22
|
||||||
|
border-b: 115,25,22,3
|
||||||
|
border-t: 115,0,22,3
|
||||||
|
corner-tl: 112,0,3,3
|
||||||
|
corner-tr: 137,0,3,3
|
||||||
|
corner-bl: 112,25,3,3
|
||||||
|
corner-br: 137,25,3,3
|
||||||
sidebar-button-soviet-highlighted-disabled: chrome.png
|
sidebar-button-soviet-highlighted-disabled: chrome.png
|
||||||
background: 168,0,28,28
|
background: 115,3,22,22
|
||||||
|
border-r: 137,3,3,22
|
||||||
|
border-l: 112,3,3,22
|
||||||
|
border-b: 115,25,22,3
|
||||||
|
border-t: 115,0,22,3
|
||||||
|
corner-tl: 112,0,3,3
|
||||||
|
corner-tr: 137,0,3,3
|
||||||
|
corner-bl: 112,25,3,3
|
||||||
|
corner-br: 137,25,3,3
|
||||||
|
|
||||||
sidebar-bits: chrome.png
|
sidebar-bits: chrome.png
|
||||||
production-tooltip-time: 416, 80, 16, 16
|
production-tooltip-time: 416, 80, 16, 16
|
||||||
|
|||||||
@@ -341,3 +341,33 @@ Container@PLAYER_WIDGETS:
|
|||||||
X: 6
|
X: 6
|
||||||
Y: 6
|
Y: 6
|
||||||
ImageCollection: production-icons
|
ImageCollection: production-icons
|
||||||
|
Button@SCROLL_UP_BUTTON:
|
||||||
|
Logic: AddRaceSuffixLogic
|
||||||
|
Y: 186
|
||||||
|
Width: 28
|
||||||
|
Height: 22
|
||||||
|
VisualHeight: 0
|
||||||
|
Background: sidebar-button
|
||||||
|
TooltipText: Scroll up
|
||||||
|
TooltipContainer: TOOLTIP_CONTAINER
|
||||||
|
Children:
|
||||||
|
Image@ICON:
|
||||||
|
X: 6
|
||||||
|
Y: 3
|
||||||
|
ImageCollection: scrollbar
|
||||||
|
ImageName: up_arrow
|
||||||
|
Button@SCROLL_DOWN_BUTTON:
|
||||||
|
Logic: AddRaceSuffixLogic
|
||||||
|
Y: 211
|
||||||
|
Width: 28
|
||||||
|
Height: 22
|
||||||
|
VisualHeight: 0
|
||||||
|
Background: sidebar-button
|
||||||
|
TooltipText: Scroll down
|
||||||
|
TooltipContainer: TOOLTIP_CONTAINER
|
||||||
|
Children:
|
||||||
|
Image@ICON:
|
||||||
|
X: 6
|
||||||
|
Y: 3
|
||||||
|
ImageCollection: scrollbar
|
||||||
|
ImageName: down_arrow
|
||||||
Reference in New Issue
Block a user