GPv3: Overlay: Only show visible and editable materials

This PR makes it so that locked materials as well as hidden materials will not have their edit points and edit lines visible.

Note: Previously in grease pencil, strokes with hidden materials would still display the edit lines. This behavior is now fixed in GPv3.

Pull Request: https://projects.blender.org/blender/blender/pulls/115740
This commit is contained in:
casey bianco-davis
2023-12-08 10:38:12 +01:00
committed by Falk David
parent 9ddd5126fe
commit 58041799bc
5 changed files with 237 additions and 128 deletions

View File

@@ -222,6 +222,7 @@ void invert_booleans(MutableSpan<bool> span);
void invert_booleans(MutableSpan<bool> span, const IndexMask &mask); void invert_booleans(MutableSpan<bool> span, const IndexMask &mask);
int64_t count_booleans(const VArray<bool> &varray); int64_t count_booleans(const VArray<bool> &varray);
int64_t count_booleans(const VArray<bool> &varray, const IndexMask &mask);
enum class BooleanMix { enum class BooleanMix {
None, None,

View File

@@ -141,40 +141,59 @@ BooleanMix booleans_mix_calc(const VArray<bool> &varray, const IndexRange range_
[&](BooleanMix a, BooleanMix b) { return (a == b) ? a : BooleanMix::Mixed; }); [&](BooleanMix a, BooleanMix b) { return (a == b) ? a : BooleanMix::Mixed; });
} }
int64_t count_booleans(const VArray<bool> &varray) int64_t count_booleans(const VArray<bool> &varray, const IndexMask &mask)
{ {
if (varray.is_empty()) { if (varray.is_empty() || mask.is_empty()) {
return 0; return 0;
} }
const CommonVArrayInfo info = varray.common_info(); /* Check if mask is full. */
if (info.type == CommonVArrayInfo::Type::Single) { if (varray.size() == mask.size()) {
return *static_cast<const bool *>(info.data) ? varray.size() : 0; const CommonVArrayInfo info = varray.common_info();
} if (info.type == CommonVArrayInfo::Type::Single) {
if (info.type == CommonVArrayInfo::Type::Span) { return *static_cast<const bool *>(info.data) ? varray.size() : 0;
const Span<bool> span(static_cast<const bool *>(info.data), varray.size()); }
if (info.type == CommonVArrayInfo::Type::Span) {
const Span<bool> span(static_cast<const bool *>(info.data), varray.size());
return threading::parallel_reduce(
varray.index_range(),
4096,
0,
[&](const IndexRange range, const int64_t init) {
const Span<bool> slice = span.slice(range);
return init + std::count(slice.begin(), slice.end(), true);
},
std::plus<int64_t>());
}
return threading::parallel_reduce( return threading::parallel_reduce(
varray.index_range(), varray.index_range(),
4096, 2048,
0, 0,
[&](const IndexRange range, const int64_t init) { [&](const IndexRange range, const int64_t init) {
const Span<bool> slice = span.slice(range); int64_t value = init;
return init + std::count(slice.begin(), slice.end(), true); /* Alternatively, this could use #materialize to retrieve many values at once. */
for (const int64_t i : range) {
value += int64_t(varray[i]);
}
return value;
}, },
std::plus<int64_t>()); std::plus<int64_t>());
} }
return threading::parallel_reduce( const CommonVArrayInfo info = varray.common_info();
varray.index_range(), if (info.type == CommonVArrayInfo::Type::Single) {
2048, return *static_cast<const bool *>(info.data) ? mask.size() : 0;
0, }
[&](const IndexRange range, const int64_t init) { int64_t value = 0;
int64_t value = init; mask.foreach_segment([&](const IndexMaskSegment segment) {
/* Alternatively, this could use #materialize to retrieve many values at once. */ for (const int64_t i : segment) {
for (const int64_t i : range) { value += int64_t(varray[i]);
value += int64_t(varray[i]); }
} });
return value; return value;
}, }
std::plus<int64_t>());
int64_t count_booleans(const VArray<bool> &varray)
{
return count_booleans(varray, IndexMask(varray.size()));
} }
} // namespace blender::array_utils } // namespace blender::array_utils

View File

@@ -198,7 +198,9 @@ BLI_INLINE int32_t pack_rotation_aspect_hardness(float rot, float asp, float har
return packed; return packed;
} }
static void grease_pencil_edit_batch_ensure(const GreasePencil &grease_pencil, const Scene &scene) static void grease_pencil_edit_batch_ensure(Object &object,
const GreasePencil &grease_pencil,
const Scene &scene)
{ {
using namespace blender::bke::greasepencil; using namespace blender::bke::greasepencil;
BLI_assert(grease_pencil.runtime != nullptr); BLI_assert(grease_pencil.runtime != nullptr);
@@ -249,6 +251,10 @@ static void grease_pencil_edit_batch_ensure(const GreasePencil &grease_pencil, c
const bke::CurvesGeometry &curves = info.drawing.strokes(); const bke::CurvesGeometry &curves = info.drawing.strokes();
const bke::AttributeAccessor attributes = curves.attributes(); const bke::AttributeAccessor attributes = curves.attributes();
const OffsetIndices<int> points_by_curve = curves.points_by_curve(); const OffsetIndices<int> points_by_curve = curves.points_by_curve();
const VArray<bool> cyclic = curves.cyclic();
IndexMaskMemory memory;
const IndexMask editable_strokes = ed::greasepencil::retrieve_editable_strokes(
object, info.drawing, memory);
/* Assumes that if the ".selection" attribute does not exist, all points are selected. */ /* Assumes that if the ".selection" attribute does not exist, all points are selected. */
const VArray<float> selection_float = *attributes.lookup_or_default<float>( const VArray<float> selection_float = *attributes.lookup_or_default<float>(
@@ -267,11 +273,15 @@ static void grease_pencil_edit_batch_ensure(const GreasePencil &grease_pencil, c
drawing_start_offset += curves.points_num(); drawing_start_offset += curves.points_num();
/* Add one id for the restart after every curve. */ /* Add one id for the restart after every curve. */
total_line_ids_num += curves.curves_num(); total_line_ids_num += editable_strokes.size();
Array<int> size_per_editable_stroke(editable_strokes.size());
offset_indices::gather_group_sizes(
points_by_curve, editable_strokes, size_per_editable_stroke);
/* Add one id for every non-cyclic segment. */ /* Add one id for every non-cyclic segment. */
total_line_ids_num += curves.points_num(); total_line_ids_num += std::accumulate(
size_per_editable_stroke.begin(), size_per_editable_stroke.end(), 0);
/* Add one id for the last segment of every cyclic curve. */ /* Add one id for the last segment of every cyclic curve. */
total_line_ids_num += array_utils::count_booleans(curves.cyclic()); total_line_ids_num += array_utils::count_booleans(curves.cyclic(), editable_strokes);
/* Do not show points for locked layers. */ /* Do not show points for locked layers. */
if (layer->is_locked()) { if (layer->is_locked()) {
@@ -281,12 +291,12 @@ static void grease_pencil_edit_batch_ensure(const GreasePencil &grease_pencil, c
const VArray<bool> selection = *attributes.lookup_or_default<bool>( const VArray<bool> selection = *attributes.lookup_or_default<bool>(
".selection", ATTR_DOMAIN_POINT, true); ".selection", ATTR_DOMAIN_POINT, true);
for (const int curve_i : curves.curves_range()) { editable_strokes.foreach_index([&](const int curve_i) {
const IndexRange points = points_by_curve[curve_i]; const IndexRange points = points_by_curve[curve_i];
if (ed::curves::has_anything_selected(selection, points)) { if (ed::curves::has_anything_selected(selection, points)) {
visible_points_num += points.size(); visible_points_num += points.size();
} }
} });
} }
GPUIndexBufBuilder elb; GPUIndexBufBuilder elb;
@@ -308,23 +318,24 @@ static void grease_pencil_edit_batch_ensure(const GreasePencil &grease_pencil, c
const bke::CurvesGeometry &curves = info.drawing.strokes(); const bke::CurvesGeometry &curves = info.drawing.strokes();
const OffsetIndices<int> points_by_curve = curves.points_by_curve(); const OffsetIndices<int> points_by_curve = curves.points_by_curve();
const VArray<bool> cyclic = curves.cyclic(); const VArray<bool> cyclic = curves.cyclic();
IndexMaskMemory memory;
const IndexMask editable_strokes = ed::greasepencil::retrieve_editable_strokes(
object, info.drawing, memory);
/* Fill line indices. */ /* Fill line indices. */
threading::parallel_for(curves.curves_range(), 512, [&](IndexRange range) { editable_strokes.foreach_index([&](const int curve_i) {
for (const int curve_i : range) { const IndexRange points = points_by_curve[curve_i];
const IndexRange points = points_by_curve[curve_i]; const bool is_cyclic = cyclic[curve_i];
const bool is_cyclic = cyclic[curve_i];
for (const int point : points) { for (const int point_i : points) {
GPU_indexbuf_add_generic_vert(&elb, point + drawing_start_offset); GPU_indexbuf_add_generic_vert(&elb, point_i + drawing_start_offset);
}
if (is_cyclic) {
GPU_indexbuf_add_generic_vert(&elb, points.first() + drawing_start_offset);
}
GPU_indexbuf_add_primitive_restart(&elb);
} }
if (is_cyclic) {
GPU_indexbuf_add_generic_vert(&elb, points.first() + drawing_start_offset);
}
GPU_indexbuf_add_primitive_restart(&elb);
}); });
/* Assumes that if the ".selection" attribute does not exist, all points are selected. */ /* Assumes that if the ".selection" attribute does not exist, all points are selected. */
@@ -333,16 +344,14 @@ static void grease_pencil_edit_batch_ensure(const GreasePencil &grease_pencil, c
/* Fill point indices. */ /* Fill point indices. */
if (!layer->is_locked()) { if (!layer->is_locked()) {
threading::parallel_for(curves.curves_range(), 512, [&](IndexRange range) { editable_strokes.foreach_index([&](const int curve_i) {
for (const int curve_i : range) { const IndexRange points = points_by_curve[curve_i];
const IndexRange points = points_by_curve[curve_i]; if (!ed::curves::has_anything_selected(selection, points)) {
if (!ed::curves::has_anything_selected(selection, points)) { return;
continue; }
}
for (const int point : points) { for (const int point : points) {
GPU_indexbuf_add_generic_vert(&epb, point + drawing_start_offset); GPU_indexbuf_add_generic_vert(&epb, point + drawing_start_offset);
}
} }
}); });
} }
@@ -365,7 +374,9 @@ static void grease_pencil_edit_batch_ensure(const GreasePencil &grease_pencil, c
cache->is_dirty = false; cache->is_dirty = false;
} }
static void grease_pencil_geom_batch_ensure(const GreasePencil &grease_pencil, const Scene &scene) static void grease_pencil_geom_batch_ensure(Object &object,
const GreasePencil &grease_pencil,
const Scene &scene)
{ {
using namespace blender::bke::greasepencil; using namespace blender::bke::greasepencil;
BLI_assert(grease_pencil.runtime != nullptr); BLI_assert(grease_pencil.runtime != nullptr);
@@ -386,7 +397,6 @@ static void grease_pencil_geom_batch_ensure(const GreasePencil &grease_pencil, c
/* First, count how many vertices and triangles are needed for the whole object. Also record the /* First, count how many vertices and triangles are needed for the whole object. Also record the
* offsets into the curves for the vertices and triangles. */ * offsets into the curves for the vertices and triangles. */
// int total_points_num = 0; /* UNUSED. */
int total_verts_num = 0; int total_verts_num = 0;
int total_triangles_num = 0; int total_triangles_num = 0;
int v_offset = 0; int v_offset = 0;
@@ -396,16 +406,34 @@ static void grease_pencil_geom_batch_ensure(const GreasePencil &grease_pencil, c
const bke::CurvesGeometry &curves = info.drawing.strokes(); const bke::CurvesGeometry &curves = info.drawing.strokes();
const OffsetIndices<int> points_by_curve = curves.points_by_curve(); const OffsetIndices<int> points_by_curve = curves.points_by_curve();
const VArray<bool> cyclic = curves.cyclic(); const VArray<bool> cyclic = curves.cyclic();
IndexMaskMemory memory;
const IndexMask visible_strokes = ed::greasepencil::retrieve_visible_strokes(
object, info.drawing, memory);
int verts_start_offsets_size = curves.curves_num(); const int num_curves = visible_strokes.size();
int tris_start_offsets_size = curves.curves_num(); const int verts_start_offsets_size = num_curves;
const int tris_start_offsets_size = num_curves;
Array<int> verts_start_offsets(verts_start_offsets_size); Array<int> verts_start_offsets(verts_start_offsets_size);
Array<int> tris_start_offsets(tris_start_offsets_size); Array<int> tris_start_offsets(tris_start_offsets_size);
/* Calculate the vertex and triangle offsets for all the curves. */ /* Calculate the triangle offsets for all the visible curves. */
int t_offset = 0; int t_offset = 0;
int num_cyclic = 0; int pos = 0;
for (const int curve_i : curves.curves_range()) { for (const int curve_i : curves.curves_range()) {
IndexRange points = points_by_curve[curve_i];
if (visible_strokes.contains(curve_i)) {
tris_start_offsets[pos] = t_offset;
pos++;
}
if (points.size() >= 3) {
t_offset += points.size() - 2;
}
}
/* Calculate the vertex offsets for all the visible curves. */
int num_cyclic = 0;
int num_points = 0;
visible_strokes.foreach_index([&](const int curve_i, const int pos) {
IndexRange points = points_by_curve[curve_i]; IndexRange points = points_by_curve[curve_i];
const bool is_cyclic = cyclic[curve_i]; const bool is_cyclic = cyclic[curve_i];
@@ -413,20 +441,14 @@ static void grease_pencil_geom_batch_ensure(const GreasePencil &grease_pencil, c
num_cyclic++; num_cyclic++;
} }
tris_start_offsets[curve_i] = t_offset; verts_start_offsets[pos] = v_offset;
if (points.size() >= 3) {
t_offset += points.size() - 2;
}
verts_start_offsets[curve_i] = v_offset;
v_offset += 1 + points.size() + (is_cyclic ? 1 : 0) + 1; v_offset += 1 + points.size() + (is_cyclic ? 1 : 0) + 1;
} num_points += points.size();
});
// total_points_num += curves.points_num(); /* UNUSED. */
/* One vertex is stored before and after as padding. Cyclic strokes have one extra vertex. */ /* One vertex is stored before and after as padding. Cyclic strokes have one extra vertex. */
total_verts_num += curves.points_num() + num_cyclic + curves.curves_num() * 2; total_verts_num += num_points + num_cyclic + num_curves * 2;
total_triangles_num += (curves.points_num() + num_cyclic) * 2; total_triangles_num += (num_points + num_cyclic) * 2;
total_triangles_num += info.drawing.triangles().size(); total_triangles_num += info.drawing.triangles().size();
verts_start_offsets_per_visible_drawing.append(std::move(verts_start_offsets)); verts_start_offsets_per_visible_drawing.append(std::move(verts_start_offsets));
@@ -477,6 +499,9 @@ static void grease_pencil_geom_batch_ensure(const GreasePencil &grease_pencil, c
const Span<uint3> triangles = info.drawing.triangles(); const Span<uint3> triangles = info.drawing.triangles();
const Span<int> verts_start_offsets = verts_start_offsets_per_visible_drawing[drawing_i]; const Span<int> verts_start_offsets = verts_start_offsets_per_visible_drawing[drawing_i];
const Span<int> tris_start_offsets = tris_start_offsets_per_visible_drawing[drawing_i]; const Span<int> tris_start_offsets = tris_start_offsets_per_visible_drawing[drawing_i];
IndexMaskMemory memory;
const IndexMask visible_strokes = ed::greasepencil::retrieve_visible_strokes(
object, info.drawing, memory);
auto populate_point = [&](IndexRange verts_range, auto populate_point = [&](IndexRange verts_range,
int curve_i, int curve_i,
@@ -510,59 +535,57 @@ static void grease_pencil_geom_batch_ensure(const GreasePencil &grease_pencil, c
GPU_indexbuf_add_tri_verts(&ibo, v_mat + 2, v_mat + 1, v_mat + 3); GPU_indexbuf_add_tri_verts(&ibo, v_mat + 2, v_mat + 1, v_mat + 3);
}; };
threading::parallel_for(curves.curves_range(), 512, [&](IndexRange range) { visible_strokes.foreach_index([&](const int curve_i, const int pos) {
for (const int curve_i : range) { IndexRange points = points_by_curve[curve_i];
IndexRange points = points_by_curve[curve_i]; const bool is_cyclic = cyclic[curve_i];
const bool is_cyclic = cyclic[curve_i]; const int verts_start_offset = verts_start_offsets[pos];
const int verts_start_offset = verts_start_offsets[curve_i]; const int tris_start_offset = tris_start_offsets[pos];
const int tris_start_offset = tris_start_offsets[curve_i]; const int num_verts = 1 + points.size() + (is_cyclic ? 1 : 0) + 1;
const int num_verts = 1 + points.size() + (is_cyclic ? 1 : 0) + 1; IndexRange verts_range = IndexRange(verts_start_offset, num_verts);
IndexRange verts_range = IndexRange(verts_start_offset, num_verts); MutableSpan<GreasePencilStrokeVert> verts_slice = verts.slice(verts_range);
MutableSpan<GreasePencilStrokeVert> verts_slice = verts.slice(verts_range); MutableSpan<GreasePencilColorVert> cols_slice = cols.slice(verts_range);
MutableSpan<GreasePencilColorVert> cols_slice = cols.slice(verts_range);
/* First vertex is not drawn. */ /* First vertex is not drawn. */
verts_slice.first().mat = -1; verts_slice.first().mat = -1;
/* If the stroke has more than 2 points, add the triangle indices to the index buffer. */ /* If the stroke has more than 2 points, add the triangle indices to the index buffer. */
if (points.size() >= 3) { if (points.size() >= 3) {
const Span<uint3> tris_slice = triangles.slice(tris_start_offset, points.size() - 2); const Span<uint3> tris_slice = triangles.slice(tris_start_offset, points.size() - 2);
for (const uint3 tri : tris_slice) { for (const uint3 tri : tris_slice) {
GPU_indexbuf_add_tri_verts(&ibo, GPU_indexbuf_add_tri_verts(&ibo,
(verts_range[1] + tri.x) << GP_VERTEX_ID_SHIFT, (verts_range[1] + tri.x) << GP_VERTEX_ID_SHIFT,
(verts_range[1] + tri.y) << GP_VERTEX_ID_SHIFT, (verts_range[1] + tri.y) << GP_VERTEX_ID_SHIFT,
(verts_range[1] + tri.z) << GP_VERTEX_ID_SHIFT); (verts_range[1] + tri.z) << GP_VERTEX_ID_SHIFT);
}
} }
/* Write all the point attributes to the vertex buffers. Create a quad for each point. */
for (const int i : IndexRange(points.size())) {
const int idx = i + 1;
populate_point(verts_range,
curve_i,
start_caps[curve_i],
end_caps[curve_i],
points[i],
idx,
verts_slice[idx],
cols_slice[idx]);
}
if (is_cyclic) {
const int idx = points.size() + 1;
populate_point(verts_range,
curve_i,
start_caps[curve_i],
end_caps[curve_i],
points[0],
idx,
verts_slice[idx],
cols_slice[idx]);
}
/* Last vertex is not drawn. */
verts_slice.last().mat = -1;
} }
/* Write all the point attributes to the vertex buffers. Create a quad for each point. */
for (const int i : IndexRange(points.size())) {
const int idx = i + 1;
populate_point(verts_range,
curve_i,
start_caps[curve_i],
end_caps[curve_i],
points[i],
idx,
verts_slice[idx],
cols_slice[idx]);
}
if (is_cyclic) {
const int idx = points.size() + 1;
populate_point(verts_range,
curve_i,
start_caps[curve_i],
end_caps[curve_i],
points[0],
idx,
verts_slice[idx],
cols_slice[idx]);
}
/* Last vertex is not drawn. */
verts_slice.last().mat = -1;
}); });
} }
@@ -628,7 +651,7 @@ GPUBatch *DRW_cache_grease_pencil_get(const Scene *scene, Object *ob)
using namespace blender::draw; using namespace blender::draw;
GreasePencil &grease_pencil = *static_cast<GreasePencil *>(ob->data); GreasePencil &grease_pencil = *static_cast<GreasePencil *>(ob->data);
GreasePencilBatchCache *cache = grease_pencil_batch_cache_get(grease_pencil); GreasePencilBatchCache *cache = grease_pencil_batch_cache_get(grease_pencil);
grease_pencil_geom_batch_ensure(grease_pencil, *scene); grease_pencil_geom_batch_ensure(*ob, grease_pencil, *scene);
return cache->geom_batch; return cache->geom_batch;
} }
@@ -638,7 +661,7 @@ GPUBatch *DRW_cache_grease_pencil_edit_points_get(const Scene *scene, Object *ob
using namespace blender::draw; using namespace blender::draw;
GreasePencil &grease_pencil = *static_cast<GreasePencil *>(ob->data); GreasePencil &grease_pencil = *static_cast<GreasePencil *>(ob->data);
GreasePencilBatchCache *cache = grease_pencil_batch_cache_get(grease_pencil); GreasePencilBatchCache *cache = grease_pencil_batch_cache_get(grease_pencil);
grease_pencil_edit_batch_ensure(grease_pencil, *scene); grease_pencil_edit_batch_ensure(*ob, grease_pencil, *scene);
return cache->edit_points; return cache->edit_points;
} }
@@ -648,7 +671,7 @@ GPUBatch *DRW_cache_grease_pencil_edit_lines_get(const Scene *scene, Object *ob)
using namespace blender::draw; using namespace blender::draw;
GreasePencil &grease_pencil = *static_cast<GreasePencil *>(ob->data); GreasePencil &grease_pencil = *static_cast<GreasePencil *>(ob->data);
GreasePencilBatchCache *cache = grease_pencil_batch_cache_get(grease_pencil); GreasePencilBatchCache *cache = grease_pencil_batch_cache_get(grease_pencil);
grease_pencil_edit_batch_ensure(grease_pencil, *scene); grease_pencil_edit_batch_ensure(*ob, grease_pencil, *scene);
return cache->edit_lines; return cache->edit_lines;
} }
@@ -658,7 +681,7 @@ GPUVertBuf *DRW_cache_grease_pencil_position_buffer_get(const Scene *scene, Obje
using namespace blender::draw; using namespace blender::draw;
GreasePencil &grease_pencil = *static_cast<GreasePencil *>(ob->data); GreasePencil &grease_pencil = *static_cast<GreasePencil *>(ob->data);
GreasePencilBatchCache *cache = grease_pencil_batch_cache_get(grease_pencil); GreasePencilBatchCache *cache = grease_pencil_batch_cache_get(grease_pencil);
grease_pencil_geom_batch_ensure(grease_pencil, *scene); grease_pencil_geom_batch_ensure(*ob, grease_pencil, *scene);
return cache->vbo; return cache->vbo;
} }
@@ -668,7 +691,7 @@ GPUVertBuf *DRW_cache_grease_pencil_color_buffer_get(const Scene *scene, Object
using namespace blender::draw; using namespace blender::draw;
GreasePencil &grease_pencil = *static_cast<GreasePencil *>(ob->data); GreasePencil &grease_pencil = *static_cast<GreasePencil *>(ob->data);
GreasePencilBatchCache *cache = grease_pencil_batch_cache_get(grease_pencil); GreasePencilBatchCache *cache = grease_pencil_batch_cache_get(grease_pencil);
grease_pencil_geom_batch_ensure(grease_pencil, *scene); grease_pencil_geom_batch_ensure(*ob, grease_pencil, *scene);
return cache->vbo_col; return cache->vbo_col;
} }

View File

@@ -312,12 +312,27 @@ static VectorSet<int> get_editable_material_indices(Object &object)
(material->gp_style->flag & GP_MATERIAL_LOCKED) == 0 && (material->gp_style->flag & GP_MATERIAL_LOCKED) == 0 &&
(material->gp_style->flag & GP_MATERIAL_HIDE) == 0) (material->gp_style->flag & GP_MATERIAL_HIDE) == 0)
{ {
locked_material_indices.add(mat_i); locked_material_indices.add_new(mat_i);
} }
} }
return locked_material_indices; return locked_material_indices;
} }
static VectorSet<int> get_hidden_material_indices(Object &object)
{
BLI_assert(object.type == OB_GREASE_PENCIL);
VectorSet<int> hidden_material_indices;
for (const int mat_i : IndexRange(object.totcol)) {
Material *material = BKE_object_material_get(&object, mat_i + 1);
if (material != nullptr && material->gp_style != nullptr &&
(material->gp_style->flag & GP_MATERIAL_HIDE) != 0)
{
hidden_material_indices.add_new(mat_i);
}
}
return hidden_material_indices;
}
IndexMask retrieve_editable_strokes(Object &object, IndexMask retrieve_editable_strokes(Object &object,
const bke::greasepencil::Drawing &drawing, const bke::greasepencil::Drawing &drawing,
IndexMaskMemory &memory) IndexMaskMemory &memory)
@@ -327,13 +342,23 @@ IndexMask retrieve_editable_strokes(Object &object,
/* Get all the editable material indices */ /* Get all the editable material indices */
VectorSet<int> editable_material_indices = get_editable_material_indices(object); VectorSet<int> editable_material_indices = get_editable_material_indices(object);
if (locked_material_indices.is_empty()) {
return drawing.strokes().curves_range();
}
const bke::CurvesGeometry &curves = drawing.strokes(); const bke::CurvesGeometry &curves = drawing.strokes();
const IndexRange curves_range = drawing.strokes().curves_range(); const IndexRange curves_range = drawing.strokes().curves_range();
const bke::AttributeAccessor attributes = curves.attributes(); const bke::AttributeAccessor attributes = curves.attributes();
const VArray<int> materials = *attributes.lookup<int>("material_index", ATTR_DOMAIN_CURVE);
if (!materials) {
/* if the attribute does not exist then the default is the first material. */
if (locked_material_indices.contains(0)) {
return curves_range;
}
return IndexMask();
}
/* Get all the strokes that have their material unlocked. */ /* Get all the strokes that have their material unlocked. */
const VArray<int> materials = *attributes.lookup_or_default<int>(
"material_index", ATTR_DOMAIN_CURVE, -1);
return IndexMask::from_predicate( return IndexMask::from_predicate(
curves_range, GrainSize(4096), memory, [&](const int64_t curve_i) { curves_range, GrainSize(4096), memory, [&](const int64_t curve_i) {
const int material_index = materials[curve_i]; const int material_index = materials[curve_i];
@@ -348,13 +373,23 @@ IndexMask retrieve_editable_points(Object &object,
/* Get all the editable material indices */ /* Get all the editable material indices */
VectorSet<int> editable_material_indices = get_editable_material_indices(object); VectorSet<int> editable_material_indices = get_editable_material_indices(object);
if (locked_material_indices.is_empty()) {
return drawing.strokes().points_range();
}
const bke::CurvesGeometry &curves = drawing.strokes(); const bke::CurvesGeometry &curves = drawing.strokes();
const IndexRange points_range = drawing.strokes().points_range(); const IndexRange points_range = drawing.strokes().points_range();
const bke::AttributeAccessor attributes = curves.attributes(); const bke::AttributeAccessor attributes = curves.attributes();
/* Propagate the material index to the points. */ /* Propagate the material index to the points. */
const VArray<int> materials = *attributes.lookup_or_default<int>( const VArray<int> materials = *attributes.lookup<int>("material_index", ATTR_DOMAIN_POINT);
"material_index", ATTR_DOMAIN_POINT, -1); if (!materials) {
/* if the attribute does not exist then the default is the first material. */
if (locked_material_indices.contains(0)) {
return points_range;
}
return IndexMask();
}
/* Get all the points that are part of a stroke with an unlocked material. */ /* Get all the points that are part of a stroke with an unlocked material. */
return IndexMask::from_predicate( return IndexMask::from_predicate(
points_range, GrainSize(4096), memory, [&](const int64_t point_i) { points_range, GrainSize(4096), memory, [&](const int64_t point_i) {
@@ -377,6 +412,33 @@ IndexMask retrieve_editable_elements(Object &object,
return {}; return {};
} }
IndexMask retrieve_visible_strokes(Object &object,
const bke::greasepencil::Drawing &drawing,
IndexMaskMemory &memory)
{
using namespace blender;
/* Get all the hidden material indices. */
VectorSet<int> hidden_material_indices = get_hidden_material_indices(object);
if (hidden_material_indices.is_empty()) {
return drawing.strokes().curves_range();
}
const bke::CurvesGeometry &curves = drawing.strokes();
const IndexRange curves_range = drawing.strokes().curves_range();
const bke::AttributeAccessor attributes = curves.attributes();
/* Get all the strokes that have their material visible. */
const VArray<int> materials = *attributes.lookup_or_default<int>(
"material_index", ATTR_DOMAIN_CURVE, -1);
return IndexMask::from_predicate(
curves_range, GrainSize(4096), memory, [&](const int64_t curve_i) {
const int material_index = materials[curve_i];
return !hidden_material_indices.contains(material_index);
});
}
IndexMask retrieve_editable_and_selected_strokes(Object &object, IndexMask retrieve_editable_and_selected_strokes(Object &object,
const bke::greasepencil::Drawing &drawing, const bke::greasepencil::Drawing &drawing,
IndexMaskMemory &memory) IndexMaskMemory &memory)

View File

@@ -181,6 +181,10 @@ IndexMask retrieve_editable_elements(Object &object,
eAttrDomain selection_domain, eAttrDomain selection_domain,
IndexMaskMemory &memory); IndexMaskMemory &memory);
IndexMask retrieve_visible_strokes(Object &grease_pencil_object,
const bke::greasepencil::Drawing &drawing,
IndexMaskMemory &memory);
IndexMask retrieve_editable_and_selected_strokes(Object &grease_pencil_object, IndexMask retrieve_editable_and_selected_strokes(Object &grease_pencil_object,
const bke::greasepencil::Drawing &drawing, const bke::greasepencil::Drawing &drawing,
IndexMaskMemory &memory); IndexMaskMemory &memory);