Skip to content

Commit a93fa19

Browse files
authored
Merge pull request #331 from Integration-Automation/feat/wait-color-batch
Add wait-for-region-colour (appear/vanish)
2 parents e826894 + d4dc012 commit a93fa19

15 files changed

Lines changed: 296 additions & 9 deletions

File tree

README/WHATS_NEW_zh-CN.md

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,11 @@
11
# 本次更新 — AutoControl
22

3+
## 本次更新 (2026-06-23) — 等待区域颜色
4+
5+
阻塞直到某颜色填满(或离开)屏幕区域。完整参考:[`docs/source/Zh/doc/new_features/v121_features_doc.rst`](../docs/source/Zh/doc/new_features/v121_features_doc.rst)
6+
7+
- **`wait_until_color`**(`AC_wait_color`):`wait_for_pixel` 精确比对单点、`wait_until_pixel_changes` 检测单点任何变化——两者都无法等「状态灯变绿」/「进度条填满」/「红色横幅消失」。本功能计数区域中接近 `target_rgb`(在 `tolerance` 内)的像素,当比例越过 `min_fraction`(或 `present=False` 时低于)即成功。可注入 sampler、无头可测。纯标准库。
8+
39
## 本次更新 (2026-06-23) — 相对鼠标移动
410

511
从当前位置将指针位移一个增量。完整参考:[`docs/source/Zh/doc/new_features/v120_features_doc.rst`](../docs/source/Zh/doc/new_features/v120_features_doc.rst)

README/WHATS_NEW_zh-TW.md

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,11 @@
11
# 本次更新 — AutoControl
22

3+
## 本次更新 (2026-06-23) — 等待區域顏色
4+
5+
阻塞直到某顏色填滿(或離開)螢幕區域。完整參考:[`docs/source/Zh/doc/new_features/v121_features_doc.rst`](../docs/source/Zh/doc/new_features/v121_features_doc.rst)
6+
7+
- **`wait_until_color`**(`AC_wait_color`):`wait_for_pixel` 精確比對單點、`wait_until_pixel_changes` 偵測單點任何變化——兩者都無法等「狀態燈變綠」/「進度條填滿」/「紅色橫幅消失」。本功能計數區域中接近 `target_rgb`(在 `tolerance` 內)的像素,當比例越過 `min_fraction`(或 `present=False` 時低於)即成功。可注入 sampler、無頭可測。純標準函式庫。
8+
39
## 本次更新 (2026-06-23) — 相對滑鼠移動
410

511
從目前位置將指標位移一個增量。完整參考:[`docs/source/Zh/doc/new_features/v120_features_doc.rst`](../docs/source/Zh/doc/new_features/v120_features_doc.rst)

WHATS_NEW.md

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,11 @@
11
# What's New — AutoControl
22

3+
## What's new (2026-06-23) — Wait for Region Colour
4+
5+
Block until a colour fills (or leaves) a screen region. Full reference: [`docs/source/Eng/doc/new_features/v121_features_doc.rst`](docs/source/Eng/doc/new_features/v121_features_doc.rst).
6+
7+
- **`wait_until_color`** (`AC_wait_color`): `wait_for_pixel` matches one point exactly and `wait_until_pixel_changes` detects any change at one point — neither waits for "the status light turns green" / "the progress bar fills" / "the red banner is gone". This counts pixels within `tolerance` of `target_rgb` over a region and succeeds when that fraction crosses `min_fraction` (or drops below it, `present=False`). Injectable sampler, headless-testable. Pure-stdlib.
8+
39
## What's new (2026-06-23) — Relative Mouse Movement
410

511
Nudge the pointer by a delta from where it is. Full reference: [`docs/source/Eng/doc/new_features/v120_features_doc.rst`](docs/source/Eng/doc/new_features/v120_features_doc.rst).
Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
Wait for Region Colour
2+
======================
3+
4+
``wait_for_pixel`` matches a single point exactly and ``wait_until_pixel_changes``
5+
detects *any* change at one point — neither answers "wait until this status light
6+
turns green", "until the progress bar is mostly filled", or "until the red error
7+
banner is gone". This adds a region-colour wait to the ``smart_waits`` family.
8+
9+
The pixel counting is a pure helper and :func:`wait_until_color` takes an
10+
injectable ``sampler``, so the loop is headless-testable without a real screen.
11+
Imports no ``PySide6``.
12+
13+
Headless API
14+
------------
15+
16+
.. code-block:: python
17+
18+
from je_auto_control import wait_until_color
19+
20+
# wait until ≥ 60% of the region is (near) green
21+
wait_until_color(region=[10, 10, 210, 40], target_rgb=[0, 200, 0],
22+
tolerance=15, min_fraction=0.6, timeout_s=20)
23+
24+
# wait until a red banner disappears
25+
wait_until_color(region=[0, 0, 800, 60], target_rgb=[200, 0, 0],
26+
present=False, timeout_s=10)
27+
28+
Pixels within ``tolerance`` (per channel) of ``target_rgb`` are counted. With
29+
``present=True`` the wait succeeds once that fraction reaches ``min_fraction``;
30+
with ``present=False`` once it drops below it. The result is a ``WaitOutcome``
31+
(``succeeded`` / ``reason`` / ``elapsed_s`` / ``samples_taken``).
32+
33+
Executor commands
34+
-----------------
35+
36+
``AC_wait_color`` takes ``target_rgb`` (and optional ``region``) as JSON arrays
37+
plus ``tolerance`` / ``min_fraction`` / ``present`` / ``timeout_s`` /
38+
``poll_interval_s``, and returns the ``WaitOutcome`` dict. It is exposed as the
39+
MCP tool ``ac_wait_color`` and as a Script Builder command under **Flow**.

docs/source/Eng/eng_index.rst

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -143,6 +143,7 @@ Comprehensive guides for all AutoControl features.
143143
doc/new_features/v118_features_doc
144144
doc/new_features/v119_features_doc
145145
doc/new_features/v120_features_doc
146+
doc/new_features/v121_features_doc
146147
doc/ocr_backends/ocr_backends_doc
147148
doc/observability/observability_doc
148149
doc/operations_layer/operations_layer_doc
Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
等待區域顏色
2+
============
3+
4+
``wait_for_pixel`` 精確比對單一點,``wait_until_pixel_changes`` 偵測單點的*任何*變化——兩者都無法回答
5+
「等到狀態燈變綠」、「等到進度條大致填滿」或「等到紅色錯誤橫幅消失」。本功能為 ``smart_waits`` 家族加入
6+
區域顏色等待。
7+
8+
像素計數為純函式輔助,:func:`wait_until_color` 接受可注入的 ``sampler``,因此迴圈可在無真實螢幕下測試。
9+
不匯入 ``PySide6``。
10+
11+
無頭 API
12+
--------
13+
14+
.. code-block:: python
15+
16+
from je_auto_control import wait_until_color
17+
18+
# 等到區域中 ≥ 60% 為(接近)綠色
19+
wait_until_color(region=[10, 10, 210, 40], target_rgb=[0, 200, 0],
20+
tolerance=15, min_fraction=0.6, timeout_s=20)
21+
22+
# 等到紅色橫幅消失
23+
wait_until_color(region=[0, 0, 800, 60], target_rgb=[200, 0, 0],
24+
present=False, timeout_s=10)
25+
26+
在 ``tolerance``(各通道)內接近 ``target_rgb`` 的像素會被計數。``present=True`` 時,當該比例達到
27+
``min_fraction`` 即成功;``present=False`` 時,當其低於該值即成功。結果為 ``WaitOutcome``
28+
(``succeeded`` / ``reason`` / ``elapsed_s`` / ``samples_taken``)。
29+
30+
執行器命令
31+
----------
32+
33+
``AC_wait_color`` 接受 ``target_rgb``(與選用的 ``region``)為 JSON 陣列,以及 ``tolerance`` / ``min_fraction`` /
34+
``present`` / ``timeout_s`` / ``poll_interval_s``,並回傳 ``WaitOutcome`` dict。它以 MCP 工具 ``ac_wait_color``
35+
以及 Script Builder 中 **Flow** 分類下的命令提供。

docs/source/Zh/zh_index.rst

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -143,6 +143,7 @@ AutoControl 所有功能的完整使用指南。
143143
doc/new_features/v118_features_doc
144144
doc/new_features/v119_features_doc
145145
doc/new_features/v120_features_doc
146+
doc/new_features/v121_features_doc
146147
doc/ocr_backends/ocr_backends_doc
147148
doc/observability/observability_doc
148149
doc/operations_layer/operations_layer_doc

je_auto_control/__init__.py

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -610,10 +610,11 @@
610610
)
611611
# Smart waits (frame-diff replacements for time.sleep)
612612
from je_auto_control.utils.smart_waits import (
613-
WaitOutcome, wait_until_clipboard_changes, wait_until_file,
614-
wait_until_gone, wait_until_image_gone, wait_until_pixel_changes,
615-
wait_until_port, wait_until_process, wait_until_region_idle,
616-
wait_until_screen_stable, wait_until_text_gone, wait_until_window_closed,
613+
WaitOutcome, wait_until_clipboard_changes, wait_until_color,
614+
wait_until_file, wait_until_gone, wait_until_image_gone,
615+
wait_until_pixel_changes, wait_until_port, wait_until_process,
616+
wait_until_region_idle, wait_until_screen_stable, wait_until_text_gone,
617+
wait_until_window_closed,
617618
)
618619
# Visual regression (golden-image comparison)
619620
from je_auto_control.utils.visual_regression import (
@@ -1242,6 +1243,7 @@ def start_autocontrol_gui(*args, **kwargs):
12421243
"wait_until_clipboard_changes", "wait_until_window_closed",
12431244
"wait_until_file", "wait_until_port", "wait_until_process",
12441245
"wait_until_gone", "wait_until_image_gone", "wait_until_text_gone",
1246+
"wait_until_color",
12451247
# Visual regression + state machine
12461248
"take_golden", "compare_to_golden", "image_difference",
12471249
"DiffResult", "MaskRegion",

je_auto_control/gui/script_builder/command_schema.py

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -478,6 +478,22 @@ def _add_flow_specs(specs: List[CommandSpec]) -> None:
478478
),
479479
description="Block until on-screen text (OCR) disappears.",
480480
))
481+
specs.append(CommandSpec(
482+
"AC_wait_color", "Flow", "Wait for Region Colour",
483+
fields=(
484+
FieldSpec("target_rgb", FieldType.STRING, placeholder="[0, 200, 0]"),
485+
FieldSpec("region", FieldType.STRING, optional=True,
486+
placeholder="[left, top, right, bottom]"),
487+
FieldSpec("tolerance", FieldType.INT, optional=True, default=10),
488+
FieldSpec("min_fraction", FieldType.FLOAT, optional=True,
489+
default=0.5, min_value=0.0, max_value=1.0),
490+
FieldSpec("present", FieldType.BOOL, optional=True, default=True),
491+
FieldSpec("timeout_s", FieldType.FLOAT, optional=True, default=10.0),
492+
FieldSpec("poll_interval_s", FieldType.FLOAT, optional=True,
493+
default=0.2, min_value=0.01),
494+
),
495+
description="Block until a colour fills (or leaves) a screen region.",
496+
))
481497
specs.append(CommandSpec(
482498
"AC_loop", "Flow", "Loop (N times)",
483499
fields=(

je_auto_control/utils/executor/action_executor.py

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -384,6 +384,24 @@ def _wait_text_gone(text: str, timeout_s: float = 10.0,
384384
).to_dict()
385385

386386

387+
def _wait_color(target_rgb: Any, region: Any = None,
388+
tolerance: int = 10, min_fraction: float = 0.5,
389+
present: bool = True, timeout_s: float = 10.0,
390+
poll_interval_s: float = 0.2) -> Dict[str, Any]:
391+
"""Executor adapter: wait until a colour fills/leaves a region."""
392+
import json
393+
from je_auto_control.utils.smart_waits import wait_until_color
394+
if isinstance(target_rgb, str):
395+
target_rgb = json.loads(target_rgb)
396+
if isinstance(region, str):
397+
region = json.loads(region) if region.strip() else None
398+
return wait_until_color(
399+
region=region, target_rgb=target_rgb, tolerance=int(tolerance),
400+
min_fraction=float(min_fraction), present=bool(present),
401+
timeout_s=float(timeout_s), poll_interval_s=float(poll_interval_s),
402+
).to_dict()
403+
404+
387405
def _wait_window_closed(title: str, case_sensitive: bool = False,
388406
timeout_s: float = 10.0,
389407
poll_interval_s: float = 0.2) -> Dict[str, Any]:
@@ -5012,6 +5030,7 @@ def __init__(self):
50125030
"AC_wait_clipboard_change": _wait_clipboard_change,
50135031
"AC_wait_image_gone": _wait_image_gone,
50145032
"AC_wait_text_gone": _wait_text_gone,
5033+
"AC_wait_color": _wait_color,
50155034
"AC_wait_window_closed": _wait_window_closed,
50165035

50175036
# Cost telemetry (LLM token + USD tracking)

0 commit comments

Comments
 (0)