Projeto 2 do exercício de expansão do editor Unity (veja a ferramenta GUIStyle integrada)

O exercício de hoje se concentra no uso de TreeView. Use TreeView para criar uma ferramenta. Imagine que a ferramenta contém duas funções, visualizar o GUIStyle integrado e visualizar o ícone integrado. Desta vez, apenas a função de visualizar o GUIStyle integrado. GUIStyle está concluído.

Captura de tela da ferramenta

Insira a descrição da imagem aqui

MTreeView e MTreeViewItem

Herdado de TreeView e TreViewItem, é um encapsulamento customizado desses dois objetos, adicionando restrições genéricas, simplificando a adição de subestruturas e a declaração de TreeViewItem.

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

namespace S.Editor
{
    public class MTreeViewItem<T> : TreeViewItem
    {
        public T data { get; protected set; }

        public MTreeViewItem(T data,int id,int depth=0)
        {
            this.data = data;
            this.id = id;
            this.depth = depth;
        }
    }

    public abstract class MTreeView<T> : TreeView
    {
        private int nextItemIndex;
        protected TreeViewItem root { get; private set; }
        protected List<TreeViewItem> items { get; private set; }

        public MTreeView(TreeViewState state) : base(state)=>OnInit();
    
        public MTreeView(TreeViewState state, MultiColumnHeader multiColumnHeader) : base(state, multiColumnHeader)=>OnInit();
        
        protected virtual void OnInit()
        {
            root=new TreeViewItem(-1,-1);
            nextItemIndex = 0;
            if (items==null)items=new List<TreeViewItem>();
            else items?.Clear();
        }
    
        public void InitTreeViewItems(IEnumerable<MTreeViewItem<T>> mItems,bool reload=true)
        {
            if (items==null)items=new List<TreeViewItem>();
            else items.Clear();
            int count = mItems == null ? 0 : mItems.Count();
            if (count>0)
            {
                foreach (var item in mItems)items.Add(item);
            }
            if (reload)Reload();
        }
    
        public void AddTreeViewItem(MTreeViewItem<T> item,bool reload=true)
        {
            items.Add(item);
            if (reload)Reload();
        }

        public MTreeViewItem<T> AddTreeViewItem(T item,bool reload=true)
        {
            MTreeViewItem<T> treeViewItem= new MTreeViewItem<T>(item,GetIndex());
            items.Add(treeViewItem);
            if (reload)Reload();
            return treeViewItem;
        }

        protected override TreeViewItem BuildRoot()
        {
            SetupParentsAndChildrenFromDepths(root,items);
            return root;
        }
    
        protected override void RowGUI(RowGUIArgs args)
        {
            MTreeViewItem<T> item = args.item as MTreeViewItem<T>;
            if (multiColumnHeader == null)//单列
            {
                CellGUI(args.rowRect,item,0);
            }
            else//多列
            {
                int visibleColumns = args.GetNumVisibleColumns();//可见列数
                if (visibleColumns>0)
                {
                    for (int i = 0; i < visibleColumns; i++)CellGUI(args.GetCellRect(i),item,i);
                }
            }
            base.RowGUI(args);
        }

        protected abstract void CellGUI(Rect rect, MTreeViewItem<T> item, int cowIndex);

        public int GetIndex()
        {
            int callBackIndex = nextItemIndex;
            nextItemIndex++;
            return callBackIndex;
        }

        protected override void SingleClickedItem(int id)
        {
            TreeViewItem item = FindItem(id, root);
            if (item == null) return;
            MTreeViewItem<T> m_item = FindItem(id, root) as MTreeViewItem<T>;
            OnClickItem(m_item);
        }

        protected MTreeViewItem<T> FindMTreeViewItem(int id)
        {
            TreeViewItem item = FindItem(id, root);
            if (item == null) return null;
            return item as MTreeViewItem<T>;
        }

        protected virtual void OnClickItem(MTreeViewItem<T> item)
        {
        }
        
        /// <summary>
        /// 拷贝字符串到剪贴板
        /// </summary>
        protected void CopyString(string value)
        {
            TextEditor textEditor = new TextEditor();
            textEditor.text = value;
            textEditor.OnFocus();
            textEditor.Copy();
        }
    }
}


EditorFerramentasJanelas

Entrada da janela de ferramentas, herdada do MEditorWindow. Para informações sobre o MEditorWindow, consulte o Projeto de Expansão do Editor 1.

using UnityEditor;
using UnityEditor.IMGUI.Controls;
using UnityEngine;

namespace S.Editor
{
    public class EditorToolsWindows : MEditorWindow
    {
        private string[] toolbarArray;
        private int toolbarIndex;
        private TreeViewState treeViewState_guiStyle;
        private MultiColumnHeader multiColumnHeader_guiStyle;
        private GUIStylesTreeView guiStyleTreeView;
        private GUIStyle[] customStyles;
        private static EditorToolsWindows window;

        [MenuItem("Tools/Unity工具")]
        static void OpenToolsWindow()
        {
            window=GetWindow<EditorToolsWindows>();
            window.Show();
        }

        private void OnEnable()
        {
            toolbarArray = GetToolbarArray();
            treeViewState_guiStyle=new TreeViewState();
            multiColumnHeader_guiStyle=CreateMultiColumnHeader();
            guiStyleTreeView = new GUIStylesTreeView(treeViewState_guiStyle,multiColumnHeader_guiStyle);
        }

        protected override void OnBodyGUI()
        {
            toolbarIndex = GUILayout.Toolbar(toolbarIndex, toolbarArray);
            switch (toolbarIndex)
            {
                case 0:
                    DrawGUIStyles();
                    break;
                case 1:

                    break;
            }
        }

        void DrawGUIStyles()
        {
            if (customStyles==null)
            {
                customStyles = GUI.skin.customStyles;
                foreach (GUIStyle style in customStyles)guiStyleTreeView.AddTreeViewItem(style,false);
                guiStyleTreeView.Reload();
            }
            guiStyleTreeView.OnGUI(new Rect(0,25,window.position.width,window.position.height));
        }
        
        public MultiColumnHeader CreateMultiColumnHeader()
        {
            MultiColumnHeaderState.Column[] columns =
            {
                new MultiColumnHeaderState.Column()
                {
                    headerContent = new GUIContent("GUIStyleName","GUI样式名字"),
                    width = 200,
                    minWidth = 100,
                    maxWidth = 300,
                },
                new MultiColumnHeaderState.Column()
                {
                    headerContent = new GUIContent("GUIStyle","GUI样式"),
                    width = 300,
                    minWidth = 200,
                    maxWidth = 400
                
                },
                new MultiColumnHeaderState.Column()
                {
                    headerContent = new GUIContent("",""),
                    width = 70,
                    maxWidth = 90,
                    minWidth = 50
                },
            };
            MultiColumnHeaderState state = new MultiColumnHeaderState(columns);
            MultiColumnHeader header = new MultiColumnHeader(state);
            return header;
        }
        
        string[] GetToolbarArray()
        {
            return new string[2] {"内置GUIStyle", "内置Icon"};
        }
    }
}

GUIStylesTreeView

Herdado do MTreeView, a restrição genérica é GUIStyle. Este TreeView é responsável por exibir as informações internas do GUIStyle.

using System;
using System.Collections.Generic;
using S.Editor;
using UnityEditor;
using UnityEditor.IMGUI.Controls;
using UnityEngine;

public class GUIStylesTreeView : MTreeView<GUIStyle>
{
    private MTreeViewItem<GUIStyle> selectedItem;
    private Vector2 infoScrollPos;
    private int leftBtnIndex;
    private GUIContent leftBtnContent;
    private GUIContent textColorContent;
    private SearchField searchField;
    public GUIStylesTreeView(TreeViewState state, MultiColumnHeader multiColumnHeader) : base(state, multiColumnHeader)
    {
    }

    protected override void OnInit()
    {
        base.OnInit();
        rowHeight = 30;
        showBorder = true;
        showAlternatingRowBackgrounds = true;
        useScrollView = true;
        leftBtnContent=new GUIContent();
        leftBtnContent.image = EditorGUIUtility.IconContent("Audio Mixer").image;
        textColorContent=new GUIContent("TextColor");
        searchField=new SearchField();
    }

    protected override bool DoesItemMatchSearch(TreeViewItem item, string search)
    {
        MTreeViewItem<GUIStyle> mItem = item as MTreeViewItem<GUIStyle>;
        return mItem.data.name.IndexOf(search, StringComparison.OrdinalIgnoreCase) >= 0;
    }

    private Rect viewAreaRect;
    private Rect infoAreaRect;
    private Rect searchAreaRect;
    
    public override void OnGUI(Rect rect)
    {
        searchAreaRect=new Rect(rect.x+rect.width*0.5f,rect.y,rect.width*0.5f,20);
        searchString=searchField.OnGUI(searchAreaRect,searchString);
        viewAreaRect=new Rect(rect.x,rect.y+20,rect.width,rect.height*0.7f);
        infoAreaRect=new Rect(rect.x,rect.y+viewAreaRect.height+searchAreaRect.height,rect.width,rect.height-viewAreaRect.height-searchAreaRect.height);
        base.OnGUI(viewAreaRect);
        OnInfoGUI(infoAreaRect);
    }

    void OnInfoGUI(Rect rect)
    {
        Rect leftRect = new Rect(infoAreaRect.x,infoAreaRect.y,80,infoAreaRect.height);
        GUILayout.BeginArea(leftRect,"","grey_border");
        OnLeftInfoGUI();
        GUILayout.EndArea();
        Rect rightRect = new Rect(infoAreaRect.x+leftRect.width,infoAreaRect.y,rect.width-leftRect.width,infoAreaRect.height);
        GUILayout.BeginArea(rightRect,"","grey_border");
        OnRightInfoGUI();
        GUILayout.EndArea();
    }

    void OnLeftInfoGUI()
    {
        if (leftBtnIndex == 0) EditorGUILayout.BeginHorizontal("InsertionMarker");
        else EditorGUILayout.BeginHorizontal();
        leftBtnContent.text = "详情";
        if (GUILayout.Button(leftBtnContent,EditorStyles.label))
        {
            leftBtnIndex = 0;
        }
        EditorGUILayout.EndHorizontal();

        if (leftBtnIndex == 1) EditorGUILayout.BeginHorizontal("InsertionMarker");
        else EditorGUILayout.BeginHorizontal();
        leftBtnContent.text = "预览";
        if (GUILayout.Button(leftBtnContent,EditorStyles.label))
        {
            leftBtnIndex = 1;
        }
        EditorGUILayout.EndHorizontal();
    }

    void OnRightInfoGUI()
    {
        if (selectedItem==null) return;
        if (leftBtnIndex==0)
        {
            infoScrollPos=EditorGUILayout.BeginScrollView(infoScrollPos);
            EditorGUILayout.LabelField($"Name: {selectedItem.data.name}");
            EditorGUILayout.LabelField($"Alignment: {selectedItem.data.alignment}");
            EditorGUILayout.LabelField($"Font: {selectedItem.data.font?.name}");
            EditorGUILayout.LabelField($"FontSize: {selectedItem.data.fontSize}");
            EditorGUILayout.LabelField($"FontStyle: {selectedItem.data.fontStyle}");
            EditorGUILayout.ColorField(textColorContent,selectedItem.data.normal.textColor,false,false,false);
            EditorGUILayout.LabelField($"ContentOffset: {selectedItem.data.contentOffset}");
            EditorGUILayout.LabelField($"FixedHeight: {selectedItem.data.fixedHeight}");
            EditorGUILayout.LabelField($"FixedWidth: {selectedItem.data.fixedWidth}");
            EditorGUILayout.LabelField($"LineHeight: {selectedItem.data.lineHeight}");
            EditorGUILayout.EndScrollView();
        }
        else
        {
            EditorGUILayout.LabelField("",selectedItem.data);
        }
    }

    protected override void CellGUI(Rect rect, MTreeViewItem<GUIStyle> item, int cowIndex)
    {
        switch (cowIndex)
        {
            case 0:
                GUI.Label(rect,item.data.name);
                break;
            case 1:
                rect.y += 5;
                GUIStyle style = item.data;
                GUIStyle st = new GUIStyle(style);
                float scale = 20/st.fixedHeight;
                st.fixedHeight *= scale;
                st.fixedWidth *= scale;
                GUI.Box(rect,"",st);
                break;
            case 2:
                rect.height = 20;
                rect.y += 5;
                if (GUI.Button(rect,"Copy"))CopyString(item.data.name);
                break;
        }
    }

    protected override void SelectionChanged(IList<int> selectedIds)
    {
        infoScrollPos = default;
        int id = selectedIds[0];
        var item = FindMTreeViewItem(id);
        selectedItem = item;
    }
}

Acho que você gosta

Origin blog.csdn.net/weixin_42498461/article/details/129145196
Recomendado
Clasificación