UI: Improve 3d text selection #109229
No reviewers
Labels
No Label
Interest
Alembic
Interest
Animation & Rigging
Interest
Asset Browser
Interest
Asset Browser Project Overview
Interest
Audio
Interest
Automated Testing
Interest
Blender Asset Bundle
Interest
BlendFile
Interest
Collada
Interest
Compatibility
Interest
Compositing
Interest
Core
Interest
Cycles
Interest
Dependency Graph
Interest
Development Management
Interest
EEVEE
Interest
EEVEE & Viewport
Interest
Freestyle
Interest
Geometry Nodes
Interest
Grease Pencil
Interest
ID Management
Interest
Images & Movies
Interest
Import Export
Interest
Line Art
Interest
Masking
Interest
Metal
Interest
Modeling
Interest
Modifiers
Interest
Motion Tracking
Interest
Nodes & Physics
Interest
OpenGL
Interest
Overlay
Interest
Overrides
Interest
Performance
Interest
Physics
Interest
Pipeline, Assets & IO
Interest
Platforms, Builds & Tests
Interest
Python API
Interest
Render & Cycles
Interest
Render Pipeline
Interest
Sculpt, Paint & Texture
Interest
Text Editor
Interest
Translations
Interest
Triaging
Interest
Undo
Interest
USD
Interest
User Interface
Interest
UV Editing
Interest
VFX & Video
Interest
Video Sequencer
Interest
Virtual Reality
Interest
Vulkan
Interest
Wayland
Interest
Workbench
Interest: X11
Legacy
Blender 2.8 Project
Legacy
Milestone 1: Basic, Local Asset Browser
Legacy
OpenGL Error
Meta
Good First Issue
Meta
Papercut
Meta
Retrospective
Meta
Security
Module
Animation & Rigging
Module
Core
Module
Development Management
Module
EEVEE & Viewport
Module
Grease Pencil
Module
Modeling
Module
Nodes & Physics
Module
Pipeline, Assets & IO
Module
Platforms, Builds & Tests
Module
Python API
Module
Render & Cycles
Module
Sculpt, Paint & Texture
Module
Triaging
Module
User Interface
Module
VFX & Video
Platform
FreeBSD
Platform
Linux
Platform
macOS
Platform
Windows
Priority
High
Priority
Low
Priority
Normal
Priority
Unbreak Now!
Status
Archived
Status
Confirmed
Status
Duplicate
Status
Needs Info from Developers
Status
Needs Information from User
Status
Needs Triage
Status
Resolved
Type
Bug
Type
Design
Type
Known Issue
Type
Patch
Type
Report
Type
To Do
No Milestone
No project
No Assignees
5 Participants
Notifications
Due Date
No due date set.
Dependencies
No dependencies set.
Reference: blender/blender#109229
Loading…
Reference in New Issue
No description provided.
Delete Branch "guishe/blender:improve-3dtext-selection"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Improve 3D text selection & feedback when moving the mouse outside of the text.
Previously mouse selection only worked if the mouse was over the text, now there is more margin to select characters or lines.
Old behavior
New behavior
Here other tests
maybe @Harley is interested? :)
Hey, that is a nice improvement. Selections that start outside of the text block was something we wanted. Thanks for working on this.
There are a couple things that need improving though:
Increase the "Line Spacing" to something like 2.0. The selection of the line is too biased to the line below. As in a selection vertically between the lines should select the one above if slightly closer to it, or below if lower than the midpoint. Current code is not perfect either, but this PR is a bit worse.
Similarly, when clicking on the right side of a character we want the cursor inserted to the right. This makes selection much more forgivable and is how it works elsewhere in the interface.
With both of these it is probably just a matter of adding a small amount - like half the character width for the horizontal issue - to your tested values. Note that doing so can sometimes cause complications for the first character.
If you add a curve then set your "Text on Curve". This can make selection quite odd if outside the text block.
This looks to be solvable. Clicking to the left of the block should only ever select the first character this might just need another check.
This last part seems mean. But if we move from requiring a click inside the block to allowing it outside users will give us bug reports if it doesn't work all over.
I made a change so that when textoncurve is assigned it looks for the closest character instead, I don't think it's the ideal solution, I'm going to analyze a better way to do it
In the video is assigned a circle curve
Hey, that is getting much better!
With normal text and character spacing set to 1.0 the placement of the cursor is perfect. Clicking on the right side of an "M" or "i" behaves exactly as expected. But increase the character spacing to 1.5 and it doesn't go to the right at the right side of the letter but the right side of the total space.
Vertical line selection looks a bit better but still seems out. Although to be honest is probably close to how it is in current code. This seems picky but it can affect how it feels for multiline selections. You select from one line then drag down to include something from one below. Where the change occurs from single to multiline should feel right.
Text on a curve seems good enough to me. As long as selecting outside the text block doesn't make it worse I wouldn't worry about things like a spiral of text. Granted I didn't test much so you might be seeing a problem I haven't noticed yet.
Now its use the actual size of the of the character to decide if the cursor is on its left or right.
between characters
Selection between different lines now uses the half-size space between lines.
between lines with space greater than 1
between lines with space 1
Something to take into consideration is that the selection is not clamped if the mouse is above or below the text, if I select from above the text it will not necessarily select from position 0, should I change it?
from top selection
Selection on curve seems fine to me
selection text on curve
Selection between lines seems strange because we can't really tell where lines end or start.
That can be fixed if the selection highlight includes that region.
That looks perfect. The character selection works nicely no matter the character width or spacing.
Yes, that works way better than current code.
I'm not sure. I don't have any programs that allow selection outside of the text area so I can't find any precedents for this. It does feel a bit odd to drag my mouse horizontally above the text area and have it select text. Not sure if it feels like a bug or a feature. On balance maybe a feature? Dragging like this above the text is similar to dragging between lines of text when the line spacing is high. I'd say leave this how it is. Once this seems complete and working well we can give it to Campbell to look at and he might say otherwise.
A thing that seems to have broken between your versions is the selection the line when clicking to the right of the text area. Clicking to the left correctly places the cursor at the beginning of the nearest line. But clicking to the right seems to select the line below:
Fixed.
Testing in the last line, it can be confusing that you can select from before the first character on the last line like this
If this feels strange then we could consider doing this like the only thing that is close to it...
Right now this PR treats a drag from above the text to the middle of the first line as setting the start of the selection at that point. Basically just setting the cursor position and anchoring the new selection from there as you drag further.
We don't have any exact precedents to this in other programs, but we do experience something that feels close. When any text editor has any blank lines before and after the block you are selecting from. In this case dragging from above and to the middle of the first line will select from the start of the line to the cursor position. However, doing so from below selects from the end of the line to the cursor position.
Of course it isn't the exact same situation in that the selection is actually starting from the line above or below, but might be what our brain is expecting. This PR as it is right now does behave exactly like this if you add a blank line above and below, so feels funny when it acts differently without those blank lines.
Blender text editor behaves the same way, it should be fine
For sure. I quite like how it works right now in this PR. A great improvement.
Code-wise, should change your comments to c-style "/* */". I know this file has some uses of single-line c++ style "//" but I'd treat those as being in error.
Your code has three blocks that all depend on
cursor_params
. I'd personally enclose all of it in aif (cursor_params).." and then have additional tests inside for
slen == 0``, 'cu->textoncurve`, etc. This would make it a bit clearer to me that all the code is for this one purpose.The "0.915f" is very specific; definitely needs a comment even if just a trial and error guess. Although when testing I get a nicer result with this:
This gives me a perfect 0.25 offset when the line-spacing is 1.0f, but still works great over 1.0f. It also has a really nice transition when the line-spacing is less than 1.0 and the selection boxes overlap.
@guishe hi, i suggestion, in windows we can select the whole line by 3 clicks .. i hope to see this in 3d text
I did this by visually testing how much space between lines made it look like they barely touched the selection borders, but your solution is better
added also a fix, before the scale was not taken into account when it was with a curve
The behavior here is such a nice improvement.
This is probably a perfect time to bring Campbell in to take a look.
@ideasman42 - This is such a nice improvement.
This mostly adds the ability to start a selection outside of the text area, and that greatly improves selection since you don't have to start off so precisely. It also improves on the location of the transition point between lines when selecting multiples. Because text on a curve is handled separately it also supports very complex arrangements better.
This causes selection not to work when multiple text boxes are used.
Supporting this might be reasonably involved as text boxes can overlap, so simply picking the text box under the cursor wont always work properly.
A possible solution could be to use this new method of selection but compute it for each text-box, then pick the closest match.
With this patch applied to main and with two text boxes arranged vertically in order I see it working well:
But if the second box is moved above the first then we can't select in the second box, which is something that works in current code, but breaks here:
@guishe:
The breaking of selection when the second text box is above the first is just because your "Loop until find the line where the mouse is over" is only checking for the cursor location being greater than the bottom of the text and interline offset. It works if you check if it is in the range between the top and bottom. Without testing much I get close to proper behavior with this:
With above I get selection working as it does today, when you start within the text blocks. It also works as you want when starting to the right or left of the text boxes. But selecting above or below either box will always select the last line of the second box if it is above the first.
4ed13db0e2
to4ec8ad653f
I update and now gets the nearest char if
cu->totbox > 1
.@Harley i will give it a try
this happens if the cursor is above the text
video
with the closest character
video
but with the closest char interline selection can be a bit off
video
Actually.... I am having great results with only the following (diff from main):
As it is now, if we check that there are no curves or multiple boxes, it is easier to select lines if the mouse is to the right of the text.
But I don't know if that can be a bit confusing, why can't do the same on text objects with curves or multiple text boxes?
I couldn't find anything not working well with just the single block of code for everything I tested with single blocks, multiple text frames, text on curve, etc. Selecting from the right, left, top, or bottom all worked great.
This type of selection on a simple 3D text object with no curve or multiple boxes, it's nice to be able to select a line without getting too close to it.
This happens if the mouse is too much far to the right whit getting the colesest one.
Yikes, yes I was not testing with blocks of text that include any lines that were short enough from their neighbors to show that behavior.
When in that short-distance loop and you think you've found the new shortest one, could you then check that the vertical position of cursor_params->cursor_location is within the range of char_location? If not don't make it best match. That way you only get a best match on the same line?
What I'm now testing with is the idea of finding both the closest character to the cursor as well as the closest character on the same line as the cursor. Then just using the closest one on the same line if there is one, or the nearest character if not.
So far it seems to do what you want, selecting the correct line if clicking on the right, and the correct character if clicking above or below.
That's working quite well now, even when multiple text boxes are overlapping.
This function now runs some quite involved logic when it's unnecessary.
@ -16,10 +16,12 @@
#include "MEM_guardedalloc.h"
#include "BLI_blenlib.h"
Prefer including only necessary headers.
@ -790,6 +792,16 @@ static float vfont_descent(const VFontData *vfd)
return vfd->em_height - vfont_ascent(vfd);
}
struct TextboxBounds {
This reads as a general structure when it's a special case for cursor placement.
This should be named in a way that reflects that, e.g.
TextBoxBounds_Cursor
.@ -934,6 +946,16 @@ static bool vfont_to_curve(Object *ob,
}
i = 0;
struct TextboxBounds *tb_bounds = MEM_malloc_arrayN(
This is allocated even when the cursor isn't being placed.
Noticed some issues still,
Text boxes with zero height aren't handled properly (I could attach a blend file, but it's fairly easy to redo with 2x text boxes and the first one is zero height).
There are some logical issues too, noted inline.
Attached a patch that resolves warnings and accounts for some text boxes having no text (these are skipped).
@ -1073,2 +1091,4 @@
CLAMP_MIN(maxlen, lineinfo[lnr].x_min);
if (tb_bounds != NULL) {
tb_bounds[curbox].xmax = max_ff(tb_bounds[curbox].xmax, xof);
This doesn't look right, the value is initialized at zero, shouldn't it be initialized to
-FLT_MAX
so the initial value doesn't impact the range? (boxes may be placed below zero).@ -1074,1 +1092,4 @@
if (tb_bounds != NULL) {
tb_bounds[curbox].xmax = max_ff(tb_bounds[curbox].xmax, xof);
tb_bounds[curbox].ymin = yof;
Worth noting in a comment that a
min_ff(..)
isn't needed as the value only ever increases.@ -1778,1 +1843,4 @@
}
/* Loop until find the first character to the right of the mouse (using the character
* midpoint on the x-axis as a reference). */
for (i; i <= end && yof == chartransdata[i].yof; i++) {
i
does nothing (removed in patch, attached).@ -1334,0 +1363,4 @@
if (tb_bounds_for_cursor != NULL) {
for (curbox = 0; curbox < cu->totbox; curbox++) {
TextBoxBounds_ForCursor *tb_bounds = &tb_bounds_for_cursor[curbox];
if (tb_bounds->last_char_index == -1) {
It was also necessary to wait for the text to be aligned, now the bounding box is calculated after that
There is an issue where the previous text boxes last index could be used even if that text box is empty, the attached patch resolves this, it also:
bounds
into local space, to be more straightforward (having the TextBox and it's bounds be in the un-scaled coordinates of thecursor_location
).Can't reproduce having in between a textbox with 0 characters (maybe if there is just a break line can make that feeling of a empty text-box), only last textboxes will have 0 chars
Having height = 0, the textbox will have no line limit, even with a very small value, the textbox will have at least one line, only the last few textboxes will contain 0 characters
I didn't check if it caused a problem in practice but the possibility of using an empty text boxes
char_index_last
which would be-1
could cause bugs, so it's better to track the last-valid-index, not just pick the value of the last index and assume it's valid.