Skip to content

Commit 5ac0695

Browse files
committed
Improve main menu discovery and startup logging
1 parent 2b981de commit 5ac0695

4 files changed

Lines changed: 181 additions & 4 deletions

File tree

src/kc-accessibility/ScreenReaderAccessibilityBehaviour.MainMenuHandlers.cs

Lines changed: 36 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -33,9 +33,19 @@ private bool TryHandleTopLevelMainMenuNavigation()
3333
return false;
3434
}
3535

36+
ConsoleUIItem focusedItem = GetFocusedItem();
37+
if (focusedItem != null)
38+
{
39+
int focusedIndex = FindButtonIndexForConsoleItem(items, focusedItem);
40+
if (focusedIndex >= 0)
41+
{
42+
topLevelMenuIndex = focusedIndex;
43+
}
44+
}
45+
3646
if (IsNavigateDownPressed() || IsNavigateNextPressed())
3747
{
38-
topLevelMenuIndex = topLevelMenuIndex < 0 ? Math.Min(1, items.Count - 1) : Mathf.Min(topLevelMenuIndex + 1, items.Count - 1);
48+
topLevelMenuIndex = topLevelMenuIndex < 0 ? 0 : Mathf.Min(topLevelMenuIndex + 1, items.Count - 1);
3949
FocusTopLevelMainMenuButton(items[topLevelMenuIndex]);
4050
return true;
4151
}
@@ -56,6 +66,31 @@ private bool TryHandleTopLevelMainMenuNavigation()
5666
return false;
5767
}
5868

69+
private int FindButtonIndexForConsoleItem(List<Button> items, ConsoleUIItem focusedItem)
70+
{
71+
if (items == null || focusedItem == null)
72+
{
73+
return -1;
74+
}
75+
76+
for (int i = 0; i < items.Count; i++)
77+
{
78+
Button button = items[i];
79+
if (button == null)
80+
{
81+
continue;
82+
}
83+
84+
ConsoleUIItem buttonItem = GetConsoleItemForComponent(button);
85+
if (buttonItem == focusedItem)
86+
{
87+
return i;
88+
}
89+
}
90+
91+
return -1;
92+
}
93+
5994
private bool TryHandleChooseModeNavigation()
6095
{
6196
if (GameState.inst.mainMenuMode.GetState() != MainMenuMode.State.ChooseMode)

src/kc-accessibility/ScreenReaderAccessibilityBehaviour.MenuSettingsHelpers.cs

Lines changed: 142 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,26 @@ private List<Button> GetTopLevelMainMenuButtons()
1515
return items;
1616
}
1717

18+
GameObject preferredRoot = FindTopLevelMainMenuButtonContainer(root) ?? root;
19+
Button[] buttons = preferredRoot.GetComponentsInChildren<Button>(includeInactive: false);
20+
for (int i = 0; i < buttons.Length; i++)
21+
{
22+
Button button = buttons[i];
23+
if (button == null || !button.gameObject.activeInHierarchy || !button.interactable)
24+
{
25+
continue;
26+
}
27+
28+
items.Add(button);
29+
}
30+
31+
items.Sort(CompareVerticalMenuButtons);
32+
LogTopLevelMainMenuButtons(preferredRoot == root ? "dynamic-root" : "dynamic-button-container", items);
33+
if (items.Count > 0)
34+
{
35+
return items;
36+
}
37+
1838
string[] labels = new string[]
1939
{
2040
"New",
@@ -35,9 +55,131 @@ private List<Button> GetTopLevelMainMenuButtons()
3555
}
3656
}
3757

58+
LogTopLevelMainMenuButtons("fallback", items);
3859
return items;
3960
}
4061

62+
private static GameObject FindTopLevelMainMenuButtonContainer(GameObject root)
63+
{
64+
if (root == null)
65+
{
66+
return null;
67+
}
68+
69+
Transform[] transforms = root.GetComponentsInChildren<Transform>(includeInactive: false);
70+
for (int i = 0; i < transforms.Length; i++)
71+
{
72+
Transform candidate = transforms[i];
73+
if (candidate == null || candidate.gameObject == null)
74+
{
75+
continue;
76+
}
77+
78+
if (string.Equals(candidate.name, "ButtonContainer", StringComparison.OrdinalIgnoreCase))
79+
{
80+
return candidate.gameObject;
81+
}
82+
}
83+
84+
return null;
85+
}
86+
87+
private void LogTopLevelMainMenuButtons(string source, List<Button> items)
88+
{
89+
if (items == null)
90+
{
91+
log("Top-level main menu discovery source=" + source + " returned null.");
92+
return;
93+
}
94+
95+
log("Top-level main menu discovery source=" + source + " count=" + items.Count + ".");
96+
for (int i = 0; i < items.Count; i++)
97+
{
98+
log("Top-level main menu item " + i + ": " + DescribeTopLevelMainMenuButtonForLog(items[i]));
99+
}
100+
}
101+
102+
private string DescribeTopLevelMainMenuButtonForLog(Button button)
103+
{
104+
if (button == null)
105+
{
106+
return "null";
107+
}
108+
109+
ConsoleUIItem consoleItem = GetConsoleItemForComponent(button);
110+
Transform transform = button.transform;
111+
Vector3 position = transform.position;
112+
string label = GetComponentLabel(button);
113+
string objectName = button.gameObject.name;
114+
string parentName = transform.parent != null ? transform.parent.name : "none";
115+
string consoleItemName = consoleItem != null ? consoleItem.gameObject.name : "none";
116+
string consoleItemType = consoleItem != null ? consoleItem.GetType().Name : "none";
117+
string localizeTerm = GetPrimaryLocalizationTerm(button.gameObject);
118+
return "label=" + SafeLogValue(label)
119+
+ ", object=" + SafeLogValue(objectName)
120+
+ ", parent=" + SafeLogValue(parentName)
121+
+ ", type=" + button.GetType().Name
122+
+ ", consoleItem=" + SafeLogValue(consoleItemName)
123+
+ ", consoleItemType=" + SafeLogValue(consoleItemType)
124+
+ ", localize=" + SafeLogValue(localizeTerm)
125+
+ ", pos=(" + position.x.ToString("F1") + "," + position.y.ToString("F1") + "," + position.z.ToString("F1") + ")";
126+
}
127+
128+
private static string SafeLogValue(string value)
129+
{
130+
return string.IsNullOrEmpty(value) ? "<empty>" : value;
131+
}
132+
133+
private static string GetPrimaryLocalizationTerm(GameObject obj)
134+
{
135+
if (obj == null)
136+
{
137+
return string.Empty;
138+
}
139+
140+
I2.Loc.Localize localize = obj.GetComponent<I2.Loc.Localize>() ?? obj.GetComponentInChildren<I2.Loc.Localize>(includeInactive: false);
141+
return localize != null ? CleanText(localize.Term) : string.Empty;
142+
}
143+
144+
private static int CompareVerticalMenuButtons(Button left, Button right)
145+
{
146+
if (left == null && right == null)
147+
{
148+
return 0;
149+
}
150+
151+
if (left == null)
152+
{
153+
return 1;
154+
}
155+
156+
if (right == null)
157+
{
158+
return -1;
159+
}
160+
161+
Vector3 leftPosition = left.transform.position;
162+
Vector3 rightPosition = right.transform.position;
163+
float yDelta = Mathf.Abs(leftPosition.y - rightPosition.y);
164+
if (yDelta > 0.5f)
165+
{
166+
return rightPosition.y.CompareTo(leftPosition.y);
167+
}
168+
169+
float xDelta = Mathf.Abs(leftPosition.x - rightPosition.x);
170+
if (xDelta > 0.5f)
171+
{
172+
return leftPosition.x.CompareTo(rightPosition.x);
173+
}
174+
175+
return string.Compare(GetStableMenuButtonName(left), GetStableMenuButtonName(right), StringComparison.OrdinalIgnoreCase);
176+
}
177+
178+
private static string GetStableMenuButtonName(Button button)
179+
{
180+
return button != null ? button.gameObject.name : string.Empty;
181+
}
182+
41183
private List<Button> GetChooseModeButtons()
42184
{
43185
List<Button> buttons = new List<Button>();

src/kc-accessibility/ScreenReaderLoadMod.cs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
public class ScreenReaderLoadMod
44
{
55
private const string InitialAnnouncement = "Kingdoms and Castles loaded.";
6-
private const string BuildStamp = "0.2.2";
6+
private const string BuildStamp = "0.2.3";
77

88
private static KCModHelper helper;
99

@@ -14,7 +14,7 @@ public class ScreenReaderLoadMod
1414
private void Preload(KCModHelper modHelper)
1515
{
1616
helper = modHelper;
17-
Log("Preload started. Build " + BuildStamp + ".");
17+
Log("Preload started. Build " + BuildStamp + ". Game version " + Application.version + ". Unity " + Application.unityVersion + ".");
1818
KCTolk.Configure(modHelper.modPath, Log);
1919
bool initialized = KCTolk.Initialize();
2020
Log("Preload finished. Tolk initialized: " + initialized);

src/kc-accessibility/info.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,5 +2,5 @@
22
"Name": "kc-accessibility",
33
"Author": "chris",
44
"Description": "Adds screen-reader accessibility support for menus and gameplay.",
5-
"ModVersion": "0.2.2"
5+
"ModVersion": "0.2.3"
66
}

0 commit comments

Comments
 (0)