Class reading and populating a scene based on text-based scene files.
Ejemplo n.º 1
0
    private void BuildNext()
    {
        //TODO: Must be fixed up to work with callback - scene saving does not work very well if done
        //      immediately after load, which is why we need to make this into a async operation
        //      of some sort. See unity case 336621.
        //Run through all scenes and build them based on the human readable representation.
        if (sceneQueue.Count > 0)
        {
            string textScene = sceneQueue.Dequeue();

            Debug.Log("Building temp for: " + textScene);

            string result = TextSceneDeserializer.Load(EditorHelper.GetProjectFolder() + textScene, this.BuildNext);

            if (result.Length == 0)
            {
                EditorUtility.DisplayDialog("Scene does not exist", "Unable to find scene file: " + textScene + " Will be excluded from build", "OK");
                BuildNext();
            }
            else
            {
                binarySceneList.Add(result);
            }
        }
        else
        {
            FinishBuild();
        }
    }
Ejemplo n.º 2
0
    /// <summary>
    /// Loads the currently selected TextScene. Will fail and notify user if the selected file is
    /// not a text file.
    /// </summary>
    public static void LoadContext()
    {
        if (Selection.activeObject == null)
        {
            EditorUtility.DisplayDialog("Nothing selected", "You need to select a text scene asset to load one", "OK");
            return;
        }

        TextAsset asset = Selection.activeObject as TextAsset;

        string assetPath = "";

        if (asset != null)
        {
            assetPath = AssetDatabase.GetAssetPath(asset);
        }

        if (!assetPath.EndsWith(".txt"))
        {
            EditorUtility.DisplayDialog("Not a text file", "Text scenes can only be loaded from TextAssets (*.txt)", "OK");
        }
        else
        {
            string fullPath = Application.dataPath
                              + assetPath.Substring(assetPath.IndexOf('/'));

            TextSceneDeserializer.LoadSafe(fullPath);
        }
    }
Ejemplo n.º 3
0
    private void FinishBuild()
    {
        Debug.Log("Building " + binarySceneList.Count + " scenes: ");

        foreach (string scene in binarySceneList)
        {
            Debug.Log(scene);
        }

        if (buildPath != null)
        {
            BuildPipeline.BuildPlayer(binarySceneList.ToArray(), buildPath, buildTarget, BuildOptions.AutoRunPlayer);
        }
        else
        {
            Debug.Log("Temp scenes generated, no player will be built.");
        }

        if (sceneToLoad.Length > 0)
        {
            TextSceneDeserializer.Load(sceneToLoad);
        }
    }
Ejemplo n.º 4
0
    public override void OnInspectorGUI()
    {
        TextSceneObject tso = target as TextSceneObject;

        EditorGUILayout.BeginVertical();

        GUILayout.Label("External scene");

        EditorGUILayout.BeginHorizontal();
        GUILayout.Label("Open scene: ");

        if (GUILayout.Button(tso.textScene.name))
        {
            if (EditorUtility.DisplayDialog("Open scenefile?", "Do you want to close the current scene and open the scene pointed to by this TextSceneObject?", "Yes", "No"))
            {
                TextSceneDeserializer.LoadSafe(EditorHelper.GetProjectFolder() + AssetDatabase.GetAssetPath(tso.textScene));
                GUIUtility.ExitGUI();
            }
        }

        EditorGUILayout.EndHorizontal();
        EditorGUILayout.EndVertical();
    }
Ejemplo n.º 5
0
    public TextSceneTempCreator(string scene, TextSceneDeserializer.TempSceneSaved callback)
    {
        state = State.SaveTemp;

        saveAndReloadTimer = Mathf.RoundToInt(SAVE_AND_RELOAD_FRAMES);
        saveAndReload = scene;
        saveAndReloadCallback = callback;
    }
Ejemplo n.º 6
0
 public void DoSaveAndReload(string scene, TextSceneDeserializer.TempSceneSaved callback)
 {
     //Must wait a couple of frames before we do the save for prefabs to behave correctly.
     //TODO: Report bug.
     process = new TextSceneTempCreator(scene, callback);
 }
Ejemplo n.º 7
0
    /// <summary>
    /// Loads a TextScene into a clean scene. Will ask user for path.
    /// </summary>
    public static void Load()
    {
        string path = EditorUtility.OpenFilePanel("Load scene file", Application.dataPath, "txt");

        TextSceneDeserializer.LoadSafe(path);
    }
Ejemplo n.º 8
0
        public bool HandleDrag()
        {
            if (Event.current.type == EventType.DragUpdated ||
                Event.current.type == EventType.DragPerform)
            {
                Entry e = DragAndDrop.GetGenericData("entry") as Entry;

                //Do not allow dragging stuff onto prefabs or textscene links.
                if (this.type != EntryType.Normal)
                {
                    selected = null;
                    DragAndDrop.visualMode = DragAndDropVisualMode.None;
                    return(false);
                }
                //Do not allow dragging prefab or textscene children around.
                else if (e != null &&
                         (e.type == EntryType.PrefabChild ||
                          e.type == EntryType.TextSceneChild))
                {
                    selected = null;
                    DragAndDrop.visualMode = DragAndDropVisualMode.None;
                    return(false);
                }
                else
                {
                    selected = this;

                    if (expanded == false &&
                        EditorApplication.timeSinceStartup > this.expandedTimer)
                    {
                        this.expanded = true;
                    }

                    DragAndDrop.visualMode = DragAndDropVisualMode.Link;

                    if (Event.current.type == EventType.DragPerform)
                    {
                        DragAndDrop.AcceptDrag();

                        if (e != null && e.go != null)
                        {
                            GameObject dragged = e.go;

                            if (dragged != null)
                            {
                                if (dragged != go)
                                {
                                    Undo.RegisterSceneUndo("Move " + dragged.name);

                                    //If the target is null (the root), we might want to orphan the object.
                                    if (go == null)
                                    {
                                        if (dragged.transform.parent != null)
                                        {
                                            if (EditorUtility.DisplayDialog("Orphan", "Do you want to make " + dragged.name + " an orphan?", "Yes", "No"))
                                            {
                                                dragged.transform.parent   = null;
                                                Selection.activeGameObject = dragged;
                                                TextSceneHierarchy.Refresh();
                                            }
                                        }
                                    }
                                    else
                                    {
                                        //Change parent to whatever we're hovering above at the time of drag end.
                                        if (EditorUtility.DisplayDialog("Change parent", "Do you want to make " + go.name + " the parent of " + dragged.name + "?", "Yes", "No"))
                                        {
                                            dragged.transform.parent   = go.transform;
                                            Selection.activeGameObject = dragged;
                                            TextSceneHierarchy.Refresh();
                                        }
                                    }
                                }
                            }
                        }
                        else if (DragAndDrop.objectReferences.Length > 0)
                        {
                            UnityEngine.Object dragged = DragAndDrop.objectReferences[0];

                            MonoScript comp             = dragged as MonoScript;
                            GameObject draggedGO        = dragged as GameObject;
                            TextAsset  draggedTextScene = dragged as TextAsset;

                            if (comp != null)
                            {
                                if (this.go != null)
                                {
                                    this.go.AddComponent(comp.GetClass());
                                    Selection.activeGameObject = this.go;
                                }
                            }
                            else if (draggedTextScene != null)
                            {
                                Undo.RegisterSceneUndo("Add scene " + draggedTextScene.name);

                                TextSceneDeserializer.LoadAdditive(draggedTextScene, this.go);
                            }
                            else if (draggedGO != null)
                            {
                                PrefabType pt = EditorUtility.GetPrefabType(dragged);

                                if (pt == PrefabType.ModelPrefab || pt == PrefabType.Prefab)
                                {
                                    Undo.RegisterSceneUndo("Create " + draggedGO.name);

                                    GameObject instance = EditorUtility.InstantiatePrefab(dragged) as GameObject;

                                    if (this.go != null)
                                    {
                                        instance.transform.parent = this.go.transform;
                                    }

                                    instance.transform.localPosition = Vector3.zero;
                                    instance.transform.localRotation = Quaternion.identity;
                                    instance.name = instance.name + "_instance";

                                    Selection.activeGameObject = instance;
                                }
                            }
                        }
                    }
                }

                Event.current.Use();
                return(true);
            }

            return(false);
        }
Ejemplo n.º 9
0
    void OnGUI()
    {
        GUILayout.BeginVertical();

        scroll = GUILayout.BeginScrollView(scroll);

        GUILayout.Label("Scenes to build");

        foreach (string scene in scenes)
        {
            EditorGUILayout.BeginHorizontal();

            if (GUILayout.Button(scene))
            {
                TextSceneDeserializer.LoadSafe(EditorHelper.GetProjectFolder() + scene);
                GUIUtility.ExitGUI();
                return;
            }


            if (GUILayout.Button("Remove", GUILayout.MaxWidth(60)))
            {
                if (EditorUtility.DisplayDialog("Remove scene", "Are you sure you want to remove this scene from the build settings?", "Yes", "No"))
                {
                    TextScene.RemoveSceneFromBuild(scene);
                    LoadSettings();
                }
            }

            if (GUILayout.Button("+", GUILayout.MaxWidth(20)))
            {
                TextScene.MoveScenePosition(scene, 1);
                LoadSettings();
            }

            if (GUILayout.Button("-", GUILayout.MaxWidth(20)))
            {
                TextScene.MoveScenePosition(scene, -1);
                LoadSettings();
            }

            GUILayout.EndHorizontal();
        }

        if (scenes.Count > 0)
        {
            EditorGUILayout.Separator();
            EditorGUILayout.BeginVertical(GUILayout.MaxWidth(150));

            if (GUILayout.Button("Build Temp"))
            {
                TextScene.BuildTempScenes();
                GUIUtility.ExitGUI();
                return;
            }

            if (GUILayout.Button("Build Streamed Web"))
            {
                TextScene.Build(BuildTarget.WebPlayerStreamed);
                GUIUtility.ExitGUI();
                return;
            }

            if (GUILayout.Button("Build Web"))
            {
                TextScene.Build(BuildTarget.WebPlayer);
                GUIUtility.ExitGUI();
                return;
            }

            if (GUILayout.Button("Build OSX"))
            {
                TextScene.Build(BuildTarget.StandaloneOSXUniversal);
                GUIUtility.ExitGUI();
                return;
            }

            if (GUILayout.Button("Build Windows"))
            {
                TextScene.Build(BuildTarget.StandaloneWindows);
                GUIUtility.ExitGUI();
                return;
            }

            EditorGUILayout.EndVertical();
        }
        else
        {
            GUILayout.Label("Add scenes via the TextScene menu item to enable build");
        }

        EditorGUILayout.Separator();

        if (GUILayout.Button("Add current", GUILayout.MaxWidth(100)))
        {
            TextScene.AddCurrentSceneToBuild();
            LoadSettings();
        }

        EditorGUILayout.Separator();

        if (GUILayout.Button("Validate Settings", GUILayout.MaxWidth(100)))
        {
            List <string> invalidScenes;

            if (TextScene.ValidateBuildSettings(out invalidScenes))
            {
                EditorUtility.DisplayDialog("Valid settings", "The build settings seem valid enough", "OK");
            }
            else
            {
                StringBuilder sb = new StringBuilder();

                sb.Append("There were errors in validation: \n");

                foreach (string scene in invalidScenes)
                {
                    sb.Append("   ");
                    sb.Append(scene);
                    sb.Append('\n');
                }

                sb.Append("Try running 'Build Temp' to fix them up, or inspect the console for further hints.");

                EditorUtility.DisplayDialog("Validation failed", sb.ToString(), "OK");
            }
        }

        GUILayout.EndScrollView();

        GUILayout.EndVertical();
    }
Ejemplo n.º 10
0
    public static void Save(string filePath)
    {
        if (EditorApplication.isPlayingOrWillChangePlaymode)
        {
            EditorUtility.DisplayDialog("Game is running", "You cannot save in Play-mode", "OK");
            return;
        }



        Transform[] sceneObjects = Helper.GetObjectsOfType <Transform>();

        List <Transform> sortedTransforms = new List <Transform>();

        //Sort these to get a somewhat predictable output
        foreach (Transform o in sceneObjects)
        {
            //Only serialize root objects, children are handled by their parents
            if (o.parent == null)
            {
                sortedTransforms.Add(o);
            }
        }

        warnings = 0;

        sortedTransforms.Sort(CompareTransform);

        StringBuilder sceneText = new StringBuilder();

        foreach (Transform o in sortedTransforms)
        {
            Serialize(sceneText, o.gameObject, 0);
        }


        //TODO: If the save didn't go without warnings, show a message/confirmation
        //      dialog here.
        if (warnings > 0)
        {
            EditorUtility.DisplayDialog("ERROR: Scene not saved", "You had " + warnings + " errors or warnings during the save. Please fix them up and try again.", "OK");
            return;
        }


        StreamWriter fileStream = File.CreateText(filePath);

        fileStream.Write(sceneText.ToString());
        fileStream.Close();

        Debug.Log("Wrote scene to file: " + filePath);

        string assetPath = filePath.Replace(EditorHelper.GetProjectFolder(), "");

        Debug.Log("Reimporting: " + assetPath);

        //Import the asset.
        AssetDatabase.ImportAsset(assetPath, ImportAssetOptions.ForceUpdate);

        Selection.activeObject = AssetDatabase.LoadAssetAtPath(assetPath, typeof(TextAsset));

        TextSceneDeserializer.Load(filePath);
    }
Ejemplo n.º 11
0
 public static void LoadContext()
 {
     TextSceneDeserializer.LoadContext();
 }
Ejemplo n.º 12
0
    public Status Update()
    {
        if (saveAndReload.Length == 0)
        {
            Debug.LogError("Invalid saveandreload name! Cancelling load/save process...");
            return(Status.Failed);
        }

        if (saveAndReloadTimer > 0)
        {
            EditorUtility.DisplayProgressBar("Creating temp...", "Creating binary temp file for TextScene: " + state.ToString(), 1.0f - saveAndReloadTimer / SAVE_AND_RELOAD_FRAMES);

            saveAndReloadTimer--;
            return(Status.Working);
        }
        else
        {
            if (state == State.SaveTemp)
            {
                Debug.Log("SaveAndReload: " + saveAndReload);

                ///FIXME: Unity sometimes puts a lock on the scenes we try to save, this is a CRUEL way to
                ///get around it.
                ///
                ///Repro-steps: *Comment out the try/catch
                ///             *Clean out tempscenes-folder.
                ///             *Open up a scene (LEVEL1) from build settings, hit play
                ///             *While playing, do something to make the game
                ///              change to another level (LEVEL2).
                ///             *Stop playing, you should now be back in the level where you
                ///              hit play from.
                ///             *Try to switch to the level you switched to in-game (LEVEL2).
                ///             *You should, after the progress bar has completed, be prompted
                ///              with an error saying Unity could not move file from Temp/Tempfile
                ///
                try
                {
                    FileStream f = File.OpenWrite(saveAndReload);
                    f.Close();
                }
                catch
                {
                    Debug.LogWarning("HACK: Getting around 'access denied' on temp files!");

                    //HACK: This seems to make Unity release the file so we can try to save it in a new go.
                    if (!EditorApplication.OpenScene(saveAndReload))
                    {
                        //Uh oh.
                        Debug.LogError("HACK failed! What to do next?");
                        EditorUtility.ClearProgressBar();
                        return(Status.Failed);
                    }

                    TextSceneDeserializer.Load(EditorHelper.GetProjectFolder() + TextScene.TempToTextSceneFile(EditorApplication.currentScene), saveAndReloadCallback);
                    return(Status.Working);
                }

                if (!EditorApplication.SaveScene(saveAndReload))
                {
                    Debug.LogError("Failed to save temp: " + saveAndReload);


                    if (EditorUtility.DisplayDialog("ERROR", "Failed to save temp (" + saveAndReload + ") - try again?", "Yes", "No"))
                    {
                        saveAndReloadTimer = Mathf.RoundToInt(SAVE_AND_RELOAD_FRAMES);
                    }
                    else
                    {
                        return(Status.Failed);
                    }


                    EditorUtility.ClearProgressBar();
                    return(Status.Working);
                }

                state = State.CreateNew;
                saveAndReloadTimer = Mathf.RoundToInt(SAVE_AND_RELOAD_FRAMES);
                return(Status.Working);
            }
            else if (state == State.CreateNew)
            {
                EditorApplication.NewScene();

                state = State.LoadTemp;
                saveAndReloadTimer = Mathf.RoundToInt(SAVE_AND_RELOAD_FRAMES);
                return(Status.Working);
            }
            else if (state == State.LoadTemp)
            {
                if (!EditorApplication.OpenScene(saveAndReload))
                {
                    Debug.LogError("Failed to load temp: " + saveAndReload);

                    if (EditorUtility.DisplayDialog("ERROR", "Failed to load temp (" + saveAndReload + ") - try again?", "Yes", "No"))
                    {
                        saveAndReloadTimer = Mathf.RoundToInt(SAVE_AND_RELOAD_FRAMES);
                    }
                    else
                    {
                        return(Status.Failed);
                    }

                    EditorUtility.ClearProgressBar();
                    return(Status.Working);
                }

                string writtenFile = EditorHelper.GetProjectFolder() + EditorApplication.currentScene;

                DateTime writtenTime = File.GetLastWriteTime(writtenFile);

                Debug.Log("Wrote temp file at " + writtenTime);

                TextSceneMonitor.Instance.SetCurrentScene(EditorHelper.GetProjectFolder() + TextScene.TempToTextSceneFile(EditorApplication.currentScene));

                saveAndReload = "";

                EditorUtility.ClearProgressBar();

                return(Status.Complete);
            }
        }

        Debug.LogError("Failing....");
        return(Status.Failed);
    }
Ejemplo n.º 13
0
    /// <summary>
    /// Regularly checks if something worthy of notifying the user happens. This includes
    /// unexpected scene changes (double-clicking .unity files), creating new scenes and
    /// source TextScene files having been changed between now and the time it was loaded.
    /// </summary>
    private void Update()
    {
        //HACK: To get around bug (TOOD: Insert case #) where Save immediately
        //      after instantiating prefabs results in weird behaviour.
        if (process != null)
        {
            TextSceneTempCreator.Status status = process.Update();

            switch (status)
            {
            case TextSceneTempCreator.Status.Failed:
                Debug.LogError("Creating temp files failed!");
                process = null;
                break;

            case TextSceneTempCreator.Status.Complete:
                Debug.Log("Creating temp files succeeded!");

                //FIXME: Either do this, or get a reference to the delegate and call
                //       if after clearing tempCreator. The callback might
                //       end up setting the tempCreator again, typically in a build-cycle,
                //       for example.
                TextSceneTempCreator tempCreatorRef = process;

                process = null;

                tempCreatorRef.InvokeCallback();

                break;

            default:
                break;
            }

            return;
        }

        //Did the user create a new scene?
        if (currentScene.Length > 0 &&
            EditorApplication.currentScene.Length == 0)
        {
            if (CheckForChangedTemp())
            {
                EditorApplication.NewScene();
            }

            currentScene        = "";
            alarmingEditorScene = "";

            TextSceneSerializer.SaveCurrent();

            //Warn the user if the save scene dialog was cancelled.
            if (currentScene.Length == 0)
            {
                EditorUtility.DisplayDialog("New Scene", "You have started a new scene after using the TextScene system. Please use the TextScene menu to save it if you want to continue using the TextScene system", "OK");
            }
        }

        //Try to detect when we go from a TextScene to a regular unit scene.
        if ((currentScene.Length > 0 &&
             EditorApplication.currentScene.Length > 0) ||
            (currentScene.Length == 0 &&
             alarmingEditorScene.Length == 0))
        {
            if (alarmingEditorScene != EditorApplication.currentScene)
            {
                string current = EditorApplication.currentScene;

                if (CheckForChangedTemp())
                {
                    EditorApplication.OpenScene(current);
                }

                if (EditorUtility.DisplayDialog("TextScene/built-in mixed usage", "It is not recommended to mix TextScene usage with built-in Unity scenes. This may cause the TextScene system to miss updates or simply behave totally weird! If you plan on using the TextScene system, you should save the current scene via the TextScene menu item and  - if successfully saved (please inspect the log for errors and warnings) - remove the original from the Assets folder. Please note that not all components/Unity objects can be saved into the TextScene format, so don't delete the original until you are 100% sure you saved what you need!", "Save to TextScene now!", "I know what I'm doing"))
                {
                    TextSceneSerializer.SaveCurrent();
                }
                else
                {
                    alarmingEditorScene = EditorApplication.currentScene;
                    currentScene        = "";
                }
            }
        }

        //Regular checks to see if the scene file was edited since our last load.
        if (currentScene.Length > 0 &&
            EditorApplication.timeSinceStartup > nextCheckForChangedFile)
        {
            if (File.Exists(currentScene))
            {
                DateTime lastWriteTime = File.GetLastWriteTime(currentScene);

                if (lastWriteTime > currentSceneLoaded)
                {
                    int result = EditorUtility.DisplayDialogComplex("Scene changed", "The TextScene you currently have open changed (" + lastWriteTime + "). Do you want to reload it?", "Yes", "Backup mine first", "No");

                    if (result == 0)                    //Yes
                    {
                        TextSceneDeserializer.Load(currentScene);
                    }
                    else if (result == 1)//Backup first
                    {
                        string filename = EditorUtility.SaveFilePanel("Backup TextScene", currentScene.Substring(0, currentScene.LastIndexOf('/')), "backup", "txt");

                        if (filename.Length != 0)
                        {
                            //This is overwritten during the save.
                            string toLoad = currentScene;

                            TextSceneSerializer.Save(filename);
                            TextSceneDeserializer.Load(toLoad);
                        }
                        else
                        {
                            EditorUtility.DisplayDialog("Unsaved", "You chose to cancel the backup of your own scene file. It is recommended that you manually save a copy, and merge with the updated file from disk (" + currentScene + ")", "OK");
                        }
                    }
                    else//No
                    {
                        //HACK: Shut this message up. We don't want to get asked this again until the
                        //      file changes again.
                        currentSceneLoaded = DateTime.Now;
                    }
                }
            }
            else
            {
                if (EditorUtility.DisplayDialog("TextScene file gone!", "It seems like the TextScene representation of your open file has been deleted. Do you want to re-save it (" + currentScene + ")?", "Yes", "No"))
                {
                    TextSceneSerializer.Save(currentScene);
                }
                else
                {
                    currentScene = "";
                }
            }

            //Also check for changed temp files (.unity in TempScenes). This happens if
            //the user uses the built-in save functionality.
            CheckForChangedTemp();

            nextCheckForChangedFile = EditorApplication.timeSinceStartup + 1.0f;
        }
    }