Reorganize mission menu and separate design from logic
This commit is contained in:
@@ -3,93 +3,6 @@ modded enum ChimeraMenuPreset
|
||||
ERR_AdminPanel
|
||||
}
|
||||
|
||||
// Presentation rules only: all mutations still use the authenticated command service.
|
||||
class ERR_AdminMenuFields
|
||||
{
|
||||
static array<string> Keys()
|
||||
{
|
||||
return {"aiDoctrine", "aiShadow", "automaticEquipmentChancePercent", "sarkaCarsPerAnger", "motorbikeCount", "planeAltitudeMetres", "planeReplacementSeconds", "planeSectorSeconds", "fieldCampCount", "fieldHospitalCount", "startWeaponCount", "startMagazineCount", "objectGuardCount", "objectGuardEvery", "objectGuardHQMode", "hunterSpawnDistanceMetres", "roadblockCount", "civilianTrafficCount", "emptyRestartHours", "startMode", "radioDefenceSeconds", "aiIntelChancePercent", "intelRevealChancePercent", "startTimeMinutes", "timeMultiplier", "startDateCode", "weatherProfile", "viewDistanceMetres", "reportIntervalSeconds", "supportSquadLimit", "responseRadiusMetres", "convoyCount", "antiAirChancePercent", "antiPersonnelMineChancePercent", "heliTimerMinutes"};
|
||||
}
|
||||
static bool Available(string key, bool hq, bool intel)
|
||||
{
|
||||
if (key == "aiDoctrine" || key == "aiShadow") return hq;
|
||||
if (key == "sarkaCarsPerAnger") return hq;
|
||||
if (key == "aiIntelChancePercent") return intel;
|
||||
if (key == "automaticEquipmentChancePercent" || key == "motorbikeCount" || key == "planeAltitudeMetres" || key == "planeReplacementSeconds" || key == "planeSectorSeconds" || key == "planeReconEnabled" || key == "objectGuardCount" || key == "objectGuardEvery" || key == "objectGuardHQMode" || key == "hunterSpawnDistanceMetres" || key == "heliTimerMinutes" || key == "antiAirChancePercent" || key == "antiPersonnelMineChancePercent" || key == "convoyCount" || key == "reportIntervalSeconds" || key == "supportSquadLimit" || key == "responseRadiusMetres") return hq;
|
||||
return Keys().Contains(key);
|
||||
}
|
||||
// A short journal has no older off-screen lines, even if its slider is zero.
|
||||
static bool FollowJournal(bool empty, float slider, float height, float viewHeight, bool latest)
|
||||
{
|
||||
return latest || empty || slider >= 0.98 || height <= viewHeight;
|
||||
}
|
||||
// TextWidget interprets hash-prefixed tokens as localization IDs. Keep the
|
||||
// server audit and retained entries intact; render their numeric IDs literally.
|
||||
static string JournalText(string line, bool details = false)
|
||||
{
|
||||
return ERR_JournalText.Menu(line, details);
|
||||
}
|
||||
static string Display(string key, string value)
|
||||
{
|
||||
if (key == "aiDoctrine") { if (value == "1") return "Coordinated"; return "Current"; }
|
||||
if (key == "aiShadow") { if (value == "1") return "On"; return "Off"; }
|
||||
if (value == "-1" || value == "-2") return ERR_Settings.SelectionText(value.ToInt());
|
||||
if (key == "startMode") { if (value == "1") return "Crash"; return "Prison"; }
|
||||
if (key == "startTimeMinutes") return ERR_TimeService.Clock(value.ToInt());
|
||||
if (key == "startDateCode") return ERR_EnvironmentService.Date(value.ToInt());
|
||||
if (key == "weatherProfile") return ERR_EnvironmentService.ProfileName(value.ToInt());
|
||||
if (key == "viewDistanceMetres" && value == "0") return "default";
|
||||
return value;
|
||||
}
|
||||
static string StartSummary(int saved, int current)
|
||||
{
|
||||
return "Next start: " + Display("startMode", saved.ToString()) + " | Current round: " + Display("startMode", current.ToString());
|
||||
}
|
||||
static string Command(string key, string value)
|
||||
{
|
||||
string prefix;
|
||||
if (key == "aiDoctrine") prefix = "mission doctrine";
|
||||
else if (key == "aiShadow") prefix = "mission aishadow";
|
||||
else if (key == "automaticEquipmentChancePercent") prefix = "hq equipment";
|
||||
else if (key == "sarkaCarsPerAnger") prefix = "mission sarkacars";
|
||||
else if (key == "motorbikeCount") prefix = "mission motorbikes";
|
||||
else if (key == "planeReconEnabled") prefix = "mission plane";
|
||||
else if (key == "planeAltitudeMetres") prefix = "mission planealtitude";
|
||||
else if (key == "planeReplacementSeconds") prefix = "mission planereplacement";
|
||||
else if (key == "planeSectorSeconds") prefix = "mission planesector";
|
||||
else if (key == "startWeaponCount") prefix = "mission startweapons";
|
||||
else if (key == "startMagazineCount") prefix = "mission startammo";
|
||||
else if (key == "objectGuardEvery") prefix = "mission objectevery";
|
||||
else if (key == "objectGuardHQMode") prefix = "mission objecthq";
|
||||
else if (key == "objectGuardCount") prefix = "mission objectguards";
|
||||
else if (key == "hunterSpawnDistanceMetres") prefix = "mission hunterdistance";
|
||||
else if (key == "fieldCampCount") prefix = "mission camps";
|
||||
else if (key == "fieldHospitalCount") prefix = "mission hospitals";
|
||||
else if (key == "roadblockCount") prefix = "mission roadblocks";
|
||||
else if (key == "emptyRestartHours") prefix = "mission emptyhours";
|
||||
else if (key == "civilianTrafficCount") prefix = "mission traffic";
|
||||
else if (key == "startMode") prefix = "mission start";
|
||||
else if (key == "radioDefenceSeconds") prefix = "mission radio";
|
||||
else if (key == "aiIntelChancePercent") prefix = "intel carrying";
|
||||
else if (key == "intelRevealChancePercent") prefix = "intel reveal";
|
||||
else if (key == "startTimeMinutes") prefix = "mission time";
|
||||
else if (key == "timeMultiplier") prefix = "mission speed";
|
||||
else if (key == "startDateCode") prefix = "mission date";
|
||||
else if (key == "weatherProfile") prefix = "mission weather";
|
||||
else if (key == "viewDistanceMetres") prefix = "mission viewdistance";
|
||||
else if (key == "reportIntervalSeconds") prefix = "hq interval";
|
||||
else if (key == "supportSquadLimit") prefix = "hq squads";
|
||||
else if (key == "responseRadiusMetres") prefix = "hq radius";
|
||||
else if (key == "antiAirChancePercent") prefix = "hq aa";
|
||||
else if (key == "antiPersonnelMineChancePercent") prefix = "hq mines";
|
||||
else if (key == "heliTimerMinutes") prefix = "hq heli timer";
|
||||
else if (key == "convoyCount") prefix = "hq convoy count";
|
||||
value = value.Trim();
|
||||
if (prefix.IsEmpty() || value.IsEmpty() || value.Length() > 32) return "";
|
||||
return prefix + " set " + value;
|
||||
}
|
||||
}
|
||||
|
||||
// Own mission dialog. ChimeraMenuBase owns focus, cursor and input-context lifetime.
|
||||
class ERR_AdminMenu : ChimeraMenuBase
|
||||
{
|
||||
@@ -133,17 +46,9 @@ class ERR_AdminMenu : ChimeraMenuBase
|
||||
m_Controller = SCR_PlayerController.Cast(GetGame().GetPlayerController());
|
||||
m_Mode = ERR_GameMode.Cast(GetGame().GetGameMode());
|
||||
if (!m_Controller) { Close(); return; }
|
||||
array<string> names = {"PlaneOn", "PlaneOff", "Close", "OpenSettings", "OpenWorld", "OpenFactions", "OpenHQ", "OpenJournal", "PauseJournal", "JournalDetails", "LatestJournal", "KeepWeaponOn", "KeepWeaponOff", "SelfEpiOn", "SelfEpiOff", "IntelSummary", "RerollIntel", "OpenMods", "OpenIntel", "OpenStatus", "OpenTerrains", "OpenItems", "OpenTTS"};
|
||||
names.Insert("RandomDay_startTimeMinutes");
|
||||
names.Insert("Default_viewDistanceMetres");
|
||||
names.Insert("OpenForces");
|
||||
names.Insert("OpenSarka"); names.Insert("SarkaBack");
|
||||
names.Insert("RestartEmptyOn"); names.Insert("RestartEmptyOff");
|
||||
names.Insert("OpenGuards"); names.Insert("GuardsBack");
|
||||
names.Insert("OpenSites"); names.Insert("SitesBack");
|
||||
names.Insert("OpenPlane"); names.Insert("PlaneBack");
|
||||
names.Insert("OpenAI"); names.Insert("AIBack");
|
||||
names.Insert("OpenStarter"); names.Insert("EquipmentOverview"); names.Insert("OpenAllowedItems"); names.Insert("OpenItemPresets"); names.Insert("OpenWeights"); names.Insert("OpenRecommendations"); names.Insert("RecommendationsBack"); names.Insert("RecommendedPlane"); names.Insert("RecommendedWeapons");
|
||||
array<string> names = {"PlaneOn", "PlaneOff", "Close", "PauseJournal", "JournalDetails", "LatestJournal", "KeepWeaponOn", "KeepWeaponOff", "SelfEpiOn", "SelfEpiOff", "IntelSummary", "RerollIntel", "RandomDay_startTimeMinutes", "Default_viewDistanceMetres", "RestartEmptyOn", "RestartEmptyOff", "RecommendedPlane", "RecommendedWeapons"};
|
||||
foreach (string mainButton : ERR_AdminMenuPages.MainButtons()) names.Insert(mainButton);
|
||||
foreach (string pageButton : Navigation()) names.Insert(pageButton);
|
||||
for (int density = 1; density <= 4; density++) names.Insert("GuardEvery_" + density.ToString());
|
||||
for (int policy = 0; policy <= 2; policy++) names.Insert("GuardHQ_" + policy.ToString());
|
||||
foreach (string key : ERR_AdminMenuFields.Keys())
|
||||
@@ -167,7 +72,7 @@ class ERR_AdminMenu : ChimeraMenuBase
|
||||
m_Ready = false; m_Age = 0; m_Poll = 0;
|
||||
GetGame().GetInputManager().AddActionListener(UIConstants.MENU_ACTION_BACK, EActionTrigger.PRESSED, OnBack);
|
||||
m_Bound = true;
|
||||
ShowPage(0);
|
||||
ShowPage(ERR_AdminPage.MISSION);
|
||||
UpdateActions();
|
||||
RequestSnapshot();
|
||||
}
|
||||
@@ -194,7 +99,7 @@ class ERR_AdminMenu : ChimeraMenuBase
|
||||
UpdateActions();
|
||||
}
|
||||
if (IsFocused() && m_Poll >= 2) RequestSnapshot();
|
||||
if (m_Page != 2) return;
|
||||
if (m_Page != ERR_AdminPage.JOURNAL) return;
|
||||
m_LogPoll += tDelta;
|
||||
if (m_LogPending && m_LogPoll > 5) m_LogPending = false;
|
||||
if (IsFocused() && m_Ready && m_HQ && !m_LogPaused && !m_LogPending && m_LogPoll >= 1)
|
||||
@@ -230,7 +135,7 @@ class ERR_AdminMenu : ChimeraMenuBase
|
||||
SCR_EditBoxComponent edit = SCR_EditBoxComponent.GetEditBoxComponent(key, GetRootWidget());
|
||||
if (edit && edit.IsInWriteMode()) return;
|
||||
}
|
||||
if (m_Page != 0) ShowPage(0);
|
||||
if (m_Page != ERR_AdminPage.MISSION) ShowPage(ERR_AdminPage.MISSION);
|
||||
else Close();
|
||||
}
|
||||
protected void SetText(string name, string value)
|
||||
@@ -238,26 +143,14 @@ class ERR_AdminMenu : ChimeraMenuBase
|
||||
TextWidget widget = TextWidget.Cast(GetRootWidget().FindAnyWidget(name));
|
||||
if (widget) widget.SetText(value);
|
||||
}
|
||||
// Stable page order is also used by the shared navigation bar and native probe.
|
||||
static array<string> Pages() { return {"SettingsPage", "HQPage", "JournalPage", "ModsPage", "FactionsPage", "WorldPage", "IntelPage", "StatusPage", "TerrainsPage", "ItemsPage", "TTSPage", "ForcesPage", "GuardsPage", "SitesPage", "PlanePage", "RecommendationsPage", "WeightsPage", "AllowedItemsPage", "ItemPresetsPage", "AIPage", "StarterPage", "SarkaPage"}; }
|
||||
static array<string> Navigation() { return {"OpenSettings", "OpenHQ", "OpenJournal", "OpenMods", "OpenFactions", "OpenWorld", "OpenIntel", "OpenStatus", "OpenTerrains", "OpenItems", "OpenTTS", "OpenForces", "OpenGuards", "OpenSites", "OpenPlane", "OpenRecommendations", "OpenWeights", "OpenAllowedItems", "OpenItemPresets", "OpenAI", "OpenStarter", "OpenSarka"}; }
|
||||
// Stable IDs are generated from the navigation manifest; extensions use named pages.
|
||||
static array<string> Pages() { return ERR_AdminMenuPages.Pages(); }
|
||||
static array<string> Navigation() { return ERR_AdminMenuPages.Navigation(); }
|
||||
protected void ShowPage(int page)
|
||||
{
|
||||
array<string> pages = Pages();
|
||||
array<string> navigation = Navigation();
|
||||
if (page < 0 || page >= pages.Count()) return;
|
||||
if (!ERR_AdminMenuView.ShowPage(GetRootWidget(), page)) return;
|
||||
m_Page = page;
|
||||
for (int i = 0; i < pages.Count(); i++)
|
||||
{
|
||||
GetRootWidget().FindAnyWidget(pages[i]).SetVisible(i == page);
|
||||
bool selected = i == page || ((page == 12 || page == 13) && i == 11) || ((page == 16 || page == 17 || page == 18 || page == 20) && i == 9) || ((page == 14 || page == 19) && i == 1);
|
||||
GetRootWidget().FindAnyWidget("Selected_" + navigation[i]).SetVisible(selected);
|
||||
ERR_SelectionStyle.Choice(SCR_ButtonTextComponent.GetButtonText(navigation[i], GetRootWidget()), selected);
|
||||
}
|
||||
GetRootWidget().FindAnyWidget("EquipmentNavigation").SetVisible(page == 9 || page == 16 || page == 17 || page == 18 || page == 20);
|
||||
GetRootWidget().FindAnyWidget("Selected_EquipmentOverview").SetVisible(page == 9);
|
||||
ERR_SelectionStyle.Choice(SCR_ButtonTextComponent.GetButtonText("EquipmentOverview", GetRootWidget()), page == 9);
|
||||
if (page == 2) m_LogPoll = 1;
|
||||
if (page == ERR_AdminPage.JOURNAL) m_LogPoll = 1;
|
||||
}
|
||||
protected int m_KeepWeaponState = -1;
|
||||
protected int m_SelfEpiState = -1;
|
||||
@@ -312,8 +205,8 @@ class ERR_AdminMenu : ChimeraMenuBase
|
||||
Widget state = GetRootWidget().FindAnyWidget("recommended_" + addonKey);
|
||||
if (state)
|
||||
{
|
||||
if (entry.Substring(divider + 1, entry.Length() - divider - 1) == "1") state.SetColor(Color.FromRGBA(105, 190, 140, 255));
|
||||
else state.SetColor(Color.FromRGBA(220, 115, 115, 255));
|
||||
if (entry.Substring(divider + 1, entry.Length() - divider - 1) == "1") state.SetColor(Color.FromInt(ERR_MenuTheme.READY_TEXT));
|
||||
else state.SetColor(Color.FromInt(ERR_MenuTheme.UNAVAILABLE_TEXT));
|
||||
}
|
||||
continue;
|
||||
}
|
||||
@@ -435,13 +328,10 @@ class ERR_AdminMenu : ChimeraMenuBase
|
||||
if (!button || !IsFocused()) return;
|
||||
string name = button.GetRootWidget().GetName();
|
||||
if (name == "Close") { Close(); return; }
|
||||
if (name == "RecommendationsBack") { ShowPage(3); return; }
|
||||
if (name == "RecommendedPlane") { ShowPage(14); return; }
|
||||
if (name == "EquipmentOverview") { ShowPage(9); return; }
|
||||
if (name == "RecommendedWeapons") { ShowPage(9); return; }
|
||||
if (name == "PlaneBack") { ShowPage(1); return; }
|
||||
if (name == "AIBack") { ShowPage(1); return; }
|
||||
if (name == "GuardsBack" || name == "SitesBack" || name == "SarkaBack") { ShowPage(11); return; }
|
||||
int section = ERR_AdminMenuPages.MainButtons().Find(name);
|
||||
if (section >= 0) { ShowPage(ERR_AdminMenuPages.MainPage(section)); return; }
|
||||
if (name == "RecommendedPlane") { ShowPage(ERR_AdminPage.PLANE); return; }
|
||||
if (name == "RecommendedWeapons") { ShowPage(ERR_AdminPage.ITEMS); return; }
|
||||
int page = Navigation().Find(name);
|
||||
if (page >= 0) { ShowPage(page); return; }
|
||||
if (name == "JournalDetails")
|
||||
|
||||
@@ -0,0 +1,86 @@
|
||||
// Presentation rules only: all mutations still use the authenticated command service.
|
||||
class ERR_AdminMenuFields
|
||||
{
|
||||
static array<string> Keys()
|
||||
{
|
||||
return {"aiDoctrine", "aiShadow", "automaticEquipmentChancePercent", "sarkaCarsPerAnger", "motorbikeCount", "planeAltitudeMetres", "planeReplacementSeconds", "planeSectorSeconds", "fieldCampCount", "fieldHospitalCount", "startWeaponCount", "startMagazineCount", "objectGuardCount", "objectGuardEvery", "objectGuardHQMode", "hunterSpawnDistanceMetres", "roadblockCount", "civilianTrafficCount", "emptyRestartHours", "startMode", "radioDefenceSeconds", "aiIntelChancePercent", "intelRevealChancePercent", "startTimeMinutes", "timeMultiplier", "startDateCode", "weatherProfile", "viewDistanceMetres", "reportIntervalSeconds", "supportSquadLimit", "responseRadiusMetres", "convoyCount", "antiAirChancePercent", "antiPersonnelMineChancePercent", "heliTimerMinutes"};
|
||||
}
|
||||
static bool Available(string key, bool hq, bool intel)
|
||||
{
|
||||
if (key == "aiDoctrine" || key == "aiShadow") return hq;
|
||||
if (key == "sarkaCarsPerAnger") return hq;
|
||||
if (key == "aiIntelChancePercent") return intel;
|
||||
if (key == "automaticEquipmentChancePercent" || key == "motorbikeCount" || key == "planeAltitudeMetres" || key == "planeReplacementSeconds" || key == "planeSectorSeconds" || key == "planeReconEnabled" || key == "objectGuardCount" || key == "objectGuardEvery" || key == "objectGuardHQMode" || key == "hunterSpawnDistanceMetres" || key == "heliTimerMinutes" || key == "antiAirChancePercent" || key == "antiPersonnelMineChancePercent" || key == "convoyCount" || key == "reportIntervalSeconds" || key == "supportSquadLimit" || key == "responseRadiusMetres") return hq;
|
||||
return Keys().Contains(key);
|
||||
}
|
||||
// A short journal has no older off-screen lines, even if its slider is zero.
|
||||
static bool FollowJournal(bool empty, float slider, float height, float viewHeight, bool latest)
|
||||
{
|
||||
return latest || empty || slider >= 0.98 || height <= viewHeight;
|
||||
}
|
||||
// TextWidget interprets hash-prefixed tokens as localization IDs. Keep the
|
||||
// server audit and retained entries intact; render their numeric IDs literally.
|
||||
static string JournalText(string line, bool details = false)
|
||||
{
|
||||
return ERR_JournalText.Menu(line, details);
|
||||
}
|
||||
static string Display(string key, string value)
|
||||
{
|
||||
if (key == "aiDoctrine") { if (value == "1") return "Coordinated"; return "Current"; }
|
||||
if (key == "aiShadow") { if (value == "1") return "On"; return "Off"; }
|
||||
if (value == "-1" || value == "-2") return ERR_Settings.SelectionText(value.ToInt());
|
||||
if (key == "startMode") { if (value == "1") return "Crash"; return "Prison"; }
|
||||
if (key == "startTimeMinutes") return ERR_TimeService.Clock(value.ToInt());
|
||||
if (key == "startDateCode") return ERR_EnvironmentService.Date(value.ToInt());
|
||||
if (key == "weatherProfile") return ERR_EnvironmentService.ProfileName(value.ToInt());
|
||||
if (key == "viewDistanceMetres" && value == "0") return "default";
|
||||
return value;
|
||||
}
|
||||
static string StartSummary(int saved, int current)
|
||||
{
|
||||
return "Next start: " + Display("startMode", saved.ToString()) + " | Current round: " + Display("startMode", current.ToString());
|
||||
}
|
||||
static string Command(string key, string value)
|
||||
{
|
||||
string prefix;
|
||||
if (key == "aiDoctrine") prefix = "mission doctrine";
|
||||
else if (key == "aiShadow") prefix = "mission aishadow";
|
||||
else if (key == "automaticEquipmentChancePercent") prefix = "hq equipment";
|
||||
else if (key == "sarkaCarsPerAnger") prefix = "mission sarkacars";
|
||||
else if (key == "motorbikeCount") prefix = "mission motorbikes";
|
||||
else if (key == "planeReconEnabled") prefix = "mission plane";
|
||||
else if (key == "planeAltitudeMetres") prefix = "mission planealtitude";
|
||||
else if (key == "planeReplacementSeconds") prefix = "mission planereplacement";
|
||||
else if (key == "planeSectorSeconds") prefix = "mission planesector";
|
||||
else if (key == "startWeaponCount") prefix = "mission startweapons";
|
||||
else if (key == "startMagazineCount") prefix = "mission startammo";
|
||||
else if (key == "objectGuardEvery") prefix = "mission objectevery";
|
||||
else if (key == "objectGuardHQMode") prefix = "mission objecthq";
|
||||
else if (key == "objectGuardCount") prefix = "mission objectguards";
|
||||
else if (key == "hunterSpawnDistanceMetres") prefix = "mission hunterdistance";
|
||||
else if (key == "fieldCampCount") prefix = "mission camps";
|
||||
else if (key == "fieldHospitalCount") prefix = "mission hospitals";
|
||||
else if (key == "roadblockCount") prefix = "mission roadblocks";
|
||||
else if (key == "emptyRestartHours") prefix = "mission emptyhours";
|
||||
else if (key == "civilianTrafficCount") prefix = "mission traffic";
|
||||
else if (key == "startMode") prefix = "mission start";
|
||||
else if (key == "radioDefenceSeconds") prefix = "mission radio";
|
||||
else if (key == "aiIntelChancePercent") prefix = "intel carrying";
|
||||
else if (key == "intelRevealChancePercent") prefix = "intel reveal";
|
||||
else if (key == "startTimeMinutes") prefix = "mission time";
|
||||
else if (key == "timeMultiplier") prefix = "mission speed";
|
||||
else if (key == "startDateCode") prefix = "mission date";
|
||||
else if (key == "weatherProfile") prefix = "mission weather";
|
||||
else if (key == "viewDistanceMetres") prefix = "mission viewdistance";
|
||||
else if (key == "reportIntervalSeconds") prefix = "hq interval";
|
||||
else if (key == "supportSquadLimit") prefix = "hq squads";
|
||||
else if (key == "responseRadiusMetres") prefix = "hq radius";
|
||||
else if (key == "antiAirChancePercent") prefix = "hq aa";
|
||||
else if (key == "antiPersonnelMineChancePercent") prefix = "hq mines";
|
||||
else if (key == "heliTimerMinutes") prefix = "hq heli timer";
|
||||
else if (key == "convoyCount") prefix = "hq convoy count";
|
||||
value = value.Trim();
|
||||
if (prefix.IsEmpty() || value.IsEmpty() || value.Length() > 32) return "";
|
||||
return prefix + " set " + value;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,46 @@
|
||||
// Generated by tools/build_admin_menu.py; edit ui/admin_menu/navigation.json.
|
||||
enum ERR_AdminPage
|
||||
{
|
||||
MISSION = 0,
|
||||
HQ = 1,
|
||||
JOURNAL = 2,
|
||||
MODS = 3,
|
||||
FACTIONS = 4,
|
||||
WORLD = 5,
|
||||
INTEL = 6,
|
||||
STATUS = 7,
|
||||
TERRAINS = 8,
|
||||
ITEMS = 9,
|
||||
SPEECH = 10,
|
||||
FORCES = 11,
|
||||
GUARDS = 12,
|
||||
SITES = 13,
|
||||
PLANE = 14,
|
||||
RECOMMENDATIONS = 15,
|
||||
WEIGHTS = 16,
|
||||
ALLOWED_ITEMS = 17,
|
||||
ITEM_PRESETS = 18,
|
||||
AI = 19,
|
||||
STARTER = 20,
|
||||
SARKA = 21,
|
||||
}
|
||||
|
||||
class ERR_AdminMenuPages
|
||||
{
|
||||
static array<string> Pages() { return {"SettingsPage", "HQPage", "JournalPage", "ModsPage", "FactionsPage", "WorldPage", "IntelPage", "StatusPage", "TerrainsPage", "ItemsPage", "TTSPage", "ForcesPage", "GuardsPage", "SitesPage", "PlanePage", "RecommendationsPage", "WeightsPage", "AllowedItemsPage", "ItemPresetsPage", "AIPage", "StarterPage", "SarkaPage"}; }
|
||||
static array<string> Navigation() { return {"OpenSettings", "OpenHQ", "OpenJournal", "OpenMods", "OpenFactions", "OpenWorld", "OpenIntel", "OpenStatus", "OpenTerrains", "OpenItems", "OpenTTS", "OpenForces", "OpenGuards", "OpenSites", "OpenPlane", "OpenRecommendations", "OpenWeights", "OpenAllowedItems", "OpenItemPresets", "OpenAI", "OpenStarter", "OpenSarka"}; }
|
||||
static array<string> MainButtons() { return {"Main_Mission", "Main_Forces", "Main_HQ", "Main_Intel", "Main_Items", "Main_Mods", "Main_Audio", "Main_Status"}; }
|
||||
static array<string> Sidebars() { return {"Sidebar_Mission", "Sidebar_Forces", "Sidebar_HQ", "Sidebar_Intel", "Sidebar_Items", "Sidebar_Mods", "Sidebar_Audio", "Sidebar_Status"}; }
|
||||
static int Group(int page)
|
||||
{
|
||||
array<int> groups = {0, 2, 7, 5, 1, 0, 3, 7, 0, 4, 6, 1, 1, 1, 2, 5, 4, 4, 4, 2, 4, 1};
|
||||
if (page < 0 || page >= groups.Count()) return -1;
|
||||
return groups[page];
|
||||
}
|
||||
static int MainPage(int group)
|
||||
{
|
||||
array<int> pages = {ERR_AdminPage.MISSION, ERR_AdminPage.FORCES, ERR_AdminPage.HQ, ERR_AdminPage.INTEL, ERR_AdminPage.ITEMS, ERR_AdminPage.MODS, ERR_AdminPage.SPEECH, ERR_AdminPage.STATUS};
|
||||
if (group < 0 || group >= pages.Count()) return -1;
|
||||
return pages[group];
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,26 @@
|
||||
// Widget presentation only. No settings writes, authorization or transport here.
|
||||
class ERR_AdminMenuView
|
||||
{
|
||||
static bool ShowPage(Widget root, int page)
|
||||
{
|
||||
int group = ERR_AdminMenuPages.Group(page);
|
||||
if (!root || group < 0) return false;
|
||||
array<string> pages = ERR_AdminMenuPages.Pages();
|
||||
array<string> navigation = ERR_AdminMenuPages.Navigation();
|
||||
for (int i = 0; i < pages.Count(); i++)
|
||||
{
|
||||
root.FindAnyWidget(pages[i]).SetVisible(i == page);
|
||||
root.FindAnyWidget("Selected_" + navigation[i]).SetVisible(i == page);
|
||||
ERR_SelectionStyle.Choice(SCR_ButtonTextComponent.GetButtonText(navigation[i], root), i == page);
|
||||
}
|
||||
array<string> buttons = ERR_AdminMenuPages.MainButtons();
|
||||
array<string> sidebars = ERR_AdminMenuPages.Sidebars();
|
||||
for (int section = 0; section < buttons.Count(); section++)
|
||||
{
|
||||
root.FindAnyWidget(sidebars[section]).SetVisible(section == group);
|
||||
root.FindAnyWidget("Selected_" + buttons[section]).SetVisible(section == group);
|
||||
ERR_SelectionStyle.Choice(SCR_ButtonTextComponent.GetButtonText(buttons[section], root), section == group);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@@ -7,7 +7,7 @@ modded class ERR_AdminMenu
|
||||
{
|
||||
Open();
|
||||
ERR_AdminMenu menu = GetOpenMenu();
|
||||
if (menu) menu.ShowPage(3);
|
||||
if (menu) menu.ShowPage(ERR_AdminPage.MODS);
|
||||
}
|
||||
override void OnMenuOpen()
|
||||
{
|
||||
|
||||
@@ -0,0 +1,13 @@
|
||||
// Generated by tools/build_admin_menu.py; edit ui/admin_menu/theme.json.
|
||||
class ERR_MenuTheme
|
||||
{
|
||||
static const int NEUTRAL = 0xFF454B52;
|
||||
static const int NEUTRAL_HOVER = 0xFF606870;
|
||||
static const int POSITIVE = 0xFF246B3C;
|
||||
static const int POSITIVE_HOVER = 0xFF31894F;
|
||||
static const int NEGATIVE = 0xFF8F2929;
|
||||
static const int NEGATIVE_HOVER = 0xFFB43B3B;
|
||||
static const int MIXED = 0xFF805B17;
|
||||
static const int READY_TEXT = 0xFF69BE8C;
|
||||
static const int UNAVAILABLE_TEXT = 0xFFDC7373;
|
||||
}
|
||||
@@ -19,16 +19,33 @@ modded class ERR_AdminMenu
|
||||
{
|
||||
GetRootWidget().Update();
|
||||
if (m_Page != expected) return false;
|
||||
int activeGroup = ERR_AdminMenuPages.Group(expected);
|
||||
Widget content = GetRootWidget().FindAnyWidget(Pages()[expected]);
|
||||
if (!content) return false;
|
||||
float contentX, contentY, contentWidth, contentHeight;
|
||||
content.GetScreenPos(contentX, contentY); content.GetScreenSize(contentWidth, contentHeight);
|
||||
array<string> mainButtons = ERR_AdminMenuPages.MainButtons();
|
||||
array<string> sidebars = ERR_AdminMenuPages.Sidebars();
|
||||
for (int group = 0; group < mainButtons.Count(); group++)
|
||||
{
|
||||
Widget mainTab = GetRootWidget().FindAnyWidget(mainButtons[group]);
|
||||
Widget marker = GetRootWidget().FindAnyWidget("Selected_" + mainButtons[group]);
|
||||
Widget sidebar = GetRootWidget().FindAnyWidget(sidebars[group]);
|
||||
if (!mainTab || !marker || !sidebar || !mainTab.IsVisible() || marker.IsVisible() != (group == activeGroup) || sidebar.IsVisible() != (group == activeGroup)) return false;
|
||||
float x, y, width, height;
|
||||
mainTab.GetScreenPos(x, y); mainTab.GetScreenSize(width, height);
|
||||
if (width <= 1 || height <= 1 || y + height > contentY) return false;
|
||||
}
|
||||
for (int i = 0; i < Pages().Count(); i++)
|
||||
{
|
||||
Widget panel = GetRootWidget().FindAnyWidget(Pages()[i]);
|
||||
Widget tab = GetRootWidget().FindAnyWidget(Navigation()[i]);
|
||||
Widget selected = GetRootWidget().FindAnyWidget("Selected_" + Navigation()[i]);
|
||||
if (!panel || !tab || !selected || panel.IsVisible() != (i == expected) || !tab.IsVisible() || selected.IsVisible() != (i == expected)) return false;
|
||||
float x, y, width, height, px, py;
|
||||
tab.GetScreenPos(x, y); tab.GetScreenSize(width, height); panel.GetScreenPos(px, py);
|
||||
if (width <= 1 || height <= 1 || (i == expected && y + height > py))
|
||||
{ PrintFormat("ERR ADMIN NAV BOUNDS: page=%1 tab=%2 bounds=%3,%4,%5,%6 panelY=%7", expected, i, x, y, width, height, py); return false; }
|
||||
if (!panel || !tab || !selected || panel.IsVisible() != (i == expected) || selected.IsVisible() != (i == expected)) return false;
|
||||
if (ERR_AdminMenuPages.Group(i) != activeGroup) continue;
|
||||
float x, y, width, height;
|
||||
tab.GetScreenPos(x, y); tab.GetScreenSize(width, height);
|
||||
if (!tab.IsVisible() || width <= 1 || height <= 1 || x + width > contentX || y < contentY || y + height > contentY + contentHeight) return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -38,6 +38,7 @@ modded class ERR_HQ
|
||||
modded class ERR_GameMode
|
||||
{
|
||||
protected int m_ERRSarkaStage;
|
||||
protected int m_ERRSarkaMenuPage;
|
||||
protected int m_ERRSarkaDeadline;
|
||||
protected bool m_ERRSarkaOrder;
|
||||
protected override void EOnInit(IEntity owner)
|
||||
@@ -66,7 +67,27 @@ modded class ERR_GameMode
|
||||
if (m_ERRSarkaStage == 0)
|
||||
{
|
||||
if (!ERR_SarkaProbeCheck(Settings().Get("sarkaCarsPerAnger") == 1, "default one car per anger point")) return;
|
||||
ERR_AdminMenu.Open(); m_ERRSarkaStage = 10; return;
|
||||
ERR_AdminMenu.Open(); m_ERRSarkaStage = 9; return;
|
||||
}
|
||||
if (m_ERRSarkaStage == 9)
|
||||
{
|
||||
ERR_AdminMenu menu = ERR_AdminMenu.GetOpenMenu();
|
||||
if (!menu || !menu.ERR_SarkaProbeReady()) return;
|
||||
menu.ERR_ProbePage(m_ERRSarkaMenuPage); m_ERRSarkaStage = 90; return;
|
||||
}
|
||||
if (m_ERRSarkaStage == 90)
|
||||
{
|
||||
ERR_AdminMenu menu = ERR_AdminMenu.GetOpenMenu();
|
||||
if (!ERR_SarkaProbeCheck(menu && menu.ERR_ProbeNavigation(m_ERRSarkaMenuPage), "top main tabs and left sidebar reach page " + m_ERRSarkaMenuPage.ToString())) return;
|
||||
System.MakeScreenshot("$logs:err-menu-sidebar-" + m_ERRSarkaMenuPage.ToString());
|
||||
m_ERRSarkaStage = 91; return;
|
||||
}
|
||||
if (m_ERRSarkaStage == 91)
|
||||
{
|
||||
m_ERRSarkaMenuPage++;
|
||||
if (m_ERRSarkaMenuPage < ERR_AdminMenu.Pages().Count()) m_ERRSarkaStage = 9;
|
||||
else m_ERRSarkaStage = 10;
|
||||
return;
|
||||
}
|
||||
if (m_ERRSarkaStage == 10)
|
||||
{
|
||||
|
||||
@@ -4,8 +4,8 @@ class ERR_SelectionStyle
|
||||
static void Action(SCR_ButtonTextComponent button, bool enable)
|
||||
{
|
||||
if (!button) return;
|
||||
Color normal = Color.FromInt(0xFF8F2929), hover = Color.FromInt(0xFFB43B3B);
|
||||
if (enable) { normal = Color.FromInt(0xFF246B3C); hover = Color.FromInt(0xFF31894F); }
|
||||
Color normal = Color.FromInt(ERR_MenuTheme.NEGATIVE), hover = Color.FromInt(ERR_MenuTheme.NEGATIVE_HOVER);
|
||||
if (enable) { normal = Color.FromInt(ERR_MenuTheme.POSITIVE); hover = Color.FromInt(ERR_MenuTheme.POSITIVE_HOVER); }
|
||||
button.SetBackgroundColors(normal, hover, normal, hover, hover);
|
||||
button.ColorizeBackground(false);
|
||||
}
|
||||
@@ -14,11 +14,11 @@ class ERR_SelectionStyle
|
||||
static void Choice(SCR_ButtonTextComponent button, bool selected, bool positive = true)
|
||||
{
|
||||
if (!button) return;
|
||||
Color normal = Color.FromInt(0xFF454B52), hover = Color.FromInt(0xFF606870);
|
||||
Color normal = Color.FromInt(ERR_MenuTheme.NEUTRAL), hover = Color.FromInt(ERR_MenuTheme.NEUTRAL_HOVER);
|
||||
if (selected)
|
||||
{
|
||||
normal = Color.FromInt(0xFF246B3C); hover = Color.FromInt(0xFF31894F);
|
||||
if (!positive) { normal = Color.FromInt(0xFF8F2929); hover = Color.FromInt(0xFFB43B3B); }
|
||||
normal = Color.FromInt(ERR_MenuTheme.POSITIVE); hover = Color.FromInt(ERR_MenuTheme.POSITIVE_HOVER);
|
||||
if (!positive) { normal = Color.FromInt(ERR_MenuTheme.NEGATIVE); hover = Color.FromInt(ERR_MenuTheme.NEGATIVE_HOVER); }
|
||||
}
|
||||
button.SetDisabledOpacity(1);
|
||||
button.SetBackgroundColors(normal, hover, normal, hover, hover);
|
||||
@@ -34,10 +34,10 @@ class ERR_SelectionStyle
|
||||
{
|
||||
SCR_ButtonTextComponent badge = SCR_ButtonTextComponent.GetButtonText(name, parent);
|
||||
if (!badge) return;
|
||||
string label = "Waiting..."; Color color = Color.FromInt(0xFF454B52);
|
||||
if (state == 0) { label = "Disabled"; color = Color.FromInt(0xFF8F2929); }
|
||||
if (state == 1) { label = "Enabled"; color = Color.FromInt(0xFF246B3C); }
|
||||
if (state == 2) { label = "Mixed"; color = Color.FromInt(0xFF805B17); }
|
||||
string label = "Waiting..."; Color color = Color.FromInt(ERR_MenuTheme.NEUTRAL);
|
||||
if (state == 0) { label = "Disabled"; color = Color.FromInt(ERR_MenuTheme.NEGATIVE); }
|
||||
if (state == 1) { label = "Enabled"; color = Color.FromInt(ERR_MenuTheme.POSITIVE); }
|
||||
if (state == 2) { label = "Mixed"; color = Color.FromInt(ERR_MenuTheme.MIXED); }
|
||||
badge.SetText(label); badge.SetDisabledOpacity(1); badge.SetEnabled(false, false);
|
||||
badge.SetBackgroundColors(color, color, color, color, color); badge.ColorizeBackground(false);
|
||||
}
|
||||
|
||||
@@ -216,7 +216,7 @@ modded class ERR_AdminMenu
|
||||
if (button.GetRootWidget() != row.FindAnyWidget("Enable")) continue;
|
||||
SCR_ComboBoxComponent combo = SCR_ComboBoxComponent.GetComboBoxComponent("ItemsMod", GetRootWidget());
|
||||
if (combo) combo.SetCurrentItem(m_ServerAddonKeys.Find(addon), false, false, false);
|
||||
ShowPage(17); SubmitItems("items list " + addon + " 0"); return;
|
||||
ShowPage(ERR_AdminPage.ALLOWED_ITEMS); SubmitItems("items list " + addon + " 0"); return;
|
||||
}
|
||||
}
|
||||
protected void SubmitItems(string command)
|
||||
|
||||
Reference in New Issue
Block a user