UINT32 PrefabUtility::generatePrefabIds(const HSceneObject& sceneObject, UINT32 startingId) { Stack<HSceneObject> todo; todo.push(sceneObject); while (!todo.empty()) { HSceneObject currentSO = todo.top(); todo.pop(); for (auto& component : currentSO->mComponents) { if (component->getLinkId() == (UINT32)-1) component->mLinkId = startingId++; } UINT32 numChildren = (UINT32)currentSO->getNumChildren(); for (UINT32 i = 0; i < numChildren; i++) { HSceneObject child = currentSO->getChild(i); if (!child->hasFlag(SOF_DontSave)) { if (child->getLinkId() == (UINT32)-1) child->mLinkId = startingId++; if(child->mPrefabLinkUUID.empty()) todo.push(currentSO->getChild(i)); } } } return startingId; }
bool ScriptEditorUtility::internal_IsInternal(ScriptSceneObject* soPtr) { if (ScriptSceneObject::checkIfDestroyed(soPtr)) return false; HSceneObject so = soPtr->getHandle(); return so->hasFlag(SOF_Internal); }
void Prefab::initialize(const HSceneObject& sceneObject) { sceneObject->mPrefabDiff = nullptr; UINT32 newNextLinkId = PrefabUtility::generatePrefabIds(sceneObject, mNextLinkId); if (newNextLinkId < mNextLinkId) { BS_EXCEPT(InternalErrorException, "Prefab ran out of IDs to assign. " \ "Consider increasing the size of the prefab ID data type."); } mNextLinkId = newNextLinkId; // If there are any child prefab instances, make sure to update their diffs so they are saved with this prefab Stack<HSceneObject> todo; todo.push(sceneObject); while (!todo.empty()) { HSceneObject current = todo.top(); todo.pop(); UINT32 childCount = current->getNumChildren(); for (UINT32 i = 0; i < childCount; i++) { HSceneObject child = current->getChild(i); if (!child->mPrefabLinkUUID.empty()) PrefabUtility::recordPrefabDiff(child); else todo.push(child); } } // Clone the hierarchy for internal storage mRoot = sceneObject->clone(false); mRoot->mParent = nullptr; // Remove objects with "dont save" flag todo.push(mRoot); while (!todo.empty()) { HSceneObject current = todo.top(); todo.pop(); if (current->hasFlag(SOF_DontSave)) current->destroy(); else { UINT32 numChildren = current->getNumChildren(); for (UINT32 i = 0; i < numChildren; i++) todo.push(current->getChild(i)); } } }
void Prefab::initialize(const HSceneObject& sceneObject) { sceneObject->mPrefabDiff = nullptr; PrefabUtility::generatePrefabIds(sceneObject); // If there are any child prefab instances, make sure to update their diffs so they are saved with this prefab Stack<HSceneObject> todo; todo.push(sceneObject); while (!todo.empty()) { HSceneObject current = todo.top(); todo.pop(); UINT32 childCount = current->getNumChildren(); for (UINT32 i = 0; i < childCount; i++) { HSceneObject child = current->getChild(i); if (!child->mPrefabLinkUUID.empty()) PrefabUtility::recordPrefabDiff(child); else todo.push(child); } } // Clone the hierarchy for internal storage if (mRoot != nullptr) mRoot->destroy(true); mRoot = sceneObject->clone(false); mRoot->mParent = nullptr; mRoot->mLinkId = -1; // Remove objects with "dont save" flag todo.push(mRoot); while (!todo.empty()) { HSceneObject current = todo.top(); todo.pop(); if (current->hasFlag(SOF_DontSave)) current->destroy(); else { UINT32 numChildren = current->getNumChildren(); for (UINT32 i = 0; i < numChildren; i++) todo.push(current->getChild(i)); } } }
SPtr<PrefabObjectDiff> PrefabDiff::generateDiff(const HSceneObject& prefab, const HSceneObject& instance) { SPtr<PrefabObjectDiff> output; if (prefab->getName() != instance->getName()) { if (output == nullptr) output = bs_shared_ptr_new<PrefabObjectDiff>(); output->name = instance->getName(); output->soFlags |= (UINT32)SceneObjectDiffFlags::Name; } if (prefab->getPosition() != instance->getPosition()) { if (output == nullptr) output = bs_shared_ptr_new<PrefabObjectDiff>(); output->position = instance->getPosition(); output->soFlags |= (UINT32)SceneObjectDiffFlags::Position; } if (prefab->getRotation() != instance->getRotation()) { if (output == nullptr) output = bs_shared_ptr_new<PrefabObjectDiff>(); output->rotation = instance->getRotation(); output->soFlags |= (UINT32)SceneObjectDiffFlags::Rotation; } if (prefab->getScale() != instance->getScale()) { if (output == nullptr) output = bs_shared_ptr_new<PrefabObjectDiff>(); output->scale = instance->getScale(); output->soFlags |= (UINT32)SceneObjectDiffFlags::Scale; } if (prefab->getActive() != instance->getActive()) { if (output == nullptr) output = bs_shared_ptr_new<PrefabObjectDiff>(); output->isActive = instance->getActive(); output->soFlags |= (UINT32)SceneObjectDiffFlags::Active; } UINT32 prefabChildCount = prefab->getNumChildren(); UINT32 instanceChildCount = instance->getNumChildren(); // Find modified and removed children for (UINT32 i = 0; i < prefabChildCount; i++) { HSceneObject prefabChild = prefab->getChild(i); SPtr<PrefabObjectDiff> childDiff; bool foundMatching = false; for (UINT32 j = 0; j < instanceChildCount; j++) { HSceneObject instanceChild = instance->getChild(j); if (prefabChild->getLinkId() == instanceChild->getLinkId()) { if (instanceChild->mPrefabLinkUUID.empty()) childDiff = generateDiff(prefabChild, instanceChild); foundMatching = true; break; } } if (foundMatching) { if (childDiff != nullptr) { if (output == nullptr) output = bs_shared_ptr_new<PrefabObjectDiff>(); output->childDiffs.push_back(childDiff); } } else { if (output == nullptr) output = bs_shared_ptr_new<PrefabObjectDiff>(); output->removedChildren.push_back(prefabChild->getLinkId()); } } // Find added children for (UINT32 i = 0; i < instanceChildCount; i++) { HSceneObject instanceChild = instance->getChild(i); if (instanceChild->hasFlag(SOF_DontSave)) continue; bool foundMatching = false; if (instanceChild->getLinkId() != -1) { for (UINT32 j = 0; j < prefabChildCount; j++) { HSceneObject prefabChild = prefab->getChild(j); if (prefabChild->getLinkId() == instanceChild->getLinkId()) { foundMatching = true; break; } } } if (!foundMatching) { BinarySerializer bs; SPtr<SerializedObject> obj = bs._encodeToIntermediate(instanceChild.get()); if (output == nullptr) output = bs_shared_ptr_new<PrefabObjectDiff>(); output->addedChildren.push_back(obj); } } const Vector<HComponent>& prefabComponents = prefab->getComponents(); const Vector<HComponent>& instanceComponents = instance->getComponents(); UINT32 prefabComponentCount = (UINT32)prefabComponents.size(); UINT32 instanceComponentCount = (UINT32)instanceComponents.size(); // Find modified and removed components for (UINT32 i = 0; i < prefabComponentCount; i++) { HComponent prefabComponent = prefabComponents[i]; SPtr<PrefabComponentDiff> childDiff; bool foundMatching = false; for (UINT32 j = 0; j < instanceComponentCount; j++) { HComponent instanceComponent = instanceComponents[j]; if (prefabComponent->getLinkId() == instanceComponent->getLinkId()) { BinarySerializer bs; SPtr<SerializedObject> encodedPrefab = bs._encodeToIntermediate(prefabComponent.get()); SPtr<SerializedObject> encodedInstance = bs._encodeToIntermediate(instanceComponent.get()); IDiff& diffHandler = prefabComponent->getRTTI()->getDiffHandler(); SPtr<SerializedObject> diff = diffHandler.generateDiff(encodedPrefab, encodedInstance); if (diff != nullptr) { childDiff = bs_shared_ptr_new<PrefabComponentDiff>(); childDiff->id = prefabComponent->getLinkId(); childDiff->data = diff; } foundMatching = true; break; } } if (foundMatching) { if (childDiff != nullptr) { if (output == nullptr) output = bs_shared_ptr_new<PrefabObjectDiff>(); output->componentDiffs.push_back(childDiff); } } else { if (output == nullptr) output = bs_shared_ptr_new<PrefabObjectDiff>(); output->removedComponents.push_back(prefabComponent->getLinkId()); } } // Find added components for (UINT32 i = 0; i < instanceComponentCount; i++) { HComponent instanceComponent = instanceComponents[i]; bool foundMatching = false; if (instanceComponent->getLinkId() != -1) { for (UINT32 j = 0; j < prefabComponentCount; j++) { HComponent prefabComponent = prefabComponents[j]; if (prefabComponent->getLinkId() == instanceComponent->getLinkId()) { foundMatching = true; break; } } } if (!foundMatching) { BinarySerializer bs; SPtr<SerializedObject> obj = bs._encodeToIntermediate(instanceComponent.get()); if (output == nullptr) output = bs_shared_ptr_new<PrefabObjectDiff>(); output->addedComponents.push_back(obj); } } if (output != nullptr) output->id = instance->getLinkId(); return output; }