Skip to content

t1k:cocos:playable:parameter-implement

FieldValue
Moduleplayable
Version2.14.4
Efforthigh
Tools—

Keywords: bind, codegen, flat-primitive, generate, implement, ParameterController, PlayableConfig, wire

/t1k:cocos:playable:parameter-implement
[scan-report-json] or [node-list]

Code generator for the flat-primitive parameter architecture. Accepts scan output and produces TypeScript parameter definitions + controller wiring. Every generated ObjectParameter contains primitive BaseParameter instances only — no ComponentParameter wrappers, no nested ObjectParameter. See parent skill ## The Load-Bearing Rule.

IntentActionReference
Generate PlayableConfig entriesOne top-level ObjectParameter per scanned node, prefixed primitivesreferences/code-templates.md
Wire entries into ParameterController (≤20 entries)Flat-dump @property + bind<T> per entryreferences/code-templates.md
Wire entries into ParameterController (>20 entries OR ≥3 groups)Sectioned controller — one section class per groupreferences/sectioned-controller.md
Optional terser apply codeProject-side FlatParamHelpers (spriteFromFlat, …)references/code-templates.md § Adapters
  1. PlayableConfig.ts — Top-level ObjectParameter entries; bodies contain prefixed primitive BaseParameter instances only.
  2. ParameterController.ts — Either flat-dump (≤20 entries) or sectioned (>20 entries) shape. Reconstructs ComponentParameter from flat primitives at apply-time.
  3. (optional) FlatParamHelpers.ts — Project-side adapters bridging flat primitives → ComponentParameter.
total entries ≤ 20 AND subtree groups ≤ 2 → flat-dump controller
total entries > 20 OR subtree groups ≥ 3 → sectioned controller (MANDATORY)
any single section > 15 entries → sub-split by functionality (MANDATORY)
any single section ≤ 3 entries → consider merging into adjacent or `Misc`

Section boundaries: start by subtree (UICanvas/{Subtree}/...), then sub-split functional clusters within any subtree exceeding 15 entries. Functional cluster signals and anti-criteria: references/sectioned-controller.md.

  • Use typed @property(Sprite), @property(Label) for visual components; @property(Node) only when the apply target is the node itself (Button, UIOpacity).
  • Direct component refs only — no getComponent in the controller.
  • One prefixed primitive per Cocos component field present on the node.
  • Full-field coverage by default. Emit EVERY field the component exposes — never a hand-picked subset. Flat-primitive path: one primitive per field in field-coverage.md. Wrapper path (ObjectParameter<XxxComponentParameter>): pass EVERY key of the component’s XxxConfig interface (read it from db://assets/packages/@playablelabs/parameter-tool/parameter/component-parameter/XxxComponentParameter.ts). Narrow ONLY with code evidence or an explicit user note. See parent skill Critical Rule 9.
  • Use actual scene values from the scan report’s primitiveShape as primitive defaults.
  • One scanned node → one top-level ObjectParameter. Max depth = 2.
  • Component-prefixed primitives on multi-component nodes (spriteColor, buttonTransition). Single-field components skip the prefix (opacity). A cc.Label is not expanded at all — one formattedText key holding a FormattedTextParameter.
  • NEVER generate nested ObjectParameter, ComponentParameter instances inside config, or CustomParameter.ts wrappers (retired in v6).
  • At >20 entries OR ≥3 subtree groups, MUST emit sectioned controller — see references/sectioned-controller.md.
  • PascalCase entry names: CtaButton, TitleLabel, BackgroundSprite, HPBarPlayerBar.
  • Multi-node logical groupings: prefix child names with the grouping (HPBarPlayer{Bar|Bg|Label}, RewardCard1{Card|Icon|Amount}).
  • Categories: UI uses UILayer-{Screen}; non-UI uses Gameplay-{Domain} / Audio / Sdk.
  • Sectioned controller: section class ParameterController_{Section}Section, controller field {section}Section (camelCase).
  • Child label (the dashboard-facing string, first constructor arg): "{ParentLabel} — {Component} {Field}" — e.g. new ColorParameter("CTA Button — Sprite Color", "#FFFFFF"). Drop the component token only for single-field components (… — Opacity), the active enable seam, method-routed custom-widget fields, and non-UI params. Keys are unaffected. Full rules: parent skill t1k-cocos-playable-parameter/references/label-convention.md.
  • references/code-templates.md — Full PlayableConfig.ts + flat-dump ParameterController.ts templates, optional FlatParamHelpers convention.
  • references/sectioned-controller.md — Sectioned controller template, group-metadata contract, section-boundary rules.
  • Parent skill t1k-cocos-playable-parameter/references/type-hierarchy.md — Two-stage model (config-stage primitives vs apply-stage ComponentParameter).
  • Parent skill t1k-cocos-playable-parameter/references/field-coverage.md — Per-component prefixed-primitive tables.
  • Parent skill t1k-cocos-playable-parameter/references/workflow-steps.md — End-to-end steps + doctor.
  • Primitive names must match host macro replacement exactly — case-sensitive.
  • Every ObjectParameter needs a matching @property (or container reference) AND a bind call. A scanned node not wired in the controller will silently never apply.
  • Async sprite loading: binder tracks promises via binder.waitForAsync(); fire AllAsyncParametersReadySignal after it resolves.
  • Do not generate store-link parameters — those are SDK-managed.
  • The cast (data as ObjectParameter<T>) inside bind<T> is required because the submodule’s BaseParameter.onUpdate signature is (arg0: BaseParameter) => void. Don’t drop the cast.
  • ComponentParameter constructors take an empty {}; assign fields directly afterward.
  • Cherry-picking component fields is the most common under-qualification defect. Absent a specific note, emit ALL fields the XxxConfig interface (or field-coverage.md table) offers. Verify against the interface, not from memory.
  • cc.Label is the one component that is NOT expanded into atoms. Emit exactly one FormattedTextParameter per Label — { text, fontColor, fontFamily, fontSize, alignment, strokeColor, strokeWidth } — in both the basic and advanced profiles. Do NOT also emit labelString/labelColor/labelFontSize/labelOutline* beside it, and do NOT emit atoms for label fields the formatted-text shape lacks (shadow, lineHeight, overflow, verticalAlign, bold/italic/underline, wrapText) — the dashboard cannot render them, so they land as undefined controls. Prefer the package template FormattedTextComponentParameter + applyFormattedTextComponentParams (parameter/component-parameter/FormattedTextComponentParameter.core) — it takes the LabelConfig seed shape, flattens through fields() as one row, bakes the non-formatted fields, and derives enableOutline from strokeWidth > 0. Only hand-roll the mapping when the vendored tool lacks it. Parent skill t1k-cocos-playable-parameter/references/field-coverage.md § cc.Label.
  • Two children of one ObjectParameter may never share a label. Distinct KEYS do not save you — the label is a separate string and the atoms default to generic ones. Shipped defect: CtaButton emitted spriteColor and labelColor (distinct keys) with labels "Color" and "Color", so the dashboard showed two identical rows and the operator could not tell the button tint from the text colour. Before emitting an entry, check its child labels are pairwise unique.
  • Flat-dump @property at scale is unreadable. Validate generator output: at >20 entries it MUST be sectioned per references/sectioned-controller.md. Verify with grep -c '^class ParameterController_.*Section'.