GPv3: Select Alternate #109240
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
6 Participants
Notifications
Due Date
No due date set.
Dependencies
No dependencies set.
Reference: blender/blender#109240
Loading…
Reference in New Issue
No description provided.
Delete Branch "Lorenzo-Carpaneto/blender:gpv3-select-alternate"
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?
Adds a "Select Alternate" operator for the new Grease Pencil data type.
This replaces the previous
gpencil.select_alternate
.Resolves #109204.
A few initial comments.
@ -275,0 +278,4 @@
curves, ATTR_DOMAIN_POINT, CD_PROP_BOOL);
const VArray<bool> cyclic = curves.cyclic();
BLI_assert_msg(selection.span.type().is<bool>(), "Error: Cannot alternate select on selection type different than bool.");
The
ensure_selection_attribute
call already makes sure we have abool
attribute. No need for the assert here.It doesn't actually. The type argument is only used when the selection attribute doesn't exist yet. So if the selection already has a float type, this operator will have to support that or change the attribute's type to boolean.
what do we want to do? We could template the function and support both selection; we could change the selection type, we could do nothing and prevent the user to use this if the type of selection isn't bool...
Since there is no exposed way of creating a
float
selection at the moment, I would just remove the assert and leave it as is.Then we are ready to merge this pr I think :)
@ -275,0 +285,4 @@
for (const int curve_i : range) {
const IndexRange points = points_by_curve[curve_i];
if (has_anything_selected(selection.span.slice(points))) {
I think it make sense to avoid the indentation and continue early.
@ -275,0 +311,4 @@
}
}
else {
if (!select_ends)
Missing brackets.
For formatting issues like these, please make sure to use
clang-format
. See https://wiki.blender.org/wiki/Tools/ClangFormat@ -198,0 +233,4 @@
"select_ends",
true,
"Select Ends",
"Select the first and enable the selection of the last point of each stroke");
"(De)select the first and last point of each stroke"
This description is not precise though, because we select the first point but the last point is selected only if we get there alternated (e.g. if we have two points we select only the first one....).
Do I change the description anyway?
Hm looking at the old operator, I think it makes sense to keep the same behavior. What we should do is call this option
deselect_ends
(everywhere it's used).If
deselect_ends
is true, then we just deselect the fist and last point. Otherwise we leave the selection as is.Then the description would be "Deselect the first and last point of each stroke".
So right now it is coded as the old behavior, we just need to decide on description and if we want to use select_ends or deselect_ends :)
I will make it as similar as the old version as possible, thus using deselect_ends
@ -275,0 +288,4 @@
if (has_anything_selected(selection.span.slice(points))) {
bool prev_selected = !select_ends;
for (int point_i = points.first(); point_i <= points.last(); point_i++) {
I think this loop can now be simplified:
mmm, this is not entirely right I think: the select ends param makes us start or from first or from second point... So the selection is kind of "inverted" based on this params (I am basing this fact on the older version of gp, that works like this)
Ah then you use
(point_i % 2 == unselect_ends)
instead.It's weird, but I noticed we can't use
points.index_range()
, because it always starts at0
. Whilepoints.first()
gives the correct offset.So keeping
for (int point_i = points.first(); point_i <= points.last(); point_i++) {
is the right thing to do.
Maybe something like this?
@mod_moder to me this seems more difficult to read than what I had originally written though...
Are we entirely sure that the first point is always 0? Because I see that index_range has a start_ init param
@SietseB is right, the for loop can stay as is.
@Lorenzo-Carpaneto The main reason for my approach is that it is:
@mod_moder These are good motivations, but I think there might be problems with your solution.
@SietseB and @filedescriptor said that
points.index_range()
is not working (and that function returns:IndexRange(size_);
. So I fear that your approach suffers from the same bug. So for now maybe better keep the loop as is, and as soon as we fix the problem with iteration on indexRange, we change the codeIndexRange is iterator factory itself. If you use
index_range()
method, you will create new IndexRange for iterating on something. In my case,points
sampled directly, look atconst IndexRange selected = points.shift(select_ends ? 0 : 1);...
lines.I was referring to
for (const int index : IndexRange(half_of_size))
const int selected_index = selected[index * 2];
You can sampling IndexRage to maping indices.
@mod_moder @HooglyBoogly I looked better at the problem that @SietseB was saying about IndexRange and I am now convinced that the solution proposed should work :) I have made the change (a bit different from suggestion but basically the same) check it out :)
38ba283662
toc66efbd41b
@ -275,0 +289,4 @@
}
bool prev_selected = deselect_ends;
for (int point_i = points.first(); point_i <= points.last(); point_i++) {
for (const int point : points) {
We are just discussing about this in the other thread, please join in the dicussion :D
Ah sorry, haha
Think I agree with Iliya in principle (whenever possible, better to write loops in a parallel way, so they have no dependence on the previous iteration)
@ -275,0 +289,4 @@
}
for (const int offset : IndexRange(points.size())) {
selection_typed[points.first() + offset] = deselect_ends ? offset % 2 : !(offset % 2);
This one is exactly the same
According to @SietseB (previous comment in the other thread)
This way should avoid this problem (cause we need to start from 0)
IndexRange(points.size())
==points.index_range()
points.first() + 0..1..2...
==points[0...1...2...]
Ah, you are totally right, pushing the proposed version, it's a bit more readable and efficient :)
Looks very close now! Just one comment on the
todo
.@ -198,0 +205,4 @@
grease_pencil.foreach_editable_drawing(
scene->r.cfra, [&](int /*drawing_index*/, GreasePencilDrawing &drawing) {
// todo: check that some points of stroke are selected
We can do this with
ed::curves::has_anything_selected
. This check should probably be done inside ofselect_alternate
though and return early if nothing in the entireCurvesGeometry
is selected.The check is already there, just forgot the comment :(
The check inside the loop is fine, what I mean is that there should be a check at the top of the function like this:
@Lorenzo-Carpaneto The check inside the loop is fine, what I meant is that there should be a check at the top of the function like this:
Looking good!
@ -275,0 +280,4 @@
const OffsetIndices points_by_curve = curves.points_by_curve();
bke::GSpanAttributeWriter selection = ensure_selection_attribute(
curves, ATTR_DOMAIN_POINT, CD_PROP_BOOL);
Hi, looks like this operator is only supported in point selection mode.
In that case, we could change the poll function to
editable_grease_pencil_point_selection_poll
That is correct, yes. Should be changed.
I'll commit then directly? (or want a PR again?)
Edit: pushed to main:
51a5be8913
Thank you @PratikPB2123