diff options
| author | Somhairle H. Marisol <[email protected]> | 2026-09-29 15:44:35 +0800 |
|---|---|---|
| committer | Somhairle H. Marisol <[email protected]> | 2026-09-29 15:44:35 +0800 |
| commit | dce50b835235a103af1d8e6ec836fe12d841f135 (patch) | |
| tree | 820d2a5f8a092e66e31b5ca06527302dd81735ed /src/LivingVillage.Desktop/Interaction.fs | |
| parent | 21b03c043466c3cbce1d71ff055c9d71631b6073 (diff) | |
| download | living-village-dce50b835235a103af1d8e6ec836fe12d841f135.tar.gz | |
p77: 日历卡/浮动提示药丸化并修复面板遮挡快捷栏
- DrawCalendarCard 改半透明底+1px 描边+accent 发丝线,日历卡微缩(52→48)
- FloatingPrompt 新增 layoutWrapped/wrapText,锚定长文本逐字折行(不丢字、居中锚点、避让 HUD 带)
- 新增 HudLayout.panelRect,DrawPanel 用其几何;DialogOverlay.bottomMargin 24→72
1280x720 下对话 rect 底 648、任务面板底 652,均 < hotbar 顶 660,不再压 3-8 号槽
- 新增 P77LayoutTests(4 尺寸不破版/不遮挡 + 真实长提示折行)
- 证据 LV_P43/P44/P67_SHOT + scripts/analyze-p77.py(verdict PASS) 落 docs/evidence/p77-*
- Desktop 361/361, Kernel 120/120, digest 953775FA...F7F6C 不变
Diffstat (limited to 'src/LivingVillage.Desktop/Interaction.fs')
| -rw-r--r-- | src/LivingVillage.Desktop/Interaction.fs | 53 |
1 files changed, 53 insertions, 0 deletions
diff --git a/src/LivingVillage.Desktop/Interaction.fs b/src/LivingVillage.Desktop/Interaction.fs index 3a65e8e..5281180 100644 --- a/src/LivingVillage.Desktop/Interaction.fs +++ b/src/LivingVillage.Desktop/Interaction.fs @@ -211,6 +211,59 @@ module FloatingPrompt = let y = max topSafe (min bottomSafe screenY) { X = x; Y = y; Width = width; Height = height } + /// P77:锚定提示支持长文本折行(逐字、不丢字),供真实用例(如「E 与河边的货郎交谈并查看货品」)。 + let maxPromptWidth = 360 + + type PromptLayout = + { Lines: string list + X: int + Y: int + Width: int + Height: int } + + let wrapText (maxWidth: int) (scale: int) (text: string) : string list = + if text = "" then + [ "" ] + else + let builder = System.Text.StringBuilder() + let mutable lines = [] + for ch in text.ToCharArray() do + let candidate = builder.ToString() + string ch + if builder.Length > 0 && measureWidth candidate scale > maxWidth then + lines <- builder.ToString() :: lines + builder.Clear() |> ignore + builder.Append(ch) |> ignore + else + builder.Append(ch) |> ignore + lines <- builder.ToString() :: lines + List.rev lines + + /// 锚定点的多行提示版式:按需折行、水平居中于目标、垂直钳制在两条 HUD 带之间。 + let layoutWrapped + (viewportWidth: int) + (viewportHeight: int) + (anchorWorldX: float32) + (anchorWorldY: float32) + (cameraX: float32) + (cameraY: float32) + (scale: int) + (text: string) : PromptLayout = + let margin = 8 + let wrapWidth = min maxPromptWidth (max 80 (viewportWidth - 2 * margin)) + let lines = wrapText wrapWidth scale text + let width = lines |> List.map (fun line -> measureWidth line scale) |> List.max + let lineHeight = 8 * scale + 4 + let height = lines.Length * lineHeight + 10 + let screenX = int anchorWorldX - int cameraX - width / 2 + let screenY = int anchorWorldY - int cameraY - 24 - height + let x = + if width + margin * 2 > viewportWidth then margin + else max margin (min (viewportWidth - margin - width) screenX) + let topSafe = hudTopBarHeight + margin + let bottomSafe = max topSafe (viewportHeight - hudBottomBandHeight - height - margin) + let y = max topSafe (min bottomSafe screenY) + { Lines = lines; X = x; Y = y; Width = width; Height = height } + module M5Interaction = let initial : M5View = |
