SWIFTPOINT//HUB
Support

Profile Builder · Nesting — one input gated behind another

How a binding becomes live while another input is held: the nesting tree, branching, the 20-level limit and gated scroll.

Nesting is the only thing the PredecessorId field of a .spcf mapping does. Indent a binding under another one and you have said exactly one thing:

This binding is active while the trigger above it is held.

That is the whole rule. There is no second rule hiding behind it.


1. What nesting is not

Older versions of this guide called the same links "Run after" and told you they fired in order. That was wrong, and the device is the proof: hold a parent down, and its child stops the moment you let go. A binding that ran after its predecessor could not do that.

So, concretely, nesting gives you none of these:

You might expect What actually happens
A sequence: press left, release it, then press right Impossible. The child is only live while the parent's trigger is held — release the parent and the child is dead, mid-press included.
A condition: if left is down, do the mouse thing Not a condition either. Nesting adds a gate; it never replaces one. A nested child and a plain root binding both fire, and their actions are not exclusive.
A priority order None. Two children of one parent are two independent gates, not a first/second choice.
A delay between steps None. Every mapping in every profile stored on this hub has OutputActionSequenceDelay: 0, and the Builder does not offer a delay on a binding.

Timing lives in actions, not in nesting. To space things out, use the Delay action inside a binding (see bindings.md). To repeat, use Loop to action / Stop loop there too.


2. What a nesting tree looks like

Here is a real tree, exported from an X1 Control Panel profile and loaded into the Builder: profile 69, the site's nesting test file, nine bindings in one layer. Every line is a binding; indentation is the gate:

Left Button Press
    -> Right Button Press
        -> Bottom Thumb Press
            -> Right Trigger Push
        -> Right Trigger Push
            -> [tilt region on roll]
                -> Bottom Thumb Press
                -> Rear Edge Press
                    -> Left Trigger Push

The names are the ones the Builder prints for these bindings, read out of that file. The tilt line is the exception and is deliberately written as its trigger type: a tilt region is stored with a direction, the label for it used to leave that out, and that label is being corrected — so the line is named by what it is rather than by a wording that is about to change. What this section is about is the shape of the line: a tilt gesture that is live only while the trigger above it is held.

Read it out loud and there is no ordering in it at all:

  • Hold Left Button. Nothing else in this profile is live yet.
  • While you hold it, Right Button Press and the second Right Trigger Push (a sibling of Bottom Thumb Press, three edges further down on its own branch) are both live. They are siblings, not a chain — pressing either works, in any order, or not at all.
  • Push Right Button Press while still holding Left and the whole left branch goes live: Bottom Thumb Press, then — only while that is held — Right Trigger Push.
  • Let go of Left Button and all eight of them go dead at once, whatever state your hand was in.

Branching is normal. 31 of the parents across the profiles stored on this hub have more than one follower; one trigger gating several children is the ordinary case, not a trick. Each child can gate several children of its own.

Bottom Thumb Press appears twice, in two different branches. That is perfectly legal and it is not a duplicate: two separate bindings, two separate things to do. If your real hand only wants one of them, build one.


3. Building a nested binding

The + Add menu lives in the button's own card in the Bindings tab. Open the card of the input you want to gate, use the menu, and pick what the new binding should hang under:

  1. Select the parent — the trigger that has to be held for the new binding to be live. The menu lists every mapping in the current group; the trigger name it shows is the gate.
  2. Choose the trigger for the new binding (button press, deep zone, tilt gesture, tilt range, wheel, surface drag).
  3. Add the actions as usual — activation and deactivation, exactly like any other binding (see bindings.md).

A node's children are listed under it in the card; the tree is drawn under the Root key of the group's binding list, so the whole structure is in one place. Cards of buttons that are only ever children stay empty — their bindings live in the tree, not in their own card.

What a nested binding does not lose. It still has its own trigger, its own activation and deactivation actions, its own Label, and Move to… to another group. Nesting only decides when it is allowed to fire.


4. The 20-level limit

A tree may be 20 levels deep, counted in edges — the root is level 0, its child level 1, and so on. The Builder refuses the 21st level and says so where you tried to add it. The deepest tree shipped on the hub is 5 levels, so 20 is headroom rather than a target.

If a file you open already nests deeper than that, every mapping is still shown and still runs; Diagnostics flags the depth as a problem and you can restructure it there.


5. The one exception: a button's own press stages

Nesting is not how a single button's press stages are drawn. When one button's whole subtree is just its light press plus its deep zones — same button, same press, nothing else — the Builder shows it as the press card: a force axis with the light press and each deep band on it (see deep-click.md). That is one physical button's pressure range, not a gating relationship, and it is never listed as nesting.

The rule that keeps the two apart: if the subtree ever leaves its button, it is nesting. A deep zone on Left Button hanging under Right Button is a nested binding and appears in the tree under Right Button — it does not join Left Button's press card, because it is not Left Button's own pressure stage any more.


6. Gated scroll is just a nested child

The classic "hold a button, the wheel does something else" trick is nothing special — it is one nested child:

  1. Bind the hold button (e.g. Top Thumb) with Mousewheel Forward and whatever a notch should do (e.g. Mouse button Left [tap]).
  2. Create the wheel binding you want to change (e.g. a second Mousewheel Forward with Scroll wheel up, 3 notches).
  3. In that new binding's card, set the parent to the Top Thumb binding.

Now the wheel binding fires only while Top Thumb is held. Let go and you are back to plain scrolling — there is no mode to switch off, nothing to remember. Repeat for wheel Back. The Sensitivity (CountDivisor) on the wheel trigger tunes how many events per notch (1 = one, higher = more).

Used for weapon cycling, map zoom, or turn-spam without moving your grip.


7. Recipes

Modifier that only exists while you hold it

Left Button Press            (nothing — this is the gate)
    -> Right Button Press    -> Mouse button Left [hold down]
                              deactivation: Mouse button Left [release]

Hold Left, then Right, and you get a right-press while the left is down. Let go of Left and the Right binding stops existing.

Scroll while held, scroll normally otherwise — §6.

Tilt inside a held button

Left Button Press
    -> Tilt gesture        -> Key Q [tap]

A tilt gesture with a hold: the tilt is only read while Left is held. Note that tilt triggers have no button of their own — they nest perfectly well anyway.

Burst fire is not nesting at all — it is one binding: Right Button [tap] → Mouse button Left [tap] · Delay 40ms · Loop to action #0, repeat 2.


8. Diagnostics

The nesting-related things Diagnostics flags:

  • Nesting too deep — a level past 20.
  • Broken nesting link — a binding points at a parent that no longer exists (⇒ Make Top-Level makes it fire on its own again).
  • Cycle — a group of bindings that gate each other in a loop. A loop has no root to hang from, so the Builder cuts it at its lowest member and shows that member as a root of its own, instead of walking it forever. Nothing is lost.
  • Mapping with no actions at all, and mapping with no trigger type.

A clean profile shows "No issues found — the profile looks coherent."