# export_abc()

지정된 슬롯의 레퍼런스를 Alembic(`.abc`) 파일로 내보냅니다.

UE5에서는 Geometry Cache(버텍스 베이크)로 들어갑니다. Morph는 Skeletal Morph Target이 아니라 버텍스 애니메이션으로 보존됩니다.

### 시그니처
```python
api.export_abc(slot: int, output_path: str, abc_options: dict = None, preset: str = None) -> dict
```

### 파라미터
| 파라미터 | 타입 | 설명 |
| --- | --- | --- |
| `slot` | `int` | 내보낼 슬롯 번호 (`0 .. MAX_REFERENCE_SLOTS-1`, 현재 최대 20) |
| `output_path` | `str` | 출력 `.abc` 파일의 절대 경로 |
| `abc_options` | `dict` | Alembic 옵션 오버라이드 (생략 시 preset 또는 기본 프리셋 사용) |
| `preset` | `str` | 사용할 프리셋 이름 (예: `"Unreal_UE5"`, `"Unity_ABC"`) |

`preset`과 `abc_options`를 동시에 지정하면, preset을 먼저 로드한 뒤 `abc_options`로 덮어씁니다.

### 반환값
```python
# success
{"success": True, "message": str, "output_path": str}

# failure
{"success": False, "message": str, "error": str}
```

Defined Selection Set 모드(`fbxExportMode == "Defined"`)이고 셋이 2개 이상이면, 내부적으로 셋별 파일을 만들고 집계 결과를 반환할 수 있습니다 (`details` / `success_count` 등).

### 예외
| 예외 | 조건 |
| --- | --- |
| `TypeError` | slot이 int가 아닐 때 (bool 포함), `abc_options`가 dict가 아닐 때 |
| `ValueError` | 슬롯이 유효하지 않거나 비어 있을 때, 출력 경로 디렉토리 없을 때, 없는 preset 이름 |

### 예제
```python
from os_fast_ref.api import FastRefAPI

api = FastRefAPI()
api.refresh()

# Default preset
result = api.export_abc(slot=0, output_path=r"J:\output\character.abc")

# Named preset (UE5 Geometry Cache)
result = api.export_abc(
    slot=0,
    output_path=r"J:\output\char.abc",
    preset="Unreal_UE5",
)

# Meshes only (bones excluded from select; Reset Root still uses full bone list)
result = api.export_abc(
    slot=0,
    output_path=r"J:\output\char_mesh.abc",
    preset="Unreal_UE5",
    abc_options={"ExportMeshes": True, "ExportBones": False},
)

# preset + partial override
result = api.export_abc(
    slot=0,
    output_path=r"J:\output\char.abc",
    preset="Unity_ABC",
    abc_options={"ResetRoot": True, "RemoveNameSpace": True},
)

if result["success"]:
    print(f"Export complete: {result.get('output_path', result.get('message'))}")
else:
    print(f"Export failed: {result.get('error', result.get('message'))}")
```

---