protected override void PerformAction(VisualElement destination, int index = -1) { m_DragPreviewElement.RemoveFromClassList(s_DragPreviewElementClassName); destination.RemoveMinSizeSpecialElement(); // We already have the correct index from the preview element that is // already inserted in the hierarchy. The index we get from the arguments // is actually incorrect (off by one) because it will count the // preview element. index = m_DragPreviewLastParent.IndexOf(m_DragPreviewElement); // We should have an item reference here if the OnDragStart() worked. var item = m_LibraryItem; if (item.makeElementAsset == null) { BuilderAssetUtilities.AddElementToAsset( paneWindow.document, m_DragPreviewElement, index); } else { BuilderAssetUtilities.AddElementToAsset( paneWindow.document, m_DragPreviewElement, item.makeElementAsset, index); } selection.NotifyOfHierarchyChange(null); selection.NotifyOfStylingChange(null); selection.Select(null, m_DragPreviewElement); // Commit to the preview element as the final element. // This will stop the ResetDragPreviewElement() from calling // RemoveFromHierarchy() on it. m_DragPreviewElement = null; }
protected override void PerformAction(VisualElement destination, DestinationPane pane, Vector2 localMousePosition, int index = -1) { // We should have an item reference here if the OnDragStart() worked. var item = m_LibraryItem; var itemVTA = item.sourceAsset; if (!paneWindow.document.WillCauseCircularDependency(itemVTA)) { BuilderDialogsUtility.DisplayDialog(BuilderConstants.InvalidWouldCauseCircularDependencyMessage, BuilderConstants.InvalidWouldCauseCircularDependencyMessageDescription, null); return; } destination.RemoveMinSizeSpecialElement(); // Determine if it applies and use Absolute Island insertion. if (BuilderProjectSettings.enableAbsolutePositionPlacement && pane == DestinationPane.Viewport && m_DragPreviewLastParent == documentRootElement && index < 0) { m_DragPreviewLastParent = BuilderPlacementUtilities.CreateAbsoluteIsland(paneWindow, documentRootElement, localMousePosition); } // Add VisualElement to Canvas. m_DragPreviewElement.RemoveFromClassList(s_DragPreviewElementClassName); if (index < 0) { m_DragPreviewLastParent.Add(m_DragPreviewElement); } else { m_DragPreviewLastParent.Insert(index, m_DragPreviewElement); } // Create equivalent VisualElementAsset. if (item.makeElementAssetCallback == null) { BuilderAssetUtilities.AddElementToAsset( paneWindow.document, m_DragPreviewElement, index); } else { BuilderAssetUtilities.AddElementToAsset( paneWindow.document, m_DragPreviewElement, item.makeElementAssetCallback, index); } selection.NotifyOfHierarchyChange(null); selection.NotifyOfStylingChange(null); selection.Select(null, m_DragPreviewElement); // Commit to the preview element as the final element. // This will stop the ResetDragPreviewElement() from calling // RemoveFromHierarchy() on it. m_DragPreviewElement = null; // If we dragged into the Viewport, focus the Viewport. if (pane == DestinationPane.Viewport) { viewport.pane.Focus(); } }
protected void AddItemToTheDocument(BuilderLibraryTreeItem item) { // If this is the uxml file entry of the currently open file, don't allow // the user to instantiate it (infinite recursion) or re-open it. var listOfOpenDocuments = m_PaneWindow.document.openUXMLFiles; bool isCurrentDocumentOpen = listOfOpenDocuments.Any(doc => doc.uxmlFileName == item.name); if (isCurrentDocumentOpen) { return; } if (m_PaneWindow.document.WillCauseCircularDependency(item.sourceAsset)) { BuilderDialogsUtility.DisplayDialog(BuilderConstants.InvalidWouldCauseCircularDependencyMessage, BuilderConstants.InvalidWouldCauseCircularDependencyMessageDescription, null); return; } var newElement = item.makeVisualElementCallback?.Invoke(); if (newElement == null) { return; } if (item.makeElementAssetCallback != null && newElement is TemplateContainer tempContainer) { if (!BuilderAssetUtilities.ValidateAsset(item.sourceAsset, item.sourceAssetPath)) { return; } } var activeVTARootElement = m_DocumentRootElement.Query().Where(e => e.GetVisualTreeAsset() == m_PaneWindow.document.visualTreeAsset).First(); if (activeVTARootElement == null) { Debug.LogError("UI Builder has a bug. Could not find document root element for currently active open UXML document."); return; } activeVTARootElement.Add(newElement); if (item.makeElementAssetCallback == null) { BuilderAssetUtilities.AddElementToAsset(m_PaneWindow.document, newElement); } else { BuilderAssetUtilities.AddElementToAsset( m_PaneWindow.document, newElement, item.makeElementAssetCallback); } m_Selection.NotifyOfHierarchyChange(); m_Selection.Select(null, newElement); }
void OnItemChosen(ITreeViewItem selectedItem) #endif { #if UNITY_2020_1_OR_NEWER if (selectedItems == null || selectedItems.Count() == 0) { return; } var selectedItem = selectedItems.First(); #else if (selectedItem == null) { return; } #endif var item = selectedItem as LibraryTreeItem; if (item.makeVisualElement == null) { return; } // If this is the uxml file entry of the currently open file, don't allow // the user to instantiate it (infinite recursion) or re-open it. if (item.name == m_PaneWindow.document.uxmlFileName) { return; } var newElement = item.makeVisualElement(); if (newElement == null) { return; } m_DocumentElement.Add(newElement); if (item.makeElementAsset == null) { BuilderAssetUtilities.AddElementToAsset(m_PaneWindow.document, newElement); } else { BuilderAssetUtilities.AddElementToAsset( m_PaneWindow.document, newElement, item.makeElementAsset); } // TODO: ListView bug. Does not refresh selection pseudo states after a // call to Refresh(). m_Selection.NotifyOfHierarchyChange(null); this.schedule.Execute(() => { m_Selection.Select(null, newElement); }).ExecuteLater(200); }
public static VisualElement CreateAbsoluteIsland(BuilderPaneWindow paneWindow, VisualElement documentRootElement, Vector2 localMousePosition) { var vta = paneWindow.document.visualTreeAsset; var selection = paneWindow.primarySelection; // Create absolute island container. var absoluteIslandContainer = new VisualElement(); absoluteIslandContainer.name = "unity-absolute-island"; documentRootElement.Add(absoluteIslandContainer); BuilderAssetUtilities.AddElementToAsset(paneWindow.document, absoluteIslandContainer); bool isTop = localMousePosition.y < documentRootElement.resolvedStyle.height / 2; bool isBottom = !isTop; bool isLeft = localMousePosition.x < documentRootElement.resolvedStyle.width / 2; bool isRight = !isLeft; // Set Absolute position. BuilderStyleUtilities.SetInlineStyleValue(vta, absoluteIslandContainer, "position", Position.Absolute); if (isTop && isLeft) { var left = localMousePosition.x; var top = localMousePosition.y; BuilderStyleUtilities.SetInlineStyleValue(vta, absoluteIslandContainer, "left", left); BuilderStyleUtilities.SetInlineStyleValue(vta, absoluteIslandContainer, "top", top); } else if (isTop && isRight) { var right = documentRootElement.resolvedStyle.width - localMousePosition.x; var top = localMousePosition.y; BuilderStyleUtilities.SetInlineStyleValue(vta, absoluteIslandContainer, "right", right); BuilderStyleUtilities.SetInlineStyleValue(vta, absoluteIslandContainer, "top", top); } else if (isBottom && isLeft) { var left = localMousePosition.x; var bottom = documentRootElement.resolvedStyle.height - localMousePosition.y; BuilderStyleUtilities.SetInlineStyleValue(vta, absoluteIslandContainer, "left", left); BuilderStyleUtilities.SetInlineStyleValue(vta, absoluteIslandContainer, "bottom", bottom); } else if (isBottom && isRight) { var right = documentRootElement.resolvedStyle.width - localMousePosition.x; var bottom = documentRootElement.resolvedStyle.height - localMousePosition.y; BuilderStyleUtilities.SetInlineStyleValue(vta, absoluteIslandContainer, "right", right); BuilderStyleUtilities.SetInlineStyleValue(vta, absoluteIslandContainer, "bottom", bottom); } // Need to explicitly update inline styles from asset. selection.NotifyOfHierarchyChange(null, absoluteIslandContainer, BuilderHierarchyChangeType.InlineStyle | BuilderHierarchyChangeType.FullRefresh); return(absoluteIslandContainer); }
protected override void PerformAction(VisualElement destination, DestinationPane pane, int index = -1) { m_DragPreviewElement.RemoveFromClassList(s_DragPreviewElementClassName); destination.RemoveMinSizeSpecialElement(); // We already have the correct index from the preview element that is // already inserted in the hierarchy. The index we get from the arguments // is actually incorrect (off by one) because it will count the // preview element. index = m_DragPreviewLastParent.IndexOf(m_DragPreviewElement); // We should have an item reference here if the OnDragStart() worked. var item = m_LibraryItem; var itemVTA = item.SourceAsset; if (!paneWindow.document.WillCauseCircularDependency(itemVTA)) { BuilderDialogsUtility.DisplayDialog(BuilderConstants.InvalidWouldCauseCircularDependencyMessage, BuilderConstants.InvalidWouldCauseCircularDependencyMessageDescription, null); return; } if (item.MakeElementAssetCallback == null) { BuilderAssetUtilities.AddElementToAsset( paneWindow.document, m_DragPreviewElement, index); } else { BuilderAssetUtilities.AddElementToAsset( paneWindow.document, m_DragPreviewElement, item.MakeElementAssetCallback, index); } selection.NotifyOfHierarchyChange(null); selection.NotifyOfStylingChange(null); selection.Select(null, m_DragPreviewElement); // Commit to the preview element as the final element. // This will stop the ResetDragPreviewElement() from calling // RemoveFromHierarchy() on it. m_DragPreviewElement = null; // If we dragged into the Viewport, focus the Viewport. if (pane == DestinationPane.Viewport) { Viewport.pane.Focus(); } }
protected void AddItemToTheDocument(BuilderLibraryTreeItem item) { // If this is the uxml file entry of the currently open file, don't allow // the user to instantiate it (infinite recursion) or re-open it. var listOfOpenDocuments = m_PaneWindow.document.openUXMLFiles; bool isCurrentDocumentOpen = listOfOpenDocuments.Any(doc => doc.uxmlFileName == item.name); if (isCurrentDocumentOpen) { return; } var newElement = item.makeVisualElementCallback?.Invoke(); if (newElement == null) { return; } var activeVTARootElement = m_DocumentRootElement.Query().Where(e => e.GetVisualTreeAsset() == m_PaneWindow.document.visualTreeAsset).First(); if (activeVTARootElement == null) { Debug.LogError("UI Builder has a bug. Could not find document root element for currently active open UXML document."); return; } activeVTARootElement.Add(newElement); if (item.makeElementAssetCallback == null) { BuilderAssetUtilities.AddElementToAsset(m_PaneWindow.document, newElement); } else { BuilderAssetUtilities.AddElementToAsset( m_PaneWindow.document, newElement, item.makeElementAssetCallback); } // TODO: ListView bug. Does not refresh selection pseudo states after a // call to Refresh(). m_Selection.NotifyOfHierarchyChange(); schedule.Execute(() => { m_Selection.Select(null, newElement); }).ExecuteLater(200); }
protected void AddItemToTheDocument(BuilderLibraryTreeItem item) { // If this is the uxml file entry of the currently open file, don't allow // the user to instantiate it (infinite recursion) or re-open it. var listOfOpenDocuments = m_PaneWindow.document.openUXMLFiles; bool isCurrentDocumentOpen = listOfOpenDocuments.Any(doc => doc.uxmlFileName == item.Name); if (isCurrentDocumentOpen) { return; } var newElement = item.MakeVisualElementCallback?.Invoke(); if (newElement == null) { return; } m_DocumentElement.Add(newElement); if (item.MakeElementAssetCallback == null) { BuilderAssetUtilities.AddElementToAsset(m_PaneWindow.document, newElement); } else { BuilderAssetUtilities.AddElementToAsset( m_PaneWindow.document, newElement, item.MakeElementAssetCallback); } // TODO: ListView bug. Does not refresh selection pseudo states after a // call to Refresh(). m_Selection.NotifyOfHierarchyChange(); schedule.Execute(() => { m_Selection.Select(null, newElement); }).ExecuteLater(200); }
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(); }