godot icon indicating copy to clipboard operation
godot copied to clipboard

Implement visible characters enter/exit FX in RichTextLabel

Open jordigulley opened this issue 1 year ago • 6 comments

Resolves godotengine/godot-proposals#9137

Adds visibility_transition property to RichTextLabel, which takes a RichTextTransition resource. This resource functions similarly to RichTextEffect, but instead of _process_custom_fx, there are 2 separate funcs for enter or exit fx.

Example

@tool
extends RichTextTransition

@export var speed:float = 2.5;

func _process_enter_fx(char_fx: CharFXTransform) -> bool:
	char_fx.color.a = lerp(0.0, 1.0, char_fx.elapsed_time * speed);
	char_fx.offset.y = lerp(-15.0, 0.0, char_fx.elapsed_time * speed);
	return char_fx.color.a >= 1;

func _process_exit_fx(char_fx: CharFXTransform) -> bool:
	char_fx.color.a = lerp(1.0, 0.0, char_fx.elapsed_time * speed);
	char_fx.offset.y = lerp(0.0, 15.0, char_fx.elapsed_time * speed);
	return char_fx.color.a <= 0;

text-transitions

Implementation Details

When a visibility_transition is set, making changes to visible_characters or visible_ratio will call _update_characters_to_transition, which will calculate the characters removed or added, and map a CharacterToTransition struct to the character. The CharacterToTransition struct contains data on if the character is entering or exiting, along with the transition's time elapsed. Before FX is processed, the RichTextLabel will check if the character currently being drawn is in the characters_to_transition map, and use the CharacterToTransition struct to call either _process_enter_fx or _process_exit_fx on the assigned RichTextTransition. If either of these methods return true, the character is done transitioning, and removed from the "to transition" map. Due to the nature of VisibleCharactersBehaviour::CHARS_BEFORE_SHAPING, having a RichTextTransition assigned restricts the visible character clipping behaviour to after shaping, to allow for exit fx.

jordigulley avatar May 09 '24 07:05 jordigulley

Here's a showcase of the feature with large amounts of text. For performance, the RichTextTransition will stop applying transitions when there is a large jump (>20 chars) in the amount of visible text. long_text

jordigulley avatar May 09 '24 07:05 jordigulley

Here's a showcase of the feature with large amounts of text. For performance, the RichTextTransition will stop applying transitions when there is a large jump (>20 chars) in the amount of visible text.

While this is a good plan (when I attempted this I didn't cap it, and it got... very bad), I do think that setting a hard cap doesn't make a ton of sense. A better option might be to add this as a variable to the class (such as max_transition_characters).

(Though if it has to be a hardcoded cap, make it a power of 2. This is a programming thing after all :p)

IntangibleMatter avatar May 09 '24 11:05 IntangibleMatter

This PR might help towards fixing https://github.com/godotengine/godot-proposals/issues/6286 (by allowing detecting on when exactly a specific character got revealed)

A better option might be to add this as a variable to the class (such as max_transition_characters).

Agreed on this point, for a use-case like this it would be important to run the transition for every character.

RedMser avatar May 09 '24 11:05 RedMser

Force pushing the branch closed the PR for some reason? Unsure why that happened. I've fixed typos. Working on adding support for the Glyph clipping modes. I will mark this as draft for now.

jordigulley avatar May 11 '24 01:05 jordigulley

Is there still interest in this PR?

Mickeon avatar Jul 05 '24 23:07 Mickeon

Is there still interest in this PR?

I can verify that I'm still interested

IntangibleMatter avatar Jul 06 '24 01:07 IntangibleMatter