public bool Equals(SceneElementId other) { return(SourceFile.Equals(other.SourceFile) && FileID.Equals(other.FileID)); }
// 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(IPsiSourceFile currentFile, IUnityHierarchyElement startUnityObject, IUnityCachedSceneProcessorConsumer consumer, ModificationHierarchyElement 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 (currentUnityObject.IsStripped) { var correspondingId = currentUnityObject.CorrespondingSourceObject; var prefabInstanceId = currentUnityObject.PrefabInstance; if (correspondingId == null || prefabInstanceId == null) { return; } var prefabInstance = mySceneElements.GetValues(new SceneElementId(currentFile, prefabInstanceId)).FirstOrDefault() as ModificationHierarchyElement; var prefabSourceFilePaths = myGuidCache.GetAssetFilePathsFromGuid(correspondingId.guid); if (prefabSourceFilePaths.Count > 1 || prefabSourceFilePaths.Count == 0) { return; } var unityModule = currentFile.PsiModule as UnityExternalFilesPsiModule; if (unityModule == null) { return; } if (!unityModule.NotNull("externalFilesModuleFactory.PsiModule != null") .TryGetFileByPath(prefabSourceFilePaths.First(), out var prefabSourceFile)) { return; } var prefabStartGameObject = mySceneElements.GetValues(new SceneElementId(prefabSourceFile, correspondingId.WithGuid(null))).FirstOrDefault(); if (prefabStartGameObject == null) { return; // TODO [vkrasnotsvetov] 19.3 Handle case, when prefab contains prefab which contains prefab } if (!prefabStartGameObject.IsStripped) { // !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 (!(prefabStartGameObject is TransformHierarchyElement)) { var attachedGameObject = prefabStartGameObject; if (attachedGameObject is ComponentHierarchyElement componentHierarchyElement) { var sceneId = new SceneElementId(prefabSourceFile, componentHierarchyElement.GameObject); attachedGameObject = mySceneElements.GetValues(sceneId).FirstOrDefault(); } if (attachedGameObject is GameObjectHierarchyElement gameObjectHierarchyElement) { var sceneId = new SceneElementId(prefabSourceFile, gameObjectHierarchyElement.TransformId); prefabStartGameObject = mySceneElements.GetValues(sceneId).FirstOrDefault(); } else { prefabStartGameObject = null; } } } ProcessSceneHierarchyFromComponentToRootInner(prefabSourceFile, prefabStartGameObject, consumer, prefabInstance); currentUnityObject = prefabInstance != null ? mySceneElements.GetValues(new SceneElementId(currentFile, prefabInstance.TransformParentId)).FirstOrDefault() : null; } else { // assert that startGameObject is GameObject var transformComponent = currentUnityObject as TransformHierarchyElement; if (transformComponent == null) { return; // strange, log here } Assertion.Assert(currentUnityObject is TransformHierarchyElement, "currentUnityObject is TransformHierarchyElement"); var fatherTransformId = new SceneElementId(currentFile, transformComponent.Father); var father = mySceneElements.GetValues(fatherTransformId).FirstOrDefault(); var goId = new SceneElementId(currentFile, transformComponent.GameObject); var gameObject = mySceneElements.GetValues(goId).FirstOrDefault() as GameObjectHierarchyElement; if (gameObject == null) { return; // strange, log here } consumer.ConsumeGameObject(gameObject, transformComponent, modifications); currentUnityObject = father; } } }