Angband.oook.cz
Angband.oook.cz
AboutVariantsLadderForumCompetitionComicScreenshotsFunniesLinks

Go Back   Angband Forums > Angband > Development

Reply
 
Thread Tools Display Modes
Old July 10, 2016, 20:58   #1
t4nk
Adept
 
Join Date: May 2016
Posts: 249
t4nk is on a distinguished road
Textui reform (warning: long and full of C)

First of all; I think that textui (the stuff in ui-*.[ch] files) is actually a pretty good UI. It performs its functions well, and, IMO, it looks nice (in an old school kind of way ). It's also a rather significant amount of tested, debugged code. Therefore, I think it's desirable to use as much of it as possible. Textui, however, does have significant technical problems. I assume that the readers of this post are well aware of what these problems are.
Here's my tentative plan for textui reform.
term_screen
Global Term will be replaced by global stack of terms
Code:
static struct {
    term *stack[TERM_STACK_MAX];
    size_t top;
} term_stack = {
    .stack[0] = term_screen
};
(or something like that; note that term_stack is NOT a replacement for angband_term[]; the latter will still exist). Some new functions will be added to ui-term.c (or, perhaps, to ui2-term.c); the main ones are Term_push(term *, struct term_hints *) and Term_pop(void). They will replace two constructions currently used in textui; the first one is
a) Term_activate
Code:
    term *old = Term;
    Term_activate(inv_term);
    ...
    Term_activate(old);
instead, it will become:
Code:
    Term_push(inv_term, NULL);
    ...
    Term_pop();
I think this is pretty self-explanatory. Another, much more important role for Term_push() and Term_pop() is
b) screen_save and screen_load
Code:
    screen_save();
    ...
    menu_select();
    ...
    screen_load();
saving and loading term_screen is used mainly (or exclusively?) by menu code, to draw menus directly on term_screen. If we want to eliminate tile_width/tile_height, menu code cannot use term_screen; the main term should display only one thing - the dungeon. That is, term_screen cannot have messages, sidebars, status lines or menus on it. It's easy to make sidebar or message line just use their own, separate terms (perhaps 'docked' to term_screen). But how to display menus? I propose they also use their own terms:
Code:
    /* that replaces screen_save() */
    struct term_hints hints = {
        .new = true,
        .width = 80,
        .height = 24,
        .position = TERM_POSITION_CENTERED_IN_TERM_SCREEN,
        .borders = true
    };
    Term_push(NULL, &hints); /* create new term for menu */
    ...
    menu_select(); /* do the usual thing */
    ...
    /* that replaces screen_load() */
    Term_pop(); /* destroy temporary term */
pushing a NULL term creates a new, termporary, empty term on top of the stack of terms (and a new subwindow appears on display). The menu code can use this term like it uses term_screen currently (Term_get_size(), Term_erase(), Term_gotoxy(), Term_putstr() should all work, and the menu still will be displayed in the new subwindow). Popping this temporary term frees it (and the subwindow disappears).
Why "term_hints"? Well, maybe the new term cannot be centered in term_screen; perhaps term_screen is too small and in the corner of display. Or maybe the frontend (main-something.c) doesn't know how to draw borders. In any case, the frontend should try to display menus in an attractive and useful way, based on information in hints.
I hope this will allow to use current menu code almost as it is; just screen_save() and screen_load() will have to be replaced by Term_push() and Term_pop(), and also stuff like region_erase() won't be necessary. menu_refresh() also does this thing:
Code:
    if (reset_screen) {
        screen_load();
        screen_save();
    }
New term can just be cleared (Term_clear()) instead.

Actually, even stuff like Term->wid can be used pretty much as it is:
Code:
#define Term \
    Term_top()

term *Term_top(void)
{
    return term_stack.stack[term_stack.top];
}
term_stack.stack[0] is always term_screen; trying to pop it (making the stack completely empty) is a fatal error. OTOH, pushing term_screen on top of term_screen in the stack is ok (just like currently with term *old = Term; Term_activate(term_screen); Term_activate(old); old can already be term_screen).
That doesn't have to be a big stack. With current textui the max depth of the stack would be what, 3? (term_screen, store interface and item description, for instance)
Term_fresh() reform
Currently, Term_fresh() performs two functions; it flushes term's contents (via Term_fresh_row_*()) and it demands that (as main-xxx.c says) "This action should make sure that all 'output' to the window will actually appear on the window". The latter is impossible. Therefore, Term_fresh() should be split into two functions: Term_fresh() (much like it is now, but without calling Term_xtra()) and Term_redraw_screen():
Code:
void Term_redraw_screen(void)
{
    Term_xtra(TERM_XTRA_REDRAW, 0);
}
By far the most useful moment to update the screen is immediately before trying to get user input. That is, before pressing a key the user should know the latest information about the state of the game. In simpler words: Term_redraw_screen() should be called before calling inkey_ex().
Another useful moment to refresh the screen is various animations. Splashscreen ("Initializing monsters" etc) is also an animation in this sense.
In most other situations redrawing the screen is not so useful; in particular, it's not a useful thing to do after updating a single tile of the map.
Colors reform
In text mode, angband's terrain has only 3 different colors, and two of those are used for hybrid_walls/solid_walls. Why doesn't text hook make any use of term_win->vta? Current situation:
Code:
struct term {
    errr (*text_hook)(int x, int y,
            int n,
            int a,
            const wchar_t *s);

    errr (*pict_hook)(int x, int y,
            int n,
            const int *ap, const wchar_t *cp,
            const int *tap, const wchar_t *tcp);
}
The hackery with "a / MAX_COLORS", "a % MAX_COLORS" is just bizarre. Term->text_hook() should get tap and tcp just like pict_hook. Even if it's not very useful now, it may become useful over time. attrs could be something better than ints: for instance, uint32_t (one byte for each of red, green, blue, alpha channels). More colors will allow to achieve some interesting cosmetic effects; slightly transparent clear icky things, lantern light that gradually becomes more dim with the distance from the player, etc. Or how about a DCSS-style minimap?
uint32_t could still be used for the "a / MAX_COLORS" thing in some kind of "low color mode" (perhaps a new grafmode).
Tilesets
Note that if term_screen can only ever have either tiles or text, the job of ui2-term.c is significantly simplified:
Code:
errr Term_fresh(void)
{
    ...
    if (use_graphics) {
        Term_fresh_row_pict();
    } else {
        Term_fresh_row_text();
    }
    ...
}
Those massive tilesets look like a pain to update or modify. How about splitting them into separate files? The .prf file could look like this:
Code:
# <darkness>
feat:0:*:0:Something.png

# open floor
feat:1:torch:1:Open floor torch.png
feat:1:los:2:Open floor los.png
feat:1:lit:3:Open floor lit.png
feat:1:dark:4:Open floor dark.png

something:...:5:filename.png
something:...:6:filename.png
something:...:7:filename.png
The frontend will have to read all .png files, create an array of pixels, fill it with contents of files (in this particular order) and remember offsets into it. ui-prefs.c will ignore the file name part (*.png), and use the file number part (that precedes the file name) as char. attr then could be used for color moding the tile, or just be unused.
Actually, the file number part is just for illustration; it's not even necessary.
Well, tilesets currently work ok so I guess that's not that urgent.
Input
Why do terms have key_queue at all? Only one term ever does something with it. term_screen's key_queue may just as well be separated from term_screen and become its own thing.

So that't my current plan for textui reform. The main change is that any frontend is assumed to be capable of creating and destroying subwindows at will; I know that at least one official frontend can do it (main-sdl.c), and of course main-sdl2.c doesn't have any problems with that either. I don't see why any graphical frontend would find it too difficult. Ncurses, OTOH, needs the functionality of Term_load() and Term_save(). It's probably possible to implement fallback to term_win_copy() for backwards compatibility, but right now that doesn't concern me.

Last edited by t4nk; July 10, 2016 at 23:22.
t4nk is offline   Reply With Quote
Old July 10, 2016, 21:06   #2
t4nk
Adept
 
Join Date: May 2016
Posts: 249
t4nk is on a distinguished road
Oops, posted in the wrong forum. Is it possible to move it to dev forum?
t4nk is offline   Reply With Quote
Old July 10, 2016, 21:51   #3
Pete Mack
Prophet
 
Join Date: Apr 2007
Location: Seattle, WA
Posts: 4,143
Donated: $40
Pete Mack is on a distinguished road
@t4nk--
You have to be able to mix tiles and characters for any monster or object missing a tile. This happens more than you might think

Also, I have no idea if people do this with gfx enabled, but I have a pref file that turns the extra valuable scrolls pink. (Rune, Banishment, Mass Banishment, *Destruction*), and some lesser ones like *enchant weapon* yellow. It'd be impossible to do this without mixing tile and character.
Pete Mack is offline   Reply With Quote
Old July 10, 2016, 22:15   #4
Nick
Vanilla maintainer
 
Nick's Avatar
 
Join Date: Apr 2007
Location: Canberra, Australia
Age: 52
Posts: 6,563
Donated: $60
Nick is on a distinguished road
This all sounds very promising.

The main problems that the ui has recently caused (or currently causes) me are
  • bad tile drawing due to menus or failure to update
  • flicker
  • slowdown while resting or running due to main map and subwindow map updates
  • failure to update correctly when changing panel, so the player running right appears on the left before disappearing on the right

These play off each other - for example, I think the last one appeared as a consequence of an attempt to fix slowdown or flicker.

My feeling is that the lower level code needed a refresh, but I wasn't prpared to go down that rabbit hole at the moment. If you are, that's great
__________________
One Ring to rule them all, One Ring to find them,
One Ring to bring them all and in the darkness bind them.
Nick is offline   Reply With Quote
Old July 11, 2016, 03:11   #5
t4nk
Adept
 
Join Date: May 2016
Posts: 249
t4nk is on a distinguished road
Quote:
Originally Posted by Pete Mack View Post
@t4nk--
You have to be able to mix tiles and characters for any monster or object missing a tile. This happens more than you might think
Wow, don't agree. Bugs, such as missing tiles, should be fixed, not worked around. It's just too annoying to add tiles to existing huge monolithic tilesets! But otherwise you gave me an idea I don't know why separate arrays for attrs and chars should exist at all. This would be a more useful construct:
Code:
struct term_point {
    wchar_t ch;
    uint32_t attr;
    bitflag flags[TERM_FLAGS_SIZE];
};
Then term_win could be full of these things, and pict_hook() and text_hook() just eliminated and replaced with a single draw_hook(). The interpretation of ch, attr and flags would be left to the frontend.

Quote:
Also, I have no idea if people do this with gfx enabled, but I have a pref file that turns the extra valuable scrolls pink. (Rune, Banishment, Mass Banishment, *Destruction*), and some lesser ones like *enchant weapon* yellow. It'd be impossible to do this without mixing tile and character.
It's called 'color modulation' and it's an easy thing to do actually (with tiles). Although that seems like an obscure feature that few players would miss.

Quote:
Originally Posted by Nick
My feeling is that the lower level code needed a refresh, but I wasn't prpared to go down that rabbit hole at the moment. If you are, that's great
I'll do what I can

Last edited by t4nk; July 11, 2016 at 03:38.
t4nk is offline   Reply With Quote
Old July 12, 2016, 04:15   #6
takkaria
Veteran
 
takkaria's Avatar
 
Join Date: Apr 2007
Posts: 1,826
Donated: $40
takkaria is on a distinguished road
Hey, I think this is smart work and mostly makes sense to me. I have some suggestions/ideas that I think would improve but don't have time to reply more fully right now. Will collect my thoughts over the next couple of days and write a longer reply
__________________
"Physician, heal thyself."
takkaria is offline   Reply With Quote
Old July 12, 2016, 10:21   #7
Carnivean
Swordsman
 
Join Date: Sep 2013
Posts: 476
Carnivean is on a distinguished road
Quote:
Originally Posted by t4nk View Post
Wow, don't agree. Bugs, such as missing tiles, should be fixed, not worked around.
It's not a bug as such. Certain users like to fiddle with the game, adding things that the maintainers didn't plan for. Unless you're going to generate a tile for them, you're going to need a backup and that;s text.
Carnivean is offline   Reply With Quote
Old July 12, 2016, 11:01   #8
t4nk
Adept
 
Join Date: May 2016
Posts: 249
t4nk is on a distinguished road
Quote:
Originally Posted by takkaria View Post
Hey, I think this is smart work and mostly makes sense to me. I have some suggestions/ideas that I think would improve but don't have time to reply more fully right now. Will collect my thoughts over the next couple of days and write a longer reply
Looking forward to it! I'm not sure how to handle various prompts...

Quote:
Originally Posted by Carnivean
It's not a bug as such. Certain users like to fiddle with the game, adding things that the maintainers didn't plan for. Unless you're going to generate a tile for them, you're going to need a backup and that;s text.
We'll see. It's not actually difficult to do, I just don't feel the need to support all users and all uses. I do have a backup - THEY will generate a tile
t4nk is offline   Reply With Quote
Old July 15, 2016, 05:57   #9
t4nk
Adept
 
Join Date: May 2016
Posts: 249
t4nk is on a distinguished road
Nick, do you want patches for current textui?
Also, I'm afraid this will be a rather substantial rewrite I'm still hoping to keep menu code, it's a good code... but the stuff like ui-input.c really makes me RAGE and why does it display messages?

edit: well, to be fair, it's really inkey() stuff that is so outrageous. That might be the single worst thing in angband's codebase...

Last edited by t4nk; July 15, 2016 at 10:47.
t4nk is offline   Reply With Quote
Old July 15, 2016, 13:57   #10
debo
Veteran
 
debo's Avatar
 
Join Date: Oct 2011
Location: Toronto, Canada
Posts: 2,326
debo is on a distinguished road
Quote:
Originally Posted by t4nk View Post
That might be the single worst thing in angband's codebase...
You probably haven't looked hard enough

(For something that is a billion years old it is still pretty good though, IMO -- and I haven't really even looked closely post-refactor!)
__________________
Glaurung, Father of the Dragons says, 'You cannot avoid the ballyhack.'
debo is online now   Reply With Quote
Reply


Currently Active Users Viewing This Thread: 1 (0 members and 1 guests)
 
Thread Tools
Display Modes

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off

Forum Jump

Similar Threads
Thread Thread Starter Forum Replies Last Post
High element reform Nick Vanilla 49 December 12, 2015 20:04
Any benefit to eating when full? Ingwe Ingweron Vanilla 2 September 27, 2014 00:04
Fightless the full-casting mage fizzix AAR 65 July 27, 2010 08:11
Identification Reform Susramanian Vanilla 36 March 8, 2010 19:23
Help with diving (warning: long) bebo Vanilla 6 January 22, 2009 02:23


All times are GMT +1. The time now is 22:50.


Powered by vBulletin® Version 3.8.7
Copyright ©2000 - 2017, vBulletin Solutions, Inc.