首页 > 解决方案 > 如何保存/存储和加载回编辑器窗口更改?

问题描述

我正在尝试使用 JsonUtility 但它没有做太多。

using System;
using System.Collections.Generic;
using UnityEditor.Callbacks;
using UnityEditor.IMGUI.Controls;
using UnityEngine;


namespace UnityEditor.TreeViewExamples
{
    class CustomHeightWindow : EditorWindow
    {
        [NonSerialized] bool m_Initialized;
        [SerializeField] TreeViewState m_TreeViewState; // Serialized in the window layout file so it survives assembly reloading
        SearchField m_SearchField;
        static CustomHeightTreeView m_TreeView;
        MyTreeAsset m_MyTreeAsset;
        SimpleTreeView simple_m_TreeView;

        private static int numofconversations = 10;
        private static int oldnumofconversations;

        [MenuItem("TreeView Examples/Custom Row Heights")]
        public static CustomHeightWindow GetWindow()
        {
            var window = GetWindow<CustomHeightWindow>();
            window.titleContent = new GUIContent("Custom Heights");
            window.Focus();
            window.Repaint();

            oldnumofconversations = numofconversations;
            CustomHeightTreeView.numberofactive = 0;

            return window;
        }

        protected void OnEnable()
        {
            var data = EditorPrefs.GetString("CustomHeightWindow", JsonUtility.ToJson(this, false));
            // Then we apply them to this window
            JsonUtility.FromJsonOverwrite(data, this);
        }

        protected void OnDisable()
        {
            // We get the Json data
            var data = JsonUtility.ToJson(this, false);
            // And we save it
            EditorPrefs.SetString("CustomHeightWindow", data);
        }

        [OnOpenAsset]
        public static bool OnOpenAsset(int instanceID, int line)
        {
            var myTreeAsset = EditorUtility.InstanceIDToObject(instanceID) as MyTreeAsset;
            if (myTreeAsset != null)
            {
                var window = GetWindow();
                window.SetTreeAsset(myTreeAsset);
                return true;
            }
            return false; // we did not handle the open
        }

        void SetTreeAsset(MyTreeAsset myTreeAsset)
        {
            m_MyTreeAsset = myTreeAsset;
            m_Initialized = false;
        }

        Rect treeViewRect
        {
            get { return new Rect(20, 70, position.width - 40, position.height - 100); }
        }

        Rect toolbarRect
        {
            get { return new Rect(20f, 10f, position.width - 40f, 20f); }
        }

        Rect bottomToolbarRect
        {
            get { return new Rect(20f, position.height - 18f, position.width - 40f, 16f); }
        }

        void InitIfNeeded()
        {
            if (!m_Initialized)
            {
                // Check if it already exists (deserialized from window layout file or scriptable object)
                if (m_TreeViewState == null)
                    m_TreeViewState = new TreeViewState();

                var treeModel = new TreeModel<MyTreeElement>(GetData());
                m_TreeView = new CustomHeightTreeView(m_TreeViewState, treeModel);
                m_SearchField = new SearchField();
                m_SearchField.downOrUpArrowKeyPressed += m_TreeView.SetFocusAndEnsureSelectedItem;

                m_Initialized = true;
            }
        }

        IList<MyTreeElement> GetData()
        {
            if (m_MyTreeAsset != null && m_MyTreeAsset.treeElements != null && m_MyTreeAsset.treeElements.Count > 0)
                return m_MyTreeAsset.treeElements;

            // generate some test data
            return MyTreeElementGenerator.GenerateRandomTree(numofconversations);
        }

        void OnSelectionChange()
        {
            if (!m_Initialized)
                return;

            var myTreeAsset = Selection.activeObject as MyTreeAsset;
            if (myTreeAsset != null && myTreeAsset != m_MyTreeAsset)
            {
                m_MyTreeAsset = myTreeAsset;
                m_TreeView.treeModel.SetData(GetData());
                m_TreeView.Reload();
            } 
        }

        void OnGUI()
        {
            if(oldnumofconversations != numofconversations)
            {
                m_Initialized = false;
                oldnumofconversations = numofconversations;
            }

            InitIfNeeded();

            SearchBar(toolbarRect);
            DoTreeView(treeViewRect);
            BottomToolBar(bottomToolbarRect);
            DoFields();
            DoTreeView();
        }

        void SearchBar(Rect rect)
        {
            m_TreeView.searchString = m_SearchField.OnGUI(rect, m_TreeView.searchString);
        }

        void DoTreeView(Rect rect)
        {
            m_TreeView.OnGUI(rect);
        }

        void BottomToolBar(Rect rect)
        {
            GUILayout.BeginArea(rect);

            using (new EditorGUILayout.HorizontalScope())
            {
                var style = "miniButton";
                if (GUILayout.Button("Expand All", style))
                {
                    m_TreeView.ExpandAll();
                }

                if (GUILayout.Button("Collapse All", style))
                {
                    m_TreeView.CollapseAll();
                }
            }

            GUILayout.EndArea();
        }

        void DoFields()
        {
            DrawBox(new Rect(20, 35, position.width - 40, 30),"", Color.white);
            numofconversations = EditorGUI.IntField(new Rect(187, 43, 50, 15), numofconversations);
            GUI.Label(new Rect(37, 41, 150, 15), "Number of conversations");

            GUI.Label(new Rect(250, 41, 220, 15), "Number of collapsed conversations");
            EditorGUI.IntField(new Rect(458, 43, 50, 15), CustomHeightTreeView.numberofactive);
        }

        void DrawBox(Rect position, string content, Color color)
        {
            Color oldColor = GUI.color;

            GUI.color = color;
            GUI.Box(position, content);

            GUI.color = oldColor;
        }

        void DoTreeView()
        {

        }
    }
}

出于某种原因,当我关闭然后重新打开窗口时,它会保存变量 numofconversations 但只有这个变量。如果在编辑器中打开窗口时,我将 numofconversations 值更改为 100,下次我将打开窗口时,它将是 100。

但我还想存储例如变量 state :

CustomHeightTreeView.numberofactive

我将它设置为 0,但是当它的值在编辑器中发生变化时,它不会保存它。

这是自定义脚本:

using UnityEditor.IMGUI.Controls;
using UnityEngine;


namespace UnityEditor.TreeViewExamples
{
    internal class CustomHeightTreeView : TreeViewWithTreeModel<MyTreeElement>
    {
        public static int numberofactive = 0;
        public static bool isactive = false;

        static class Styles
        {
            public static GUIStyle background = "RL Background";
            public static GUIStyle headerBackground = "RL Header";
        }

        public CustomHeightTreeView(TreeViewState state, TreeModel<MyTreeElement> model)
            : base(state, model)
        {
            // Custom setup
            showBorder = true;
            customFoldoutYOffset = 3f;

            Reload();
        }

        protected override float GetCustomRowHeight (int row, TreeViewItem item)
        {
            var myItem = (TreeViewItem<MyTreeElement>)item;

            if (myItem.data.enabled)
                return 85f;

            return 30f;
        }

        public override void OnGUI (Rect rect)
        {
            // Background
            if (Event.current.type == EventType.Repaint)
                DefaultStyles.backgroundOdd.Draw(rect, false, false, false, false);

            // TreeView
            base.OnGUI (rect);
        }

        protected override void RowGUI (RowGUIArgs args)
        {
            var item = (TreeViewItem<MyTreeElement>) args.item;
            var contentIndent = GetContentIndent (item);
            // Background
            var bgRect = args.rowRect;
            bgRect.x = contentIndent;
            bgRect.width = Mathf.Max (bgRect.width - contentIndent, 155f) - 5f;
            bgRect.yMin += 2f;
            bgRect.yMax -= 2f;

            DrawItemBackground(bgRect);

            if(item.data.enabled == true && isactive == true)
            {
                DrawItemBackgroundColor(bgRect);
            }

            /*if(item.data.enabled == true && isactive == false)
            {
                isactive = true;
                numberofactive++;
                DrawItemBackgroundColor(bgRect);
            }*/

            // Custom label
            var headerRect = bgRect;
            headerRect.xMin += 5f;
            headerRect.xMax -= 10f;
            headerRect.height = Styles.headerBackground.fixedHeight;
            HeaderGUI (headerRect, args.label, item);

            // Controls
            var controlsRect = headerRect;
            controlsRect.xMin += 20f;
            controlsRect.y += headerRect.height;
            if (item.data.enabled)
                ControlsGUI (controlsRect, item);
        }

        void DrawItemBackground (Rect bgRect)
        {
            if (Event.current.type == EventType.Repaint)
            {
                var rect = bgRect;
                rect.height = Styles.headerBackground.fixedHeight;
                Styles.headerBackground.Draw(rect, false, false, false, false);

                rect.y += rect.height;
                rect.height = bgRect.height - rect.height;
                Styles.background.Draw(rect, false, false, false, false);
            }
        }

        void DrawItemBackgroundColor(Rect bgRect)
        {
            if (Event.current.type == EventType.Repaint)
            {
                Color oldColor = GUI.color; 
                GUI.color = new Color32(255, 182, 193,100);

                var rect = bgRect;
                rect.height = Styles.headerBackground.fixedHeight;
                Styles.headerBackground.Draw(rect, false, false, false, false);

                rect.y += rect.height;
                rect.height = bgRect.height - rect.height;
                Styles.background.Draw(rect, false, false, false, false);

                GUI.color = oldColor;
            }
        }

        void HeaderGUI (Rect headerRect, string label, TreeViewItem<MyTreeElement> item)
        {
            headerRect.y += 1f;

            // Do toggle
            Rect toggleRect = headerRect;
            toggleRect.width = 16;
            EditorGUI.BeginChangeCheck ();
                item.data.enabled = EditorGUI.Toggle(toggleRect, item.data.enabled); // hide when outside cell rect
            if (EditorGUI.EndChangeCheck())
            {
                RefreshCustomRowHeights();

                if (item.data.enabled == true)
                {
                    isactive = true;
                    numberofactive++;
                }
                else
                {
                    numberofactive--;
                }
            }

            Rect labelRect = headerRect;
            labelRect.xMin += toggleRect.width + 2f;
            GUI.Label (labelRect, label);
        }

        void ControlsGUI(Rect controlsRect, TreeViewItem<MyTreeElement> item)
        {
            var rect = controlsRect;
            rect.y += 3f;
            rect.height = EditorGUIUtility.singleLineHeight;
            item.data.floatValue1 = EditorGUI.Slider(rect, GUIContent.none, item.data.floatValue1, 0f, 1f);
            rect.y += rect.height + EditorGUIUtility.standardVerticalSpacing;
            item.data.material = (Material)EditorGUI.ObjectField(rect, GUIContent.none, item.data.material, typeof(Material), false);
            rect.y += rect.height + EditorGUIUtility.standardVerticalSpacing;
            item.data.text = GUI.TextField(rect, item.data.text);
        }

        protected override Rect GetRenameRect (Rect rowRect, int row, TreeViewItem item)
        {
            // Match label perfectly
            var renameRect = base.GetRenameRect (rowRect, row, item);
            renameRect.xMin += 25f;
            renameRect.y += 2f;
            return renameRect;
        }

        // Rename
        //--------

        protected override bool CanRename(TreeViewItem item)
        {
            // Only allow rename if we can show the rename overlay with a certain width (label might be clipped by other columns)
            Rect renameRect = GetRenameRect (treeViewRect, 0, item);
            return renameRect.width > 30;
        }

        protected override void RenameEnded(RenameEndedArgs args)
        {
            // Set the backend name and reload the tree to reflect the new model
            if (args.acceptedRename)
            {
                var element = treeModel.Find(args.itemID);
                element.name = args.newName;
                Reload();
            }
        }
    }
}

在此脚本中,我根据当前启用的项目数设置变量 numberofactive :

void HeaderGUI (Rect headerRect, string label, TreeViewItem<MyTreeElement> item)
        {
            headerRect.y += 1f;

            // Do toggle
            Rect toggleRect = headerRect;
            toggleRect.width = 16;
            EditorGUI.BeginChangeCheck ();
                item.data.enabled = EditorGUI.Toggle(toggleRect, item.data.enabled); // hide when outside cell rect
            if (EditorGUI.EndChangeCheck())
            {
                RefreshCustomRowHeights();

                if (item.data.enabled == true)
                {
                    isactive = true;
                    numberofactive++;
                }
                else
                {
                    numberofactive--;
                }
            }

            Rect labelRect = headerRect;
            labelRect.xMin += toggleRect.width + 2f;
            GUI.Label (labelRect, label);
        }

当窗口在编辑器中打开时,如果我切换并折叠例如 5 个项目,它将将变量 numberofactive 更新为 5,然后如果仅切换 3,则更新为 3。但它不会保存它。

这是一个变量,它没有保存还有更多其他变量。例如,它也没有保存 item.enable 状态。如果 item.enable 是 true 或 false,它不会保存它,也不会在第一次打开窗口时切换它。

我知道代码很长,但想法是保存变量值和可视 gui 的编辑器窗口状态。

标签: c#unity3d

解决方案


推荐阅读