# Custom Attributes

Spark provides a set of custom attributes for controlling how fields appear in the Spark Editor. These attributes work on fields in `SparkDatabaseEntry` subclasses and other serialized objects.

## Inspector Attributes

### \[Section]

Groups fields under a collapsible header in the inspector.

```csharp
[Section("Movement Settings")]
[SerializeField] private float speed = 5f;
[SerializeField] private float jumpHeight = 2f;

[Section("Combat Settings", collapsible: true)]
[SerializeField] private float attackDamage = 10f;
```

All fields between one `[Section]` and the next (or the end of the class) are grouped under that section. The `collapsible` parameter defaults to true.

### \[DisplayNameTooltip]

Overrides the field label and adds a tooltip.

```csharp
[DisplayNameTooltip("Walk Speed", "Base movement speed in units per second.")]
[SerializeField] private float speed = 5f;
```

### \[ReadOnly]

Makes a field visible but not editable in the inspector. Useful for displaying computed or system-managed values.

```csharp
[ReadOnly]
[SerializeField] private string generatedId;
```

### \[InlineField]

Renders a nested object's fields directly in the parent inspector instead of as a foldout.

```csharp
[InlineField]
[SerializeField] private DamageSettings damageSettings;
```

### \[SparkInspector]

Marks a class or field for full Spark inspector customization. This attribute signals the editor to use Spark's custom rendering pipeline for the entire inspector.

### \[SparkFoldout]

Controls foldout behavior for nested objects.

```csharp
[SparkFoldout(defaultOpen: true)]
[SerializeField] private AdvancedSettings settings;
```

## Field Attributes

### \[ConditionalField]

Shows or hides a field based on the value of another field on the same object.

```csharp
[SerializeField] private bool useCustomSpeed = false;

[ConditionalField("useCustomSpeed", true)]
[SerializeField] private float customSpeed = 10f;
```

The field `customSpeed` only appears when `useCustomSpeed` is `true`. Works with bools, enums, strings, and ints.

```csharp
[SerializeField] private DamageType damageType;

[ConditionalField("damageType", DamageType.Fire)]
[SerializeField] private float burnDuration = 3f;
```

### \[ConditionalMultiField]

Shows a field based on multiple conditions.

```csharp
[ConditionalMultiField("isRanged", true, "hasAmmo", true)]
[SerializeField] private int ammoCapacity = 30;
```

Both conditions must be true for the field to show.

### \[Switch]

Switches field rendering based on another field's value. Similar to conditional fields but designed for switching between different field layouts.

```csharp
[SerializeField] private TargetingMode targetMode;

[Switch("targetMode", "Single", "AoE")]
[SerializeField] private float radius = 5f; // Only shown for AoE
```

### \[NestedField]

Renders nested data objects inline with full editing support.

```csharp
[NestedField]
[SerializeField] private List<RewardData> rewards;
```

### \[TagField]

Renders a dropdown with Unity tags.

```csharp
[TagField]
[SerializeField] private string targetTag = "Player";
```

### \[CustomFieldUI]

Marks a field for custom UI rendering. The corresponding custom UI handler must be registered in the editor.

```csharp
[CustomFieldUI("ColorPicker")]
[SerializeField] private Color tintColor = Color.white;
```

## Database Attributes

### \[SparkDatabaseEntrySelector]

Creates a dropdown picker that lets you select any `SparkDatabaseEntry` from the project.

```csharp
[SparkDatabaseEntrySelector]
[SerializeField] private string targetEntryId;
```

This opens the entry selector window with search, filtering, and type selection.

### \[DatabaseEntryDropdown]

Creates a dropdown picker filtered to a specific entry type.

```csharp
[DatabaseEntryDropdown(typeof(ItemEntry))]
[SerializeField] private string requiredItemId;

[DatabaseEntryDropdown(typeof(QuestEntry))]
[SerializeField] private string prerequisiteQuestId;
```

This is more focused than `[SparkDatabaseEntrySelector]` and only shows entries of the specified type.

### \[ScriptableObjectDropdown]

Creates a dropdown for selecting ScriptableObject assets of a specific type.

```csharp
[ScriptableObjectDropdown(typeof(LootTableEntry))]
[SerializeField] private LootTableEntry lootTable;
```

### \[NestedData]

Marks a list of `SparkDatabaseEntryNestedData` for inline editing.

```csharp
[NestedData]
[SerializeField] private List<QuestObjective> objectives;
```

The Spark Editor renders these as an editable list with add/remove/reorder controls.

### \[ShowInEventDropdown]

Exposes a field or event for use in the string-based event dropdown system. This makes it selectable in trigger and rule configurations.

## Trigger Attributes

### \[TriggerRefresh]

Marks a field that should trigger a UI refresh when changed. Used in trigger and requirement type editors.

```csharp
[TriggerRefresh]
[SerializeField] private TriggerMode mode;
```

### \[HorizontalRuleTriggers]

Adds a visual separator before trigger fields in the editor.

### \[HorizontalRuleChecks]

Adds a visual separator before requirement check fields in the editor.

## Combining Attributes

Attributes can be combined on a single field:

```csharp
[Section("Rewards")]
[DisplayNameTooltip("Gold Reward", "Amount of gold given on completion.")]
[ConditionalField("rewardType", RewardType.Currency)]
[SerializeField] private int goldAmount = 100;
```

The `[Section]` groups the field, `[DisplayNameTooltip]` customizes the label, and `[ConditionalField]` controls visibility. They all work together.

## Usage Guidelines

* Use `[Section]` on every entry with more than 5 fields. It keeps the inspector organized.
* Use `[ConditionalField]` to hide irrelevant options. Show only what matters for the current configuration.
* Use `[DatabaseEntryDropdown]` instead of raw string fields for entry references. It prevents typos and shows available options.
* Use `[ReadOnly]` for system-managed fields that users should see but not edit.
* Use `[DisplayNameTooltip]` for fields where the variable name alone is not clear enough.


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://docs.sparkframework.dev/documentation/developer-guide/core-systems/custom-attributes.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
