void CmdDeleteSO::recordSO(const HSceneObject& sceneObject) { MemorySerializer serializer; mSerializedObject = serializer.encode(mSceneObject.get(), mSerializedObjectSize); HSceneObject parent = mSceneObject->getParent(); if (parent != nullptr) mSerializedObjectParentId = parent->getInstanceId(); mSceneObjectProxy = CmdUtility::createProxy(mSceneObject); }
void CmdBreakPrefab::revert() { if (mPrefabRoot == nullptr || mPrefabRoot.isDestroyed()) return; mPrefabRoot->_setPrefabLinkUUID(mPrefabLinkUUID); mPrefabRoot->_setPrefabDiff(mPrefabDiff); Stack<HSceneObject> todo; todo.push(mPrefabRoot); while (!todo.empty()) { HSceneObject currentSO = todo.top(); todo.pop(); const Vector<HComponent>& components = currentSO->getComponents(); for (auto& component : components) { auto iterFind = mLinkIds.find(component->getInstanceId()); if (iterFind != mLinkIds.end()) component->_setLinkId(iterFind->second); } UINT32 numChildren = (UINT32)currentSO->getNumChildren(); for (UINT32 i = 0; i < numChildren; i++) { HSceneObject child = currentSO->getChild(i); auto iterFind = mLinkIds.find(child->getInstanceId()); if (iterFind != mLinkIds.end()) child->_setLinkId(iterFind->second); if (child->_getPrefabLinkUUID().empty()) todo.push(child); } } }
void CmdBreakPrefab::commit() { clear(); if (mSceneObject == nullptr || mSceneObject.isDestroyed()) return; HSceneObject rootObj = mSceneObject; while (rootObj != nullptr) { if (!rootObj->_getPrefabLinkUUID().empty()) break; if (rootObj->getParent() != nullptr) rootObj = rootObj->getParent(); else rootObj = nullptr; } if (rootObj != nullptr) { mPrefabRoot = rootObj; mPrefabLinkUUID = rootObj->_getPrefabLinkUUID(); mPrefabDiff = rootObj->_getPrefabDiff(); Stack<HSceneObject> todo; todo.push(mPrefabRoot); while (!todo.empty()) { HSceneObject currentSO = todo.top(); todo.pop(); const Vector<HComponent>& components = currentSO->getComponents(); for (auto& component : components) { UINT32 linkId = component->getLinkId(); if (linkId != (UINT32)-1) mLinkIds[component->getInstanceId()] = linkId; mLinkIds[component->getInstanceId()] = component->getLinkId(); } UINT32 numChildren = (UINT32)currentSO->getNumChildren(); for (UINT32 i = 0; i < numChildren; i++) { HSceneObject child = currentSO->getChild(i); UINT32 linkId = child->getLinkId(); if (linkId != (UINT32)-1) mLinkIds[child->getInstanceId()] = linkId; if (child->_getPrefabLinkUUID().empty()) todo.push(child); } } } mSceneObject->breakPrefabLink(); }
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 }); } } }