renpy / renpy

The Ren'Py Visual Novel Engine
http://www.renpy.org/
5.05k stars 705 forks source link

NVL with gui.nvl_height = None (dynamic height) causes text to be cropped/bleeding at the bottom of the screen #5090

Closed hsandt closed 1 year ago

hsandt commented 1 year ago

When using NVL mode with define gui.nvl_height = None to enable dynamic text height, the auto-scroll feature stops working properly.

In this example with same-height paragraphs:

Renpy 8 1 3 - NVL with dynamic block height fails to auto-scroll

it just stops scrolling and doesn't display blocks 4 and 5 before the end of the game.

If you combine blocks of different heights, the text may slightly auto-scroll at times; but still not enough to show the true bottom of the text.

This thread: https://lemmasoft.renai.us/forums/viewtopic.php?t=40849 shows a different issue, cropping before reaching screen bottom and overlapping due to gui.nvl_height being to small. The two solutions are: a. set gui.nvl_height to a bigger value (for novels alternating very short and very long paragraphs though, it creates very big gaps) b. set gui.nvl_height to None for dynamic height (ideal to make text look the same as in an actual book)

This thread: https://lemmasoft.renai.us/forums/viewtopic.php?t=41379 shows this very issue when using dynamic height. The other user suggests to just manually clear as dynamic height cannot track the text length... But it does, otherwise it wouldn't be able to place the next block of text right afterward. Besides, since the text sometimes move a little when alternating different block heights, it doesn't seem like Renpy is completely ignoring dynamic height blocks either.

In fact, history already allows dynamic height and also has a scroll bar, so it's definitely aware of dynamic heights. And in Renpy 8.2, with the addition of history_spacing https://github.com/renpy/renpy/commit/d309f3fb93d4ff249ad2250a5ee693fa2a805a98, it will be able to show the complete text with a novel-like spacing and a scrollbar. This means we already have all the features needed to make a fully scrollable text (I could hack around by reusing the History panel as my main screen but I'd rather not, not it doesn't have smooth scrolling yet).

As of manually clearing the text, it works, but it does not give the same effect. There is also the edge case where a certain localization will make text slightly bigger and in this case we don't want the coder to get in and inject an extra nvl clear for a specific language: scrolling by a few lines can be tolerated there.

While at the moment, the instant auto-scroll is not great, is progressive scrolling is implemented later, it will be great to combine dynamic height and full progressive scrolling for a continuous scrolling experience (like reading a PDF, or playing in browser a game made with Inky).

Finally, there is old issue: Automatic nvl-clear when block goes off the window https://github.com/renpy/renpy/issues/283 Unfortunately, it was closed saying "this has been implemented" without indicating if this is the first suggestion, auto-clear (which I have not found an option for) or the alternative not mentioned in the title, auto-scroll, or the variant, smooth scrolling. From what I see, it must be instant auto-scroll that has been implemented, but broken by NVL dynamic height (not sure if it was added before or after said feature).

hsandt commented 1 year ago

Interestingly, if you have already seen the text, holding Ctrl to skip Seen text will properly scroll down to the bottom of the text.

BTW I have seen another developer copy history behavior to create an auto-scrollable text area so I may actually do this for now, even if I don't need manual scrolling too.

Accessibility note: I just realised that using nvl clear regularly may not be enough if user uses Accessibility panel > increase font size too much so it bleeds before the next nvl clear anyway.

MiiNiPaa commented 1 year ago

By default for autosized nvl text a simple vbox is used without any capabilities for scrolling. If you want scrolling, you need to modify nvl screen to suit your needs. Bonus mentions: 1) config.nvl_list_length = X keeps and displays only latest X sentences. Great with fixed-height, can still have issues with variable height if your paragraphs are too long. 2) Translators can add their own nvl clear statements to the translation blocks. No need to modify base game.

hsandt commented 1 year ago

I'm working on a scrolling system based on History but there still are some limitations (e.g. clicking on the NVL box tries to drag, preventing continue-on-click).

Thanks, config.nvl_list_length = 6 explains why I couldn't scroll to that many entries in the past! Increasing it works great for scrolling. Keeping it small looks good for fixed height. It works for dynamic height but indeed you get issues, as the bottom line is not stable, so not great for smooth reading.

OK, I didn't know translators could force clear text.

I'm still working with manual nvl clear for now, keeping a little margin in case user increases font size for accessibility, as my scrolling system is not reliable yet.

renpytom commented 1 year ago

@MiiNiPaa is right - I don't think there's much we can do here.

hsandt commented 12 months ago

OK, let's put full scrolling with a side scrollbar aside.

Would it still be possible to have auto-scroll to bottom after new block appears?

Because it works when we use fixed nvl_height size, so certainly some auto-scroll feature is implemented. It's just the dynamic size not being supported, correct?

If this is not meant to be supported at all, then this could be explained in https://www.renpy.org/doc/html/gui.html > gui.nvl_height to avoid bad surprises to users.

In the meantime I added a bunch of nvl clears and it works fine on desktop. However on mobile where the font size is bigger, it looks like I need twice as many nvl clear. I may have to resort to conditional nvl clear (if small, do extra nvl clear mid-page) which starts getting more cumbersome for testing and iterations (each time I change paragraphs a bit I'll need to check the smartphone emulator see if nvl clear is enough and the desktop version see if there are not too many nvl clear... but I suppose that's a general issue of exporting games on devices with various physical dimensions).

Maybe I'll eventually manage to get the full history-like scrolling working by the time I release for mobile though. In fact, dragging on a touch screen is even better than scrolling on PC (but I still got the issue where click/touch won't continue to next sentence, you'd have to click/touch outside the scrolling area).

eevee commented 11 months ago

Would it still be possible to have auto-scroll to bottom after new block appears?

You can wrap the vbox in the nvl screen in a viewport, much like how the menu works:

            viewport:
                yinitial 1.0

Add a scrollbar if you like. But be aware that enabling pagekeys or the scroll wheel will collide with the normal rollback/rollforward bindings, and arrowkeys will cause the viewport to be focusable, which can interfere with pressing spacebar to advance. I've found it makes the most sense to just make the area unscrollable; the player already has access to rollback and the history if they want to read the backscroll, and a third mechanism is probably not necessary.

hsandt commented 11 months ago

Thanks, someone else told me the same thing in #283 and actually, I had a WIP that was doing this but for some reason I wasn't satisfied and I gave up on it. Turns out it was working pretty well, I just had to disable scrolling features as you said to avoid input conflicts (although I'm considering keeping mouse wheel because it's really convenient to go up just a little if you missed something, without causing a full rollback, which would also not work if a big chunk of text was shown at once - so big it caused scrolling even if it was the first block, causing the first lines to be out of view).

As I said on the other issue, I still have troubles with smooth scrolling though.

You can find the core changes I did in the code for instant scrolling on this thread: https://lemmasoft.renai.us/forums/viewtopic.php?t=67577 where I'm also asking how to smooth scroll.

Kassy2048 commented 11 months ago

(but I still got the issue where click/touch won't continue to next sentence, you'd have to click/touch outside the scrolling area)

You can add the mouseup_1 event to the dismiss_unfocused keymap so that single clicks to the viewport will make the story continue (clicks that drag the viewport will not). This can have side effects on displayables that react to clicks but don't prevent them to propagate though.

init python:
    config.keymap['dismiss_unfocused'].append('mouseup_1')
hsandt commented 11 months ago

Thanks, it allowed me to go through on click and tap, it even tolerates a small mouse/finger motion before release as it will only start to register drag after a certain motion threshold.

I still have the issue where NVL viewport is focused (apparently making it draggable enables that) preventing SPACE/ENTER from advancing, so I added custom bindings for those too. Fortunately, selected buttons still take priority over catching Enter input so you can e.g. navigate to select History in the quick menu and press enter and it will open it instead of advancing to next block in the script.

This is the additional code:

    # When NVL viewport is focused, SPACE, RETURN, KP_ENTER will not
    # advance, so we must add a custom binding
    config.keymap['dismiss_unfocused'].append('K_SPACE')
    # For these two, note that priority handle still works:
    # if a Quick Menu button is selected, Enter will still call its action
    # without advancing story
    config.keymap['dismiss_unfocused'].append('K_RETURN')
    config.keymap['dismiss_unfocused'].append('K_KP_ENTER')