Add three-tier layout mode (Wide/Medium/Narrow) for command panels (#5603)

* Add three-tier layout mode (Wide/Medium/Narrow) for command panels

- Add LayoutMode enum: Wide (>2.0), Medium (>=1.35), Narrow (<1.35)
- EagleGameController exposes CurrentLayoutMode property
- CommandSelector base class receives layout mode from CommandPanelController
- Adds IsNarrowLayout helper for selectors to check narrow mode

In narrow mode (iPad-like 4:3 aspect ratios), selectors can hide
hero/battalion pickers since users can select via the Resident
Heroes and Battalions panels instead.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>

* Add heroesColumn and battalionsColumn fields to March/Defend selectors

These GameObject fields allow hiding the hero and battalion selection
columns in narrow layout mode. Wire them up in Unity editor to the
appropriate column GameObjects.

Also fixes DefendCommandSelector import: UnityEditor -> UnityEngine

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>

* Hide hero/battalion columns in narrow layout mode

In SetUpUI(), hide heroesColumn and battalionsColumn when IsNarrowLayout
is true. Users can still select heroes and battalions via the Resident
Heroes and Battalions side panels.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>

* Wire up heroesColumn and battalionsColumn in Unity

Connect the column GameObjects to MarchCommandSelector and
DefendCommandSelector so they can be hidden in narrow layout mode.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
2026-01-25 19:35:59 -08:00
committed by GitHub
co-authored by Claude Opus 4.5
parent 5572a806af
commit d858f8243d
6 changed files with 911 additions and 390 deletions
@@ -58,6 +58,8 @@ namespace eagle {
return;
}
// Pass layout mode to selector before setting up UI
Selector.CurrentLayoutMode = mainController.CurrentLayoutMode;
Selector.UpdateAvailableCommand(Model, AvailableCommand);
headerLabel.text = Selector.HeaderString;
} catch (Exception e) { errorHandler.Add(e); }
@@ -14,6 +14,19 @@ namespace eagle {
public abstract class CommandSelector : MonoBehaviour {
public Texture ButtonImage;
/// <summary>
/// Current layout mode. Set by CommandPanelController before SetUpUI is called.
/// Selectors can use this to adjust their UI for narrow screens.
/// </summary>
public LayoutMode CurrentLayoutMode { get; set; } = LayoutMode.Medium;
/// <summary>
/// True when in narrow layout mode (iPad-like 4:3 aspect ratios).
/// In narrow mode, selectors should hide hero/battalion pickers since
/// users can select via the Resident Heroes and Battalions panels.
/// </summary>
protected bool IsNarrowLayout => CurrentLayoutMode == LayoutMode.Narrow;
public abstract AvailableCommand.SealedValueOneofCase CommandType { get; }
public virtual bool IsAppropriateFor(AvailableCommand cmd) => cmd.SealedValueCase
== CommandType;
@@ -5,7 +5,7 @@ using Net.Eagle0.Eagle.Api;
using Net.Eagle0.Eagle.Api.Command.Util;
using Net.Eagle0.Eagle.Common;
using TMPro;
using UnityEditor;
using UnityEngine;
namespace eagle {
using BattalionId = Int32;
@@ -25,6 +25,10 @@ namespace eagle {
public EventBasedUnitSelector unitSelector;
public TMP_Dropdown rallyPointDropdown;
// Columns to hide in narrow layout mode (users select via side panels instead)
public GameObject heroesColumn;
public GameObject battalionsColumn;
public override AvailableCommand.SealedValueOneofCase CommandType =>
AvailableCommand.SealedValueOneofCase.DefendCommand;
public override string HeaderString => "Defend";
@@ -128,6 +132,10 @@ namespace eagle {
}
protected override void SetUpUI() {
// Hide hero/battalion columns in narrow mode - users select via side panels
if (heroesColumn != null) heroesColumn.SetActive(!IsNarrowLayout);
if (battalionsColumn != null) battalionsColumn.SetActive(!IsNarrowLayout);
if (DefendCommand.AvailableFleeProvinceIds.Count > 0) {
var availableRallyPointProvinceNames =
DefendCommand.AvailableFleeProvinceIds
@@ -7,6 +7,7 @@ using Net.Eagle0.Eagle.Api.Command.Util;
using Net.Eagle0.Eagle.Common;
using Net.Eagle0.Eagle.Views;
using TMPro;
using UnityEngine;
using UnityEngine.UI;
namespace eagle {
@@ -38,6 +39,10 @@ namespace eagle {
public EventBasedUnitSelector unitSelector;
public TMP_Dropdown fromDropdown;
public TMP_Dropdown toDropdown;
// Columns to hide in narrow layout mode (users select via side panels instead)
public GameObject heroesColumn;
public GameObject battalionsColumn;
public Slider goldSlider;
public Slider foodSlider;
public TMP_Text goldTakenLabel;
@@ -294,6 +299,10 @@ namespace eagle {
}
protected override void SetUpUI() {
// Hide hero/battalion columns in narrow mode - users select via side panels
if (heroesColumn != null) heroesColumn.SetActive(!IsNarrowLayout);
if (battalionsColumn != null) battalionsColumn.SetActive(!IsNarrowLayout);
_sortedOneProvinceCommands =
MarchAvailableCommand.OneProvinceCommands
.OrderBy(cmd => _model.Provinces[cmd.OriginProvinceId].Name)
@@ -19,6 +19,14 @@ namespace eagle {
using FactionId = Int32;
using ProvinceId = Int32;
/// <summary>
/// Layout mode based on aspect ratio:
/// - Wide: Ultra-wide screens (ratio > 2.0), factions/armies column on right
/// - Medium: Standard widescreen (ratio >= 1.35), default layout
/// - Narrow: iPad-like 4:3 (ratio < 1.35), compact command panels
/// </summary>
public enum LayoutMode { Wide, Medium, Narrow }
public class EagleGameController : MonoBehaviour {
public SoundManager soundManager;
@@ -75,7 +83,22 @@ namespace eagle {
public CommandWarningPanelController commandWarningPanelController;
private double _aspectRatio;
private bool IsWideScreen => _aspectRatio > 2.0;
private const double WideScreenThreshold = 2.0;
private const double NarrowScreenThreshold = 1.35;
private bool IsWideScreen => _aspectRatio > WideScreenThreshold;
private bool IsNarrowScreen => _aspectRatio < NarrowScreenThreshold;
/// <summary>
/// Current layout mode based on aspect ratio. Accessible to CommandSelectors.
/// </summary>
public LayoutMode CurrentLayoutMode {
get {
if (IsWideScreen) return LayoutMode.Wide;
if (IsNarrowScreen) return LayoutMode.Narrow;
return LayoutMode.Medium;
}
}
private int _lastWidth;
private int _lastHeight;
File diff suppressed because it is too large Load Diff