Bootstrap Chameleon Logo

Canvas Layout

Summary: 本文介绍了UE4中的自由布局选项,Canvas和Overlay。Canvas用于指定子控件的位置和尺寸,而Overlay按顺序堆叠子控件,共享相同的坐标。文章解释了如何在Canvas中使用位置、对齐、尺寸、内容填充和颜色,以及如何在各种情况下应用Overlay。

Canvas

SCanvas正如它的名字,和画布一样,可以指定子控件的位置和尺寸。一些复杂的,需要固定位置和尺寸的控件用Canvas布局就会很方便。比如下面例子中的“Rigging Tool”中,“角色”的各个部分是是通过Canvas lay

A humanoid layout combining buttons and SCanvas layout

    "Root":{
        "SBorder": {
            "BorderImage": {
                "Style": "FEditorStyle",
                "Brush": "ToolPanel.DarkGroupBorder"
            },
            "Content":{
                "Padding": [0, 20],
                "SCanvas": {
                    "ToolTipText": "Canvas is a layout widget that allows you to arbitrary position and size child widgets in a relative coordinate space",
                    "Slots": [
                        {
                            "Position": [97.5, 0],
                            "Size": [25, 20],
                            "SButton": {"ButtonColorAndOpacity": [0, 5, 0 ,1], "OnClick": "print('Head.')",
                                "ContentPadding": [-8, 0],
                                "Text": "^_^",
                                "ToolTipText": "Head"
                            }
                        },
                        {
                            "Position": [90, 22],
                            "Size": [40, 40],
                            "SButton": {"ButtonColorAndOpacity": [0, 2, 0 ,1], "OnClick": "print('Body.')"}
                        },
                        {
                            "Position": [70, 25],
                            "Size": [15, 40],
                            "SButton": {"ButtonColorAndOpacity": [2, 0, 0 ,1], "OnClick": "print('Right Arm.')"}
                        },
                        {
                            "Position": [135, 25],
                            "Size": [15, 40],
                            "SButton": {"ButtonColorAndOpacity": [0, 0, 2 ,1], "OnClick": "print('Left Arm.')"}
                        },
                        {
                            "Position": [95, 65],
                            "Size": [15, 25],
                            "SButton": {"ButtonColorAndOpacity": [1, 0, 0 ,1], "OnClick": "print('Right Upper Leg.')"}
                        },
                        {
                            "Position": [112, 65],
                            "Size": [15, 25],
                            "SButton": {"ButtonColorAndOpacity": [0, 0, 1 ,1], "OnClick": "print('Left Upper Leg.')"}
                        },
                        {
                            "Position": [95, 92],
                            "Size": [15, 27],
                            "SButton": {"ButtonColorAndOpacity": [1, 0, 0 ,1], "OnClick": "print('Right Leg.')"}
                        },
                        {
                            "Position": [112, 92],
                            "Size": [15, 27],
                            "SButton": {"ButtonColorAndOpacity": [0, 0, 1 ,1], "OnClick": "print('Left Leg.')"}
                        }
                    ]
                }
            }
        }
    }

Position

!!! 注意,这里的"Position"是相对位置,因此,如果我们想要整体调整按钮的位置,可以通过控制SCanvas自身或者其父组件的位置来做。 例如,下面的"Padding": [0, 20]讲SCanvas向下一定了20px。当然,更严谨的写法是 "Padding": [0, 0, 0, 20],这样不会影响Canvas下方的组件。

    "Padding": [0, 20],
    "SCanvas": {
        ...
    }

HAlign/VAlign

SCanvas组件中的子控件,默认是以"HAlign": "Left", "VAlign": "Top" 对齐到目标坐标的。

之前的腿部部分的代码,将ui左侧的角色的右脚按钮设置为向右对齐,Position也为"Position": [112, 65],

    {
        "Position": [95, 65],
        "Size": [15, 25],
        "SButton": {"ButtonColorAndOpacity": [1, 0, 0 ,1], "OnClick": "print('Right Upper Leg.')"}
    },
    {
        "Position": [112, 65],
        "Size": [15, 25],
        "SButton": {"ButtonColorAndOpacity": [0, 0, 1 ,1], "OnClick": "print('Left Upper Leg.')"}
    },

改为:

    {
        "Position": [112, 65],
        "Size": [15, 25],
        "HAlign": "Right",
        "SButton": {"ButtonColorAndOpacity": [1, 0, 0 ,1], "OnClick": "print('Right Upper Leg.')"}
    },
    {
        "Position": [112, 65],
        "Size": [15, 25],
        "SButton": {"ButtonColorAndOpacity": [0, 0, 1 ,1], "OnClick": "print('Left Upper Leg.')"}
    },

左右脚按钮会分别对齐的中线:[112, 65] 的位置

An arrow pointing to the humanoid layout's center two legs

"VAlign" 也时同理,可以控制控件与目标坐标的对齐方式。

"HAlign"可选值:

  • "Left"
  • "Center"
  • "Right"

VAlign可选值:

  • "Top"
  • "Center"
  • "Bottom"

Size

Size属性将设置子控件的尺寸

注意,Canvas 的Slot 没有"Padding"属性,因此不能在指定位置之后再次通过"Padding"来进行微调

按钮的 Content Padding 和 Color

Content Padding

有读者可能会注意到,上面头部按钮的代码中,我们使用了"ContentPadding": [-8, 0],这个奇怪的属性。

如果我们删除它,将会发现按钮中的文章 "Text": "^_^"将显示不出来。这是因为UE5在计算按钮尺寸时,左右各额外加上了8px,使得按钮尺寸过小时,上面的文本内容被空白区域遮挡。具体的详细说明可见这里ContentPadding

Color

同样还是头部的按钮,这里我们使用了"SButton": {"ButtonColorAndOpacity": [0, 5, 0, 1], 用一个数值为unreal.LinearColor(0,5,0,1) 的线性颜色为按钮的背景设置颜色。

注意,这里颜色值大于1了,目的是将其与按钮的暗色背景相乘,使得最终获得一个亮绿色。Hacky:D

Overlay

SOverlay布局会将各个子控件依次重叠排列,代码中靠后的Slot会依次覆盖在之前的Slot之上。各个Slot共享同样的坐标。

所以,如果我们将上面例子中的SCanvas放入到SOverlay布局中,并在并列的地方加上一个按钮,就会获得这样一个诡异的结果:

"SOverlay":
{
    "Slots": [
        {
            "SCanvas": {
                "ToolTipText": "Canvas is a layout widget that allows you to arbitrary position and size child widgets in a relative coordinate space",
                "Slots": [...]
            }
        },
        {
            "SButton": { "Text": "A Big Opacity Button", "ButtonColorAndOpacity": [1, 0, 0, 0.3],
                "VAlign": "Center",
                "HAlign": "Center"
            }
        }
    ]
}

一个半透明的按钮覆盖在了之前的"Rigging" 按钮上,并且处理了所有的点击事件,(下方的按钮无法被点击)

A GIF showing a button with SOverlay blocking the click message of the 'humanoid' buttons

应用

更创建的按钮是将图片作为工具的背景图,比如在地图编辑器的各个Tile的按钮下方,放上背景图片

A snapshot of map editor with a map background

或者将多个控件进行组合使用,比如将SButton 和SEditableText放在一起,使得控件能够有可编辑的文本和按钮

    "SOverlay": {
    "Slots": [{
            "SButton": {"ButtonStyle": {"Style": "FEditorStyle", "StyleName": "HoverHintOnly"}, "ContentPadding": [16, 0],
                "OnClick": "chameleon_shelf.on_button_click(id=0)",
                "Content": { "SImage": {"Aka": "Img_0", "ImagePathInPlugin": "Resources/PythonGreyIcon_40x.png", "ColorAndOpacity": [1,1,1,0.6]}}
            }
        },{
            "Padding": [0, 20, 0, 0],
            "SEditableText":{"Aka": "Txt_0", "Text": "", "ColorAndOpacity": [1,1,1,1], "Justification": "Right"}
        }
    ]
}

A snapshot of Chameleon Shelf Tool

关于Shelf Tools 的具体解释可以看这里:Shelf Tools