Files
dwarf-fortress-annals/scripts/df-screen.py
T

104 lines
3.2 KiB
Python

#!/usr/bin/env python3
"""从 DFHack 文本截图中按文字定位控件,并生成点击坐标。
配合 dfannals/screentext 与 dfannals/click 使用:
1) dfhack-run dfannals/screentext
2) scripts/df-screen.py click --label "History length" --text "250 years"
屏幕文本文件里第 1 行是表头,因此 屏幕 y = 文件行号 - 2。
坐标为 0 起始的字符网格坐标,与 dfannals/click 一致。
"""
from __future__ import annotations
import argparse
import sys
from pathlib import Path
SCREEN = Path("/mnt/c/Users/23518/DwarfFortress/dfannals-screen.txt")
def read_screen(path: Path) -> list[str]:
if not path.is_file():
sys.exit(f"找不到截图文件:{path}")
raw = path.read_text(encoding="utf-8", errors="replace").splitlines()
return raw[1:] # 去掉 "# focus=..." 表头,使下标 = 屏幕 y
def char_index(line: str, needle: str) -> int:
return line.find(needle)
def find_row(lines: list[str], needle: str, start: int = 0) -> int:
for i in range(start, len(lines)):
if needle in lines[i]:
return i
return -1
def cmd_list(args: argparse.Namespace) -> int:
lines = read_screen(args.file)
for y, line in enumerate(lines):
if line.strip():
print(f"{y:3} | {line.rstrip()}")
return 0
def cmd_click(args: argparse.Namespace) -> int:
lines = read_screen(args.file)
start = 0
if args.label:
label_row = find_row(lines, args.label)
if label_row < 0:
sys.exit(f"界面上找不到标签:{args.label}")
start = label_row
row = find_row(lines, args.text, start)
if row < 0:
sys.exit(f"找不到文字:{args.text}" + (f"(在 {args.label} 之下)" if args.label else ""))
line = lines[row]
idx = char_index(line, args.text)
x = idx + len(args.text) // 2
y = row
print(f"{x} {y}")
if args.verbose:
print(f"# 第 {row} 行,列 {idx},点击中心 ({x}, {y})", file=sys.stderr)
return 0
def cmd_where(args: argparse.Namespace) -> int:
lines = read_screen(args.file)
for pattern in args.patterns:
row = find_row(lines, pattern)
if row < 0:
print(f"{pattern}: 未找到")
continue
idx = char_index(lines[row], pattern)
print(f"{pattern}: x={idx + len(pattern) // 2} y={row}")
return 0
def main() -> int:
parser = argparse.ArgumentParser(description="DF 文本截图定位工具")
parser.add_argument("--file", type=Path, default=SCREEN)
sub = parser.add_subparsers(dest="cmd", required=True)
p = sub.add_parser("list", help="列出非空行(带屏幕 y 坐标)")
p.set_defaults(func=cmd_list)
p = sub.add_parser("click", help="输出某段文字的中心坐标")
p.add_argument("--label", help="先定位这个标签,再在它下面找目标文字")
p.add_argument("--text", required=True, help="要点击的文字")
p.add_argument("-v", "--verbose", action="store_true")
p.set_defaults(func=cmd_click)
p = sub.add_parser("where", help="批量定位若干文字")
p.add_argument("patterns", nargs="+")
p.set_defaults(func=cmd_where)
args = parser.parse_args()
return args.func(args)
if __name__ == "__main__":
sys.exit(main())