void PrefabUtility::restoreLinkedInstanceData(const HSceneObject& so, SceneObjectProxy& proxy, UnorderedMap<UINT32, GameObjectInstanceDataPtr>& linkedInstanceData) { Stack<HSceneObject> todo; todo.push(so); // Root is not in the instance data map because its link ID belongs to the parent prefab, if any so->_setInstanceData(proxy.instanceData); while (!todo.empty()) { HSceneObject current = todo.top(); todo.pop(); Vector<HComponent>& components = current->mComponents; for (auto& component : components) { if (component->getLinkId() != (UINT32)-1) { auto iterFind = linkedInstanceData.find(component->getLinkId()); if (iterFind != linkedInstanceData.end()) { component->_setInstanceData(iterFind->second); component._setHandleData(component.getInternalPtr()); } } } UINT32 numChildren = current->getNumChildren(); for (UINT32 i = 0; i < numChildren; i++) { HSceneObject child = current->getChild(i); if (child->getLinkId() != (UINT32)-1) { auto iterFind = linkedInstanceData.find(child->getLinkId()); if (iterFind != linkedInstanceData.end()) child->_setInstanceData(iterFind->second); } if (child->mPrefabLinkUUID.empty()) todo.push(child); } } }
void PrefabDiff::renameInstanceIds(const HSceneObject& prefab, const HSceneObject& instance, Vector<RenamedGameObject>& output) { UnorderedMap<String, UnorderedMap<UINT32, UINT64>> linkToInstanceId; struct StackEntry { HSceneObject so; String uuid; }; // When renaming it is important to rename the prefab and not the instance, since the diff will otherwise // contain prefab's IDs, but will be used for the instance. Stack<StackEntry> todo; todo.push({ instance, "root" }); while (!todo.empty()) { StackEntry current = todo.top(); todo.pop(); String childParentUUID; if (current.so->mPrefabLinkUUID.empty()) childParentUUID = current.uuid; else childParentUUID = current.so->mPrefabLinkUUID; UnorderedMap<UINT32, UINT64>& idMap = linkToInstanceId[childParentUUID]; const Vector<HComponent>& components = current.so->getComponents(); for (auto& component : components) { if (component->getLinkId() != (UINT32)-1) idMap[component->getLinkId()] = component->getInstanceId(); } UINT32 numChildren = current.so->getNumChildren(); for (UINT32 i = 0; i < numChildren; i++) { HSceneObject child = current.so->getChild(i); if (child->getLinkId() != (UINT32)-1) idMap[child->getLinkId()] = child->getInstanceId(); todo.push({ child, childParentUUID }); } } // Root has link ID from its parent so we handle it separately { output.push_back(RenamedGameObject()); RenamedGameObject& renamedGO = output.back(); renamedGO.instanceData = instance->mInstanceData; renamedGO.originalId = instance->getInstanceId(); prefab->mInstanceData->mInstanceId = instance->getInstanceId(); } todo.push({ prefab, "root" }); while (!todo.empty()) { StackEntry current = todo.top(); todo.pop(); String childParentUUID; if (current.so->mPrefabLinkUUID.empty()) childParentUUID = current.uuid; else childParentUUID = current.so->mPrefabLinkUUID; auto iterFind = linkToInstanceId.find(childParentUUID); if (iterFind != linkToInstanceId.end()) { UnorderedMap<UINT32, UINT64>& idMap = iterFind->second; const Vector<HComponent>& components = current.so->getComponents(); for (auto& component : components) { auto iterFind2 = idMap.find(component->getLinkId()); if (iterFind2 != idMap.end()) { output.push_back(RenamedGameObject()); RenamedGameObject& renamedGO = output.back(); renamedGO.instanceData = component->mInstanceData; renamedGO.originalId = component->getInstanceId(); component->mInstanceData->mInstanceId = iterFind2->second; } } } UINT32 numChildren = current.so->getNumChildren(); for (UINT32 i = 0; i < numChildren; i++) { HSceneObject child = current.so->getChild(i); if (iterFind != linkToInstanceId.end()) { if (child->getLinkId() != -1) { UnorderedMap<UINT32, UINT64>& idMap = iterFind->second; auto iterFind2 = idMap.find(child->getLinkId()); if (iterFind2 != idMap.end()) { output.push_back(RenamedGameObject()); RenamedGameObject& renamedGO = output.back(); renamedGO.instanceData = child->mInstanceData; renamedGO.originalId = child->getInstanceId(); child->mInstanceData->mInstanceId = iterFind2->second; } } } todo.push({ child, childParentUUID }); } } }