# Reading and Inspecting Blueprints via Python

Use `execute_python` with `import unreal` to read existing Blueprint structure, variables, components, and graphs.

## Load and inspect a Blueprint
```python
import unreal
bp = unreal.load_asset('/Game/Blueprints/BP_MyCharacter')
if bp:
    print(f'Blueprint: {bp.get_name()}')
    print(f'Path: {bp.get_path_name()}')
    print(f'Parent Class: {bp.parent_class.get_name() if bp.parent_class else "None"}')
    print(f'Type: {bp.blueprint_type}')
```

## List Blueprint variables (properties)
```python
import unreal
bp = unreal.load_asset('/Game/Blueprints/BP_MyCharacter')
if bp:
    for var_desc in bp.new_variables:
        print(f'  {var_desc.var_name} : {var_desc.var_type.pin_category}')
        # Check flags
        flags = var_desc.property_flags
        if flags & unreal.PropertyFlags.CPF_EDIT:
            print(f'    - EditAnywhere')
        if flags & unreal.PropertyFlags.CPF_BLUEPRINT_VISIBLE:
            print(f'    - BlueprintReadWrite')
        if flags & unreal.PropertyFlags.CPF_NET:
            print(f'    - Replicated')
```

## List Blueprint components (SCS tree)

> **CRITICAL:** `bp.simple_construction_script` does NOT work in UE 5.7 Python.
> Use `unreal.UNDBlueprintHelpers.get_blueprint_components()` instead.

```python
import unreal
bp = unreal.load_asset('/Game/Blueprints/BP_MyCharacter')
if bp:
    comps = unreal.UNDBlueprintHelpers.get_blueprint_components(bp)
    for comp in comps:
        print(f'  {comp}')
    # Output: "SpringArm (SpringArmComponent) [parent: ROOT]"
    #         "Camera (CameraComponent) [parent: SpringArm]"
```

## List Blueprint graphs
```python
import unreal
bp = unreal.load_asset('/Game/Blueprints/BP_MyCharacter')
if bp:
    # Event graphs (UbergraphPages)
    for graph in bp.ubergraph_pages:
        print(f'  [EventGraph] {graph.get_name()} — {len(graph.nodes)} nodes')
    # Function graphs
    for graph in bp.function_graphs:
        print(f'  [Function] {graph.get_name()} — {len(graph.nodes)} nodes')
    # Macro graphs
    for graph in bp.macro_graphs:
        print(f'  [Macro] {graph.get_name()} — {len(graph.nodes)} nodes')
```

## Read graph node details
```python
import unreal
bp = unreal.load_asset('/Game/Blueprints/BP_MyCharacter')
if bp and bp.ubergraph_pages:
    graph = bp.ubergraph_pages[0]  # First event graph
    for node in graph.nodes:
        title = node.get_node_title(unreal.NodeTitleType.FULL_TITLE)
        print(f'  Node: {title}')
        # List pins and connections
        for pin in node.pins:
            direction = 'IN' if pin.direction == unreal.EdGraphPinDirection.EGPD_INPUT else 'OUT'
            linked = [f'{l.get_owning_node().get_node_title(unreal.NodeTitleType.LIST_TITLE)}.{l.pin_name}'
                      for l in pin.linked_to if l.get_owning_node()]
            if linked:
                print(f'    {direction} {pin.pin_name} → {", ".join(linked)}')
```

## List implemented interfaces
```python
import unreal
bp = unreal.load_asset('/Game/Blueprints/BP_MyCharacter')
if bp:
    for iface in bp.implemented_interfaces:
        if iface.interface:
            print(f'  Implements: {iface.interface.get_name()}')
```

## Get CDO (Class Default Object) property values
```python
import unreal
bp = unreal.load_asset('/Game/Blueprints/BP_MyCharacter')
if bp:
    gen_class = bp.generated_class()
    cdo = unreal.get_default_object(gen_class)
    if cdo:
        # Read any UPROPERTY value
        print(f'  MaxHealth: {cdo.get_editor_property("MaxHealth")}')
```

## Common patterns
- **Before modifying a BP**: always read it first to understand current structure
- **Variable inspection**: iterate `bp.new_variables` for user-defined vars
- **Component tree**: use `unreal.UNDBlueprintHelpers.get_blueprint_components(bp)` to see full hierarchy
- **Graph analysis**: iterate `graph.nodes` and check `node.pins` for connections
- **Compare**: read two BPs and diff their variables/components/graphs

## Critical rules
- Always check if asset exists before loading (`query_ue_api('does asset exist')` to find the check method)
- Cast loaded asset: `unreal.load_asset()` returns UObject, cast to UBlueprint
- Some Python API names may differ from C++ — use `dir(node)` to discover available methods
- Graph node inspection is read-only — modification uses different APIs (see blueprint_graphs module)
