| 1240 | } |
| 1241 | |
| 1242 | bool DuplicateActorSync( |
| 1243 | const FString& SrcKey, |
| 1244 | const FString& NewActorId, |
| 1245 | bool bHasOverrideLocation, |
| 1246 | const FVector& OverrideLocationMeters, |
| 1247 | FString& OutActorName, |
| 1248 | FString& OutActorPath, |
| 1249 | FString& OutBlueprintClassPath, |
| 1250 | FString& OutError) |
| 1251 | { |
| 1252 | OutError.Empty(); |
| 1253 | if (!GEditor) |
| 1254 | { |
| 1255 | OutError = TEXT("GEditor null"); |
| 1256 | return false; |
| 1257 | } |
| 1258 | UWorld* World = GEditor->GetEditorWorldContext().World(); |
| 1259 | if (!World) |
| 1260 | { |
| 1261 | OutError = TEXT("editor world unavailable"); |
| 1262 | return false; |
| 1263 | } |
| 1264 | AActor* Src = FindByActorIdOrName(World, SrcKey); |
| 1265 | if (!Src) |
| 1266 | { |
| 1267 | OutError = FString::Printf(TEXT("no actor matching '%s'"), *SrcKey); |
| 1268 | return false; |
| 1269 | } |
| 1270 | |
| 1271 | // MJ metres throughout. |
| 1272 | FVector SourceMjPos; |
| 1273 | { |
| 1274 | double MjPos[3]; |
| 1275 | MjUtils::UEToMjPosition(Src->GetActorLocation(), MjPos); |
| 1276 | SourceMjPos = FVector(MjPos[0], MjPos[1], MjPos[2]); |
| 1277 | } |
| 1278 | FQuat SrcQuatXyzw; |
| 1279 | { |
| 1280 | double MjQuat[4]; |
| 1281 | MjUtils::UEToMjRotation(Src->GetActorQuat(), MjQuat); |
| 1282 | // MjUtils emits wxyz; pack as xyzw for SpawnActorSync. |
| 1283 | SrcQuatXyzw = FQuat(MjQuat[1], MjQuat[2], MjQuat[3], MjQuat[0]); |
| 1284 | } |
| 1285 | const FVector SrcScale = Src->GetActorScale3D(); |
| 1286 | |
| 1287 | const FVector SpawnLoc = bHasOverrideLocation |
| 1288 | ? OverrideLocationMeters |
| 1289 | : SourceMjPos + FVector(1.0, 0.0, 0.0); // default: 1m on +X |
| 1290 | |
| 1291 | bool bWasExisting = false; |
| 1292 | return SpawnActorSync( |
| 1293 | Src->GetClass()->GetPathName(), |
| 1294 | NewActorId, SpawnLoc, SrcQuatXyzw, SrcScale, |
| 1295 | OutActorName, OutActorPath, OutBlueprintClassPath, |
| 1296 | bWasExisting, OutError); |
| 1297 | } |
| 1298 | |
| 1299 | bool ActorHierarchySync( |