private static void Write(UnsafeWriter writer, ModificationHierarchyElement value) { value.Id.WriteTo(writer); value.CorrespondingSourceObject.WriteTo(writer); value.PrefabInstance.WriteTo(writer); writer.Write(value.IsStripped); value.TransformParentId.WriteTo(writer); WriteDictionary(writer, value.myRootIndexes, (w, v) => { if (w.WriteNullness(v)) { w.Write(v.Value); } }); WriteDictionary(writer, value.myNames, (w, v) => w.Write(v)); }
public void ConsumeGameObject(GameObjectHierarchyElement gameObject, TransformHierarchyElement transformHierarchyElement, ModificationHierarchyElement modifications) { string name = null; if (modifications != null) { name = modifications.GetName(new FileID(null, gameObject.Id.fileID)); } if (name == null) { name = gameObject.Name; } if (name?.Equals(string.Empty) == true) { name = null; } myParts.Push(name ?? "..."); int?rootOrder = null; if (modifications != null) { rootOrder = modifications.GetRootIndex(transformHierarchyElement.Id.WithGuid(null)); } if (rootOrder == null) { rootOrder = transformHierarchyElement.RootOrder; } myIndex.Push(rootOrder ?? 0); }
protected bool Equals(ModificationHierarchyElement other) { return(Id.Equals(other.Id)); }
// 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; } } }
public void AddPrefabModification(IBuffer buffer) { var anchor = UnitySceneDataUtil.GetAnchorFromBuffer(buffer); if (anchor == null) { return; } var lexer = new YamlLexer(buffer, false, false); lexer.Start(); TokenNodeType currentToken; var transformParentId = FileID.Null; while ((currentToken = lexer.TokenType) != null) { if (currentToken == YamlTokenType.INDENT) { var indentSize = lexer.TokenEnd - lexer.TokenStart; lexer.Advance(); currentToken = lexer.TokenType; if (currentToken == YamlTokenType.NS_PLAIN_ONE_LINE_IN) { var text = buffer.GetText(new TextRange(lexer.TokenStart, lexer.TokenEnd)); if (text.Equals(UnityYamlConstants.TransformParentProperty)) { lexer.Advance(); UnitySceneDataUtil.SkipWhitespace(lexer); currentToken = lexer.TokenType; if (currentToken == YamlTokenType.COLON) { lexer.Advance(); var result = UnitySceneDataUtil.GetFileId(buffer, lexer); if (result != null) { transformParentId = result; } } } else if (text.Equals(UnityYamlConstants.ModificationsProperty)) { var names = new Dictionary <FileID, string>(); var rootIndexes = new Dictionary <FileID, int?>(); GetModifications(buffer, lexer, indentSize, names, rootIndexes); var id = new FileID(null, anchor); Elements[id] = new ModificationHierarchyElement(id, null, null, false, transformParentId, rootIndexes, names); return; } } } else { lexer.Advance(); } } }