There are two main actors in this system: the Application State Manager and the Application State. The public interface related to transitions should be very simple.
Push(state, next_state, transfer_request) : Pauses the state, pushes next_state to the stack and starts next_state. When next_state finishes successfully, it will use the transfer_request to transfer data to state.
TargetSingleTile: This state does not have its own gui – it uses whatever gui was there before. It adds a selection of highlighted tiles, centered at the character. When the user clicks on a tile that is within the selection, the state completes successfully and transfers the selected tile to the parent. At the tile, a skeleton appears.
The system is still a bit rough around the edges, and it looks like it can be converted to a generic state machine (which I could reuse perhaps for some basic AI), but it's ok for now.
More widget work this week, but it's shaping up reasonably well, so next week I might actually be moving on to something else.
TileGrid rendering is now pixel-perfect for the single-rectangle case, so thankfully that bug is gone.
Given a database of allocated, configured but inactive widgets, we should at any point be able to clone one and activate it, ready for use, for example when spawning floaters and modal widgets.
Floater and modal widget functionality is now implemented: handling focus, input, spawning and destruction.
Widget dimensions get finalized at activation time. If widget dimensions are set to 0 or under, then we can calculate optimal dimensions based on what the widget really is, e.g. a text widget would calculate the optimal dimensions for the text that it will display. For padding the optimal dimensions, negative dimensions are interpreted as amount of padding to add to the optimal. Example: A textbox widget with dimensions (100, -16) will calculate the optimal box height given a width of 100, and will add 16 to that height: that will be the final height of the box on activation.
More widget work this week, implementing the specification for focus and input handling.
I now have a working Button, which is really a TextBox with special input hanlding: They send events when pressed/released, and can have a custom renderer for each case, so that for example a button can appear pressed when you click on it.
I also set up a working ListBox, which is a special container for buttons, which provides custom renderers for highlighted items and binds the number keys (1,2,3, etc) to the children buttons. This will be used for any dialog with options. I'm tempted to adjust the rendering logic so that each widget has a list of potential renderers (defaulting to a generic one) for any state combination: in/out-of-focus for all widgets and pressed or not for buttons.
Dense tile rendering: Instanced rendering of visible tiles, tile locations are implicit given the view grid start and size. We can use this for rendering tiles with per-tile individual data. In the below video "Widget test 1", this is how the tiles on the bottom-left are rendered.
Sparse tile rendering: Similar to the above, but we need to provide the tiles to be rendered explicitly, as a number of instances and per-instance data. In the below video "Widget test 1", this is how the flashing tiles are rendered.
Single rectangle: When the tilemap to be displayed is just a single, continuous texture and there are no per-tile data, there's no reason to use instancing. In this case, we can render just the part of the texture that's visible in the view grid. In both the below videos, this is how the biome map and DCSS tile map are rendered.
Here, I demonstrate the current version of my widget … zoo, with some animated margin corner tiles, button-pressing (that ugly little red box which goes darker) and tilegrids. For the tilemap display, I'm randomly setting the focal point with a keypress, and the widget refocuses appropriately. There is still some rendering bug with the selection square in the tilemap, where it is occasionally a bit off. Still eludes me, and I'll possibly spend way too much time to fix it.