From c89f782c15c03e22f48ce82486790a6826cfaecd Mon Sep 17 00:00:00 2001 From: knoxHuang Date: Mon, 4 Nov 2024 10:50:38 +0800 Subject: [PATCH] refine rich text and other i18n --- cocos/2d/components/rich-text.ts | 32 ++--- cocos/2d/framework/ui-renderer.ts | 1 - cocos/dragon-bones/ArmatureDisplay.ts | 1 - cocos/spine/skeleton.ts | 1 - editor/i18n/en/localization.js | 35 +----- editor/i18n/en/modules/ui.js | 126 ++++++++++++++++++-- editor/i18n/zh/assets.js | 1 + editor/i18n/zh/localization.js | 32 +---- editor/i18n/zh/modules/ui.js | 125 +++++++++++++++++--- editor/inspector/components/label.js | 47 +------- editor/inspector/components/rich-text.js | 141 ++++++++++++++++++++++- editor/inspector/contributions/node.js | 4 +- 12 files changed, 404 insertions(+), 142 deletions(-) diff --git a/cocos/2d/components/rich-text.ts b/cocos/2d/components/rich-text.ts index c352e867c34..958bae1b77b 100644 --- a/cocos/2d/components/rich-text.ts +++ b/cocos/2d/components/rich-text.ts @@ -23,7 +23,18 @@ THE SOFTWARE. */ -import { ccclass, executeInEditMode, executionOrder, help, menu, tooltip, multiline, type, displayOrder, serializable } from 'cc.decorator'; +import { + ccclass, + executeInEditMode, + executionOrder, + help, + menu, + multiline, + type, + displayOrder, + serializable, + editable, +} from 'cc.decorator'; import { DEBUG, DEV, EDITOR } from 'internal:constants'; import { Font, SpriteAtlas, TTFFont, SpriteFrame } from '../assets'; import { EventTouch } from '../../input/types'; @@ -162,7 +173,6 @@ export class RichText extends Component { * 富文本显示的文本内容。 */ @multiline - @tooltip('i18n:richtext.string') get string (): string { return this._string; } @@ -183,7 +193,6 @@ export class RichText extends Component { * 文本内容的水平对齐方式。 */ @type(HorizontalTextAlignment) - @tooltip('i18n:richtext.horizontal_align') get horizontalAlign (): HorizontalTextAlignment { return this._horizontalAlign; } @@ -206,7 +215,6 @@ export class RichText extends Component { * 文本内容的竖直对齐方式。 */ @type(VerticalTextAlignment) - @tooltip('i18n:richtext.vertical_align') get verticalAlign (): VerticalTextAlignment { return this._verticalAlign; } @@ -228,7 +236,7 @@ export class RichText extends Component { * @zh * 富文本字体大小。 */ - @tooltip('i18n:richtext.font_size') + @editable get fontSize (): number { return this._fontSize; } @@ -270,7 +278,7 @@ export class RichText extends Component { * @zh * 富文本定制系统字体。 */ - @tooltip('i18n:richtext.font_family') + @editable get fontFamily (): string { return this._fontFamily; } @@ -289,7 +297,6 @@ export class RichText extends Component { * 富文本定制字体。 */ @type(Font) - @tooltip('i18n:richtext.font') get font (): TTFFont | null { return this._font; } @@ -313,12 +320,11 @@ export class RichText extends Component { /** * @en - * Whether use system font name or not. + * Whether to use system font name or not. * * @zh * 是否使用系统字体。 */ - @tooltip('i18n:richtext.use_system_font') @displayOrder(12) get useSystemFont (): boolean { return this._isSystemFontUsed; @@ -350,7 +356,6 @@ export class RichText extends Component { * 文本缓存模式, 该模式只支持系统字体。 */ @type(CacheMode) - @tooltip('i18n:richtext.cache_mode') get cacheMode (): CacheMode { return this._cacheMode; } @@ -369,7 +374,7 @@ export class RichText extends Component { * @zh * 富文本的最大宽度。 */ - @tooltip('i18n:richtext.max_width') + @editable get maxWidth (): number { return this._maxWidth; } @@ -391,7 +396,7 @@ export class RichText extends Component { * @zh * 富文本行高。 */ - @tooltip('i18n:richtext.line_height') + @editable get lineHeight (): number { return this._lineHeight; } @@ -414,7 +419,6 @@ export class RichText extends Component { * 对于 img 标签里面的 src 属性名称,都需要在 imageAtlas 里面找到一个有效的 spriteFrame,否则 img tag 会判定为无效。 */ @type(SpriteAtlas) - @tooltip('i18n:richtext.image_atlas') get imageAtlas (): SpriteAtlas | null { return this._imageAtlas; } @@ -437,7 +441,7 @@ export class RichText extends Component { * @zh * 选中此选项后,RichText 将阻止节点边界框中的所有输入事件(鼠标和触摸),从而防止输入事件穿透到底层节点。 */ - @tooltip('i18n:richtext.handleTouchEvent') + @editable get handleTouchEvent (): boolean { return this._handleTouchEvent; } diff --git a/cocos/2d/framework/ui-renderer.ts b/cocos/2d/framework/ui-renderer.ts index c4e1cd1d32f..1bb55a0e652 100644 --- a/cocos/2d/framework/ui-renderer.ts +++ b/cocos/2d/framework/ui-renderer.ts @@ -168,7 +168,6 @@ export class UIRenderer extends Renderer { */ @type(Material) @displayOrder(0) - @displayName('CustomMaterial') @disallowAnimation get customMaterial (): Material | null { return this._customMaterial; diff --git a/cocos/dragon-bones/ArmatureDisplay.ts b/cocos/dragon-bones/ArmatureDisplay.ts index 615b501c053..c7f638dfbf5 100644 --- a/cocos/dragon-bones/ArmatureDisplay.ts +++ b/cocos/dragon-bones/ArmatureDisplay.ts @@ -699,7 +699,6 @@ export class ArmatureDisplay extends UIRenderer { @override @type(Material) @displayOrder(0) - @displayName('CustomMaterial') get customMaterial (): Material | null { return this._customMaterial; } diff --git a/cocos/spine/skeleton.ts b/cocos/spine/skeleton.ts index 7a1b3feda90..9e2eede6c15 100644 --- a/cocos/spine/skeleton.ts +++ b/cocos/spine/skeleton.ts @@ -643,7 +643,6 @@ export class Skeleton extends UIRenderer { @override @type(Material) @displayOrder(0) - @displayName('CustomMaterial') get customMaterial (): Material | null { return this._customMaterial; } diff --git a/editor/i18n/en/localization.js b/editor/i18n/en/localization.js index 7dc087d9334..89406e3b88d 100755 --- a/editor/i18n/en/localization.js +++ b/editor/i18n/en/localization.js @@ -8,7 +8,12 @@ const version = pkg.version.replace(/(^\d+\.\d+)\..*$/, (str, a) => { const url = 'https://docs.cocos.com/creator'; module.exports = link(mixin({ - + common: { + 'attribute': { + 'title': 'Attribute: ', + 'description': 'Description: ', + }, + }, classes: { 'cc': { 'animation': { @@ -315,14 +320,6 @@ module.exports = link(mixin({ csmTransitionRange: 'CSM layers transition range(in NDC space: value range is 0 to 1)', }, sprite: { - gray_scale: 'Whether turn on grayscale rendering mode', - sprite_frame: 'Sprite Frame image to use', - atlas: 'Atlas that the image belongs to', - type: - 'Rendering mode:
- Simple: Modifying the size will stretch the image as a whole, which is suitable for sequence frame animation and normal images.
' + - '- Sliced: When changing the size, the four corners will not stretch, which is suitable for UI buttons and panel backgrounds.
' + - '- Tiled : When changing the size, the original size image will continue to be tiled.
' + - '- Filled : set a certain starting position and direction of filling, and the picture can be cropped and displayed at a certain ratio.', original_size: "Use the Image's original size as the Node size?", edit_button: 'Edit', select_button: 'Select In Atlas', @@ -334,10 +331,6 @@ module.exports = link(mixin({ fill_range: 'The normalizad value indicates how much of the sprite we want to show', src_blend_factor: 'The source image blend mode', dst_blend_factor: 'The destination image blend mode', - size_mode: - 'Set the size of the node on which the Sprite component is on.
CUSTOM for setting width and height manually;
TRIMMED to use image size with transparent pixels trimmed;
RAW to use image size without trimming.', - trim: - "Whether to render transparent pixels around image in node's bounding box.
If you check this option the bounding box will not include transparent pixels around the image.", }, UIOpacity: { opacity: 'The value between 0 to 255 showing the transparency of the object', @@ -664,22 +657,6 @@ module.exports = link(mixin({ url: 'A given URL to be loaded by the Webview,
it should have a http or https prefix.', webviewEvents: "The Webview's event callback ,
it will be triggered when certain Webview event occurs.", }, - richtext: { - string: 'Text of the RichText, you could use BBcode in the string', - horizontal_align: 'Horizontal alignment', - vertical_align: 'Vertical alignment', - font_size: 'Font size, in points', - font: 'Custom TTF font of Rich Text', - font_family: 'Custom System font of Rich Text', - use_system_font: 'Using system font', - cache_mode: 'The cache mode of label. This mode only supports system fonts.', - max_width: 'The maximize width of RichText, pass 0 means not limit the maximize width.', - line_height: 'Line height, in points', - image_atlas: - 'The image atlas for the img tag. For each src value in the img tag,
there should be a valid sprite frame in the image atlas.', - handleTouchEvent: - 'Once checked, the Rich Text will block all input events (mouse and touch) within the bounding box of the node,
preventing the input from penetrating into the underlying node.', - }, UICoordinateTracker: { target: 'Target node', camera: 'The 3D camera representing the original coordinate system.', diff --git a/editor/i18n/en/modules/ui.js b/editor/i18n/en/modules/ui.js index 3a14a00f68b..c4724350a81 100644 --- a/editor/i18n/en/modules/ui.js +++ b/editor/i18n/en/modules/ui.js @@ -25,16 +25,16 @@ module.exports = { 'horizontalAlign': { displayName: 'Horizontal Alignment', tooltip: 'Horizontal alignment mode.', - tooltip_left: 'Align Left', - tooltip_right: 'Align Right', - tooltip_center: 'Align Center', + tooltip_left: 'Align Left.', + tooltip_right: 'Align Right.', + tooltip_center: 'Align Center.', }, 'verticalAlign': { displayName: 'Vertical Alignment', tooltip: 'Vertical alignment mode.', - tooltip_top: 'Align Top', - tooltip_bottom: 'Align Bottom', - tooltip_center: 'Align Center', + tooltip_top: 'Align Top.', + tooltip_bottom: 'Align Bottom.', + tooltip_center: 'Align Center.', }, 'fontSize': { displayName: 'Font Size', @@ -61,7 +61,8 @@ module.exports = { }, 'useSystemFont': { displayName: 'System Fonts', - tooltip: 'Whether to use system default fonts. The referenced font asset would be dereferenced once this option was checked.', + tooltip: 'Whether to use system default fonts. ' + + '
The referenced font asset would be dereferenced once this option was checked.', }, 'fontFamily': { displayName: 'Font Family', @@ -76,7 +77,7 @@ module.exports = { tooltip: 'Text cache modes:
' + '1. NONE: No cache,draw once.
' + '2. BITMAP: Text is added as a static image to the dynamic atlas for batch merging, but its content cannot be dynamically modified frequently.
' + - '3. CHAR: Split the text into characters and cache the character texture into a character atlas for reuse, ' + + '3. CHAR: Split the text into characters and cache the character texture into a character atlas for reuse,
' + 'which is suitable for text content with repeated character content and frequently updated.', }, 'isBold': { @@ -125,6 +126,115 @@ module.exports = { }, }, }, + 'RichText': { + properties: { + 'string': { + displayName: 'string', + tooltip: 'Text of the RichText, you could use BBcode in the string.', + }, + 'horizontalAlign': { + displayName: 'Horizontal Alignment', + tooltip: 'Horizontal alignment mode.', + tooltip_left: 'Align Left.', + tooltip_right: 'Align Right.', + tooltip_center: 'Align Center.', + }, + 'verticalAlign': { + displayName: 'Vertical Alignment', + tooltip: 'Vertical alignment mode.', + tooltip_top: 'Align Top.', + tooltip_bottom: 'Align Bottom.', + tooltip_center: 'Align Center.', + }, + 'fontSize': { + displayName: 'Font Size', + tooltip: 'Font size, in points.', + }, + 'fontColor': { + displayName: 'Color', + tooltip: 'Default text color for rich text. ' + + '
It takes effect when the text content does not have a color parameter set. ' + + '
Color cascading is not supported yet.', + }, + 'fontFamily': { + displayName: 'Font Family', + tooltip: 'Font names.', + }, + 'font': { + displayName: 'Font', + tooltip: 'Custom TTF font of Rich Text.', + }, + 'useSystemFont': { + displayName: 'System Fonts', + tooltip: 'Whether to use system default fonts. ' + + '
The referenced font asset would be dereferenced once this option was checked.', + }, + 'cacheMode': { + displayName: 'Cache Mode', + tooltip: 'Text cache modes:
' + + '1. NONE: No cache,draw once.
' + + '2. BITMAP: Text is added as a static image to the dynamic atlas for batch merging, but its content cannot be dynamically modified frequently.
' + + '3. CHAR: Split the text into characters and cache the character texture into a character atlas for reuse,
' + + 'which is suitable for text content with repeated character content and frequently updated.', + }, + 'maxWidth': { + displayName: 'Max Width', + tooltip: 'The maximize width of RichText, pass 0 means not limit the maximize width.', + }, + 'lineHeight': { + displayName: 'Line Height', + tooltip: 'Line height, in points.', + }, + 'imageAtlas': { + displayName: 'Image Atlas', + tooltip: 'The image atlas for the img tag. ' + + '
For each src value in the img tag, ' + + '
there should be a valid sprite frame in the image atlas.', + }, + 'handleTouchEvent': { + displayName: 'Block input events', + tooltip: 'Once checked, the Rich Text will block all input events (mouse and touch) within the bounding box of the node, ' + + '
preventing the input from penetrating into the underlying node.', + }, + }, + }, + 'Sprite': { + properties: { + __extends__: 'classes.cc.UIRenderer.properties', + 'grayscale': { + displayName: 'Grayscale', + tooltip: 'Whether turn on grayscale rendering mode.', + }, + 'spriteAtlas': { + displayName: 'Sprite Atlas', + tooltip: 'Atlas that the image belongs to.', + }, + 'sprite_frame': { + displayName: 'Sprite Frame', + tooltip: 'Sprite Frame image to use.', + }, + 'type': { + displayName: 'Type', + tooltip: 'Rendering mode:' + + '
- Simple: Modifying the size will stretch the image as a whole, which is suitable for sequence frame animation and normal images.
' + + '- Sliced: When changing the size, the four corners will not stretch, which is suitable for UI buttons and panel backgrounds.
' + + '- Tiled : When changing the size, the original size image will continue to be tiled.
' + + '- Filled : set a certain starting position and direction of filling, and the picture can be cropped and displayed at a certain ratio.', + }, + 'size_mode': { + displayName: 'Size Mode', + tooltip: 'Set the size of the node on which the Sprite component is on. ' + + '
CUSTOM for setting width and height manually;' + + '
TRIMMED to use image size with transparent pixels trimmed; ' + + '
RAW to use image size without trimming.', + }, + 'trim': { + displayName: 'Trim', + tooltip: "Whether to render transparent pixels around image in node's bounding box. " + + "
If you check this option the bounding box will not include transparent pixels around the image.", + }, + }, + }, }, }, }; diff --git a/editor/i18n/zh/assets.js b/editor/i18n/zh/assets.js index 6f4298b47a3..7702bdde45d 100644 --- a/editor/i18n/zh/assets.js +++ b/editor/i18n/zh/assets.js @@ -152,6 +152,7 @@ module.exports = { isRGBE: '作为 RGBE 格式', isRGBETip: '作为 RGBE 格式', flipGreenChannel: '翻转绿色通道', + flipGreenChannelTip: '是否翻转绿通道', }, spriteFrame: { packable: 'Packable', diff --git a/editor/i18n/zh/localization.js b/editor/i18n/zh/localization.js index c1e84f49f52..6b0adfc164e 100755 --- a/editor/i18n/zh/localization.js +++ b/editor/i18n/zh/localization.js @@ -8,7 +8,12 @@ const version = pkg.version.replace(/(^\d+\.\d+)\..*$/, (str, a) => { const url = 'https://docs.cocos.com/creator'; module.exports = link(mixin({ - + common: { + 'attribute': { + 'title': '属性:', + 'description': '描述:', + }, + }, classes: { 'cc': { 'animation': { @@ -305,14 +310,6 @@ module.exports = link(mixin({ csmTransitionRange: '级联阴影层级过渡范围(NDC空间: 取值范围为 0 ~ 1)', }, sprite: { - gray_scale: '是否开启灰度渲染模式', - atlas: '图片资源所属的 Atlas 图集资源', - sprite_frame: '渲染 Sprite 使用的 Sprite Frame 图片资源', - type: - '渲染模式:
- 普通(Simple):修改尺寸会整体拉伸图像,适用于序列帧动画和普通图像
' + - '- 九宫格 Sliced 修改尺寸时四个角的区域不会拉伸,适用于 UI 按钮和面板背景
' + - '- 平铺 Tiled 修改尺寸时会不断平铺原始大小的图片
' + - '- 填充 Filled 设置一定的填充起始位置和方向,能够以一定比率剪裁显示图片', original_size: '是否使用图片资源的原始尺寸作为 Sprite 节点的 size', edit_button: '编辑', select_button: '选择', @@ -324,9 +321,6 @@ module.exports = link(mixin({ fill_range: '填充总量,取值范围 0 ~ 1 指定显示图像范围的百分比', src_blend_factor: '混合显示两张图片时,源图片的取值模式', dst_blend_factor: '混合显示两张图片时,目标图片的取值模式', - size_mode: - '指定 Sprite 所在节点的尺寸
CUSTOM 表示自定义尺寸
TRIMMED 表示取原始图片剪裁透明像素后的尺寸
RAW 表示取原始图片未剪裁的尺寸', - trim: '节点约束框内是否包括透明像素区域,勾选此项会去除节点约束框内的透明区域', }, UIOpacity: { opacity: '设置物体的不透明度,取值范围为 0 ~ 255', @@ -648,20 +642,6 @@ module.exports = link(mixin({ url: '指定一个 URL 地址,这个地址以 http 或者 https 开头,请填写一个有效的 URL 地址。', webviewEvents: 'Webview 的回调事件,当网页加载过程中,加载完成后或者加载出错时都会回调此函数', }, - richtext: { - string: '富文本的内容字符串, 你可以在里面使用 BBCode 来指定特定文本的样式', - horizontal_align: '水平对齐方式', - vertical_align: '竖直对齐方式', - font_size: '字体大小, 单位是 point', - font: '富文本定制字体', - font_family: '富文本定制系统字体', - use_system_font: '是否使用系统字体', - cache_mode: '文本缓存模式, 该模式只支持系统字体', - max_width: '富文本的最大宽度, 传 0 的话意味着必须手动换行.', - line_height: '字体行高, 单位是 point', - image_atlas: '对于 img 标签里面的 src 属性名称,都需要在 image atlas 里面找到一个有效的 sprite frame,否则 img tag 会判定为无效', - handleTouchEvent: '选中此选项后,rich text 将阻止节点边界框中的所有输入事件(鼠标和触摸),从而防止输入事件穿透到底层节点', - }, UICoordinateTracker: { target: '目标对象', camera: '照射相机', diff --git a/editor/i18n/zh/modules/ui.js b/editor/i18n/zh/modules/ui.js index ca1306685c0..4e7afd6879f 100644 --- a/editor/i18n/zh/modules/ui.js +++ b/editor/i18n/zh/modules/ui.js @@ -25,16 +25,16 @@ module.exports = { 'horizontalAlign': { displayName: '水平对齐', tooltip: '文字水平对齐模式。', - tooltip_left: '左对齐', - tooltip_right: '右对齐', - tooltip_center: '居中对齐', + tooltip_left: '左对齐。', + tooltip_right: '右对齐。', + tooltip_center: '居中对齐。', }, 'verticalAlign': { displayName: '竖直对齐', tooltip: '文字竖直对齐模式。', - tooltip_top: '上对齐', - tooltip_bottom: '下对齐', - tooltip_center: '居中对齐', + tooltip_top: '上对齐。', + tooltip_bottom: '下对齐。', + tooltip_center: '居中对齐。', }, 'fontSize': { displayName: '字体大小', @@ -46,14 +46,14 @@ module.exports = { }, 'spacingX': { displayName: '水平间距', - tooltip: '文本字符之间的间距。仅在使用位图字体时生效', + tooltip: '文本字符之间的间距。仅在使用位图字体时生效。', }, 'overflow': { displayName: '溢出处理', tooltip: '文字排版模式,包括以下三种:
' + - '1. CLAMP: 节点约束框之外的文字会被截断
' + - '2. SHRINK: 自动根据节点约束框缩小文字
' + - '3. RESIZE: 根据文本内容自动更新节点的 height 属性.', + '1. CLAMP: 节点约束框之外的文字会被截断。
' + + '2. SHRINK: 自动根据节点约束框缩小文字。
' + + '3. RESIZE: 根据文本内容自动更新节点的 height 属性。', }, 'enableWrapText': { displayName: '自动换行', @@ -74,9 +74,9 @@ module.exports = { 'cacheMode': { displayName: '缓存模式', tooltip: '文本缓存模式,包括以下三种:
' + - '1. NONE: 不做任何缓存,文本内容进行一次绘制
' + - '2. BITMAP: 将文本作为静态图像加入动态图集进行批次合并,但是不能频繁动态修改文本内容
' + - '3. CHAR: 将文本拆分为字符并且把字符纹理缓存到一张字符图集中进行复用,适用于字符内容重复并且频繁更新的文本内容', + '1. NONE: 不做任何缓存,文本内容进行一次绘制。
' + + '2. BITMAP: 将文本作为静态图像加入动态图集进行批次合并,但是不能频繁动态修改文本内容。
' + + '3. CHAR: 将文本拆分为字符并且把字符纹理缓存到一张字符图集中进行复用,适用于字符内容重复并且频繁更新的文本内容。', }, 'isBold': { displayName: '粗体', @@ -124,6 +124,105 @@ module.exports = { }, }, }, + 'RichText': { + properties: { + 'string': { + tooltip: '显示的富文本内容字符串。', + }, + 'horizontalAlign': { + displayName: '水平对齐', + tooltip: '文字水平对齐模式。', + tooltip_left: '左对齐。', + tooltip_right: '右对齐。', + tooltip_center: '居中对齐。', + }, + 'verticalAlign': { + displayName: '竖直对齐', + tooltip: '文字竖直对齐模式。', + tooltip_top: '上对齐。', + tooltip_bottom: '下对齐。', + tooltip_center: '居中对齐。', + }, + 'fontSize': { + displayName: '字体大小', + tooltip: '文字尺寸,以点为单位。', + }, + 'fontColor': { + displayName: '颜色', + tooltip: '富文本默认文字颜色。在文本内容没有设置颜色参数时生效。暂不支持颜色级联。', + }, + 'fontFamily': { + displayName: '字体族', + tooltip: '文字字体名字。', + }, + 'font': { + displayName: '字体', + tooltip: '使用的字体资源。', + }, + 'useSystemFont': { + displayName: '系统字体', + tooltip: '是否使用系统默认字体,选中此项会将引用的字体资产置空。', + }, + 'cacheMode': { + displayName: '缓存模式', + tooltip: '文本缓存模式,包括以下三种:
' + + '1. NONE: 不做任何缓存,文本内容进行一次绘制。
' + + '2. BITMAP: 将文本作为静态图像加入动态图集进行批次合并,但是不能频繁动态修改文本内容。
' + + '3. CHAR: 将文本拆分为字符并且把字符纹理缓存到一张字符图集中进行复用,适用于字符内容重复并且频繁更新的文本内容。', + }, + 'maxWidth': { + displayName: '缓存模式', + tooltip: '富文本的最大宽度, 传 0 的话意味着必须手动换行。', + }, + 'lineHeight': { + displayName: '行高', + tooltip: '文字行高,以点为单位。', + }, + 'imageAtlas': { + displayName: '图集', + tooltip: '对于 img 标签里面的 src 属性名称,' + + '
都需要在 image atlas 里面找到一个有效的 sprite frame,' + + '
否则 img tag 会判定为无效。', + }, + 'handleTouchEvent': { + displayName: '阻止输入事件', + tooltip: '选中此选项后,rich text 将阻止节点边界框中的所有输入事件(鼠标和触摸),' + + '
从而防止输入事件穿透到底层节点。', + }, + }, + }, + 'Sprite': { + properties: { + __extends__: 'classes.cc.UIRenderer.properties', + 'grayscale': { + displayName: 'Grayscale', + tooltip: '是否开启灰度渲染模式', + }, + 'spriteAtlas': { + displayName: 'Sprite Atlas', + tooltip: '图片资源所属的 Atlas 图集资源', + }, + 'sprite_frame': { + displayName: 'Sprite Frame', + tooltip: '渲染 Sprite 使用的 Sprite Frame 图片资源', + }, + 'type': { + displayName: 'Type', + tooltip: '渲染模式:
- 普通(Simple):修改尺寸会整体拉伸图像,适用于序列帧动画和普通图像
' + + '- 九宫格 Sliced 修改尺寸时四个角的区域不会拉伸,适用于 UI 按钮和面板背景
' + + '- 平铺 Tiled 修改尺寸时会不断平铺原始大小的图片
' + + '- 填充 Filled 设置一定的填充起始位置和方向,能够以一定比率剪裁显示图片', + }, + 'size_mode': { + displayName: 'Size Mode', + tooltip: '指定 Sprite 所在节点的尺寸
CUSTOM 表示自定义尺寸
TRIMMED 表示取原始图片剪裁透明像素后的尺寸
RAW 表示取原始图片未剪裁的尺寸', + }, + 'trim': { + displayName: 'Trim', + tooltip: '节点约束框内是否包括透明像素区域,勾选此项会去除节点约束框内的透明区域', + }, + }, + }, }, }, }; diff --git a/editor/inspector/components/label.js b/editor/inspector/components/label.js index 1a5683e1eee..efb6f44f579 100644 --- a/editor/inspector/components/label.js +++ b/editor/inspector/components/label.js @@ -1,4 +1,4 @@ -const { getName, setHidden, isMultipleInvalid } = require('../utils/prop'); +const { setTooltip, setHidden, isMultipleInvalid, createRadioGroup, setLabel } = require('../utils/prop'); const { template, $, update, close } = require('./base'); const fontStyles = ['isBold', 'isItalic', 'isUnderline']; exports.template = template; @@ -50,42 +50,6 @@ ui-tab { } `; -/** - * - * @param {object} options - * @param {any[]} options.enumList - * @param {string} options.tooltip - * @param {(elementName: string) => string}options.getIconName - * @param {(event: CustomEvent) => {}} options.onChange - * @returns - */ -function createRadioGroup(options) { - const { enumList, getIconName, onChange, tooltip: rawTooltip } = options; - const $radioGroup = document.createElement('ui-radio-group'); - $radioGroup.setAttribute('slot', 'content'); - $radioGroup.addEventListener('change', (e) => { - onChange(e); - }); - - for (let index = 0; index < enumList.length; index++) { - const element = enumList[index]; - const icon = document.createElement('ui-icon'); - const button = document.createElement('ui-radio-button'); - - const iconName = getIconName(element.name); - const tooltip = `${rawTooltip}_${element.name.toLocaleLowerCase()}`; - - icon.value = iconName; - button.appendChild(icon); - button.value = element.value; - button.setAttribute('tooltip', tooltip); - - $radioGroup.appendChild(button); - } - - return $radioGroup; -} - exports.ready = function() { this.elements = { horizontalAlign: { @@ -94,8 +58,7 @@ exports.ready = function() { prop.dump = dump; const label = document.createElement('ui-label'); label.setAttribute('slot', 'label'); - label.value = getName(dump); - label.setAttribute('tooltip', dump.tooltip); + setLabel(dump, label); const content = createRadioGroup({ enumList: dump.enumList, @@ -139,8 +102,7 @@ exports.ready = function() { prop.dump = dump; const label = document.createElement('ui-label'); label.setAttribute('slot', 'label'); - label.value = getName(dump); - label.setAttribute('tooltip', dump.tooltip); + setLabel(dump, label); const content = createRadioGroup({ enumList: dump.enumList, @@ -197,7 +159,7 @@ exports.ready = function() { const label = document.createElement('ui-label'); label.innerHTML = styleDisplayNames[index]; label.setAttribute('key', style); - label.setAttribute('tooltip', this.dump.value[style].tooltip); + setTooltip(this.dump.value[style], label); label.classList.add('fontStyle', styleClassNames[index]); label.addEventListener('click', () => { prop.dump = this.dump.value[style]; @@ -242,6 +204,5 @@ exports.ready = function() { setHidden(true, element); }, }, - }; }; diff --git a/editor/inspector/components/rich-text.js b/editor/inspector/components/rich-text.js index 775fa94265d..66fbc9ca027 100644 --- a/editor/inspector/components/rich-text.js +++ b/editor/inspector/components/rich-text.js @@ -5,7 +5,54 @@ exports.$ = $; exports.update = update; exports.close = close; -const { setHidden, isMultipleInvalid } = require('../utils/prop'); +const { setHidden, isMultipleInvalid, getName, createRadioGroup, setLabel } = require('../utils/prop'); + +const fontStyles = ['isBold', 'isItalic', 'isUnderline']; + +exports.style = ` +ui-tab { + flex: none; +} + +.fontStyleParent { + display:flex +} + +.fontStyle:nth-child(2) { + margin-left: 5px; + margin-right: 5px; +} + +.fontStyle { + height: 20px; + width: 42px; + text-align: center; + line-height: 20px; + border: calc(var(--size-normal-border) * 1px) solid var(--color-default-border-weaker); + border-radius: calc(var(--size-normal-radius) * 1px); +} + +.fontStyle.invalid { + background-color: var(--color-default-fill); +} + +.fontStyle.select { + background-color: var(--color-info-fill-important); + border-color: var(--color-focus-border-emphasis); +} + +.fontStyle.italic { + font-style: italic; +} + +.fontStyle.bold { + font-weight: bold; +} + +.fontStyle.underline { + text-decoration-line: underline; +} +`; exports.ready = function() { this.elements = { @@ -14,14 +61,98 @@ exports.ready = function() { setHidden(isMultipleInvalid(dump.useSystemFont) || !dump.useSystemFont.value, element); }, }, - cacheMode: { + font: { update(element, dump) { - this.elements.fontFamily.update.call(this, element, dump); + setHidden(isMultipleInvalid(dump.useSystemFont) || !!dump.useSystemFont.value, element); }, }, - font: { + horizontalAlign: { + create(dump) { + const prop = document.createElement('ui-prop'); + prop.dump = dump; + const label = document.createElement('ui-label'); + label.setAttribute('slot', 'label'); + setLabel(dump, label); + + const content = createRadioGroup({ + enumList: dump.enumList, + tooltip: dump.tooltip, + getIconName: (elName) => { + const iconName = elName.toLocaleLowerCase(); + if (iconName === 'center') { + return `align-h-${iconName}`; + } + return `align-${iconName}`; + }, + onChange: (event) => { + const value = Number(event.target.value); + if (Number.isFinite(value) && value !== -1) { + dump.value = value; + if (dump.values) { + dump.values.forEach((_, index) => dump.values[index] = dump.value); + } + prop.dispatch('change-dump'); + prop.dispatch('confirm-dump'); + } + }, + }); + + prop.appendChild(label); + prop.appendChild(content); + return prop; + }, update(element, dump) { - setHidden(isMultipleInvalid(dump.useSystemFont) || !!dump.useSystemFont.value, element); + const radioGroup = element.querySelector('ui-radio-group'); + if (isMultipleInvalid(dump.horizontalAlign)) { + radioGroup.value = -1; + } else { + radioGroup.value = dump.horizontalAlign.value; + } + }, + }, + verticalAlign: { + create(dump) { + const prop = document.createElement('ui-prop'); + prop.dump = dump; + const label = document.createElement('ui-label'); + label.setAttribute('slot', 'label'); + setLabel(dump, label); + + const content = createRadioGroup({ + enumList: dump.enumList, + tooltip: dump.tooltip, + getIconName: (elementName) => { + const iconName = elementName.toLocaleLowerCase(); + if (iconName === 'center') { + return `align-v-${iconName}`; + } + return `align-${iconName}`; + }, + onChange: (e) => { + const enumVal = Number(e.target.value); + if (!Number.isFinite(enumVal) || enumVal === -1) { + return; + } + dump.value = enumVal; + if (dump.values) { + dump.values.forEach((_, index) => (dump.values[index] = dump.value)); + } + prop.dispatch('change-dump'); + prop.dispatch('confirm-dump'); + }, + }); + + prop.appendChild(label); + prop.appendChild(content); + return prop; + }, + update(element, dump) { + const radioGroup = element.querySelector('ui-radio-group'); + if (isMultipleInvalid(dump.verticalAlign)) { + radioGroup.value = -1; + } else { + radioGroup.value = dump.verticalAlign.value; + } }, }, }; diff --git a/editor/inspector/contributions/node.js b/editor/inspector/contributions/node.js index eff019cf046..bfc5b7a2d3f 100644 --- a/editor/inspector/contributions/node.js +++ b/editor/inspector/contributions/node.js @@ -6,7 +6,7 @@ const Profile = require('@base/electron-profile'); const { throttle } = require('lodash'); const utils = require('./utils'); const { trackEventWithTimer } = require('../utils/metrics'); -const { injectionStyle } = require('../utils/prop'); +const { injectionStyle, setLabel } = require('../utils/prop'); // ipc messages protocol const messageProtocol = { @@ -473,6 +473,7 @@ exports.$ = { nodeRotation: '.container > .body > .node > .rotation', nodeScale: '.container > .body > .node > .scale', nodeMobility: '.container > .body > .node > .mobility', + nodeLayer: '.container > .body > .node > .layer', nodeLayerSelect: '.container > .body > .node > .layer .layer-select', nodeLayerButton: '.container > .body > .node > .layer .layer-edit', @@ -1178,6 +1179,7 @@ const Elements = { panel.$.nodeRotation.render(panel.dump.rotation); panel.$.nodeScale.render(panel.dump.scale); panel.$.nodeMobility.render(panel.dump.mobility); + setLabel(panel.dump.layer, panel.$.nodeLayer); // 查找需要渲染的 component 列表 const componentList = [];