Visual Builder guide

No-Code Workspace — Block Reference

Choose a block from the selector below or, on desktop, from the left rail. Every block includes purpose, parameters, common scenarios, cautions, and an in-app screenshot.

Select -> Configure -> Connect -> Verify

Professional no-code workflow map

Cross-macro local library

Local Shared Macro Area

The Local Shared Macro Area moves blocks, variables, dialog fields, gallery assets, and imported media dependencies between macros on the same device. It is device-local, not cloud sync, not Firebase sharing, and not a replacement for public macro sharing.

Professional usage model: put a reusable login flow, common scan region, shared dialog form, variable group, template image, color profile, replay recording, or imported PLAY_SOUND media file into the shared area from one macro, then import it from the relevant + menu in another macro.

VISUAL_BLOCKSVARIABLESDIALOG_FIELDSTEMPLATE_IMAGECOLOR_SWATCHREPLAY_RECORDMEDIA_FILE
1

Send to the shared area

When one item or a multi-selection is active, the shared-area button can copy the selected part from the workspace, group, true/false action branch, dialog, and variables surfaces into the device-local library.

2

Import into another macro

The shared-area entry under the + menu imports the selected item into the surface that opened it. Main workspace, group, action branch, dialog, and variables each receive the compatible item type.

3

Share gallery assets

Gallery items include template images, color swatches, replay records, and imported audio/media files. They can move between macros on the same device so repeated templates, colors, recordings, and PLAY_SOUND media assets do not need to be captured again.

4

Keep it clean

The shared area is not a permanent dumping ground. Delete stale shared items from the shared-library panel; imports create a copy in the target macro and do not rewrite the source macro flow.

Checkpoint: after importing, review block names, linked template/image/color/record/media assets, and variable names in the target macro. The shared area creates a copy; delete stale shared items from the shared-library panel to keep the library clean.

AI assistant

Build a block chain with MH AI in natural language

Tell MH AI what you want in plain language; it proposes the right block sequence and lands it in the workspace after you approve. In the current release it works with cloud providers such as Gemini, Claude, and OpenAI; on-device local models are on the roadmap.

Learn more
SearchBlock usage recipe

Image (IMAGE)

Searches for a template image on screen

Block Preview

Captured from the in-app Visual Builder block card in the English UI.

v1.0.36English UI
Image (IMAGE) block card

Block Preview

Captured from the English Visual Builder block card with the Advanced/extra settings panel expanded.

v1.0.36English UI
Image (IMAGE) advanced settings panel

What Does It Do?

Searches for a specific template inside the selected scan region. Goes to TRUE if a match is found, FALSE otherwise. Scanning runs with a single selected engine; there is no automatic full-screen fallback.

Pro note: region strategy matters

IMAGE is not only about choosing one template. In the builder, multiple regions and per-region excludes are a core part of making the flow stable.

Shared Mechanics for Search Blocks

Multiple search regions and exclude regions

IMAGE, TEXT, COLOR, and OCR-related blocks can define multiple search regions. Each region can also carry its own exclude region to remove noisy areas and reduce false matches.

Sticky anchors for edge-aware scaling

You can now assign a sticky anchor to each search region. This brings Region.sticky into the no-code surface so the region can stay aligned to anchors such as top_left, bottom_right, or center when screen geometry changes.

Scan rate, timeout, and retry behavior

Search timeout defines one search window. Retry on true, retry on false, and waitUntilFound turn a block into a one-shot check or controlled polling step. scanRateHz controls attempts per second.

Match tuning and device variance

mScore, scale, and scan engine choices matter across themes, display sizes, and rendering differences. Smaller regions plus the right engine dramatically improve builder stability.

When to Use?

1

Use when you want to check if any screen element is visible:

2

Checking if a button appeared

3

Detecting if a notification or alert opened

4

Waiting for a loading screen to finish

5

Verifying navigation to a specific page

6

Checking if any icon or visual element exists

How to Use?

1

Add "Image (IMAGE)" block

2

Capture the template with "Select Template"

3

SCAN REGION: Always constrain the search area (smaller = faster)

4

SCAN ENGINE: quick_image / balanced_image / precision_image / color_aware_image / small_object_image

5

MATCH RATIO (mScore): lower = flexible, higher = stricter

6

SCALE: adjust for device differences

7

SEARCH TIMEOUT: 0 = single attempt

8

If retry is needed, set SCAN RATE (Hz): attempts per second

9

Configure TRUE/FALSE branches

10

ADVANCED — SCORE & POSITION: name a "Score Variable" (e.g. matchScore) and write the match location into matchX/matchY/matchW/matchH; then COMPARE on the score or CLICK {matchX} to act where it was found

11

ADVANCED — MULTI-MATCH: if the template appears in many spots, set the selection mode (First / Highest Score / Closest to Centre / Random)

Parameters

Template

Image to search for. Capture from screen or select from gallery

Scan Region

Screen area to search [x, y, width, height]. Smaller = faster

Match Ratio (mScore)

0.10-0.99 range. 0.80 default. Low = flexible, high = exact. Slider + manual + variable supported

Scale

1.0 = original. For different screen resolutions. Slider + manual + variable supported

Scan Engine

quick_image / balanced_image / precision_image / color_aware_image / small_object_image

Search Timeout

0 = single try, 5000 = try for 5sec. Slider 0-30000ms + variable supported

Scan Rate (Hz)

Attempts per second in retry mode. 1-30 Hz

Wait Before (ms)

Wait before searching. Slider 0-5000ms + variable supported

Wait After (ms)

Wait after searching. Slider 0-5000ms + variable supported

Retry Modes

Retry on true / Retry on false / Infinite / Wait until found

Score Variable (Advanced)

In Advanced, type a variable name (e.g. matchScore) and the 0.0–1.0 confidence (1.0 = perfect match) is written there the moment a match is found. Left empty, the score is computed but discarded. Right after, COMPARE "matchScore >= 0.90" to separate weak from strong matches — a second smarter gate over the risky grey zone just above the threshold.

Match Position (matchX/Y/W/H) (Advanced)

Writes the match X/Y and box width/height into your own variables (e.g. matchX, matchY, matchW, matchH). Once stored, feed them into later blocks via {x}: CLICK {matchX},{matchY} to act where it was found, or MATH_EVAL to target a neighbour (delX = matchX + matchW + 60). Because the position lives in a variable it survives across other steps, loops, and waits.

Multi-Match Selection (Advanced)

When the template is found in many spots at once (20 chests, 10 "Claim" buttons), chooses which one is handed to the next action: First (in scan order), Highest Score (clearest), Closest to Centre (near the region middle), or Random (different each run). Put a "Click on Match" CLICK on TRUE and wrap IMAGE+CLICK in a GROUP loop to process the whole field.

Example Usage

1

Scenario 1: Auto-click "OK" button when it appears

2

Add IMAGE → save "OK" button as template

3

Scan region: Area where button can appear

4

Add CLICK to TRUE → enable "Click on match"

5

Retry: "Retry on false" (waits until button appears)

6

Scenario 2: Wait for loading screen to finish

7

IMAGE → save loading icon as template

8

Retry: "Retry on true" (waits until icon disappears)

9

In FALSE: Loading done, proceed to next step

10

Scenario 3 (game farming, multi-target): A field has 15 identical resource nodes

11

IMAGE → save the node template, scan region covering the whole field

12

Advanced → Multi-Match Selection: Highest Score (clearest node each pass)

13

Add a "Click on match" CLICK on the TRUE branch

14

Wrap IMAGE+CLICK in a GROUP loop → as earlier copies are consumed it picks the next, harvesting the whole field

Combinations / Used With

1

MOST COMMON COMBINATIONS:

2

IMAGE + CLICK: Find something and click it

3

IMAGE + WAIT: Wait for something to appear/disappear

4

IMAGE + SWIPE: Swipe when something is found

5

IMAGE + IMAGE: Multiple visual checks in sequence

6

IMAGE + COMPARE: Make decisions based on found position

7

IMAGE + COMPARE (branch on score): Compare the score variable to a threshold (matchScore >= 0.92)

8

IMAGE + CLICK {matchX}: Store the match position in a variable then click there

9

IMAGE + GROUP (multi-match): Selection mode + loop to process every copy

10

IMAGE + LOG: Log search results (for debugging)

Tip

Searches for a template image on screen

Warnings / Cautions

1

WARNING:

2

Starting macro without selecting template means block always goes to FALSE

3

Do not leave scan region as full screen — slow and may cause false matches

4

Do not capture templates from areas with changing backgrounds

5

Do not lower match ratio below 0.50

6

Adjust Scale when using on devices with different resolution

Step-by-Step Mastery: Basic → Advanced → Pro

The same block at three levels: a quick start, the real options, and professional techniques.

Basic

The IMAGE block searches for a small template image inside your scan region. If it finds it, the block goes to TRUE; otherwise it goes to FALSE. The simplest use: capture a button with "Select Template", shrink the scan region to a small area where the button can appear, and add a CLICK with "Click on match" on the TRUE branch. It runs with a single engine and has no automatic full-screen fallback, so always constrain the region.

Advanced

Choosing the Scan Engine (scanEngine) is the core decision: quick_image is fast but not foolproof, balanced_image is the default balance, precision_image is the strictest but slow, color_aware_image is for hue-sensitive templates, and small_object_image is for tiny icons. Match Ratio (mScore) ranges 0.10–0.99; 0.80 is default and you should not drop below 0.50. Scale compensates for size differences across resolutions. The retry-and-timing pair works precisely like this: when Search Timeout (searchTimeout) is 0 the block makes a SINGLE attempt and decides TRUE/FALSE immediately; a value greater than 0 (ms) scans repeatedly within that window, waiting until the timeout elapses or a match is found. Scan Rate (scanRateHz) is the attempts per second inside that retry window; 0 = legacy mode (roughly a 200ms interval, ~5 Hz). Retry Modes (retryOnTrue / retryOnFalse / waitUntilFound) decide which branch re-triggers; "Wait until found" plus a sensible searchTimeout is the cleanest way to wait for a button whose entry animation has finished. The Search Region is the real speed-and-accuracy lever: because searchRegions is a list you can define several rectangles in one block; each region has region [x,y,w,h], an excludeRegion, a shape (rectangle/oval) and a Sticky Anchor (stickyAnchor). Anchor options: none, top_left, top_center, top_right, center_left, center, center_right, bottom_left, bottom_center, bottom_right; the anchor pins the region to that corner/edge so it does not drift when the screen rotates or the resolution changes.

Pro

The real power lives under ADVANCED → Match Tuning (matchTuning): use Score Variable (scoreVar) to write the 0.0–1.0 confidence into a variable, then immediately COMPARE "matchScore >= 0.92" to handle the threshold's grey zone. Context variables (contextX/Y/W/H) spread the match box into variables like matchX/matchY/matchW/matchH; then CLICK {matchX},{matchY} there or target a neighbour with MATH_EVAL (delX = matchX + matchW + 60). Jitter (jitterEnabled + jitterPaddingPx) picks a random point inside the box instead of the centre for a human-like tap. Multi-Target Strategy (multiTargetStrategy): first / best_score / nearest / random / all / sequential; in sequential mode, setting sequentialClickMode = per_click rescans after each click so it stays accurate even if the screen scrolls. Add multiple templates (searchImages) and imageSearchMode becomes "any" or "all". SCALE CALIBRATION is the key to multi-resolution distribution. On the device where you captured the template, Scale = 1.0 works perfectly; if the match ratio drops on a different screen, follow these steps: (1) enable scoreVar and LOG the matchScore, (2) run the macro on the target device and read the real score, (3) change Scale in 0.05 steps (e.g. 1.10–1.30 on a high-DPI device, 0.75–0.95 on a low-DPI one) and compare the score at each step, (4) lock in the Scale where the score peaks. A practical shortcut: the ratio target-device-width / capture-device-width is a good starting Scale. If you distribute to many devices, either calibrate Scale per device or capture the template at the most common resolution and loosen mScore a little.

Real-World Scenarios — Step-by-Step Recipes

Small, reproducible examples that combine several blocks — build them straight into your own macro.

Auto-click a button when it appears
  1. 1Add an IMAGE block and capture the button with "Select Template"
  2. 2Shrink the scan region to the small area where the button appears
  3. 3Scan Engine = balanced_image, mScore = 0.85
  4. 4Retry Mode = Wait until found
  5. 5Add a CLICK on the TRUE branch and enable "Click on match" (no coordinates needed)
Harvest every copy in a field (game farming)
  1. 1Add IMAGE, save the resource-node template, scan region covering the whole field
  2. 2ADVANCED → Multi-Target Strategy = sequential, sequentialClickMode = per_click
  3. 3Add a CLICK with "Click on match" on TRUE
  4. 4Wrap the IMAGE + CLICK pair in a GROUP loop
  5. 5Use BREAK on the FALSE branch to leave the loop when no copies remain
Calibrate a non-matching template on a new device (Scale)
  1. 1ADVANCED → set scoreVar = "score"
  2. 2Add LOG "score=" .. score on IMAGE's shared TRUE/FALSE path
  3. 3Run on the target device and read the real score (e.g. misses at 0.62)
  4. 4Step Scale from 1.0 in 0.05 increments, comparing the score each time
  5. 5Lock the value where the score peaks (e.g. 1.15); keep mScore at 0.80
A scan region that does not drift on rotation (sticky anchor)
  1. 1Add IMAGE, draw the scan region over the small area where the target appears
  2. 2Set the region's Sticky Anchor (stickyAnchor) to the corner where the element truly stays (e.g. top_right for a top-right icon)
  3. 3searchTimeout = 1500ms, scanRateHz = 0 (legacy ~200ms)
  4. 4Retry Mode = Wait until found
  5. 5Rotate the device and confirm the region travels with the corner

Which Blocks to Pair With — Pro Combinations

This block is useful on its own — but it shines when paired with the right partners.

+ CLICK (Click on Match)

The most common pairing: find something and tap exactly on it without entering coordinates; clickOnMatch reuses the match location automatically.

+ Sticky Anchor (stickyAnchor)

A tight scan region is the biggest speed+reliability lever; the anchor keeps that tight region on the correct corner even when the device rotates or resolution changes, so you do not lose the narrowing benefit.

+ COMPARE (branch on score)

Compare the matchScore written by scoreVar against a threshold (matchScore >= 0.92) to reject weak matches; a second gate over the risky grey zone just above the threshold.

+ CLICK {matchX},{matchY} (context variable)

contextX/Y variables store the match position; because it lives in a variable you can click that spot even after other steps, waits, or loops.

+ GROUP (loop) + BREAK

Combined with the sequential multi-target strategy, it picks the next copy each pass and the FALSE branch breaks the loop once they are all consumed.

+ WAIT

When waiting for something like a loading animation to appear or vanish, WAIT inserts breathing room between passes so you do not burn CPU needlessly.

Common Mistakes and Fixes

Leaving the scan region as full screen: it is slow and a similar image elsewhere causes a false match. Fix: shrink the region to the smallest rectangle where the target can appear.

Capturing the template from an area with an animated or changing background. Fix: capture from a region with a stable background and crisp edges; switch to precision_image if needed.

Not adjusting Scale on a device with a different resolution and wondering why nothing matches. Fix: calibrate Scale by testing on the target device.

Leaving searchTimeout = 0 but expecting "wait until it appears" behaviour; 0 makes only a single attempt and can fall straight to FALSE. Fix: if you need to wait, give searchTimeout a window (e.g. 1500ms) and choose the right Retry Mode.

Pro Tips

Add the scoreVar + COMPARE pair to every critical search: even if a 0.81 match counts as "found", COMPARE matchScore >= 0.92 ensures you only act on genuinely clean matches.

Tune scanRateHz in the retry window to the goal: 0 (legacy ~200ms / ~5 Hz) is enough for most UIs and is battery-friendly; if you are missing a brief flash/animation, raise the Hz, but watch the CPU/battery cost on older devices.

The #1 way to speed up a search: shrink the scan region to the smallest rectangle where the target can appear and pin it with stickyAnchor. A tight region speeds scanning manyfold and rejects look-alikes elsewhere on screen.

To look human, enable jitterEnabled with a small jitterPaddingPx; each tap lands on a slightly different point inside the box instead of the exact centre.

On scrolling lists use the sequential strategy with sequentialClickMode = per_click; it rescans after each click, so even if the list shifts it still hits the next correct item.

This Block's Code (Editor View)

Lua

When you add this block in the no-code workspace, the Code Editor generates exactly the Lua below. Study it to see what the block does under the hood, to learn Lua, or to copy and adapt it. Use the Copy button (top-right) to paste it into the Code Editor, or “Try in Editor →” to run it in the live editor.

local _startMs1 = System.currentTime()
local _timedOut1 = false
local _loop1 = true
while _loop1 do
    if System.currentTime() - _startMs1 > 3000 then
        _timedOut1 = true
        _loop1 = false
        break
    end
    Snap.screenRefresh()
    local _reg3 = Region(0, 0, 540, 960)
    local m2 = _reg3:find(Asset.image("btn_play"):mScore(0.8):scale(1.5), {engine="balanced_image"})
    _lastMatch = m2
    if _lastMatch ~= nil then
        _loop1 = false
        match_score = (_lastMatch ~= nil and _lastMatch.getScore ~= nil and _lastMatch:getScore()) or 0
    else
        wait(1)
    end
end
if _timedOut1 then
    System.log("Search retry timeout exceeded: IMAGE")
end

Note: generated code can evolve across versions; helper names (e.g. _reg1, m1) and internal optimizations may change. The logic and the called APIs reflect the block’s behavior.

Shared Controls for This Block Family

The guidance below is not identical for every block. It summarizes the professional controls that most often repeat in the selected block family.

🔎Scan Region

Keep the search close to the target. Smaller regions are faster and more stable.

🚫Exclude Region

Exclude static noise, badges, animations, or reflective areas to reduce false matches.

Timeout and Scan Rate

Timeout and scan rate define whether the block acts as a single check or controlled polling step.

🎯Match Tuning

mScore, scale, and engine choice must be tuned together for theme, resolution, and rendering differences.

🧭Result Variables

Passing _lastMatch, _lastOcrText, plus the Advanced score variable (0.0–1.0 confidence) and match position (matchX/matchY/matchW/matchH) into later blocks keeps the flow readable and smarter; COMPARE on the score, or CLICK {matchX} to act where it was found.

Builder vs Lua Boundary

Raw touch pointer lifecycle stays code-first

TOUCH and TOUCH_BREAK cover recipe-style touch flows. Raw pointer choreography such as Touch.down, Touch.move, Touch.up, Touch.dispatch, Touch.reset, Touch.breakAll, and Touch.releaseAfter is not exposed as a first-class builder block.

Touch.downTouch.moveTouch.upTouch.dispatchTouch.resetTouch.breakAllTouch.releaseAfter
Bounded dialog design is builder-backed; freer composition stays code-first

The DIALOG block and dialog designer cover a bounded field set in the builder: info text, text input, checkbox, radio group, dropdown, image picker, tab group, and recorder picker. Freer Setting.builder composition, multi-step wizard flows, and mixed HUD/dialog choreography still do not map 1:1 into the builder.

Setting.builderDialogHudTextView
Advanced HTTP request chaining stays code-first

HTTP_GET, HTTP_POST, and HTTP_PUT cover common fixed-method flows; HTTP_REQUEST covers one bounded request with method, header lines, body, content type, and timeout. Freer query/retry composition, chained request objects, and lower-level client flows still need the code editor.

Request.setParameterRequest.setHeaderRequest.setBodyRequest.setContentTypeRequest.setRetryRequest()TRY_CATCHCUSTOM_CODE
General programming surfaces stay code-first

General-purpose helpers such as Map, Array, JSON, Regex, and Metrics are broader than the builder recipe model. These surfaces remain on the coded runtime side instead of becoming first-class builder blocks.

MapArrayJSONRegexMetrics
Low-level runtime and Lua composition stays code-first

Runtime helpers, raw Request objects, Lua built-ins such as print/pcall/xpcall, and free-form object chaining patterns are represented through CUSTOM_CODE or the code editor.

RuntimeRequestprintpcallxpcallCUSTOM_CODE

Debug Mode and Breakpoints

Each block card now exposes an independent breakpoint toggle. When enabled, the breakpoint preference is stored with the block.

Breakpoints are only emitted into runtime code when Debug Mode is enabled from Visual Builder settings. When Debug Mode is off, breakpoints stay saved but do not pause execution.

Use ASSERT for fail-fast validation, and use breakpoints for step-by-step tracing and controlled pauses in the same flow.

Variable Scope

1

Variables defined with SET_VARIABLE are accessible throughout the macro (global scope). All blocks can read/write the same variable.

2

However, a variable defined inside a GROUP will be 'nil' (undefined) until the GROUP executes. Blocks outside the GROUP using this variable may produce unexpected results.

3

FOR_EACH loop variables (item and index) only carry valid values inside the loop body. Outside the loop they are outside local scope and should not be used.

4

TRY_CATCH error variable is only valid within the catch block. If the try block succeeds, the catch branch is not entered and the error variable remains undefined.

5

TIP: Before using a variable inside a GROUP, assign a default value with SET_VARIABLE outside the GROUP. This way the variable won't be nil even if the GROUP has not run.

Inline Expressions

You can embed variable values and calculations into text fields using {{ expression }} syntax. Expressions inside double curly braces are evaluated as Lua code and the result is inserted into the text.

Syntax
{{ expression }}
Examples
Skor: {{ score + 1 }}"Skor: " .. tostring(score + 1)
{{ name }} kazandı!tostring(name) .. " kazandı!"
X:{{ x }} Y:{{ y }}"X:" .. tostring(x) .. " Y:" .. tostring(y)
Supported Blocks
SET_VARIABLELOGCOMPARECLIPBOARD_WRITENOTIFY_TOASTKV_SET
Security Note

Expressions are checked by the sandbox policy. Security-sensitive calls like loadstring, require, debug are automatically blocked.

General Tips

1

Keep scan regions as small as possible — improves speed, reduces false matches.

2

Always add an exit condition when using infinite loops (BREAK, timeout, or conditional exit).

3

Use network operations and error-prone steps inside TRY_CATCH.

4

If you need global error handling, use the Error Handler (ERROR_HANDLER) block as a singleton in the project.

5

Small coordinate offsets (CLICK/SWIPE) improve tap accuracy across different DPI and screen scales.

6

Customize macros with Dialog block — different parameters each run.

7

Define repeating steps once with GROUP_CALL, call from many places.