godotengine / godot-proposals

Godot Improvement Proposals (GIPs)
MIT License
1.12k stars 69 forks source link

Implement using several different font styles (light, bold, italic, …) and colors in one single TextEdit #1781

Open Kukuschi opened 3 years ago

Kukuschi commented 3 years ago

Describe the project you are working on: Story outlining and writing tool: One can write text snippets, compare and edit them and arrange them in different ways (utilizing a custom tree structure). One starts with a rough sketch and refine it in different stages. The program collects and presents all data that is needed in a certain scene and presents it to the writer when he needs them.

Describe the problem or limitation you are having in your project: The TextEdit node does not allow different font styles or font colors. Different styles are needed. e.g. italics for inner monologues and different colors to mark text that needs revision etc.

Describe the feature / enhancement and how it helps to overcome the problem or limitation: Instead of one font, several fonts (same font in different styles) can be added to the TextEdit (best would be to not limit the amount as there can be many different thinkable styles: bold, italic, small caps, underlined, etc. + all thinkable combinations of those). One can switch between the different styles and colors of text while writing or change a style of selected text. (like in most basic word processors). Having the ability to have different font sizes within one TextEdit would be a nice addition. Maybe doable with a subset of BBCode?

Describe how your proposal will work, with code, pseudocode, mockups, and/or diagrams: Different fonts can be added to the them of an element or maybe (less limiting?) via code:

var bold = false
var italic = false
...
var fontsize = 0
var fontcolor = Color(0, 0, 0, 0)

func _ready():
   var dynamic_font_italic = DynamicFont.new() 
   dynamic_font_italic.font_data = load("res://Fonts/Font-Italic.ttf")
   var dynamic_font_bold = DynamicFont.new()
   dynamic_font_bold.font_data = load("res://Fonts/Font-Bold.ttf")
   ...

func _process(delta):
   #get the actual style combination,  fontsize an color from some radio buttons/input fields or something like that and write the following text accordingly into Textedit (maybe via BBCode) 

If this enhancement will not be used often, can it be worked around with a few lines of script?: It can hardly be worked around. One very clumsy workaround would be to overlay a RichTextLable over a TextEdit (font color = background color) that does ignore mouse and transfer text on the fly to it by adding BBCode. The alignment is a mess and it gets unusable when the text gets longer than the TextEdit (scroll bar). Also selecting text is ugly etc. pp.

Is there a reason why this should be core and not an add-on in the asset library?: Imho that is self-evident. TextEdit like it is seems more like a emergency solution and basic formatting (styles, color, maybe size) seem to be very basic features for such a node.

P.S. Syntax highlighting is no solution to this as it is not about highlighting keywords automatically but highlighting/changing text manually.

YuriSizov commented 3 years ago

Syntax highlighting can be a solution, though, as in 4.0 the methods for defining your own highlighter are exposed and you can base it on whatever logic you want, be it manual or automatic.

Calinou commented 3 years ago

Maybe doable with a subset of BBCode?

Unfortunately, having two different BBCode implementations in two different nodes sounds like opening a can of worms to me.

Kukuschi commented 3 years ago

Unfortunately, having two different BBCode implementations in two different nodes sounds like opening a can of worms to me.

I cannot think of another solution than using some kind of markup language (does not need do be BBCode), but maybe somebody has a better Idea. :/

Kukuschi commented 3 years ago

Another idea that does not require a mark up language:

So instead of adding a scrollbar to the TextEdit, it would change its width until the style is changed or enter is hit (or some other user defined condition is met like e.g. max_width). Then the focus/cursor would be put to the next TextEdit "in the chain" (via script) and continues there (this TextEdit could be generated via script and placed in a way that looks like it is all continuous text). The text itself would need to be hold as a nested array by a parent node of these TextEdits i guess (containing text. color, font, fontsize etc.) If the text is changed this nested array gets changed and then reorders and re-renders all affected TextEdits (would that lead to performance problems with very long (novel length) texts and many TextEdits?)

Pretty hacky compared to a mark up language tho^^ (still the proposed changes in the bullet list might be interesting)

Kukuschi commented 3 years ago

As now there is a new textserver for Godot 4.0 https://github.com/godotengine/godot/pull/41100 is there a WYSIWYG editor/TextEdit or is this all still limited to be only displayed via RichTextLabel? (In https://github.com/godotengine/godot-proposals/issues/1182 it was at least considered it seems)

Calinou commented 3 years ago

As now there is a new textserver for Godot 4.0 godotengine/godot#41100 is there a WYSIWYG editor/TextEdit or is this all still limited to be only displayed via RichTextLabel?

While TextServer makes it easier to use different font sizes in RichTextLabel, it doesn't intend to handle editing features. There are still no plans to implement a built-in WYSIWYG editor.

dsobiera commented 3 years ago

For what it is worth knowing, I too, would love to see some sort of ability to do WYSIWYG TextEdit in Godot (different fonts, sizes and styles per document).

Currently, I am developing a desktop application using Java and JavaFX to help with novel writing. In addition to the WYSIWYG "word processor" my application has 2d cards with pictures and paths to other cards.

If Godot ever got a WYSIWYG capability, I'd move my work to Godot.

Calinou commented 2 years ago

A rich-text LineEdit control was implemented in an add-on by @Kehom: http://kehomsforge.com/news/posts/20200513/newuiaddon

I'm not sure if it covers multiline functionality (which is the main difference between LineEdit from TextEdit). It seems like a good start nonetheless.

Kehom commented 2 years ago

The Control I implemented in the addon does not handle multiple lines. Also, it handles formatting based on "patterns" as the original intention of the widget is to be used as single line input for in game consoles and/or chat boxes. Mostly the idea is to allow it to highlight correct (or incorrect) console commands, allow emoticons to be rendered as well as possibly item linking within a chat window.

That said, some form of formatting is indeed required in order to "tell" the control what and how it should render. BBCode is one of those methods. Yet, if dealing with a WYSIWYG then a completely different method can be used, perhaps by inserting binary codes (numbers, really) within the internal data.

Anixias commented 1 year ago

As of the current version of Godot, this still seems to be impossible to do without writing a custom TextEdit node from scratch. The SyntaxHighlighter only supports the "color" key, making it impossible to have multiple fonts within a single TextEdit. Are there any plans to have this implemented?

Calinou commented 1 year ago

Are there any plans to have this implemented?

We haven't decided yet whether it's a good idea to implement this in core, or whether it's best left to a community add-on. That said, I don't think this is likely to be accepted in core, given this can be implemented by an add-on and this is a specialized need.

Kehom commented 1 year ago

Just a heads up. I do have plans to implement such control as a GDExtension, given that font rendering in Godot 4 is way more capable than what we have in 3. Still, there are two limitations in the GDExtension system that are preventing me from porting my other addons into Godot 4 (and working on new ones). Namely:

gro-david commented 1 year ago

Just a quick question after reading through this. This may be quite a dumb question, because i haven't read through the source code.... If I understand correctly a syntax highlighter in the ScriptEditor is telling the ScriptEditor in which color to display the different keywords. This color doesn't need to be saved it gets applied dynamically, I personally don't see anything getting in way of the same procedure with different font styles. So how is this color getting applied? I am thinking about loading multiple fonts and applying them like we apply the font color.

gro-david commented 1 year ago

Also: how is the RichTextLabel displaying multiple font styles? Maybe some of that code could be reused...

tokengamedev commented 1 year ago

This proposal is a good one, to improve the script editor. IMO it should be part of core. It should include options of underline, bold, italic and strikethrough for a single font family. Including multiple font families should not be allowed as in most code editors as part of the core

Calinou commented 1 year ago

The difficulty is in handling fonts with different widths/heights while also making the text editable. We also want to avoid code duplication between RichTextLabel and TextEdot/CodeEdit, given RichTextLabel is prone to regressions already.

We could choose to support only font variations with the same metrics as the base font, which would simplify the implementation a fair bit. However, this would make the implementation only really useful with monospace or uniwidth fonts (which are commonly used for programming).

gro-david commented 1 year ago

Could someone please send a link to the source code of the RichTextLabel, the CodeEdit, and the SyntaxHighlighter? I unfortunately couldn't find it anywhere...

Calinou commented 1 year ago

Could someone please send a link to the source code of the RichTextLabel, the CodeEdit, and the SyntaxHighlighter? I unfortunately couldn't find it anywhere...

Here it is 🙂

golddotasksquestions commented 8 months ago

Being able to allow the player/user of my projects to edit formatted and styled text with inline images during runtime (WYSIWYG), has been a long unfulfilled desire of mine.

In one particular case, I need this for a card game where the player/user is supposed to be able to create their own cards. In another example I have a map editor (think D&D maps) where the user is supposed to be able to write text on the map and change it freely. Yet another case where I needed this was a platformer level editor.

Right now the only "workaround" is to use RichTextLabels and then when the user clicks on the RichTextLabel a TextEdit node appears on top with the same text.

However this has countless shortcomings which makes this such a bad workaround it's basically unshippable in any thing but a personal hobby project: The RichTextLabel and the TextEdit can't have the same formatting, not only makes this the switch between the two terribly obvious, it also results in a very different Rect2 size of the text boxes. As you maybe can imagine, this results in total layout breaking chaos as the different Rect2 size suddenly completely demands different space. Or you need to have a scrollbar and only show part of the text, which can make it terribly unreadable, besides being ugly.

Since there is no BBCode in TextEdit nodes, all the written out BBCode in the TextEdit either breaks formatting further, or is completely omitted, making it incredibly hard to for the user to assess what the text is going to look like. Not only does the user now have to imagine what it might look like and whether or not it might fit into the box, the user also has to remember what format and styling individual words had and where inline images where placed ....

In short, it's such a terrible "workaround", it does not even deserve that name.

We really need a Text node which allows for formatting and styling as well as live editing during runtime!

tutabot commented 1 month ago

I need to style both TextEdit and LineEdit nodes. I think adding the same BBCode implementation RichTextLabel to all three would be beneficial. Here is my LineEdit issue which very much relates to this issue: https://github.com/godotengine/godot-proposals/issues/10475

I think a lot of the current issues with TextEdit right now comes from it being treated like an input for code, not for regular text. I guess the previous Godot contributors considered labels to be static without input and code to be dynamic. To be more specific, I feel like the text nodes in Godot Label, RichTextLabel, TextEdit and LineEdit were created specifically for Godot itself. This separation of text-display nodes and text-input nodes might have made sense back then, but since Godot is now used by a much bigger audience, and text needed for much more usecases than just a code and 3D editor, this separation is very limiting.