| 633 | } |
| 634 | |
| 635 | bool Prefab::ApplyAll(Actor* targetActor) |
| 636 | { |
| 637 | PROFILE_CPU(); |
| 638 | const auto startTime = DateTime::NowUTC(); |
| 639 | |
| 640 | // Perform validation |
| 641 | if (!IsLoaded()) |
| 642 | { |
| 643 | Log::Exception(TEXT("Cannot apply changes on not loaded prefab asset.")); |
| 644 | return true; |
| 645 | } |
| 646 | if (targetActor == nullptr) |
| 647 | { |
| 648 | Log::ArgumentNullException(); |
| 649 | return true; |
| 650 | } |
| 651 | if (targetActor->GetPrefabID() != GetID()) |
| 652 | { |
| 653 | Log::Exception(TEXT("Cannot apply changes to the prefab. Prefab instance root object has link to the other prefab.")); |
| 654 | return true; |
| 655 | } |
| 656 | if (GetDefaultInstance() == nullptr) |
| 657 | { |
| 658 | LOG(Warning, "Failed to create default prefab instance for the prefab asset."); |
| 659 | return true; |
| 660 | } |
| 661 | if (targetActor == _defaultInstance || targetActor->HasActorInHierarchy(_defaultInstance) || _defaultInstance->HasActorInHierarchy(targetActor)) |
| 662 | { |
| 663 | LOG(Error, "Cannot apply changes to the prefab using default instance. Use manually spawned prefab instance instead."); |
| 664 | return true; |
| 665 | } |
| 666 | if (targetActor->GetPrefabObjectID() != GetRootObjectId()) |
| 667 | { |
| 668 | LOG(Warning, "Applying prefab changes with modified root object. Root object id: {0}, new root: {1} (prefab object id: {2})", GetRootObjectId().ToString(), targetActor->ToString(), targetActor->GetPrefabObjectID()); |
| 669 | SceneObject* newRootDefault = GetDefaultInstance(targetActor->GetPrefabObjectID()); |
| 670 | const ISerializable::DeserializeStream** newRootDataPtr = ObjectsDataCache.TryGet(targetActor->GetPrefabObjectID()); |
| 671 | if (!newRootDefault || !newRootDataPtr || !*newRootDataPtr) |
| 672 | { |
| 673 | LOG(Error, "Cannot change the prefab root object to the actor that is not yet added to the prefab."); |
| 674 | return true; |
| 675 | } |
| 676 | const ISerializable::DeserializeStream& newRootData = **newRootDataPtr; |
| 677 | Guid prefabId, prefabObjectID; |
| 678 | if (JsonTools::GetGuidIfValid(prefabId, newRootData, "PrefabID") && JsonTools::GetGuidIfValid(prefabObjectID, newRootData, "PrefabObjectID")) |
| 679 | { |
| 680 | const auto nestedPrefab = Content::Load<Prefab>(prefabId); |
| 681 | if (nestedPrefab && nestedPrefab->GetRootObjectId() != prefabObjectID) |
| 682 | { |
| 683 | LOG(Error, "Cannot change the prefab root object is from other nested prefab (excluding root of that nested prefab prefab)."); |
| 684 | return true; |
| 685 | } |
| 686 | } |
| 687 | } |
| 688 | if (!IsInMainThread()) |
| 689 | { |
| 690 | // Prefabs cannot be updated on async thread so sync it with a Main Thread |
| 691 | bool result = true; |
| 692 | Function<void()> action = [&] |
no test coverage detected