首页 > 其他分享 >UI Toolkit进阶 - Template模板

UI Toolkit进阶 - Template模板

时间:2024-04-09 17:35:33浏览次数:24  
标签:界面 -- 元素 Toolkit UI Template 节点

上篇文章我们介绍了UI Toolkit,但是没有深入它的用法。本文就以一个项目界面从UGUI到UI Toolkit的改造过程为例,来学习一下较高阶的使用方法。

首先介绍一下本次的项目MarkovCraft,这个项目是在MarkovJunior基础上的一个二次开发,把原项目放在了Unity中,让用户在三维环境中看到动态的生成过程,并且加了一些导出的功能。那本次要改造的界面就是这个项目里面的模型预览面板,用于展示xml模型里面定义的生成流程。每个流程序列由一系列的节点(Node)或者说元素(Element)组成,其中像序列节点等特殊节点还可以包含子节点,形成嵌套结构。现有的UGUI实现能够实现功能,但是在处理较长模型的时候会生成大量UI GameObject引起严重的性能问题,所以本文考虑使用UI Toolkit对它重新进行实现。

从结构来讲,模型xml文档的结构与uxml界面文档的结构是很类似的,几乎可以一一对应过来,这就为我们的设计实现提供了很大的方便。从这个意义上讲,拿UI Toolkit实现要比之前拿UGUI来实现更合适,我们只需要将每种xml元素转换为对应的uxml元素即可。

为了方便讨论,我在这里贴一个简单的模型示例,右图是现有的UGUI实现显示出来的效果:

<!-- BacktrackerCycle.xml -->

<sequence values="BRGWA" origin="True">
  <union symbol="?" values="WA"/>
  <markov>
    <one in="RBB" out="GGR"/>
    <one in="RGG" out="WAR"/>
  </markov>
  <one in="R" out="W"/>
  <one in="WBW" out="WAW" steps="1"/>
  <all in="BBB/B?B" out="***/*B*"/>
  <all in="A" out="W"/>
</sequence>

我们先把模型中允许出现的所有类型的节点汇总一下,左侧是所有类型的节点对应C#类的继承树,右边括号里是节点在xml中的元素名:

Markov Junior Nodes Hierarchy
=============================

Node
|
|--Branch
|  |--MapNode               (map)
|  |--SequenceNode          (sequence)
|  |--MarkovNode            (markov)
|  |--WFCNode               (wfc)
|     |--OverlapNode           (+sample)
|     |--TileNode              (+tileset)
|
|--RuleNode
|  |--AllNode               (all)
|  |--OneNode               (one)
|  |--ParallelNode          (prl)
|
|--PathNode                 (path)
|--ConvChainNode            (overlap)
|--ConvolutionNode          (convolution)

=============================

其中,继承自Branch类的节点(mapseqeunce等),是能够包含子节点的,而其他的节点不能。继承自Rule类的几种节点(alloneprl)类似,都是替换节点,属性基本相同,后续可以共用一个UI模板,而不用每个各用各的。

我们分别把每种节点的界面做出来,界面的外观与原来的UGUI保持一致。以Rule Node为例,界面包含了节点名称的Label和为后续填充节点规则预留的槽位。这里可以临时加一个占位符元素看看节点的尺寸能不能正确地自适应,如图:

005_02.png

其中要指定元素为文档中的槽位(插入子元素的位置),只需要给该元素加一个 content-container属性即可,属性值任意填什么都可以。每种节点做完之后,可以手搓一个假的示例看一下带有嵌套结构整体的效果,验证一下各个节点的布局自适应有没有问题:

005_03.png

到这个地方,我们的文档资源就准备好了,接下来开始改代码。我在重制这部分代码的时候,并没有直接把原来的那套代码改掉,而是另外做了一套新的代码,和之前的实现平行存在,互不干涉。这样做有几个好处,一个是新版和旧版可以直接放在一起跑,可以很方便地进行比较,再一个就是写新的这套代码的时候可以很方便地去参考旧的代码,顺便找找之前的代码有没有什么小bug。这两套代码在逻辑上面基本一致,改起来工作量不大,这里说几个比较大的区别:

因为UI Toolkit中的界面元素不再是GameObject,所以我们对每个界面元素附加的C#对象也不再是组件的形式,故Node类就不再继承自MonoBehaviour类了。不过在之前的实现中,这些Node对象就是放在列表里面统一进行更新的,所以更新逻辑这一块完全不用修改,只需把创建和获取节点对象的代码进行相应修改即可。创建节点对象原来的做法是在节点的Prefab里面预先挂好对应的节点脚本,实例化Prefab之后使用GetComponent来获取节点脚本组件。而本次的做法是先拿到界面元素,然后把界面元素作为参数传给节点对象的构造函数,并且把这个引用保存在节点元素里面,类似下面这样。这种方式更符合面向对象编程的一般写法,而且无需像原来那样获取脚本组件,效率更高一些。

public class BaseGraphNodeV2
{
  // ...

  protected readonly VisualElement? m_NodeElement;

  public BaseGraphNodeV2(VisualElement nodeElement)
  {
      m_NodeElement = nodeElement;
  }

  // ...
}

更多的细节可以参考本次更新的commit,这里不再赘述。把代码修改完之后,就可以进行整体测试了。最终实现的视觉效果跟原来还是有稍许差异,但是不影响使用,所以也就不再过多纠结了。最后附一张改造前和改造后的合影:

005_04.png

标签:界面,--,元素,Toolkit,UI,Template,节点
From: https://www.cnblogs.com/devbobcorn/p/18083755

相关文章

  • AI进行元素识别和文字识别实现UI自动化测试
    【背景】一般移动端APP会有页面元素属性,比如:ID,ClassName,Text等,可以方便定位需要操控的元素控件。而这类的UI控件识别框架的结果输出往往依赖于开发同学在代码中对控件元素进行合理有效的命名,且一旦这些控件元素被混淆后就很难进行有效的元素定位。为了降低每个版本UI元素的层级等......
  • .NET CORE中Applicationbuilder的Use和Run方法有什么区别
    .NETCORE中Applicationbuilder的Use和Run方法有什么区别?Applicationbuilder:用于构件应用程序的中间件管道。Use额Run是用来配置中间件和构建管道。Use方法:用于添加中间件到管道中,并指定中间件的处理逻辑,可以多次调用,按照调用顺序一次添加多个中间件。Use方法通常用于添加通用......
  • vue使用docxtemplater导出word
    安装//安装docxtemplaternpminstalldocxtemplaterpizzip--save//安装jszip-utilsnpminstalljszip-utils--save//安装jszipnpminstalljszip--save//安装FileSavernpminstallfile-saver--save//引入处理图片......
  • 谷芦语(Guruica)入门
    简介谷芦语(Guruica)印度尼西亚爪哇岛的中爪哇省山区的谷芦村(guru)的语言,在主要城市梭罗(Surakarta)的东北部。相传当时第一个荷兰探险者进入谷芦村后,指着一个村民询问这是哪里。村民以为是问他是谁,就说“我吗?”(guruauru?),因此此地就被称为guru了。另一说法是村民对探险者打招呼,说......
  • 鸿蒙HarmonyOS实战-ArkUI组件(Video)
    ......
  • GUI development with Rust and GTK4 阅读笔记
    简记这是我第二次从头开始阅读,有第一次的印象要容易不少。如果只关心具体的做法,而不思考为什么这样做,以及整体的框架,阅读的过程将会举步维艰。简略记录gtk-rs的书中提到的点。对同一个问题书中所演示了多种处理方法,而且跨度比较大,第一次阅读的时候经常出现忘记之前的内容。f......
  • PostgreSQL中json_build_object的用法
    在PostgreSQL数据库中,有时我们需要将多个字段合并成一个JSON对象,并将其用于保存或传输数据。json_build_object函数可用于将指定的键值对合并为一个JSON对象。该函数的语法如下:sqljson_build_object(keytext,valueany[,...])其中,key是JSON对象中的键名,可以是......
  • 开发Element-UI的Table 组件列显示隐藏,列表数据勾选批量导出/全量导出,显示导出进度并
    #用法<TabColDisplay:total="total"api-url="hgp/order"api-name="hgpLocalList":s-param="listQuery":select-ids="selIds"title="快速......
  • CEF编译报错:ValueError: path is on mount '\\\\tab_group_types.mojom-webui.js'
    F:\code\chromium_git\chromium\src>autoninja-Cout\Debug_GN_x64cef"f:\code\depot_tools\bootstrap-2@3_11_6_chromium_30_bin\python3\bin\python3.exe"F:\code\depot_tools\ninja.py-Cout\Debug_GN_x64cef-j10ninja:Enteringdirec......
  • .net maui blazor路由和导航,传参,刷新
    .netmauiblazor路由和导航,传参,刷新参考:https://learn.microsoft.com/zh-cn/aspnet/core/blazor/fundamentals/routing?view=aspnetcore-8.0页面:TestPage1.razor:@page"/test1/{Text}"<p>必填参数:@Text</p>@code{[Parameter]publicstring?Text{get;......