tModLoader 基础UI

基础准备

​ 首先创建一个类,继承ModSystem,无特殊需求UI类也可以丢这个类里面,成为内部类。由于UI只需要在客户端就行了,所以使用特性标记,仅在客户端加载[Autoload(Side = ModSide.Client)]

方法 说明
Load() 用来载入UI
UpdateUI() 用来更新UI
ModifyInterfaceLayers((List layers) 用来确定UI所在层级,并注册UI层级
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
[Autoload(Side = ModSide.Client)]
class UISystem : ModSystem
{
	public override void Load()
	{
        base.Load();
    }
    
    public override void UpdateUI(GameTime gameTime)
	{
        base.UpdateUI(gameTime);
    }
    
    public override void ModifyInterfaceLayers(List<GameInterfaceLayer> layers)
	{
        base.ModifyInterfaceLayers(layers);
    }   
}

创建UI

​ 我们创建一个ModSystem的内部类,并继承UIState / UIElement,只需要重写OnInitialize()方法即可。在这个方法里面我们进行界面的创建 布局等。

1
2
3
4
5
6
7
public class BzaUI : UIState
{
    public override void OnInitialize()
	{
        base.OnInitialize();
    }
}

​ 原版有很多的控件供给我们使用,在Terraria.GameContent.UI.Elements名称空间下。我们使用UIImageButton创建一个自定义图像的按钮,并加入到画布中。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
public class BzaUI : UIState
{
    private UIImageButton MyButton;
    public override void OnInitialize()
	{
        //导入图片资源
        Asset<Texture2D> tex2d = Request<Texture2D>("ModName/xxxxx/imageName");
        //使用图片资源创建控件
        MyButton = new UIImageButton(tex2d);
        
        //将控件添加到父组件 如果想要自定义画布可以使用UIPanel类
        Append(MyButton);
        base.OnInitialize();
    }
}

使用UI

​ 在UI类创建完成后,就需要在ModSystem进行加载了,先创建一个我们自己的UI实例,然后创建UserInterface用来承载我们的UI

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
[Autoload(Side = ModSide.Client)]
class UISystem : ModSystem
{
    public BzaUI bzaUI;//自己的UI
    public UserInterface userInterface;//用户接口
    
	public override void Load()
	{
        bzaUI = new BzaUI();
        bzaUI.Activate();//激活

        userInterface = new UserInterface();
        userInterface.SetState(bzaUI);//将接口状态设置为我们的UI

        base.Load();
    }
    
    public override void UpdateUI(GameTime gameTime)
	{
        //每帧都更新UI
        userInterface?.Update(gameTime);
        base.UpdateUI(gameTime);
    }
}

​ 对于ModifyInterfaceLayers单独拉出来说,layers包含原版以及模组的全部UI层级。每个层级都有自己的名字。并且按照先后顺序进行绘制。具体可以使用ModderTool这个模组的一个用户接口层选项进行查看,我们就不定义他在谁之上谁之下了。直接往0处插入我们自己的图层。

​ 使用List(集合)中的Insert()方法可以往指定索引处插入数据。这边我指定0,然后创建一个LegacyGameInterfaceLayer就是图层。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
    public override void ModifyInterfaceLayers(List<GameInterfaceLayer> layers)
	{
        layers.Insert
		(
    		0, 
    		new LegacyGameInterfaceLayer(
             	"GensokyoWPNACC:Bza",	//我们层的名字
             	() =>{ bzaUI.Draw(Main.spriteBatch); return true;}, //一个func委托,里面是UI绘制的逻辑,返回UI是否可见
             	InterfaceScaleType.UI)	//我们图层的类型
        );
        base.ModifyInterfaceLayers(layers);
    }   

​ 现在进入游戏应该就能在不起眼的小角落看到你的按钮了 当然他现在什么也干不了

添加点击事件

​ 设置我们UI的TopLeft属性可以更改UI的位置

1
2
3
4
5
public override void OnInitialize()
{
	Top.Pixels = Main.screenHeight - 100;
	Left.Pixels = Main.screenWidth / 5;
}

​ 现在我们为按钮添加点击事件(伪代码)

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
public override void OnInitialize()
{
        Asset<Texture2D> tex2d = Request<Texture2D>("ModName/xxxxx/imageName");
        MyButton = new UIImageButton(tex2d);
        //添加事件
    	XAddIB.OnLeftClick += new MouseEvent(this.XAdd);

        Append(MyButton);
}

private void XAdd(UIMouseEvent evt, UIElement listeningElement)
{
    //方法逻辑
}

​ 这样我们单机按钮就会触发你的方法逻辑了 使用Visual Studio查看MyButton其中小闪电的就代表事件

绘制鼠标悬停文本

​ 直接上代码了,这个确实是没什么好讲的

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
public override void ModifyInterfaceLayers(List<GameInterfaceLayer> layers)
{
    layers.Insert
    (
        0, 
        new LegacyGameInterfaceLayer
            (
                 "GensokyoWPNACC:Bza",
                 () =>{
                        var sb = Main.spriteBatch;
                        var font = FontAssets.MouseText.Value;
                        var ms = Main.MouseScreen + new Vector2(0, -20);
                        var color = Color.White;
                        var rot = 0f;
                        var origin = Vector2.Zero;
                        var scale = new Vector2(1.2f, 1.2f);
                     	var drawText = "6666";

                        bzaUI.Draw(Main.spriteBatch);

                        //字体绘制
                     	//isOnButton使用OnMouseOver事件控制
                        if (BzaUI.isOnButton)
                        {
                            ChatManager.DrawColorCodedStringWithShadow(sb, font, drawText, ms, color, rot, origin, scale);
                        }
                        return true;
                 },
                 InterfaceScaleType.UI
            )
    );
    
    base.ModifyInterfaceLayers(layers);
}
使用 Hugo 构建
主题 StackJimmy 设计