nstgeorge / VEKTA

A space exploration game created in Processing 3 with orbital mechanics
MIT License
1 stars 1 forks source link

Add an HTML-style UI markup system #96

Open rvanasa opened 3 years ago

rvanasa commented 3 years ago

Short Description

In order to make UI elements as clean and reusable as possible, a modular (probably XML-based) markup system would be tremendously helpful.

More Details

Let's use this discussion thread to brainstorm ideas and experiment with hypothetical XML snippets, since I want to have a good sense of how this will work before starting the project.

@nstgeorge, if you have some spare time, would you mind writing out an example of how you'd imagine something like the player's inventory structured as an XML file? It'll be good for us to figure out what specifically should be possible to customize.

Here's a very loose/incomplete idea for how it could work (left-side item info, right-side menu buttons):

<HorizontalLayout spacing="2" widths="equal">
    <If exists="cursorItem">
        <ItemInfo item="cursorItem" />
    </If>
    <Menu spacing="0.5">
        <ForEach ref="item" in="inventory">
            <ItemButton item="item" cursorRef="cursorItem" />
        </ForEach>
        <BackButton />
    </Menu>
</HorizontalLayout>
nstgeorge commented 3 years ago

Sure. Here's something like what I'm thinking, borrowing a lot of language from CSS Flexbox, Bootstrap, and Angular. This page would have an item list on the left with an item name, picture, and short description on the right.

<container layout="row" justify="center">
    <list>
        <button class="item-list" foreach="item in inventory" name="$item.name" selected="item == selectedItem" color="$item.color" disabled="!item.isAvailable" />
        <button name="Back" padding="2" />
    </list>
    <container>
        <title level="1" name="$selectedItem.name" padding="2" />
        <!-- Imaginary image -->
        <image src="$selectedItem.image" padding="2" />
        <p text="$selectedItem.desc" />
    </container>
</container>

I don't feel too strongly on the capitalization, if you like title case we can go with that. Also, the class option in the button might not be feasible, I guess it depends on how we want to handle styling. I think standardizing everything while supplying ways to override some common options might be fine, and we could eliminate the use of classes. Also not super happy with the name field, could be more clear that that is what will be displayed by those objects. Similarly, not sure if the dollar sign variable functionality is best for fields that expect raw text.

What I really do like here is how the layout is implied by the code itself. We don't have to specify a whole lot of detail, because we can figure out the intent. If the width of these objects isn't given, we can assume they evenly divide the screen; The padding is standard if not supplied; the layouts, when not given, could default to column; etc. That's what I'm really looking for from this, personally. We can simplify the XML page layout by being smart about assumptions.

nstgeorge commented 3 years ago

Writing in this way will also allow us to define constants across the entire UI that can easily be tuned later. The less styling we can specify within the XML, the better, I think.

rvanasa commented 3 years ago

Your example would definitely be the ideal way to do this. The capital case "paradigm" would correspond to an extensible class hierarchy (essentially React components or C# serialization), whereas the lowercase style would imply using a system like HTML/Bootstrap, which have highly standardized logic nuggets which compose together to create anything.

Agreed about having "reasonable defaults" for everything, such as padding="1" (standard unit), left justified, etc. And yeah we can figure out styling later.

For the name and text fields, we could just write user-facing text in between the open/close tags (e.g. <p>{$selectedItem.desc}</p> or something like that).

Another thing to consider is defining modular templates or "components" similar to React, since I think it's important for making the markup cleaner and more self-documenting. For instance, we could convert between both our examples using the following sort of structure:

<template name="HorizontalLayout">
    <container layout="row" justify="$props.justify" ...>
        {$props.children}
    </container>
</template>

<HorizontalLayout justify="center" />
 is equivalent to 
<container layout="row" justify="center" />

(The {$props.children} line is referencing everything between the open/close tags of the template, similar to React)

This way, we can avoid having to copy/paste the most common patterns, which will make the UI a lot more maintainable in the long term.

nstgeorge commented 3 years ago

Yep, big fan of all of those ideas. The template stuff in particular seems like it would be very helpful.

Since we're designing this "language" for this very specific use case, we can standardize a lot of stuff on the backend, so those "highly standardized logic nuggets" (I'm on mobile so I can't see exactly what you said) can be really powerful for us, even more so than in other web UI platforms.

rvanasa commented 3 years ago

Absolutely. This will make life so much easier for us.