// Invariant : startGameObject is Transform Component if it is not stripped // This method traverse scene hierarchy via visiting transform components and push corresponding to transform GameObject into consumer private void ProcessSceneHierarchyFromComponentToRootInner(IYamlDocument startUnityObject, IUnitySceneProcessorConsumer consumer, IBlockMappingNode modifications) { var currentUnityObject = startUnityObject; while (currentUnityObject != null) { // Unity object could be stripped, it means, that corresponding real object belongs to another yaml file // Also, it has reference to prefab instance in current file, which stores all prefab modification if (IsStripped(currentUnityObject)) { var file = (IYamlFile)currentUnityObject.GetContainingFile(); var correspondingId = currentUnityObject.GetUnityObjectPropertyValue(GetCorrespondingSourceObjectProperty())?.AsFileID(); var prefabInstanceId = currentUnityObject.GetUnityObjectPropertyValue(GetPrefabInstanceProperty())?.AsFileID(); // assert not null if (correspondingId == null || prefabInstanceId == null) { return; } var prefabInstance = file.FindDocumentByAnchor(prefabInstanceId.fileID); var prefabSourceFile = myMetaFileGuidCache.GetAssetFilePathsFromGuid(correspondingId.guid); if (prefabSourceFile.Count > 1 || prefabSourceFile.Count == 0) { return; } myFactory.PsiModule.NotNull("externalFilesModuleFactory.PsiModule != null") .TryGetFileByPath(prefabSourceFile.First(), out var sourceFile); if (sourceFile == null) { return; } // [TODO] Is prefab file committed??? var prefabFile = (IYamlFile)sourceFile.GetDominantPsiFile <YamlLanguage>(); var prefabStartGameObject = prefabFile.FindDocumentByAnchor(correspondingId.fileID); if (!IsStripped(prefabStartGameObject)) { // !u!4 is transform. If tag is different, let's extract transform, there are two cases: // 1) prefabStartGameObject is GameObject(!u!1), take its transform // 2) prefabStartGameObject is Component, so get attached gameobject and from this gameobject take transform component if (!GetUnityObjectTag(prefabStartGameObject).Equals("!u!4")) { var attachedGameObject = prefabStartGameObject; if (!GetUnityObjectTag(prefabStartGameObject).Equals("!u!1")) { attachedGameObject = attachedGameObject.GetUnityObjectDocumentFromFileIDProperty(UnityYamlConstants .GameObjectProperty); } prefabStartGameObject = UnityObjectPsiUtil.FindTransformComponentForGameObject(attachedGameObject); } } var localModifications = UnityObjectPsiUtil.GetPrefabModification(prefabInstance); ProcessSceneHierarchyFromComponentToRootInner(prefabStartGameObject, consumer, localModifications); currentUnityObject = UnityObjectPsiUtil.GetTransformFromPrefabInstance(prefabInstance); } else { // assert that startGameObject is GameObject var father = currentUnityObject.GetUnityObjectDocumentFromFileIDProperty(UnityYamlConstants.FatherProperty); var gameObject = currentUnityObject.GetUnityObjectDocumentFromFileIDProperty(UnityYamlConstants.GameObjectProperty); consumer.ConsumeGameObject(gameObject, modifications); currentUnityObject = father; } } }
public void ProcessSceneHierarchyFromComponentToRoot(IYamlDocument startComponent, IUnitySceneProcessorConsumer consumer) { if (startComponent == null) { return; } var start = startComponent; if (!IsStripped(startComponent)) // start component can be stripped, e.g : prefab's MonoBehavior's function is passed to button event handler { // Component must be attached to game object start = start.GetUnityObjectDocumentFromFileIDProperty(UnityYamlConstants.GameObjectProperty); // GameObject could be stripped, if another prefab's gameobject is modified via adding MonoBehaviour if (!IsStripped(start)) { // Each GameObject must have Transform. We will use it to process scene hierarcy start = UnityObjectPsiUtil.FindTransformComponentForGameObject(start); } } ProcessSceneHierarchyFromComponentToRootInner(start, consumer, null); }