GUI Controls update proposal

Started by Crimson Wizard, Wed 03/07/2024 14:02:22

Previous topic - Next topic

Crimson Wizard

GUI controls in AGS games did not receive much updates since it turned opensource. While AGS allows to create many custom things with scripting, using raw drawing and/or overlays (for instance), there are situations when things would rather be achieved using standard GUI controls, but they are either missing a property or behavior.

Here I tried to organize ideas and requests that I heard over previous years. I think that for the long term it's best to not rush adding stuff to gui controls, but think this over first. I also think that, since GUI controls have a class hierarchy already, it is easier to expand multiple controls at once, as you may add common behavior to the parent class instead of adding same thing to many controls many times.

I also look at some classic GUI frameworks, such as C# WinForms, for comparison and example.

Related tickets (some directly, some indirectly):
https://github.com/adventuregamestudio/ags/issues/1208
https://github.com/adventuregamestudio/ags/issues/472
https://github.com/adventuregamestudio/ags/issues/669
https://github.com/adventuregamestudio/ags/issues/1876

NOTE: here I would not like to discuss dynamic creation of GUI controls (a well known request), as that's tangential to their looks and behavior.


So here's my thoughts and proposals.
Following list may be amended and altered after discussion.


1. Common Control events.

GUIControl should have a OnClick event, available to all the subtypes.
In addition to that: OnMouseDown/OnMouseUp events, in case one wants to distinct these events. @eri0o once suggested to have more "generic" name like OnPointerDown/OnPointerUp, suitable for multiple sorts of "devices". There may be other alternatives (to avoid mixing "pointer" terms), e.g. OnCursorDown/Up, etc.

The purpose of having these in the parent class is to let script low-level handling of player's input for any control.

2. Common Control appearance.

GUIControl should have Background and Border properties, so these are available to all subtypes. Including Background/Border Color and Image.
Optionally: Border width.
Optionally, Advanced: tiled Border graphics (but not sure how to configure these conveniently).

Alternatively, we might insert an intermediate class, something like FrameControl, which defines a control which has a "box" like appearance. This will keep an option to have controls derived from GUIControl but having a completely different kind of appearance.

The reasoning: sometimes user may like to have an underlaying color or image for a control, but with the exception of a Button (and maybe Slider) there's no direct way to do this. The workarounds are: either put another nonclickable button with a graphic underneath, or paint GUI background. The latter is inconvenient, as you will have to repaint it anytime if controls are moved.

This involves properties:
* BackgroundColor;
* BorderColor;
* BorderWidth;
* Image; maybe having "Image" is better than "BackgroundImage"? but need to consider pre-existing properties in derived controls, such as Button and Slider.
* ImageStyle: normal, stretched, tiled (?).

3. Labels.

Labels are defined as a control that displays a text or image and does not have any additional "interactive states" or values.

OTOH there's a suggestion to make Labels support image animation, similar to how Buttons are animated currently (Animate command). See the feature suggestion ticket.

New properties:
* Padding for the text or image. (ticket)
* Full set of TextAlignment options (like Button has currently).
If animation is supported, then it also will have to have:
* readonly View, Loop, Frame.

4. Buttons.

Buttons become a subtype of Label, inheriting its properties and behavior.
They are defined as a control that has multiple states depending on user input: normal, highlighted (under cursor), pushed.

While Buttons may reuse "BackgroundColor" as "NormalColor" (it's not necessary to do this though), they have multiple states, and so would likely need extra Color properties for "MouseOver" and "Pushed" state as well.

In regards to the BorderColor, buttons have a quirk that in their 3D look they draw border with 2 colors: a lighter color on top and left and darker color on right and bottom. At the moment I'm not sure which would be the best option here. Either they may derive these by mathematically darkening/lightening BorderColor property value, or require separate properties.

Buttons should have a ClickAction and NewModeNumber properties deprecated. These properties are a legacy from times when Iconbars were not scripted, but had cursor modes appointed to each button. All of this may be done in script now.
ClickAction = NoAction is equivalent to not having any registered OnClick function, so that's similarly redundant.
Buttons will simply be either ones which run some script on OnClick or not.

5. ListBoxes.

Properties that let to define a fixed row height, and/or row padding (padding is added to the font's height). I suppose that row height should be exclusive with row padding.
Text alignment including vertical alignment, in case row height is larger than the font.

Support for multiline List items, where a long text is wrapped into multiple lines instead of being cut at the control's edge.
(This may be mutually exclusive with row height)

Item arrangement property: allow to display items from bottom up.

Custom graphics for the scrollbar: arrow sprite(s), scrollbar sprite, scroll position sprite. And/or tiled scrollbar setting, where scrollbar is defined by upper/bottom edge and a middle tile.

eri0o

About controls and touch

I think I don't feel more like the OnPointer approach would be good to be exposed to scripting now after investigation on the touch, and touch and mouse have subtle different behavior - like the release of a button in touch being when finger isn't on top of the button anymore and with mouse is when releasing the button. We could still use this inside AGS if convenient, but I think scripting wise touch and mouse would work better as separate things. We could allow to emulate one or the other to make it easier to test things - like emulate touch with the mouse so you can test touch controls on the desktop.

To me this interaction aspect is the more important.

Spoiler
the below topic is hugely complex and MUCH more complicated... So it's hidden here.

On the topic of alternative GUI controls, one that I thought a lot was the use of keyboard to navigate (this usually implies a concept of a GUI being selected). I couldn't figure anyway that wasn't restrictive and came to the conclusion of leaving to scripting. I played with dear imgui previously and a huge chunk of commits fixing stuff is in keyboard navigation, which is a "minor" feature comparing to everything else. Also imgui is a hugely complex library with it's own set of issues but it is a possible alternative internal engine to use under the hood for GUIs - but integrating it for such type of use case is hard.
[close]

About appearance

Also regarding buttons and GUIs, they could use some way of using 9 piece applied to them (see my fancy module) so one could "theme" GUIs more easily.

Crimson Wizard

Dave Gilbert have recently reported a problem where ListBox is not arranging items far enough from each other. Maybe this have happened before to someone elese. Unlike Label control, which uses LineSpacing when wrapping text, ListBox is still using font's height to define item's height.

I am in doubts whether this will be correct to use LineSpacing in ListBox, as line spacing is meant for wrapping same text, while list box items are sort of separate entities.

Alternatively, ListBox could have an explicit "row height" property, and/or "row padding" property.

SMF spam blocked by CleanTalk