# Universal API Discovery Methodology

When you need to work with ANY UE system — and you don't know the exact API — follow this priority order. Works for Materials, GAS, Niagara, AI, Audio, Animation, Physics, or any future engine system.

## Priority 1: query_ue_api (fastest, most reliable)

The `query_ue_api` tool searches UE reflection database. Use it FIRST for everything.

```
# Find classes by keyword
query_ue_api(mode="keyword", query="SoundCue")
query_ue_api(mode="keyword", query="GameplayAbility")
query_ue_api(mode="keyword", query="NiagaraSystem")

# Get full class info (properties, functions)
query_ue_api(mode="class_info", query="UGameplayAbility")

# Find functions by keyword across all classes
query_ue_api(mode="keyword", query="SpawnActor")
query_ue_api(mode="keyword", query="SetMaterial")

# Find enums
query_ue_api(mode="keyword", query="ECollisionChannel")
```

**When to use**: Always start here. Covers all reflected classes, functions, enums, structs.

## Priority 2: Python dir() + help() (runtime introspection)

When query_ue_api gives a class name but you need to explore its Python methods:

```python
import unreal

# List all methods/properties on a class
obj = unreal.EditorAssetLibrary
print([x for x in dir(obj) if not x.startswith('_')])

# Get method documentation
help(unreal.EditorAssetLibrary.save_asset)

# Explore a loaded object
asset = unreal.load_asset('/Game/Blueprints/BP_MyActor')
print(type(asset))
print([x for x in dir(asset) if not x.startswith('_')])
```

**When to use**: After query_ue_api found the class — explore what Python methods are available.

## Priority 3: get_editor_property_names() (discover settable properties)

```python
import unreal

asset = unreal.load_asset('/Game/Materials/M_Rock')
props = asset.get_editor_property_names()
for p in sorted(props):
    print(p)
```

**When to use**: When you need to configure an asset but don't know its property names.

## Priority 4: UniversalBridge JSON Reflection (complex/nested properties)

```python
import unreal
bridge = unreal.UNDUniversalBridge

# Read any property as JSON (including nested structs, arrays)
value = bridge.get_property_as_json(asset, 'SomeProperty')
print(value)

# Read nested property with dot-path
value = bridge.get_property_as_json(asset, 'EditorData.SubTrees[0].RootHash')
print(value)

# Serialize entire object to see all properties
full = bridge.serialize_object_to_json(asset)
print(full)
```

**When to use**: When get_editor_property fails (Transient, protected, complex nested struct).

## Priority 5: QueryGraphActions (discover graph nodes)

For ANY graph editor (Material, BehaviorTree, AnimBP, Niagara, ControlRig):

```python
import unreal
bridge = unreal.UNDUniversalBridge

# Get a graph from the asset
graph = ...  # e.g. from BlueprintEditorLibrary.find_graph(bp, 'EventGraph')

# Search for available nodes by keyword
actions = bridge.query_graph_actions(graph, 'Delay', 10)
for a in actions:
    print(a)  # "[0] Flow Control > Delay"
```

**When to use**: When you need to discover what nodes can be added to a specific graph type.

## Decision Tree

```
I need to find...
├── A class or function name → query_ue_api (keyword mode)
├── All methods on a class → dir(unreal.ClassName)
├── All settable properties → obj.get_editor_property_names()
├── A nested/complex property value → bridge.get_property_as_json()
├── What nodes exist for a graph → bridge.query_graph_actions()
├── Full object structure → bridge.serialize_object_to_json()
├── A factory for asset creation → query_ue_api("Factory" + system name)
└── An enum's values → query_ue_api(mode="keyword", query="EEnumName")
```

## CRITICAL: Python Binding Limitations

**Not everything C++ exposes is available in Python.** Know these rules:

### UFUNCTION vs UE_API
- `UFUNCTION()` → accessible from Python as `obj.method_name()`
- `UE_API` (no UFUNCTION) → C++ linkage only, NOT in Python
- Example: `UStateTreeFactory::SetSchemaClass()` is `UE_API` → Python can't call it

### UCLASS(MinimalAPI)
- Only exports `StaticClass()` and CDO — class may not appear in `unreal.*` namespace
- Example: `UStateTreeComponentSchema` → `unreal.StateTreeComponentSchema` fails

### Protected + Transient UPROPERTY
- Not accessible via `get_editor_property()` / `set_editor_property()`
- Use `UNDBlueprintHelpers.create_asset_with_factory()` for factory properties
- Use `UNDUniversalBridge.set_property_from_json()` for object properties

### Common AttributeError patterns
```
unreal.SomeClass()                    → class not in Python namespace
obj.some_method()                     → method is UE_API, not UFUNCTION
obj.set_editor_property('field', v)   → property is protected/Transient
```

**Solution for all three**: use UNDBlueprintHelpers or UNDUniversalBridge (C++ runtime reflection bypasses Python binding limits).

## Anti-Patterns

1. **NEVER guess function/class names** — always discover first via query_ue_api or dir()
2. **NEVER assume unreal.* namespace** — if it fails, the class lacks Python bindings
3. **NEVER hardcode API paths** from documentation — UE5 API changes between versions
4. **NEVER skip verification** — always `print()` results after discovery to confirm correctness
5. **NEVER call open_editor_for_asset()** — crashes editor (FMRUList null dereference)
