publish eve_orehold_watcher.py
This commit is contained in:
parent
6545b6ca3f
commit
3476f9a4a3
1 changed files with 72 additions and 19 deletions
|
|
@ -293,13 +293,77 @@ def parse_orehold_text(text):
|
||||||
return cur, cap
|
return cur, cap
|
||||||
|
|
||||||
|
|
||||||
|
def capture_window(cls="triuiScreen"):
|
||||||
|
"""Capture the EVE client window via PrintWindow — gets EVE's pixels even when it's
|
||||||
|
behind Discord/unfocused/moved (no overlap, no screen-position dependence). Returns a
|
||||||
|
PIL Image (window-relative, e.g. 3840x2160) or None. Frees GDI handles each call."""
|
||||||
|
if os.name != "nt":
|
||||||
|
return None
|
||||||
|
import ctypes
|
||||||
|
import ctypes.wintypes as wt
|
||||||
|
from PIL import Image
|
||||||
|
u = ctypes.windll.user32
|
||||||
|
g = ctypes.windll.gdi32
|
||||||
|
try:
|
||||||
|
u.SetProcessDPIAware()
|
||||||
|
except Exception:
|
||||||
|
pass
|
||||||
|
hwnd = u.FindWindowW(cls, None)
|
||||||
|
if not hwnd:
|
||||||
|
res = []
|
||||||
|
|
||||||
|
@ctypes.WINFUNCTYPE(ctypes.c_bool, wt.HWND, wt.LPARAM)
|
||||||
|
def _cb(h, _l):
|
||||||
|
n = u.GetWindowTextLengthW(h)
|
||||||
|
if n:
|
||||||
|
b = ctypes.create_unicode_buffer(n + 1)
|
||||||
|
u.GetWindowTextW(h, b, n + 1)
|
||||||
|
if b.value.startswith("EVE -"):
|
||||||
|
res.append(h)
|
||||||
|
return True
|
||||||
|
|
||||||
|
u.EnumWindows(_cb, 0)
|
||||||
|
hwnd = res[0] if res else 0
|
||||||
|
if not hwnd:
|
||||||
|
return None
|
||||||
|
r = wt.RECT()
|
||||||
|
u.GetClientRect(hwnd, ctypes.byref(r))
|
||||||
|
w, h = r.right, r.bottom
|
||||||
|
if w <= 0 or h <= 0:
|
||||||
|
return None
|
||||||
|
hdc = u.GetDC(hwnd)
|
||||||
|
mdc = g.CreateCompatibleDC(hdc)
|
||||||
|
bmp = g.CreateCompatibleBitmap(hdc, w, h)
|
||||||
|
g.SelectObject(mdc, bmp)
|
||||||
|
u.PrintWindow(hwnd, mdc, 2) # PW_RENDERFULLCONTENT (works for DX windows)
|
||||||
|
|
||||||
|
class BMIH(ctypes.Structure):
|
||||||
|
_fields_ = [("biSize", wt.DWORD), ("biWidth", ctypes.c_long), ("biHeight", ctypes.c_long),
|
||||||
|
("biPlanes", wt.WORD), ("biBitCount", wt.WORD), ("biCompression", wt.DWORD),
|
||||||
|
("biSizeImage", wt.DWORD), ("p1", ctypes.c_long), ("p2", ctypes.c_long),
|
||||||
|
("p3", wt.DWORD), ("p4", wt.DWORD)]
|
||||||
|
bmi = BMIH()
|
||||||
|
bmi.biSize = ctypes.sizeof(BMIH); bmi.biWidth = w; bmi.biHeight = -h
|
||||||
|
bmi.biPlanes = 1; bmi.biBitCount = 32; bmi.biCompression = 0
|
||||||
|
buf = ctypes.create_string_buffer(w * h * 4)
|
||||||
|
g.GetDIBits(mdc, bmp, 0, h, buf, ctypes.byref(bmi), 0)
|
||||||
|
img = Image.frombuffer("RGB", (w, h), buf, "raw", "BGRX", 0, 1)
|
||||||
|
g.DeleteObject(bmp); g.DeleteDC(mdc); u.ReleaseDC(hwnd, hdc) # avoid GDI leak
|
||||||
|
return img
|
||||||
|
|
||||||
|
|
||||||
def grab_region(region):
|
def grab_region(region):
|
||||||
|
"""Crop a WINDOW-RELATIVE region from the EVE window capture (occlusion-proof).
|
||||||
|
Falls back to absolute-screen grab if the EVE window can't be found."""
|
||||||
|
img = capture_window()
|
||||||
|
if img is not None:
|
||||||
|
l, t, ww, hh = region
|
||||||
|
return img.crop((l, t, l + ww, t + hh))
|
||||||
import mss
|
import mss
|
||||||
from PIL import Image
|
from PIL import Image
|
||||||
left, top, width, height = region
|
left, top, width, height = region
|
||||||
with mss.mss() as sct:
|
with mss.mss() as sct:
|
||||||
raw = sct.grab({"left": left, "top": top, "width": width,
|
raw = sct.grab({"left": left, "top": top, "width": width, "height": height})
|
||||||
"height": height})
|
|
||||||
return Image.frombytes("RGB", raw.size, raw.bgra, "raw", "BGRX")
|
return Image.frombytes("RGB", raw.size, raw.bgra, "raw", "BGRX")
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -347,24 +411,13 @@ def _detect_readout(cp, img, mon_left=0, mon_top=0, save=True, scale=1):
|
||||||
|
|
||||||
|
|
||||||
def auto_region(cp):
|
def auto_region(cp):
|
||||||
"""Scan the whole screen for the ore-hold readout and save its location —
|
"""Find the ore-hold 'X / Y m³' readout WITHIN the EVE window capture (clean,
|
||||||
replaces the manual --snip. Just have the in-game Ore Hold window open."""
|
occlusion-proof). Returns a WINDOW-RELATIVE region. Have the Ore Hold window open."""
|
||||||
import mss
|
img = capture_window()
|
||||||
from PIL import Image
|
if img is None:
|
||||||
try:
|
|
||||||
with mss.mss() as sct:
|
|
||||||
mon = sct.monitors[0] # full virtual desktop (all screens)
|
|
||||||
raw = sct.grab(mon)
|
|
||||||
img = Image.frombytes("RGB", raw.size, raw.bgra, "raw", "BGRX")
|
|
||||||
# crop the center band (where EVE sits) then upscale, so small m³ text is readable
|
|
||||||
W, Hh = img.size
|
|
||||||
cx0, cy0 = int(W * 0.22), 0
|
|
||||||
crop = img.crop((cx0, cy0, int(W * 0.82), int(Hh * 0.97)))
|
|
||||||
up = crop.resize((crop.width * 2, crop.height * 2))
|
|
||||||
except Exception as e:
|
|
||||||
print(f"[ocr] auto-detect error: {e}")
|
|
||||||
return None
|
return None
|
||||||
return _detect_readout(cp, up, mon["left"] + cx0, mon["top"] + cy0, scale=2)
|
up = img.resize((img.width * 2, img.height * 2)) # upscale so small m³ text reads
|
||||||
|
return _detect_readout(cp, up, 0, 0, scale=2) # window-relative (origin 0,0)
|
||||||
|
|
||||||
|
|
||||||
def run_ocr(cp):
|
def run_ocr(cp):
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue