From 3a1bc1387126d41cd20940bb335cff352b60ed28 Mon Sep 17 00:00:00 2001 From: linyuzhe Date: Sun, 8 Jun 2025 11:03:20 +0800 Subject: [PATCH] =?UTF-8?q?fix=EF=BC=9A=E4=BF=AE=E6=94=B9=E4=BB=A3?= =?UTF-8?q?=E7=A0=81=E5=9D=97=E7=BC=A9=E8=BF=9B=E3=80=81=E4=BB=A3=E7=A0=81?= =?UTF-8?q?=E5=9D=97=E3=80=81json=E6=A0=BC=E5=BC=8F?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- mcguide/18-界面与交互/19-控件属性动画.md | 339 ++-- mcguide/18-界面与交互/2-从零开始创建UI.md | 22 +- mcguide/18-界面与交互/30-UI说明文档.md | 1621 ++++++++++-------- mcguide/18-界面与交互/40-UIAPI文档.md | 4 +- mcguide/18-界面与交互/61-原生界面修改文档.md | 10 +- mcguide/18-界面与交互/70-UI数据绑定.md | 6 +- 6 files changed, 1056 insertions(+), 946 deletions(-) diff --git a/mcguide/18-界面与交互/19-控件属性动画.md b/mcguide/18-界面与交互/19-控件属性动画.md index 256ad7d..7e9996d 100644 --- a/mcguide/18-界面与交互/19-控件属性动画.md +++ b/mcguide/18-界面与交互/19-控件属性动画.md @@ -187,12 +187,12 @@ uv动画和序列帧动画都是uv起点属性的动画,不同于其他属性 要表现一个属性动画,需要先写一个Json数据块,透明度动画举例如下(相关参数会在下文详细描述): ```json - { - "anim_type" : "alpha", - "duration" : 1.0, - "from" : 0.0, - "to" : 1.0 - } +{ + "anim_type" : "alpha", + "duration" : 1.0, + "from" : 0.0, + "to" : 1.0 +} ``` 这段代码块代表一个控件在1秒钟内alpha值从0线性变化到1的属性动画,为了将这个动画绑定到控件上,一共有两种写法。 @@ -200,38 +200,38 @@ uv动画和序列帧动画都是uv起点属性的动画,不同于其他属性 一种是将Json数据块直接赋给alpha属性: ```json - { - "alphaImg" : { - "alpha" : { - "anim_type" : "alpha", - "duration" : 0.30, - "from" : 0.0, - "to" : 1.0 - }, - "texture" : "textures/netease/common/image/default", - "type" : "image", - "visible" : true - } - } -``` - -另一种则是将属性动画写成自定义控件的形式写在UIjson文件的最外层,在alpha属性值以 “@”+动画名 的形式进行赋值: - -```json - { - "alphaImg" : { - "alpha" : "@show_alpha_ani", - "texture" : "textures/netease/common/image/default", - "type" : "image", - "visible" : true - }, - "show_alpha_ani": { +{ + "alphaImg" : { + "alpha" : { "anim_type" : "alpha", "duration" : 0.30, "from" : 0.0, "to" : 1.0 }, - } + "texture" : "textures/netease/common/image/default", + "type" : "image", + "visible" : true + } +} +``` + +另一种则是将属性动画写成自定义控件的形式写在UIjson文件的最外层,在alpha属性值以 “@”+动画名 的形式进行赋值: + +```json +{ + "alphaImg" : { + "alpha" : "@show_alpha_ani", + "texture" : "textures/netease/common/image/default", + "type" : "image", + "visible" : true + }, + "show_alpha_ani": { + "anim_type" : "alpha", + "duration" : 0.30, + "from" : 0.0, + "to" : 1.0 + } +} ``` 两种写法都能达成相同的效果,不同的是第二种写法能够被复用。 @@ -259,33 +259,34 @@ uv动画和序列帧动画都是uv起点属性的动画,不同于其他属性 * 注2 ```json - "alphaImg" : { - "alpha" : "@show_alpha_ani", - "texture" : "textures/netease/common/image/default", - "type" : "image", - "visible" : true - }, - "show_alpha_ani": { - "anim_type" : "alpha", - "duration" : 0.30, - "from" : 0.0, - "next" : "@hold_alpha_ani", - "to" : 1.0 - }, - "hold_alpha_ani" : { - "anim_type" : "alpha", - "duration" : 1, - "from" : 1.0, - "next" : "@hide_alpha_ani", - "to" : 1.0 - }, - "hide_alpha_ani" : { - "anim_type" : "alpha", - "duration" : 0.30, - "from" : 1.0, - "to" : 0.0 - }, - +{ + "alphaImg" : { + "alpha" : "@show_alpha_ani", + "texture" : "textures/netease/common/image/default", + "type" : "image", + "visible" : true + }, + "show_alpha_ani": { + "anim_type" : "alpha", + "duration" : 0.30, + "from" : 0.0, + "next" : "@hold_alpha_ani", + "to" : 1.0 + }, + "hold_alpha_ani" : { + "anim_type" : "alpha", + "duration" : 1, + "from" : 1.0, + "next" : "@hide_alpha_ani", + "to" : 1.0 + }, + "hide_alpha_ani" : { + "anim_type" : "alpha", + "duration" : 0.30, + "from" : 1.0, + "to" : 0.0 + } +} ``` ### 透明度动画 @@ -301,33 +302,34 @@ uv动画和序列帧动画都是uv起点属性的动画,不同于其他属性 ![alpha动画](./picture/UIAnimation/alpha.gif) ```json - "alphaImg" : { - "alpha" : "@show_alpha_ani", - "texture" : "textures/netease/common/image/default", - "type" : "image", - "visible" : true - }, - "show_alpha_ani": { - "anim_type" : "alpha", - "duration" : 0.30, - "from" : 0.0, - "next" : "@hold_alpha_ani", - "to" : 1.0 - }, - "hold_alpha_ani" : { - "anim_type" : "alpha", - "duration" : 1, - "from" : 1.0, - "next" : "@hide_alpha_ani", - "to" : 1.0 - }, - "hide_alpha_ani" : { - "anim_type" : "alpha", - "duration" : 0.30, - "from" : 1.0, - "to" : 0.0 - }, - +{ + "alphaImg" : { + "alpha" : "@show_alpha_ani", + "texture" : "textures/netease/common/image/default", + "type" : "image", + "visible" : true + }, + "show_alpha_ani": { + "anim_type" : "alpha", + "duration" : 0.30, + "from" : 0.0, + "next" : "@hold_alpha_ani", + "to" : 1.0 + }, + "hold_alpha_ani" : { + "anim_type" : "alpha", + "duration" : 1, + "from" : 1.0, + "next" : "@hide_alpha_ani", + "to" : 1.0 + }, + "hide_alpha_ani" : { + "anim_type" : "alpha", + "duration" : 0.30, + "from" : 1.0, + "to" : 0.0 + } +} ``` ### 裁剪动画 @@ -343,18 +345,19 @@ uv动画和序列帧动画都是uv起点属性的动画,不同于其他属性 ![clip动画](./picture/UIAnimation/clip.gif) ```json - "clipImg" : { - "clip_ratio" : { - "anim_type" : "clip", - "duration" : 1.0, - "from" : 0.0, - "to" : 1.0 - }, - "texture" : "textures/netease/common/image/default", - "type" : "image", - "visible" : true - }, - +{ + "clipImg" : { + "clip_ratio" : { + "anim_type" : "clip", + "duration" : 1.0, + "from" : 0.0, + "to" : 1.0 + }, + "texture" : "textures/netease/common/image/default", + "type" : "image", + "visible" : true + } +} ``` ### 颜色动画 @@ -370,19 +373,20 @@ uv动画和序列帧动画都是uv起点属性的动画,不同于其他属性 ![color动画](./picture/UIAnimation/color.gif) ```json - "colorImg" : { - "color": "@color_ani", - "texture" : "textures/netease/common/image/default", - "type" : "image", - "visible" : true - }, - "color_ani": { - "anim_type" : "color", - "duration" : 1.0, - "from" : [1,0,0], - "to" : [0,0,1] - }, - +{ + "colorImg" : { + "color": "@color_ani", + "texture" : "textures/netease/common/image/default", + "type" : "image", + "visible" : true + }, + "color_ani": { + "anim_type" : "color", + "duration" : 1.0, + "from" : [1,0,0], + "to" : [0,0,1] + } +} ``` ### 序列帧动画 @@ -402,20 +406,22 @@ uv动画和序列帧动画都是uv起点属性的动画,不同于其他属性 ![flipbook动画](./picture/UIAnimation/flipbook.gif) ```json - "flipbookImg" : { - "texture" : "textures/ui/my_eating_apple", - "type" : "image", - "uv" : "@flipbook_ani", - "uv_size" : [ 64.0, 64.0 ], - "visible" : true - }, - "flipbook_ani": { - "anim_type": "flip_book", - "initial_frame": 10, - "frame_count": 36, - "fps": 10, - "reversible": false - }, +{ + "flipbookImg" : { + "texture" : "textures/ui/my_eating_apple", + "type" : "image", + "uv" : "@flipbook_ani", + "uv_size" : [ 64.0, 64.0 ], + "visible" : true + }, + "flipbook_ani": { + "anim_type": "flip_book", + "initial_frame": 10, + "frame_count": 36, + "fps": 10, + "reversible": false + } +} ``` 当一个图片控件被用作序列帧的载体时,该控件的属性配置有以下规则需要遵守: @@ -441,19 +447,20 @@ uv动画和序列帧动画都是uv起点属性的动画,不同于其他属性 ![offset动画](./picture/UIAnimation/offset.gif) ```json - "offsetImg" : { - "offset" : "@offset_ani", - "texture" : "textures/netease/common/image/default", - "type" : "image", - "visible" : true - }, - "offset_ani": { - "anim_type" : "offset", - "duration" : 1.0, - "from" : [0, 0], - "to" : [0, 50] - }, - +{ + "offsetImg" : { + "offset" : "@offset_ani", + "texture" : "textures/netease/common/image/default", + "type" : "image", + "visible" : true + }, + "offset_ani": { + "anim_type" : "offset", + "duration" : 1.0, + "from" : [0, 0], + "to" : [0, 50] + } +} ``` **注** @@ -477,19 +484,20 @@ uv动画和序列帧动画都是uv起点属性的动画,不同于其他属性 ![size动画](./picture/UIAnimation/size.gif) ```json - "sizeImg" : { - "size" : "@size_ani", - "texture" : "textures/netease/common/image/default", - "type" : "image", - "visible" : true - }, - "size_ani": { - "anim_type" : "size", - "duration" : 1.0, - "from" : [100, 100], - "to" : [150, 150] - }, - +{ + "sizeImg" : { + "size" : "@size_ani", + "texture" : "textures/netease/common/image/default", + "type" : "image", + "visible" : true + }, + "size_ani": { + "anim_type" : "size", + "duration" : 1.0, + "from" : [100, 100], + "to" : [150, 150] + } +} ``` **注** @@ -513,19 +521,20 @@ uv动画和序列帧动画都是uv起点属性的动画,不同于其他属性 ![uv动画](./picture/UIAnimation/uv.gif) ```json - "sizeImg" : { - "uv" : "@uv_ani", - "texture" : "textures/netease/common/image/default", - "type" : "image", - "visible" : true - }, - "uv_ani": { - "anim_type" : "uv", - "duration" : 5, - "from" : [0, 0], - "to" : [2240, 0] - }, - +{ + "sizeImg" : { + "uv" : "@uv_ani", + "texture" : "textures/netease/common/image/default", + "type" : "image", + "visible" : true + }, + "uv_ani": { + "anim_type" : "uv", + "duration" : 5, + "from" : [0, 0], + "to" : [2240, 0] + } +} ``` diff --git a/mcguide/18-界面与交互/2-从零开始创建UI.md b/mcguide/18-界面与交互/2-从零开始创建UI.md index 582892f..ee13072 100644 --- a/mcguide/18-界面与交互/2-从零开始创建UI.md +++ b/mcguide/18-界面与交互/2-从零开始创建UI.md @@ -248,20 +248,20 @@ shootButton的锚点,位移XY,尺寸XY的参考属性如下。按照这种 3. 然后激活(显示)对应的界面预设 ```python - def InitClient(self): - import mod.client.extraClientApi as clientApi - self.ListenForEngineEvent(UiInitFinishedEvent, self, self.OnUIInitFinished) +def InitClient(self): + import mod.client.extraClientApi as clientApi + self.ListenForEngineEvent(UiInitFinishedEvent, self, self.OnUIInitFinished) ``` ```python - def OnUIInitFinished(self, args): - import mod.client.extraClientApi as clientApi - if clientApi.GetPlatform() == 0: - uiNodePreset = self.GetParent().GetChildPresetsByName("PC版UI界面")[0] - else: - uiNodePreset = self.GetParent().GetChildPresetsByName("PE版UI界面")[0] - if uiNodePreset: - uiNodePreset.SetUiActive(True) +def OnUIInitFinished(self, args): + import mod.client.extraClientApi as clientApi + if clientApi.GetPlatform() == 0: + uiNodePreset = self.GetParent().GetChildPresetsByName("PC版UI界面")[0] + else: + uiNodePreset = self.GetParent().GetChildPresetsByName("PE版UI界面")[0] + if uiNodePreset: + uiNodePreset.SetUiActive(True) ``` 我们利用[UI API文档](40-UIAPI文档.html)中对各个控件的接口和游戏原生支持的格式化,可以在python代码中动态的改变界面的表现,具体可以参考[样式代码](https://minecraft-zh.gamepedia.com/index.php?title=%E6%A0%B7%E5%BC%8F%E4%BB%A3%E7%A0%81&variant=zh) diff --git a/mcguide/18-界面与交互/30-UI说明文档.md b/mcguide/18-界面与交互/30-UI说明文档.md index 2144611..3cd3002 100644 --- a/mcguide/18-界面与交互/30-UI说明文档.md +++ b/mcguide/18-界面与交互/30-UI说明文档.md @@ -12,13 +12,12 @@ time: 分钟 * 示例中为"myUIName" -```json - myUIName.json +```html +myUIName.json - "namespace" : "myUIName" - - myUIName.py +"namespace": "myUIName" +myUIName.py ``` ## JSON编写说明 @@ -32,7 +31,9 @@ Json是UI界面的显示内容和绑定的集合,UI是一种树状的组织结 命名空间是这个界面的名称,我们规定json文件名和namespace一致。 ```json - "namespace" : "myUIName" +{ + "namespace" : "myUIName" +} ``` ### Main Screen @@ -42,10 +43,12 @@ main是这个界面名称,我们规定使用main,即一个json文件是一 controls中的内容是该界面下的树状节点,即子节点。 ```json - "main@common.base_screen" : { +{ + "main@common.base_screen" : { "controls" : [ ] } +} ``` | 变量 | 解释 | @@ -87,7 +90,8 @@ path = "/panel0/text0" 为了适配异形屏,我们可以展示screen中的内容通过引用的形式写在screen的$screen_content属性中。 ```json - "main@common.base_screen" : { +{ + "main@common.base_screen" : { "$screen_content":"myUIName.panel0" }, "panel0":{ @@ -99,10 +103,11 @@ path = "/panel0/text0" "type" : "panel" }, "text0" : { - "text" : "Hello World!", - "type" : "label", - "visible" : true + "text" : "Hello World!", + "type" : "label", + "visible" : true } +} ``` 被$screen_content引用的内容,其显示内容的范围不会被异形屏遮挡。此时text0的路径为 @@ -121,45 +126,47 @@ path = base_path + "/text0" screen,即画布控件,是游戏中一个UI界面的根节点,所有其他控件只有挂在画布下才能被正确显示出来。 ```json -"main1" : { - "absorbs_input" : true, - "always_accepts_input" : false, - "controls" : [ - { - "label0@test.label0" : {} - } - ], - "force_render_below" : false, - "is_showing_menu" : true, - "render_game_behind" : true, - "render_only_when_topmost" : true, - "should_steal_mouse" : false, - "type" : "screen" +{ + "main1" : { + "absorbs_input" : true, + "always_accepts_input" : false, + "controls" : [ + { + "label0@test.label0" : {} + } + ], + "force_render_below" : false, + "is_showing_menu" : true, + "render_game_behind" : true, + "render_only_when_topmost" : true, + "should_steal_mouse" : false, + "type" : "screen" }, "main2@common.base_screen" : { - "$screen_content" : "test.netease_editor_root_panel_base_screen0", - "absorbs_input" : true, - "always_accepts_input" : false, - "force_render_below" : false, - "is_showing_menu" : true, - "render_game_behind" : true, - "render_only_when_topmost" : true, - "should_steal_mouse" : false + "$screen_content" : "test.netease_editor_root_panel_base_screen0", + "absorbs_input" : true, + "always_accepts_input" : false, + "force_render_below" : false, + "is_showing_menu" : true, + "render_game_behind" : true, + "render_only_when_topmost" : true, + "should_steal_mouse" : false }, "netease_editor_root_panel_base_screen0" : { - "anchor_from" : "top_left", - "anchor_to" : "top_left", - "controls" : [ - { - "label1@test.label1" : {} - } - ], - "layer" : 1, - "offset" : [ 0, 0 ], - "size" : [ "100%", "100%" ], - "type" : "panel", - "visible" : true + "anchor_from" : "top_left", + "anchor_to" : "top_left", + "controls" : [ + { + "label1@test.label1" : {} + } + ], + "layer" : 1, + "offset" : [ 0, 0 ], + "size" : [ "100%", "100%" ], + "type" : "panel", + "visible" : true } +} ``` |
变量
| 解释 | @@ -196,21 +203,21 @@ absorbs_input暂时无法生效,等待后续修复。 ### 通用属性 通用属性是每个控件都支持编辑的属性,对每个控件的位置、大小等基本属性进行设置。 -|
变量
| 解释 | -| :------------: | ----------------------------------------------------------- | -| anchor_from | 挂接在父节点锚点的位置,取值范围["top_left", "top_middle", "top_right", "left_middle", "center", "right_middle", "bottom_left", "bottom_middle", "bottom_right"] | -| anchor_to | 自身挂接锚点的位置,取值同anchor_from | -| layer | 当前控件相对父节点的层级,最终显示层级取决于父节点到该节点的layer之和 | -| offset | 自身相对父节点的偏移,值为百分比+像素(1个像素等于屏幕上3个像素) | -| size | 相对父节点的大小,取值同offset | -| max_size | 最大尺寸,取值同offset。当该控件尺寸可变时,最大不能超过该属性配置的尺寸 | -| min_size | 最小尺寸,取值同offset。当该控件尺寸可变时,最小不能小于该属性配置的尺寸 | -| clips_children | 裁剪子控件,取值bool值,开启后该控件范围外的子控件将不会被渲染 | -| clip_offset | 裁剪偏移,取值[x,y]。当开启裁剪子控件后,用来调整裁剪范围的偏移 | -| alpha | 透明度,取值0-1.0。调整控件的透明度 | +|
变量
| 解释 | +| :------------: | ----------------------------------------------------------- | +| anchor_from | 挂接在父节点锚点的位置,取值范围["top_left", "top_middle", "top_right", "left_middle", "center", "right_middle", "bottom_left", "bottom_middle", "bottom_right"] | +| anchor_to | 自身挂接锚点的位置,取值同anchor_from | +| layer | 当前控件相对父节点的层级,最终显示层级取决于父节点到该节点的layer之和 | +| offset | 自身相对父节点的偏移,值为百分比+像素(1个像素等于屏幕上3个像素) | +| size | 相对父节点的大小,取值同offset | +| max_size | 最大尺寸,取值同offset。当该控件尺寸可变时,最大不能超过该属性配置的尺寸 | +| min_size | 最小尺寸,取值同offset。当该控件尺寸可变时,最小不能小于该属性配置的尺寸 | +| clips_children | 裁剪子控件,取值bool值,开启后该控件范围外的子控件将不会被渲染 | +| clip_offset | 裁剪偏移,取值[x,y]。当开启裁剪子控件后,用来调整裁剪范围的偏移 | +| alpha | 透明度,取值0-1.0。调整控件的透明度 | | propagate_alpha | 透明度传递,取值bool。该控件的透明度是否会影响子控件 | -| enable | 是否可交互,取值bool。关闭该属性后按钮等控件变得不可交互 | -| type | 当前控件类型 | +| enable | 是否可交互,取值bool。关闭该属性后按钮等控件变得不可交互 | +| type | 当前控件类型 | | visible | 默认是否显示,true为显示,false为不显示 | 下图为UI编辑器中控件的通用属性编辑面板 @@ -250,24 +257,26 @@ absorbs_input暂时无法生效,等待后续修复。 ### Label Label 是文本框控件,用来显示文本信息,默认的字体是MC字体,如果有中文会变成中文字体格式,暂时不支持换字体,可以通过接口统一设置字体,如果需要设置后续有介绍。 -```json - "label0" : { - "anchor_from" : "center", - "anchor_to" : "center", - "color" : [ 1, 1, 1 ], - "font_scale_factor" : 1.0, - "font_size" : "normal", - "font_type" : "smooth", - "layer" : 1, - "offset" : [ 0, 0 ], - "shadow" : false, - "size" : [ 100, 100 ], - "text" : "Hello World!", - "text_alignment" : "center", - "line_padding" : 0.0, - "type" : "label", - "visible" : true - }, +```json +{ + "label0" : { + "anchor_from" : "center", + "anchor_to" : "center", + "color" : [ 1, 1, 1 ], + "font_scale_factor" : 1.0, + "font_size" : "normal", + "font_type" : "smooth", + "layer" : 1, + "offset" : [ 0, 0 ], + "shadow" : false, + "size" : [ 100, 100 ], + "text" : "Hello World!", + "text_alignment" : "center", + "line_padding" : 0.0, + "type" : "label", + "visible" : true + } +} ``` |
变量
| 解释 | | :------------: | ----------------------------------------------------------- | @@ -315,30 +324,32 @@ Label 是文本框控件,用来显示文本信息,默认的字体是MC字体 Image是指图片控件,具有图片裁剪,图片九宫格,颜色叠加,uv偏移,旋转显示的额外属性。 ```json - "image0" : { - "anchor_from" : "center", - "anchor_to" : "center", - "is_new_nine_slice" : false, - "layer" : 2, - "nine_slice_buttom" : 0, - "nine_slice_left" : 0, - "nine_slice_right" : 0, - "nine_slice_top" : 0, - "offset" : [ 0, 0 ], - "size" : [ 100, 100 ], - "texture" : "textures/netease/common/image/default", - "nineslice_size" : [ 0, 0, 0, 0 ], - "grayscale" : false, - "keep_ratio" : true, - "clip_direction" : "left", - "clip_ratio" : 0.0, - "type" : "image", - "uv" : [ 0, 0 ], - "uv_size" : [ 107, 107 ], - "rotate_pivot": [0.5, 0.5], - "rotate_angle": 0, - "visible" : true - }, +{ + "image0" : { + "anchor_from" : "center", + "anchor_to" : "center", + "is_new_nine_slice" : false, + "layer" : 2, + "nine_slice_buttom" : 0, + "nine_slice_left" : 0, + "nine_slice_right" : 0, + "nine_slice_top" : 0, + "offset" : [ 0, 0 ], + "size" : [ 100, 100 ], + "texture" : "textures/netease/common/image/default", + "nineslice_size" : [ 0, 0, 0, 0 ], + "grayscale" : false, + "keep_ratio" : true, + "clip_direction" : "left", + "clip_ratio" : 0.0, + "type" : "image", + "uv" : [ 0, 0 ], + "uv_size" : [ 107, 107 ], + "rotate_pivot": [0.5, 0.5], + "rotate_angle": 0, + "visible" : true + } +} ``` |
变量
| 解释 | @@ -397,33 +408,33 @@ json如下: "type" : "screen" }, "image" : { - "layer": 3, - "size": [ 100, 100 ], - "offset": "@UIDemo.animation_in", - "texture": "textures/netease/common/image/default", - "is_new_nine_slice": false, - "nine_slice_buttom" : 0, - "nine_slice_left" : 0, - "nine_slice_right" : 0, - "nine_slice_top" : 0, - "nineslice_size" : [0, 0, 0, 0], - "type": "image" + "layer": 3, + "size": [ 100, 100 ], + "offset": "@UIDemo.animation_in", + "texture": "textures/netease/common/image/default", + "is_new_nine_slice": false, + "nine_slice_buttom" : 0, + "nine_slice_left" : 0, + "nine_slice_right" : 0, + "nine_slice_top" : 0, + "nineslice_size" : [0, 0, 0, 0], + "type": "image" }, "animation_in": { - "anim_type": "offset", - "duration": 1.5, - "from": [ -100, 0 ], - "to": [ 100, 0 ], - "next": "@UIDemo.animation_out" + "anim_type": "offset", + "duration": 1.5, + "from": [ -100, 0 ], + "to": [ 100, 0 ], + "next": "@UIDemo.animation_out" }, "animation_out": { - "anim_type": "offset", - "duration": 1.5, - "from": [ 100, 0 ], - "to": [ -100, 0 ], - "next": "@UIDemo.animation_in" + "anim_type": "offset", + "duration": 1.5, + "from": [ 100, 0 ], + "to": [ -100, 0 ], + "next": "@UIDemo.animation_in" }, - "namespace" : "UIDemo" + "namespace" : "UIDemo" } ``` @@ -456,101 +467,103 @@ Button 是按钮控件,同时含有Image和Label。按钮有三种状态,分 * controls表示控制的子节点, ```json - "button0@common.button" : { - "$default_texture" : "textures/netease/common/button/default", - "$hover_texture" : "textures/netease/common/button/hover", - "$is_new_nine_slice" : false, - "$label_color" : [ 1, 1, 1 ], - "$label_font_scale_factor" : 1.0, - "$label_font_size" : "large", - "$label_layer" : 3, - "$label_offset" : [ 0, 0 ], - "$label_text" : "Button", - "$nine_slice_buttom" : 0, - "$nine_slice_left" : 0, - "$nine_slice_right" : 0, - "$nine_slice_top" : 0, - "$nineslice_size" : [ 0, 0, 0, 0 ], - "$pressed_button_name" : "%fpsBattle.click", - "$pressed_texture" : "textures/netease/common/button/pressed", - "$texture_layer" : 2, - "anchor_from" : "center", - "anchor_to" : "center", - "is_handle_button_move_event" : true, - "button_mappings" : [], - "bindings" : [ - { - "binding_collection_name" : "", - "binding_condition" : "always_when_visible", - "binding_type" : "collection_details" - } - ], - "controls" : [ - { - "default@fpsBattle.default" : {} - }, - { - "hover@fpsBattle.hover" : {} - }, - { - "pressed@fpsBattle.pressed" : {} - }, - { - "button_label@fpsBattle.button_label" : {} - } - ], - "default_control" : "default", - "hover_control" : "hover", - "layer" : 3, - "offset" : [ 0, 0 ], - "pressed_control" : "pressed", - "size" : [ 100, 50 ], - "type" : "button", - "visible" : true +{ + "button0@common.button" : { + "$default_texture" : "textures/netease/common/button/default", + "$hover_texture" : "textures/netease/common/button/hover", + "$is_new_nine_slice" : false, + "$label_color" : [ 1, 1, 1 ], + "$label_font_scale_factor" : 1.0, + "$label_font_size" : "large", + "$label_layer" : 3, + "$label_offset" : [ 0, 0 ], + "$label_text" : "Button", + "$nine_slice_buttom" : 0, + "$nine_slice_left" : 0, + "$nine_slice_right" : 0, + "$nine_slice_top" : 0, + "$nineslice_size" : [ 0, 0, 0, 0 ], + "$pressed_button_name" : "%fpsBattle.click", + "$pressed_texture" : "textures/netease/common/button/pressed", + "$texture_layer" : 2, + "anchor_from" : "center", + "anchor_to" : "center", + "is_handle_button_move_event" : true, + "button_mappings" : [], + "bindings" : [ + { + "binding_collection_name" : "", + "binding_condition" : "always_when_visible", + "binding_type" : "collection_details" + } + ], + "controls" : [ + { + "default@fpsBattle.default" : {} + }, + { + "hover@fpsBattle.hover" : {} + }, + { + "pressed@fpsBattle.pressed" : {} + }, + { + "button_label@fpsBattle.button_label" : {} + } + ], + "default_control" : "default", + "hover_control" : "hover", + "layer" : 3, + "offset" : [ 0, 0 ], + "pressed_control" : "pressed", + "size" : [ 100, 50 ], + "type" : "button", + "visible" : true }, "button_label" : { - "color" : "$label_color", - "font_scale_factor" : "$label_font_scale_factor", - "font_size" : "$label_font_size", - "font_type" : "smooth", - "layer" : "$label_layer", - "max_size" : [ "100%", "100%" ], - "offset" : [ 0, 0 ], - "shadow" : false, - "text" : "$label_text", - "text_alignment" : "center", - "type" : "label" + "color" : "$label_color", + "font_scale_factor" : "$label_font_scale_factor", + "font_size" : "$label_font_size", + "font_type" : "smooth", + "layer" : "$label_layer", + "max_size" : [ "100%", "100%" ], + "offset" : [ 0, 0 ], + "shadow" : false, + "text" : "$label_text", + "text_alignment" : "center", + "type" : "label" }, "default" : { - "is_new_nine_slice" : "$is_new_nine_slice", - "layer" : "$texture_layer", - "nine_slice_buttom" : "$nine_slice_buttom", - "nine_slice_left" : "$nine_slice_left", - "nine_slice_right" : "$nine_slice_right", - "nine_slice_top" : "$nine_slice_top", - "texture" : "$default_texture", - "type" : "image" + "is_new_nine_slice" : "$is_new_nine_slice", + "layer" : "$texture_layer", + "nine_slice_buttom" : "$nine_slice_buttom", + "nine_slice_left" : "$nine_slice_left", + "nine_slice_right" : "$nine_slice_right", + "nine_slice_top" : "$nine_slice_top", + "texture" : "$default_texture", + "type" : "image" }, "hover" : { - "is_new_nine_slice" : "$is_new_nine_slice", - "layer" : "$texture_layer", - "nine_slice_buttom" : "$nine_slice_buttom", - "nine_slice_left" : "$nine_slice_left", - "nine_slice_right" : "$nine_slice_right", - "nine_slice_top" : "$nine_slice_top", - "texture" : "$hover_texture", - "type" : "image" + "is_new_nine_slice" : "$is_new_nine_slice", + "layer" : "$texture_layer", + "nine_slice_buttom" : "$nine_slice_buttom", + "nine_slice_left" : "$nine_slice_left", + "nine_slice_right" : "$nine_slice_right", + "nine_slice_top" : "$nine_slice_top", + "texture" : "$hover_texture", + "type" : "image" }, "pressed" : { - "is_new_nine_slice" : "$is_new_nine_slice", - "layer" : "$texture_layer", - "nine_slice_buttom" : "$nine_slice_buttom", - "nine_slice_left" : "$nine_slice_left", - "nine_slice_right" : "$nine_slice_right", - "nine_slice_top" : "$nine_slice_top", - "texture" : "$pressed_texture", - "type" : "image" - }, + "is_new_nine_slice" : "$is_new_nine_slice", + "layer" : "$texture_layer", + "nine_slice_buttom" : "$nine_slice_buttom", + "nine_slice_left" : "$nine_slice_left", + "nine_slice_right" : "$nine_slice_right", + "nine_slice_top" : "$nine_slice_top", + "texture" : "$pressed_texture", + "type" : "image" + } +} ``` |
变量
| 解释 | @@ -587,15 +600,17 @@ Button 是按钮控件,同时含有Image和Label。按钮有三种状态,分 panel为面板控件,主要是用来将控件进行分类和管理,类似文件夹。 ```json - "panel" : { - "anchor_from" : "center", - "anchor_to" : "center", - "layer" : 0, - "offset" : [ 0, 0 ], - "size" : [ "50.000000%+0 px", "50.000000%+0px" ], - "type" : "panel", - "visible" : true +{ + "panel" : { + "anchor_from" : "center", + "anchor_to" : "center", + "layer" : 0, + "offset" : [ 0, 0 ], + "size" : [ "50.000000%+0 px", "50.000000%+0px" ], + "type" : "panel", + "visible" : true } +} ``` | 变量 | 解释 | @@ -609,25 +624,27 @@ panel为面板控件,主要是用来将控件进行分类和管理,类似文 input_panel与panel类似,可以用来放置其他控件,但除此之外还可以用来拖动,或实现“模态框”功能。 ```json -"InputPanel" : { - "anchor_from" : "top_left", - "anchor_to" : "top_left", - "button_mappings": [ - { - "from_button_id": "button.menu_select", - "to_button_id": "#netease_to_button_id", - "mapping_type": "pressed" - } - ], - "layer" : 10, - "modal" : true, - "is_swallow": true, - "contained": true, - "draggable": "both", - "offset" : [ 0.0, 0.0 ], - "size" : [ 198.0, 137.0 ], - "type" : "input_panel", - "visible" : true +{ + "InputPanel" : { + "anchor_from" : "top_left", + "anchor_to" : "top_left", + "button_mappings": [ + { + "from_button_id": "button.menu_select", + "to_button_id": "#netease_to_button_id", + "mapping_type": "pressed" + } + ], + "layer" : 10, + "modal" : true, + "is_swallow": true, + "contained": true, + "draggable": "both", + "offset" : [ 0.0, 0.0 ], + "size" : [ 198.0, 137.0 ], + "type" : "input_panel", + "visible" : true + } } ``` @@ -681,23 +698,28 @@ InputPanel维护着一个拖拽偏移量,它代表着在整个拖拽过程中 布局面板,用于自动布局该控件的子控件 ```json -"stack_panel0": { - "layer": 1, - "orientation": "horizontal", - "size": [100, 100], - "type": "stack_panel", - "controls": [{ - "panel_0": { - "type": "panel", - "size": [2, 2] - } - }, { - "fill_0": { - "type": "panel", - "size": ["fill", 1] - } - }] -}, +{ + "stack_panel0": { + "layer": 1, + "orientation": "horizontal", + "size": [100, 100], + "type": "stack_panel", + "controls": [ + { + "panel_0": { + "type": "panel", + "size": [2, 2] + } + }, + { + "fill_0": { + "type": "panel", + "size": ["fill", 1] + } + } + ] + } +} ``` | 变量 | 解释 | @@ -725,51 +747,53 @@ InputPanel维护着一个拖拽偏移量,它代表着在整个拖拽过程中 TextEditBox是输入框控件,用来输入文字信息,可以获取输入内容,设置输入框内容,触发输入中和输入完成事件,设置最大输入值等。下面的示例展示了一个搜索框的信息。 ```json - "text_edit_box0@common.text_edit_box" : { - "$edit_box_default_texture" : "textures/ui/edit_box_indent", - "$edit_box_hover_texture" : "textures/ui/edit_box_indent_hover", - "$font_size" : "normal", - "$is_new_nine_slice" : false, - "$nine_slice_buttom" : 0, - "$nine_slice_left" : 0, - "$nine_slice_right" : 0, - "$nine_slice_top" : 0, - "$nineslice_size" : [ 0, 0, 0, 0 ], - "$place_holder_text" : "请输入内容", - "$place_holder_text_color" : [ 0.50, 0.50, 0.50 ], - "$text_background_default" : "fpsBattle.edit_box_background_default", - "$text_background_hover" : "fpsBattle.edit_box_background_hover", - "$text_box_name" : "%fpsBattle.message_text_box", - "$text_box_text_color" : [ 1, 1, 1 ], - "$text_edit_box_content_binding_name" : "#fpsBattle.message_text_box_content", - "anchor_from" : "center", - "anchor_to" : "center", - "enabled_newline" : false, - "layer" : 5, - "max_length" : 512, - "offset" : [ 0, 0 ], - "size" : [ 300, 27 ], - "type" : "edit_box", - "visible" : true +{ + "text_edit_box0@common.text_edit_box" : { + "$edit_box_default_texture" : "textures/ui/edit_box_indent", + "$edit_box_hover_texture" : "textures/ui/edit_box_indent_hover", + "$font_size" : "normal", + "$is_new_nine_slice" : false, + "$nine_slice_buttom" : 0, + "$nine_slice_left" : 0, + "$nine_slice_right" : 0, + "$nine_slice_top" : 0, + "$nineslice_size" : [ 0, 0, 0, 0 ], + "$place_holder_text" : "请输入内容", + "$place_holder_text_color" : [ 0.50, 0.50, 0.50 ], + "$text_background_default" : "fpsBattle.edit_box_background_default", + "$text_background_hover" : "fpsBattle.edit_box_background_hover", + "$text_box_name" : "%fpsBattle.message_text_box", + "$text_box_text_color" : [ 1, 1, 1 ], + "$text_edit_box_content_binding_name" : "#fpsBattle.message_text_box_content", + "anchor_from" : "center", + "anchor_to" : "center", + "enabled_newline" : false, + "layer" : 5, + "max_length" : 512, + "offset" : [ 0, 0 ], + "size" : [ 300, 27 ], + "type" : "edit_box", + "visible" : true }, "edit_box_background_default" : { - "is_new_nine_slice" : "$is_new_nine_slice", - "nine_slice_buttom" : "$nine_slice_buttom", - "nine_slice_left" : "$nine_slice_left", - "nine_slice_right" : "$nine_slice_right", - "nine_slice_top" : "$nine_slice_top", - "texture" : "$edit_box_default_texture", - "type" : "image" + "is_new_nine_slice" : "$is_new_nine_slice", + "nine_slice_buttom" : "$nine_slice_buttom", + "nine_slice_left" : "$nine_slice_left", + "nine_slice_right" : "$nine_slice_right", + "nine_slice_top" : "$nine_slice_top", + "texture" : "$edit_box_default_texture", + "type" : "image" }, "edit_box_background_hover" : { - "is_new_nine_slice" : "$is_new_nine_slice", - "nine_slice_buttom" : "$nine_slice_buttom", - "nine_slice_left" : "$nine_slice_left", - "nine_slice_right" : "$nine_slice_right", - "nine_slice_top" : "$nine_slice_top", - "texture" : "$edit_box_hover_texture", - "type" : "image" - }, + "is_new_nine_slice" : "$is_new_nine_slice", + "nine_slice_buttom" : "$nine_slice_buttom", + "nine_slice_left" : "$nine_slice_left", + "nine_slice_right" : "$nine_slice_right", + "nine_slice_top" : "$nine_slice_top", + "texture" : "$edit_box_hover_texture", + "type" : "image" + } +} ``` |
变量
| 解释 | @@ -788,22 +812,26 @@ TextEditBox是输入框控件,用来输入文字信息,可以获取输入内 * 注1 ```python +import mod.client.extraClientApi as clientApi +ViewBinder = clientApi.GetViewBinderCls() +ViewRequest = clientApi.GetViewViewRequestCls() +ScreenNode = clientApi.GetScreenNodeCls() + class TestScreen(ScreenNode): - def __init__(self, namespace, name, param): - ScreenNode.__init__(self, namespace, name, param) + def __init__(self, namespace, name, param): + ScreenNode.__init__(self, namespace, name, param) self.text = "" self.holder = str("请输入姓名") - + @ViewBinder.binding(ViewBinder.BF_EditChanged | ViewBinder.BF_EditFinished) - def TextBox(self, args): - print "SearchTextBox ", args - self.text = args["Text"] - return ViewRequest.Refresh - - @ViewBinder.binding(ViewBinder.BF_BindString) - def ReturnTextString(self): - return self.text + def TextBox(self, args): + print "SearchTextBox ", args + self.text = args["Text"] + return ViewRequest.Refresh + @ViewBinder.binding(ViewBinder.BF_BindString) + def ReturnTextString(self): + return self.text ``` * 注2 @@ -843,21 +871,23 @@ PC和IOS平台没有这个问题 该控件可以用于在ui上显示骨骼模型 ```json -"paper_doll0" : { - "anchor_from" : "center", - "anchor_to" : "center", - "animation" : "", - "animation_looped": true, - "layer" : 7, - "modelname" : "", - "modelsize" : 1.0, - "offset" : [ 0, 0 ], - "renderer" : "paper_doll_renderer", - "size" : [ 100, 100 ], - "type" : "custom", - "visible" : true, - "enable_scissor_test" : false, - }, +{ + "paper_doll0" : { + "anchor_from" : "center", + "anchor_to" : "center", + "animation" : "", + "animation_looped": true, + "layer" : 7, + "modelname" : "", + "modelsize" : 1.0, + "offset" : [ 0, 0 ], + "renderer" : "paper_doll_renderer", + "size" : [ 100, 100 ], + "type" : "custom", + "visible" : true, + "enable_scissor_test" : false, + } +} ``` |
变量
| 解释 | | :----------: | ----------------------------------------------------------- | @@ -891,19 +921,21 @@ PC和IOS平台没有这个问题 3)生物类型原版模型展示。 ```json -"paper_doll0" : { - "anchor_from" : "center", - "anchor_to" : "center", - "layer" : 22, - "offset" : [ 0.0, 0.0 ], - "renderer" : "netease_paper_doll_renderer", - "init_rot_y": 60.0, - "rotation": "gesture_x", - "screen_scale": 1.0, - "size" : [ 100, 100 ], - "type" : "custom", - "visible" : true, - "enable_scissor_test" : false, +{ + "paper_doll0" : { + "anchor_from" : "center", + "anchor_to" : "center", + "layer" : 22, + "offset" : [ 0.0, 0.0 ], + "renderer" : "netease_paper_doll_renderer", + "init_rot_y": 60.0, + "rotation": "gesture_x", + "screen_scale": 1.0, + "size" : [ 100, 100 ], + "type" : "custom", + "visible" : true, + "enable_scissor_test" : false + } } ``` @@ -934,7 +966,7 @@ param = { "init_rot_y": 60, # 初始朝向 "molang_dict": {"variable.liedownamount": 1} # molang变量dict,其中key为字符串,value为float类型 } -uiNode.RenderPaperDoll(path, param) +self.GetBaseUIControl(path).asNeteasePaperDoll().RenderEntity(param) ``` 2)渲染骨骼模型 @@ -947,7 +979,7 @@ param = { "animation": "fengxi", # 动画名称 "animation_looped": False, # 是否循环播放 } -uiNode.RenderPaperDoll(path, param) +self.GetBaseUIControl(path).asNeteasePaperDoll().RenderSkeletonModel(param) ``` 3)渲染原版生物模型(不需要生物实例) @@ -960,7 +992,7 @@ param = { "init_rot_y": 60, "molang_dict": {"variable.state": 2, "variable.liedownamount": 1} # 通过molang变量来调整渲染效果(坐下的猫) } -uiNode.RenderPaperDoll(path, param) +self.GetBaseUIControl(path).asNeteasePaperDoll().RenderEntity(param) ``` 使用注意事项: @@ -981,19 +1013,21 @@ uiNode.RenderPaperDoll(path, param) 该控件可以用于在ui上显示物品 ```json -"item_renderer0" : { - "anchor_from" : "center", - "anchor_to" : "center", - "layer" : 1, - "offset" : [ 0, 0 ], - "property_bag" : { - "#item_id_aux" : 131072 - }, - "renderer" : "inventory_item_renderer", - "size" : [ 100, 100 ], - "type" : "custom", - "visible" : true - }, +{ + "item_renderer0" : { + "anchor_from" : "center", + "anchor_to" : "center", + "layer" : 1, + "offset" : [ 0, 0 ], + "property_bag" : { + "#item_id_aux" : 131072 + }, + "renderer" : "inventory_item_renderer", + "size" : [ 100, 100 ], + "type" : "custom", + "visible" : true + } +} ``` |
变量
| 解释 | | :----------: | ----------------------------------------------------------- | @@ -1026,42 +1060,44 @@ uiNode.RenderPaperDoll(path, param) 该控件是可以滑动的窗口,需要有其他控件附属。 ```json - "scroll_view0@common.scrolling_panel" : { - "$background_nine_slice_buttom" : 0, - "$background_nine_slice_left" : 0, - "$background_nine_slice_right" : 0, - "$background_nine_slice_top" : 0, - "$background_nineslice_size" : [ 0, 0, 0, 0 ], - "$box_nine_slice_buttom" : 0, - "$box_nine_slice_left" : 0, - "$box_nine_slice_right" : 0, - "$box_nine_slice_top" : 0, - "$box_nineslice_size" : [ 0, 0, 0, 0 ], - "$is_background_nine_slice" : false, - "$is_box_nine_slice" : false, - "$is_track_nine_slice" : false, - "$scroll_background_image_control" : "fpsBattle.scroll_background_image", - "$scroll_background_texture" : "textures/ui/ScrollRail", - "$scroll_box_mouse_image_control" : "fpsBattle.scroll_box_image", - "$scroll_box_texture" : "textures/ui/newTouchScrollBox", - "$scroll_box_touch_image_control" : "fpsBattle.scroll_box_image", - "$scroll_track_image_control" : "fpsBattle.scroll_track_image", - "$scroll_track_texture" : "textures/ui/ScrollRail", - "$scrolling_content" : "fpsBattle.image", - "$show_background" : true, - "$track_nine_slice_buttom" : 0, - "$track_nine_slice_left" : 0, - "$track_nine_slice_right" : 0, - "$track_nine_slice_top" : 0, - "$track_nineslice_size" : [ 0, 0, 0, 0 ], - "anchor_from" : "center", - "anchor_to" : "center", - "layer" : 9, - "offset" : [ 0, 0 ], - "size" : [ 100, 80 ], - "type" : "scroll_view", - "visible" : true - }, +{ + "scroll_view0@common.scrolling_panel" : { + "$background_nine_slice_buttom" : 0, + "$background_nine_slice_left" : 0, + "$background_nine_slice_right" : 0, + "$background_nine_slice_top" : 0, + "$background_nineslice_size" : [ 0, 0, 0, 0 ], + "$box_nine_slice_buttom" : 0, + "$box_nine_slice_left" : 0, + "$box_nine_slice_right" : 0, + "$box_nine_slice_top" : 0, + "$box_nineslice_size" : [ 0, 0, 0, 0 ], + "$is_background_nine_slice" : false, + "$is_box_nine_slice" : false, + "$is_track_nine_slice" : false, + "$scroll_background_image_control" : "fpsBattle.scroll_background_image", + "$scroll_background_texture" : "textures/ui/ScrollRail", + "$scroll_box_mouse_image_control" : "fpsBattle.scroll_box_image", + "$scroll_box_texture" : "textures/ui/newTouchScrollBox", + "$scroll_box_touch_image_control" : "fpsBattle.scroll_box_image", + "$scroll_track_image_control" : "fpsBattle.scroll_track_image", + "$scroll_track_texture" : "textures/ui/ScrollRail", + "$scrolling_content" : "fpsBattle.image", + "$show_background" : true, + "$track_nine_slice_buttom" : 0, + "$track_nine_slice_left" : 0, + "$track_nine_slice_right" : 0, + "$track_nine_slice_top" : 0, + "$track_nineslice_size" : [ 0, 0, 0, 0 ], + "anchor_from" : "center", + "anchor_to" : "center", + "layer" : 9, + "offset" : [ 0, 0 ], + "size" : [ 100, 80 ], + "type" : "scroll_view", + "visible" : true + } +} ``` |
变量
| 解释 | @@ -1126,32 +1162,34 @@ mouse_path = scroll_view_path + "/scroll_mouse/scroll_view/stack_panel/backgroun Grid组件属于网格型的排列,可以依附在滚动条中,用来实现背包等功能。 ```json - "grid0" : { - "anchor_from" : "center", - "anchor_to" : "center", - "collection_name" : "test_grid", - "grid_dimensions" : [ 2, 2 ], - "grid_item_template" : "fpsBattle.netease_editor_template_image", - "grid_rescaling_type" : "none", - "maximum_grid_items" : 0, - "layer" : 1, - "offset" : [ 0, 0 ], - "size" : [ 200, 200 ], - "type" : "grid", - "visible" : true +{ + "grid0" : { + "anchor_from" : "center", + "anchor_to" : "center", + "collection_name" : "test_grid", + "grid_dimensions" : [ 2, 2 ], + "grid_item_template" : "fpsBattle.netease_editor_template_image", + "grid_rescaling_type" : "none", + "maximum_grid_items" : 0, + "layer" : 1, + "offset" : [ 0, 0 ], + "size" : [ 200, 200 ], + "type" : "grid", + "visible" : true }, "netease_editor_template_image" : { - "anchor_from" : "center", - "anchor_to" : "center", - "layer" : 1, - "offset" : [ 0, 0 ], - "size" : [ "50%", "50%" ], - "texture" : "textures/netease/common/image/default", - "type" : "image", - "uv" : [ 0, 0 ], - "uv_size" : [ 107, 107 ], - "visible" : true - }, + "anchor_from" : "center", + "anchor_to" : "center", + "layer" : 1, + "offset" : [ 0, 0 ], + "size" : [ "50%", "50%" ], + "texture" : "textures/netease/common/image/default", + "type" : "image", + "uv" : [ 0, 0 ], + "uv_size" : [ 107, 107 ], + "visible" : true + } +} ``` |
变量
| 解释 | @@ -1186,43 +1224,49 @@ Grid组件属于网格型的排列,可以依附在滚动条中,用来实现 3. grid控件不建议使用其子控件路径对其动态生成的格子控件直接进行SetVisible等操作,因为在每次界面刷新时grid控件会对所有的格子做一次数据更新,更新的过程中会强制将格子可见性置True。如果有需要对格子进行操作,可以使用数据绑定的方式,如下代码和json。需要注意的是在数据绑定的回调函数中需要明确grid本身是否可见,否则会造成grid子节点控件的可见性数据异常,从而影响界面操作逻辑。 ```json - "grid1" : { - "anchor_from" : "center", - "anchor_to" : "center", - "collection_name" : "gridDemo", - "grid_dimensions" : [ 2, 2 ], - "grid_item_template" : "UIDemo.scrollviewBtn0", - "layer" : 39, - "offset" : [ 0, 0 ], - "size" : [ 200, 200 ], - "type" : "grid", - "visible" : true +{ + "grid1" : { + "anchor_from" : "center", + "anchor_to" : "center", + "collection_name" : "gridDemo", + "grid_dimensions" : [ 2, 2 ], + "grid_item_template" : "UIDemo.scrollviewBtn0", + "layer" : 39, + "offset" : [ 0, 0 ], + "size" : [ 200, 200 ], + "type" : "grid", + "visible" : true }, "scrollviewBtn0@UIDemo.scrollviewBtn": { - "bindings" : [ - { - "binding_collection_name" : "gridDemo", - "binding_condition" : "always", - "binding_name" : "#UIDemo.visible", - "binding_name_override" : "#visible", - "binding_type" : "collection" - } - ], - "visible" : "#UIDemo.visible" - }, + "bindings" : [ + { + "binding_collection_name" : "gridDemo", + "binding_condition" : "always", + "binding_name" : "#UIDemo.visible", + "binding_name_override" : "#visible", + "binding_type" : "collection" + } + ], + "visible" : "#UIDemo.visible" + } +} ``` ```python +import mod.client.extraClientApi as clientApi +ViewBinder = clientApi.GetViewBinderCls() +ViewRequest = clientApi.GetViewViewRequestCls() +ScreenNode = clientApi.GetScreenNodeCls() + class UIDemoScreen(ScreenNode): def __init__(self, namespace, name, param): - self.demoGridControl = None - ...... + ScreenNode.__init__(self, namespace, name, param) + self.demoGridControl = None + + def Create(self): + self.demoGridControl = self.GetBaseUIControl("/grid1") - def Create(self): - self.demoGridControl = self.GetBaseUIControl("/grid1") - ...... - - @ViewBinder.binding_collection(ViewBinder.BF_BindBool, "gridDemo", "#UIDemo.visible") + @ViewBinder.binding_collection(ViewBinder.BF_BindBool, "gridDemo", "#UIDemo.visible") def GridItemVisible(self, index): return index < self.showNum and self.demoGridControl.GetVisible() ``` @@ -1233,55 +1277,57 @@ class UIDemoScreen(ScreenNode): ProgressBar进度条控件,用于百分比显示进度 ```json - "progress_bar0" : { - "$clip_direction" : "left", - "$clip_ratio" : 0.0, - "$is_new_nine_slice" : false, - "$nine_slice_buttom" : 0, - "$nine_slice_left" : 0, - "$nine_slice_right" : 0, - "$nine_slice_top" : 0, - "$nineslice_size" : [ 0, 0, 0, 0 ], - "$progress_bar_empty_texture" : "textures/ui/empty_progress_bar", - "$progress_bar_filled_texture" : "textures/ui/filled_progress_bar", - "anchor_from" : "center", - "anchor_to" : "center", - "controls" : [ - { - "empty_progress_bar@fpsBattle.empty_progress_bar" : {} - }, - { - "filled_progress_bar@fpsBattle.filled_progress_bar" : {} - } - ], - "layer" : 8, - "offset" : [ 0, 0 ], - "size" : [ 100, 10 ], - "type" : "panel", - "visible" : true - }, - "empty_progress_bar" : { - "is_new_nine_slice" : "$is_new_nine_slice", - "layer" : 1, - "nine_slice_buttom" : "$nine_slice_buttom", - "nine_slice_left" : "$nine_slice_left", - "nine_slice_right" : "$nine_slice_right", - "nine_slice_top" : "$nine_slice_top", - "texture" : "$progress_bar_empty_texture", - "type" : "image" - }, - "filled_progress_bar" : { - "clip_direction" : "$clip_direction", - "clip_ratio" : "$clip_ratio", - "is_new_nine_slice" : "$is_new_nine_slice", - "layer" : 2, - "nine_slice_buttom" : "$nine_slice_buttom", - "nine_slice_left" : "$nine_slice_left", - "nine_slice_right" : "$nine_slice_right", - "nine_slice_top" : "$nine_slice_top", - "texture" : "$progress_bar_filled_texture", - "type" : "image" - }, +{ + "progress_bar0" : { + "$clip_direction" : "left", + "$clip_ratio" : 0.0, + "$is_new_nine_slice" : false, + "$nine_slice_buttom" : 0, + "$nine_slice_left" : 0, + "$nine_slice_right" : 0, + "$nine_slice_top" : 0, + "$nineslice_size" : [ 0, 0, 0, 0 ], + "$progress_bar_empty_texture" : "textures/ui/empty_progress_bar", + "$progress_bar_filled_texture" : "textures/ui/filled_progress_bar", + "anchor_from" : "center", + "anchor_to" : "center", + "controls" : [ + { + "empty_progress_bar@fpsBattle.empty_progress_bar" : {} + }, + { + "filled_progress_bar@fpsBattle.filled_progress_bar" : {} + } + ], + "layer" : 8, + "offset" : [ 0, 0 ], + "size" : [ 100, 10 ], + "type" : "panel", + "visible" : true + }, + "empty_progress_bar" : { + "is_new_nine_slice" : "$is_new_nine_slice", + "layer" : 1, + "nine_slice_buttom" : "$nine_slice_buttom", + "nine_slice_left" : "$nine_slice_left", + "nine_slice_right" : "$nine_slice_right", + "nine_slice_top" : "$nine_slice_top", + "texture" : "$progress_bar_empty_texture", + "type" : "image" + }, + "filled_progress_bar" : { + "clip_direction" : "$clip_direction", + "clip_ratio" : "$clip_ratio", + "is_new_nine_slice" : "$is_new_nine_slice", + "layer" : 2, + "nine_slice_buttom" : "$nine_slice_buttom", + "nine_slice_left" : "$nine_slice_left", + "nine_slice_right" : "$nine_slice_right", + "nine_slice_top" : "$nine_slice_top", + "texture" : "$progress_bar_filled_texture", + "type" : "image" + } +} ``` |
变量
| 解释 | @@ -1312,28 +1358,30 @@ ProgressBar进度条控件,用于百分比显示进度 开关控件,用于两个状态之间的切换 ```json -"switch_toggle0@common_toggles.switch_toggle_collection" : { - "$default_texture" : "textures/ui/toggle_off", - "$hover_texture" : "textures/ui/toggle_on", - "$pressed_no_hover_texture" : "textures/ui/toggle_on_hover", - "$pressed_texture" : "textures/ui/toggle_off_hover", - "$toggle_name" : "#fpsBattle.toggle_name", - "$toggle_state_binding_name" : "#fpsBattle.toggle_state", - "anchor_from" : "center", - "anchor_to" : "center", - "bindings" : [ - { - "binding_collection_name" : "", - "binding_condition" : "always_when_visible", - "binding_type" : "collection_details" - } - ], - "layer" : 6, - "offset" : [ 0, 0 ], - "size" : [ 100, 100 ], - "type" : "panel", - "visible" : true - }, +{ + "switch_toggle0@common_toggles.switch_toggle_collection" : { + "$default_texture" : "textures/ui/toggle_off", + "$hover_texture" : "textures/ui/toggle_on", + "$pressed_no_hover_texture" : "textures/ui/toggle_on_hover", + "$pressed_texture" : "textures/ui/toggle_off_hover", + "$toggle_name" : "#fpsBattle.toggle_name", + "$toggle_state_binding_name" : "#fpsBattle.toggle_state", + "anchor_from" : "center", + "anchor_to" : "center", + "bindings" : [ + { + "binding_collection_name" : "", + "binding_condition" : "always_when_visible", + "binding_type" : "collection_details" + } + ], + "layer" : 6, + "offset" : [ 0, 0 ], + "size" : [ 100, 100 ], + "type" : "panel", + "visible" : true + } +} ``` |
变量
| 解释 | @@ -1348,9 +1396,14 @@ ProgressBar进度条控件,用于百分比显示进度 * 注1 ```python +import mod.client.extraClientApi as clientApi +ViewBinder = clientApi.GetViewBinderCls() +ViewRequest = clientApi.GetViewViewRequestCls() +ScreenNode = clientApi.GetScreenNodeCls() + class TestScreen(ScreenNode): - def __init__(self, namespace, name, param): - ScreenNode.__init__(self, namespace, name, param) + def __init__(self, namespace, name, param): + ScreenNode.__init__(self, namespace, name, param) self.currentToggleShow = True @ViewBinder.binding(ViewBinder.BF_ToggleChanged) @@ -1358,7 +1411,7 @@ class TestScreen(ScreenNode): self.currentToggleShow = args["state"] return ViewRequest.Refresh - @ViewBinder.binding(ViewBinder.BF_BindBool) + @ViewBinder.binding(ViewBinder.BF_BindBool) def ReturnToggleState(self): return self.currentToggleShow @@ -1381,32 +1434,34 @@ class TestScreen(ScreenNode): 滑动条控件,用于拖动设置进度或百分比。 ```json -"slider0@common.slider": { - "$slider_tts_text_value": "#netease_tts_text_value", - "$slider_name": "#UIDemoScreen.OnDemoSliderChange", - "$slider_value_binding_name":"#UIDemoScreen.ReturnSliderValue", - "$slider_steps_binding_name": "#UIDemoScreen.ReturnSliderStep", - "$background_default_control": "common.slider_background", - "$progress_default_control": "common.slider_progress", - "$progress_default_clip_direction": "left", - "$background_hover_control": "common.slider_background_hover", - "$progress_hover_control": "common.slider_progress_hover", - "$progress_hover_clip_direction": "left", - "$slider_direction": "horizontal", - "$slider_box_layout": "common.slider_button_layout", - "$slider_box_hover_layout": "common.slider_button_hover_layout", - "$slider_box_locked_layout": "common.slider_button_locked_layout", - "$slider_box_indent_layout": "common.slider_button_indent_layout", - "$slider_box_size": [ 10, 16 ], - "size": [ 100, 10 ], - "offset": [ 0, 0 ], - "$slider_step_factory_control_ids": { - "slider_step": "@common.slider_step", - "slider_step_hover": "@common.slider_step_hover", - "slider_step_progress": "@common.slider_step_progress", - "slider_step_progress_hover": "@common.slider_step_progress_hover" - }, - } +{ + "slider0@common.slider": { + "$slider_tts_text_value": "#netease_tts_text_value", + "$slider_name": "#UIDemoScreen.OnDemoSliderChange", + "$slider_value_binding_name": "#UIDemoScreen.ReturnSliderValue", + "$slider_steps_binding_name": "#UIDemoScreen.ReturnSliderStep", + "$background_default_control": "common.slider_background", + "$progress_default_control": "common.slider_progress", + "$progress_default_clip_direction": "left", + "$background_hover_control": "common.slider_background_hover", + "$progress_hover_control": "common.slider_progress_hover", + "$progress_hover_clip_direction": "left", + "$slider_direction": "horizontal", + "$slider_box_layout": "common.slider_button_layout", + "$slider_box_hover_layout": "common.slider_button_hover_layout", + "$slider_box_locked_layout": "common.slider_button_locked_layout", + "$slider_box_indent_layout": "common.slider_button_indent_layout", + "$slider_box_size": [10, 16], + "size": [100, 10], + "offset": [0, 0], + "$slider_step_factory_control_ids": { + "slider_step": "@common.slider_step", + "slider_step_hover": "@common.slider_step_hover", + "slider_step_progress": "@common.slider_step_progress", + "slider_step_progress_hover": "@common.slider_step_progress_hover" + } + } +} ``` |
变量
| 解释 | @@ -1436,27 +1491,32 @@ class TestScreen(ScreenNode): * 注1 ```python +import mod.client.extraClientApi as clientApi +ViewBinder = clientApi.GetViewBinderCls() +ViewRequest = clientApi.GetViewViewRequestCls() +ScreenNode = clientApi.GetScreenNodeCls() + class UIDemoScreen(ScreenNode): - def __init__(self, namespace, name, param): - ScreenNode.__init__(self, namespace, name, param) + def __init__(self, namespace, name, param): + ScreenNode.__init__(self, namespace, name, param) self.sliderPercentValue = 0.5 # 百分比值 # self.sliderAbsValue = 5.0 # 固定值 @ViewBinder.binding(ViewBinder.BF_SliderChanged | ViewBinder.BF_SliderFinished) - def OnDemoSliderChange(self, value, isFinish, _unused): - self.sliderPercentValue = value # 百分比类型滑动条保存值 - # self.sliderAbsValue = value # 固定格类型滑动条保存值 - return ViewRequest.Refresh + def OnDemoSliderChange(self, value, isFinish, _unused): + self.sliderPercentValue = value # 百分比类型滑动条保存值 + # self.sliderAbsValue = value # 固定格类型滑动条保存值 + return ViewRequest.Refresh - @ViewBinder.binding(ViewBinder.BF_BindFloat) - def ReturnSliderValue(self): - return self.sliderPercentValue # 百分比类型滑动条返回值 - # return self.sliderAbsValue # 固定格类型滑动条返回值 + @ViewBinder.binding(ViewBinder.BF_BindFloat) + def ReturnSliderValue(self): + return self.sliderPercentValue # 百分比类型滑动条返回值 + # return self.sliderAbsValue # 固定格类型滑动条返回值 @ViewBinder.binding(ViewBinder.BF_BindInt) - def ReturnSliderStep(self): - return 1 # 百分比类型滑动条 - # return 10 # 固定格类型滑动条 + def ReturnSliderStep(self): + return 1 # 百分比类型滑动条 + # return 10 # 固定格类型滑动条 ``` 下图为Slider在游戏中的控件表现 @@ -1527,37 +1587,37 @@ def getFirstItemRange(itemNum): "controls": [ { "state_default@custom_wheel_namespace.wheel_state": { - "texture" : "textures/ui/circle/custom_wheel_selection_default" + "texture" : "textures/ui/circle/custom_wheel_selection_default" } }, { "state_0@custom_wheel_namespace.wheel_state": { - "texture" : "textures/ui/circle/custom_wheel_selection_0" + "texture" : "textures/ui/circle/custom_wheel_selection_0" } }, { "state_1@custom_wheel_namespace.wheel_state": { - "texture" : "textures/ui/circle/custom_wheel_selection_1" + "texture" : "textures/ui/circle/custom_wheel_selection_1" } }, { "state_2@custom_wheel_namespace.wheel_state": { - "texture" : "textures/ui/circle/custom_wheel_selection_2" + "texture" : "textures/ui/circle/custom_wheel_selection_2" } }, { "state_3@custom_wheel_namespace.wheel_state": { - "texture" : "textures/ui/circle/custom_wheel_selection_3" + "texture" : "textures/ui/circle/custom_wheel_selection_3" } }, { "state_4@custom_wheel_namespace.wheel_state": { - "texture" : "textures/ui/circle/custom_wheel_selection_4" + "texture" : "textures/ui/circle/custom_wheel_selection_4" } }, { "state_5@custom_wheel_namespace.wheel_state": { - "texture" : "textures/ui/circle/custom_wheel_selection_5" + "texture" : "textures/ui/circle/custom_wheel_selection_5" } } ] @@ -1630,11 +1690,13 @@ hover事件的触发本质上是与鼠标悬浮相关,在PC模式中,当鼠 ```json - "main" : { - "controls" : [], - "type" : "screen", - "gamepad_cursor_deflection_mode": true - }, +{ + "main" : { + "controls" : [], + "type" : "screen", + "gamepad_cursor_deflection_mode": true + } +} ``` @@ -1644,38 +1706,40 @@ hover事件的触发本质上是与鼠标悬浮相关,在PC模式中,当鼠 网易版单选下拉框,可以在给定的选项中进行选择。 ```json -"comboBoxPanel@combo_box.comboBoxPanel" : { - "$content_size":[ "100.0%+0.0px", 100 ], - "$item_size":[ "100.0%+0.0px", "10.0%x+0.0px" ], - "$title_label":"combo_box.titleLabel", - "$content_label":"combo_box.label", - "$title_down_image":"combo_box.dropdownImage", - "$title_up_image":"combo_box.dropupImage", - "$default_title_texture" : "textures/ui/button_borderless_light", - "$hover_title_texture" : "textures/ui/button_borderless_lighthover", - "$pressed_title_texture" : "textures/ui/button_borderless_lightpressed", - "$title_nineslice_size|default" : [ 0.0, 0.0, 0.0, 0.0 ], - "$default_item_texture" : "textures/ui/button_borderless_light", - "$hover_item_texture" : "textures/ui/button_borderless_lighthover", - "$pressed_item_texture" : "textures/ui/button_borderless_lightpressed", - "$item_nineslice_size|default" : [ 0.0, 0.0, 0.0, 0.0 ], - "$scroll_background_texture" : "textures/ui/ScrollRail", - "alpha" : 1.0, - "anchor_from" : "center", - "anchor_to" : "center", - "clip_offset" : [ 0, 0 ], - "clips_children" : false, - "enabled" : true, - "layer" : 0, - "max_size" : [ 0, 0 ], - "min_size" : [ 0, 0 ], - "offset" : [ 0.0, 0.0 ], - "priority" : 0, - "propagate_alpha" : false, - "size" : [ 120, 20 ], - "type" : "panel", - "visible" : true - } +{ + "comboBoxPanel@combo_box.comboBoxPanel" : { + "$content_size":[ "100.0%+0.0px", 100 ], + "$item_size":[ "100.0%+0.0px", "10.0%x+0.0px" ], + "$title_label":"combo_box.titleLabel", + "$content_label":"combo_box.label", + "$title_down_image":"combo_box.dropdownImage", + "$title_up_image":"combo_box.dropupImage", + "$default_title_texture" : "textures/ui/button_borderless_light", + "$hover_title_texture" : "textures/ui/button_borderless_lighthover", + "$pressed_title_texture" : "textures/ui/button_borderless_lightpressed", + "$title_nineslice_size|default" : [ 0.0, 0.0, 0.0, 0.0 ], + "$default_item_texture" : "textures/ui/button_borderless_light", + "$hover_item_texture" : "textures/ui/button_borderless_lighthover", + "$pressed_item_texture" : "textures/ui/button_borderless_lightpressed", + "$item_nineslice_size|default" : [ 0.0, 0.0, 0.0, 0.0 ], + "$scroll_background_texture" : "textures/ui/ScrollRail", + "alpha" : 1.0, + "anchor_from" : "center", + "anchor_to" : "center", + "clip_offset" : [ 0, 0 ], + "clips_children" : false, + "enabled" : true, + "layer" : 0, + "max_size" : [ 0, 0 ], + "min_size" : [ 0, 0 ], + "offset" : [ 0.0, 0.0 ], + "priority" : 0, + "propagate_alpha" : false, + "size" : [ 120, 20 ], + "type" : "panel", + "visible" : true + } +} ``` @@ -1712,38 +1776,40 @@ UI编辑器暂时不支持编辑 其中官方封装了地图界面基类 MiniMapBaseScreen 供开发者扩展。 ```json -"mainPanel@mini_map.mini_map_wrapper" : { - "anchor_from" : "top_right", - "anchor_to" : "top_right", - "layer" : 1, - "offset" : [ -10.0, 10.0 ], - "$enable_live_update": false, - "$live_update_interval": 5, - "$use_default_face_icon": true, - "$face_icon_size": [4,4], - "$face_icon_bg_color": "white", - "$highest_y": 0 - // 如果希望小地图能够被裁剪,请继承后修改controls如下: - "controls":[ - { - "mini_map_bg@mini_map.mini_map_bg": {} - }, - { - "netease_mini_map@mini_map.netease_mini_map": { - "allow_clipping":true, - "enable_scissor_test" : true - } - }, - { - "icon@mini_map.icon": {} - }, - { - "head_lbl@mini_map.head_label": {} - }, - { - "text_lbl@mini_map.text_label": {} - } - ] +{ + "mainPanel@mini_map.mini_map_wrapper" : { + "anchor_from" : "top_right", + "anchor_to" : "top_right", + "layer" : 1, + "offset" : [ -10.0, 10.0 ], + "$enable_live_update": false, + "$live_update_interval": 5, + "$use_default_face_icon": true, + "$face_icon_size": [4,4], + "$face_icon_bg_color": "white", + "$highest_y": 0, + // 如果希望小地图能够被裁剪,请继承后修改controls如下: + "controls":[ + { + "mini_map_bg@mini_map.mini_map_bg": {} + }, + { + "netease_mini_map@mini_map.netease_mini_map": { + "allow_clipping":true, + "enable_scissor_test" : true + } + }, + { + "icon@mini_map.icon": {} + }, + { + "head_lbl@mini_map.head_label": {} + }, + { + "text_lbl@mini_map.text_label": {} + } + ] + } } ``` @@ -1764,12 +1830,14 @@ UI编辑器暂时不支持编辑 该控件可以用于在ui上绘制渐变颜色 ```json -"gradient": { - "color1": [1, 0, 1, 1], - "color2": [0, 0, 1, 1], - "gradient_direction": "vertical", - "renderer": "gradient_renderer", - "type": "custom" +{ + "gradient": { + "color1": [1, 0, 1, 1], + "color2": [0, 0, 1, 1], + "gradient_direction": "vertical", + "renderer": "gradient_renderer", + "type": "custom" + } } ``` @@ -1874,6 +1942,10 @@ ScreenNode = clientApi.GetScreenNodeCls() ### UI界面初始化 ```python +import mod.client.extraClientApi as clientApi + +ScreenNode = clientApi.GetScreenNodeCls() + class TestScreen(ScreenNode): def __init__(self, namespace, name, param): ScreenNode.__init__(self, namespace, name, param) @@ -1884,32 +1956,32 @@ ScreenNode是我们的UI节点基类,必须继承。 ```python # Bind Type class ViewBinder(object): - ButtonFilter = 0x10000000 - BF_ButtonClickUp = 0 | ButtonFilter - BF_ButtonClickDown = 1 | ButtonFilter - BF_ButtonClick = 2 | ButtonFilter - BF_ButtonClickCancel= 3 - BF_InteractButtonClick = 4 - BindFilter = 0x01000000 - BF_BindBool = 5 | BindFilter - BF_BindInt = 6 | BindFilter - BF_BindFloat = 7 | BindFilter - BF_BindString = 8 | BindFilter - BF_BindGridSize = 9 | BindFilter - BF_BindColor = 10 | BindFilter - EditFilter = 0x00100000 - BF_EditChanged = 11 | EditFilter - BF_EditFinished = 12 | EditFilter + ButtonFilter = 0x10000000 + BF_ButtonClickUp = 0 | ButtonFilter + BF_ButtonClickDown = 1 | ButtonFilter + BF_ButtonClick = 2 | ButtonFilter + BF_ButtonClickCancel = 3 + BF_InteractButtonClick = 4 + BindFilter = 0x01000000 + BF_BindBool = 5 | BindFilter + BF_BindInt = 6 | BindFilter + BF_BindFloat = 7 | BindFilter + BF_BindString = 8 | BindFilter + BF_BindGridSize = 9 | BindFilter + BF_BindColor = 10 | BindFilter + EditFilter = 0x00100000 + BF_EditChanged = 11 | EditFilter + BF_EditFinished = 12 | EditFilter ToggleFilter = 0x00010000 - BF_ToggleChanged = 13 | ToggleFilter + BF_ToggleChanged = 13 | ToggleFilter + # Return Type class ViewRequest(object): - Nothing = 0 - Refresh = 1 << 0 - PointerHeldEventsRequest = 1 << 1 - PointerHeldEventsCancel = 1 << 2 - Exit = 1 << 3 - + Nothing = 0 + Refresh = 1 << 0 + PointerHeldEventsRequest = 1 << 1 + PointerHeldEventsCancel = 1 << 2 + Exit = 1 << 3 ``` ### UI绑定和返回 @@ -1940,19 +2012,25 @@ bind_flag为上文中绑定类型,binding_name为绑定名称。 binding_name为脚本绑定变量,binding_name_override为引擎变量,json格式如下 ```json - "bindings" : [ - { +{ + "bindings": [ + { "binding_condition" : "always", "binding_name" : "#scoreboard_grid.item_count", "binding_name_override" : "#StackGridItemsCount" - } - ] + } + ] +} ``` 对应的Python代码如下 ```python - @ViewBinder.binding(ViewBinder.BF_BindInt, "#scoreboard_grid.item_count") - def OnStarkGridResize(self): - return len(self.scoreBoardList) +import mod.client.extraClientApi as clientApi + +ViewBinder = clientApi.GetViewBinderCls() + +@ViewBinder.binding(ViewBinder.BF_BindInt, "#scoreboard_grid.item_count") +def OnStarkGridResize(self): + return len(self.scoreBoardList) ``` **binding_collection(bind_flag, collection_name, binding_name = None)** @@ -1962,38 +2040,46 @@ bind_flag为上文中的绑定类型,collection_name为集合名称,binding_ 集合的json如下: ```json -"collection_name" : "scoreboard_stackgrid" +{ + "collection_name" : "scoreboard_stackgrid" +} ``` 在集合的子控件中,binding_collection_name为集合名,binding_condition为绑定条件,binding_name为绑定名称,binding_type为collection绑定,property_bag设置他的初始值,text为它的绑定值。 ```json - "label_score_board" : { - "bindings" : [ - { - "binding_collection_name" : "scoreboard_stackgrid", - "binding_condition" : "always", - "binding_name" : "#label_score_board.text", - "binding_type" : "collection" - } - ], - "offset" : [ "0%+0 px", "0%+0px" ], - "property_bag" : { - "#label_score_board.text" : "666666666666" - }, - "text" : "#label_score_board.text", - "text_alignment" : "left", - "type" : "label", - "visible" : true - }, +{ + "label_score_board" : { + "bindings" : [ + { + "binding_collection_name" : "scoreboard_stackgrid", + "binding_condition" : "always", + "binding_name" : "#label_score_board.text", + "binding_type" : "collection" + } + ], + "offset" : [ "0%+0 px", "0%+0px" ], + "property_bag" : { + "#label_score_board.text" : "666666666666" + }, + "text" : "#label_score_board.text", + "text_alignment" : "left", + "type" : "label", + "visible" : true + } +} ``` 对应的Python代码如下,其中index表示在集合中的哪一元素。 ```python - @ViewBinder.binding_collection(ViewBinder.BF_BindString, "scoreboard_stackgrid", "#label_score_board.text") - def OnRefreshScoreBoardLabel(self, index): - return self.scoreBoardList[index] if len(self.scoreBoardList) > index else "" +import mod.client.extraClientApi as clientApi + +ViewBinder = clientApi.GetViewBinderCls() + +@ViewBinder.binding_collection(ViewBinder.BF_BindString, "scoreboard_stackgrid", "#label_score_board.text") +def OnRefreshScoreBoardLabel(self, index): + return self.scoreBoardList[index] if len(self.scoreBoardList) > index else "" ``` ## 接口调用说明 @@ -2009,10 +2095,11 @@ bind_flag为上文中的绑定类型,collection_name为集合名称,binding_ 假设设置Mod名称为"myModName",示例: ```python - @Mod.Binding(name = "myModName", version = "0.1") - class MyModClass(object): - def __init__(self): - pass +from mod.common.mod import Mod +@Mod.Binding(name = "myModName", version = "0.1") +class MyModClass(object): + def __init__(self): + pass ``` ### 界面创建流程及生命周期 @@ -2089,7 +2176,7 @@ bind_flag为上文中的绑定类型,collection_name为集合名称,binding_ 使用方法如下所示 -```json +```html // 定制化文本控件 ``` -```json +```html // 在非标签的内容 Dear player,
welcome to Minecraft,
where you can build your own world ``` -```json +```html // 按钮控件 // 注意:如果按钮控件空间不足以显示该字符串,多余部分将以"..."显示 :恭喜!
击杀了{"text" : "末影人", "format_code":"§2"} ``` @@ -2125,69 +2212,79 @@ Dear player,
welcome to Minecraft,
where you can build your own world #### 定制化文本控件 -在字符串中嵌入``样式文本会被解析成定制文本,与常规文本不同的是定制化文本可以独立设置文字的字体、大小、颜色等,丰富富文本的文本样式。label_data为特殊化数据,以下所列属性为必须属性,text为文本,font为字体,默认值为unicode,scale为字体缩放倍率,默认值为1.0,color为字体颜色,默认值为[1,1,1,1]。需要注意的是如果文本中存在中文字符则字体会被强制设置为unicode,此外如果字体缩放倍率过大该段文本将不会被显示。 +在字符串中嵌入``样式文本会被解析成定制文本,与常规文本不同的是定制化文本可以独立设置文字的字体、大小、颜色等,丰富富文本的文本样式。label_data为特殊化数据,以下所列属性为必须属性,text为文本,font为字体,默认值为unicode,scale为字体缩放倍率,默认值为1.0,color为字体颜色,默认值为[1,1,1,1]。需要注意的是如果文本中存在中文字符则字体会被强制设置为unicode,此外如果字体缩放倍率过大该段文本将不会被显示。 ```json - label_data:{ - "text" : "玩家一", - "font" : "smooth", - "scale": 3, - "color": [1,0,0,1] - } +{ + "label_data": { + "text" : "玩家一", + "font" : "smooth", + "scale": 3, + "color": [1,0,0,1] + } +} ``` #### 图片控件 -在字符串中嵌入`image_data`样式文本会被解析成图片,image_data为特殊化数据,以下所列属性为必须属性,texture为资源路径,x为图片宽度,y为图片高度 +在字符串中嵌入`"image_data"`样式文本会被解析成图片,image_data为特殊化数据,以下所列属性为必须属性,texture为资源路径,x为图片宽度,y为图片高度 ```json - image_data:{ - "texture":"texture/ui/laugh", - "x":30, - "y":30 +{ + "image_data": { + "texture":"texture/ui/laugh", + "x":30, + "y":30 } +} ``` #### 按钮 -在字符串中嵌入``样式会被解析成按钮,button_data为特殊化数据,开发者可以在其中添加符合json格式的自定义数据,在点击富文本中对应按钮时会将button_data通过回调函数整个返回,以下属性为必须属性,press_texture为按钮按下贴图,hover_texture为按钮鼠标悬浮贴图,default_texture为默认状态下按钮贴图,button_label为按钮上的问题,x为按钮宽度,y为按钮高度 +在字符串中嵌入``样式会被解析成按钮,button_data为特殊化数据,开发者可以在其中添加符合json格式的自定义数据,在点击富文本中对应按钮时会将button_data通过回调函数整个返回,以下属性为必须属性,press_texture为按钮按下贴图,hover_texture为按钮鼠标悬浮贴图,default_texture为默认状态下按钮贴图,button_label为按钮上的问题,x为按钮宽度,y为按钮高度 ```json - button_data:{ - "press_texture": "", - "hover_texture": "", - "default_texture": "", - "button_label": "", - "x":20, - "y":20 +{ + "button_data":{ + "press_texture": "", + "hover_texture": "", + "default_texture": "", + "button_label": "", + "x":20, + "y":20 } +} ``` #### 超链接 -在字符串中嵌入`link_data`样式会被解析成超链接,外观和普通文本无异但可以被点击,link_data为特殊化数据,开发者可以在其中添加符合json格式的自定义数据,在点击富文本中对应超链接时会将link_data通过回调函数整个返回,以下属性为必须属性,text表示显示文本,format_code表示该段显示文本的样式代码,注意,基岩版的文本控件不支持下划线和删除线。 +在字符串中嵌入`"link_data"`样式会被解析成超链接,外观和普通文本无异但可以被点击,link_data为特殊化数据,开发者可以在其中添加符合json格式的自定义数据,在点击富文本中对应超链接时会将link_data通过回调函数整个返回,以下属性为必须属性,text表示显示文本,format_code表示该段显示文本的样式代码,注意,基岩版的文本控件不支持下划线和删除线。 ```json - link_data:{ - "text":"末影人", - "format_code":"§2" - } +{ + "link_data":{ + "text":"末影人", + "format_code":"§2" + } +} ``` #### 序列帧动画 -在字符串中嵌入`sfx_data`样式文本会被解析成图片,sfx_data为特殊化数据,以下所列属性为必须属性,texture为资源路径,x为显示图片宽度,y为显示图片高度,uv_x为截取图片宽度,uv_y为截取图片高度,frame_count表示该序列帧的总帧数,fps为每秒执行帧数。 +在字符串中嵌入`"sfx_data"`样式文本会被解析成图片,sfx_data为特殊化数据,以下所列属性为必须属性,texture为资源路径,x为显示图片宽度,y为显示图片高度,uv_x为截取图片宽度,uv_y为截取图片高度,frame_count表示该序列帧的总帧数,fps为每秒执行帧数。 ```json - sfx_data:{ - "texture": "textures/ui/eating_apple", - "x":30, - "y":30, - "uv_x": 64, - "uv_y": 64, - "frame_count": 36, - "fps": 10 +{ + "sfx_data":{ + "texture": "textures/ui/eating_apple", + "x":30, + "y":30, + "uv_x": 64, + "uv_y": 64, + "frame_count": 36, + "fps": 10 } +} ``` ### 富文本成品范例 @@ -2229,28 +2326,30 @@ Dear player,
welcome to Minecraft,
where you can build your own world 开发者可以设置富文本的文本字体颜色,默认值为[1,1,1],白色 ```json - "main" : { - "absorbs_input" : true, - "always_accepts_input" : false, - "controls" : [ - { - "RichTextPanel@RichText.RichTextPanel" : {} - } - ], - "force_render_below" : false, - "is_showing_menu" : true, - "render_game_behind" : true, - "render_only_when_topmost" : true, - "should_steal_mouse" : false, - "type" : "screen" +{ + "main" : { + "absorbs_input" : true, + "always_accepts_input" : false, + "controls" : [ + { + "RichTextPanel@RichText.RichTextPanel" : {} + } + ], + "force_render_below" : false, + "is_showing_menu" : true, + "render_game_behind" : true, + "render_only_when_topmost" : true, + "should_steal_mouse" : false, + "type" : "screen" }, "RichTextPanel@rich_text.RichTextPanel" : { - "$rich_panel_bg": "textures/ui/effect_background", - "$rich_panel_nineslice_size": 0.01, - "$rich_panel_font_size" : "large", - "$rich_panel_font_scale_factor" : 2.0, - "$rich_panel_color" : [1,1,1] - }, + "$rich_panel_bg": "textures/ui/effect_background", + "$rich_panel_nineslice_size": 0.01, + "$rich_panel_font_size" : "large", + "$rich_panel_font_scale_factor" : 2.0, + "$rich_panel_color" : [1,1,1] + } +} ``` #### python脚本编写 @@ -2278,22 +2377,22 @@ Dear player,
welcome to Minecraft,
where you can build your own world 以下是示例 ```python - def CreateRichText(self): - self.richTextPath = "/RichTextPanel" - self.richTextItem = self.GetRichTextItem(self.richTextPath) - self.richTextItem.registerLinkItemClickCallback(self.OnLinkItemClickCallback) - self.richTextItem.registerButtonItemClickCallback(self.OnButtonItemClickCallback) - self.richTextItem.registerRichTextFinishCallback(self.OnRichTextCreateFinishCallback) - self.richTextItem.readRichText('[玩家]:恭喜!{"texture":"textures/ui/skin/ty_yuanshenghuli_0_0", "x":30, "y":30}击杀了{"text" : "末影人", "format_code":"§2"}{"texture": "textures/ui/eating_apple","x":30, "y":30,"uv_x": 64,"uv_y": 64,"frame_count": 36,"fps": 10}') +def CreateRichText(self): + self.richTextPath = "/RichTextPanel" + self.richTextItem = self.GetRichTextItem(self.richTextPath) + self.richTextItem.registerLinkItemClickCallback(self.OnLinkItemClickCallback) + self.richTextItem.registerButtonItemClickCallback(self.OnButtonItemClickCallback) + self.richTextItem.registerRichTextFinishCallback(self.OnRichTextCreateFinishCallback) + self.richTextItem.readRichText('[玩家]:恭喜!{"texture":"textures/ui/skin/ty_yuanshenghuli_0_0", "x":30, "y":30}击杀了{"text" : "末影人", "format_code":"§2"}{"texture": "textures/ui/eating_apple","x":30, "y":30,"uv_x": 64,"uv_y": 64,"frame_count": 36,"fps": 10}') - def OnButtonItemClickCallback(self, data, touchX, touchY): - print("---OnButtonItemClickCallback---", data, touchX, touchY) +def OnButtonItemClickCallback(self, data, touchX, touchY): + print("---OnButtonItemClickCallback---", data, touchX, touchY) - def OnLinkItemClickCallback(self, data, touchX, touchY): - print("---OnLinkItemClickCallback---", data, touchX, touchY) +def OnLinkItemClickCallback(self, data, touchX, touchY): + print("---OnLinkItemClickCallback---", data, touchX, touchY) - def OnRichTextCreateFinishCallback(self): - print("---OnRichTextCreateFinishCallback---") +def OnRichTextCreateFinishCallback(self): + print("---OnRichTextCreateFinishCallback---") ``` ##### 使用事项 diff --git a/mcguide/18-界面与交互/40-UIAPI文档.md b/mcguide/18-界面与交互/40-UIAPI文档.md index 02371ba..c1e41c8 100644 --- a/mcguide/18-界面与交互/40-UIAPI文档.md +++ b/mcguide/18-界面与交互/40-UIAPI文档.md @@ -23,8 +23,8 @@ sidebarDepth: 1 ScreenNode的一些有用的函数,界面Node节点的获取方式在[UI使用文档](30-UI说明文档.html)中有详细说明。 ```python - import mod.client.extraClientApi as clientApi - uiNode = clientApi.GetUI("myModName", "myUIName") +import mod.client.extraClientApi as clientApi +uiNode = clientApi.GetUI("myModName", "myUIName") ``` 假设下文中的函数,uiNode为获取到的ScreenNode继承类,调用的UI界面是按下面的节点树组织结构的 diff --git a/mcguide/18-界面与交互/61-原生界面修改文档.md b/mcguide/18-界面与交互/61-原生界面修改文档.md index cbb3b72..2306028 100644 --- a/mcguide/18-界面与交互/61-原生界面修改文档.md +++ b/mcguide/18-界面与交互/61-原生界面修改文档.md @@ -116,8 +116,10 @@ CustomUIScreenProxy是原生界面的代理类,可通过extraClientApi.GetUISc - 示例 ```python +# coding=utf-8 import client.extraClientApi as clientApi CustomUIScreenProxy = clientApi.GetUIScreenProxyCls() +ViewBinder = clientApi.GetViewBinderCls() class PauseScreenProxy(CustomUIScreenProxy): @@ -135,10 +137,10 @@ class PauseScreenProxy(CustomUIScreenProxy): @ViewBinder.binding(ViewBinder.BF_ToggleChanged, "#myMod.myToggle") def onToggleChanged(self, args): - """ - proxy也支持binding,这里展示的是绑定一类toggle(这类toggle甚至可以不存在),这类toggle满足"toggle_name"属性是"#myMod.myToggle"这一要求,当他们发生状态改变的时候就会调用该函数。 - """ - print("myToggle onToggleChanged: {}".format(args)) + """ + proxy也支持binding,这里展示的是绑定一类toggle(这类toggle甚至可以不存在),这类toggle满足"toggle_name"属性是"#myMod.myToggle"这一要求,当他们发生状态改变的时候就会调用该函数。 + """ + print("myToggle onToggleChanged: {}".format(args)) ``` diff --git a/mcguide/18-界面与交互/70-UI数据绑定.md b/mcguide/18-界面与交互/70-UI数据绑定.md index 0d6767b..10f7776 100644 --- a/mcguide/18-界面与交互/70-UI数据绑定.md +++ b/mcguide/18-界面与交互/70-UI数据绑定.md @@ -387,9 +387,9 @@ def OnItemToggleChecked(self, args): toggleIndex = 0 self.mCurItemIndex = toggleIndex itemDict = self.mItemData[self.mCurItemTab][toggleIndex] - self.SetSprite(self.mItemIcon, itemDict["icon"]) - self.SetText(self.mItemName, itemDict["name"]) - self.SetText(self.mItemDesc, itemDict["desc"]) + self.GetBaseUIControl(self.mItemIcon).asImage().SetSprite(itemDict["icon"]) + self.GetBaseUIControl(self.mItemName).asLabel().SetText(itemDict["name"]) + self.GetBaseUIControl(self.mItemDesc).asLabel().SetText(itemDict["desc"]) self.set_control_visible(self.mItemInfoWrap, True) ```