| 482 | } // namespace |
| 483 | |
| 484 | bool SpawnLightSync( |
| 485 | const FString& Kind, |
| 486 | const FString& ActorId, |
| 487 | const FVector& LocationMeters, |
| 488 | const FVector& RotationEulerDegrees, |
| 489 | float Intensity, |
| 490 | const FLinearColor& Color, |
| 491 | FString& OutActorName, |
| 492 | FString& OutActorPath, |
| 493 | FString& OutResolvedKind, |
| 494 | FString& OutError) |
| 495 | { |
| 496 | OutActorName.Empty(); |
| 497 | OutActorPath.Empty(); |
| 498 | OutResolvedKind.Empty(); |
| 499 | OutError.Empty(); |
| 500 | |
| 501 | if (!GEditor) |
| 502 | { |
| 503 | OutError = TEXT("GEditor null"); |
| 504 | return false; |
| 505 | } |
| 506 | UWorld* World = GEditor->GetEditorWorldContext().World(); |
| 507 | if (!World) |
| 508 | { |
| 509 | OutError = TEXT("editor world unavailable"); |
| 510 | return false; |
| 511 | } |
| 512 | |
| 513 | UClass* LightClass = LightClassForKind(Kind); |
| 514 | if (!LightClass) |
| 515 | { |
| 516 | OutError = FString::Printf( |
| 517 | TEXT("unknown light kind '%s' (expect directional|point|spot)"), |
| 518 | *Kind); |
| 519 | return false; |
| 520 | } |
| 521 | OutResolvedKind = Kind.ToLower(); |
| 522 | |
| 523 | // Position: MJ -> UE (cm + Y-flip + handedness handled by helper). |
| 524 | double MjPos[3] = {LocationMeters.X, LocationMeters.Y, LocationMeters.Z}; |
| 525 | const FVector UELoc = MjUtils::MjToUEPosition(MjPos); |
| 526 | |
| 527 | // Rotation: input is degrees in (Roll, Pitch, Yaw) along MJ axes |
| 528 | // (X, Y, Z respectively). FRotator constructor is (Pitch, Yaw, Roll). |
| 529 | const FRotator UERot(RotationEulerDegrees.Y, RotationEulerDegrees.Z, |
| 530 | RotationEulerDegrees.X); |
| 531 | |
| 532 | FActorSpawnParameters Params; |
| 533 | Params.SpawnCollisionHandlingOverride = ESpawnActorCollisionHandlingMethod::AlwaysSpawn; |
| 534 | AActor* Actor = World->SpawnActor(LightClass, &UELoc, &UERot, Params); |
| 535 | if (!Actor) |
| 536 | { |
| 537 | OutError = FString::Printf(TEXT("SpawnActor returned null for light '%s'"), *Kind); |
| 538 | return false; |
| 539 | } |
| 540 | |
| 541 | // Apply intensity / colour through the LightComponent. |