diff --git a/IdleSpectator/AgentHarness.cs b/IdleSpectator/AgentHarness.cs index 79bacd9..051ff8a 100644 --- a/IdleSpectator/AgentHarness.cs +++ b/IdleSpectator/AgentHarness.cs @@ -3092,23 +3092,6 @@ public static class AgentHarness break; } - case "saga_hover_panel_dwell": - { - LifeSagaViewController.HarnessSimulatePanelDwell(); - bool ok = LifeSagaViewController.IsHoverPreview; - if (ok) - { - _cmdOk++; - } - else - { - _cmdFail++; - } - - Emit(cmd, ok, detail: $"hoverId={LifeSagaViewController.HoverPreviewId}"); - break; - } - case "saga_hover_tick_away": { LifeSagaViewController.HarnessTickExitAwayFromChrome(); @@ -3142,25 +3125,6 @@ public static class AgentHarness break; } - case "saga_open_lore": - { - LifeSagaViewController.SelectTab(LifeSagaViewController.Tab.Saga); - WatchCaption.RequestRelayout(); - LifeSagaPanel.HarnessOpenLore(); - bool ok = Chronicle.HudVisible; - if (ok) - { - _cmdOk++; - } - else - { - _cmdFail++; - } - - Emit(cmd, ok, detail: $"lore={ok} bound={LifeSagaPanel.BoundUnitId}"); - break; - } - case "saga_select_tab": { string raw = (cmd.value ?? "dossier").Trim().ToLowerInvariant(); @@ -8517,9 +8481,10 @@ public static class AgentHarness int rows = LifeSagaRail.LastHoverRowCount; float height = LifeSagaRail.LastHoverHeight; pass = LifeSagaViewController.EffectiveTab == LifeSagaViewController.Tab.Saga - && height >= 100f - && height <= 200f; - detail = $"snapshot rows={rows} height={height:0.0} tab={LifeSagaViewController.EffectiveTab} compact={pass}"; + && height >= LifeSagaPanel.BodyHeightMin - 0.5f + && height <= LifeSagaPanel.BodyHeightMax + 0.5f; + detail = + $"snapshot rows={rows} height={height:0.0} tab={LifeSagaViewController.EffectiveTab} min={LifeSagaPanel.BodyHeightMin} max={LifeSagaPanel.BodyHeightMax}"; break; } case "saga_tab_selected": @@ -8567,14 +8532,25 @@ public static class AgentHarness detail = $"boundId={model?.UnitId ?? 0} name='{model?.Name}' lens={model?.PrimaryLens}"; break; } - case "saga_panel_evidence": + case "saga_dossier_chrome_restored": + { + bool onDossier = LifeSagaViewController.EffectiveTab == LifeSagaViewController.Tab.Dossier + && !LifeSagaViewController.IsHoverPreview; + bool sagaHidden = !LifeSagaPanel.Visible; + bool chrome = WatchCaption.HarnessDossierChromeRestored(); + pass = onDossier && sagaHidden && chrome; + detail = + $"onDossier={onDossier} sagaHidden={sagaHidden} chrome={chrome} reason='{WatchCaption.LastDetail}'"; + break; + } + case "saga_panel_lens": { LifeSagaViewModel model = LifeSagaViewController.BuildEffectivePresentation(); bool want = ParseBool(cmd.value, defaultValue: true); - bool have = model != null && !string.IsNullOrEmpty(model.EvidenceLine); + bool have = model != null && !string.IsNullOrEmpty(model.LensEyebrow); pass = have == want; detail = - $"evidence='{model?.EvidenceTitle}:{model?.EvidenceLine}' want={want} lens={model?.PrimaryLens}"; + $"lensEyebrow='{model?.LensEyebrow}' want={want} primary={model?.PrimaryLens}"; break; } case "saga_panel_empty": diff --git a/IdleSpectator/HarnessScenarios.cs b/IdleSpectator/HarnessScenarios.cs index 33176a9..6a4e747 100644 --- a/IdleSpectator/HarnessScenarios.cs +++ b/IdleSpectator/HarnessScenarios.cs @@ -3044,16 +3044,14 @@ internal static class HarnessScenarios Step("sad19", "assert", expect: "saga_tab_effective", value: "saga"), Step("sad20", "assert", expect: "saga_hover_preview", value: "true"), Step("sad21", "assert", expect: "saga_read_pause", value: "true"), - // Panel dwell clears the exit timer; leaving chrome must re-arm and restore Dossier. - Step("sad21b", "saga_hover_panel_dwell"), - Step("sad21c", "saga_hover_tick_away"), - Step("sad21d", "wait", wait: 0.1f), - Step("sad21e", "saga_hover_tick_away"), - Step("sad21f", "wait", wait: 0.4f), - Step("sad21g", "saga_hover_tick_away"), + // Leaving the glyph restores Dossier immediately (no panel-dwell keep-alive). + Step("sad21b", "saga_hide_hover"), + Step("sad21d", "saga_hover_tick_away"), Step("sad21h", "assert", expect: "saga_hover_preview", value: "false"), Step("sad21i", "assert", expect: "saga_tab_effective", value: "dossier"), Step("sad21j", "assert", expect: "saga_read_pause", value: "false"), + // Dossier chrome must restore immediately (not wait for a tip ownership change). + Step("sad21j2", "assert", expect: "saga_dossier_chrome_restored"), Step("sad21k", "saga_show_hover_first"), Step("sad21l", "assert", expect: "saga_hover_preview", value: "true"), // Tab click during preview cancels preview and applies the selected tab. @@ -3062,14 +3060,15 @@ internal static class HarnessScenarios Step("sad21o", "assert", expect: "saga_tab_effective", value: "dossier"), Step("sad22", "saga_show_hover_first"), Step("sad22b", "saga_hide_hover"), - Step("sad23", "wait", wait: 0.4f), Step("sad23b", "saga_hover_tick_away"), Step("sad24", "assert", expect: "saga_hover_preview", value: "false"), Step("sad25", "assert", expect: "saga_tab_effective", value: "dossier"), Step("sad26", "assert", expect: "saga_read_pause", value: "false"), Step("sad27", "assert", expect: "saga_overview_tip_not", value: "Fighting |Why |Now |Notable "), Step("sad28", "saga_select_tab", value: "saga"), - Step("sad29", "assert", expect: "saga_panel_evidence", value: "true"), + Step("sad29", "assert", expect: "saga_panel_lens", value: "true"), + Step("sad29b", "assert", expect: "saga_overview_tip_not", + value: "Evidence|kills ·|remembered clashes|Open Lore"), // Non-MC watch with no pin → empty pick state; rail click pins subject. Step("sad30", "interest_saga_clear"), Step("sad31", "spawn", asset: "human", count: 2), @@ -3085,12 +3084,6 @@ internal static class HarnessScenarios Step("sad41", "assert", expect: "saga_panel_empty", value: "false"), Step("sad42", "assert", expect: "saga_panel_bound"), Step("sad43", "screenshot", value: "saga-rail-top"), - // Open Lore from Saga and restore Saga on close. - Step("sad44", "saga_open_lore"), - Step("sad45", "assert", expect: "chronicle_visible", value: "true"), - Step("sad46", "lore_close"), - Step("sad47", "assert", expect: "saga_tab_effective", value: "saga"), - Step("sad48", "assert", expect: "saga_panel_bound"), Step("sad90", "fast_timing", value: "false"), Step("sad99", "snapshot"), }; @@ -3155,7 +3148,7 @@ internal static class HarnessScenarios Step("shp17", "assert", expect: "tip_contains", value: "PauseHold"), Step("shp18", "assert", expect: "tip_not_contains", value: "ShouldNotCut"), Step("shp19", "saga_hide_hover"), - Step("shp20", "wait", wait: 0.35f), + Step("shp20", "saga_hover_tick_away"), Step("shp21", "assert", expect: "saga_read_pause", value: "false"), Step("shp90", "fast_timing", value: "false"), Step("shp99", "snapshot"), diff --git a/IdleSpectator/Story/LifeSagaOverview.cs b/IdleSpectator/Story/LifeSagaOverview.cs index 1d65ef5..132fdea 100644 --- a/IdleSpectator/Story/LifeSagaOverview.cs +++ b/IdleSpectator/Story/LifeSagaOverview.cs @@ -44,12 +44,12 @@ public static class LifeSagaOverview }); } - if (!string.IsNullOrEmpty(model.EvidenceLine)) + if (!string.IsNullOrEmpty(model.LensEyebrow)) { snapshot.Rows.Add(new LifeSagaSnapshotRow { Kind = LifeSagaSnapshotRowKind.Current, - Text = model.EvidenceTitle + ": " + model.EvidenceLine + Text = model.LensEyebrow }); } diff --git a/IdleSpectator/Story/LifeSagaPanel.cs b/IdleSpectator/Story/LifeSagaPanel.cs index cae53f9..c3897e3 100644 --- a/IdleSpectator/Story/LifeSagaPanel.cs +++ b/IdleSpectator/Story/LifeSagaPanel.cs @@ -1,13 +1,13 @@ using System.Collections.Generic; using System.Text; using UnityEngine; -using UnityEngine.Events; using UnityEngine.UI; namespace IdleSpectator; /// -/// Saga body matching Design A (cast + stakes): identity, stake, cast, evidence, legacy, Open Lore. +/// Saga story card: identity + stake beside the portrait, Cast and Legacy full-width under it. +/// No Evidence stats dump and no Open Lore button (L still opens Lore). /// Width is fixed to the tabbed chrome so right-anchored hover cannot slide the rail. /// Height sizes to content (capped) so lines wrap fully instead of ellipsis. /// @@ -28,29 +28,26 @@ public static class LifeSagaPanel private const float ColGap = 6f; private const float CastFace = 16f; private const float CastSlotW = 54f; - private const float LoreH = 11f; private const float SecLabelH = 10f; private const float LineH = 10f; + private const int EyebrowFont = 7; private const int NameFont = 9; private const int TitleFont = 7; private const int StakeFont = 8; private const int BodyFont = 7; private const int MaxCast = 4; private const int MaxLegacy = 5; - private const int BuildVersion = 7; + private const int BuildVersion = 8; private static GameObject _root; private static RectTransform _rootRt; + private static Text _eyebrowText; private static Text _nameText; private static Text _titleText; private static Text _stakeText; private static Text _castHead; - private static Text _evidenceHead; - private static Text _evidenceText; private static Text _legacyHead; private static Text _legacyText; - private static Button _loreBtn; - private static Text _loreBtnLabel; private static readonly CastSlot[] CastSlots = new CastSlot[MaxCast]; private static long _boundId; private static string _speciesId = ""; @@ -93,16 +90,13 @@ public static class LifeSagaPanel Object.Destroy(_root); _root = null; _rootRt = null; + _eyebrowText = null; _nameText = null; _titleText = null; _stakeText = null; _castHead = null; - _evidenceHead = null; - _evidenceText = null; _legacyHead = null; _legacyText = null; - _loreBtn = null; - _loreBtnLabel = null; } _root = new GameObject("LifeSagaPanel", typeof(RectTransform)); @@ -113,6 +107,7 @@ public static class LifeSagaPanel _rootRt.anchorMax = new Vector2(0f, 1f); _rootRt.sizeDelta = new Vector2(BodyWidthFixed, BodyHeightMin); + _eyebrowText = MakeLabel(_root.transform, "SagaEyebrow", EyebrowFont, HudTheme.Muted, FontStyle.Normal); _nameText = MakeLabel(_root.transform, "SagaName", NameFont, HudTheme.ValueOrange, FontStyle.Bold); _titleText = MakeLabel(_root.transform, "SagaTitle", TitleFont, HudTheme.Muted, FontStyle.Normal); _stakeText = MakeLabel(_root.transform, "StakeBody", StakeFont, HudTheme.ValueOrange, FontStyle.Bold); @@ -120,11 +115,6 @@ public static class LifeSagaPanel _stakeText.verticalOverflow = VerticalWrapMode.Overflow; _castHead = MakeLabel(_root.transform, "CastHead", BodyFont, HudTheme.Muted, FontStyle.Bold); _castHead.text = "Cast"; - _evidenceHead = MakeLabel(_root.transform, "EvidenceHead", BodyFont, HudTheme.Muted, FontStyle.Bold); - _evidenceHead.text = "Evidence"; - _evidenceText = MakeLabel(_root.transform, "EvidenceBody", BodyFont, HudTheme.Body, FontStyle.Normal); - _evidenceText.horizontalOverflow = HorizontalWrapMode.Wrap; - _evidenceText.verticalOverflow = VerticalWrapMode.Overflow; _legacyHead = MakeLabel(_root.transform, "LegacyHead", BodyFont, HudTheme.Muted, FontStyle.Bold); _legacyHead.text = "Legacy"; _legacyText = MakeLabel(_root.transform, "LegacyBody", BodyFont, HudTheme.Body, FontStyle.Normal); @@ -136,23 +126,6 @@ public static class LifeSagaPanel CastSlots[i] = BuildCast(i); } - GameObject loreGo = new GameObject("SagaLoreBtn", typeof(RectTransform), typeof(Image), typeof(Button)); - loreGo.transform.SetParent(_root.transform, false); - Image loreBg = loreGo.GetComponent(); - loreBg.color = new Color(0f, 0f, 0f, 0f); - loreBg.raycastTarget = true; - _loreBtn = loreGo.GetComponent