# Blueprint Component Management via UNDBlueprintHelpers

> UE 5.7 does NOT expose `simple_construction_script` to Python.
> **NEVER** use `bp.simple_construction_script` — it will raise AttributeError.
> **NEVER** call `open_editor_for_asset()` — crashes the editor.
> Use `unreal.UNDBlueprintHelpers` (C++ wrappers) for ALL component operations.

## Add a component to a Blueprint

```python
import unreal
helpers = unreal.UNDBlueprintHelpers
bp = unreal.load_asset('/Game/Blueprints/BP_MyActor')

# Add a static mesh component (attaches to root by default)
helpers.add_component_to_blueprint(bp, 'StaticMeshComponent', 'FloorMesh')

# Add with parent attachment
helpers.add_component_to_blueprint(bp, 'SpringArmComponent', 'SpringArm')
helpers.add_component_to_blueprint(bp, 'CameraComponent', 'Camera', 'SpringArm')

# Add as new root component (replaces DefaultSceneRoot)
helpers.add_component_to_blueprint(bp, 'SceneComponent', 'Root', '', True)

# Compile + save after adding components
unreal.KismetEditorLibrary.compile_blueprint(bp)
unreal.EditorAssetLibrary.save_loaded_asset(bp)
```

## Set component properties (defaults)

```python
helpers = unreal.UNDBlueprintHelpers
bp = unreal.load_asset('/Game/Blueprints/BP_MyActor')

# Set mesh asset (object property — use full asset path in quotes)
helpers.set_component_property(bp, 'FloorMesh', 'StaticMesh', '"/Engine/BasicShapes/Cube"')

# Set numeric property
helpers.set_component_property(bp, 'FloorMesh', 'CastShadow', 'true')

# Set struct property (Vector, Rotator, etc. — JSON object)
helpers.set_component_property(bp, 'FloorMesh', 'RelativeLocation', '{"X": 0, "Y": 0, "Z": -50}')
helpers.set_component_property(bp, 'FloorMesh', 'RelativeScale3D', '{"X": 5, "Y": 5, "Z": 0.1}')

# Set collision profile (string/name property)
helpers.set_component_property(bp, 'Trigger', 'CollisionProfileName', '"Trigger"')
```

## List existing components

```python
bp = unreal.load_asset('/Game/Blueprints/BP_MyActor')
for comp in unreal.UNDBlueprintHelpers.get_blueprint_components(bp):
    print(comp)
# Output: "SpringArm (SpringArmComponent) [parent: ROOT]"
#         "Camera (CameraComponent) [parent: SpringArm]"
```

## Remove a component

```python
helpers = unreal.UNDBlueprintHelpers
bp = unreal.load_asset('/Game/Blueprints/BP_MyActor')
helpers.remove_component_from_blueprint(bp, 'OldMesh')
```

## Trigger volumes (BoxComponent / SphereComponent)

```python
import unreal
helpers = unreal.UNDBlueprintHelpers
bp = unreal.load_asset('/Game/Blueprints/BP_PickupItem')

# Add sphere trigger
helpers.add_component_to_blueprint(bp, 'SphereComponent', 'PickupTrigger')

# Configure trigger properties
helpers.set_component_property(bp, 'PickupTrigger', 'SphereRadius', '150.0')
helpers.set_component_property(bp, 'PickupTrigger', 'CollisionProfileName', '"Trigger"')
helpers.set_component_property(bp, 'PickupTrigger', 'GenerateOverlapEvents', 'true')
helpers.set_component_property(bp, 'PickupTrigger', 'HiddenInGame', 'true')

# Compile + save
unreal.KismetEditorLibrary.compile_blueprint(bp)
unreal.EditorAssetLibrary.save_loaded_asset(bp)
```

## Common component types
- `StaticMeshComponent` — static mesh rendering
- `SkeletalMeshComponent` — skeletal mesh with animation
- `SceneComponent` — base transform (default root)
- `CapsuleComponent` — collision capsule
- `SpringArmComponent` — camera boom
- `CameraComponent` — camera
- `CharacterMovementComponent` — movement (ACharacter only, auto-created)
- `BoxComponent` / `SphereComponent` — collision shapes
- `AudioComponent` — spatial sound
- `PointLightComponent` / `SpotLightComponent` — lights
- `NiagaraComponent` — particle effects
- `WidgetComponent` — 3D UI widget
- `ArrowComponent` — directional indicator (editor only)
- `SplineComponent` — path/curve
- `ProjectileMovementComponent` — projectile physics
- `RotatingMovementComponent` — constant rotation

## CRITICAL RULES
- ALWAYS use `unreal.UNDBlueprintHelpers` for component operations — NOT `bp.simple_construction_script`
- ALWAYS verify with `get_blueprint_components()` before AND after modifications
- ALWAYS compile + save after component changes
- ACharacter already has CapsuleComponent, CharacterMovement, Mesh — don't duplicate
- Component class names are case-insensitive, U prefix is optional
- Fuzzy matching will auto-correct typos (e.g. "StatcMeshComponent" → "StaticMeshComponent")
