# SDK 1.0.0-pre.2 migration

Use EpicTuner 0.8.3 or later. This is a source-helper and host-diagnostics update;
C ABI 1.1, service table layouts and existing numeric constants are unchanged.

## Dropdown selection: properties and events are different domains

`ET_UI_SELECTED` was always an **event type**, not a property. It has the same
numeric value as the unrelated `ET_UI_UNITS` property. Renumbering it would break
existing event handlers. Prefer the explicit names added in this SDK:

- Set a dropdown's index with `ET_UI_SELECTED_INDEX` (alias of `ET_UI_VALUE`).
- Receive selection events as `ET_UI_EVENT_SELECTED` (legacy `ET_UI_SELECTED`).
- Both the selected property and event value use `ET_VALUE_F64`: a zero-based
  index, not the option text. `-1` is the no-selection property value.

```cpp
panel.add(ET_UI_SELECT, "model").text(ET_UI_OPTIONS, "").selectedIndex(-1);
// After a Make selection, update options and index together in one atomic patch:
ui.patch(e.panel, {Ui::text("model", ET_UI_OPTIONS, "Model A\nModel B"),
                  Ui::selectedIndex("model", 0)}, e.revision, e.origin, &completion);
```

Do not place `ET_UI_SELECTED` in a property array or a patch. The host now reports
the node, offending property and correction instead of a generic type error.
Empty options render an empty, disabled control. Populate options and choose an
index in the same patch. When replacing a short list, reset its old index too.
For a single option, set index `0` to autoselect it. Programmatic selection does
not generate a user selection event: update dependent controls and the preview
in the same plugin logic instead of waiting for a callback.

## Several patches from one event

Before host 0.8.3, the first successful patch advanced the panel revision and
subsequent calls using that event's revision failed with `ET_ERROR_CONFLICT`.
This affected every property, including a status update followed by options.

Host 0.8.3 queues synchronous patch calls made inside the same UI event callback,
for the event's panel, revision and origin. It applies them in call order, using
each successful completion's revision for the next call. A failed call cancels
its remaining dependent calls. Intervening user edits still cause a conflict;
they are never silently overwritten. Every call keeps its own completion.
Host **0.8.4** extends this to calls using the SDK's default origin `0`, including
a status/render call before the options call. Use 0.8.4 or later for that pattern.

Prefer one atomic patch for mutually dependent options, indexes and previews.
Separate status/render patches may precede it. Calls made later from timers or
completion callbacks must use a fresh revision (the successful patch completion
returns it as `ET_VALUE_U64`). Do not reuse a saved event revision indefinitely.

## Patch errors and startup failures

Patches remain atomic: partial application would leave dependent controls
inconsistent. `ET_OK` means queued. A completion supplies the actual result and
`detail`; copy or log that borrowed string inside the callback. Rejections are
also visible in Tools > Plugins diagnostics without a completion callback.

The host reports named service failures and immediate UI validation failures when
startup fails. For plugin-specific operations, use
`return context.check(result, "Load base tune database")` to attach the step name.
An asynchronous definition failure must be handled in its completion; returning
from `start()` cannot synchronously report a later host reply. Keep the callback
owner alive and return `ET_OK` when the definition has been queued successfully.

## Empty table previews

Plugin-owned calibration tables use tab-separated cells and newline-separated
rows, with `ET_UI_COLUMNS` matching the row width (12 for a 2-row, 12-column table).
Set a range covering every finite value. `ET_UI_VALUE` contains the edited/current
dataset and takes precedence over initial `ET_UI_DATA`. For refreshed previews,
patch `ET_UI_VALUE`; otherwise a previous edited value can hide new initial data.
Keep `ET_UI_TARGET` empty for plugin-owned data. A rejected atomic patch changes
neither the dropdowns nor the preview. Inspect the completion before assuming the
renderer failed. The client now displays an explicit message for empty previews.

See [the control/event tables](UI.md), [the first-plugin tutorial](GETTING_STARTED.md),
and the [cascading-select example](../examples/cascading-selects/README.md) for a complete Make → Model → Tune flow.
