DUI3xxx · 语义
语法没错,但这棵树对不上:重复的 id、未知的类型。
本页由 scripts/diagnostics/sync.py 从插件的码表(EDreamUIDiagnosticCode)生成,卡片里的枚举名就是测试断言用的那个名字。
DUI3001
错误枚举名DuplicateNodeId
两个用了同一个 id 的节点。
怎么会出现:id 是节点的身份:它同时是 guid、类成员变量名、绑定的键和本地化键。比较不区分大小写,因为它最终变成一个 FName。重复的 id 永远不会被悄悄改成 OkBtn_1,那样会让你的绑定悄悄指向另一个节点。slot 和控件共用这个命名空间,所以两个同名的 slot、一个和控件同名的 slot 也是这个码;宿主里填充组件 slot 的 slot Detail { … } 不算。
Widget Root {
Text Title { Text = "Settings" }
Text title { Text = "Audio" }
}怎么改:给其中一个改名;如果冲突来自一次改名,用 (was: …) 让下一次编译把引用迁移过去。
DUI3002
错误枚举名InvalidNodeId
一个不是标识符、以数字开头或者是关键字的 id。
怎么会出现:id 要能当 C++ 标识符:字母、数字和 _,不以数字开头(ASCII 以外的字符算字母,所以 id 可以是中文)。2ndPanel 会被拒绝,因为生成的类会把它声明成 _2ndPanel,照着文件里的名字写的绑定就全都对不上。class、style、resources、slot、for、each、in、was、use、timeline、external、ease 是关键字,不能当节点 id 或 slot 名;超过 FName 长度的 id 也报这个码。
Widget Root {
Text 2ndLine { }
Text external { }
}怎么改:换一个以字母或 _ 开头、不是关键字的 id,比如 SecondLine。
DUI3003
错误枚举名UnknownNodeType
一个既不是标签、容器、别名、注册控件,也不是路径的节点类型。
怎么会出现:节点类型按顺序解析:内置标签(Text、Image 等)、布局容器(VerticalBox 等)、use … as 给出的组件别名、注册标签(Native.Button 等)、资产路径(以 / 开头)。都对不上就报这个码;对带作用域或命名空间的名字,消息会列出那里实际有哪些。
Widget Root {
Txt Title { Text = "Settings" }
}怎么改:修正拼写;组件先用 use "…" as Name 引进来,或者写它的完整资产路径。
DUI3004
错误枚举名UnknownStyle
一个指向这个文件看不到的样式的 : Name。
怎么会出现:节点的样式子句或者样式的基类,用了一个既没有在本文件声明、也没有被 use 带进来的样式名。样式可以写在戴它的节点下面,先后不影响。带命名空间的名字(nier.Label)如果命名空间本身没被声明,报的是 DUI3021 而不是这个码。
style Caption { FontSize = 14 }
Text Note : Captoin { Text = "Ready" }怎么改:修正样式名,或者 use 声明了它的那个库。
DUI3005
错误枚举名DuplicateStyle
同一个文件里的两个同名样式。
怎么会出现:本地样式可以遮蔽导入的同名样式,但两个本地样式同名时,构建器和写回器可能对“一个节点到底拿到了哪些属性”得出不同的答案,所以第二个被拒绝。
style Caption { FontSize = 14 }
style Caption { FontSize = 12 }
Text Note : Caption { Text = "Ready" }怎么改:合并成一个,或者改名其中一个;要在一个样式上做变体,用继承,比如 style Small : Caption。
DUI3006
错误枚举名UnknownBehaviourClass
一个指向控件无法携带的东西的 + Name。
怎么会出现:+ 后面的类名会依次加上插件的前缀去找(UIButton 和 Button 都能找到按钮行为),也可以写 /Script/Module.Class 全路径;找不到一个行为、布局容器或 layout-self 对象时报这个码。样式里的 + 行也一样。
Widget Confirm {
+ UIButon { TransitionType = None }
}怎么改:修正类名,或者写出完整的 /Script/… 路径。
DUI3007
错误枚举名DuplicateSlotName_Retired
这个码已经退役、从不报出,两个同名 slot 现在报 DUI3001。
DUI3008
警告枚举名ShadowedLoopVariable
一个遮蔽了外层循环变量的循环变量(警告)。
怎么会出现:嵌套的 for / each 用了和外层一样的变量名。它只是警告,因为遮蔽本身改变不了构建出来的树。不过循环本来就不能嵌套:构建时内层循环会被 DUI5021 或 DUI5012 拒绝。
VerticalBox Groups {
for Item in GetGroups() {
VerticalBox Group {
for Item in GetEntries() {
Text Entry { Text <- Item.Name }
}
}
}
}怎么改:内层换一个变量名;更要紧的是把内层循环放进一个组件,由组件自己的文件去循环,列表经由它的 props 传进去。
DUI3009
错误枚举名ParentRefusedChild
一个不肯接受这个子节点的父节点:已经满了的内容控件,或者被填了两次的命名 slot。
怎么会出现:节点没问题,父节点也没问题,只是这一对不行。SizeBox、ScaleBox、SafeZone、Border 只放一个子节点;命名 slot 只放一个控件,同一个 slot 也不能填两次;嵌套成环同样被拒绝。挂接时多出来的子节点会被悄悄丢掉,没有这个码,你会得到一棵少了一截的树,而那一截明明就写在你的文件里。
SizeBox Box {
Text A { Text = "One" }
Text B { Text = "Two" }
}怎么改:把几个子节点放进一个容器(比如 VerticalBox { … })再放进去;需要一个 slot 放多个控件时,在声明里给它一个布局容器。
DUI3010
错误枚举名RenameOldIdStillInUse
一个 (was: X),而 X 仍然是这个文件里某个节点的 id。
怎么会出现:你把节点从 X 改了名,又新建了一个叫 X 的节点。“把指向 X 的东西都搬过来”会把引用从一个确实存在、也需要它们的节点上搬走,所以拒绝;而且整个文件的迁移都不做,因为迁移了一半的文件比没迁移的更糟:下一次编译就不再从作者写下的样子出发了。
Widget Root {
Text Title (was: Heading) { Text = "Settings" }
Text Heading { Text = "Audio" }
}怎么改:先给另一个节点改名,或者删掉 (was: Heading)。
DUI3011
错误枚举名DuplicateWasId
两个都声称 (was: X) 的节点。
怎么会出现:一个旧名字不能变成两个新名字,没有办法决定由谁继承 X 的引用,所以整个文件的迁移都不做。
Widget Root {
Text Title (was: Heading) { }
Text Subtitle (was: Heading) { }
}怎么改:把子句留在要继承引用的那个节点上,删掉另一个。
DUI3012
错误枚举名SelfRename
一个写在节点 X 自己身上的 (was: X)。
怎么会出现:改名子句说的是节点以前叫什么,名字没变就没有可迁移的东西,几乎一定是笔误;整个文件的迁移都不做。
Text Title (was: Title) { Text = "Settings" }怎么改:删掉这个 (was: …);如果是想改名,把新的 id 写在类型后面,旧的写进 (was: …)。
DUI3013
警告枚举名RenameGraphReferenceAmbiguous
一个同时是别的成员名字的旧 id,因此图表引用没有被迁移(警告)。
怎么会出现:Blueprint 图表里的引用按名字解析。如果旧名字同时是这个 Blueprint 自己声明的变量、父类的成员,或者某个函数里的局部变量,改写所有对它的引用就会悄悄改动与这个控件毫无关系的代码,所以图表这一路不做。绑定和动画轨道这两路没有歧义,照常迁移。
怎么改:手动把图表里的引用指向新名字,或者给另一个同名的东西改名。
DUI3014
错误枚举名DuplicateResource
两个同名的资源条目。
怎么会出现:条目会在多个 resources 块之间累积;一个名字声明了两次时,第一个处处生效,所以第二个被拒绝。
resources {
Color Accent = #FF6600
Color Accent = #E05A47
}
Text Note { Color = @Accent }怎么改:删掉其中一个,或者给它改名。
DUI3015
错误枚举名StyleCycle
一个沿着基类链继承了自己的样式。
怎么会出现:style A : B,沿着基类往上走又回到了 A。这时什么都不应用,戴着这个样式的节点报这个码。
style Caption : Warning { FontSize = 14 }
style Warning : Caption { Color = #E05A47 }
Text Note : Warning { Text = "Unsaved changes" }怎么改:断开这个环,让其中一个不再继承另一个。
DUI3016
错误枚举名DuplicateTimeline
两个同名的时间轴。
怎么会出现:时间轴的名字既是动画的显示名,也是一个类成员变量(编译器为每个动画声明一个,和 UMG 为 UWidgetAnimation 做的一样),两个同名就是一个谁也访问不到的变量,和两个同名样式一样被拒绝。
timeline Pulse external
timeline Pulse { duration = 0.6 }
Widget Root { }怎么改:给其中一个改名。
DUI3017
错误枚举名DuplicateComponentAlias
两行给出同一个名字的 use … as。
怎么会出现:第一行处处生效,第二行被拒绝,免得一个类型名因为远处的某一行而悄悄换了意思。
use "UI/Components/Row.dui" as Row
use "UI/Components/NieR_Row.dui" as Row
Widget Root { }怎么改:给第二个换一个名字。
DUI3018
错误枚举名AliasShadowsBuiltIn
一个与标签或容器同名的 use … as 名字。
怎么会出现:节点类型先问内置标签和布局容器,再问别名,所以叫 Text 或 VerticalBox 的别名永远写不出来:别名改变不了 Text 的意思。
use "UI/Components/Label.dui" as Text
Widget Root { }怎么改:换一个不是标签或容器名的名字,比如 Label。
DUI3019
错误枚举名DuplicateProp
两行声明同一个名字的 props。
怎么会出现:一个名字只能是一个属性;第一行保留,第二行被拒绝。
props {
Text Label
String Label
}
Widget Root { }怎么改:删掉其中一行,或者给它改名。
DUI3020
错误枚举名DuplicateEvent
两个同名的 events 条目,或者一个条目里声明了两次的参数。
怎么会出现:每个事件都会变成一个事件分发器,所以名字必须唯一;同一个事件的参数名也必须唯一。
events {
Picked(Number Index, Number Index)
Closed
Closed
}
Widget Root { }怎么改:删掉重复的那个,或者给它改名。
DUI3021
错误枚举名UnknownNamespace
一个 ns 没有被任何 use … as ns 声明过的 ns.Name。
怎么会出现:样式、资源和组件别名可以带命名空间前缀(: nier.Label、@nier.Ink、nier.Row),这个前缀必须来自 use "…" as nier。这种情况只报这一个码,不会再报一条“没有这个样式”,把你引去找一个并不存在的拼写错误。
Text Note : nier.Label { Text = "Ready" }怎么改:加上 use "UI/NieR_Common.dui" as nier,或者修正前缀的拼写。
DUI3022
错误枚举名MultipleDefaultSlots
一个文件里不止一个 slot … default。
怎么会出现:嵌套进来却没写 slot 名的内容只有一个去处。第一个保留默认的角色,这样已经按它编译过的宿主仍然一致。
Widget Root {
slot Rows default
slot Footer default
}怎么改:只在一个 slot 上写 default。
DUI3023
警告枚举名DuplicateRowKey
一个 rows 表里第一个值生成了同一个 id 的两行(警告)。
怎么会出现:每一行的 id 来自它的第一个值(比如 Page_0__Row_City_Ruins),这样插入或调整行的顺序不会动到别的行的 id 和本地化键。两行的键生成了同一个 id,或者生成了文件里已经有的 id 时,后一行会在后面加上 _1 这样的序号,而这个序号连同它的本地化键会随着行的顺序移动,这恰恰是键列要避免的不稳定。
VerticalBox Menu {
rows Text (Text) {
"Audio"
"Audio"
}
}怎么改:让各行的第一个值互不相同;需要按名字找到的行,写成单独的节点。