Пример #1
0
        internal static InstantiationResult Instantiate(SceneTemplateAsset sceneTemplate, bool loadAdditively, string newSceneOutputPath, SceneTemplateAnalytics.SceneInstantiationType instantiationType)
        {
            if (!sceneTemplate.isValid)
            {
                throw new Exception("templateScene is empty");
            }

            if (EditorApplication.isUpdating)
            {
                Debug.LogFormat(LogType.Warning, LogOption.None, null, "Cannot instantiate a new scene while updating the editor is disallowed.");
                return(null);
            }

            // If we are loading additively, we cannot add a new Untitled scene if another unsaved Untitled scene is already opened
            if (loadAdditively && SceneTemplateUtils.HasSceneUntitled())
            {
                Debug.LogFormat(LogType.Warning, LogOption.None, null, "Cannot instantiate a new scene additively while an unsaved Untitled scene already exists.");
                return(null);
            }

            var sourceScenePath = AssetDatabase.GetAssetPath(sceneTemplate.templateScene);

            if (String.IsNullOrEmpty(sourceScenePath))
            {
                throw new Exception("Cannot find path for sceneTemplate: " + sceneTemplate.ToString());
            }

            if (!Application.isBatchMode && !loadAdditively && !EditorSceneManager.SaveCurrentModifiedScenesIfUserWantsTo())
            {
                return(null);
            }

            var instantiateEvent = new SceneTemplateAnalytics.SceneInstantiationEvent(sceneTemplate, instantiationType)
            {
                additive = loadAdditively
            };

            sceneTemplate.UpdateDependencies();
            var hasAnyCloneableDependencies = sceneTemplate.hasCloneableDependencies;

            SceneAsset newSceneAsset = null;
            Scene      newScene;

            var templatePipeline = sceneTemplate.CreatePipeline();

            if (!InstantiateInMemoryScene(sceneTemplate, sourceScenePath, ref newSceneOutputPath, out var rootFolder, out var isTempMemory))
            {
                instantiateEvent.isCancelled = true;
                SceneTemplateAnalytics.SendSceneInstantiationEvent(instantiateEvent);
                return(null);
            }

            templatePipeline?.BeforeTemplateInstantiation(sceneTemplate, loadAdditively, isTempMemory ? null : newSceneOutputPath);
            newSceneTemplateInstantiating?.Invoke(sceneTemplate, isTempMemory ? null : newSceneOutputPath, loadAdditively);

            newSceneAsset = AssetDatabase.LoadAssetAtPath <SceneAsset>(newSceneOutputPath);

            var refPathMap = new Dictionary <string, string>();
            var idMap      = new Dictionary <int, int>();

            if (hasAnyCloneableDependencies)
            {
                var clonedAssets = CopyCloneableDependencies(sceneTemplate, newSceneOutputPath, ref refPathMap);
                idMap.Add(sceneTemplate.templateScene.GetInstanceID(), newSceneAsset.GetInstanceID());
                ReferenceUtils.RemapAssetReferences(refPathMap, idMap);

                foreach (var clone in clonedAssets)
                {
                    if (clone)
                    {
                        EditorUtility.SetDirty(clone);
                    }
                }
                AssetDatabase.SaveAssets();
            }

            newScene = EditorSceneManager.OpenScene(newSceneOutputPath, loadAdditively ? OpenSceneMode.Additive : OpenSceneMode.Single);

            if (hasAnyCloneableDependencies)
            {
                EditorSceneManager.RemapAssetReferencesInScene(newScene, refPathMap, idMap);
            }

            EditorSceneManager.SaveScene(newScene, newSceneOutputPath);

            if (isTempMemory)
            {
                newSceneAsset = null;
                newScene.SetPathAndGuid("", newScene.guid);
                s_CurrentInMemorySceneState.guid       = newScene.guid;
                s_CurrentInMemorySceneState.rootFolder = rootFolder;
                s_CurrentInMemorySceneState.hasCloneableDependencies = hasAnyCloneableDependencies;
                s_CurrentInMemorySceneState.dependencyFolderName     = Path.GetFileNameWithoutExtension(newSceneOutputPath);
            }

            SceneTemplateAnalytics.SendSceneInstantiationEvent(instantiateEvent);
            templatePipeline?.AfterTemplateInstantiation(sceneTemplate, newScene, loadAdditively, newSceneOutputPath);
            newSceneTemplateInstantiated?.Invoke(sceneTemplate, newScene, newSceneAsset, loadAdditively);

            SceneTemplateUtils.SetLastFolder(newSceneOutputPath);

            return(new InstantiationResult(newScene, newSceneAsset));
        }
        private void BuildUI()
        {
            // Keyboard events need a focusable element to trigger
            rootVisualElement.focusable = true;
            rootVisualElement.RegisterCallback <KeyUpEvent>(e =>
            {
                switch (e.keyCode)
                {
                case KeyCode.Escape when !docked:
                    Close();
                    break;
                }
            });

            // Load stylesheets
            rootVisualElement.AddToClassList(Styles.unityThemeVariables);
            rootVisualElement.AddToClassList(Styles.sceneTemplateThemeVariables);
            rootVisualElement.AddStyleSheetPath(Styles.k_CommonStyleSheetPath);
            rootVisualElement.AddStyleSheetPath(Styles.variableStyleSheet);

            // Create a container to offset everything nicely inside the window
            {
                var offsetContainer = new VisualElement();
                offsetContainer.AddToClassList(Styles.classOffsetContainer);
                rootVisualElement.Add(offsetContainer);

                // Create a container for the scene templates and description
                {
                    var mainContainer = new VisualElement();
                    mainContainer.style.flexDirection = FlexDirection.Row;
                    mainContainer.AddToClassList(Styles.classMainContainer);
                    offsetContainer.Add(mainContainer);

                    {
                        // Create a container for the scene templates lists(left side)
                        var sceneTemplatesContainer = new VisualElement();
                        sceneTemplatesContainer.AddToClassList(Styles.classTemplatesContainer);
                        sceneTemplatesContainer.AddToClassList(Styles.sceneTemplateDialogBorder);
                        // mainContainer.Add(sceneTemplatesContainer);
                        CreateAllSceneTemplateListsUI(sceneTemplatesContainer);

                        // Create a container for the template description (right side)
                        var descriptionContainer = new VisualElement();
                        descriptionContainer.AddToClassList(Styles.classDescriptionContainer);
                        descriptionContainer.AddToClassList(Styles.classBorder);
                        // mainContainer.Add(descriptionContainer);
                        CreateTemplateDescriptionUI(descriptionContainer);

                        if (EditorPrefs.HasKey(GetKeyName(nameof(m_Splitter))))
                        {
                            var splitterPosition = EditorPrefs.GetFloat(GetKeyName(nameof(m_Splitter)));
                            sceneTemplatesContainer.style.width = splitterPosition;
                        }
                        else
                        {
                            EditorApplication.delayCall += () =>
                            {
                                sceneTemplatesContainer.style.width = position.width * 0.60f;
                            };
                        }
                        m_Splitter = new VisualSplitter(sceneTemplatesContainer, descriptionContainer, FlexDirection.Row);
                        mainContainer.Add(m_Splitter);
                    }
                }

                // Create the button row
                {
                    var buttonRow = new VisualElement();
                    buttonRow.AddToClassList(Styles.sceneTemplateDialogFooter);
                    offsetContainer.Add(buttonRow);
                    buttonRow.style.flexDirection = FlexDirection.Row;

                    var loadAdditiveToggle = new Toggle()
                    {
                        name = k_SceneTemplateCreateAdditiveButtonName, text = L10n.Tr("Load additively"), tooltip = k_LoadAdditivelyToolTip
                    };
                    if (SceneTemplateUtils.HasSceneUntitled())
                    {
                        loadAdditiveToggle.SetEnabled(false);
                        loadAdditiveToggle.tooltip = k_LoadAdditivelyToolTipDisabledHasUnsavedUntitled;
                    }
                    buttonRow.Add(loadAdditiveToggle);
                    {
                        // The buttons need to be right-aligned
                        var buttonSection = new VisualElement();
                        buttonSection.style.flexDirection = FlexDirection.RowReverse;
                        buttonSection.AddToClassList(Styles.classButtons);
                        buttonRow.Add(buttonSection);
                        var createSceneButton = new Button(() =>
                        {
                            if (m_LastSelectedTemplate == null)
                            {
                                return;
                            }
                            OnCreateNewScene(m_LastSelectedTemplate);
                        })
                        {
                            text = L10n.Tr("Create"), tooltip = L10n.Tr("Instantiate a new scene from a template")
                        };
                        createSceneButton.AddToClassList(Styles.classButton);
                        var cancelButton = new Button(Close)
                        {
                            text = L10n.Tr("Cancel"), tooltip = L10n.Tr("Close scene template dialog without instantiating a new scene.")
                        };
                        cancelButton.AddToClassList(Styles.classButton);
                        buttonSection.Add(cancelButton);
                        buttonSection.Add(createSceneButton);

                        m_Buttons = new List <ButtonInfo>
                        {
                            new ButtonInfo {
                                button = createSceneButton, callback = OnCreateNewScene
                            },
                            new ButtonInfo {
                                button = cancelButton, callback = info => Close()
                            }
                        };
                        m_SelectedButtonIndex = m_Buttons.FindIndex(bi => bi.button == createSceneButton);
                        UpdateSelectedButton();
                    }
                }
                SetAllElementSequentiallyFocusable(rootVisualElement, false);
            }

            if (m_LastSelectedTemplate != null)
            {
                UpdateTemplateDescriptionUI(m_LastSelectedTemplate);
            }
        }