Class HudAnimationSequenceLayerInspector
Reads and rewrites the fields a sequence layer (TransformScaleSequenceLayerSO,
TransformRotationSequenceLayerSO, TransformPositionSequenceLayerSO,
ActivationSequenceLayerSO) exposes only as
private or protected serialized fields — transformId, steps, phaseMode,
repeatCount, loop — through a cached UnityEditor.SerializedObject, since none of them
offer a public setter.
Inherited Members
Namespace: Serenity.GameUi.Infrastructure.Editor.Builder
Assembly: Serenity.UnityGameUi.Infrastructure.Editor.dll
Syntax
public static class HudAnimationSequenceLayerInspector
Remarks
Shared by the Animation tab's divergence warning and fix button, its inline step editor
(HudAnimationLayerEditorGui), and the project validator's asset-level animation checks
(SerenityHudBindingValidator), so none of them ever disagree about what "a sequence layer" is or
what its authored fields mean.
One UnityEditor.SerializedObject is cached per layer instance rather than rebuilt on every access — this file is read from every GUI repaint (the divergence warning, the step editor) and a fresh UnityEditor.SerializedObject per repaint would be needless per-frame allocation. The cache entry is dropped, not reused, the moment its target goes Unity-fake-null (the asset was deleted or the domain reloaded out from under it) — holding on to a stale wrapper is exactly how a Exception from a destroyed native object ends up thrown mid-repaint.
Methods
ApplyAndSave(ProceduralLayerSO, string)
Applies whatever pending edits are staged on layer's cached
UnityEditor.SerializedObject, in the project's standard foreign-asset write order: record Undo,
apply the properties, mark the asset dirty, then save.
Declaration
public static void ApplyAndSave(ProceduralLayerSO layer, string undoName)
Parameters
| Type | Name | Description |
|---|---|---|
| ProceduralLayerSO | layer | The layer to save; a no-op when null. |
| string | undoName | The Undo group's name, shown in the Edit ▸ Undo History window — should name the specific action, not a generic "Edit animation layer" label. |
Remarks
Reserved for discrete one-click actions — the transformId "fix" button (SetTransformId(ProceduralLayerSO, string)) and the template gallery's "Create" button — NOT for per-field edits (step values, phase mode, repeat count). UnityEditor.AssetDatabase.SaveAssets synchronously flushes every dirty asset in the whole project; calling it from a per-field write path would mean a mouse drag on a float/Vector3 field — which fires many repaints — flushes the whole project on every one of those repaints. Per-field edits must go through ApplyPendingEdits(ProceduralLayerSO) instead, which dirties the asset without saving.
ApplyPendingEdits(ProceduralLayerSO)
Applies whatever pending edits are staged on layer's cached
UnityEditor.SerializedObject and marks the asset dirty — the standard "dirty asset, saved on the
editor's next project save" flow, the same one any ordinary inspector field uses.
Declaration
public static void ApplyPendingEdits(ProceduralLayerSO layer)
Parameters
| Type | Name | Description |
|---|---|---|
| ProceduralLayerSO | layer | The layer to mark dirty; a no-op when null. |
Remarks
This is the per-field write path: step values, phase mode, repeat count — anything a continuous drag can touch. Deliberately does NOT call UnityEditor.AssetDatabase.SaveAssets (see ApplyAndSave(ProceduralLayerSO, string)'s remarks) and deliberately does NOT call UnityEditor.Undo.RecordObject(UnityEngine.Object,System.String) — UnityEditor.SerializedObject.ApplyModifiedProperties already integrates with Undo itself, so calling both would double-push an undo entry per field edit, now amplified per drag frame.
GetLoopProperty(ProceduralLayerSO)
The layer's own loop field: in ABSOLUTE mode, whether the
sequence repeats continuously rather than holding on its last step (has no effect in
ON_ACTIVATE mode — see each sequence layer's own loop tooltip).
Declaration
public static SerializedProperty GetLoopProperty(ProceduralLayerSO layer)
Parameters
| Type | Name | Description |
|---|---|---|
| ProceduralLayerSO | layer | The layer to read; must be a sequence layer. |
Returns
| Type | Description |
|---|---|
| SerializedProperty | The serialized loop property, or null when |
GetPhaseModeProperty(ProceduralLayerSO)
The layer's inherited phaseMode field (backing PhaseMode).
Declaration
public static SerializedProperty GetPhaseModeProperty(ProceduralLayerSO layer)
Parameters
| Type | Name | Description |
|---|---|---|
| ProceduralLayerSO | layer | The layer to read; must be a sequence layer. |
Returns
| Type | Description |
|---|---|
| SerializedProperty | The serialized phase-mode property, or null when |
GetRepeatCountProperty(ProceduralLayerSO)
The layer's inherited repeatCount field (backing RepeatCount).
Declaration
public static SerializedProperty GetRepeatCountProperty(ProceduralLayerSO layer)
Parameters
| Type | Name | Description |
|---|---|---|
| ProceduralLayerSO | layer | The layer to read; must be a sequence layer. |
Returns
| Type | Description |
|---|---|
| SerializedProperty | The serialized repeat-count property, or null when |
GetSerializedLayer(ProceduralLayerSO)
A live, up-to-date UnityEditor.SerializedObject for layer, cached per layer
instance and already UnityEditor.SerializedObject.Update-ed for this call.
Declaration
public static SerializedObject GetSerializedLayer(ProceduralLayerSO layer)
Parameters
| Type | Name | Description |
|---|---|---|
| ProceduralLayerSO | layer | The foreign layer asset to wrap; may be null. |
Returns
| Type | Description |
|---|---|
| SerializedObject | The cached, updated UnityEditor.SerializedObject, or null when |
Remarks
Call this once per draw pass and reuse the result for every property read that pass, rather than calling it once per field — UnityEditor.SerializedObject.Update is cheap but not free, and a layer with several steps means several fields read per repaint.
Ownership: the returned UnityEditor.SerializedObject is the SAME shared instance this
class hands to every caller for a given layer. Callers must never call
UnityEditor.SerializedObject.Dispose on it — doing so would pull it out from under every other
caller and under this class's own fake-null eviction check above, which would then itself throw on
the disposed object. This class owns the instance's lifetime and disposes it itself when the entry
is evicted below.
GetStepsProperty(ProceduralLayerSO)
The layer's steps array — ScaleStep entries for a
TransformScaleSequenceLayerSO, ActivationStep entries for an
ActivationSequenceLayerSO.
Declaration
public static SerializedProperty GetStepsProperty(ProceduralLayerSO layer)
Parameters
| Type | Name | Description |
|---|---|---|
| ProceduralLayerSO | layer | The layer to read; must be a sequence layer. |
Returns
| Type | Description |
|---|---|
| SerializedProperty | The serialized steps array, or null when |
GetTransformId(ProceduralLayerSO)
The transform id the layer targets, or empty when the layer is null, is not a sequence layer, or has none authored.
Declaration
public static string GetTransformId(ProceduralLayerSO layer)
Parameters
| Type | Name | Description |
|---|---|---|
| ProceduralLayerSO | layer | The layer to read. |
Returns
| Type | Description |
|---|---|
| string | The authored transform id. |
IsDeliberateAmbientLoop(ProceduralLayerSO)
Whether layer is deliberately configured to loop forever: a sequence layer,
phased ABSOLUTE, with its own loop field true — the shape
Serenity.GameUi.Infrastructure.Editor.Builder.HudAnimationLayerScaffold.ConfigureAmbientLoop(UnityEditor.SerializedObject,System.String) bakes into every ambient template
(pulse, heartbeat, insert-coin blink). The single shared source of truth for "is this an
intentional ambient loop" — both HudAnimationLayerEditorGui's collapsed-warning/inline
checks and SerenityHudBindingValidator's project-wide scan call this instead of keeping their
own copy, so the two can never disagree about which layers are ambient loops versus genuinely stuck.
Declaration
public static bool IsDeliberateAmbientLoop(ProceduralLayerSO layer)
Parameters
| Type | Name | Description |
|---|---|---|
| ProceduralLayerSO | layer | The layer to check; may be null or a non-sequence layer. |
Returns
| Type | Description |
|---|---|
| bool | True only for a sequence layer in ABSOLUTE phase with |
Remarks
Trustworthy as an "intentional" signal ONLY because loop now defaults to false on
every sequence layer type (see TransformScaleSequenceLayerSO/
ActivationSequenceLayerSO's own loop field docs) — a freshly created,
un-configured layer therefore reads as NOT an ambient loop, so the ABSOLUTE-phase and
repeatCount-is-0 warnings still fire on exactly the footgun they exist to catch, rather than being
silently suppressed for a layer nobody ever touched.
IsSequenceLayer(ProceduralLayerSO)
Whether layer is one of the sequence-layer kinds the Animation tab's scaffold
buttons create and its divergence checks apply to.
Declaration
public static bool IsSequenceLayer(ProceduralLayerSO layer)
Parameters
| Type | Name | Description |
|---|---|---|
| ProceduralLayerSO | layer | The layer to check; may be null. |
Returns
| Type | Description |
|---|---|
| bool | True for a transform-scale, transform-rotation, transform-position, activation, or graphic-color sequence layer. |
SetTransformId(ProceduralLayerSO, string)
Rewrites the layer's transformId to newTransformId, recorded for Undo
under a group name matching the "Point layer at '…'" fix button's own label, and saved immediately
— the fix button's whole job, and a discrete one-click action rather than a per-field edit, so it
goes through the full ApplyAndSave(ProceduralLayerSO, string) sequence rather than ApplyPendingEdits(ProceduralLayerSO).
Declaration
public static void SetTransformId(ProceduralLayerSO layer, string newTransformId)
Parameters
| Type | Name | Description |
|---|---|---|
| ProceduralLayerSO | layer | The layer to rewrite; a no-op when null or not a sequence layer. |
| string | newTransformId | The transform id to write. |