从 XML 文件高效创建 UI 元素 (OpenGL / C# NET 6.0)

发布于 2025-01-15 23:45:08 字数 2194 浏览 2 评论 0原文

我目前正在开发一个基于 OpenTK 的小型游戏框架。在这个项目中,还应该有一种方法可以通过在 XML 文件中定义 UI 元素的布局来轻松创建 UI 元素,例如 WPF 和 XAML,但复杂程度要低一些(没有计划绑定等)。

现在,当涉及到从 XML 文件高效创建这些 ui 元素时,我有点陷入困境。这个概念是,用于布局的核心元素(例如图像、标签和窗格)很少,所有更复杂元素的结构都在 XML 中定义并由单独的类(继承自 UIElement,所有 UIElement 的基类)表示。

例如,按钮的外观如下:

Button.xml

<Button Layout="AlignLayout Stretch Stretch">
    <Image Name="image"></Image>
    <Image Name="hoverImage"></Image>
    <Image Name="pressedImage"></Image>
    <AlignPane HorizontalLayout="Center" VerticalLayout="Center">
        <Label Name="label"
               IgnoreInputEvents="true">
        </Label>
    </AlignPane>
</Button>

Button.cs

public class Button : UIElement
{
    protected Image image;
    protected Image hoverImage;
    protected Image pressedImage;
    protected Label label;

    public Button(UIElement? parent, Texture2D backgroundTexture,
        Texture2D hoverTexture, Texture2D pressedTexture,
        string text) : base(parent)
    {
        // Receive XML layout here probably? (from cache, not parsed)

        image.Texture = backgroundTexture;
        hoverImage.Texture = hoverTexture;
        pressedImage.Texture = pressedTexture;
        label.Text = text;

        // ...
    }
}

,代码中的用法很简单:

Button startButton = new Button(OverlayUICanvas, bgTex, hovTex, prsTex, "Start");

或使用其他 XML 文件中的元素。

xml中的元素属性在相应的类中设置属性(“Name”除外,它预计将根元素中的字段/属性设置为创建的类的实例)

基本上我已经得到了类似的东西,除了它是超级低效(可能是因为所有反射都在进行,包括带参数的构造函数调用)。在测试时,加载只有 8 个元素的简单内容需要超过 100 毫秒。

如果我能以某种方式缓存加载的布局,然后创建一个新实例,而不需要再次进行所有反射(布局将在游戏开始时加载或其他什么),那也不会太糟糕,但我真的不知道如何我可以存档这个。

创建这些元素的新实例非常重要:想象一下游戏需要在运行时从列表或类似的东西创建一些元素。

我确实没有找到任何关于如何执行此操作的好信息,甚至不确定是否可以这样做。如果我理解正确的话,WPF 通过在编译时生成一些源代码来解决这个问题,但它指出这只适用于 netstandard2.0,如果这甚至可以帮助我解决这个问题,我很难理解。

如果您出于某种原因想自己查看当前源代码:

https: //github.com/BlakkM9/VengineX/tree/master/VengineX/UI

但请记住 - 这个项目是 WIP,处于非常非常早期的状态,真的不专业。

我很乐意提供任何可能引导我走向正确方向的提示和提示!

I'm currently working on a small game framework, build on top of OpenTK. In this project there should also be a way to easily create UI elements by defining their layout in an XML file, like WPF and XAML but way less complex (no bindings planned etc).

Now I'm kind of stuck when it comes to efficiently creating these ui elements from the XML file. The concept is that there are few core elements like image, label and panes for layouting and the structure of all more complex elements are defined in XML and represented by a seperated class (that inherits from UIElement, the base class for all UIElements).

For example, this is how it could look like for a button:

Button.xml

<Button Layout="AlignLayout Stretch Stretch">
    <Image Name="image"></Image>
    <Image Name="hoverImage"></Image>
    <Image Name="pressedImage"></Image>
    <AlignPane HorizontalLayout="Center" VerticalLayout="Center">
        <Label Name="label"
               IgnoreInputEvents="true">
        </Label>
    </AlignPane>
</Button>

Button.cs

public class Button : UIElement
{
    protected Image image;
    protected Image hoverImage;
    protected Image pressedImage;
    protected Label label;

    public Button(UIElement? parent, Texture2D backgroundTexture,
        Texture2D hoverTexture, Texture2D pressedTexture,
        string text) : base(parent)
    {
        // Receive XML layout here probably? (from cache, not parsed)

        image.Texture = backgroundTexture;
        hoverImage.Texture = hoverTexture;
        pressedImage.Texture = pressedTexture;
        label.Text = text;

        // ...
    }
}

and the usage in code would simply be:

Button startButton = new Button(OverlayUICanvas, bgTex, hovTex, prsTex, "Start");

or use the element in some other XML file.

The element attributes in xml set properties in the corresponding class (except "Name", which is expected to set the fields/properties in the root element to the instance of the created class)

Basically i got something like this working already except that it is super inefficient (probably because all the reflection going on including parametered constructor calls). While testing it took over 100ms to load something simple with just 8 total elements.

It wouldn't be too bad if i could somehow cache the loaded layout somehow and then just create a new instance, without all the reflection going on again (layout would be loaded at game start or something) but i really have no clue how i could archive this.

Creating new instance of these elements is pretty important: imagine the game needs to creates some elements at runtime from a list or something like that.

I didn't really found any good information on how to do this, not even sure if it is possible like that. If I undestood correctly, WPF solves this by generating some source code on compilation but it stated this only works for netstandard2.0 and I'm having a hard time wrapping my head around if this would even help me solve this problem.

If you want to take a look at the current source yourself for some reason:

https://github.com/BlakkM9/VengineX/tree/master/VengineX/UI

but please keep in mind - this project is WIP, in a very very early state and nothing professional, really.

I'm graceful for any tips and hints that might lead me in the right direction!

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。
列表为空,暂无数据
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文