// For tests only.

        static string DisplaySaveFileDialogForUSS()
        {
            var path = BuilderDialogsUtility.DisplaySaveFileDialog(
                "Save USS File", null, null, "uss");

            return(path);
        }
Example #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);
        }
        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);
        }
        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);
        }
Example #6
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);
        }
        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);
        }
Example #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);
        }
Example #9
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();
            }
        }
        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);
        }
Example #12
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);
        }
        public bool CheckForUnsavedChanges()
        {
            if (!hasUnsavedChanges)
            {
                return(true);
            }

            var 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:
                return(true);
            }

            return(true);
        }
Example #14
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);
        }
Example #15
0
        StyleSheet GetOrCreateOrAddMainStyleSheet()
        {
            // Get StyleSheet.
            var mainStyleSheet = m_PaneWindow.document.activeStyleSheet;

            if (mainStyleSheet == null)
            {
                var option = BuilderDialogsUtility.DisplayDialogComplex(
                    BuilderConstants.ExtractInlineStylesNoUSSDialogTitle,
                    BuilderConstants.ExtractInlineStylesNoUSSDialogMessage,
                    BuilderConstants.ExtractInlineStylesNoUSSDialogNewUSSOption,
                    BuilderConstants.ExtractInlineStylesNoUSSDialogExistingUSSOption,
                    BuilderConstants.DialogCancelOption);

                switch (option)
                {
                // New
                case 0:
                    if (!BuilderStyleSheetsUtilities.CreateNewUSSAsset(m_PaneWindow))
                    {
                        return(null);
                    }
                    break;

                // Existing
                case 1:
                    if (!BuilderStyleSheetsUtilities.AddExistingUSSToAsset(m_PaneWindow))
                    {
                        return(null);
                    }
                    break;

                // Cancel
                case 2:
                    return(null);
                }

                mainStyleSheet = m_PaneWindow.document.activeStyleSheet;
            }
            return(mainStyleSheet);
        }
Example #16
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);
        }
        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);
                }
            }
        }
        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);
        }
        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);
        }
        public bool SaveNewDocument(
            VisualElement documentRootElement, bool isSaveAs,
            out bool needsFullRefresh,
            string manualUxmlPath = null)
        {
            needsFullRefresh = false;

            ClearUndo();

            // Re-use or ask the user for the UXML path.
            var newUxmlPath = uxmlPath;

            if (string.IsNullOrEmpty(newUxmlPath) || isSaveAs)
            {
                if (!string.IsNullOrEmpty(manualUxmlPath))
                {
                    newUxmlPath = manualUxmlPath;
                }
                else
                {
                    newUxmlPath = BuilderDialogsUtility.DisplaySaveFileDialog("Save UXML", null, null, "uxml");
                    if (newUxmlPath == null) // User cancelled the save dialog.
                    {
                        return(false);
                    }
                }
            }

            // Save USS files.
            foreach (var openUSSFile in m_OpenUSSFiles)
            {
                openUSSFile.SaveToDisk(visualTreeAsset);
            }

            { // Save UXML file.
                // Need to save a backup before the AssetDatabase.Refresh().
                if (m_VisualTreeAssetBackup == null)
                {
                    m_VisualTreeAssetBackup = m_VisualTreeAsset.DeepCopy();
                }
                else
                {
                    m_VisualTreeAsset.DeepOverwrite(m_VisualTreeAssetBackup);
                }
                WriteUXMLToFile(newUxmlPath);
            }

            // Once we wrote all the files to disk, we refresh the DB and reload
            // the files from the AssetDatabase.
            m_DocumentBeingSavedExplicitly = true;
            try
            {
                AssetDatabase.Refresh();
            }
            finally
            {
                m_DocumentBeingSavedExplicitly = false;
            }

            // Check if any USS assets have changed reload them.
            foreach (var openUSSFile in m_OpenUSSFiles)
            {
                needsFullRefresh |= openUSSFile.PostSaveToDiskChecksAndFixes();
            }
            { // Check if the UXML asset has changed and reload it.
                m_VisualTreeAsset = AssetDatabase.LoadAssetAtPath <VisualTreeAsset>(newUxmlPath);
                needsFullRefresh |= m_VisualTreeAsset != m_VisualTreeAssetBackup;
            }

            if (needsFullRefresh)
            {
                // Copy previous document settings.
                if (m_Settings != null)
                {
                    m_Settings.UxmlGuid = AssetDatabase.AssetPathToGUID(newUxmlPath);
                    m_Settings.UxmlPath = newUxmlPath;
                    m_Settings.SaveSettingsToDisk();
                }

                { // Fix up UXML asset.
                    // To get all the selection markers into the new assets.
                    m_VisualTreeAssetBackup.DeepOverwrite(m_VisualTreeAsset);

                    // Reset asset name.
                    m_VisualTreeAsset.name = Path.GetFileNameWithoutExtension(newUxmlPath);

                    m_VisualTreeAsset.ConvertAllAssetReferencesToPaths();
                    m_OpenendVisualTreeAssetOldPath = newUxmlPath;
                }

                if (documentRootElement != null)
                {
                    ReloadDocumentToCanvas(documentRootElement);
                }
            }

            hasUnsavedChanges = false;

            return(true);
        }
        public bool SaveNewDocument(
            VisualElement documentRootElement, bool isSaveAs,
            out bool needsFullRefresh,
            string manualUxmlPath = null)
        {
            needsFullRefresh = false;

            ClearUndo();

            // Re-use or ask the user for the UXML path.
            var newUxmlPath = uxmlPath;

            if (string.IsNullOrEmpty(newUxmlPath) || isSaveAs)
            {
                if (!string.IsNullOrEmpty(manualUxmlPath))
                {
                    newUxmlPath = manualUxmlPath;
                }
                else
                {
                    newUxmlPath = BuilderDialogsUtility.DisplaySaveFileDialog("Save UXML", null, null, "uxml");
                    if (newUxmlPath == null) // User cancelled the save dialog.
                    {
                        return(false);
                    }
                }
            }

            // Save USS files.
            foreach (var openUSSFile in m_OpenUSSFiles)
            {
                openUSSFile.SaveToDisk(visualTreeAsset);
            }

            // Save UXML files
            // Saving all open UXML files to ensure references correct upon changes in child documents.
            foreach (var openUXMLFile in openUXMLFiles)
            {
                openUXMLFile.PreSaveSyncBackup();
            }

            WriteUXMLToFile(newUxmlPath);

            // Once we wrote all the files to disk, we refresh the DB and reload
            // the files from the AssetDatabase.
            m_DocumentBeingSavedExplicitly = true;
            try
            {
                AssetDatabase.Refresh();
            }
            finally
            {
                m_DocumentBeingSavedExplicitly = false;
            }

            // Check if any USS assets have changed reload them.
            foreach (var openUSSFile in m_OpenUSSFiles)
            {
                needsFullRefresh |= openUSSFile.PostSaveToDiskChecksAndFixes();
            }

            // Check if any UXML assets have changed and reload them.
            // Saving all open UXML files to ensure references correct upon changes in child subdocuments.
            foreach (var openUXMLFile in openUXMLFiles)
            {
                needsFullRefresh |= openUXMLFile.PostSaveToDiskChecksAndFixes(this == openUXMLFile ? newUxmlPath : null, needsFullRefresh);
            }

            if (needsFullRefresh)
            {
                // Copy previous document settings.
                if (m_Settings != null)
                {
                    m_Settings.UxmlGuid = AssetDatabase.AssetPathToGUID(newUxmlPath);
                    m_Settings.UxmlPath = newUxmlPath;
                    m_Settings.SaveSettingsToDisk();
                }

                // Reset asset name.
                m_VisualTreeAsset.name          = Path.GetFileNameWithoutExtension(newUxmlPath);
                m_OpenendVisualTreeAssetOldPath = newUxmlPath;

                if (documentRootElement != null)
                {
                    ReloadDocumentToCanvas(documentRootElement);
                }
            }

            hasUnsavedChanges = false;

            return(true);
        }
        void ExtractLocalStylesToNewClass(string className)
        {
            // Get StyleSheet.
            var mainStyleSheet = m_PaneWindow.document.activeStyleSheet;

            if (mainStyleSheet == null)
            {
                var option = BuilderDialogsUtility.DisplayDialogComplex(
                    BuilderConstants.ExtractInlineStylesNoUSSDialogTitle,
                    BuilderConstants.ExtractInlineStylesNoUSSDialogMessage,
                    BuilderConstants.ExtractInlineStylesNoUSSDialogNewUSSOption,
                    BuilderConstants.ExtractInlineStylesNoUSSDialogExistingUSSOption,
                    BuilderConstants.DialogCancelOption);

                switch (option)
                {
                // New
                case 0:
                    if (!BuilderStyleSheetsUtilities.CreateNewUSSAsset(m_PaneWindow))
                    {
                        return;
                    }
                    break;

                // Existing
                case 1:
                    if (!BuilderStyleSheetsUtilities.AddExistingUSSToAsset(m_PaneWindow))
                    {
                        return;
                    }
                    break;

                // Cancel
                case 2:
                    return;
                }

                mainStyleSheet = m_PaneWindow.document.activeStyleSheet;
            }

            PreAddStyleClass(className);

            // Create new selector in main StyleSheet.
            var selectorString       = BuilderConstants.UssSelectorClassNameSymbol + className;
            var selectorsRootElement = BuilderSharedStyles.GetSelectorContainerElement(m_Selection.documentElement);
            var newSelector          = BuilderSharedStyles.CreateNewSelector(selectorsRootElement, mainStyleSheet, selectorString);

            // Transfer all properties from inline styles rule to new selector.
            mainStyleSheet.TransferRulePropertiesToSelector(
                newSelector, m_Inspector.styleSheet, m_Inspector.currentRule);

            // Update VisualTreeAsset.
            BuilderAssetUtilities.AddStyleClassToElementInAsset(
                m_PaneWindow.document, currentVisualElement, className);

            // Overwrite Undo Message.
            Undo.RegisterCompleteObjectUndo(
                new Object[] { m_PaneWindow.document.visualTreeAsset, mainStyleSheet },
                BuilderConstants.CreateStyleClassUndoMessage);

            // We actually want to get the notification back and refresh ourselves.
            m_Selection.NotifyOfStylingChange(null);
            m_Selection.NotifyOfHierarchyChange(null, currentVisualElement);
        }
Example #23
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();
        }
Example #24
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);
        }