Exemple #1
0
        public IPsiSourceFile GetSourceFile(IHierarchyReference hierarchyReference, out Guid?guid)
        {
            guid = null;
            if (hierarchyReference == null)
            {
                return(null);
            }

            myShellLocks.AssertReadAccessAllowed();
            switch (hierarchyReference)
            {
            case LocalReference localReference:
                var sourceFile = myManager[localReference.OwningPsiPersistentIndex];
                guid = sourceFile != null?myMetaFileGuidCache.GetAssetGuid(sourceFile) : null;

                return(sourceFile);

            case ExternalReference externalReference:
                guid = externalReference.ExternalAssetGuid;
                var paths = myMetaFileGuidCache.GetAssetFilePathsFromGuid(guid.Value);
                if (paths.Count != 1)
                {
                    return(null);
                }

                return(myPsiModule.TryGetFileByPath(paths[0], out var result) ? result : null);

            default:
                throw new InvalidOperationException();
            }
        }
Exemple #2
0
        // 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;
                }
            }
        }
        private IDictionary <long, IHierarchyElement> DoImport(Guid ownerGuid, AssetDocumentHierarchyElement assetDocumentHierarchyElement, HashSet <Guid> visitedGuid)
        {
            var result = new Dictionary <long, IHierarchyElement>();

            foreach (var prefabInstanceHierarchy in assetDocumentHierarchyElement.GetPrefabInstanceHierarchies())
            {
                var guid           = prefabInstanceHierarchy.SourcePrefabGuid;
                var sourceFilePath = myMetaFileGuidCache.GetAssetFilePathsFromGuid(guid).FirstOrDefault();
                if (sourceFilePath == null)
                {
                    continue;
                }
                if (!myUnityExternalFilesPsiModule.TryGetFileByPath(sourceFilePath, out var sourceFile))
                {
                    continue;
                }

                var prefabHierarchy = assetDocumentHierarchyElement.AssetDocumentHierarchyElementContainer.GetAssetHierarchyFor(sourceFile);
                if (prefabHierarchy == null)
                {
                    continue;
                }

                if (!myCache.TryGetFromCache(guid, out var importedElements))
                {
                    if (!visitedGuid.Contains(guid)) // invalid assets with cycles in prefab imports
                    {
                        myDependencies.Add(guid, ownerGuid);
                        visitedGuid.Add(guid);
                        importedElements = DoImport(guid, prefabHierarchy, visitedGuid);
                        StoreResult(guid, importedElements);
                    }
                    else
                    {
                        importedElements = EmptyDictionary <long, IHierarchyElement> .Instance;
                    }
                }

                foreach (var element in prefabHierarchy.Elements())
                {
                    if (element is IStrippedHierarchyElement)
                    {
                        continue;
                    }

                    if (element is IPrefabInstanceHierarchy)
                    {
                        continue;
                    }

                    var imported = element.Import(prefabInstanceHierarchy);
                    if (imported == null)
                    {
                        continue;
                    }
                    result[imported.Location.LocalDocumentAnchor] = imported;
                }

                foreach (var element in importedElements.Values)
                {
                    Assertion.Assert(!(element is IStrippedHierarchyElement), "element should be imported");
                    Assertion.Assert(!(element is IPrefabInstanceHierarchy), "prefab should be imported");

                    var imported = element.Import(prefabInstanceHierarchy);
                    if (imported == null)
                    {
                        continue;
                    }

                    result[imported.Location.LocalDocumentAnchor] = imported;
                }
            }

            foreach (var value in result.Values)
            {
                var transform = value as ImportedTransformHierarchy;
                var reference = transform?.OwningGameObject;
                if (reference == null)
                {
                    continue;
                }

                var importedGameObject = result.GetValueSafe(reference.Value.LocalDocumentAnchor) as ImportedGameObjectHierarchy;
                if (importedGameObject == null)
                {
                    continue;
                }

                importedGameObject.TransformHierarchy = transform;
            }

            return(result);
        }