internal static string GenerateUSS(this StyleSheet styleSheet)
        {
            string result = null;

            try
            {
                result = StyleSheetToUss.ToUssString(styleSheet);
            }
            catch (Exception ex)
            {
                if (!styleSheet.name.Contains(BuilderConstants.InvalidUXMLOrUSSAssetNameSuffix))
                {
                    var message = string.Format(BuilderConstants.InvalidUSSDialogMessage, styleSheet.name);
                    BuilderDialogsUtility.DisplayDialog(BuilderConstants.InvalidUSSDialogTitle, message);
                    styleSheet.name = styleSheet.name + BuilderConstants.InvalidUXMLOrUSSAssetNameSuffix;
                }
                else
                {
                    var name    = styleSheet.name.Replace(BuilderConstants.InvalidUXMLOrUSSAssetNameSuffix, string.Empty);
                    var message = string.Format(BuilderConstants.InvalidUSSDialogMessage, name);
                    Builder.ShowWarning(message);
                }
                Debug.LogError(ex.Message + "\n" + ex.StackTrace);
            }
            return(result);
        }
Esempio n. 2
0
        internal static string GenerateUXML(this VisualTreeAsset vta, string vtaPath, bool writingToFile = false)
        {
            string result = null;

            try
            {
                result = VisualTreeAssetToUXML.GenerateUXML(vta, vtaPath, writingToFile);
            }
            catch (Exception ex)
            {
                if (!vta.name.Contains(BuilderConstants.InvalidUXMLOrUSSAssetNameSuffix))
                {
                    var message = string.Format(BuilderConstants.InvalidUXMLDialogMessage, vta.name);
                    BuilderDialogsUtility.DisplayDialog(BuilderConstants.InvalidUXMLDialogTitle, message);
                    vta.name = vta.name + BuilderConstants.InvalidUXMLOrUSSAssetNameSuffix;
                }
                else
                {
                    var name    = vta.name.Replace(BuilderConstants.InvalidUXMLOrUSSAssetNameSuffix, string.Empty);
                    var message = string.Format(BuilderConstants.InvalidUXMLDialogMessage, name);
                    Builder.ShowWarning(message);
                }
                Debug.LogError(ex.Message + "\n" + ex.StackTrace);
            }
            return(result);
        }
        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();
            }
        }
Esempio n. 4
0
        internal bool SaveNewTemplateFileFromHierarchy(string newTemplatePath, string uxml)
        {
            var  isReplacingFile            = File.Exists(newTemplatePath);
            bool isReplacingFileInHierarchy = false;

            if (isReplacingFile)
            {
                var replacedVTA = EditorGUIUtility.Load(newTemplatePath) as VisualTreeAsset;
                isReplacingFileInHierarchy = replacedVTA.TemplateExists(m_VisualTreeAsset);

                if (isReplacingFileInHierarchy && hasUnsavedChanges)
                {
                    // If we are replacing an element in the hierarchy and there is unsaved changes,
                    // we need to save to make sure we don't lose any elements
                    var saveUnsavedChanges = BuilderDialogsUtility.DisplayDialog(
                        BuilderConstants.SaveDialogSaveChangesPromptTitle,
                        BuilderConstants.SaveDialogReplaceWithNewTemplateMessage,
                        BuilderConstants.DialogSaveActionOption,
                        BuilderConstants.DialogCancelOption);

                    if (saveUnsavedChanges)
                    {
                        var wasDocumentSaved = SaveUnsavedChanges();

                        if (!wasDocumentSaved)
                        {
                            // Save failed
                            Debug.LogError("Saving the current template failed. New template will not be created.");
                            return(false);
                        }
                    }
                    else
                    {
                        // Save cancelled
                        return(false);
                    }
                }
            }

            if (isReplacingFileInHierarchy)
            {
                // This is necessary to make sure we don't show the external changes popup
                // since we are creating a new template
                m_DocumentBeingSavedExplicitly = true;
            }

            File.WriteAllText(newTemplatePath, uxml);
            AssetDatabase.Refresh();

            if (isReplacingFileInHierarchy)
            {
                m_DocumentBeingSavedExplicitly = false;
            }

            return(true);
        }
        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);
        }
        static public bool WriteTextFileToDisk(string path, string content)
        {
            bool success = FileUtil.WriteTextFileToDisk(path, content, out string message);

            if (!success)
            {
                Debug.LogError(message);
                BuilderDialogsUtility.DisplayDialog("Save - " + path, message, "Ok");
            }

            return(success);
        }
Esempio n. 7
0
        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();
            }
        }
Esempio n. 8
0
        public bool CheckForUnsavedChanges(bool assetModifiedExternally = false)
        {
            if (!hasUnsavedChanges)
            {
                return(true);
            }

            if (assetModifiedExternally)
            {
                // TODO: Nothing can be done here yet, other than telling the user
                // what just happened. Adding the ability to save unsaved changes
                // after a file has been modified externally will require some
                // major changes to the document flow.
                var promptTitle = string.Format(BuilderConstants.SaveDialogExternalChangesPromptTitle,
                                                m_Document.uxmlPath);
                BuilderDialogsUtility.DisplayDialog(
                    promptTitle,
                    BuilderConstants.SaveDialogExternalChangesPromptMessage);

                return(true);
            }
            else
            {
                var option = BuilderDialogsUtility.DisplayDialogComplex(
                    BuilderConstants.SaveDialogSaveChangesPromptTitle,
                    BuilderConstants.SaveDialogSaveChangesPromptMessage,
                    BuilderConstants.DialogSaveActionOption,
                    BuilderConstants.DialogCancelOption,
                    BuilderConstants.DialogDontSaveActionOption);

                switch (option)
                {
                // Save
                case 0:
                    return(SaveUnsavedChanges());

                // Cancel
                case 1:
                    return(false);

                // Don't Save
                case 2:
                    RestoreAssetsFromBackup();
                    return(true);
                }
            }

            return(true);
        }
        public static bool ValidateAsset(VisualTreeAsset asset, string path)
        {
            string errorMessage = null;

            string errorTitle = null;

            if (asset == null)
            {
                if (string.IsNullOrEmpty(path))
                {
                    path = "<unspecified>";
                }

                if (path.StartsWith("Packages/"))
                {
                    errorMessage = $"The asset at path {path} is not a UXML Document.\nNote, for assets inside Packages folder, the folder name for the package needs to match the actual official package name (ie. com.example instead of Example).";
                }
                else
                {
                    errorMessage = $"The asset at path {path} is not a UXML Document.";
                }
                errorTitle = "Invalid Asset Type";
            }
            else if (asset.importedWithErrors)
            {
                if (string.IsNullOrEmpty(path))
                {
                    path = AssetDatabase.GetAssetPath(asset);
                }

                if (string.IsNullOrEmpty(path))
                {
                    path = "<unspecified>";
                }

                errorMessage = string.Format(BuilderConstants.InvalidUXMLDialogMessage, path);
                errorTitle   = BuilderConstants.InvalidUXMLDialogTitle;
            }

            if (errorMessage != null)
            {
                BuilderDialogsUtility.DisplayDialog(errorTitle, errorMessage, "Ok");
                Debug.LogError(errorMessage);
                return(false);
            }

            return(true);
        }
        public static void AddStyleSheetToAsset(
            BuilderDocument document, string ussPath)
        {
            var styleSheet = AssetDatabase.LoadAssetAtPath <StyleSheet>(ussPath);

            if (styleSheet == null)
            {
                BuilderDialogsUtility.DisplayDialog("Invalid Asset Type", @"Asset at path {ussPath} is not a StyleSheet.");
                return;
            }

            Undo.RegisterCompleteObjectUndo(
                document.visualTreeAsset, "Add StyleSheet to UXML");

            document.AddStyleSheetToDocument(styleSheet, ussPath);
        }
Esempio n. 11
0
        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);
        }
Esempio n. 12
0
        bool IsFileActionCompatible(string assetPath, string actionName)
        {
            if (assetPath.Equals(document.uxmlPath) || document.ussPaths.Contains(assetPath))
            {
                var fileName     = Path.GetFileName(assetPath);
                var acceptAction = BuilderDialogsUtility.DisplayDialog(BuilderConstants.ErrorDialogNotice,
                                                                       string.Format(BuilderConstants.ErrorIncompatibleFileActionMessage, actionName, fileName),
                                                                       BuilderConstants.DialogDiscardOption,
                                                                       string.Format(BuilderConstants.DialogAbortActionOption, actionName.ToPascalCase()));

                if (acceptAction)
                {
                    NewDocument(false);
                }

                return(acceptAction);
            }

            return(true);
        }
Esempio n. 13
0
        bool IsFileActionCompatible(string assetPath, string actionName)
        {
            if (IsAssetUsedInDocument(document, assetPath))
            {
                var fileName     = Path.GetFileName(assetPath);
                var acceptAction = BuilderDialogsUtility.DisplayDialog(BuilderConstants.ErrorDialogNotice,
                                                                       string.Format(BuilderConstants.ErrorIncompatibleFileActionMessage, actionName, fileName),
                                                                       string.Format(BuilderConstants.DialogDiscardOption, actionName.ToPascalCase()),
                                                                       string.Format(BuilderConstants.DialogAbortActionOption, actionName.ToPascalCase()));

                if (acceptAction)
                {
                    // Open a new, empty document
                    NewDocument(false);
                }

                return(acceptAction);
            }

            return(true);
        }
        public static bool AddStyleSheetToAsset(
            BuilderDocument document, string ussPath)
        {
            var styleSheet = BuilderPackageUtilities.LoadAssetAtPath <StyleSheet>(ussPath);

            string errorMessage = null;
            string errorTitle   = null;

            if (styleSheet == null)
            {
                if (ussPath.StartsWith("Packages/"))
                {
                    errorMessage = $"Asset at path {ussPath} is not a StyleSheet.\nNote, for assets inside Packages folder, the folder name for the package needs to match the actual official package name (ie. com.example instead of Example).";
                }
                else
                {
                    errorMessage = $"Asset at path {ussPath} is not a StyleSheet.";
                }
                errorTitle = "Invalid Asset Type";
            }
            else if (styleSheet.importedWithErrors)
            {
                errorMessage = string.Format(BuilderConstants.InvalidUSSDialogMessage, ussPath);
                errorTitle   = BuilderConstants.InvalidUSSDialogTitle;
            }

            if (errorMessage != null)
            {
                BuilderDialogsUtility.DisplayDialog(errorTitle, errorMessage, "Ok");
                Debug.LogError(errorMessage);
                return(false);
            }

            Undo.RegisterCompleteObjectUndo(
                document.visualTreeAsset, "Add StyleSheet to UXML");

            document.AddStyleSheetToDocument(styleSheet, ussPath);
            return(true);
        }
Esempio n. 15
0
        private void OnEditButton()
        {
            if (BuilderExternalPackages.is2DSpriteEditorInstalled)
            {
                // Open 2D Sprite Editor with current image loaded
                BuilderExternalPackages.Open2DSpriteEditor((Object)value);
                return;
            }

            // Handle the missing 2D Sprite Editor package case.
            if (BuilderDialogsUtility.DisplayDialog(
                    k_No2DSpriteEditorPackageInstalledTitle,
                    k_No2DSpriteEditorPackageInstalledMessage,
                    "Install",
                    "Cancel"))
            {
                if (!Install2DSpriteEditorPackage())
                {
                    Application.OpenURL(k_2DSpriteEditorInstallationURL);
                }
            }
        }
Esempio n. 16
0
        public static void AddStyleSheetToAsset(
            BuilderDocument document, string ussPath)
        {
            var styleSheet = BuilderPackageUtilities.LoadAssetAtPath <StyleSheet>(ussPath);

            if (styleSheet == null)
            {
                if (ussPath.StartsWith("Packages/"))
                {
                    BuilderDialogsUtility.DisplayDialog("Invalid Asset Type", $"Asset at path {ussPath} is not a StyleSheet.\nNote, for assets inside Packages folder, the folder name for the package needs to match the actual official package name (ie. com.example instead of Example).");
                }
                else
                {
                    BuilderDialogsUtility.DisplayDialog("Invalid Asset Type", $"Asset at path {ussPath} is not a StyleSheet.");
                }
                return;
            }

            Undo.RegisterCompleteObjectUndo(
                document.visualTreeAsset, "Add StyleSheet to UXML");

            document.AddStyleSheetToDocument(styleSheet, ussPath);
        }
Esempio n. 17
0
        public bool CheckForUnsavedChanges(bool assetModifiedExternally = false)
        {
            if (!hasUnsavedChanges)
            {
                return(true);
            }

            int option = -1;

            if (assetModifiedExternally)
            {
                // TODO: Nothing can be done here yet, other than telling the user
                // what just happened. Adding the ability to save unsaved changes
                // after a file has been modified externally will require some
                // major changes to the document flow.
                BuilderDialogsUtility.DisplayDialog(
                    BuilderConstants.SaveDialogExternalChangesPromptTitle,
                    BuilderConstants.SaveDialogExternalChangesPromptMessage);

                return(true);
            }
            else
            {
                option = BuilderDialogsUtility.DisplayDialogComplex(
                    BuilderConstants.SaveDialogSaveChangesPromptTitle,
                    BuilderConstants.SaveDialogSaveChangesPromptMessage,
                    BuilderConstants.DialogSaveActionOption,
                    BuilderConstants.DialogCancelOption,
                    BuilderConstants.DialogDontSaveActionOption);

                switch (option)
                {
                // Save
                case 0:
                    if (!string.IsNullOrEmpty(uxmlPath) && !string.IsNullOrEmpty(ussPath))
                    {
                        SaveNewDocument(uxmlPath, ussPath, null, false);
                        return(true);
                    }
                    else
                    {
                        var builderWindow = Builder.ActiveWindow;
                        if (builderWindow == null)
                        {
                            builderWindow = Builder.ShowWindow();
                        }

                        builderWindow.toolbar.PromptSaveDocumentDialog();
                        return(false);
                    }

                // Cancel
                case 1:
                    return(false);

                // Don't Save
                case 2:
                    RestoreAssetsFromBackup();
                    return(true);
                }
            }

            return(true);
        }
Esempio n. 18
0
        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();
        }