public void DeleteElement(VisualElement element) { if (BuilderSharedStyles.IsSelectorsContainerElement(element) || BuilderSharedStyles.IsDocumentElement(element) || !element.IsLinkedToAsset()) { return; } if (BuilderSharedStyles.IsSelectorElement(element)) { Undo.RegisterCompleteObjectUndo( m_PaneWindow.document.mainStyleSheet, BuilderConstants.DeleteSelectorUndoMessage); var selectorStr = BuilderSharedStyles.GetSelectorString(element); m_PaneWindow.document.mainStyleSheet.RemoveSelector(selectorStr); } else { BuilderAssetUtilities.DeleteElementFromAsset(m_PaneWindow.document, element); } element.RemoveFromHierarchy(); m_PaneWindow.document.hasUnsavedChanges = true; }
bool DeleteElementFromVisualTreeAsset(VisualElement element) { var vea = element.GetVisualElementAsset(); if (vea == null) { return(false); } BuilderAssetUtilities.DeleteElementFromAsset(m_PaneWindow.document, element); element.RemoveFromHierarchy(); m_Selection.NotifyOfHierarchyChange(); return(true); }
bool DeleteElementFromVisualTreeAsset(VisualElement element) { var vea = element.GetVisualElementAsset(); if (vea == null) { return(false); } #if UNITY_2019_4 // Before 2020.1, the only way to attach a StyleSheet to a UXML document was via a <Style> // tag as a child of an element tag. This meant that if there were no elements in the document, // there cannot be any StyleSheets attached to it. Therefore, we need to warn the user when // deleting the last element in the document that they will lose the list of attached StyleSheets // as well. This is something that can be undone via undo so it's not terrible if they say "Yes" // accidentally. // // 2020.1 adds support for the global <Style> tag so this limitation is lifted. However, the // UI Builder does not yet support the global <Style> tag. Plus, even when support to the // UI Builder is added, we still need to maintain support for 2019.3 via this logic. if (m_PaneWindow.document.firstStyleSheet != null && m_PaneWindow.document.visualTreeAsset.WillBeEmptyIfRemovingOne(vea)) { var continueDeletion = BuilderDialogsUtility.DisplayDialog( BuilderConstants.DeleteLastElementDialogTitle, BuilderConstants.DeleteLastElementDialogMessage, "Yes", "Cancel"); if (!continueDeletion) { return(false); } BuilderAssetUtilities.DeleteElementFromAsset(m_PaneWindow.document, element); m_PaneWindow.OnEnableAfterAllSerialization(); } else #endif { BuilderAssetUtilities.DeleteElementFromAsset(m_PaneWindow.document, element); element.RemoveFromHierarchy(); m_Selection.NotifyOfHierarchyChange(); } return(true); }
public void UnpackTemplateContainer(VisualElement templateContainer, bool unpackCompletely = false) { if (templateContainer == null) { Debug.LogError("Template to unpack is null"); return; } var elementsToUnpack = new List <VisualElement>(); var rootVEA = templateContainer.GetVisualElementAsset(); var isRootElement = true; VisualElementAsset rootUnpackedVEA = null; elementsToUnpack.Add(templateContainer); while (elementsToUnpack.Count > 0) { var elementToUnpack = elementsToUnpack[0]; var unpackedVE = new VisualElement(); var templateContainerParent = elementToUnpack.parent; var templateContainerIndex = templateContainerParent.IndexOf(elementToUnpack); // Create new unpacked element and add it in the hierarchy templateContainerParent.Add(unpackedVE); BuilderAssetUtilities.AddElementToAsset(m_PaneWindow.document, unpackedVE, templateContainerIndex + 1); var linkedInstancedVTA = elementToUnpack.GetProperty(BuilderConstants.ElementLinkedInstancedVisualTreeAssetVEPropertyName) as VisualTreeAsset; var linkedTA = elementToUnpack.GetVisualElementAsset() as TemplateAsset; var linkedVTACopy = linkedInstancedVTA.DeepCopy(); var unpackedVEA = unpackedVE.GetVisualElementAsset(); var templateContainerVEA = elementToUnpack.GetVisualElementAsset(); var attributeOverrides = linkedTA.attributeOverrides; var attributes = elementToUnpack.GetOverriddenAttributes(); foreach (var attribute in attributes) { unpackedVEA.SetAttributeValue(attribute.Key, attribute.Value); } if (isRootElement) { rootUnpackedVEA = unpackedVEA; } // Apply attribute overrides to elements in the unpacked element BuilderAssetUtilities.ApplyAttributeOverridesToTreeAsset(attributeOverrides, linkedVTACopy); // Move attribute overrides to new template containers BuilderAssetUtilities.CopyAttributeOverridesToChildTemplateAssets(attributeOverrides, linkedVTACopy); // Apply stylesheets to new element + inline rules BuilderAssetUtilities.AddStyleSheetsFromTreeAsset(unpackedVEA, linkedInstancedVTA); unpackedVEA.ruleIndex = templateContainerVEA.ruleIndex; BuilderAssetUtilities.TransferAssetToAsset(m_PaneWindow.document, unpackedVEA, linkedVTACopy, false); elementsToUnpack.Remove(elementToUnpack); if (elementToUnpack != templateContainer) { BuilderAssetUtilities.DeleteElementFromAsset(m_PaneWindow.document, elementToUnpack, false); elementToUnpack.RemoveFromHierarchy(); } if (unpackCompletely && elementsToUnpack.Count == 0) { VisualElement tree = new VisualElement(); m_PaneWindow.document.activeOpenUXMLFile.visualTreeAsset.LinkedCloneTree(tree); var newElement = tree.Query <VisualElement>().Where(x => x.GetVisualElementAsset() == rootUnpackedVEA).First(); var newTemplates = newElement.Query <TemplateContainer>().Where(x => x.GetVisualElementAsset() != null).ToList(); elementsToUnpack.AddRange(newTemplates); isRootElement = false; } } m_Selection.NotifyOfHierarchyChange(); m_PaneWindow.OnEnableAfterAllSerialization(); // Keep hierarchy tree state in the new unpacked element var hierarchy = Builder.ActiveWindow.hierarchy; hierarchy.elementHierarchyView.CopyTreeViewItemStates(rootVEA, rootUnpackedVEA); // Delete old template element BuilderAssetUtilities.DeleteElementFromAsset(m_PaneWindow.document, templateContainer, false); templateContainer.RemoveFromHierarchy(); m_Selection.ClearSelection(null); rootUnpackedVEA.Select(); m_Selection.NotifyOfHierarchyChange(); m_PaneWindow.OnEnableAfterAllSerialization(); }
public void CreateTemplateFromHierarchy(VisualElement ve, VisualTreeAsset vta, string path = "") { var veas = new List <VisualElementAsset>(); var vea = ve.GetVisualElementAsset(); veas.Add(vea); if (string.IsNullOrEmpty(path)) { path = BuilderDialogsUtility.DisplaySaveFileDialog("Save UXML", null, ve.name, "uxml"); if (string.IsNullOrEmpty(path)) { // Save dialog cancelled return; } } if (path == m_PaneWindow.document.activeOpenUXMLFile.uxmlPath) { // Path is the same as the active open uxml file. Abort! BuilderDialogsUtility.DisplayDialog( BuilderConstants.InvalidCreateTemplatePathTitle, BuilderConstants.InvalidCreateTemplatePathMessage, BuilderConstants.DialogOkOption); return; } var uxml = VisualTreeAssetToUXML.GenerateUXML(vta, null, veas); if (!m_PaneWindow.document.SaveNewTemplateFileFromHierarchy(path, uxml)) { // New template wasn't saved return; } var parent = ve.parent; var parentVEA = parent.GetVisualElementAsset(); var index = parent.IndexOf(ve); // Delete old element BuilderAssetUtilities.DeleteElementFromAsset(m_PaneWindow.document, ve); ve.RemoveFromHierarchy(); // Replace with new template var newTemplateVTA = EditorGUIUtility.Load(path) as VisualTreeAsset; var newTemplateContainer = newTemplateVTA.CloneTree(); newTemplateContainer.SetProperty(BuilderConstants.LibraryItemLinkedTemplateContainerPathVEPropertyName, path); newTemplateContainer.name = newTemplateVTA.name; parent.Insert(index, newTemplateContainer); BuilderAssetUtilities.AddElementToAsset(m_PaneWindow.document, newTemplateContainer, (inVta, inParent, ve) => { var vea = inVta.AddTemplateInstance(inParent, path) as VisualElementAsset; vea.AddProperty("name", newTemplateVTA.name); ve.SetProperty(BuilderConstants.ElementLinkedInstancedVisualTreeAssetVEPropertyName, newTemplateVTA); return(vea); }, index); m_Selection.Select(null, newTemplateContainer); // Refresh m_Selection.NotifyOfHierarchyChange(); m_PaneWindow.OnEnableAfterAllSerialization(); }