Class AchievementConditionNodeWriter
Every write the condition tree drawer makes to an authored tree: replacing a node with another type, adding, removing and reordering a composite's children, and clearing the tree.
Inherited Members
Namespace: Serenity.Achievements.Infrastructure.Editor
Assembly: Serenity.UnityAchievements.Infrastructure.Editor.dll
Syntax
public static class AchievementConditionNodeWriter
Remarks
Separate from AchievementConditionNodeGui so the drawing stays reading-only and the writes stay in one place, because they all share three rules that are easy to get wrong.
First, everything goes through UnityEditor.SerializedProperty rather than through the managed object the property holds. Assigning a node's fields directly would edit the loaded instance behind the serialization system's back: no undo entry, no prefab override, and no repaint for the other inspector looking at the same asset.
Second, a choice made in an AdvancedDropdown arrives AFTER the GUI pass that opened it
has already applied its changes, so the property captured during that pass is stale and
writing through it silently does nothing. Every method that a dropdown calls back into takes
the owning UnityEditor.SerializedObject and a property path and re-finds the property — the
same deferral SerenityTypeSearchPicker.WriteStringDeferred makes for string fields.
Third, each write applies its own serialized changes, so a host watching only its own
ApplyModifiedProperties never sees them. Every successful write tells the
AchievementConditionEditContext, which is how an inspector's project-wide
findings stop describing a tree the author already changed.
Fields
ChildrenField
The serialized name of the child list every composite carries.
Declaration
public const string ChildrenField = "conditions"
Field Value
| Type | Description |
|---|---|
| string |
InnerField
The serialized name of the single child every wrapper carries.
Declaration
public const string InnerField = "inner"
Field Value
| Type | Description |
|---|---|
| string |
ReplaceDialogTitle
Heading of the question asked before a replacement drops children.
Declaration
public const string ReplaceDialogTitle = "Replace condition"
Field Value
| Type | Description |
|---|---|
| string |
ReplaceNodeUndoLabel
Undo label for a node type change.
Declaration
public const string ReplaceNodeUndoLabel = "Change Condition Type"
Field Value
| Type | Description |
|---|---|
| string |
Methods
AppendChildDeferred(SerializedObject, string, Type, AchievementConditionEditContext)
Appends a new child of the given type to a composite's list.
Declaration
public static void AppendChildDeferred(SerializedObject owner, string listPath, Type childType, AchievementConditionEditContext context)
Parameters
| Type | Name | Description |
|---|---|---|
| SerializedObject | owner | The serialized object the tree belongs to. |
| string | listPath | Path of the composite's child list. |
| Type | childType | The concrete condition type to append. |
| AchievementConditionEditContext | context | What the drawer was given to write with. |
ChildLossQuestion(AchievementCondition, AchievementCondition, int)
What the author is asked before a replacement drops children.
Declaration
public static string ChildLossQuestion(AchievementCondition previous, AchievementCondition replacement, int lostChildCount)
Parameters
| Type | Name | Description |
|---|---|---|
| AchievementCondition | previous | The node being replaced. |
| AchievementCondition | replacement | The node replacing it. |
| int | lostChildCount | How many children the replacement cannot hold. |
Returns
| Type | Description |
|---|---|
| string | The question. |
ChildrenToCarryOver(AchievementCondition, AchievementCondition)
The children a replacement node can take over from the node it replaces.
Declaration
public static List<AchievementCondition> ChildrenToCarryOver(AchievementCondition previous, AchievementCondition replacement)
Parameters
| Type | Name | Description |
|---|---|---|
| AchievementCondition | previous | The node being replaced. May be |
| AchievementCondition | replacement | The node replacing it. |
Returns
| Type | Description |
|---|---|
| List<AchievementCondition> | The children to carry over, in order. |
Remarks
A composite takes everything, so swapping between All Of, Any Of and In Order keeps the whole authored list, and promoting a wrapper to a composite keeps its one child. A wrapper takes over only from another wrapper: taking the first child of a composite would throw the rest away without saying so, and an author who meant that can remove them. A leaf takes nothing, because it has nowhere to put them.
ClearDeferred(SerializedObject, string, AchievementConditionEditContext)
Empties a node slot, leaving the achievement unlocked from code alone.
Declaration
public static void ClearDeferred(SerializedObject owner, string nodePath, AchievementConditionEditContext context)
Parameters
| Type | Name | Description |
|---|---|---|
| SerializedObject | owner | The serialized object the tree belongs to. |
| string | nodePath | Path of the node property to empty. |
| AchievementConditionEditContext | context | What the drawer was given to write with. |
MoveChild(SerializedProperty, int, int, AchievementConditionEditContext)
Moves one child to another position in a composite's list.
Declaration
public static void MoveChild(SerializedProperty listProperty, int fromIndex, int toIndex, AchievementConditionEditContext context)
Parameters
| Type | Name | Description |
|---|---|---|
| SerializedProperty | listProperty | The composite's child list. |
| int | fromIndex | Position of the child to move. |
| int | toIndex | Position to move it to. Out-of-range targets are ignored. |
| AchievementConditionEditContext | context | What the drawer was given to write with. |
RemoveChildAt(SerializedProperty, int, AchievementConditionEditContext)
Removes one child from a composite's list.
Declaration
public static void RemoveChildAt(SerializedProperty listProperty, int childIndex, AchievementConditionEditContext context)
Parameters
| Type | Name | Description |
|---|---|---|
| SerializedProperty | listProperty | The composite's child list. |
| int | childIndex | Position of the child to remove. |
| AchievementConditionEditContext | context | What the drawer was given to write with. |
Remarks
Deleted twice when the first delete only emptied the slot: Unity's array delete nulls an element before it removes it for some property kinds, and a tree left holding a null child reads to an author as a node that refuses to go away. Both deletes share the single apply below, so they are already one undo step without a group around them.
ReplaceDeferred(SerializedObject, string, Type, AchievementConditionEditContext)
Replaces the node a managed-reference property holds with a new node of the given type, carrying over the children the new shape can hold.
Declaration
public static void ReplaceDeferred(SerializedObject owner, string nodePath, Type replacementType, AchievementConditionEditContext context)
Parameters
| Type | Name | Description |
|---|---|---|
| SerializedObject | owner | The serialized object the tree belongs to. |
| string | nodePath | Path of the node property to replace. |
| Type | replacementType | The concrete condition type to put there. |
| AchievementConditionEditContext | context | What the drawer was given to write with. |
Remarks
Works for every slot a node can sit in — the achievement's root condition, a wrapper's inner slot, or one element of a composite's list — because all three are the same kind of managed-reference property. That is also why an empty slot is filled by the same call rather than by a separate "add" path.
Both serialized writes happen inside one undo group. Replacing the node and re-parenting its children are two applies, and two undo steps would let the author land on a tree holding the new node with none of its children — a state nobody authored.