UI Tool Kit 使用

news2025/1/6 19:32:48

Unity 2021 已经把UIBuilder 内置了,项目组也打算 后续工具采用 toolkit来写,这边也是找了一下教程熟悉了一下。

UI 工具包 - Unity 手册

 首先 先创建一个EditorWindow

 会生成相应的C#,UXML,USS代码

 默认会把显示的MenuItem代码生成,以及Root VisualElement生成,会默认加载对应的uxml文件。

 [MenuItem("Tools/TestTool")]
    public static void ShowExample()
    {
        TestTool wnd = GetWindow<TestTool>();
        wnd.titleContent = new GUIContent("TestToolPanel");
    }

public void CreateGUI()
    {
        // Each editor window contains a root VisualElement object
        VisualElement root = rootVisualElement;

        // VisualElements objects can contain other VisualElement following a tree hierarchy.
        VisualElement label = new Label("Hello World! From C#");
        root.Add(label);

        // Import UXML
        var visualTree = AssetDatabase.LoadAssetAtPath<VisualTreeAsset>("Assets/Cube/delete.uxml");
        VisualElement labelFromUXML = visualTree.Instantiate();
        root.Add(labelFromUXML);

        // A stylesheet can be added to a VisualElement.
        // The style will be applied to the VisualElement and all of its children.
        var styleSheet = AssetDatabase.LoadAssetAtPath<StyleSheet>("Assets/Cube/delete.uss");
        VisualElement labelWithStyle = new Label("Hello World! With Style");
        labelWithStyle.styleSheets.Add(styleSheet);
        root.Add(labelWithStyle);
    }

新的方式 是通过 像Root 结点添加 各种组件的方式,可以在 UIBuilder面板上操作,也可以代码添加。

 代码添加:

 var rightPart = root.Q<VisualElement>("right");
 HelpBox tipBox = new HelpBox("Test Tip", HelpBoxMessageType.Info);   
 rightPart.Add(tipBox);

想使用 面板上的 结点可以采用代码查找Name的方式:

 _objFiled = root.Q<ObjectField>("ObjectField");

 还可以给某些组件 添加事件,比如 Toggle

toggle.RegisterValueChangedCallback(TogValueChanged);

 private void TogValueChanged(ChangeEvent<bool> evt)
 {
     // evt.newValue
 }

按钮组件的 事件 绑定:

_createBtn = root.Q<Button>("CreateBtn");
_createBtn.clicked += CreateEvent;

ListView组件的使用:

 _leftList = root.Q<ListView>("LeftListView");
 //赋值
 _leftList.itemsSource = _objs;
//单个Item
 _leftList.makeItem = MakeListItem;
//数据绑定
 _leftList.bindItem = BindListItem;
   //List Item 选中事件
 _leftList.onSelectionChange += OnSelectChange;

新版UI 也支持 IMGUI嵌入

//嵌入IMGUI 
 rightPart.Add(new IMGUIContainer(() =>
  {
            if (GUILayout.Button("TestBtn"))
            {
                Debug.Log("TestLog");
            }
            
   }));              

支持计时器任务:

//计时器(默认 打开界面 就会执行)
        var scheduleItem = root.schedule.Execute(() =>
        {
            Debug.Log("Schedule Event");
        });
//间隔2秒执行一次
        //scheduleItem.Every(2000);
        //打开页面之后延迟两秒执行
        //scheduleItem.ExecuteLater(2000);

 完整代码:


    //打开页面执行一次
    public void CreateGUI()
    {
        // Each editor window contains a root VisualElement object
        VisualElement root = rootVisualElement;

        // Import UXML
        var visualTree = AssetDatabase.LoadAssetAtPath<VisualTreeAsset>("Assets/Editor/Test/TestTool.uxml");
        VisualElement labelFromUXML = visualTree.Instantiate();
        root.Add(labelFromUXML);
        var rightPart = root.Q<VisualElement>("right");
        HelpBox tipBox = new HelpBox("Test Tip", HelpBoxMessageType.Info);
        
        rightPart.Add(tipBox);
        _objFiled = root.Q<ObjectField>("ObjectField");
        if (_objFiled != null)
        {
            _objFiled.objectType = typeof(GameObject);
            _objFiled.allowSceneObjects = false;
            //注册一个回调 当有变化的时候
            _objFiled.RegisterValueChangedCallback((obj) => { Debug.Log(obj.newValue.name); });
        }

        _createBtn = root.Q<Button>("CreateBtn");
        _createBtn.clicked += CreateEvent;
        _refreshBtn = root.Q<Button>("RefreshBtn");
        _refreshBtn.clicked += RefreshEvent;

        _leftList = root.Q<ListView>("LeftListView");
        
        _leftList.onSelectionChange += OnSelectChange;

        _nameText = root.Q<TextField>("NameTextField");
        _posText = root.Q<Vector3Field>("PosField");
       //数据绑定
        _nameText.bindingPath = "m_Name";
        _posText.bindingPath = "m_LocalPosition";

        //嵌入IMGUI 
        rightPart.Add(new IMGUIContainer(() =>
        {
            if (GUILayout.Button("TestBtn"))
            {
                Debug.Log("TestLog");
            }
            
        }));

        //计时器(默认 打开界面 就会执行)
        var scheduleItem = root.schedule.Execute(() =>
        {
            Debug.Log("Schedule Event");
        });

        //间隔2秒执行一次
        //scheduleItem.Every(2000);
        //打开页面之后延迟两秒执行
        //scheduleItem.ExecuteLater(2000);
    
    }

    private void OnSelectChange(IEnumerable<object> obj)
    {
        foreach (var item in obj)
        {
            GameObject go = item as GameObject;
            Selection.activeGameObject = go;
            SerializedObject serializedObj = new SerializedObject(go);
            _nameText.Bind(serializedObj);
            SerializedObject serializedTrans = new SerializedObject(go.transform);
            _posText.Bind(serializedTrans);
        }
    }

    private void BindListItem(VisualElement arg1, int index)
    {
        Label label = arg1 as Label;
        var go = _objs[index];
        label.text = go.name;
    }

    private VisualElement MakeListItem()
    {
        var label = new Label();
        label.style.unityTextAlign = TextAnchor.MiddleCenter;
        label.style.marginLeft = 5;
        return label;
    }

    private void CreateEvent()
    {
        if (_objFiled.value == null)
        {
            return;
        }
        GameObject prefab = _objFiled.value as GameObject;
        GameObject obj = Instantiate(prefab);
        obj.transform.position = new Vector3(Random.Range(0, 10), 0, Random.Range(0, 10));
    }

    private void RefreshEvent()
    {
        Scene currentScene = SceneManager.GetActiveScene();
        _objs = currentScene.GetRootGameObjects();
        _leftList.itemsSource = _objs;
        _leftList.makeItem = MakeListItem;
        _leftList.bindItem = BindListItem;
    }

   

同时UIToolKit 也支持 脚本编辑器扩展:

[CustomEditor(typeof(TestCube))]
public class TestCubeEditor : Editor
{

    public override void OnInspectorGUI()
    {
        base.OnInspectorGUI();
    }

    //该函数优先级大于上面
    public override VisualElement CreateInspectorGUI()
    {
        //return base.CreateInspectorGUI();
        VisualElement root = new VisualElement();
        Button testBtn = new Button();
        testBtn.style.width = 200;

        root.Add(testBtn);

        Label testLabel = new Label("TestLabel");

        root.Add(testLabel);

        Toggle tog = new Toggle();
        root.Add(tog);

        return root;
    }

}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/656194.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

记录--设计一个可选择不连续的时间范围的日期选择器

这里给大家分享我在网上总结出来的一些知识&#xff0c;希望对大家有所帮助 npm包&#xff1a;sta-datepicker效果图 需求 普通的时间选择器要么只能单选&#xff0c;要么只能选范围&#xff0c;不可以随意选择若干个时间&#xff0c;同时大多数现成的时间选择器选择结束会收起…

EasyExcel实战与笔记

概述 Excel导入导出是业务开发中非常常见的需求。本文记录一下如何快速入门使用EasyExcel&#xff0c;深度实战&#xff0c;以及遇到的问题。 入门 使用EasyExcel导入如下依赖即可&#xff1a; <dependency><groupId>com.alibaba</groupId><artifactI…

java-代码生成器——有了代码生成器两个小时的工作量2分钟完成了

代码生成器 &#x1f942;代码生成器&#x1f33b;1. 第一步引用相关依赖&#x1f357;2. 第二步编写代码 CodeGet.java&#x1f969;3. 第三步运行查看结果&#x1f356;4. 第四步总结一下 &#x1f942;代码生成器 只需要创建好表的结构&#xff0c;代码生成器通过简单的配置…

Linux知识点 -- 进程控制(二)

Linux知识点 – 进程控制&#xff08;二&#xff09; 文章目录 Linux知识点 -- 进程控制&#xff08;二&#xff09;一、进程程序替换1.概念2.替换原理3.进程替换的操作4.使用exec函数执行自己写的程序5.使用exec函数执行其他语言的程序 二、编写一个简易的shell 一、进程程序替…

LeetCode 892. Surface Area of 3D Shapes【数组,数学】简单

本文属于「征服LeetCode」系列文章之一&#xff0c;这一系列正式开始于2021/08/12。由于LeetCode上部分题目有锁&#xff0c;本系列将至少持续到刷完所有无锁题之日为止&#xff1b;由于LeetCode还在不断地创建新题&#xff0c;本系列的终止日期可能是永远。在这一系列刷题文章…

KCC@北京启动,为一个城市做好开源!

KCC&#xff08;开源社城市社区&#xff09;北京区在6月12日正式成立&#xff0c;吸引了众多开源爱好者和技术开发者参与。现场举行的活动围绕 “为一个城市做好开源” 的话题展开讨论&#xff0c;包括开发者关系、开源背后的无用之用、开源在中国的变化、开源的困难与挑战以及…

OpenAI ChatGPT 使用示例

1.编程应用 1.1. 生成例子代码 ChatGPT帮助我们生产我们需要的例子代码。而且准确率很高。即使你不懂某一种语言也没关系&#xff0c;一定程度上较低了程序员的的门槛。 我有三组数据&#xff0c;第一组是星期一到星期五&#xff0c;第二组是这一天的具体时间&#xff0c;第三…

etcd 备份操作---马哥教育

etcd安装&#xff1a; mkdir -pv etcd-download-test tar -zxvf etcd-v3.4.4-linux-amd64.tar.gz -C etcd-download-test/ 编辑修改系统环境变量 /etc/profile export ETCD_HOME/tmp/etcd-download-test/etcd-v3.4.4-linux-amd64 export PATH$PATH:$JAVA_HOME/bin:$ETCD_HOM…

html实现好看的个人介绍,个人主页模板2(附源码)

文章目录 1.设计来源1.1 主界面1.2 关于我界面1.3 项目演示界面1.4 联系我界面 2.效果和源码2.1 动态效果2.2 源代码2.3 源码目录 源码下载 作者&#xff1a;xcLeigh 文章地址&#xff1a;https://blog.csdn.net/weixin_43151418/article/details/131257976 html实现好看的个人…

老胡的周刊(第095期)

老胡的信息周刊[1]&#xff0c;记录这周我看到的有价值的信息&#xff0c;主要针对计算机领域&#xff0c;内容主题极大程度被我个人喜好主导。这个项目核心目的在于记录让自己有印象的信息做一个留存以及共享。 &#x1f3af; 项目 tabby[2] 自托管的 AI 编码助手&#xff0c;…

230617安装SqlServer2017Express后,再安装一个SqlServer2017ExpressAdvanced

230616安装SqlServer2017Express 下载地址 选择语言 Microsoft SQL Server 2017 Express 下载地址: 简体中文 感谢下载 Microsoft SQL Server 2017 Express 获得下载软件 我将下载的文件的名称加上了SHA256值, 一长串 是一个 .exe 的自解压文件, 双击后,默认解压到同根文件夹…

计组期末模拟(补充)

单选题 2-1&#xff08;本题考查课程目标2&#xff09; 某计算机有 16 个通用寄存器&#xff0c;采用 32 位定长指令字&#xff0c;操作码字段&#xff08;含寻址方式位&#xff09;为 8 位&#xff0c;Store 指令的源操作数和目的操作数分别采用寄存器直接寻址和基址寻址方式…

PHP intval()函数详解,intval()函数漏洞原理及绕过思路

「作者主页」&#xff1a;士别三日wyx 「作者简介」&#xff1a;CSDN top100、阿里云博客专家、华为云享专家、网络安全领域优质创作者 「推荐专栏」&#xff1a;对网络安全感兴趣的小伙伴可以关注专栏《网络安全入门到精通》 intval 一、进制自动转换二、转换数组三、转换小数…

#systemverilog# 之 event region 和 timeslot 仿真调度(三)Verdi 辅助查看

前面的几篇文章,我们对SV仿真调度进行了理论分析和实战演练。那么工具厂商,对该类问题有没有提供相应的支持。这个应该是肯定的。因为我们知道,SV只是出于定义标准的角度,规定了仿真调度事件原理。但是具体实施细节,应是每家EDA仿真工具厂商根据自家的软件开发算法而定的。…

MySQL - 第3节 - MySQL数据类型

1.数据类型的作用 数据类型的作用&#xff1a; • 决定了存储数据时应该开辟的空间大小。 • 决定了如何识别一个特定的二进制序列。 • 决定了数据的取值范围。 2.数据类型分类 注&#xff1a;MySQL本身是不支持bool类型的&#xff0c;当把一个数据设置成bool类型时&#xff0…

NetMock 简介:简化 Java、Android 和 Kotlin 多平台中的 HTTP 请求测试

NetMock 简介&#xff1a;简化 Java、Android 和 Kotlin 多平台中的 HTTP 请求测试 NetMock可让我们摆脱在测试环境中模拟请求和响应的复杂性。 NetMock是一个功能强大、用户友好的库&#xff0c;旨在简化模拟HTTP请求和响应的过程。 对开发者来说&#xff0c;测试HTTP请求经…

稳定?国企也裁员!

大家好&#xff0c;我是爱搞事情的了不起&#xff01; 我所在的公司是一家央企下面的子公司&#xff0c;号称“国企”。 提起国企&#xff0c;好多人的印象中是855不加班&#xff0c;不裁员&#xff0c;真实情况是这样吗&#xff1f; 当国企领导 去年过年聚会&#xff0c;一个部…

《微服务架构设计模式》第二章 服务的拆分策略

内容总结自《微服务架构设计模式》 服务的拆分策略 一、架构是什么软件架构的41视图模型为什么重要分层架构风格 二、定义微服务如何定义服务拆分难点定义服务API 一、架构是什么 软件架构的定义&#xff1a;计算机系统的软件架构是构建这个系统所需要的一组结构&#xff0c;包…

内参:美联储下半年加息时间表和路径

* * * 原创&#xff1a;刘教链 * * * 星球会员请直接转到知识星球查看全文&#xff1b; 普通读者可以微信付费查看本篇全文&#xff0c;也欢迎加入星球。 加入星球&#xff0c;解锁全年365天内参全文阅读权限 &#xff08;年费制 折合仅1.6元/天&#xff09; 6.15教链内参&…

redis锁

一、redis锁的实现 加锁命令&#xff1a; SETNX key value&#xff1a; 当键不存在时&#xff0c;对键进行设置操作并返回成功1&#xff0c;否则返回失败0。 Key是锁的唯一标识&#xff0c;一般按业务来决定命名&#xff1b; Value 往往用来比较加锁的是哪一个线程或者哪一个…