当前位置: 首页 > article >正文

Unity编辑拓展显示自定义类型

        配合自定义特性或着header可以添加注解

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEditor;
using System.Reflection;
using System;
using Unity.VisualScripting;

#if UNITY_EDITOR

public class EditorRender
{
    public static Enum RenderEnum(FieldInfo fieldInfo, Enum value, Type type, params GUILayoutOption[] style)
    {
        var array = Enum.GetValues(type);// 直接使用  Enum[] EnumValueArr =   (Enum[])Enum.GetValues(type);  不行,这里不能用enum,存在类型转换异常,只能指定枚举类型
        Enum[] EnumValueArr = new Enum[array.Length];
        for (int i = 0; i < array.Length; i++)
        {
            EnumValueArr[i] = (Enum)Enum.Parse(type, array.GetValue(i).ToString());
        }
        int[] IntValueArr = new int[EnumValueArr.Length];
        string[] EnumDescArr = new string[EnumValueArr.Length];

        for (int i = 0; i < EnumValueArr.Length; i++)
        {
            Enum e = EnumValueArr[i];
            IntValueArr[i] = (int)Enum.Parse(type, e.ToString());
            var field = type.GetField(e.ToString());
            HeaderAttribute header = field.GetAttribute<HeaderAttribute>();
            if (header != null)
            {
                EnumDescArr[i] = header.header;
            }
            else
            {
                EnumDescArr[i] = "未定义";
            }
        }
        int selectValue = (int)Enum.Parse(type, value.ToString());
        selectValue = EditorGUILayout.IntPopup(selectValue, EnumDescArr, IntValueArr, style);
        value = (Enum)Enum.Parse(type, selectValue.ToString());
        return value;
    }

    public static object RenderValue(FieldInfo fieldInfo, Type type, object value, object defaultValue = null, params GUILayoutOption[] style)
    {
        SetDefaultValue(type, ref value, defaultValue);

        if (type == typeof(int))
        {
            return EditorGUILayout.IntField(int.Parse(value.ToString()), style);
        }
        else if (type == typeof(float))
        {
            return EditorGUILayout.FloatField(float.Parse(value.ToString()), style);
        }
        else if (type == typeof(long))
        {
            return EditorGUILayout.LongField(long.Parse(value.ToString()), style);
        }
        else if (type == typeof(string))
        {
            return GUILayout.TextArea(value as string, style);
        }
        else if (type == typeof(bool))
        {
            return GUILayout.Toggle(bool.Parse(value.ToString()), "", style);
        }
        else if (type.IsEnum)
        {
            value = EditorRender.RenderEnum(fieldInfo, (Enum)value, type, style);
            return value;
        }
        else if (value is IList)
        {
            value = RenderList(type.GetGenericArguments()[0], value as IList);
            return value;
        }
        if (value == null)
        {
            return Activator.CreateInstance(type);
        }


        return null;
    }

    public static object RenderList(Type type, IList list)
    {
        if (list == null)
        {
            return Activator.CreateInstance(typeof(List<>).MakeGenericType(type));
        }
        for (int i = 0; i < list.Count; i++)
        {

            list[i] = RenderValue(null, type, list[i], style: GUILayout.MaxWidth(400));
            if (GUILayout.Button("X", GUILayout.MaxWidth(50)))
            {
                list.RemoveAt(i);
                GUILayout.EndHorizontal();
                break;
            }
        }
        GUILayout.BeginHorizontal();
        GUILayout.FlexibleSpace();
        if (GUILayout.Button("Add", GUILayout.MaxWidth(500)))
        {
            list.Add(Activator.CreateInstance(type));
        }
        GUILayout.EndHorizontal();
        return list;

    }

    public static void SetDefaultValue(Type type, ref object value, object defaultValue)
    {
        if (value == null || string.IsNullOrEmpty(value.ToString()))
        {
            if (defaultValue != null)
            {
                value = defaultValue;
                return;
            }
            if (type == typeof(int))
            {
                value = 0;
            }
            else if (type == typeof(float))
            {
                value = 0;
            }
            else if (type == typeof(long))
            {
                value = 0;
            }
            else if (type == typeof(Single))
            {
                value = 0;
            }
            else if (type == typeof(string))
            {
                value = string.Empty;
            }
            else if (type == typeof(bool))
            {
                value = false;
            }
            else if (type == typeof(Vector3))
            {
                value = Vector3.zero;
            }
            else if (type == typeof(Vector2))
            {
                value = Vector2.zero;
            }
            else if (type.IsEnum)
            {

            }
        }
    }

    public static object RenderField(FieldInfo fieldInfo, HeaderAttribute header, object obj, params GUILayoutOption[] style)
    {
        GUILayout.BeginHorizontal(GUI.skin.button);

        GUILayout.BeginVertical();
        Type t = fieldInfo.FieldType;
        GUILayout.Label($"{fieldInfo.Name}({t.Name})");

        if (header!= null)
        {
            GUILayout.Label(header.header);
        }
        GUILayout.EndVertical();

        
        var value = RenderValue(fieldInfo, t, obj, style: style);
        GUILayout.EndHorizontal();

        return value;
    }

    public static object RenderObject(object value)
    {
        var propertyInfos = value.GetType().GetFields();
        for (int i = 0; i < propertyInfos.Length; i++)
        {
            var property = propertyInfos[i];
            object obj = property.GetValue(value);
            obj = EditorRender.RenderField(property, null, obj, GUILayout.MaxWidth(400));
            property.SetValue(value, obj);

            GUILayout.Space(5);
        }


        return value;
    }
}

#endif

        使用方式,直接调用RenderObject就行

    private class CustomClass
    {
        public string Name;
        public int Age;
        public bool Sex;
    }
    private CustomClass m_CustomClass;


    private void OnGUI()
    {
        m_CustomClass = (CustomClass)EditorRender.RenderObject(m_CustomClass);
    }

        这里用的都是变量,如果使用属性的话,将获取属性,获取属性值,写入属性值的方式修改源代码即可,RenderValue里如果有未定义其他类型,记得补充


http://www.kler.cn/a/513672.html

相关文章:

  • Linux——信号量和(环形队列消费者模型)
  • 人工智能之深度学习_[3] -PyTorch自动微分模块和构建线性回归模型
  • AI 新动态:技术突破与应用拓展
  • 大数据学习(37)- Flink运行时架构
  • 【机器学习实战入门】使用OpenCV进行性别和年龄检测
  • mybatis的多对一、一对多的用法
  • JAVA:Spring Boot 实现责任链模式处理订单流程的技术指南
  • Java设计模式 十二 享元模式 (Flyweight Pattern)
  • 【GitHub】登录时的2FA验证
  • 简识JVM栈中的程序计数器
  • CPU狂飙900%如何分析?怎么定位?怎么溯源处理
  • C语言 结构体
  • 2024年度总结-CSDN
  • 图片专栏——修改分辨率
  • SSTI注入
  • 【vim】vim编辑器如何设置行号
  • 【2024年终总结】我与CSDN的一年
  • 5、原来可以这样理解C语言_数组(5)sizeof 计算数组元素个数
  • 数字图像处理:实验五
  • Golang的文件处理优化策略
  • WPF 实现动态属性绑定与动态绑定详解
  • springboot 配置多数据源以及动态切换数据源
  • Excel 技巧15 - 在Excel中抠图头像,换背景色(★★)
  • 利用大型语言模型在量化投资中实现自动化策略
  • 洛谷P2853 [USACO06DEC] Cow Picnic S
  • 如何查看某用户的Git提交数