ComponentControl
The members of one component control: its identity, its kind and the effective value for the instance being evaluated.
One component control with its effective value for the evaluating instance.
id
Type: string (field).
The control id (stable per definition).
Worked example: A control's stable id
The scene. A Badge component whose internal comp holds one blue face layer, exposed with a scalar Amount control, plus one Badge instance placed in the Host comp with Amount overridden to 65.
- The comp Host: 640 by 360 at 25 fps, 100 frames (4 seconds).
- The comp Badge internals: 200 by 200 at 25 fps, 100 frames (4 seconds).
- Badge face in Badge internals: a solid layer, at [100, 100], 120 by 120, filled 4d9de0.
- Badge in Host: a component instance, at [320, 180].
- The instance overrides the component's c_amount control to 65.
- The component Badge wraps Badge internals and exposes 1 control: Amount (scalar, default 20).
The script is EMBEDDED in the Badge component - add it from the component's own Scripts group, and it travels with the component wherever it is placed.
The script. Add a component script named Id check and paste:
export const outputs = ["layer_1:transform.opacity"];
export function frame() {
const first = thisComponent.controls[0];
return first.id === "c_amount" ? 75 : 5;
}
Line by line:
- Lines 4-5: Each exposed control keeps a stable id per definition - the key control(id) uses and the one instance overrides are stored against. Relabelling the control never touches it. The check passes, so the face rests at 75.
What you see. The badge face rests at 75 percent - confirmation that the first exposed control's id is the stable c_amount whatever its label says.
label
Type: string (field).
The display label.
Worked example: The human label
The scene. A Badge component whose internal comp holds one blue face layer, exposed with a scalar Amount control, plus one Badge instance placed in the Host comp with Amount overridden to 65.
- The comp Host: 640 by 360 at 25 fps, 100 frames (4 seconds).
- The comp Badge internals: 200 by 200 at 25 fps, 100 frames (4 seconds).
- Badge face in Badge internals: a solid layer, at [100, 100], 120 by 120, filled 4d9de0.
- Badge in Host: a component instance, at [320, 180].
- The instance overrides the component's c_amount control to 65.
- The component Badge wraps Badge internals and exposes 1 control: Amount (scalar, default 20).
The script is EMBEDDED in the Badge component - add it from the component's own Scripts group, and it travels with the component wherever it is placed.
The script. Add a component script named Label seat and paste:
export const outputs = ["layer_1:transform.position"];
export function frame() {
const label = thisComponent.controls[0].label;
return [value[0], 60 + label.length * 8];
}
Line by line:
- Lines 4-5: label is what the component's surface shows people - "Amount", six characters, seating the face at y 108. Use labels for display logic; keep references on ids.
What you see. The badge face seats itself at y 108 - eight pixels per letter of the control's label.
kind
Type: 'text' | 'scalar' | 'colour' | 'point2' | 'image' | 'video' | 'audio' | 'boolean' | 'dropdown' (field).
The control kind.
Worked example: Branch on the control's kind
The scene. A Badge component whose internal comp holds one blue face layer, exposed with a scalar Amount control, plus one Badge instance placed in the Host comp with Amount overridden to 65.
- The comp Host: 640 by 360 at 25 fps, 100 frames (4 seconds).
- The comp Badge internals: 200 by 200 at 25 fps, 100 frames (4 seconds).
- Badge face in Badge internals: a solid layer, at [100, 100], 120 by 120, filled 4d9de0.
- Badge in Host: a component instance, at [320, 180].
- The instance overrides the component's c_amount control to 65.
- The component Badge wraps Badge internals and exposes 1 control: Amount (scalar, default 20).
The script is EMBEDDED in the Badge component - add it from the component's own Scripts group, and it travels with the component wherever it is placed.
The script. Add a component script named Kind gate and paste:
export const outputs = ["layer_1:transform.scale"];
export function frame() {
const amount = thisComponent.control("c_amount");
return amount.kind === "scalar" ? [130, 130] : [70, 70];
}
Line by line:
- Lines 4-5: kind names the control's value shape - text, scalar, colour or point2 - and therefore what .value will be (string, number, [r, g, b, a] or [x, y]). Amount is a scalar, so the wide branch wins and the face renders at 130 percent. Kind checks keep a generic script honest about what it was handed.
What you see. The badge face renders at 130 percent scale - the branch for a scalar control, chosen by inspecting the control's kind.
value
Type: T (field).
The EFFECTIVE value in wire units (the instance's track sample over its stored override over the default). Per kind: text/dropdown a string (the dropdown's item index or the effect enum's spelling, exactly as the bound member accepts it), scalar a number, colour [r, g, b, a] 0..1, point2 [x, y], boolean a boolean, image/video/audio the asset id string or null (the definition's own asset).
Worked example: The effective value, per context
The scene. A Badge component whose internal comp holds one blue face layer, exposed with a scalar Amount control, plus one Badge instance placed in the Host comp with Amount overridden to 65.
- The comp Host: 640 by 360 at 25 fps, 100 frames (4 seconds).
- The comp Badge internals: 200 by 200 at 25 fps, 100 frames (4 seconds).
- Badge face in Badge internals: a solid layer, at [100, 100], 120 by 120, filled 4d9de0.
- Badge in Host: a component instance, at [320, 180].
- The instance overrides the component's c_amount control to 65.
- The component Badge wraps Badge internals and exposes 1 control: Amount (scalar, default 20).
The script is EMBEDDED in the Badge component - add it from the component's own Scripts group, and it travels with the component wherever it is placed.
The script. Add a component script named Amount seat and paste:
export const outputs = ["layer_1:transform.position"];
export function frame() {
const amount = thisComponent.control("c_amount").value;
return [amount * 3, value[1]];
}
Line by line:
- Line 4: value is the control's EFFECTIVE value for the evaluating context: the definition's default (20) in the component editor, each instance's override (65 in the Host comp's Badge) when placed, and any keyframed track wins over both. This one member is what makes a component's controls feel live.
- Line 5: Three pixels of slide per unit of Amount: x 60 under the default, x 195 inside the overridden instance.
What you see. The badge face parks at x 60 while editing the definition; the placed instance carries it right out to x 195 under its Amount of 65 - the same script reading each context's own truth.