c# - 如何保存/存储和加载回编辑器窗口更改?
问题描述
我正在尝试使用 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 的编辑器窗口状态。
解决方案
推荐阅读
- sql-server - 使用子查询或 CTE 进行 SQL Server 更新,需要保证竞争条件安全
- python - 如何安排 conda env 中的 python 脚本每 n 分钟运行一次?
- php - 当控制器中有进程时,Laravel 卡住了
- python - PyQt5 窗口出现空
- html - 在 Crome 上显示黑屏的 html 视频
- azure-ad-b2c - B2C 密码重置策略强制登录进入忘记密码流程
- git - 如何从 .gitignore 中删除某些文件目录关于 Git
- python - 如何用科学记数法(张量格式)解析文本文件并将它们转换为浮点数
- spring-boot - 为什么 Spring Converter 没有抛出异常?
- grails - CSV 插件控制器在哪里?