Modding:Interfaces de Usuario (GUI)

From Vintage Story Wiki
This page is a translated version of the page Modding:GUIs and the translation is 89% complete.

This page was last verified for Vintage Story version 1.15.

Other languages:

Crear buenas interfaces gráficas de usuario es una tarea desafiante - a veces, incluso las empresas más grandes se equivocan.

En Vintage Story actualmente se necesitas formular tus GUI en código, lo que requiere un pensamiento espacial agudo. Con suerte, algún día tendremos un diseñador de Interfaz de Usuarios de apuntar y hacer clic que elimine mucho trabajo. Hasta entonces, estos son algunos de los elementos esenciales.

Protip:

Utilice la combinación de teclas de depuración para "Ciclar modos de esquema de diálogo" al crear una GUI. Dibujará contornos alrededor de los límites de los elementos de la GUI, lo que hará que sea mucho más fácil comprender cómo se traduce su código a la GUI visual.

Empezando

Debe encapsular cada cuadro de diálogo GUI en su propia clase, aunque un cuadro de diálogo puede constar de varias ventanas (el cuadro de diálogo de carácter básico, por ejemplo, tiene dos), uno para los dispositivos portátiles de los jugadores y otro para las estadísticas del jugador. Hay un par de clases básicas para hacerte la vida un poco más fácil.

GUI de Entidad de Bloque

TPara crear una GUI vinculada a una entidad de bloque, herede de GuiDialogBlockEntity. En el código de su entidad de bloque, puede crear y abrir esa interfaz gráfica de usuario, por ejemplo tras la interacción del jugador (ejemplo: Entidad de bloque de Molino, Bloque de dialogo de Molino)

HUD

Para crear un elemento GUI que no sea interactuable, herede de HudElement.

GUI de Proposito General

Para cualquier otro uso, herede de la clase de propósito general GuiDialog, del cual también heredan HudElement y GuiDialogBlockEntity. Puedes anular ToggleKeyCombinationCode a algo como "tuAsombrosoKeyCode" y use capi.Input.RegisterHotKey + capi.Input.SetHotKeyHandler para tener su propia tecla del teclado asignada para abrir/cerrar su GUI (ejemplo: Mapa del Mundo)

Conceptos básicos de la GUI

En general, puedes construir tu propio sistema GUI si lo deseas, simplemente anulando OnRenderGUI y renderiza lo que quieras. También hay una multitud de métodos reemplazables para manejar las entradas del mouse y del teclado; consulte también la DialogosGui clase en Github

Si desea utilizar el sistema GUI básico, su concepto es simplemente una lista plana o jerárquica de elementos GUI colocados en ciertas posiciones. La posición está determinada por una instancia de ElementBounds. Echemos un vistazo más de cerca a sus propiedades:

Limites de Elementos

  • FixedX/FixedY: La posición absoluta donde se debe colocar el elemento.
  • FixedWidth/FixedHeight: El ancho y alto absolutos del elemento.
  • FixedPaddingX/FixedPaddingY: El padding interior absoluto del elemento.
  • FixedMarginX/FixedMarginY: El padding exterior absoluto del elemento.
  • ParentBounds: Los límites principales, en los que reside este elemento
  • ChildBounds: Los límites secundarios que contiene este elemento
  • Alignment: La alineación del elemento. Si se establece en None se utiliza la posición fija X/Y. Para cualquier otro valor, se ignoran los valores fijos X/Y. Por ejemplo cuando usaste RightTop el elemento siempre estará en la esquina superior derecha de sus límites principales. Si se utiliza RightFixed el elemento estará alineado a la derecha, pero su posición Y está determinada por FixedY
  • HorizontalSizing/VerticalSizing: El método de dimensionamiento a utilizar puede ser Fixed (por defecto), Percentual o FitToChildren

GuiComposer

This is the component that builds and manages your GUI elements for you. You can create a composer via the client api: capi.Gui.CreateCompo(dialogName, bounds). You have to supply it with a unique identifier and the overall dialog bounds. Once you have a GUIComposer instance you can chain-add elements. Here's a small example:

private void SetupDialog()
{
    // Auto-sized dialog at the center of the screen
    ElementBounds dialogBounds = ElementStdBounds.AutosizedMainDialog.WithAlignment(EnumDialogArea.CenterMiddle);

    // Just a simple 300x300 pixel box
    ElementBounds textBounds = ElementBounds.Fixed(0, 0, 300, 300);
        
    SingleComposer = capi.Gui.CreateCompo("myAwesomeDialog", dialogBounds)
        .AddStaticText("This is a piece of text at the center of your screen - Enjoy!", CairoFont.WhiteDetailText(), textBounds)
        .Compose()
    ;
}

Some explanations:

  • ElementStdBounds: Contains a bunch of often used element bounds configurations. See also ElementStdBounds on Github.
  • ElementBounds.Fixed(0, 0, 300, 300): Create a new bounds instance with fixedX/Y at 0/0 and a fixed widt/height of 300/300 pixels.
  • CairoFont.WhiteDetailText(): Create a new font configuration based on a often used size and color, in this case white with font size 14
  • SingleComposer: This property is defined in the GuiDialog class. Its a getter/setter to the Composers dictionary. It contains all the "windows" of this dialog which are then rendered / handled by this GuiDialog instance

Fancying it up

This is of course the absolute minimum example that will only show some text. Let's add a title bar and a dialog background:

private void SetupDialog()
{
    // Auto-sized dialog at the center of the screen
    ElementBounds dialogBounds = ElementStdBounds.AutosizedMainDialog.WithAlignment(EnumDialogArea.CenterMiddle);

    // Just a simple 300x100 pixel box with 40 pixels top spacing for the title bar
    ElementBounds textBounds = ElementBounds.Fixed(0, 40, 300, 100);

    // Background boundaries. Again, just make it fit it's child elements, then add the text as a child element
    ElementBounds bgBounds = ElementBounds.Fill.WithFixedPadding(GuiStyle.ElementToDialogPadding);
    bgBounds.BothSizing = ElementSizing.FitToChildren;
    bgBounds.WithChildren(textBounds);

    SingleComposer = capi.Gui.CreateCompo("myAwesomeDialog", dialogBounds)
        .AddShadedDialogBG(bgBounds)
        .AddDialogTitleBar("Heck yeah!", OnTitleBarCloseClicked)
        .AddStaticText("This is a piece of text at the center of your screen - Enjoy!", CairoFont.WhiteDetailText(), textBounds)
        .Compose()
    ;
}

private void OnTitleBarCloseClicked()
{
    TryClose();
}

This covers some of the most basic parts. There is a grand amount of various pre-built UI elements that each come with their own argument list that are in dire need of Documentation. Here's an overview of some of the more commonly used ones

Dialog / Graphics

  • .AddShadedDialogBG: Draws a pretty background and dialog border
  • .AddDialogTitleBar: Draws a title bar with a close button and a button to move around the dialog
  • .AddInset: Adds a darkened section with a inset border around it

Text

  • .AddStaticText: Add a static snippet of text
  • .AddDynamicText: Add a snippet of text that can be set to other texts without the need to redraw the whole dialog
  • .AddRichtext: Same as .AddDynamicText but allows use of VTML - a minimalist version of HTML code
  • .AddHoverText: When the mouse cursor moves over the element boundaries, will show supplied text as a tooltip

UI Control/Input

  • .AddButton: Adds a clickable button
  • .AddDropDown: Adds a drop down element
  • .AddHorizontalTabs: Adds horizontally aligned tabs, like the ingame chat window has
  • .AddVerticalScrollbar: Adds a vertical scrollbar
  • .AddTextInput: Adds an single line editable text field
  • .AddNumberInput: Adds an editable text field built for entering numbers
  • .AddTextArea: Adds multiple line editable text field

Tables/Grids/Inventory

Other

  • .AddIf/.EndIf: Can be used to conditionally add certain elements (but you can also just split up your creation code for more fine grained control)
  • .BeginClip/.EndClip: Used in combination with a scrollbar to cut away oversized content, such as in the creative inventory
  • .AddStaticCustomDraw: Lets you define your own drawing code to be added to the GUI

Examples

A simple standard dialog, triggered by the keyboard key 'U'

public class GuiDialogAnnoyingText : GuiDialog
{
    public override string ToggleKeyCombinationCode => "annoyingtextgui";

    public GuiDialogAnnoyingText(ICoreClientAPI capi) : base(capi)
    {
        SetupDialog();
    }

    private void SetupDialog()
    {
        // Auto-sized dialog at the center of the screen
        ElementBounds dialogBounds = ElementStdBounds.AutosizedMainDialog.WithAlignment(EnumDialogArea.CenterMiddle);

        // Just a simple 300x300 pixel box
        ElementBounds textBounds = ElementBounds.Fixed(0, 40, 300, 100);

        // Background boundaries. Again, just make it fit it's child elements, then add the text as a child element
        ElementBounds bgBounds = ElementBounds.Fill.WithFixedPadding(GuiStyle.ElementToDialogPadding);
        bgBounds.BothSizing = ElementSizing.FitToChildren;
        bgBounds.WithChildren(textBounds);

        // Lastly, create the dialog
        SingleComposer = capi.Gui.CreateCompo("myAwesomeDialog", dialogBounds)
            .AddShadedDialogBG(bgBounds)
            .AddDialogTitleBar("Heck yeah!", OnTitleBarCloseClicked)
            .AddStaticText("This is a piece of text at the center of your screen - Enjoy!", CairoFont.WhiteDetailText(), textBounds)
            .Compose()
        ;
    }

    private void OnTitleBarCloseClicked()
    {
        TryClose();
    }
}

public class AnnoyingTextSystem : ModSystem
{
    ICoreClientAPI capi;
    GuiDialog dialog;

    public override bool ShouldLoad(EnumAppSide forSide)
    {
        return forSide == EnumAppSide.Client;
    }
        
    public override void StartClientSide(ICoreClientAPI api)
    {
        base.StartClientSide(api);

        dialog = new GuiDialogAnnoyingText(api);

        capi = api;
        capi.Input.RegisterHotKey("annoyingtextgui", "Annoys you with annoyingly centered text", GlKeys.U, HotkeyType.GUIOrOtherControls);
        capi.Input.SetHotKeyHandler("annoyingtextgui", ToggleGui);
    }

    private bool ToggleGui(KeyCombination comb)
    {
        if (dialog.IsOpened()) dialog.TryClose();
        else dialog.TryOpen();

        return true;
    }
}


TBD

More to come here in the future.

Icon Sign.png

Wondering where some links have gone?
The modding navbox is going through some changes! Check out Navigation Box Updates for more info and help finding specific pages.

Modding
Modding Introduction Getting Started Pack Temático
Content Modding Content Mods Developing a Content Mod Basic Tutorials Intermediate Tutorials Advanced Tutorials Content Mod Concepts
Code Modding Code Mods Setting up your Development Environment
Property Overview ItemEntityEntity BehaviorsBlockBlock BehaviorsBlock ClassesBlock EntitiesBlock Entity BehaviorsCollectible BehaviorsWorld properties
Workflows & Infrastructure Modding Efficiency TipsMod-engine compatibilityMod ExtensibilityVS Engine
Additional Resources Community Resources Modding API Updates Programming Languages List of server commandsList of client commandsClient startup parametersServer startup parameters
Example ModsAPI DocsGitHub Repository