godotengine / godot-proposals

Godot Improvement Proposals (GIPs)
MIT License
1.14k stars 93 forks source link

Add autowrap line break detection functionality to labels #8827

Open bhiltunen opened 9 months ago

bhiltunen commented 9 months ago

Describe the project you are working on

A dialogue heavy game, similar to titles like Disco Elysium.

The dialogue is taken from a database of strings written in a separate program, and instantiated in-game at runtime.

Disco-Elysium05242021-082736-79410

Describe the problem or limitation you are having in your project

I want to add a behaviour to my dialogue text where I can add a custom string/text everytime my dialogue autowraps via the autowrapping functionality of the Label or RichTextLabel nodes. (In my case, I want to indent every new line as per the Disco screenshots, so inserting a "\t" the moment a line break occurs)

Screenshot 2024-01-07 173019

Currently, there is no way to detect when a line break happens as a result of the Autowrapping behaviour.

Describe the feature / enhancement and how it helps to overcome the problem or limitation

Add a way to detect, in a script, the moment that the Autowrapping feature wraps the text, and to be able to insert custom text directly to the start of the new line. Optionally, export an option into the editor to directly control/access this without necessarily requiring code.

Describe how your proposal will work, with code, pseudo-code, mock-ups, and/or diagrams

This would probably work by modifying the existing code for Autowrapping to send out a signal whenever it executes the wrapping functionality. There needs to be at least 1. some way of detecting when the wrapping occurs and 2. some way to access and send out the spot within the string that is transported onto a new line.

If this enhancement will not be used often, can it be worked around with a few lines of script?

No. For this functionality to work the Label and RichTextLabel (and maybe the TextServer class itself) have to be modified, as the signal needs to come directly from them.

Is there a reason why this should be core and not an add-on in the asset library?

A small enhancement to a pre-existing node does not merit an add-on.

Mickeon commented 9 months ago

I understand the issue, but I do not agree with the proposed solution. That's potentially a lot of signals to send when autowrap occurs, and it's not always cheap.

Detecting an autowrap may be already possible with an ad-hoc solution. Making this up as I go. RichTextLabel's get_character_line allows you to know what line any given character is positioned in. This means that, by iterating through the entire text, you can recognise a line break or an autowrap, by checking the value returned by get_character_line. If it's greater than the previous value, a line break happened and one could act accordingly. It's not that simple, but it sounds possible.

YuriSizov commented 9 months ago

Detecting an autowrap may be already possible with an ad-hoc solution.

Both Label and RichTextLabel have get_line_count(). Text reshaping can realistically only happen when the text is set (which user controls) or when a resize happens (which we have signals for, item_rect_changed and resized). So detecting if the text has wrapping is perfectly possible.

However, I agree that the suggested solution is not proper. It will lead to endless, or at least excessive, reshaping. What you want here is a property that allows you to add a leading character for each line. If set, it will be accounted for during the reshaping process and inserted automatically.

RVDEYO commented 8 months ago

I understand the issue, but I do not agree with the proposed solution. That's potentially a lot of signals to send when autowrap occurs, and it's not always cheap.

Would putting the index points of each autowrap into a PackedIntArray be the better solution ? Shouldn’t be all that taxing and still give the functionality they want? This way they can just access the index points via a getter function?

Mickeon commented 8 months ago

It would be much, much less taxing than a signal in theory, yeah. Not sure about how easy it is to implement it. The wrap position has to be calculated at some point during the text updating process, that's for sure.